diff --git a/.release-please-manifest.json b/.release-please-manifest.json index e8710fd..d365658 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1 @@ -{".":"0.0.4"} +{".":"0.0.5"} diff --git a/CHANGELOG.md b/CHANGELOG.md index c27d494..5f55958 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,61 @@ # Changelog +## [0.0.5](https://github.com/validator-labs/validator-plugin-maas/compare/v0.0.4...v0.0.5) (2024-07-26) + + +### Features + +* add upstream dns validation ([#102](https://github.com/validator-labs/validator-plugin-maas/issues/102)) ([50b317e](https://github.com/validator-labs/validator-plugin-maas/commit/50b317e7a3e370c51ade305f4164a0edb225ca97)) + + +### Bug Fixes + +* **deps:** update kubernetes packages to v0.30.1 ([#49](https://github.com/validator-labs/validator-plugin-maas/issues/49)) ([377eece](https://github.com/validator-labs/validator-plugin-maas/commit/377eece67c2edd9b181dcd0f6a639e936e8d7442)) +* **deps:** update kubernetes packages to v0.30.2 ([#83](https://github.com/validator-labs/validator-plugin-maas/issues/83)) ([726a2ce](https://github.com/validator-labs/validator-plugin-maas/commit/726a2cea156c9b43e53a5b3f8e6acda4e9736c2a)) +* **deps:** update module github.com/go-logr/logr to v1.4.2 ([59edbe8](https://github.com/validator-labs/validator-plugin-maas/commit/59edbe8e8f95c2f859678d815ec68d6c0fda866b)) +* **deps:** update module github.com/maas/gomaasclient to v0.5.0 ([#74](https://github.com/validator-labs/validator-plugin-maas/issues/74)) ([26b3340](https://github.com/validator-labs/validator-plugin-maas/commit/26b334004b60a296e321106999143b85df1ed24e)) +* **deps:** update module github.com/onsi/ginkgo/v2 to v2.19.0 ([61ecc09](https://github.com/validator-labs/validator-plugin-maas/commit/61ecc09d247a6cc88b35e1cd1422ea883195b02a)) +* **deps:** update module github.com/validator-labs/validator to v0.0.41 ([e0f3909](https://github.com/validator-labs/validator-plugin-maas/commit/e0f39096f8c9adde4a779ab76af830e43525850b)) +* **deps:** update module github.com/validator-labs/validator to v0.0.42 ([#81](https://github.com/validator-labs/validator-plugin-maas/issues/81)) ([713d9f0](https://github.com/validator-labs/validator-plugin-maas/commit/713d9f02787d380dba23a61a3b8924f0cc4afb6d)) +* **deps:** update module github.com/validator-labs/validator to v0.0.43 ([929bc17](https://github.com/validator-labs/validator-plugin-maas/commit/929bc17d29efc01f68a569aa8eb6ea3aee8492f9)) +* **deps:** update module sigs.k8s.io/cluster-api to v1.7.3 ([052dee8](https://github.com/validator-labs/validator-plugin-maas/commit/052dee8eab2791e1b00ced0ba037c29ca48bb5f4)) +* **deps:** update module sigs.k8s.io/controller-runtime to v0.18.4 ([a438000](https://github.com/validator-labs/validator-plugin-maas/commit/a438000b8855fae923d2e0d5f69bc29c995cfc24)) + + +### Other + +* **deps:** pin googleapis/release-please-action action to f3969c0 ([#67](https://github.com/validator-labs/validator-plugin-maas/issues/67)) ([9fef1b8](https://github.com/validator-labs/validator-plugin-maas/commit/9fef1b8f71845efee191156580019a7edf5c6b73)) +* **deps:** update actions/checkout digest to 0ad4b8f ([#61](https://github.com/validator-labs/validator-plugin-maas/issues/61)) ([7d40608](https://github.com/validator-labs/validator-plugin-maas/commit/7d40608b1fcfef9f7438f92154258b925928d4ea)) +* **deps:** update actions/checkout digest to a5ac7e5 ([0d79ce6](https://github.com/validator-labs/validator-plugin-maas/commit/0d79ce6b5e4d9424e6b33cd0543fbd523ae0bf84)) +* **deps:** update anchore/sbom-action action to v0.16.0 ([cd9bab3](https://github.com/validator-labs/validator-plugin-maas/commit/cd9bab323ce1bcf9ea82d7728eec8460c116ac27)) +* **deps:** update codecov/codecov-action digest to 125fc84 ([#69](https://github.com/validator-labs/validator-plugin-maas/issues/69)) ([3ae8c36](https://github.com/validator-labs/validator-plugin-maas/commit/3ae8c36bc808300861e2240ec967cd0241d2b5b1)) +* **deps:** update dependency go to v1.22.4 ([#76](https://github.com/validator-labs/validator-plugin-maas/issues/76)) ([47fe6e2](https://github.com/validator-labs/validator-plugin-maas/commit/47fe6e22698ac46db51df43663c01ea237feb32f)) +* **deps:** update docker/login-action digest to 0d4c9c5 ([#70](https://github.com/validator-labs/validator-plugin-maas/issues/70)) ([6b0f1a2](https://github.com/validator-labs/validator-plugin-maas/commit/6b0f1a29cc586393ed17d0bf11e8ca8bd35acdaf)) +* **deps:** update docker/setup-buildx-action digest to d70bba7 ([#26](https://github.com/validator-labs/validator-plugin-maas/issues/26)) ([41c699c](https://github.com/validator-labs/validator-plugin-maas/commit/41c699cf2ac1cba5c2b14ded653d67652bad6f25)) +* **deps:** update gcr.io/kubebuilder/kube-rbac-proxy docker tag to v0.16.0 ([#47](https://github.com/validator-labs/validator-plugin-maas/issues/47)) ([a53bf65](https://github.com/validator-labs/validator-plugin-maas/commit/a53bf6533fdfc9459a41d17322d991edc38947b1)) +* **deps:** update quay.io/validator-labs/validator-plugin-maas docker tag to v0.0.42 ([#80](https://github.com/validator-labs/validator-plugin-maas/issues/80)) ([3653e6e](https://github.com/validator-labs/validator-plugin-maas/commit/3653e6ee14919283504921e0a38ccb7ce19479a4)) + + +### Dependency Updates + +* **deps:** update dependency go to v1.22.5 ([#92](https://github.com/validator-labs/validator-plugin-maas/issues/92)) ([b9cbe1d](https://github.com/validator-labs/validator-plugin-maas/commit/b9cbe1d875541ee7c193401d6577390ba71a674e)) +* **deps:** update kubernetes packages to v0.30.3 ([#98](https://github.com/validator-labs/validator-plugin-maas/issues/98)) ([8ae9189](https://github.com/validator-labs/validator-plugin-maas/commit/8ae9189bb1cd443eb658a8c096af278d5d0e3f5e)) +* **deps:** update module github.com/maas/gomaasclient to v0.6.0 ([#90](https://github.com/validator-labs/validator-plugin-maas/issues/90)) ([d00fb21](https://github.com/validator-labs/validator-plugin-maas/commit/d00fb219dd5d48824fd63fefed9cd3cff97fdbdc)) +* **deps:** update module github.com/onsi/ginkgo/v2 to v2.19.1 ([93815c3](https://github.com/validator-labs/validator-plugin-maas/commit/93815c3946c4c61de027928f5ec494137de9c71a)) +* **deps:** update module github.com/onsi/gomega to v1.34.0 ([47cc390](https://github.com/validator-labs/validator-plugin-maas/commit/47cc390159d638c4b1155a8c41c1c59b17d52b30)) +* **deps:** update module github.com/validator-labs/validator to v0.0.44 ([e135801](https://github.com/validator-labs/validator-plugin-maas/commit/e13580155acd53b5b7feb9a2cde30508b16ed3e4)) +* **deps:** update module github.com/validator-labs/validator to v0.0.46 ([#96](https://github.com/validator-labs/validator-plugin-maas/issues/96)) ([3bb0e30](https://github.com/validator-labs/validator-plugin-maas/commit/3bb0e30333b055849f65b7e3443fe7cbc505d332)) +* **deps:** update module github.com/validator-labs/validator to v0.0.47 ([#100](https://github.com/validator-labs/validator-plugin-maas/issues/100)) ([addb5d0](https://github.com/validator-labs/validator-plugin-maas/commit/addb5d01b65a84548802f1797fc9985550f9fca5)) +* **deps:** update module github.com/validator-labs/validator to v0.0.48 ([79092a1](https://github.com/validator-labs/validator-plugin-maas/commit/79092a132f3cfa0fab34d81eee7ab3be80b1a779)) +* **deps:** update module github.com/validator-labs/validator to v0.0.49 ([ba024df](https://github.com/validator-labs/validator-plugin-maas/commit/ba024df408f5900963e727894350c8bf8a900ef7)) +* **deps:** update module sigs.k8s.io/cluster-api to v1.7.4 ([0f646f9](https://github.com/validator-labs/validator-plugin-maas/commit/0f646f93e8326b7dc2fc21c2f2fcbd48bd149ed0)) + + +### Refactoring + +* change api format to match other plugins ([#99](https://github.com/validator-labs/validator-plugin-maas/issues/99)) ([891a21b](https://github.com/validator-labs/validator-plugin-maas/commit/891a21bbd7b5492d0777ccbd4001a7f884187339)) +* enable revive and address all lints ([#94](https://github.com/validator-labs/validator-plugin-maas/issues/94)) ([796238b](https://github.com/validator-labs/validator-plugin-maas/commit/796238b8538fa2e578c6e6439a1d1791c233455e)) + ## [0.0.4](https://github.com/validator-labs/validator-plugin-maas/compare/v0.0.3...v0.0.4) (2024-05-17) diff --git a/Makefile b/Makefile index b0c6438..2d1808d 100644 --- a/Makefile +++ b/Makefile @@ -6,3 +6,15 @@ IMG ?= quay.io/validator-labs/validator-plugin-maas:latest # Helm vars CHART_NAME=validator-plugin-maas + +.PHONY: dev +dev: + devspace dev -n validator + +# Static Analysis / CI + +chartCrds = chart/validator-plugin-maas/crds/validation.spectrocloud.labs_maasvalidators.yaml + +reviewable-ext: + rm $(chartCrds) + cp config/crd/bases/validation.spectrocloud.labs_maasvalidators.yaml $(chartCrds) diff --git a/chart/validator-plugin-maas/Chart.yaml b/chart/validator-plugin-maas/Chart.yaml index e050cc9..18bdf2f 100644 --- a/chart/validator-plugin-maas/Chart.yaml +++ b/chart/validator-plugin-maas/Chart.yaml @@ -2,5 +2,5 @@ apiVersion: v2 name: validator-plugin-maas description: Perform various validations against a MaaS instance type: application -version: 0.0.4 +version: 0.0.5 appVersion: 0.0.1 diff --git a/chart/validator-plugin-maas/README.md b/chart/validator-plugin-maas/README.md index f354abc..f0d9589 100644 --- a/chart/validator-plugin-maas/README.md +++ b/chart/validator-plugin-maas/README.md @@ -24,7 +24,7 @@ The following table lists the configurable parameters of the Validator-plugin-ma | `controllerManager.manager.containerSecurityContext.allowPrivilegeEscalation` | | `false` | | `controllerManager.manager.containerSecurityContext.capabilities.drop` | | `["ALL"]` | | `controllerManager.manager.image.repository` | | `"quay.io/validator-labs/validator-plugin-maas"` | -| `controllerManager.manager.image.tag` | x-release-please-version | `"v0.0.4"` | +| `controllerManager.manager.image.tag` | x-release-please-version | `"v0.0.5"` | | `controllerManager.manager.resources.limits.cpu` | | `"500m"` | | `controllerManager.manager.resources.limits.memory` | | `"128Mi"` | | `controllerManager.manager.resources.requests.cpu` | | `"10m"` | diff --git a/chart/validator-plugin-maas/crds/maasvalidator-crd.yaml b/chart/validator-plugin-maas/crds/maasvalidator-crd.yaml deleted file mode 100644 index d532d05..0000000 --- a/chart/validator-plugin-maas/crds/maasvalidator-crd.yaml +++ /dev/null @@ -1,97 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.12.0 - name: maasvalidators.validation.spectrocloud.labs -spec: - group: validation.spectrocloud.labs - names: - kind: MaasValidator - listKind: MaasValidatorList - plural: maasvalidators - singular: maasvalidator - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: MaasValidator is the Schema for the maasvalidators API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: MaasValidatorSpec defines the desired state of MaasValidator - properties: - MaasInstance: - description: MaasInstance describes the MaaS host - properties: - auth: - properties: - secretName: - type: string - token: - type: string - type: object - host: - description: Host is the URL for your MaaS instance - type: string - required: - - auth - - host - type: object - MaasInstanceRules: - properties: - auth: - description: Auth provides authentication information for the - MaaS Instance - properties: - secretName: - type: string - token: - type: string - type: object - bootable-images: - description: OSImages is a list of bootable os images - items: - properties: - name: - description: The name of the bootable image - type: string - os-arch: - description: OS Architecture - type: string - required: - - name - - os-arch - type: object - type: array - name: - description: Unique rule name - type: string - required: - - auth - - name - type: object - required: - - MaasInstance - type: object - status: - description: MaasValidatorStatus defines the observed state of MaasValidator - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/chart/validator-plugin-maas/crds/validation.spectrocloud.labs_maasvalidators.yaml b/chart/validator-plugin-maas/crds/validation.spectrocloud.labs_maasvalidators.yaml new file mode 100644 index 0000000..fe755af --- /dev/null +++ b/chart/validator-plugin-maas/crds/validation.spectrocloud.labs_maasvalidators.yaml @@ -0,0 +1,198 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.15.0 + name: maasvalidators.validation.spectrocloud.labs +spec: + group: validation.spectrocloud.labs + names: + kind: MaasValidator + listKind: MaasValidatorList + plural: maasvalidators + singular: maasvalidator + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: MaasValidator is the Schema for the maasvalidators API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: MaasValidatorSpec defines the desired state of MaasValidator + properties: + auth: + description: Auth provides authentication information for the MAAS + Instance + properties: + secretName: + type: string + token: + type: string + required: + - secretName + - token + type: object + host: + description: Host is the URL for your MAAS Instance + type: string + imageRules: + items: + description: ImageRule defines a rule for validating one or more + OS images + properties: + images: + description: The list of OS images to validate + items: + description: Image defines one OS image + properties: + architecture: + description: OS Architecture + type: string + name: + description: The name of the bootable image + type: string + required: + - architecture + - name + type: object + type: array + name: + description: Unique name for the rule + type: string + required: + - images + - name + type: object + type: array + internalDNSRules: + items: + description: InternalDNSRule provides rules for the internal DNS + server + properties: + dnsRecords: + description: The DNS records for the internal DNS server + items: + description: DNSRecord provides an internal DNS record + properties: + hostname: + description: The hostname for the DNS record + type: string + ip: + description: The IP address for the DNS record + type: string + ttl: + description: Optional Time To Live (TTL) for the DNS record + type: integer + type: + description: The type of DNS record + type: string + required: + - hostname + - ip + - type + type: object + type: array + maasDomain: + description: The domain name for the internal DNS server + type: string + required: + - dnsRecords + - maasDomain + type: object + type: array + resourceAvailabilityRules: + items: + description: ResourceAvailabilityRule provides rules for validating + resource availability + properties: + name: + description: Unique name for the rule + type: string + resources: + description: The list of resources to validate + items: + description: Resource defines a compute resource + properties: + az: + description: Availability Zone + type: string + labels: + description: Optional machine labels + items: + type: string + type: array + numCPU: + description: Minimum CPU cores per machine + type: integer + numDisk: + description: Minimum Disk space per machine in GB + type: integer + numMachines: + description: Minimum desired number of machines + type: integer + numRAM: + description: Minimum RAM per machine in GB + type: integer + pool: + description: Optional machine pool + type: string + required: + - az + - numCPU + - numDisk + - numMachines + - numRAM + type: object + type: array + required: + - name + - resources + type: object + type: array + upstreamDNSRules: + items: + description: UpstreamDNSRule provides rules for validating the external + DNS server + properties: + name: + description: Unique name for the rule + type: string + numDNSServers: + description: The minimum expected number of upstream DNS servers + type: integer + required: + - name + - numDNSServers + type: object + type: array + required: + - auth + - host + type: object + status: + description: MaasValidatorStatus defines the observed state of MaasValidator + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/chart/validator-plugin-maas/values.yaml b/chart/validator-plugin-maas/values.yaml index 10c6ad2..a1d7563 100644 --- a/chart/validator-plugin-maas/values.yaml +++ b/chart/validator-plugin-maas/values.yaml @@ -31,7 +31,7 @@ controllerManager: - ALL image: repository: quay.io/validator-labs/validator-plugin-maas - tag: v0.0.4 # x-release-please-version + tag: v0.0.5 # x-release-please-version resources: limits: cpu: 500m diff --git a/go.mod b/go.mod index 004c70d..e96e528 100644 --- a/go.mod +++ b/go.mod @@ -8,10 +8,10 @@ require ( github.com/canonical/gomaasclient v0.6.0 github.com/deckarep/golang-set/v2 v2.6.0 github.com/go-logr/logr v1.4.2 - github.com/onsi/ginkgo/v2 v2.19.0 + github.com/onsi/ginkgo/v2 v2.19.1 github.com/onsi/gomega v1.34.0 github.com/stretchr/testify v1.9.0 - github.com/validator-labs/validator v0.0.49 + github.com/validator-labs/validator v0.0.50 k8s.io/api v0.30.3 k8s.io/apimachinery v0.30.3 k8s.io/client-go v0.30.3 diff --git a/go.sum b/go.sum index 8d3b911..5faf919 100644 --- a/go.sum +++ b/go.sum @@ -205,8 +205,8 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U= -github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= -github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= +github.com/onsi/ginkgo/v2 v2.19.1 h1:QXgq3Z8Crl5EL1WBAC98A5sEBHARrAJNzAmMxzLcRF0= +github.com/onsi/ginkgo/v2 v2.19.1/go.mod h1:O3DtEWQkPa/F7fBMgmZQKKsluAy8pd3rEQdrjkPb9zA= github.com/onsi/gomega v1.34.0 h1:eSSPsPNp6ZpsG8X1OVmOTxig+CblTc4AxpPBykhe2Os= github.com/onsi/gomega v1.34.0/go.mod h1:MIKI8c+f+QLWk+hxbePD4i0LMJSExPaZOVfkoex4cAo= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -245,8 +245,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/validator-labs/validator v0.0.49 h1:gqtiVFBdLHNJysGx7MDx09uYJ7aLZ5x0bHgFmN9bVhM= -github.com/validator-labs/validator v0.0.49/go.mod h1:YxUKAXuSR6fIAi7WCQV/Wbrzf9szf8aCTeYWEA+JyIY= +github.com/validator-labs/validator v0.0.50 h1:8h0Dy1Hl0818WuTF8hgZ3HaNxUtGSm130Zrp7f7vjGw= +github.com/validator-labs/validator v0.0.50/go.mod h1:YxUKAXuSR6fIAi7WCQV/Wbrzf9szf8aCTeYWEA+JyIY= github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/internal/controller/maasvalidator_controller.go b/internal/controller/maasvalidator_controller.go index 2cc72ca..54f18d5 100644 --- a/internal/controller/maasvalidator_controller.go +++ b/internal/controller/maasvalidator_controller.go @@ -141,7 +141,7 @@ func (r *MaasValidatorReconciler) Reconcile(ctx context.Context, req ctrl.Reques resp.AddResult(vrr, err) } - seenAZ := make([]string, 0) + seenAZ := make(map[string]bool, 0) // MAAS Instance resource availability rules for _, rule := range validator.Spec.ResourceAvailabilityRules { vrr, err := resourceRulesService.ReconcileMaasInstanceResourceRule(rule, seenAZ) @@ -149,7 +149,7 @@ func (r *MaasValidatorReconciler) Reconcile(ctx context.Context, req ctrl.Reques r.Log.V(0).Error(err, "failed to reconcile MAAS resource rule") } resp.AddResult(vrr, err) - seenAZ = append(seenAZ, rule.AZ) + seenAZ[rule.AZ] = true } // Patch the ValidationResult with the latest ValidationRuleResults diff --git a/internal/validators/res/resource_validator.go b/internal/validators/res/resource_validator.go index ef54a34..15f309a 100644 --- a/internal/validators/res/resource_validator.go +++ b/internal/validators/res/resource_validator.go @@ -3,6 +3,7 @@ package res import ( "fmt" + "slices" "sort" "github.com/canonical/gomaasclient/api" @@ -38,15 +39,15 @@ func NewResourceRulesService(log logr.Logger, api api.Machines) *ResourceRulesSe } // ReconcileMaasInstanceResourceRule reconciles a MAAS instance resource rule from the MaasValidator config -func (s *ResourceRulesService) ReconcileMaasInstanceResourceRule(rule v1alpha1.ResourceAvailabilityRule, seen []string) (*types.ValidationRuleResult, error) { +func (s *ResourceRulesService) ReconcileMaasInstanceResourceRule(rule v1alpha1.ResourceAvailabilityRule, seen map[string]bool) (*types.ValidationRuleResult, error) { errs := make([]error, 0) details := make([]string, 0) vr := utils.BuildValidationResult(rule.Name, constants.ValidationTypeResource) // do not process an AZ more than once - if containsString(seen, rule.AZ) { - errs = append(errs, fmt.Errorf("availability zone %s already validated", rule.AZ)) + if seen[rule.AZ] { + errs = append(errs, fmt.Errorf("availability zone %s referenced in a previous rule; AZ resource requirements must be defined in a single rule", rule.AZ)) } else { errs, details = s.findMachineResources(rule) } @@ -59,85 +60,82 @@ func (s *ResourceRulesService) ReconcileMaasInstanceResourceRule(rule v1alpha1.R return vr, nil } -// contains checks if a slice contains a string -func containsString(s []string, e string) bool { - for _, a := range s { - if a == e { - return true - } - } - return false -} - // findMachineResources checks whether the rule is satisfied by the machines in the availability zone func (s *ResourceRulesService) findMachineResources(rule v1alpha1.ResourceAvailabilityRule) ([]error, []string) { errs := make([]error, 0) details := make([]string, 0) - // Get all "ready" machines in the availability zone - machines, err := s.api.Get(&entity.MachinesParams{Zone: []string{rule.AZ}, Status: []string{"ready"}}) + resources, err := s.getAvailableMAASResources(rule) if err != nil { - errs = append(errs, fmt.Errorf("error retrieving machines in availability zone %s", rule.AZ)) + errs = append(errs, err) return errs, details } - resources := formatMachines(machines) - // each rule may have multiple resource checks for 1 AZ for _, rr := range rule.Resources { - detail, err := compareResources(&resources, rr) + var matching []resource + resources, matching, err = s.compareResources(resources, rr) if err != nil { errs = append(errs, err) } - if detail != "" { - details = append(details, detail) + + if len(matching) == rr.NumMachines { + details = append(details, fmt.Sprintf("Found %d machine(s) available with %v Cores, %vGB RAM, %vGB Disk", len(matching), rr.NumCPU, rr.RAM, rr.Disk)) } } return errs, details } -func compareResources(resources *[]resource, expected v1alpha1.Resource) (string, error) { - need := expected.NumMachines - errMsg := fmt.Errorf("insufficient machines available with %v Cores, %vGB RAM, %vGB Disk", expected.NumCPU, expected.RAM, expected.Disk) +func (s *ResourceRulesService) compareResources(resources []resource, expected v1alpha1.Resource) ([]resource, []resource, error) { + if len(resources) < expected.NumMachines { + return resources, nil, fmt.Errorf("not enough resources available in az: have: %v, need: %v", len(resources), expected.NumMachines) + } - for seen := 0; need > 0; seen++ { - // not enough machines left to fill requirement - if len(*resources)-seen < need { - return "", errMsg - } + matching := make([]resource, 0) + remaining := make([]resource, 0) - resource := (*resources)[seen] - // check that the machine has the required resources - if resource.NumCPU < expected.NumCPU || resource.RAM < expected.RAM || resource.Disk < expected.Disk { - continue - } + for _, r := range resources { + ok := true + if r.NumCPU < expected.NumCPU || r.RAM < expected.RAM || r.Disk < expected.Disk { + ok = false + } // if pool is specified, check that the machine is in the required pool - if expected.Pool != "" && resource.Pool != expected.Pool { - continue + if expected.Pool != "" && r.Pool != expected.Pool { + ok = false } - // if tags are specified, check that the machine has all the required tags if len(expected.Tags) > 0 { for _, tag := range expected.Tags { - if !containsString(resource.Tags, tag) { - continue + if !slices.Contains(r.Tags, tag) { + ok = false } } } - // once all checks pass, remove the machine from the list of available machines - *resources = append((*resources)[:seen], (*resources)[seen+1:]...) - need-- - // decrement seen to account for the removed resource - seen-- + if ok { + matching = append(matching, r) + } else { + remaining = append(remaining, r) + } + + if len(matching) == expected.NumMachines { + remaining = append(remaining, resources[len(matching):]...) + return remaining, matching, nil + } } - return fmt.Sprintf("Found %d machine(s) available with %v Cores, %vGB RAM, %vGB Disk", expected.NumMachines, expected.NumCPU, expected.RAM, expected.Disk), nil + err := fmt.Errorf("insufficient machines available with %v Cores, %vGB RAM, %vGB Disk. %v/%v available", expected.NumCPU, expected.RAM, expected.Disk, len(matching), expected.NumMachines) + return resources, matching, err } -func formatMachines(machines []entity.Machine) []resource { +func (s *ResourceRulesService) getAvailableMAASResources(rule v1alpha1.ResourceAvailabilityRule) ([]resource, error) { + machines, err := s.api.Get(&entity.MachinesParams{Zone: []string{rule.AZ}, Status: []string{"ready"}}) + if err != nil { + return nil, fmt.Errorf("error retrieving machines in availability zone %s: %w", rule.AZ, err) + } + resources := make([]resource, 0) for _, m := range machines { resources = append(resources, resource{ @@ -153,5 +151,5 @@ func formatMachines(machines []entity.Machine) []resource { sort.Slice(resources, func(i, j int) bool { return resources[i].NumCPU < resources[j].NumCPU }) - return resources + return resources, nil } diff --git a/internal/validators/res/resource_validator_test.go b/internal/validators/res/resource_validator_test.go index 35e7eda..df8ed3a 100644 --- a/internal/validators/res/resource_validator_test.go +++ b/internal/validators/res/resource_validator_test.go @@ -57,7 +57,9 @@ func TestReconcileMaasInstanceImageRule(t *testing.T) { logr.Logger{}, &DummyMachine{ MachinesList: []entity.Machine{ - {Zone: entity.Zone{Name: "az1"}, Hostname: "maas.foo", ResourceURI: "/api/2.0/machines/1/", CPUCount: 24, Memory: 32, Storage: 150, Pool: entity.ResourcePool{Name: "pool1"}, TagNames: []string{"tag1", "tag2"}}, + {Zone: entity.Zone{Name: "az1"}, Hostname: "maas.foo", ResourceURI: "/api/2.0/machines/1/", CPUCount: 24, Memory: 32 * 1024, Storage: 150 * 1000, Pool: entity.ResourcePool{Name: "pool1"}, TagNames: []string{"tag1", "tag2"}}, + {Zone: entity.Zone{Name: "az1"}, Hostname: "maas.foo", ResourceURI: "/api/2.0/machines/1/", CPUCount: 12, Memory: 32 * 1024, Storage: 150 * 1000, Pool: entity.ResourcePool{Name: "pool1"}, TagNames: []string{"tag1", "tag2"}}, + {Zone: entity.Zone{Name: "az1"}, Hostname: "maas.foo", ResourceURI: "/api/2.0/machines/1/", CPUCount: 12, Memory: 32 * 1024, Storage: 150 * 1000, Pool: entity.ResourcePool{Name: "pool1"}, TagNames: []string{"tag1", "tag2"}}, }, }), resources: []v1alpha1.ResourceAvailabilityRule{ @@ -65,7 +67,7 @@ func TestReconcileMaasInstanceImageRule(t *testing.T) { {NumMachines: 2, NumCPU: 16, RAM: 16, Disk: 100, Pool: "pool1", Tags: []string{"tag1", "tag2"}}, }}, }, - errors: []string{"insufficient machines available with 16 Cores, 16GB RAM, 100GB Disk"}, + errors: []string{"insufficient machines available with 16 Cores, 16GB RAM, 100GB Disk. 1/2 available"}, details: nil, }, { @@ -80,7 +82,7 @@ func TestReconcileMaasInstanceImageRule(t *testing.T) { {NumMachines: 1, NumCPU: 16, RAM: 16, Disk: 100, Pool: "pool1", Tags: []string{"tag1", "tag2"}}, }}, }, - errors: []string{"insufficient machines available with 16 Cores, 16GB RAM, 100GB Disk"}, + errors: []string{"not enough resources available in az: have: 0, need: 1"}, details: nil, }, } @@ -91,7 +93,7 @@ func TestReconcileMaasInstanceImageRule(t *testing.T) { var errors []string for _, rule := range tc.resources { - vr, _ := tc.ruleService.ReconcileMaasInstanceResourceRule(rule, []string{}) + vr, _ := tc.ruleService.ReconcileMaasInstanceResourceRule(rule, map[string]bool{}) details = append(details, vr.Condition.Details...) errors = append(errors, vr.Condition.Failures...) }