diff --git a/.agents/config-expert-river.md b/.agents/config-expert-river.md index 0c8c141abe..8b2d83fb93 100644 --- a/.agents/config-expert-river.md +++ b/.agents/config-expert-river.md @@ -299,7 +299,6 @@ River has expertise in identifying unused configuration fields, optimizing confi **3. Client Library Configurations:** - `pkg/client/iam/IAMConfig` - Identity and access management configuration - `pkg/client/ocm/impl/OCMConfig` - OpenShift Cluster Manager client configuration -- `pkg/client/ocm/impl/AddonConfig` - OCM addon configuration - `pkg/client/telemetry/TelemetryConfigImpl` - Telemetry and phone-home configuration **4. Server Infrastructure Configurations:** @@ -320,7 +319,6 @@ River has expertise in identifying unused configuration fields, optimizing confi - `TenantResourceConfig` - Tenant resource allocation and overrides - `AuthProviderConfig` - Additional auth provider configurations for centrals - `DataPlaneClusterConfig` - GitOps data plane cluster definitions -- `AddonConfig` - Addon installation configuration **7. Sub-configurations and Nested Structs:** - `ManagedDB` (fleetshard) - Managed database configuration for RDS diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 05155df1f8..5da30a76f8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,7 +8,7 @@ repos: require_serial: true pass_filenames: true stages: [pre-push, manual] - files: '(openapi/.*|pkg/workers/worker_interface.go|pkg/client/ocm/id.go|pkg/client/aws/client.go|pkg/client/ocm/client.go|pkg/client/iam/client.go|pkg/services/authorization/authorization.go|pkg/services/sso/iam_service.go|pkg/client/redhatsso/client.go|pkg/auth/auth_agent_service.go|internal/central/pkg/services/cluster_placement_strategy.go|internal/central/pkg/services/cloud_providers.go|internal/central/pkg/services/clusters.go|internal/central/pkg/services/quota.go|internal/central/pkg/services/fleetshard_operator_addon.go|internal/central/pkg/services/quota_service_factory.go|internal/central/pkg/clusters/cluster_builder.go|internal/central/pkg/clusters/provider.go|internal/central/pkg/services/central.go)' + files: '(openapi/.*|pkg/workers/worker_interface.go|pkg/client/ocm/id.go|pkg/client/aws/client.go|pkg/client/ocm/client.go|pkg/client/iam/client.go|pkg/services/authorization/authorization.go|pkg/services/sso/iam_service.go|pkg/client/redhatsso/client.go|pkg/auth/auth_agent_service.go|internal/central/pkg/services/cluster_placement_strategy.go|internal/central/pkg/services/cloud_providers.go|internal/central/pkg/services/clusters.go|internal/central/pkg/services/quota.go|internal/central/pkg/services/quota_service_factory.go|internal/central/pkg/clusters/cluster_builder.go|internal/central/pkg/clusters/provider.go|internal/central/pkg/services/central.go)' - repo: https://github.com/Yelp/detect-secrets rev: v1.5.0 hooks: diff --git a/.secrets.baseline b/.secrets.baseline index d304f0a575..c9677ce8cc 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -278,7 +278,7 @@ "filename": "pkg/client/fleetmanager/mocks/client_moq.go", "hashed_secret": "44e17306b837162269a410204daaa5ecee4ec22c", "is_verified": false, - "line_number": 760 + "line_number": 704 } ], "pkg/client/redhatsso/api/api/openapi.yaml": [ @@ -296,63 +296,63 @@ "filename": "templates/service-template.yml", "hashed_secret": "13032f402fed753c2248419ea4f69f99931f6dbc", "is_verified": false, - "line_number": 450 + "line_number": 442 }, { "type": "Base64 High Entropy String", "filename": "templates/service-template.yml", "hashed_secret": "30025f80f6e22cdafb85db387d50f90ea884576a", "is_verified": false, - "line_number": 450 + "line_number": 442 }, { "type": "Base64 High Entropy String", "filename": "templates/service-template.yml", "hashed_secret": "355f24fd038bcaf85617abdcaa64af51ed19bbcf", "is_verified": false, - "line_number": 450 + "line_number": 442 }, { "type": "Base64 High Entropy String", "filename": "templates/service-template.yml", "hashed_secret": "3d8a1dcd2c3c765ce35c9a9552d23273cc4ddace", "is_verified": false, - "line_number": 450 + "line_number": 442 }, { "type": "Base64 High Entropy String", "filename": "templates/service-template.yml", "hashed_secret": "4ac7b0522761eba972467942cd5cd7499dd2c361", "is_verified": false, - "line_number": 450 + "line_number": 442 }, { "type": "Base64 High Entropy String", "filename": "templates/service-template.yml", "hashed_secret": "7639ab2a6bcf2ea30a055a99468c9cd844d4c22a", "is_verified": false, - "line_number": 450 + "line_number": 442 }, { "type": "Base64 High Entropy String", "filename": "templates/service-template.yml", "hashed_secret": "b56360daf4793d2a74991a972b34d95bc00fb2da", "is_verified": false, - "line_number": 450 + "line_number": 442 }, { "type": "Base64 High Entropy String", "filename": "templates/service-template.yml", "hashed_secret": "c9a73ef9ee8ce9f38437227801c70bcc6740d1a1", "is_verified": false, - "line_number": 450 + "line_number": 442 }, { "type": "Secret Keyword", "filename": "templates/service-template.yml", "hashed_secret": "4e199b4a1c40b497a95fcd1cd896351733849949", "is_verified": false, - "line_number": 633, + "line_number": 625, "is_secret": false } ], @@ -382,5 +382,5 @@ } ] }, - "generated_at": "2026-01-23T11:01:34Z" + "generated_at": "2026-01-26T16:35:51Z" } diff --git a/Makefile b/Makefile index 94e5054429..c6268c4f0a 100644 --- a/Makefile +++ b/Makefile @@ -598,9 +598,6 @@ secrets/touch: secrets/ocm-service.clientId \ secrets/ocm-service.clientSecret \ secrets/ocm-service.token \ - secrets/ocm-addon-service.clientId \ - secrets/ocm-addon-service.clientSecret \ - secrets/ocm-addon-service.token \ secrets/rhsso-logs.clientId \ secrets/rhsso-logs.clientSecret \ secrets/rhsso-metrics.clientId \ @@ -632,11 +629,8 @@ centralidp/setup: ocm/setup: OCM_OFFLINE_TOKEN ?= "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" # pragma: allowlist secret ocm/setup: @echo -n "$(OCM_OFFLINE_TOKEN)" > secrets/ocm-service.token - @echo -n "$(OCM_OFFLINE_TOKEN)" > secrets/ocm-addon-service.token @echo -n "" > secrets/ocm-service.clientId @echo -n "" > secrets/ocm-service.clientSecret - @echo -n "" > secrets/ocm-addon-service.clientId - @echo -n "" > secrets/ocm-addon-service.clientSecret .PHONY: ocm/setup # create project where the service will be deployed in an OpenShift cluster @@ -657,9 +651,6 @@ deploy/secrets: -p OCM_SERVICE_CLIENT_ID="$(shell ([ -s './secrets/ocm-service.clientId' ] && [ -z '${OCM_SERVICE_CLIENT_ID}' ]) && cat ./secrets/ocm-service.clientId || echo '${OCM_SERVICE_CLIENT_ID}')" \ -p OCM_SERVICE_CLIENT_SECRET="$(shell ([ -s './secrets/ocm-service.clientSecret' ] && [ -z '${OCM_SERVICE_CLIENT_SECRET}' ]) && cat ./secrets/ocm-service.clientSecret || echo '${OCM_SERVICE_CLIENT_SECRET}')" \ -p OCM_SERVICE_TOKEN="$(shell ([ -s './secrets/ocm-service.token' ] && [ -z '${OCM_SERVICE_TOKEN}' ]) && cat ./secrets/ocm-service.token || echo '${OCM_SERVICE_TOKEN}')" \ - -p OCM_ADDON_SERVICE_CLIENT_ID="$(shell ([ -s './secrets/ocm-addon-service.clientId' ] && [ -z '${OCM_ADDON_SERVICE_CLIENT_ID}' ]) && cat ./secrets/ocm-addon-service.clientId || echo '${OCM_ADDON_SERVICE_CLIENT_ID}')" \ - -p OCM_ADDON_SERVICE_CLIENT_SECRET="$(shell ([ -s './secrets/ocm-addon-service.clientSecret' ] && [ -z '${OCM_ADDON_SERVICE_CLIENT_SECRET}' ]) && cat ./secrets/ocm-addon-service.clientSecret || echo '${OCM_ADDON_SERVICE_CLIENT_SECRET}')" \ - -p OCM_ADDON_SERVICE_TOKEN="$(shell ([ -s './secrets/ocm-addon-service.token' ] && [ -z '${OCM_ADDON_SERVICE_TOKEN}' ]) && cat ./secrets/ocm-addon-service.token || echo '${OCM_ADDON_SERVICE_TOKEN}')" \ -p AWS_ACCESS_KEY="$(shell ([ -s './secrets/aws.accesskey' ] && [ -z '${AWS_ACCESS_KEY}' ]) && cat ./secrets/aws.accesskey || echo '${AWS_ACCESS_KEY}')" \ -p AWS_ACCOUNT_ID="$(shell ([ -s './secrets/aws.accountid' ] && [ -z '${AWS_ACCOUNT_ID}' ]) && cat ./secrets/aws.accountid || echo '${AWS_ACCOUNT_ID}')" \ -p AWS_SECRET_ACCESS_KEY="$(shell ([ -s './secrets/aws.secretaccesskey' ] && [ -z '${AWS_SECRET_ACCESS_KEY}' ]) && cat ./secrets/aws.secretaccesskey || echo '${AWS_SECRET_ACCESS_KEY}')" \ @@ -702,7 +693,6 @@ deploy/service: ENABLE_CENTRAL_EXTERNAL_DOMAIN ?= "false" deploy/service: ENABLE_CENTRAL_LIFE_SPAN ?= "false" deploy/service: CENTRAL_LIFE_SPAN ?= "48" deploy/service: OCM_URL ?= "https://api.stage.openshift.com" -deploy/service: OCM_ADDON_SERVICE_URL ?= "https://api.stage.openshift.com" deploy/service: SERVICE_PUBLIC_HOST_URL ?= "https://api.openshift.com" deploy/service: ENABLE_TERMS_ACCEPTANCE ?= "false" deploy/service: ENABLE_DENY_LIST ?= "false" @@ -738,7 +728,6 @@ endif -p ENABLE_OCM_MOCK=$(ENABLE_OCM_MOCK) \ -p OCM_MOCK_MODE=$(OCM_MOCK_MODE) \ -p OCM_URL="$(OCM_URL)" \ - -p OCM_ADDON_SERVICE_URL="$(OCM_ADDON_SERVICE_URL)" \ -p AMS_URL="${AMS_URL}" \ -p SERVICE_PUBLIC_HOST_URL="https://$(shell oc get routes/fleet-manager -o jsonpath="{.spec.host}" -n $(NAMESPACE))" \ -p ENABLE_TERMS_ACCEPTANCE="${ENABLE_TERMS_ACCEPTANCE}" \ diff --git a/config/emailsender-authz.yaml b/config/emailsender-authz.yaml index d8ec5d8428..2d2b418c39 100644 --- a/config/emailsender-authz.yaml +++ b/config/emailsender-authz.yaml @@ -1,7 +1,6 @@ -# For development we use ocm tokens issued by RH SSO to authenticate to emailsender API -# for prod we use serviceaccount issued by the OSD cluster for centrals -# this file should be replaced by a secret/configmap mounted to emailsender -# with the fitting values per cluster through the fleetshard addon +# For development, we use ocm tokens issued by RH SSO to authenticate to emailsender API. +# For prod, we use serviceaccount issued by the OSD cluster for centrals. +# This file should be replaced by a secret/configmap mounted to emailsender with the fitting values per cluster. --- jwks_urls: - "https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/certs" diff --git a/dashboards/grafana-dashboard-acs-fleet-manager.configmap.yaml b/dashboards/grafana-dashboard-acs-fleet-manager.configmap.yaml index c13609c76c..62794b3441 100644 --- a/dashboards/grafana-dashboard-acs-fleet-manager.configmap.yaml +++ b/dashboards/grafana-dashboard-acs-fleet-manager.configmap.yaml @@ -724,108 +724,6 @@ data: "type": "prometheus" }, "description": "The number of centrals with no quota allowance." - }, - { - "datasource": { - "type": "prometheus", - "uid": "${datasource}" - }, - "description": "Shows the addon installation status on the Data Plane clusters ", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "fillOpacity": 70, - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineWidth": 0, - "spanNulls": false - }, - "fieldMinMax": false, - "mappings": [ - { - "options": { - "0": { - "color": "green", - "index": 0, - "text": "Healthy" - }, - "1": { - "color": "orange", - "index": 1, - "text": "Upgrade" - }, - "2": { - "color": "red", - "index": 1, - "text": "Unhealthy" - } - }, - "type": "value" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 42 - }, - "id": 16, - "options": { - "alignValue": "left", - "legend": { - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "mergeValues": false, - "rowHeight": 0.9, - "showValue": "auto", - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "${datasource}" - }, - "disableTextWrap": false, - "editorMode": "code", - "exemplar": false, - "expr": "max by(cluster_name) (acs_fleet_manager_cluster_addon_status{id=~\"acs-fleetshard-dev|acs-fleetshard-qe|acs-fleetshard\"})", - "format": "time_series", - "fullMetaSearch": false, - "includeNullMetadata": true, - "instant": false, - "legendFormat": "__auto", - "range": true, - "refId": "A", - "useBackend": false - } - ], - "title": "Addon Status", - "type": "state-timeline" } ], "schemaVersion": 37, diff --git a/deploy/charts/fleetshard-sync/templates/deployment.yaml b/deploy/charts/fleetshard-sync/templates/deployment.yaml index ade03b01d9..6512ecb805 100644 --- a/deploy/charts/fleetshard-sync/templates/deployment.yaml +++ b/deploy/charts/fleetshard-sync/templates/deployment.yaml @@ -130,10 +130,6 @@ spec: value: {{ .Values.gitops.enabled | quote }} - name: RHACS_TARGETED_OPERATOR_UPGRADES value: {{ .Values.targetedOperatorUpgrades.enabled | quote }} - - name: RHACS_ADDON_AUTO_UPGRADE - value: {{ .Values.addonAutoUpgradeEnabled | quote }} - - name: FLEETSHARD_ADDON_NAME - value: {{ .Values.addonName | quote }} {{- if eq "SERVICE_ACCOUNT_TOKEN" .Values.authType }} - name: FLEET_MANAGER_TOKEN_FILE value: "/var/run/secrets/tokens/fleet-manager-token" diff --git a/deploy/charts/fleetshard-sync/values.yaml b/deploy/charts/fleetshard-sync/values.yaml index 3f2e3f7fd6..15fdc09145 100644 --- a/deploy/charts/fleetshard-sync/values.yaml +++ b/deploy/charts/fleetshard-sync/values.yaml @@ -54,8 +54,6 @@ targetedOperatorUpgrades: affinity: {} nodeSelector: {} tolerations: [] -addonAutoUpgradeEnabled: true -addonName: acs-fleetshard tenantImagePullSecret: name: "" key: .dockerconfigjson diff --git a/dev/env/defaults/00-defaults.env b/dev/env/defaults/00-defaults.env index 940adda887..61cacd3c1d 100644 --- a/dev/env/defaults/00-defaults.env +++ b/dev/env/defaults/00-defaults.env @@ -30,9 +30,6 @@ export EMAIL_SENDER_IMAGE_DEFAULT="" export OCM_SERVICE_CLIENT_ID_DEFAULT="" export OCM_SERVICE_CLIENT_SECRET_DEFAULT="" export OCM_SERVICE_TOKEN_DEFAULT="" -export OCM_ADDON_SERVICE_CLIENT_ID_DEFAULT="" -export OCM_ADDON_SERVICE_CLIENT_SECRET_DEFAULT="" -export OCM_ADDON_SERVICE_TOKEN_DEFAULT="" export ROUTE53_ACCESS_KEY_DEFAULT="" export ROUTE53_SECRET_ACCESS_KEY_DEFAULT="" export SPAWN_LOGGER_DEFAULT="false" diff --git a/dev/env/manifests/addons/acs-fleetshard/01-acs-fleetshard-addon.yaml b/dev/env/manifests/addons/acs-fleetshard/01-acs-fleetshard-addon.yaml deleted file mode 100644 index e7b88fe9e5..0000000000 --- a/dev/env/manifests/addons/acs-fleetshard/01-acs-fleetshard-addon.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# This object is required for reporting the addon metadata to fleet manager -apiVersion: addons.managed.openshift.io/v1alpha1 -kind: Addon -metadata: - name: acs-fleetshard -spec: - displayName: Red Hat Advanced Cluster Security Fleet Shard - install: - olmOwnNamespace: - catalogSourceImage: acs-fleetshard-index@sha256:71eabccb4d3962043eac953fb3c09a6cc6a88b18c472dd264efc5eb3da4960ac - channel: stable - namespace: "$ACSCS_NAMESPACE" - packageName: acs-fleetshard - type: OLMOwnNamespace - installAckRequired: false - packageOperator: - image: acs-fleetshard-package@sha256:3e51c039662b875c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c - pause: true # No actual processing by the addon-operator - version: 0.1.0 diff --git a/dev/env/manifests/addons/acs-fleetshard/02-acs-fleetshard-parameters-secret.yaml b/dev/env/manifests/addons/acs-fleetshard/02-acs-fleetshard-parameters-secret.yaml deleted file mode 100644 index ac888242cf..0000000000 --- a/dev/env/manifests/addons/acs-fleetshard/02-acs-fleetshard-parameters-secret.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: addon-acs-fleetshard-parameters - namespace: "$ACSCS_NAMESPACE" -stringData: {} diff --git a/dev/env/manifests/addons/crds/00-addon-crd.yaml b/dev/env/manifests/addons/crds/00-addon-crd.yaml deleted file mode 100644 index b7141f2146..0000000000 --- a/dev/env/manifests/addons/crds/00-addon-crd.yaml +++ /dev/null @@ -1,622 +0,0 @@ -# Downloaded from https://raw.githubusercontent.com/openshift/addon-operator/main/deploy/crds/addons.managed.openshift.io_addons.yaml ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.6.2 - creationTimestamp: null - name: addons.addons.managed.openshift.io -spec: - group: addons.managed.openshift.io - names: - kind: Addon - listKind: AddonList - plural: addons - singular: addon - scope: Cluster - versions: - - additionalPrinterColumns: - - jsonPath: .status.phase - name: Status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: "Addon is the Schema for the Addons API \n **Example** ```yaml - apiVersion: addons.managed.openshift.io/v1alpha1 kind: Addon metadata: \n - \tname: reference-addon \n spec: \n \tdisplayName: An amazing example addon! - \tnamespaces: \t- name: reference-addon \tinstall: \t type: OLMOwnNamespace - \t olmOwnNamespace: \t namespace: reference-addon \t packageName: - reference-addon \t channel: alpha \t catalogSourceImage: quay.io/osd-addons/reference-addon-index@sha256:58cb1c4478a150dc44e6c179d709726516d84db46e4e130a5227d8b76456b5bd - \n ```" - 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: AddonSpec defines the desired state of Addon. - properties: - commonAnnotations: - additionalProperties: - type: string - description: Annotations to be applied to all resources. - type: object - commonLabels: - additionalProperties: - type: string - description: Labels to be applied to all resources. - type: object - correlationID: - description: Correlation ID for co-relating current AddonCR revision - and reported status. - type: string - deleteAckRequired: - description: Defines whether the addon needs acknowledgment from the - underlying addon's operator before deletion. - type: boolean - displayName: - description: Human readable name for this addon. - minLength: 1 - type: string - install: - description: Defines how an Addon is installed. This field is immutable. - properties: - olmAllNamespaces: - description: OLMAllNamespaces config parameters. Present only - if Type = OLMAllNamespaces. - properties: - additionalCatalogSources: - description: Additional catalog source objects to be created - in the cluster - items: - properties: - image: - description: Image url of the additional catalog source - minLength: 1 - type: string - name: - description: Name of the additional catalog source - minLength: 1 - type: string - required: - - image - - name - type: object - type: array - catalogSourceImage: - description: Defines the CatalogSource image. - minLength: 1 - type: string - channel: - description: Channel for the Subscription object. - minLength: 1 - type: string - config: - description: Configs to be passed to subscription OLM object - properties: - env: - description: Array of env variables to be passed to the - subscription object. - items: - properties: - name: - description: Name of the environment variable - minLength: 1 - type: string - value: - description: Value of the environment variable - minLength: 1 - type: string - required: - - name - - value - type: object - type: array - required: - - env - type: object - namespace: - description: Namespace to install the Addon into. - minLength: 1 - type: string - packageName: - description: Name of the package to install via OLM. OLM will - resove this package name to install the matching bundle. - minLength: 1 - type: string - pullSecretName: - description: Reference to a secret of type kubernetes.io/dockercfg - or kubernetes.io/dockerconfigjson in the addon operators - installation namespace. The secret referenced here, will - be made available to the addon in the addon installation - namespace, as addon-pullsecret prior to installing the addon - itself. - type: string - required: - - catalogSourceImage - - channel - - namespace - - packageName - type: object - olmOwnNamespace: - description: OLMOwnNamespace config parameters. Present only if - Type = OLMOwnNamespace. - properties: - additionalCatalogSources: - description: Additional catalog source objects to be created - in the cluster - items: - properties: - image: - description: Image url of the additional catalog source - minLength: 1 - type: string - name: - description: Name of the additional catalog source - minLength: 1 - type: string - required: - - image - - name - type: object - type: array - catalogSourceImage: - description: Defines the CatalogSource image. - minLength: 1 - type: string - channel: - description: Channel for the Subscription object. - minLength: 1 - type: string - config: - description: Configs to be passed to subscription OLM object - properties: - env: - description: Array of env variables to be passed to the - subscription object. - items: - properties: - name: - description: Name of the environment variable - minLength: 1 - type: string - value: - description: Value of the environment variable - minLength: 1 - type: string - required: - - name - - value - type: object - type: array - required: - - env - type: object - namespace: - description: Namespace to install the Addon into. - minLength: 1 - type: string - packageName: - description: Name of the package to install via OLM. OLM will - resove this package name to install the matching bundle. - minLength: 1 - type: string - pullSecretName: - description: Reference to a secret of type kubernetes.io/dockercfg - or kubernetes.io/dockerconfigjson in the addon operators - installation namespace. The secret referenced here, will - be made available to the addon in the addon installation - namespace, as addon-pullsecret prior to installing the addon - itself. - type: string - required: - - catalogSourceImage - - channel - - namespace - - packageName - type: object - type: - description: Type of installation. - enum: - - OLMOwnNamespace - - OLMAllNamespaces - type: string - required: - - type - type: object - installAckRequired: - description: Defines if the addon needs installation acknowledgment - from its corresponding addon instance. - type: boolean - monitoring: - description: Defines how an addon is monitored. - properties: - federation: - description: Configuration parameters to be injected in the ServiceMonitor - used for federation. The target prometheus server found by matchLabels - needs to serve service-ca signed TLS traffic (https://docs.openshift.com/container-platform/4.6/security/certificate_types_descriptions/service-ca-certificates.html), - and it needs to be runing inside the namespace specified by - `.monitoring.federation.namespace` with the service name 'prometheus'. - properties: - matchLabels: - additionalProperties: - type: string - description: List of labels used to discover the prometheus - server(s) to be federated. - minProperties: 1 - type: object - matchNames: - description: List of series names to federate from the prometheus - server. - items: - type: string - type: array - namespace: - description: Namespace where the prometheus server is running. - minLength: 1 - type: string - portName: - description: The name of the service port fronting the prometheus - server. - minLength: 1 - type: string - required: - - matchLabels - - matchNames - - namespace - - portName - type: object - monitoringStack: - description: Settings For Monitoring Stack - properties: - rhobsRemoteWriteConfig: - description: Settings for RHOBS Remote Write - properties: - allowlist: - description: List of metrics to push to RHOBS. Any metric - not listed here is dropped. - items: - type: string - type: array - oauth2: - description: OAuth2 config for the remote write URL - properties: - clientId: - description: The secret or configmap containing the - OAuth2 client id - properties: - configMap: - description: ConfigMap containing data to use - for the targets. - properties: - key: - description: The key to select. - type: string - name: - description: 'Name of the referent. More info: - https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, - kind, uid?' - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - secret: - description: Secret containing data to use for - the targets. - properties: - key: - description: The key of the secret to select - from. Must be a valid secret key. - type: string - name: - description: 'Name of the referent. More info: - https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, - kind, uid?' - type: string - optional: - description: Specify whether the Secret or - its key must be defined - type: boolean - required: - - key - type: object - type: object - clientSecret: - description: The secret containing the OAuth2 client - secret - properties: - key: - description: The key of the secret to select from. Must - be a valid secret key. - type: string - name: - description: 'Name of the referent. More info: - https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, - uid?' - type: string - optional: - description: Specify whether the Secret or its - key must be defined - type: boolean - required: - - key - type: object - endpointParams: - additionalProperties: - type: string - description: Parameters to append to the token URL - type: object - scopes: - description: OAuth2 scopes used for the token request - items: - type: string - type: array - tokenUrl: - description: The URL to fetch the token from - minLength: 1 - type: string - required: - - clientId - - clientSecret - - tokenUrl - type: object - url: - description: 'RHOBS endpoints where your data is sent - to It varies by environment: - Staging: https://observatorium-mst.stage.api.openshift.com/api/metrics/v1//api/v1/receive - Production: https://observatorium-mst.api.openshift.com/api/metrics/v1//api/v1/receive' - type: string - required: - - url - type: object - type: object - type: object - namespaces: - description: Defines a list of Kubernetes Namespaces that belong to - this Addon. Namespaces listed here will be created prior to installation - of the Addon and will be removed from the cluster when the Addon - is deleted. Collisions with existing Namespaces will result in the - existing Namespaces being adopted. - items: - properties: - annotations: - additionalProperties: - type: string - description: Annotations to be added to the namespace - type: object - labels: - additionalProperties: - type: string - description: Labels to be added to the namespace - type: object - name: - description: Name of the KubernetesNamespace. - minLength: 1 - type: string - required: - - name - type: object - type: array - packageOperator: - description: defines the PackageOperator image as part of the addon - Spec - properties: - image: - type: string - required: - - image - type: object - pause: - description: Pause reconciliation of Addon when set to True - type: boolean - secretPropagation: - description: Settings for propagating secrets from the Addon Operator - install namespace into Addon namespaces. - properties: - secrets: - items: - properties: - destinationSecret: - description: Destination secret name in every Addon namespace. - properties: - name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?' - type: string - type: object - sourceSecret: - description: Source secret name in the Addon Operator install - namespace. - properties: - name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?' - type: string - type: object - required: - - destinationSecret - - sourceSecret - type: object - type: array - required: - - secrets - type: object - upgradePolicy: - description: UpgradePolicy enables status reporting via upgrade policies. - properties: - id: - description: Upgrade policy id. - type: string - required: - - id - type: object - version: - description: Version of the Addon to deploy. Used for reporting via - status and metrics. - type: string - required: - - displayName - - install - type: object - status: - default: - phase: Pending - description: AddonStatus defines the observed state of Addon - properties: - conditions: - description: Conditions is a list of status conditions ths object - is in. - items: - description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - \n \ttype FooStatus struct{ \t // Represents the observations - of a foo's current state. \t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\" \t // - +patchMergeKey=type \t // +patchStrategy=merge \t // +listType=map - \t // +listMapKey=type \t Conditions []metav1.Condition - `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" - protobuf:\"bytes,1,rep,name=conditions\"` \n \t // other fields - \t}" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - lastObservedAvailableCSV: - description: Namespaced name of the csv(available) that was last observed. - type: string - observedGeneration: - description: The most recent generation observed by the controller. - format: int64 - type: integer - observedVersion: - description: Observed version of the Addon on the cluster, only present - when .spec.version is populated. - type: string - ocmReportedStatusHash: - description: Tracks the last addon status reported to OCM. - properties: - observedGeneration: - description: The most recent generation a status update was based - on. - format: int64 - type: integer - statusHash: - description: Hash of the last reported status. - type: string - required: - - observedGeneration - - statusHash - type: object - phase: - description: 'DEPRECATED: This field is not part of any API contract - it will go away as soon as kubectl can print conditions! Human readable - status - please use .Conditions from code' - type: string - upgradePolicy: - description: Tracks last reported upgrade policy status. - properties: - id: - description: Upgrade policy id. - type: string - observedGeneration: - description: The most recent generation a status update was based - on. - format: int64 - type: integer - value: - description: Upgrade policy value. - type: string - version: - description: Upgrade Policy Version. - type: string - required: - - id - - observedGeneration - - value - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/dev/env/scripts/bootstrap.sh b/dev/env/scripts/bootstrap.sh index 92dc482689..6ebe306871 100755 --- a/dev/env/scripts/bootstrap.sh +++ b/dev/env/scripts/bootstrap.sh @@ -114,16 +114,6 @@ if ! is_openshift_cluster "$CLUSTER_TYPE"; then apply "${MANIFESTS_DIR}/monitoring" fi -# Apply addon CRD only if it doesn't exist -if ! $KUBECTL get crd addons.addons.managed.openshift.io &>/dev/null; then - log "Addon CRD not found, applying..." - apply "${MANIFESTS_DIR}/addons/crds/00-addon-crd.yaml" - wait_for_crd "addons.addons.managed.openshift.io" -else - log "Addon CRD already exists, skipping..." -fi -apply "${MANIFESTS_DIR}/addons/acs-fleetshard" - if [[ "$INSTALL_EXTERNAL_DNS" == "true" ]]; then log "Installing ExternalDNS for OpenShift" apply "${MANIFESTS_DIR}/external-dns-operator" diff --git a/dev/env/scripts/lib.sh b/dev/env/scripts/lib.sh index 3613853855..d4f0e342a2 100644 --- a/dev/env/scripts/lib.sh +++ b/dev/env/scripts/lib.sh @@ -92,9 +92,6 @@ init() { export OCM_SERVICE_CLIENT_ID=${OCM_SERVICE_CLIENT_ID:-$OCM_SERVICE_CLIENT_ID_DEFAULT} export OCM_SERVICE_CLIENT_SECRET=${OCM_SERVICE_CLIENT_SECRET:-$OCM_SERVICE_CLIENT_SECRET_DEFAULT} export OCM_SERVICE_TOKEN=${OCM_SERVICE_TOKEN:-$OCM_SERVICE_TOKEN_DEFAULT} - export OCM_ADDON_SERVICE_CLIENT_ID=${OCM_ADDON_SERVICE_CLIENT_ID:-$OCM_ADDON_SERVICE_CLIENT_ID_DEFAULT} - export OCM_ADDON_SERVICE_CLIENT_SECRET=${OCM_ADDON_SERVICE_CLIENT_SECRET:-$OCM_ADDON_SERVICE_CLIENT_SECRET_DEFAULT} - export OCM_ADDON_SERVICE_TOKEN=${OCM_ADDON_SERVICE_TOKEN:-$OCM_ADDON_SERVICE_TOKEN_DEFAULT} export ROUTE53_ACCESS_KEY=${ROUTE53_ACCESS_KEY:-$ROUTE53_ACCESS_KEY_DEFAULT} export ROUTE53_SECRET_ACCESS_KEY=${ROUTE53_SECRET_ACCESS_KEY:-$ROUTE53_SECRET_ACCESS_KEY_DEFAULT} export SPAWN_LOGGER=${SPAWN_LOGGER:-$SPAWN_LOGGER_DEFAULT} diff --git a/dev/env/values/fleetshard-sync/values.yaml b/dev/env/values/fleetshard-sync/values.yaml index faf3440fbd..94ae9310f4 100644 --- a/dev/env/values/fleetshard-sync/values.yaml +++ b/dev/env/values/fleetshard-sync/values.yaml @@ -10,7 +10,6 @@ secretEncryption: type: "local" tenantImagePullSecret: name: "rhacs-registry" -addonAutoUpgradeEnabled: false printCentralUpdateDiff: true resources: requests: diff --git a/emailsender/README.md b/emailsender/README.md index bd350e390e..0df7342491 100644 --- a/emailsender/README.md +++ b/emailsender/README.md @@ -33,11 +33,7 @@ All related AWS and emailsender limits and how to change them are document in th ## Deployment -The emailsender is deployed as part of the acs-fleetshard-sync addon. The helm chart is defined in `deploy/charts/emailsender`. - -The most important helm values are exposed for configuration through the addon. - -For more details refer to the addon [documentation](https://spaces.redhat.com/pages/viewpage.action?spaceKey=StackRox&title=ACS+Fleetshard+Addon). +The emailsender helm chart is defined in [deploy/charts/emailsender](../deploy/charts/emailsender). The chart is installed on the Data Plane clusters using ArgoCD. ## API Authentication diff --git a/fleetshard/config/config.go b/fleetshard/config/config.go index 0c098ef9dd..1a0f7fbf93 100644 --- a/fleetshard/config/config.go +++ b/fleetshard/config/config.go @@ -44,7 +44,6 @@ type Config struct { Telemetry Telemetry AuditLogging AuditLogging SecretEncryption SecretEncryption - FleetshardAddonName string `env:"FLEETSHARD_ADDON_NAME" envDefault:"acs-fleetshard"` } // ManagedDB for configuring managed DB specific parameters diff --git a/fleetshard/pkg/cluster/addon_service.go b/fleetshard/pkg/cluster/addon_service.go deleted file mode 100644 index a82a6b92bd..0000000000 --- a/fleetshard/pkg/cluster/addon_service.go +++ /dev/null @@ -1,79 +0,0 @@ -// Package cluster provides access to cluster resources not related with centrals -package cluster - -import ( - "context" - "fmt" - - addonsV1alpha1 "github.com/openshift/addon-operator/apis/addons/v1alpha1" - - "github.com/stackrox/acs-fleet-manager/pkg/shared" - corev1 "k8s.io/api/core/v1" - ctrlClient "sigs.k8s.io/controller-runtime/pkg/client" -) - -// AddonService allows to access addons installed on a cluster -type AddonService interface { - // GetAddon returns the addon with the specified ID or error in case service fails to find such an addon - GetAddon(ctx context.Context, id string) (shared.Addon, error) -} - -var ( - _ AddonService = (*addonService)(nil) -) - -type addonService struct { - k8sClient ctrlClient.Client -} - -// NewAddonService return a new instance of AddonService -func NewAddonService(k8sClient ctrlClient.Client) AddonService { - return &addonService{ - k8sClient: k8sClient, - } -} - -func (s *addonService) GetAddon(ctx context.Context, id string) (shared.Addon, error) { - addonObj := addonsV1alpha1.Addon{} - addon := shared.Addon{} - if err := s.k8sClient.Get(ctx, ctrlClient.ObjectKey{Name: id}, &addonObj); err != nil { - return addon, fmt.Errorf("get addon %s: %w", id, err) - } - - addon.ID = addonObj.Name - addon.Version = addonObj.Spec.Version - - if addonObj.Spec.Install.OLMOwnNamespace == nil { - return addon, fmt.Errorf("addon with install mode other than OLMOwnNamespace is not supported") - } - addon.SourceImage = addonObj.Spec.Install.OLMOwnNamespace.CatalogSourceImage - - if addonObj.Spec.AddonPackageOperator == nil { - return addon, fmt.Errorf("addon without AddonPackageOperator is not supported") - } - addon.PackageImage = addonObj.Spec.AddonPackageOperator.Image - - secret, err := s.getAddonParametersSecret(ctx, addonObj.Spec.Install.OLMOwnNamespace.Namespace, id) - if err != nil { - return addon, err - } - parameters := make(map[string]string, len(secret.Data)) - for k, v := range secret.Data { - parameters[k] = string(v[:]) - } - addon.Parameters = parameters - - return addon, nil -} - -func (s *addonService) getAddonParametersSecret(ctx context.Context, namespace string, addonID string) (corev1.Secret, error) { - secretName := fmt.Sprintf("addon-%s-parameters", addonID) - secret := corev1.Secret{} // pragma: allowlist secret - err := s.k8sClient.Get(ctx, ctrlClient.ObjectKey{Namespace: namespace, Name: secretName}, &secret) - - if err != nil { - return secret, fmt.Errorf("get addon parameters secret %s: %w", secretName, err) - } - - return secret, nil -} diff --git a/fleetshard/pkg/cluster/addon_service_test.go b/fleetshard/pkg/cluster/addon_service_test.go deleted file mode 100644 index 708691c6ce..0000000000 --- a/fleetshard/pkg/cluster/addon_service_test.go +++ /dev/null @@ -1,143 +0,0 @@ -package cluster - -import ( - "context" - "reflect" - "testing" - - addonsV1alpha1 "github.com/openshift/addon-operator/apis/addons/v1alpha1" - "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/testutils" - "github.com/stackrox/acs-fleet-manager/pkg/shared" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - ctrlClient "sigs.k8s.io/controller-runtime/pkg/client" -) - -const ( - addonNamespace = "rhacs" -) - -func Test_addonService_GetAddon(t *testing.T) { - type fields struct { - k8sClient ctrlClient.Client - } - type args struct { - id string - } - tests := []struct { - name string - fields fields - args args - want shared.Addon - wantErr bool - }{ - { - name: "should retrieve the addon when it exists", - args: args{ - id: "acs-fleetshard", - }, - fields: fields{ - k8sClient: testutils.NewFakeClientBuilder(t, - addon( - "acs-fleetshard", - "0.2.0", - "quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac", - "quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", - ), - addonParametersSecret("addon-acs-fleetshard-parameters", map[string][]byte{"acscsEnvironment": []byte("test")}), - ).Build(), - }, - want: shared.Addon{ - ID: "acs-fleetshard", - Version: "0.2.0", - SourceImage: "quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac", - PackageImage: "quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", - Parameters: map[string]string{ - "acscsEnvironment": "test", - }, - }, - }, - { - name: "should return error when addon does not exist", - args: args{ - id: "acs-fleetshard", - }, - fields: fields{ - k8sClient: testutils.NewFakeClientBuilder(t).Build(), // no objects - }, - wantErr: true, - }, - { - name: "should return error when no package secret", - args: args{ - id: "acs-fleetshard", - }, - fields: fields{ - k8sClient: testutils.NewFakeClientBuilder(t, - addon( - "acs-fleetshard", - "0.2.0", - "quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac", - "quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", - ), - ).Build(), - }, - wantErr: true, - want: shared.Addon{ - ID: "acs-fleetshard", - Version: "0.2.0", - SourceImage: "quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac", - PackageImage: "quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ad := &addonService{ - k8sClient: tt.fields.k8sClient, - } - got, err := ad.GetAddon(context.TODO(), tt.args.id) - if (err != nil) != tt.wantErr { - t.Errorf("GetAddon() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetAddon() got = %v, want %v", got, tt.want) - } - }) - } -} - -func addon(name string, version string, addonImage string, packageImage string) ctrlClient.Object { - return &addonsV1alpha1.Addon{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - }, - Spec: addonsV1alpha1.AddonSpec{ - Install: addonsV1alpha1.AddonInstallSpec{ - OLMOwnNamespace: &addonsV1alpha1.AddonInstallOLMOwnNamespace{ - AddonInstallOLMCommon: addonsV1alpha1.AddonInstallOLMCommon{ - CatalogSourceImage: addonImage, - Channel: "stable", - Namespace: addonNamespace, - PackageName: name, - }, - }, - }, - Version: version, - AddonPackageOperator: &addonsV1alpha1.AddonPackageOperator{ - Image: packageImage, - }, - }, - } -} - -func addonParametersSecret(name string, parameters map[string][]byte) ctrlClient.Object { - return &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: addonNamespace, - }, - Data: parameters, - } -} diff --git a/fleetshard/pkg/k8s/client.go b/fleetshard/pkg/k8s/client.go index 3d3fe05b69..2a44390e85 100644 --- a/fleetshard/pkg/k8s/client.go +++ b/fleetshard/pkg/k8s/client.go @@ -4,7 +4,6 @@ package k8s import ( argoCd "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" "github.com/golang/glog" - "github.com/openshift/addon-operator/apis/addons" openshiftOperatorV1 "github.com/openshift/api/operator/v1" openshiftRouteV1 "github.com/openshift/api/route/v1" "github.com/stackrox/rox/operator/api/v1alpha1" @@ -56,7 +55,6 @@ func buildClientOrDie(config *rest.Config) ctrlClient.Client { must(v1alpha1.AddToScheme(scheme)) must(openshiftRouteV1.Install(scheme)) must(openshiftOperatorV1.Install(scheme)) - must(addons.AddToScheme(scheme)) must(verticalpodautoscalingv1.AddToScheme(scheme)) must(argoCd.AddToScheme(scheme)) diff --git a/fleetshard/pkg/runtime/runtime.go b/fleetshard/pkg/runtime/runtime.go index a6e8db5e2a..329ce7c4f9 100644 --- a/fleetshard/pkg/runtime/runtime.go +++ b/fleetshard/pkg/runtime/runtime.go @@ -21,7 +21,6 @@ import ( "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/central/postgres" centralReconciler "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/central/reconciler" "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/cipher" - "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/cluster" "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/fleetshardmetrics" "github.com/stackrox/acs-fleet-manager/fleetshard/pkg/k8s" "github.com/stackrox/acs-fleet-manager/internal/central/pkg/api/private" @@ -57,7 +56,6 @@ type Runtime struct { statusResponseCh chan private.DataPlaneCentralStatus secretCipher cipher.Cipher encryptionKeyGenerator cipher.KeyGenerator - addonService cluster.AddonService runtimeApplicationsReconciler *runtimeApplicationsReconciler } @@ -99,8 +97,6 @@ func NewRuntime(ctx context.Context, config *config.Config, k8sClient ctrlClient return nil, fmt.Errorf("creating encryption KeyGenerator: %w", err) } - addonService := cluster.NewAddonService(k8sClient) - return &Runtime{ config: config, k8sClient: k8sClient, @@ -110,7 +106,6 @@ func NewRuntime(ctx context.Context, config *config.Config, k8sClient ctrlClient reconcilers: make(reconcilerRegistry), secretCipher: secretCipher, // pragma: allowlist secret encryptionKeyGenerator: encryptionKeyGen, - addonService: addonService, runtimeApplicationsReconciler: newRuntimeApplicationsReconciler(k8sClient, config.ArgoCdNamespace), }, nil } @@ -220,12 +215,6 @@ func (r *Runtime) Start() error { } } - if features.AddonAutoUpgrade.Enabled() { - if err := r.sendClusterStatus(ctx); err != nil { - glog.Errorf("Failed to send cluster status update due to an error: %v", err) - } - } - r.deleteStaleReconcilers(&list) if features.ClusterMigration.Enabled() { @@ -359,29 +348,3 @@ func (r *Runtime) isReconcilePaused(ctx context.Context, remoteCentral private.M return false, nil } - -func (r *Runtime) sendClusterStatus(ctx context.Context) error { - addonName := r.config.FleetshardAddonName - addon, err := r.addonService.GetAddon(ctx, addonName) - if err != nil { - return fmt.Errorf("retrieving %s addon: %w", addonName, err) - } - - _, err = r.client.PrivateAPI().UpdateAgentClusterStatus(ctx, r.clusterID, private.DataPlaneClusterUpdateStatusRequest{ - Addons: []private.DataPlaneClusterUpdateStatusRequestAddons{ - { - Id: addonName, - Version: addon.Version, - SourceImage: addon.SourceImage, - PackageImage: addon.PackageImage, - ParametersSHA256Sum: addon.Parameters.SHA256Sum(), - }, - }, - }) - - if err != nil { - return fmt.Errorf("calling fleet manager private api to update the cluster status: %w", err) - } - - return nil -} diff --git a/fleetshard/pkg/testutils/k8s.go b/fleetshard/pkg/testutils/k8s.go index 0478349ca5..bb95245edd 100644 --- a/fleetshard/pkg/testutils/k8s.go +++ b/fleetshard/pkg/testutils/k8s.go @@ -8,7 +8,6 @@ import ( argoCd "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" "github.com/hashicorp/go-multierror" - "github.com/openshift/addon-operator/apis/addons" openshiftOperatorV1 "github.com/openshift/api/operator/v1" openshiftRouteV1 "github.com/openshift/api/route/v1" "github.com/pkg/errors" @@ -109,7 +108,6 @@ func NewScheme(t *testing.T) *runtime.Scheme { require.NoError(t, clientgoscheme.AddToScheme(scheme)) require.NoError(t, openshiftRouteV1.Install(scheme)) require.NoError(t, openshiftOperatorV1.Install(scheme)) - require.NoError(t, addons.AddToScheme(scheme)) require.NoError(t, argoCd.AddToScheme(scheme)) return scheme diff --git a/go.mod b/go.mod index 6a25cfc630..94cf806ae5 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,6 @@ require ( github.com/onsi/ginkgo/v2 v2.23.4 github.com/onsi/gomega v1.37.0 github.com/openshift-online/ocm-sdk-go v0.1.456 - github.com/openshift/addon-operator/apis v0.0.0-20231110045543-dd01f2f5c184 github.com/openshift/api v0.0.0-20250320115527-3aa9dd5b9002 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.9.1 @@ -233,7 +232,6 @@ require ( github.com/pquerna/otp v1.4.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/redis/go-redis/v9 v9.7.3 // indirect - github.com/rhobs/obo-prometheus-operator/pkg/apis/monitoring v0.66.0-rhobs1 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect diff --git a/go.sum b/go.sum index d313717229..02738e6393 100644 --- a/go.sum +++ b/go.sum @@ -730,8 +730,6 @@ github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQ github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/openshift-online/ocm-sdk-go v0.1.456 h1:N9AmVv8H+FSlld88iCsafy+8Lhykz/1XUrmVhww/BYM= github.com/openshift-online/ocm-sdk-go v0.1.456/go.mod h1:CiAu2jwl3ITKOxkeV0Qnhzv4gs35AmpIzVABQLtcI2Y= -github.com/openshift/addon-operator/apis v0.0.0-20231110045543-dd01f2f5c184 h1:P93o33VcHaOTjOTm6/UojtJdr1qLc2U7vPMBno39rdc= -github.com/openshift/addon-operator/apis v0.0.0-20231110045543-dd01f2f5c184/go.mod h1:JS2tbakhIZRgBiULsIUSHGsdz7G/Vylvg1mqI1TlXzs= github.com/openshift/api v0.0.0-20250320115527-3aa9dd5b9002 h1:AP8WxjiCyGlyhRlDG83cuk789Gy96IdYNuTO/sAMwl0= github.com/openshift/api v0.0.0-20250320115527-3aa9dd5b9002/go.mod h1:yk60tHAmHhtVpJQo3TwVYq2zpuP70iJIFDCmeKMIzPw= github.com/openshift/client-go v0.0.0-20250324153519-f0faeb0f2f2e h1:OfOI0eTTUdwqaUHgm0YsinRYtOj4OGO+ioauVNPuDeQ= @@ -774,8 +772,6 @@ github.com/redhat-developer/app-services-sdk-core/app-services-sdk-go/serviceacc github.com/redis/go-redis/v9 v9.0.0-rc.4/go.mod h1:Vo3EsyWnicKnSKCA7HhgnvnyA74wOA69Cd2Meli5mmA= github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM= github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA= -github.com/rhobs/obo-prometheus-operator/pkg/apis/monitoring v0.66.0-rhobs1 h1:+2dvyv90foYNSUceYWSlE+SfkeJSFRHV9eOqfnhE0Rw= -github.com/rhobs/obo-prometheus-operator/pkg/apis/monitoring v0.66.0-rhobs1/go.mod h1:D7aYXoiteBUNwv3nMQ3NKKNlIEvFA1zS1nKJi7t8/IE= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= diff --git a/internal/central/pkg/api/dbapi/data_plane_cluster_status.go b/internal/central/pkg/api/dbapi/data_plane_cluster_status.go deleted file mode 100644 index 65cab5c4b5..0000000000 --- a/internal/central/pkg/api/dbapi/data_plane_cluster_status.go +++ /dev/null @@ -1,19 +0,0 @@ -package dbapi - -// AddonInstallation represents the actual information about addons installed on the cluster -type AddonInstallation struct { - ID string - Version string - SourceImage string - PackageImage string - ParametersSHA256Sum string -} - -// DataPlaneClusterStatus is the actual state reported from the data plane cluster -type DataPlaneClusterStatus struct { - Addons []AddonInstallation -} - -// DataPlaneClusterConfig ... -type DataPlaneClusterConfig struct { -} diff --git a/internal/central/pkg/api/private/api/openapi.yaml b/internal/central/pkg/api/private/api/openapi.yaml index 9aef804535..b01666ac22 100644 --- a/internal/central/pkg/api/private/api/openapi.yaml +++ b/internal/central/pkg/api/private/api/openapi.yaml @@ -16,49 +16,6 @@ servers: tags: - name: Agent Clusters paths: - /api/rhacs/v1/agent-clusters/{id}/status: - put: - operationId: updateAgentClusterStatus - parameters: - - description: The ID of record - in: path - name: id - required: true - schema: - type: string - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/DataPlaneClusterUpdateStatusRequest' - description: Cluster status update data - required: true - responses: - "200": - description: Cluster status is updated - "400": - content: - application/json: - examples: - "400InvalidIdExample": - $ref: '#/components/examples/400InvalidIdExample' - schema: - $ref: '#/components/schemas/Error' - description: id value is not valid - "404": - content: - application/json: - examples: - "404Example": - $ref: '#/components/examples/404Example' - schema: - $ref: '#/components/schemas/Error' - description: Auth token is not valid. - security: - - Bearer: [] - summary: Update the status of an agent cluster - tags: - - Agent Clusters /api/rhacs/v1/agent-clusters/{id}/centrals/status: put: operationId: updateCentralClusterStatus @@ -183,46 +140,6 @@ paths: summary: Get the ManagedaCentral for the specified agent cluster and centralId tags: - Agent Clusters - /api/rhacs/v1/agent-clusters/{id}: - get: - operationId: getDataPlaneClusterAgentConfig - parameters: - - description: The ID of record - in: path - name: id - required: true - schema: - type: string - responses: - "200": - content: - application/json: - schema: - $ref: '#/components/schemas/DataplaneClusterAgentConfig' - description: The Data Plane Cluster Agent configuration - "400": - content: - application/json: - examples: - "400InvalidIdExample": - $ref: '#/components/examples/400InvalidIdExample' - schema: - $ref: '#/components/schemas/Error' - description: id value is not valid - "404": - content: - application/json: - examples: - "404Example": - $ref: '#/components/examples/404Example' - schema: - $ref: '#/components/schemas/Error' - description: Auth token is not valid. - security: - - Bearer: [] - summary: Get the data plane cluster agent configuration - tags: - - Agent Clusters components: examples: ManagedCentralExample: @@ -332,26 +249,6 @@ components: - $ref: '#/components/schemas/ListReference' - $ref: '#/components/schemas/ManagedCentralList_allOf' description: A list of ManagedCentral - DataPlaneClusterUpdateStatusRequest: - description: Schema for the request to update a data plane cluster's status - example: - addons: - - packageImage: packageImage - parametersSHA256Sum: parametersSHA256Sum - id: id - sourceImage: sourceImage - version: version - - packageImage: packageImage - parametersSHA256Sum: parametersSHA256Sum - id: id - sourceImage: sourceImage - version: version - properties: - addons: - items: - $ref: '#/components/schemas/DataPlaneClusterUpdateStatusRequest_addons' - type: array - type: object DataPlaneCentralStatus: description: Schema of the status object for a Central example: @@ -384,8 +281,6 @@ components: type: object DataplaneClusterAgentConfig: description: Configuration for the data plane cluster agent - example: - spec: '{}' properties: spec: description: Data plane cluster agent spec @@ -546,24 +441,6 @@ components: items: type: object type: array - DataPlaneClusterUpdateStatusRequest_addons: - example: - packageImage: packageImage - parametersSHA256Sum: parametersSHA256Sum - id: id - sourceImage: sourceImage - version: version - properties: - id: - type: string - version: - type: string - sourceImage: - type: string - packageImage: - type: string - parametersSHA256Sum: - type: string DataPlaneCentralStatus_conditions: properties: type: diff --git a/internal/central/pkg/api/private/api_agent_clusters.go b/internal/central/pkg/api/private/api_agent_clusters.go index 7ad4bea797..36d211b0dd 100644 --- a/internal/central/pkg/api/private/api_agent_clusters.go +++ b/internal/central/pkg/api/private/api_agent_clusters.go @@ -220,191 +220,6 @@ func (a *AgentClustersApiService) GetCentrals(ctx _context.Context, id string) ( return localVarReturnValue, localVarHTTPResponse, nil } -/* -GetDataPlaneClusterAgentConfig Get the data plane cluster agent configuration - - @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - - @param id The ID of record - -@return DataplaneClusterAgentConfig -*/ -func (a *AgentClustersApiService) GetDataPlaneClusterAgentConfig(ctx _context.Context, id string) (DataplaneClusterAgentConfig, *_nethttp.Response, error) { - var ( - localVarHTTPMethod = _nethttp.MethodGet - localVarPostBody interface{} - localVarFormFileName string - localVarFileName string - localVarFileBytes []byte - localVarReturnValue DataplaneClusterAgentConfig - ) - - // create path and map variables - localVarPath := a.client.cfg.BasePath + "/api/rhacs/v1/agent-clusters/{id}" - localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", _neturl.QueryEscape(parameterToString(id, "")), -1) - - localVarHeaderParams := make(map[string]string) - localVarQueryParams := _neturl.Values{} - localVarFormParams := _neturl.Values{} - - // to determine the Content-Type header - localVarHTTPContentTypes := []string{} - - // set Content-Type header - localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) - if localVarHTTPContentType != "" { - localVarHeaderParams["Content-Type"] = localVarHTTPContentType - } - - // to determine the Accept header - localVarHTTPHeaderAccepts := []string{"application/json"} - - // set Accept header - localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) - if localVarHTTPHeaderAccept != "" { - localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept - } - r, err := a.client.prepareRequest(ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes) - if err != nil { - return localVarReturnValue, nil, err - } - - localVarHTTPResponse, err := a.client.callAPI(r) - if err != nil || localVarHTTPResponse == nil { - return localVarReturnValue, localVarHTTPResponse, err - } - - localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) - localVarHTTPResponse.Body.Close() - if err != nil { - return localVarReturnValue, localVarHTTPResponse, err - } - - if localVarHTTPResponse.StatusCode >= 300 { - newErr := GenericOpenAPIError{ - body: localVarBody, - error: localVarHTTPResponse.Status, - } - if localVarHTTPResponse.StatusCode == 400 { - var v Error - err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr - } - newErr.model = v - return localVarReturnValue, localVarHTTPResponse, newErr - } - if localVarHTTPResponse.StatusCode == 404 { - var v Error - err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr - } - newErr.model = v - } - return localVarReturnValue, localVarHTTPResponse, newErr - } - - err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) - if err != nil { - newErr := GenericOpenAPIError{ - body: localVarBody, - error: err.Error(), - } - return localVarReturnValue, localVarHTTPResponse, newErr - } - - return localVarReturnValue, localVarHTTPResponse, nil -} - -/* -UpdateAgentClusterStatus Update the status of an agent cluster - - @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - - @param id The ID of record - - @param dataPlaneClusterUpdateStatusRequest Cluster status update data -*/ -func (a *AgentClustersApiService) UpdateAgentClusterStatus(ctx _context.Context, id string, dataPlaneClusterUpdateStatusRequest DataPlaneClusterUpdateStatusRequest) (*_nethttp.Response, error) { - var ( - localVarHTTPMethod = _nethttp.MethodPut - localVarPostBody interface{} - localVarFormFileName string - localVarFileName string - localVarFileBytes []byte - ) - - // create path and map variables - localVarPath := a.client.cfg.BasePath + "/api/rhacs/v1/agent-clusters/{id}/status" - localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", _neturl.QueryEscape(parameterToString(id, "")), -1) - - localVarHeaderParams := make(map[string]string) - localVarQueryParams := _neturl.Values{} - localVarFormParams := _neturl.Values{} - - // to determine the Content-Type header - localVarHTTPContentTypes := []string{"application/json"} - - // set Content-Type header - localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) - if localVarHTTPContentType != "" { - localVarHeaderParams["Content-Type"] = localVarHTTPContentType - } - - // to determine the Accept header - localVarHTTPHeaderAccepts := []string{"application/json"} - - // set Accept header - localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) - if localVarHTTPHeaderAccept != "" { - localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept - } - // body params - localVarPostBody = &dataPlaneClusterUpdateStatusRequest - r, err := a.client.prepareRequest(ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes) - if err != nil { - return nil, err - } - - localVarHTTPResponse, err := a.client.callAPI(r) - if err != nil || localVarHTTPResponse == nil { - return localVarHTTPResponse, err - } - - localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) - localVarHTTPResponse.Body.Close() - if err != nil { - return localVarHTTPResponse, err - } - - if localVarHTTPResponse.StatusCode >= 300 { - newErr := GenericOpenAPIError{ - body: localVarBody, - error: localVarHTTPResponse.Status, - } - if localVarHTTPResponse.StatusCode == 400 { - var v Error - err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() - return localVarHTTPResponse, newErr - } - newErr.model = v - return localVarHTTPResponse, newErr - } - if localVarHTTPResponse.StatusCode == 404 { - var v Error - err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() - return localVarHTTPResponse, newErr - } - newErr.model = v - } - return localVarHTTPResponse, newErr - } - - return localVarHTTPResponse, nil -} - /* UpdateCentralClusterStatus Update the status of Centrals on an agent cluster - @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). diff --git a/internal/central/pkg/api/private/model_data_plane_cluster_update_status_request.go b/internal/central/pkg/api/private/model_data_plane_cluster_update_status_request.go deleted file mode 100644 index 9b8d757ccd..0000000000 --- a/internal/central/pkg/api/private/model_data_plane_cluster_update_status_request.go +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Red Hat Advanced Cluster Security Service Fleet Manager - * - * Red Hat Advanced Cluster Security (RHACS) Service Fleet Manager APIs that are used by internal services e.g fleetshard-sync. - * - * API version: 1.4.0 - * Generated by: OpenAPI Generator (https://openapi-generator.tech) - */ - -// Code generated by OpenAPI Generator (https://openapi-generator.tech). DO NOT EDIT. -package private - -// DataPlaneClusterUpdateStatusRequest Schema for the request to update a data plane cluster's status -type DataPlaneClusterUpdateStatusRequest struct { - Addons []DataPlaneClusterUpdateStatusRequestAddons `json:"addons,omitempty"` -} diff --git a/internal/central/pkg/api/private/model_data_plane_cluster_update_status_request_addons.go b/internal/central/pkg/api/private/model_data_plane_cluster_update_status_request_addons.go deleted file mode 100644 index d97cf40056..0000000000 --- a/internal/central/pkg/api/private/model_data_plane_cluster_update_status_request_addons.go +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Red Hat Advanced Cluster Security Service Fleet Manager - * - * Red Hat Advanced Cluster Security (RHACS) Service Fleet Manager APIs that are used by internal services e.g fleetshard-sync. - * - * API version: 1.4.0 - * Generated by: OpenAPI Generator (https://openapi-generator.tech) - */ - -// Code generated by OpenAPI Generator (https://openapi-generator.tech). DO NOT EDIT. -package private - -// DataPlaneClusterUpdateStatusRequestAddons struct for DataPlaneClusterUpdateStatusRequestAddons -type DataPlaneClusterUpdateStatusRequestAddons struct { - Id string `json:"id,omitempty"` - Version string `json:"version,omitempty"` - SourceImage string `json:"sourceImage,omitempty"` - PackageImage string `json:"packageImage,omitempty"` - ParametersSHA256Sum string `json:"parametersSHA256Sum,omitempty"` -} diff --git a/internal/central/pkg/gitops/config.go b/internal/central/pkg/gitops/config.go index d7d7f4d636..d381b00528 100644 --- a/internal/central/pkg/gitops/config.go +++ b/internal/central/pkg/gitops/config.go @@ -10,10 +10,9 @@ import ( // Config represents the gitops configuration type Config struct { - TenantResources TenantResourceConfig `json:"tenantResources"` - Centrals CentralsConfig `json:"centrals"` - DataPlaneClusters []DataPlaneClusterConfig `json:"dataPlaneClusters"` - Applications []argocd.Application `json:"applications"` + TenantResources TenantResourceConfig `json:"tenantResources"` + Centrals CentralsConfig `json:"centrals"` + Applications []argocd.Application `json:"applications"` } // AuthProviderAddition represents tenant's additional auth provider gitops configuration @@ -68,20 +67,6 @@ type CentralsConfig struct { AdditionalAuthProviders []AuthProviderAddition `json:"additionalAuthProviders"` } -// DataPlaneClusterConfig represents the configuration to be applied for a data plane cluster. -type DataPlaneClusterConfig struct { - ClusterID string `json:"clusterID"` - ClusterName string `json:"clusterName"` - Addons []AddonConfig `json:"addons"` -} - -// AddonConfig represents the addon configuration to be installed on a cluster -type AddonConfig struct { - ID string `json:"id"` - Version string `json:"version"` - Parameters map[string]string `json:"parameters"` -} - // TenantResourceConfig represents the declarative configuration for tenant resource values defaults and overrides. type TenantResourceConfig struct { Default string `json:"default"` @@ -101,7 +86,6 @@ func ValidateConfig(config Config) field.ErrorList { var errs field.ErrorList errs = append(errs, validateCentralsConfig(field.NewPath("centrals"), config.Centrals)...) errs = append(errs, validateTenantResourcesConfig(field.NewPath("tenantResources"), config.TenantResources)...) - errs = append(errs, validateDataPlaneClusterConfigs(field.NewPath("dataPlaneClusters"), config.DataPlaneClusters)...) errs = append(errs, validateApplications(field.NewPath("applications"), config.Applications)...) return errs } @@ -332,49 +316,6 @@ func validateInstanceID(path *field.Path, instanceID string) field.ErrorList { return errs } -func validateDataPlaneClusterConfigs(path *field.Path, clusters []DataPlaneClusterConfig) field.ErrorList { - var errs field.ErrorList - var seenCluster = make(map[string]struct{}) - for i, cluster := range clusters { - errs = append(errs, validateClusterID(path.Index(i).Child("clusterID"), cluster.ClusterID)...) - if _, ok := seenCluster[cluster.ClusterID]; ok { - errs = append(errs, field.Duplicate(path, cluster)) - } - seenCluster[cluster.ClusterID] = struct{}{} - errs = append(errs, validateAddons(path.Index(i).Child("addons"), cluster.Addons)...) - } - return errs -} - -func validateClusterID(path *field.Path, clusterID string) field.ErrorList { - var errs field.ErrorList - if len(clusterID) == 0 { - errs = append(errs, field.Required(path, "clusterID is required")) - } - return errs -} - -func validateAddons(path *field.Path, addons []AddonConfig) field.ErrorList { - var errs field.ErrorList - var seenAddon = make(map[string]struct{}) - for i, addon := range addons { - errs = append(errs, validateAddonID(path.Index(i).Child("id"), addon.ID)...) - if _, ok := seenAddon[addon.ID]; ok { - errs = append(errs, field.Duplicate(path, addon)) - } - seenAddon[addon.ID] = struct{}{} - } - return errs -} - -func validateAddonID(path *field.Path, addonID string) field.ErrorList { - var errs field.ErrorList - if len(addonID) == 0 { - errs = append(errs, field.Required(path, "id is required")) - } - return errs -} - func validateApplications(path *field.Path, applications []argocd.Application) field.ErrorList { var errs field.ErrorList diff --git a/internal/central/pkg/gitops/config_test.go b/internal/central/pkg/gitops/config_test.go index 5254c9fa5b..bd7276edc0 100644 --- a/internal/central/pkg/gitops/config_test.go +++ b/internal/central/pkg/gitops/config_test.go @@ -15,7 +15,6 @@ func TestValidateGitOpsConfig(t *testing.T) { yaml string assert func(t *testing.T, c *Config, err field.ErrorList) } - tests := []tc{ { name: "valid", @@ -62,43 +61,6 @@ centrals: - key: "a" value: "b" role: "Admin" -`, - }, - { - name: "valid cluster config", - assert: func(t *testing.T, c *Config, err field.ErrorList) { - require.Empty(t, err) - }, - yaml: ` -dataPlaneClusters: - - clusterID: 1234567890abcdef1234567890abcdef - addons: - - id: acs-fleetshard -`, - }, - { - name: "invalid cluster config when no clusterID", - assert: func(t *testing.T, c *Config, err field.ErrorList) { - require.Len(t, err, 1) - assert.Equal(t, field.Required(field.NewPath("dataPlaneClusters").Index(0).Child("clusterID"), "clusterID is required"), err[0]) - }, - yaml: ` -dataPlaneClusters: - - addons: - - id: acs-fleetshard -`, - }, - { - name: "invalid cluster config when no addon ID", - assert: func(t *testing.T, c *Config, err field.ErrorList) { - require.Len(t, err, 1) - assert.Equal(t, field.Required(field.NewPath("dataPlaneClusters").Index(0).Child("addons").Index(0).Child("id"), "id is required"), err[0]) - }, - yaml: ` -dataPlaneClusters: - - clusterID: 1234567890abcdef1234567890abcdef - addons: - - version: 0.2.0 `, }, } diff --git a/internal/central/pkg/gitops/provider_test.go b/internal/central/pkg/gitops/provider_test.go index d6f8d1f2c6..f52f916545 100644 --- a/internal/central/pkg/gitops/provider_test.go +++ b/internal/central/pkg/gitops/provider_test.go @@ -169,100 +169,3 @@ applications: [{name: "foo"}] assert.Equal(t, 2, validationFnCalls) } - -func TestProviderGet_DataPlaneClusters(t *testing.T) { - successfulValidation := func(config Config) error { - return nil - } - type tc struct { - name string - file string - expectedConfigs []DataPlaneClusterConfig - } - - tcs := []tc{ - { - name: "should return nil when no data plane clusters defined", - file: "", - expectedConfigs: nil, - }, - { - name: "should return empty slice when the list of clusters is empty", - file: "dataPlaneClusters: []", - expectedConfigs: []DataPlaneClusterConfig{}, - }, - { - name: "should return config when no addons defined in the cluster", - file: ` -dataPlaneClusters: - - clusterID: 1234567890abcdef1234567890abcdef - clusterName: acs-dev-dp-01 -`, - expectedConfigs: []DataPlaneClusterConfig{ - { - ClusterID: "1234567890abcdef1234567890abcdef", // pragma: allowlist secret - ClusterName: "acs-dev-dp-01", - }, - }, - }, - { - name: "should return config when cluster with the empty addon slice is defined", - file: ` -dataPlaneClusters: - - clusterID: 1234567890abcdef1234567890abcdef - addons: [] -`, - expectedConfigs: []DataPlaneClusterConfig{ - { - ClusterID: "1234567890abcdef1234567890abcdef", // pragma: allowlist secret - Addons: []AddonConfig{}, - }, - }, - }, - { - name: "should return config when cluster with an addon is defined", - file: ` -dataPlaneClusters: - - clusterID: 1234567890abcdef1234567890abcdef - addons: - - id: acs-fleetshard - version: 0.2.0 - parameters: - acscsEnvironment: test -`, - expectedConfigs: []DataPlaneClusterConfig{ - { - ClusterID: "1234567890abcdef1234567890abcdef", // pragma: allowlist secret - Addons: []AddonConfig{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - Parameters: map[string]string{ - "acscsEnvironment": "test", - }, - }, - }, - }, - }, - }, - } - for _, tc := range tcs { - t.Run(tc.name, func(t *testing.T) { - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "config.yaml") - err := os.WriteFile(tmpFile, []byte(tc.file), 0644) - if err != nil { - t.Fatal(err) - } - p := &provider{ - reader: NewFileReader(tmpFile), - lastWorkingConfig: atomic.Pointer[Config]{}, - validationFn: successfulValidation, - } - config, err := p.Get() - require.NoError(t, err) - assert.Equal(t, tc.expectedConfigs, config.DataPlaneClusters) - }) - } - -} diff --git a/internal/central/pkg/handlers/data_plane_cluster.go b/internal/central/pkg/handlers/data_plane_cluster.go deleted file mode 100644 index e98dc72e74..0000000000 --- a/internal/central/pkg/handlers/data_plane_cluster.go +++ /dev/null @@ -1,66 +0,0 @@ -package handlers - -import ( - "net/http" - - "github.com/stackrox/acs-fleet-manager/internal/central/pkg/api/private" - "github.com/stackrox/acs-fleet-manager/internal/central/pkg/presenters" - "github.com/stackrox/acs-fleet-manager/internal/central/pkg/services" - "github.com/stackrox/acs-fleet-manager/pkg/handlers" - - "github.com/gorilla/mux" - "github.com/stackrox/acs-fleet-manager/pkg/errors" -) - -type dataPlaneClusterHandler struct { - service services.DataPlaneClusterService -} - -// NewDataPlaneClusterHandler ... -func NewDataPlaneClusterHandler(service services.DataPlaneClusterService) *dataPlaneClusterHandler { - return &dataPlaneClusterHandler{ - service: service, - } -} - -// UpdateDataPlaneClusterStatus ... -func (h *dataPlaneClusterHandler) UpdateDataPlaneClusterStatus(w http.ResponseWriter, r *http.Request) { - dataPlaneClusterID := mux.Vars(r)["id"] - - var dataPlaneClusterUpdateRequest private.DataPlaneClusterUpdateStatusRequest - - cfg := &handlers.HandlerConfig{ - MarshalInto: &dataPlaneClusterUpdateRequest, - Validate: []handlers.Validate{ - handlers.ValidateLength(&dataPlaneClusterID, "id", &handlers.MinRequiredFieldLength, nil), - }, - Action: func() (interface{}, *errors.ServiceError) { - dataPlaneClusterStatus := presenters.ConvertDataPlaneClusterStatus(dataPlaneClusterUpdateRequest) - svcErr := h.service.UpdateDataPlaneClusterStatus(dataPlaneClusterID, dataPlaneClusterStatus) - return nil, svcErr - }, - } - - handlers.Handle(w, r, cfg, http.StatusOK) -} - -// GetDataPlaneClusterConfig ... -func (h *dataPlaneClusterHandler) GetDataPlaneClusterConfig(w http.ResponseWriter, r *http.Request) { - dataPlaneClusterID := mux.Vars(r)["id"] - - cfg := &handlers.HandlerConfig{ - Validate: []handlers.Validate{ - handlers.ValidateLength(&dataPlaneClusterID, "id", &handlers.MinRequiredFieldLength, nil), - }, - Action: func() (interface{}, *errors.ServiceError) { - ctx := r.Context() - dataClusterConfig, err := h.service.GetDataPlaneClusterConfig(ctx, dataPlaneClusterID) - if err != nil { - return nil, err - } - return presenters.PresentDataPlaneClusterConfig(dataClusterConfig), nil - }, - } - - handlers.HandleGet(w, r, cfg) -} diff --git a/internal/central/pkg/migrations/20260126000000_drop_cluster_addons.go b/internal/central/pkg/migrations/20260126000000_drop_cluster_addons.go new file mode 100644 index 0000000000..7a20be10bc --- /dev/null +++ b/internal/central/pkg/migrations/20260126000000_drop_cluster_addons.go @@ -0,0 +1,31 @@ +package migrations + +// Migrations should NEVER use types from other packages. Types can change +// and then migrations run on a _new_ database will fail or behave unexpectedly. +// Instead of importing types, always re-create the type in the migration, as +// is done here, even though the same type is defined in pkg/api + +import ( + "github.com/go-gormigrate/gormigrate/v2" + "github.com/stackrox/acs-fleet-manager/pkg/db" + "gorm.io/gorm" +) + +func dropClusterAddons() *gormigrate.Migration { + type Cluster struct { + db.Model + Addons string `json:"addons"` // To be dropped + } + + migrationID := "20260126000000" + + return &gormigrate.Migration{ + ID: migrationID, + Migrate: func(tx *gorm.DB) error { + return dropIfColumnExists(tx, &Cluster{}, "addons") + }, + Rollback: func(tx *gorm.DB) error { + return addColumnIfNotExists(tx, &Cluster{}, "addons") + }, + } +} diff --git a/internal/central/pkg/migrations/migrations.go b/internal/central/pkg/migrations/migrations.go index 614e4fac1c..aaa4b9656c 100644 --- a/internal/central/pkg/migrations/migrations.go +++ b/internal/central/pkg/migrations/migrations.go @@ -57,6 +57,7 @@ func getMigrations() []*gormigrate.Migration { addSecretDataSha256SumToCentralRequest(), addEnteredProvisioningAtToCentralRequest(), renameLeaderLeaseTypes(), + dropClusterAddons(), } } diff --git a/internal/central/pkg/presenters/data_plane_cluster_status.go b/internal/central/pkg/presenters/data_plane_cluster_status.go deleted file mode 100644 index ce2e1d4f12..0000000000 --- a/internal/central/pkg/presenters/data_plane_cluster_status.go +++ /dev/null @@ -1,29 +0,0 @@ -package presenters - -import ( - "github.com/stackrox/acs-fleet-manager/internal/central/pkg/api/dbapi" - "github.com/stackrox/acs-fleet-manager/internal/central/pkg/api/private" -) - -// ConvertDataPlaneClusterStatus ... -func ConvertDataPlaneClusterStatus(status private.DataPlaneClusterUpdateStatusRequest) dbapi.DataPlaneClusterStatus { - var addonInstallations []dbapi.AddonInstallation - for _, addon := range status.Addons { - addonInstallations = append(addonInstallations, dbapi.AddonInstallation{ - ID: addon.Id, - Version: addon.Version, - SourceImage: addon.SourceImage, - PackageImage: addon.PackageImage, - ParametersSHA256Sum: addon.ParametersSHA256Sum, - }) - } - - return dbapi.DataPlaneClusterStatus{ - Addons: addonInstallations, - } -} - -// PresentDataPlaneClusterConfig ... -func PresentDataPlaneClusterConfig(_ *dbapi.DataPlaneClusterConfig) private.DataplaneClusterAgentConfig { - return private.DataplaneClusterAgentConfig{} -} diff --git a/internal/central/pkg/routes/route_loader.go b/internal/central/pkg/routes/route_loader.go index 4dab1bfcff..f110c36e06 100644 --- a/internal/central/pkg/routes/route_loader.go +++ b/internal/central/pkg/routes/route_loader.go @@ -44,7 +44,6 @@ type options struct { Central services.CentralService ClusterService services.ClusterService CloudProviders services.CloudProvidersService - DataPlaneCluster services.DataPlaneClusterService DataPlaneCentralService services.DataPlaneCentralService AccountService account.AccountService AuthService authorization.Authorization @@ -170,15 +169,8 @@ func (s *options) buildAPIBaseRouter(mainRouter *mux.Router, basePath string) er apiV1Router.HandleFunc("", v1Metadata.ServeHTTP).Methods(http.MethodGet) // /agent-clusters/{id} - dataPlaneClusterHandler := handlers.NewDataPlaneClusterHandler(s.DataPlaneCluster) dataPlaneCentralHandler := handlers.NewDataPlaneCentralHandler(s.DataPlaneCentralService, s.Central, s.ClusterService, s.ManagedCentralPresenter, s.GitopsProvider) apiV1DataPlaneRequestsRouter := apiV1Router.PathPrefix(routes.PrivateAPIPrefix).Subrouter() - apiV1DataPlaneRequestsRouter.HandleFunc("/{id}", dataPlaneClusterHandler.GetDataPlaneClusterConfig). - Name(logger.NewLogEvent("get-dataplane-cluster-config", "get dataplane cluster config by id").ToString()). - Methods(http.MethodGet) - apiV1DataPlaneRequestsRouter.HandleFunc("/{id}/status", dataPlaneClusterHandler.UpdateDataPlaneClusterStatus). - Name(logger.NewLogEvent("update-dataplane-cluster-status", "update dataplane cluster status by id").ToString()). - Methods(http.MethodPut) apiV1DataPlaneRequestsRouter.HandleFunc("/{id}/centrals/status", dataPlaneCentralHandler.UpdateCentralStatuses). Name(logger.NewLogEvent("update-dataplane-centrals-status", "update dataplane centrals status by id").ToString()). Methods(http.MethodPut) diff --git a/internal/central/pkg/services/addon.go b/internal/central/pkg/services/addon.go deleted file mode 100644 index 03c2f5c5eb..0000000000 --- a/internal/central/pkg/services/addon.go +++ /dev/null @@ -1,351 +0,0 @@ -package services - -import ( - "encoding/json" - "errors" - "fmt" - "time" - - "github.com/golang/glog" - clustersmgmtv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" - "github.com/stackrox/acs-fleet-manager/internal/central/pkg/api/dbapi" - "github.com/stackrox/acs-fleet-manager/internal/central/pkg/gitops" - "github.com/stackrox/acs-fleet-manager/pkg/api" - "github.com/stackrox/acs-fleet-manager/pkg/client/ocm" - ocmImpl "github.com/stackrox/acs-fleet-manager/pkg/client/ocm/impl" - "github.com/stackrox/acs-fleet-manager/pkg/features" - "github.com/stackrox/acs-fleet-manager/pkg/metrics" - "github.com/stackrox/acs-fleet-manager/pkg/shared" - "golang.org/x/exp/maps" -) - -const fleetshardImageTagParameter = "fleetshardSyncImageTag" - -// This backoff was introduced to prevent reaching OCM service log limits -// by sending too many addon upgrade requests. The limit is 1000. A backoff -// of 20 minutes would result in 504 requests per week, which leaves some space -// for other openshift components to call the API as well. -const addonUpgradeBackoff = 20 * time.Minute - -type updateAddonStatusMetricFunc func(addonID, clusterName string, status metrics.AddonStatus) - -// AddonProvisioner keeps addon installations on the data plane clusters up-to-date -type AddonProvisioner struct { - ocmClient ocm.Client - customizations []addonCustomization - updateAddonStatusMetricFunc updateAddonStatusMetricFunc - // lastStatusPerInstall holds the status for a specific addons installation on a cluster - // the id is clusterid:addonid, it maps to the last status of that install operation - lastStatusPerInstall map[string]metrics.AddonStatus - lastUpgradeRequestTime time.Time -} - -// NewAddonProvisioner creates a new instance of AddonProvisioner -func NewAddonProvisioner(addonConfig *ocmImpl.AddonConfig, baseConfig *ocmImpl.OCMConfig) (*AddonProvisioner, error) { - addonOCMConfig := *baseConfig - - addonOCMConfig.BaseURL = addonConfig.URL - addonOCMConfig.ClientID = addonConfig.ClientID - addonOCMConfig.ClientSecret = addonConfig.ClientSecret // pragma: allowlist secret - addonOCMConfig.SelfToken = addonConfig.SelfToken - - conn, _, err := ocmImpl.NewOCMConnection(&addonOCMConfig, addonOCMConfig.BaseURL) - if err != nil { - return nil, fmt.Errorf("addon service ocm connection: %w", err) - } - return &AddonProvisioner{ - ocmClient: ocmImpl.NewClient(conn), - customizations: initCustomizations(*addonConfig), - updateAddonStatusMetricFunc: metrics.UpdateClusterAddonStatusMetric, - lastStatusPerInstall: map[string]metrics.AddonStatus{}, - }, nil -} - -func initCustomizations(config ocmImpl.AddonConfig) []addonCustomization { - var customizations []addonCustomization - - if config.InheritFleetshardSyncImageTag { - if config.FleetshardSyncImageTag == "" { - glog.Error("fleetshard image tag should not be empty when inherit customization is enabled") - } else { - customizations = append(customizations, inheritFleetshardImageTag(config.FleetshardSyncImageTag)) - } - } - return customizations -} - -type addonCustomization func(gitops.AddonConfig) gitops.AddonConfig - -// Provision installs, upgrades or uninstalls the addons based on a given config -func (p *AddonProvisioner) Provision(cluster api.Cluster, dataplaneClusterConfig gitops.DataPlaneClusterConfig) error { - var errs []error - - installedAddons, err := p.getInstalledAddons(cluster) - if err != nil { - errs = append(errs, err) - } - - for _, expectedConfig := range dataplaneClusterConfig.Addons { - for _, customization := range p.customizations { - expectedConfig = customization(expectedConfig) - } - installedOnCluster, existOnCluster := installedAddons[expectedConfig.ID] - if existOnCluster { - delete(installedAddons, expectedConfig.ID) // retained installations are absent in GitOps - we need to uninstall them - } - errs = append(errs, p.provisionAddon(dataplaneClusterConfig, expectedConfig, installedOnCluster, existOnCluster)) - } - - for _, installedAddon := range installedAddons { - // addon is installed on the cluster but not present in gitops config - uninstall it - errs = append(errs, p.uninstallAddon(cluster.ClusterID, dataplaneClusterConfig.ClusterName, installedAddon.ID)) - p.updateAddonStatus(installedAddon.ID, dataplaneClusterConfig.ClusterName, cluster.ClusterID, metrics.AddonHealthy) - } - - return errors.Join(errs...) -} - -func (p *AddonProvisioner) provisionAddon(dataplaneClusterConfig gitops.DataPlaneClusterConfig, expectedConfig gitops.AddonConfig, installedOnCluster dbapi.AddonInstallation, existOnCluster bool) (provisionError error) { - var errs []error - clusterID := dataplaneClusterConfig.ClusterID - status := metrics.AddonHealthy - - defer func() { - provisionError = errors.Join(errs...) - if provisionError != nil { - status = metrics.AddonUnhealthy - } - p.updateAddonStatus(expectedConfig.ID, dataplaneClusterConfig.ClusterName, clusterID, status) - }() - - if err := p.augmentGitopsWithOCMDefaultValues(&expectedConfig); err != nil { - errs = append(errs, fmt.Errorf("augment addon %s with default values from OCM: %w", expectedConfig.ID, err)) - return - } - installedInOCM, addonErr := p.ocmClient.GetAddonInstallation(clusterID, expectedConfig.ID) - - if addonErr != nil { - if addonErr.Is404() { - // addon does not exist, install it - errs = append(errs, p.installAddon(clusterID, dataplaneClusterConfig.ClusterName, expectedConfig)) - status = metrics.AddonUpgrade - } else { - errs = append(errs, fmt.Errorf("failed to get addon %s: %w", expectedConfig.ID, addonErr)) - } - return - } - if updateInProgress(installedInOCM) { - glog.V(10).Infof("Addon %s is not in a final state: %s, skip until the next worker iteration", installedInOCM.ID(), installedInOCM.State()) - status = metrics.AddonUpgrade - return - } - if gitOpsConfigDifferent(expectedConfig, installedInOCM) { - errs = append(errs, p.updateAddon(clusterID, dataplaneClusterConfig.ClusterName, expectedConfig)) - status = metrics.AddonUpgrade - return - } - if !existOnCluster { - glog.V(10).Infof("Addon %s is not installed on the data plane", installedInOCM.ID()) - status = metrics.AddonUnhealthy - return - } - versionInstalledInOCM, err := p.ocmClient.GetAddonVersion(installedInOCM.ID(), installedInOCM.AddonVersion().ID()) - if err != nil { - errs = append(errs, fmt.Errorf("get addon version object for addon %s with version %s: %w", - installedInOCM.ID(), installedInOCM.AddonVersion().ID(), err)) - return - } - if clusterInstallationDifferent(installedOnCluster, versionInstalledInOCM) { - errs = append(errs, p.updateAddon(clusterID, dataplaneClusterConfig.ClusterName, expectedConfig)) - status = metrics.AddonUpgrade - } else { - glog.V(10).Infof("Addon %s is already up-to-date", installedOnCluster.ID) - errs = append(errs, validateUpToDateAddon(installedInOCM, installedOnCluster)) - } - return -} - -func (p *AddonProvisioner) augmentGitopsWithOCMDefaultValues(expectedConfig *gitops.AddonConfig) error { - if expectedConfig.Version == "" { - addon, err := p.ocmClient.GetAddon(expectedConfig.ID) - if err != nil { - return fmt.Errorf("get addon %s with the latest version: %w", expectedConfig.ID, err) - } - expectedConfig.Version = addon.Version().ID() - addDefaultParameters(expectedConfig, addon.Parameters()) - } else { - addonInstallation, err := p.ocmClient.GetAddonVersion(expectedConfig.ID, expectedConfig.Version) - if err != nil { - return fmt.Errorf("get addon %s with the latest version: %w", expectedConfig.ID, err) - } - addDefaultParameters(expectedConfig, addonInstallation.Parameters()) - } - return nil -} - -func addDefaultParameters(config *gitops.AddonConfig, parameters *clustersmgmtv1.AddOnParameterList) { - if parameters == nil { - return - } - if config.Parameters == nil { - config.Parameters = make(map[string]string) - } - parameters.Each(func(parameter *clustersmgmtv1.AddOnParameter) bool { - if _, exists := config.Parameters[parameter.ID()]; !exists { - config.Parameters[parameter.ID()] = parameter.DefaultValue() - } - return true - }) -} - -func validateUpToDateAddon(ocmInstallation *clustersmgmtv1.AddOnInstallation, dataPlaneInstallation dbapi.AddonInstallation) error { - var errs []error - if ocmInstallation.State() == clustersmgmtv1.AddOnInstallationStateFailed { - // addon is already up-to-date with gitops config and still failed - errs = append(errs, fmt.Errorf("addon %s is in a failed state", ocmInstallation.ID())) - } - if ocmInstallation.AddonVersion().ID() != dataPlaneInstallation.Version { - errs = append(errs, fmt.Errorf("addon %s version mismatch: ocm - %s, data plane - %s", - ocmInstallation.ID(), ocmInstallation.AddonVersion().ID(), dataPlaneInstallation.Version)) - } - if ocmSHA256Sum := convertParametersFromOCMAPI(ocmInstallation.Parameters()).SHA256Sum(); ocmSHA256Sum != dataPlaneInstallation.ParametersSHA256Sum { - errs = append(errs, fmt.Errorf("addon %s parameters mismatch: ocm sha256sum - %s, data plane sha256sum - %s", - ocmInstallation.ID(), ocmSHA256Sum, dataPlaneInstallation.ParametersSHA256Sum)) - } - return errors.Join(errs...) -} - -func (p *AddonProvisioner) getInstalledAddons(cluster api.Cluster) (map[string]dbapi.AddonInstallation, error) { - if !features.AddonAutoUpgrade.Enabled() { - glog.V(10).Info("Addon auto upgrade feature is disabled, the existing addon installations will NOT be updated") - return map[string]dbapi.AddonInstallation{}, nil - } - if len(cluster.Addons) == 0 { - return map[string]dbapi.AddonInstallation{}, nil - } - var installedAddons []dbapi.AddonInstallation - if err := json.Unmarshal(cluster.Addons, &installedAddons); err != nil { - return map[string]dbapi.AddonInstallation{}, fmt.Errorf("unmarshal installed addons: %w", err) - } - result := make(map[string]dbapi.AddonInstallation) - for _, addon := range installedAddons { - result[addon.ID] = addon - } - return result, nil -} - -func (p *AddonProvisioner) installAddon(clusterID string, clusterName string, config gitops.AddonConfig) error { - addonInstallation, err := p.newInstallation(config) - if err != nil { - return err - } - if err = p.ocmClient.CreateAddonInstallation(clusterID, addonInstallation); err != nil { - return fmt.Errorf("create addon %s in ocm: %w", config.ID, err) - } - glog.V(5).Infof("Addon %s has been installed on the cluster %s (%s)", config.ID, clusterID, clusterName) - return nil -} - -func (p *AddonProvisioner) newInstallation(config gitops.AddonConfig) (*clustersmgmtv1.AddOnInstallation, error) { - installation, err := clustersmgmtv1.NewAddOnInstallation(). - ID(config.ID). - Addon(clustersmgmtv1.NewAddOn().ID(config.ID)). - Parameters(convertParametersToOCMAPI(config.Parameters)). - AddonVersion(clustersmgmtv1.NewAddOnVersion().ID(config.Version)). - Build() - - if err != nil { - return nil, fmt.Errorf("build new addon installation %s: %w", config.ID, err) - } - - return installation, nil -} - -func (p *AddonProvisioner) updateAddon(clusterID string, clusterName string, config gitops.AddonConfig) error { - if p.backoffUpgradeRequest(config.ID, clusterID) { - glog.V(5).Infof("update addon request backoff for cluster: %s (%s)", clusterID, clusterName) - return nil - } - - update, err := p.newInstallation(config) - if err != nil { - return err - } - p.lastUpgradeRequestTime = time.Now() - if err := p.ocmClient.UpdateAddonInstallation(clusterID, update); err != nil { - return fmt.Errorf("update addon %s: %w", update.ID(), err) - } - glog.V(5).Infof("Addon %s has been updated on the cluster %s (%s)", config.ID, clusterID, clusterName) - return nil -} - -func (p *AddonProvisioner) backoffUpgradeRequest(addonID string, clusterID string) bool { - id := installID(addonID, clusterID) - return p.lastStatusPerInstall[id] != metrics.AddonHealthy && time.Since(p.lastUpgradeRequestTime) < addonUpgradeBackoff -} - -func (p *AddonProvisioner) uninstallAddon(clusterID string, clusterName string, addonID string) error { - if err := p.ocmClient.DeleteAddonInstallation(clusterID, addonID); err != nil { - return fmt.Errorf("uninstall addon %s: %w", addonID, err) - } - glog.V(5).Infof("Addon %s has been uninstalled from the cluster %s (%s)", addonID, clusterID, clusterName) - return nil -} - -func (p *AddonProvisioner) updateAddonStatus(addonID string, clusterName string, clusterID string, status metrics.AddonStatus) { - if p.updateAddonStatusMetricFunc != nil { - p.updateAddonStatusMetricFunc(addonID, clusterName, status) - } - - if p.lastStatusPerInstall == nil { - p.lastStatusPerInstall = map[string]metrics.AddonStatus{} - } - - p.lastStatusPerInstall[installID(addonID, clusterID)] = status -} - -func installID(addonID string, clusterID string) string { - return fmt.Sprintf("%s:%s", clusterID, addonID) -} - -func isFinalState(state clustersmgmtv1.AddOnInstallationState) bool { - return state == clustersmgmtv1.AddOnInstallationStateFailed || state == clustersmgmtv1.AddOnInstallationStateReady -} - -func updateInProgress(installedInOCM *clustersmgmtv1.AddOnInstallation) bool { - return !isFinalState(installedInOCM.State()) -} - -func gitOpsConfigDifferent(expectedConfig gitops.AddonConfig, installedInOCM *clustersmgmtv1.AddOnInstallation) bool { - return installedInOCM.AddonVersion().ID() != expectedConfig.Version || !maps.Equal(convertParametersFromOCMAPI(installedInOCM.Parameters()), expectedConfig.Parameters) -} - -func clusterInstallationDifferent(current dbapi.AddonInstallation, addonVersion *clustersmgmtv1.AddOnVersion) bool { - return current.SourceImage != addonVersion.SourceImage() || current.PackageImage != addonVersion.PackageImage() -} - -func convertParametersToOCMAPI(parameters map[string]string) *clustersmgmtv1.AddOnInstallationParameterListBuilder { - var values []*clustersmgmtv1.AddOnInstallationParameterBuilder - for key, value := range parameters { - values = append(values, clustersmgmtv1.NewAddOnInstallationParameter().ID(key).Value(value)) - } - return clustersmgmtv1.NewAddOnInstallationParameterList().Items(values...) -} - -func convertParametersFromOCMAPI(parameters *clustersmgmtv1.AddOnInstallationParameterList) shared.AddonParameters { - result := make(map[string]string) - parameters.Each(func(item *clustersmgmtv1.AddOnInstallationParameter) bool { - result[item.ID()] = item.Value() - return true - }) - return result -} - -func inheritFleetshardImageTag(imageTag string) addonCustomization { - return func(addon gitops.AddonConfig) gitops.AddonConfig { - if param := addon.Parameters[fleetshardImageTagParameter]; param == "inherit" { - addon.Parameters[fleetshardImageTagParameter] = imageTag - } - return addon - } -} diff --git a/internal/central/pkg/services/addon_test.go b/internal/central/pkg/services/addon_test.go deleted file mode 100644 index e361fc9503..0000000000 --- a/internal/central/pkg/services/addon_test.go +++ /dev/null @@ -1,1283 +0,0 @@ -package services - -import ( - "encoding/json" - "testing" - "time" - - . "github.com/onsi/gomega" - clustersmgmtv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" - "github.com/stackrox/acs-fleet-manager/internal/central/pkg/api/dbapi" - "github.com/stackrox/acs-fleet-manager/internal/central/pkg/gitops" - "github.com/stackrox/acs-fleet-manager/pkg/api" - ocmImpl "github.com/stackrox/acs-fleet-manager/pkg/client/ocm/impl" - ocm "github.com/stackrox/acs-fleet-manager/pkg/client/ocm/mocks" - "github.com/stackrox/acs-fleet-manager/pkg/errors" - "github.com/stackrox/acs-fleet-manager/pkg/metrics" -) - -func TestAddonProvisioner_Provision(t *testing.T) { - RegisterTestingT(t) - type statusUpdate struct { - clusterName string - addonID string - status metrics.AddonStatus - } - type fields struct { - ocmClient *ocm.ClientMock - } - type args struct { - cluster api.Cluster - clusterConfig gitops.DataPlaneClusterConfig - } - tests := []struct { - name string - setup func() - fields fields - args args - wantErr bool - wantStatuses []statusUpdate - want func(mock *ocm.ClientMock) - }{ - { - name: "should return no error when no addons have to be installed", - wantErr: false, - }, - { - name: "should install addon when not installed in ocm", - fields: fields{ - ocmClient: &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - return nil, errors.NotFound("") - }, - CreateAddonInstallationFunc: func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { - return nil - }, - GetAddonFunc: func(addonID string) (*clustersmgmtv1.AddOn, error) { - return clustersmgmtv1.NewAddOn(). - ID(addonID). - Version(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - Build() - }, - }, - }, - args: args{ - clusterConfig: gitops.DataPlaneClusterConfig{ - ClusterID: "123456789abcdef", - ClusterName: "acs-dev-dp-01", - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard", - }, - }, - }, - }, - want: func(mock *ocm.ClientMock) { - Expect(mock.GetAddonInstallationCalls()).To(HaveLen(1)) - }, - wantStatuses: []statusUpdate{ - {clusterName: "acs-dev-dp-01", addonID: "acs-fleetshard", status: metrics.AddonUpgrade}, - }, - }, - { - name: "should return error when ocmClient.GetAddonInstallation returns error", - fields: fields{ - ocmClient: &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - return nil, errors.GeneralError("test") - }, - GetAddonFunc: func(addonID string) (*clustersmgmtv1.AddOn, error) { - return clustersmgmtv1.NewAddOn(). - ID(addonID). - Version(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - Build() - }, - }, - }, - args: args{ - clusterConfig: gitops.DataPlaneClusterConfig{ - ClusterID: "123456789abcdef", - ClusterName: "acs-dev-dp-01", - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard", - }, - }, - }, - }, - wantErr: true, - wantStatuses: []statusUpdate{ - {clusterName: "acs-dev-dp-01", addonID: "acs-fleetshard", status: metrics.AddonUnhealthy}, - }, - }, - { - name: "should return error when ocmClient.CreateAddonInstallation returns error", - fields: fields{ - ocmClient: &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - return nil, errors.NotFound("") - }, - CreateAddonInstallationFunc: func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { - return errors.GeneralError("test") - }, - GetAddonFunc: func(addonID string) (*clustersmgmtv1.AddOn, error) { - return clustersmgmtv1.NewAddOn(). - ID(addonID). - Version(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - Build() - }, - }, - }, - args: args{ - clusterConfig: gitops.DataPlaneClusterConfig{ - ClusterID: "123456789abcdef", - ClusterName: "acs-dev-dp-01", - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard", - }, - }, - }, - }, - wantErr: true, - wantStatuses: []statusUpdate{ - {clusterName: "acs-dev-dp-01", addonID: "acs-fleetshard", status: metrics.AddonUnhealthy}, - }, - }, - { - name: "should install one addon if failed to request another one from ocm", - fields: fields{ - ocmClient: &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - if addonID == "beta" { - return nil, errors.NotFound("") - } - return nil, errors.GeneralError("test") - }, - CreateAddonInstallationFunc: func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { - return nil - }, - GetAddonFunc: func(addonID string) (*clustersmgmtv1.AddOn, error) { - return clustersmgmtv1.NewAddOn(). - ID(addonID). - Version(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - Build() - }, - }, - }, - args: args{ - clusterConfig: gitops.DataPlaneClusterConfig{ - ClusterID: "123456789abcdef", - ClusterName: "acs-dev-dp-01", - Addons: []gitops.AddonConfig{ - { - ID: "alpha", - }, - { - ID: "beta", - }, - }, - }, - }, - wantErr: true, - want: func(mock *ocm.ClientMock) { - Expect(mock.CreateAddonInstallationCalls()).To(HaveLen(1)) - }, - wantStatuses: []statusUpdate{ - {clusterName: "acs-dev-dp-01", addonID: "alpha", status: metrics.AddonUnhealthy}, - {clusterName: "acs-dev-dp-01", addonID: "beta", status: metrics.AddonUpgrade}, - }, - }, - { - name: "should install one addon if can't create another one in ocm", - fields: fields{ - ocmClient: &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - return nil, errors.NotFound("") - }, - CreateAddonInstallationFunc: func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { - if addon.Addon().ID() == "alpha" { - return errors.GeneralError("test") - } - return nil - }, - GetAddonFunc: func(addonID string) (*clustersmgmtv1.AddOn, error) { - return clustersmgmtv1.NewAddOn(). - ID(addonID). - Version(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - Build() - }, - }, - }, - args: args{ - clusterConfig: gitops.DataPlaneClusterConfig{ - ClusterID: "123456789abcdef", - ClusterName: "acs-dev-dp-01", - Addons: []gitops.AddonConfig{ - { - ID: "alpha", - }, - { - ID: "beta", - }, - }, - }, - }, - wantErr: true, - want: func(mock *ocm.ClientMock) { - Expect(mock.CreateAddonInstallationCalls()).To(HaveLen(2)) - }, - wantStatuses: []statusUpdate{ - {clusterName: "acs-dev-dp-01", addonID: "alpha", status: metrics.AddonUnhealthy}, - {clusterName: "acs-dev-dp-01", addonID: "beta", status: metrics.AddonUpgrade}, - }, - }, - { - name: "should NOT upgrade when no addons installed yet", - fields: fields{ - ocmClient: &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - object, err := clustersmgmtv1.NewAddOnInstallation(). - ID(addonID). - Addon(clustersmgmtv1.NewAddOn().ID(addonID)). - AddonVersion(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - Build() - Expect(err).To(Not(HaveOccurred())) - return object, nil - }, - GetAddonVersionFunc: func(addonID string, version string) (*clustersmgmtv1.AddOnVersion, error) { - return clustersmgmtv1.NewAddOnVersion().ID("0.2.0").Build() - }, - }, - }, - args: args{ - clusterConfig: gitops.DataPlaneClusterConfig{ - ClusterID: "123456789abcdef", - ClusterName: "acs-dev-dp-01", - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - }, - }, - }, - }, - want: func(mock *ocm.ClientMock) { - Expect(mock.UpdateAddonInstallationCalls()).To(BeEmpty()) - }, - wantStatuses: []statusUpdate{ - {clusterName: "acs-dev-dp-01", addonID: "acs-fleetshard", status: metrics.AddonUpgrade}, - }, - }, - { - name: "should NOT upgrade when the version in config didn't change", - fields: fields{ - ocmClient: &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - object, err := clustersmgmtv1.NewAddOnInstallation(). - ID(addonID). - Addon(clustersmgmtv1.NewAddOn().ID(addonID)). - AddonVersion(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - State(clustersmgmtv1.AddOnInstallationStateReady). - Parameters(clustersmgmtv1.NewAddOnInstallationParameterList().Items(clustersmgmtv1.NewAddOnInstallationParameter().ID("acscsEnvironment").Value("test"))). - Build() - Expect(err).To(Not(HaveOccurred())) - return object, nil - }, - GetAddonVersionFunc: func(addonID string, version string) (*clustersmgmtv1.AddOnVersion, error) { - return clustersmgmtv1.NewAddOnVersion(). - ID("0.2.0"). - SourceImage("quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac"). - PackageImage("quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c"). - Build() - }, - }, - }, - args: args{ - cluster: api.Cluster{ - Addons: addonsJSON([]dbapi.AddonInstallation{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - SourceImage: "quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac", - PackageImage: "quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", - ParametersSHA256Sum: "2b44291c69be83a96af144cc390b7919aebf6421d3d9a976543198032f257a48", // pragma: allowlist secret - }, - }), - }, - clusterConfig: gitops.DataPlaneClusterConfig{ - ClusterID: "123456789abcdef", - ClusterName: "acs-dev-dp-01", - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - Parameters: map[string]string{ - "acscsEnvironment": "test", - }, - }, - }, - }, - }, - want: func(mock *ocm.ClientMock) { - Expect(mock.UpdateAddonInstallationCalls()).To(BeEmpty()) - }, - wantStatuses: []statusUpdate{ - {clusterName: "acs-dev-dp-01", addonID: "acs-fleetshard", status: metrics.AddonHealthy}, - }, - }, - { - name: "should return error when checksum mismatch", - fields: fields{ - ocmClient: &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - object, err := clustersmgmtv1.NewAddOnInstallation(). - ID(addonID). - Addon(clustersmgmtv1.NewAddOn().ID(addonID)). - AddonVersion(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - State(clustersmgmtv1.AddOnInstallationStateReady). - Parameters(clustersmgmtv1.NewAddOnInstallationParameterList().Items(clustersmgmtv1.NewAddOnInstallationParameter().ID("acscsEnvironment").Value("test"))). - Build() - Expect(err).To(Not(HaveOccurred())) - return object, nil - }, - GetAddonVersionFunc: func(addonID string, version string) (*clustersmgmtv1.AddOnVersion, error) { - return clustersmgmtv1.NewAddOnVersion(). - ID("0.2.0"). - SourceImage("quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac"). - PackageImage("quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c"). - Build() - }, - }, - }, - args: args{ - cluster: api.Cluster{ - Addons: addonsJSON([]dbapi.AddonInstallation{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - SourceImage: "quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac", - PackageImage: "quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", - ParametersSHA256Sum: "f54d2c5cb370f4f87a31ccd8f72d97a85d89838720bd69278d1d40ee1cea00dc", // pragma: allowlist secret - }, - }), - }, - clusterConfig: gitops.DataPlaneClusterConfig{ - ClusterID: "123456789abcdef", - ClusterName: "acs-dev-dp-01", - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - Parameters: map[string]string{ - "acscsEnvironment": "test", - }, - }, - }, - }, - }, - wantErr: true, - wantStatuses: []statusUpdate{ - {clusterName: "acs-dev-dp-01", addonID: "acs-fleetshard", status: metrics.AddonUnhealthy}, - }, - }, - { - name: "should upgrade when parameters changed", - fields: fields{ - ocmClient: &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - object, err := clustersmgmtv1.NewAddOnInstallation(). - ID(addonID). - Addon(clustersmgmtv1.NewAddOn().ID(addonID)). - AddonVersion(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - State(clustersmgmtv1.AddOnInstallationStateReady). - Parameters(clustersmgmtv1.NewAddOnInstallationParameterList().Items(clustersmgmtv1.NewAddOnInstallationParameter().ID("acscsEnvironment").Value("test"))). - Build() - Expect(err).To(Not(HaveOccurred())) - return object, nil - }, - GetAddonVersionFunc: func(addonID string, version string) (*clustersmgmtv1.AddOnVersion, error) { - return clustersmgmtv1.NewAddOnVersion(). - ID("0.2.0"). - SourceImage("quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac"). - PackageImage("quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c"). - Build() - }, - UpdateAddonInstallationFunc: func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { - return nil - }, - }, - }, - args: args{ - cluster: api.Cluster{ - Addons: addonsJSON([]dbapi.AddonInstallation{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - SourceImage: "quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac", - PackageImage: "quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", - ParametersSHA256Sum: "2b44291c69be83a96af144cc390b7919aebf6421d3d9a976543198032f257a48", // pragma: allowlist secret - }, - }), - }, - clusterConfig: gitops.DataPlaneClusterConfig{ - ClusterID: "123456789abcdef", - ClusterName: "acs-dev-dp-01", - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - Parameters: map[string]string{ - "acscsEnvironment": "outdated", - }, - }, - }, - }, - }, - want: func(mock *ocm.ClientMock) { - Expect(mock.UpdateAddonInstallationCalls()).To(HaveLen(1)) - }, - wantStatuses: []statusUpdate{ - {clusterName: "acs-dev-dp-01", addonID: "acs-fleetshard", status: metrics.AddonUpgrade}, - }, - }, - { - name: "should upgrade when version changed", - fields: fields{ - ocmClient: &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - object, err := clustersmgmtv1.NewAddOnInstallation(). - ID(addonID). - Addon(clustersmgmtv1.NewAddOn().ID(addonID)). - AddonVersion(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - State(clustersmgmtv1.AddOnInstallationStateReady). - Parameters(clustersmgmtv1.NewAddOnInstallationParameterList().Items(clustersmgmtv1.NewAddOnInstallationParameter().ID("acscsEnvironment").Value("test"))). - Build() - Expect(err).To(Not(HaveOccurred())) - return object, nil - }, - GetAddonVersionFunc: func(addonID string, version string) (*clustersmgmtv1.AddOnVersion, error) { - return clustersmgmtv1.NewAddOnVersion(). - ID("0.2.0"). - SourceImage("quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac"). - PackageImage("quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c"). - Build() - }, - UpdateAddonInstallationFunc: func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { - return nil - }, - }, - }, - args: args{ - cluster: api.Cluster{ - Addons: addonsJSON([]dbapi.AddonInstallation{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - SourceImage: "quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac", - PackageImage: "quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", - ParametersSHA256Sum: "3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", // pragma: allowlist secret - }, - }), - }, - clusterConfig: gitops.DataPlaneClusterConfig{ - ClusterID: "123456789abcdef", - ClusterName: "acs-dev-dp-01", - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard", - Version: "0.3.0", - Parameters: map[string]string{ - "acscsEnvironment": "test", - }, - }, - }, - }, - }, - want: func(mock *ocm.ClientMock) { - Expect(mock.UpdateAddonInstallationCalls()).To(HaveLen(1)) - }, - wantStatuses: []statusUpdate{ - {clusterName: "acs-dev-dp-01", addonID: "acs-fleetshard", status: metrics.AddonUpgrade}, - }, - }, - { - name: "should upgrade when sourceImage changed", - fields: fields{ - ocmClient: &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - object, err := clustersmgmtv1.NewAddOnInstallation(). - ID(addonID). - Addon(clustersmgmtv1.NewAddOn().ID(addonID)). - AddonVersion(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - State(clustersmgmtv1.AddOnInstallationStateReady). - Parameters(clustersmgmtv1.NewAddOnInstallationParameterList().Items(clustersmgmtv1.NewAddOnInstallationParameter().ID("acscsEnvironment").Value("test"))). - Build() - Expect(err).To(Not(HaveOccurred())) - return object, nil - }, - GetAddonVersionFunc: func(addonID string, version string) (*clustersmgmtv1.AddOnVersion, error) { - return clustersmgmtv1.NewAddOnVersion(). - ID("0.2.0"). - SourceImage("quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac"). - PackageImage("quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c"). - Build() - }, - UpdateAddonInstallationFunc: func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { - return nil - }, - }, - }, - args: args{ - cluster: api.Cluster{ - Addons: addonsJSON([]dbapi.AddonInstallation{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - SourceImage: "quay.io/osd-addons/acs-fleetshard-index@sha256:81eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac", - PackageImage: "quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", - ParametersSHA256Sum: "3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", // pragma: allowlist secret - }, - }), - }, - clusterConfig: gitops.DataPlaneClusterConfig{ - ClusterID: "123456789abcdef", - ClusterName: "acs-dev-dp-01", - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard", - Version: "0.3.0", - Parameters: map[string]string{ - "acscsEnvironment": "test", - }, - }, - }, - }, - }, - want: func(mock *ocm.ClientMock) { - Expect(mock.UpdateAddonInstallationCalls()).To(HaveLen(1)) - }, - wantStatuses: []statusUpdate{ - {clusterName: "acs-dev-dp-01", addonID: "acs-fleetshard", status: metrics.AddonUpgrade}, - }, - }, - { - name: "should upgrade when packageImage changed", - fields: fields{ - ocmClient: &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - object, err := clustersmgmtv1.NewAddOnInstallation(). - ID(addonID). - Addon(clustersmgmtv1.NewAddOn().ID(addonID)). - AddonVersion(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - State(clustersmgmtv1.AddOnInstallationStateReady). - Parameters(clustersmgmtv1.NewAddOnInstallationParameterList().Items(clustersmgmtv1.NewAddOnInstallationParameter().ID("acscsEnvironment").Value("test"))). - Build() - Expect(err).To(Not(HaveOccurred())) - return object, nil - }, - GetAddonVersionFunc: func(addonID string, version string) (*clustersmgmtv1.AddOnVersion, error) { - return clustersmgmtv1.NewAddOnVersion(). - ID("0.2.0"). - SourceImage("quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac"). - PackageImage("quay.io/osd-addons/acs-fleetshard-package@sha256:4e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c"). - Build() - }, - UpdateAddonInstallationFunc: func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { - return nil - }, - }, - }, - args: args{ - cluster: api.Cluster{ - Addons: addonsJSON([]dbapi.AddonInstallation{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - SourceImage: "quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac", - PackageImage: "quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", - ParametersSHA256Sum: "3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", // pragma: allowlist secret - }, - }), - }, - clusterConfig: gitops.DataPlaneClusterConfig{ - ClusterID: "123456789abcdef", - ClusterName: "acs-dev-dp-01", - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard", - Version: "0.3.0", - Parameters: map[string]string{ - "acscsEnvironment": "test", - }, - }, - }, - }, - }, - want: func(mock *ocm.ClientMock) { - Expect(mock.UpdateAddonInstallationCalls()).To(HaveLen(1)) - }, - wantStatuses: []statusUpdate{ - {clusterName: "acs-dev-dp-01", addonID: "acs-fleetshard", status: metrics.AddonUpgrade}, - }, - }, - { - name: "should uninstall when no addon declared in gitops", - fields: fields{ - ocmClient: &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - object, err := clustersmgmtv1.NewAddOnInstallation(). - ID(addonID). - Addon(clustersmgmtv1.NewAddOn().ID(addonID)). - AddonVersion(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - State(clustersmgmtv1.AddOnInstallationStateReady). - Parameters(clustersmgmtv1.NewAddOnInstallationParameterList().Items(clustersmgmtv1.NewAddOnInstallationParameter().ID("acscsEnvironment").Value("test"))). - Build() - Expect(err).To(Not(HaveOccurred())) - return object, nil - }, - GetAddonVersionFunc: func(addonID string, version string) (*clustersmgmtv1.AddOnVersion, error) { - return clustersmgmtv1.NewAddOnVersion(). - ID("0.2.0"). - SourceImage("quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac"). - PackageImage("quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c"). - Build() - }, - DeleteAddonInstallationFunc: func(clusterID string, addonID string) error { - return nil - }, - }, - }, - args: args{ - cluster: api.Cluster{ - Addons: addonsJSON([]dbapi.AddonInstallation{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - SourceImage: "quay.io/osd-addons/acs-fleetshard-index@sha256:81eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac", - PackageImage: "quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", - ParametersSHA256Sum: "3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", // pragma: allowlist secret - }, - }), - }, - clusterConfig: gitops.DataPlaneClusterConfig{ - ClusterID: "123456789abcdef", - ClusterName: "acs-dev-dp-01", - Addons: []gitops.AddonConfig{}, - }, - }, - want: func(mock *ocm.ClientMock) { - Expect(mock.DeleteAddonInstallationCalls()).To(HaveLen(1)) - }, - wantStatuses: []statusUpdate{ - {clusterName: "acs-dev-dp-01", addonID: "acs-fleetshard", status: metrics.AddonHealthy}, - }, - }, - { - name: "should install addon with default parameter", - fields: fields{ - ocmClient: &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - return nil, errors.NotFound("") - }, - CreateAddonInstallationFunc: func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { - return nil - }, - GetAddonFunc: func(addonID string) (*clustersmgmtv1.AddOn, error) { - return clustersmgmtv1.NewAddOn(). - ID(addonID). - Version(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - Parameters(clustersmgmtv1.NewAddOnParameterList().Items(clustersmgmtv1.NewAddOnParameter().ID("defaultParam").DefaultValue("123"))). - Build() - - }, - }, - }, - args: args{ - clusterConfig: gitops.DataPlaneClusterConfig{ - ClusterID: "123456789abcdef", - ClusterName: "acs-dev-dp-01", - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard", - Parameters: map[string]string{ - "customParam": "abc", - }, - }, - }, - }, - }, - want: func(mock *ocm.ClientMock) { - Expect(mock.CreateAddonInstallationCalls()).To(HaveLen(1)) - Expect(mock.CreateAddonInstallationCalls()[0].Addon.Parameters().Len()).To(Equal(2)) - }, - }, - { - name: "should parameter defined in gitops take precedence on install ", - fields: fields{ - ocmClient: &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - return nil, errors.NotFound("") - }, - CreateAddonInstallationFunc: func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { - return nil - }, - GetAddonFunc: func(addonID string) (*clustersmgmtv1.AddOn, error) { - return clustersmgmtv1.NewAddOn(). - ID(addonID). - Version(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - Parameters(clustersmgmtv1.NewAddOnParameterList().Items(clustersmgmtv1.NewAddOnParameter().ID("param").DefaultValue("default"))). - Build() - - }, - }, - }, - args: args{ - clusterConfig: gitops.DataPlaneClusterConfig{ - ClusterID: "123456789abcdef", - ClusterName: "acs-dev-dp-01", - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard", - Parameters: map[string]string{ - "param": "custom", - }, - }, - }, - }, - }, - want: func(mock *ocm.ClientMock) { - Expect(mock.CreateAddonInstallationCalls()).To(HaveLen(1)) - Expect(mock.CreateAddonInstallationCalls()[0].Addon.Parameters().Len()).To(Equal(1)) - Expect(mock.CreateAddonInstallationCalls()[0].Addon.Parameters().Get(0).ID()).To(Equal("param")) - Expect(mock.CreateAddonInstallationCalls()[0].Addon.Parameters().Get(0).Value()).To(Equal("custom")) - }, - }, - { - name: "should upgrade with default parameter", - fields: fields{ - ocmClient: &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - object, err := clustersmgmtv1.NewAddOnInstallation(). - ID(addonID). - Addon(clustersmgmtv1.NewAddOn().ID(addonID)). - AddonVersion(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - State(clustersmgmtv1.AddOnInstallationStateReady). - Parameters(clustersmgmtv1.NewAddOnInstallationParameterList().Items(clustersmgmtv1.NewAddOnInstallationParameter().ID("acscsEnvironment").Value("test"))). - Build() - Expect(err).To(Not(HaveOccurred())) - return object, nil - }, - GetAddonVersionFunc: func(addonID string, version string) (*clustersmgmtv1.AddOnVersion, error) { - return clustersmgmtv1.NewAddOnVersion(). - ID("0.2.0"). - SourceImage("quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac"). - PackageImage("quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c"). - Parameters(clustersmgmtv1.NewAddOnParameterList().Items( - clustersmgmtv1.NewAddOnParameter().ID("defaultParam").DefaultValue("abc"))). - Build() - }, - UpdateAddonInstallationFunc: func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { - return nil - }, - }, - }, - args: args{ - cluster: api.Cluster{ - Addons: addonsJSON([]dbapi.AddonInstallation{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - SourceImage: "quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac", - PackageImage: "quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", - ParametersSHA256Sum: "2b44291c69be83a96af144cc390b7919aebf6421d3d9a976543198032f257a48", // pragma: allowlist secret - }, - }), - }, - clusterConfig: gitops.DataPlaneClusterConfig{ - ClusterID: "123456789abcdef", - ClusterName: "acs-dev-dp-01", - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - }, - }, - }, - }, - want: func(mock *ocm.ClientMock) { - Expect(mock.UpdateAddonInstallationCalls()).To(HaveLen(1)) - Expect(mock.UpdateAddonInstallationCalls()[0].Addon.Parameters().Len()).To(Equal(1)) - Expect(mock.UpdateAddonInstallationCalls()[0].Addon.Parameters().Get(0).ID()).To(Equal("defaultParam")) - Expect(mock.UpdateAddonInstallationCalls()[0].Addon.Parameters().Get(0).Value()).To(Equal("abc")) - }, - }, - { - name: "should parameter defined in gitops take precedence on update", - fields: fields{ - ocmClient: &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - object, err := clustersmgmtv1.NewAddOnInstallation(). - ID(addonID). - Addon(clustersmgmtv1.NewAddOn().ID(addonID)). - AddonVersion(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - State(clustersmgmtv1.AddOnInstallationStateReady). - Parameters(clustersmgmtv1.NewAddOnInstallationParameterList().Items(clustersmgmtv1.NewAddOnInstallationParameter().ID("acscsEnvironment").Value("test"))). - Build() - Expect(err).To(Not(HaveOccurred())) - return object, nil - }, - GetAddonVersionFunc: func(addonID string, version string) (*clustersmgmtv1.AddOnVersion, error) { - return clustersmgmtv1.NewAddOnVersion(). - ID("0.2.0"). - SourceImage("quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac"). - PackageImage("quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c"). - Parameters(clustersmgmtv1.NewAddOnParameterList().Items( - clustersmgmtv1.NewAddOnParameter().ID("param").DefaultValue("default"))). - Build() - }, - UpdateAddonInstallationFunc: func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { - return nil - }, - }, - }, - args: args{ - cluster: api.Cluster{ - Addons: addonsJSON([]dbapi.AddonInstallation{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - SourceImage: "quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac", - PackageImage: "quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", - ParametersSHA256Sum: "2b44291c69be83a96af144cc390b7919aebf6421d3d9a976543198032f257a48", // pragma: allowlist secret - }, - }), - }, - clusterConfig: gitops.DataPlaneClusterConfig{ - ClusterID: "123456789abcdef", - ClusterName: "acs-dev-dp-01", - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - Parameters: map[string]string{ - "param": "custom", - }, - }, - }, - }, - }, - want: func(mock *ocm.ClientMock) { - Expect(mock.UpdateAddonInstallationCalls()).To(HaveLen(1)) - Expect(mock.UpdateAddonInstallationCalls()[0].Addon.Parameters().Len()).To(Equal(1)) - Expect(mock.UpdateAddonInstallationCalls()[0].Addon.Parameters().Get(0).ID()).To(Equal("param")) - Expect(mock.UpdateAddonInstallationCalls()[0].Addon.Parameters().Get(0).Value()).To(Equal("custom")) - }, - }, - { - name: "should default parameters be taken from the actual gitops version", - fields: fields{ - ocmClient: &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - object, err := clustersmgmtv1.NewAddOnInstallation(). - ID(addonID). - Addon(clustersmgmtv1.NewAddOn().ID(addonID)). - AddonVersion(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - State(clustersmgmtv1.AddOnInstallationStateReady). - Parameters(clustersmgmtv1.NewAddOnInstallationParameterList().Items(clustersmgmtv1.NewAddOnInstallationParameter().ID("acscsEnvironment").Value("test"))). - Build() - Expect(err).To(Not(HaveOccurred())) - return object, nil - }, - GetAddonVersionFunc: func(addonID string, version string) (*clustersmgmtv1.AddOnVersion, error) { - if version == "0.2.0" { - return clustersmgmtv1.NewAddOnVersion(). - ID("0.2.0"). - SourceImage("quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac"). - PackageImage("quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c"). - Parameters(clustersmgmtv1.NewAddOnParameterList().Items( - clustersmgmtv1.NewAddOnParameter().ID("deprecatedParam").DefaultValue("value"))). - Build() - } else if version == "0.3.0" { - return clustersmgmtv1.NewAddOnVersion(). - ID("0.3.0"). - SourceImage("quay.io/osd-addons/acs-fleetshard-index@sha256:81eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac"). - PackageImage("quay.io/osd-addons/acs-fleetshard-package@sha256:4e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c"). - Build() - } - return nil, errors.NotFound("version not found") - }, - UpdateAddonInstallationFunc: func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { - return nil - }, - }, - }, - args: args{ - cluster: api.Cluster{ - Addons: addonsJSON([]dbapi.AddonInstallation{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - SourceImage: "quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac", - PackageImage: "quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", - ParametersSHA256Sum: "3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", // pragma: allowlist secret - }, - }), - }, - clusterConfig: gitops.DataPlaneClusterConfig{ - ClusterID: "123456789abcdef", - ClusterName: "acs-dev-dp-01", - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard", - Version: "0.3.0", - }, - }, - }, - }, - want: func(mock *ocm.ClientMock) { - Expect(mock.UpdateAddonInstallationCalls()).To(HaveLen(1)) - Expect(mock.UpdateAddonInstallationCalls()[0].Addon.Parameters().Len()).To(Equal(0)) - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.setup != nil { - tt.setup() - } - var updates []statusUpdate - p := &AddonProvisioner{ - ocmClient: tt.fields.ocmClient, - updateAddonStatusMetricFunc: func(addonID, clusterName string, status metrics.AddonStatus) { - updates = append(updates, statusUpdate{addonID: addonID, clusterName: clusterName, status: status}) - }, - } - err := p.Provision(tt.args.cluster, tt.args.clusterConfig) - if tt.wantErr { - Expect(err).To(HaveOccurred()) - } else { - Expect(err).To(Not(HaveOccurred())) - } - if tt.want != nil { - tt.want(tt.fields.ocmClient) - } - - if tt.fields.ocmClient != nil { - if len(tt.fields.ocmClient.UpdateAddonInstallationCalls()) > 0 { - Expect(p.lastUpgradeRequestTime).NotTo(Equal(time.Time{})) - Expect(p.lastStatusPerInstall).NotTo(BeEmpty()) - } - } - if tt.wantStatuses != nil { - Expect(updates).To(Equal(tt.wantStatuses)) - } - }) - } -} - -func TestAddonProvisioner_Provision_NonFinalState(t *testing.T) { - RegisterTestingT(t) - tests := []struct { - name string - state clustersmgmtv1.AddOnInstallationState - }{ - { - name: "should skip the update if there's no installation state", - }, - { - name: "should skip the update if the addon is in deleting state", - state: clustersmgmtv1.AddOnInstallationStateDeleting, - }, - { - name: "should skip the update if the addon is in installing state", - state: clustersmgmtv1.AddOnInstallationStateInstalling, - }, - { - name: "should skip the update if the addon is in pending state", - state: clustersmgmtv1.AddOnInstallationStatePending, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ocmMock := &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - builder := clustersmgmtv1.NewAddOnInstallation(). - ID(addonID). - Addon(clustersmgmtv1.NewAddOn().ID(addonID)). - AddonVersion(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")) - if tt.state != "" { - builder = builder.State(tt.state) - } - object, err := builder.Build() - Expect(err).To(Not(HaveOccurred())) - return object, nil - }, - GetAddonVersionFunc: func(addonID string, version string) (*clustersmgmtv1.AddOnVersion, error) { - return clustersmgmtv1.NewAddOnVersion().ID("0.2.0").Build() - }, - } - p := &AddonProvisioner{ - ocmClient: ocmMock, - } - err := p.Provision(api.Cluster{ - Addons: addonsJSON([]dbapi.AddonInstallation{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - SourceImage: "quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac", - PackageImage: "quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", - ParametersSHA256Sum: "f54d2c5cb370f4f87a31ccd8f72d97a85d89838720bd69278d1d40ee1cea00dc", // pragma: allowlist secret - }, - }), - }, - gitops.DataPlaneClusterConfig{ - ClusterID: "123456789abcdef", - ClusterName: "acs-dev-dp-01", - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - }, - }, - }) - Expect(err).To(Not(HaveOccurred())) - Expect(ocmMock.UpdateAddonInstallationCalls()).To(BeEmpty()) - }) - } -} - -func TestAddonProvisioner_Provision_AutoUpgradeDisabled(t *testing.T) { - t.Setenv("RHACS_ADDON_AUTO_UPGRADE", "false") - t.Run("should NOT upgrade when auto upgrade feature is disabled", func(t *testing.T) { - mock := ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - object, err := clustersmgmtv1.NewAddOnInstallation(). - ID(addonID). - Addon(clustersmgmtv1.NewAddOn().ID(addonID)). - AddonVersion(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - Build() - Expect(err).To(Not(HaveOccurred())) - return object, nil - }, - GetAddonVersionFunc: func(addonID string, version string) (*clustersmgmtv1.AddOnVersion, error) { - return clustersmgmtv1.NewAddOnVersion().ID("0.2.0").Build() - }, - } - p := &AddonProvisioner{ - ocmClient: &mock, - } - err := p.Provision(api.Cluster{}, gitops.DataPlaneClusterConfig{ - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - }, - }, - }) - Expect(err).To(Not(HaveOccurred())) - Expect(mock.UpdateAddonInstallationCalls()).To(BeEmpty()) - }) -} - -func TestAddonProvisioner_Provision_InheritFleetshardImageTag_Install(t *testing.T) { - RegisterTestingT(t) - - ocmMock := &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - return nil, errors.NotFound("") - }, - CreateAddonInstallationFunc: func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { - return nil - }, - GetAddonFunc: func(addonID string) (*clustersmgmtv1.AddOn, error) { - return clustersmgmtv1.NewAddOn(). - ID(addonID). - Version(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - Build() - }, - } - addonConfig := ocmImpl.AddonConfig{ - FleetshardSyncImageTag: "0307e03", - InheritFleetshardSyncImageTag: true, - } - p := &AddonProvisioner{ - ocmClient: ocmMock, - customizations: initCustomizations(addonConfig), - } - err := p.Provision(api.Cluster{}, gitops.DataPlaneClusterConfig{ - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard-dev", - Parameters: map[string]string{ - "fleetshardSyncImageTag": "inherit", - }, - }, - }, - }) - Expect(err).To(Not(HaveOccurred())) - Expect(ocmMock.CreateAddonInstallationCalls()).To(HaveLen(1)) - Expect(ocmMock.CreateAddonInstallationCalls()[0].Addon.Parameters().Len()).To(Equal(1)) - Expect(ocmMock.CreateAddonInstallationCalls()[0].Addon.Parameters().Get(0).ID()).To(Equal("fleetshardSyncImageTag")) - Expect(ocmMock.CreateAddonInstallationCalls()[0].Addon.Parameters().Get(0).Value()).To(Equal("0307e03")) -} - -func TestAddonProvisioner_Provision_InheritFleetshardImageTag_Upgrade(t *testing.T) { - RegisterTestingT(t) - - ocmMock := &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - object, err := clustersmgmtv1.NewAddOnInstallation(). - ID(addonID). - Addon(clustersmgmtv1.NewAddOn().ID(addonID)). - AddonVersion(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - State(clustersmgmtv1.AddOnInstallationStateReady). - Build() - Expect(err).To(Not(HaveOccurred())) - return object, nil - }, - GetAddonVersionFunc: func(addonID string, version string) (*clustersmgmtv1.AddOnVersion, error) { - return clustersmgmtv1.NewAddOnVersion(). - ID("0.2.0"). - SourceImage("quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac"). - PackageImage("quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c"). - Build() - }, - UpdateAddonInstallationFunc: func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { - return nil - }, - } - addonConfig := ocmImpl.AddonConfig{ - FleetshardSyncImageTag: "0307e03", - InheritFleetshardSyncImageTag: true, - } - p := &AddonProvisioner{ - ocmClient: ocmMock, - customizations: initCustomizations(addonConfig), - } - err := p.Provision(api.Cluster{ - Addons: addonsJSON([]dbapi.AddonInstallation{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - SourceImage: "quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac", - PackageImage: "quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", - ParametersSHA256Sum: "3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", // pragma: allowlist secret - }, - }), - }, - gitops.DataPlaneClusterConfig{ - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard", - Version: "0.3.0", - Parameters: map[string]string{ - "fleetshardSyncImageTag": "inherit", - }, - }, - }, - }) - - Expect(err).To(Not(HaveOccurred())) - Expect(ocmMock.UpdateAddonInstallationCalls()).To(HaveLen(1)) - Expect(ocmMock.UpdateAddonInstallationCalls()[0].Addon.Parameters().Len()).To(Equal(1)) - Expect(ocmMock.UpdateAddonInstallationCalls()[0].Addon.Parameters().Get(0).ID()).To(Equal("fleetshardSyncImageTag")) - Expect(ocmMock.UpdateAddonInstallationCalls()[0].Addon.Parameters().Get(0).Value()).To(Equal("0307e03")) -} - -func addonsJSON(addons []dbapi.AddonInstallation) api.JSON { - result, err := json.Marshal(addons) - Expect(err).To(Not(HaveOccurred())) - return result -} - -func TestAddonProvisioner_NewAddonProvisioner(t *testing.T) { - RegisterTestingT(t) - - addonConfigPtr := &ocmImpl.AddonConfig{ - URL: "https://addon-service.test", - ClientID: "addon-client-id", - ClientSecret: "addon-client-secret", // pragma: allowlist secret - SelfToken: "addon-token", - } - - baseConfigPtr := &ocmImpl.OCMConfig{ - BaseURL: "https://base.test", - ClientID: "base-client-id", - ClientSecret: "base-client-secret", // pragma: allowlist secret - SelfToken: "base-token", - } - - _, err := NewAddonProvisioner(addonConfigPtr, baseConfigPtr) - - Expect(err).To(Not(HaveOccurred())) - Expect(baseConfigPtr.BaseURL).To(Equal("https://base.test")) - Expect(baseConfigPtr.ClientID).To(Equal("base-client-id")) - Expect(baseConfigPtr.ClientSecret).To(Equal("base-client-secret")) - Expect(baseConfigPtr.SelfToken).To(Equal("base-token")) -} - -func TestAddonProvisioner_Provision_UpgradeBackoff(t *testing.T) { - RegisterTestingT(t) - - ocmMock := &ocm.ClientMock{ - GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *errors.ServiceError) { - object, err := clustersmgmtv1.NewAddOnInstallation(). - ID(addonID). - Addon(clustersmgmtv1.NewAddOn().ID(addonID)). - AddonVersion(clustersmgmtv1.NewAddOnVersion().ID("0.2.0")). - State(clustersmgmtv1.AddOnInstallationStateReady). - Build() - Expect(err).To(Not(HaveOccurred())) - return object, nil - }, - GetAddonVersionFunc: func(addonID string, version string) (*clustersmgmtv1.AddOnVersion, error) { - return clustersmgmtv1.NewAddOnVersion(). - ID("0.2.0"). - SourceImage("quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac"). - PackageImage("quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c"). - Build() - }, - UpdateAddonInstallationFunc: func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { - return nil - }, - } - addonConfig := ocmImpl.AddonConfig{ - FleetshardSyncImageTag: "0307e03", - InheritFleetshardSyncImageTag: true, - } - p := &AddonProvisioner{ - ocmClient: ocmMock, - customizations: initCustomizations(addonConfig), - lastStatusPerInstall: map[string]metrics.AddonStatus{ - "cluster-id:acs-fleetshard": metrics.AddonUpgrade, - }, - lastUpgradeRequestTime: time.Now(), - } - err := p.Provision(api.Cluster{ - Addons: addonsJSON([]dbapi.AddonInstallation{ - { - ID: "acs-fleetshard", - Version: "0.2.0", - SourceImage: "quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac", - PackageImage: "quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", - ParametersSHA256Sum: "3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", // pragma: allowlist secret - }, - }), - }, - gitops.DataPlaneClusterConfig{ - ClusterID: "cluster-id", - Addons: []gitops.AddonConfig{ - { - ID: "acs-fleetshard", - Version: "0.3.0", - Parameters: map[string]string{ - "fleetshardSyncImageTag": "inherit", - }, - }, - }, - }) - - Expect(err).To(Not(HaveOccurred())) - Expect(ocmMock.UpdateAddonInstallationCalls()).To(BeEmpty()) -} diff --git a/internal/central/pkg/services/data_plane_cluster.go b/internal/central/pkg/services/data_plane_cluster.go deleted file mode 100644 index f74306af15..0000000000 --- a/internal/central/pkg/services/data_plane_cluster.go +++ /dev/null @@ -1,78 +0,0 @@ -package services - -import ( - "context" - "encoding/json" - "fmt" - - "github.com/goava/di" - "github.com/stackrox/acs-fleet-manager/internal/central/pkg/api/dbapi" - "github.com/stackrox/acs-fleet-manager/internal/central/pkg/config" - "github.com/stackrox/acs-fleet-manager/pkg/api" - "github.com/stackrox/acs-fleet-manager/pkg/errors" -) - -// DataPlaneClusterService ... -type DataPlaneClusterService interface { - UpdateDataPlaneClusterStatus(clusterID string, status dbapi.DataPlaneClusterStatus) *errors.ServiceError - GetDataPlaneClusterConfig(ctx context.Context, clusterID string) (*dbapi.DataPlaneClusterConfig, *errors.ServiceError) -} - -var _ DataPlaneClusterService = &dataPlaneClusterService{} - -type dataPlaneClusterService struct { - di.Inject - ClusterService ClusterService - CentralConfig *config.CentralConfig - DataplaneClusterConfig *config.DataplaneClusterConfig -} - -// NewDataPlaneClusterService ... -func NewDataPlaneClusterService(config dataPlaneClusterService) DataPlaneClusterService { - return &config -} - -// GetDataPlaneClusterConfig ... -func (d *dataPlaneClusterService) GetDataPlaneClusterConfig(ctx context.Context, clusterID string) (*dbapi.DataPlaneClusterConfig, *errors.ServiceError) { - cluster, svcErr := d.ClusterService.FindClusterByID(clusterID) - if svcErr != nil { - return nil, svcErr - } - if cluster == nil { - // 404 is used for authenticated requests. So to distinguish the errors, we use 400 here - return nil, errors.BadRequest("Cluster agent with ID '%s' not found", clusterID) - } - - return &dbapi.DataPlaneClusterConfig{}, nil -} - -// UpdateDataPlaneClusterStatus ... -func (d *dataPlaneClusterService) UpdateDataPlaneClusterStatus(clusterID string, status dbapi.DataPlaneClusterStatus) *errors.ServiceError { - cluster, svcErr := d.ClusterService.FindClusterByID(clusterID) - if svcErr != nil { - return svcErr - } - if cluster == nil { - // 404 is used for authenticated requests. So to distinguish the errors, we use 400 here - return errors.BadRequest("Cluster agent with ID '%s' not found", clusterID) - } - - err := d.setClusterStatus(cluster, status) - if err != nil { - return errors.ToServiceError(err) - } - - return nil -} - -func (d *dataPlaneClusterService) setClusterStatus(cluster *api.Cluster, status dbapi.DataPlaneClusterStatus) error { - addonsJSON, err := json.Marshal(status.Addons) - if err != nil { - return fmt.Errorf("marshal fleetshardAddonStatus to JSON: %w", err) - } - cluster.Addons = addonsJSON - if err := d.ClusterService.Update(*cluster); err != nil { - return fmt.Errorf("updating cluster status: %w", err) - } - return nil -} diff --git a/internal/central/pkg/workers/clusters_mgr.go b/internal/central/pkg/workers/clusters_mgr.go index 2f571c36f4..55591ddf10 100644 --- a/internal/central/pkg/workers/clusters_mgr.go +++ b/internal/central/pkg/workers/clusters_mgr.go @@ -26,15 +26,6 @@ import ( "github.com/pkg/errors" ) -const ( - mkReadOnlyGroupName = "mk-readonly-access" - mkSREGroupName = "central-sre" - mkReadOnlyRoleBindingName = "mk-dedicated-readers" - mkSRERoleBindingName = "central-sre-cluster-admin" - dedicatedReadersRoleBindingName = "dedicated-readers" - clusterAdminRoleName = "cluster-admin" -) - var ( readyClusterCount int32 ) @@ -75,7 +66,6 @@ type ClusterManagerOptions struct { SupportedProviders *config.ProviderConfig ClusterService services.ClusterService CloudProvidersService services.CloudProvidersService - AddonProvisioner *services.AddonProvisioner GitOpsConfigProvider gitops.ConfigProvider } @@ -314,16 +304,6 @@ func (c *ClusterManager) processReadyClusters() []error { readyClusterCount = int32(len(readyClusters)) logger.InfoChangedInt32(&readyClusterCount, "ready clusters count = %d", readyClusterCount) - gitopsConfig, err := c.GitOpsConfigProvider.Get() - if err != nil { - errs = append(errs, fmt.Errorf("get gitops config: %w", err)) - return errs - } - clusterConfigByID := make(map[string]gitops.DataPlaneClusterConfig) - for _, cluster := range gitopsConfig.DataPlaneClusters { - clusterConfigByID[cluster.ClusterID] = cluster - } - for _, readyCluster := range readyClusters { emptyClusterReconciled := false var recErr error @@ -333,9 +313,6 @@ func (c *ClusterManager) processReadyClusters() []error { if !emptyClusterReconciled && recErr == nil { recErr = c.reconcileReadyCluster(readyCluster) } - if recErr == nil { - recErr = c.reconcileClusterAddons(readyCluster, clusterConfigByID) - } if recErr != nil { errs = append(errs, errors.Wrapf(recErr, "failed to reconcile ready cluster %s", readyCluster.ClusterID)) } @@ -751,15 +728,3 @@ func (c *ClusterManager) setCentralPerClusterCountMetrics() error { return nil } - -func (c *ClusterManager) reconcileClusterAddons(cluster api.Cluster, clusterConfigByID map[string]gitops.DataPlaneClusterConfig) error { - clusterConfig, exists := clusterConfigByID[cluster.ClusterID] - if !exists { - // There's no such cluster in gitops config, skipping - return nil - } - if err := c.AddonProvisioner.Provision(cluster, clusterConfig); err != nil { - return fmt.Errorf("provision addons: %w", err) - } - return nil -} diff --git a/internal/central/providers.go b/internal/central/providers.go index edcaf1be22..ba33db715e 100644 --- a/internal/central/providers.go +++ b/internal/central/providers.go @@ -54,9 +54,7 @@ func ServiceProviders() di.Option { di.Provide(services.NewClusterService), di.Provide(services.NewCentralService), di.Provide(services.NewCloudProvidersService), - di.Provide(services.NewAddonProvisioner), di.Provide(services.NewClusterPlacementStrategy), - di.Provide(services.NewDataPlaneClusterService), di.Provide(services.NewDataPlaneCentralService), di.Provide(clusters.NewDefaultProviderFactory, di.As(new(clusters.ProviderFactory))), di.Provide(routes.NewRouteLoader), diff --git a/internal/central/test/integration/centrals_test.go b/internal/central/test/integration/centrals_test.go index 8a0ad5e170..ce637f1d39 100644 --- a/internal/central/test/integration/centrals_test.go +++ b/internal/central/test/integration/centrals_test.go @@ -139,14 +139,7 @@ func TestCentral_Delete(t *testing.T) { sampleCentralID := api.NewID() - ocmServerBuilder := mocks.NewMockConfigurableServerBuilder() - mockedGetClusterResponse, err := mockedClusterWithMetricsInfo(mocks.MockClusterComputeNodes) - if err != nil { - t.Fatalf("%s", err.Error()) - } - ocmServerBuilder.SetClusterGetResponse(mockedGetClusterResponse, nil) - - ocmServer := ocmServerBuilder.Build() + ocmServer := mocks.NewMockConfigurableServerBuilder().Build() defer ocmServer.Close() h, _, tearDown := test.NewCentralHelper(t, ocmServer) diff --git a/internal/central/test/integration/data_plane_endpoints_test.go b/internal/central/test/integration/data_plane_endpoints_test.go deleted file mode 100644 index 24b7561098..0000000000 --- a/internal/central/test/integration/data_plane_endpoints_test.go +++ /dev/null @@ -1,102 +0,0 @@ -package integration - -import ( - "context" - "encoding/json" - "fmt" - "net/http" - "testing" - - . "github.com/onsi/gomega" - clustersmgmtv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" - "github.com/stackrox/acs-fleet-manager/internal/central/pkg/api/dbapi" - "github.com/stackrox/acs-fleet-manager/internal/central/pkg/api/private" - "github.com/stackrox/acs-fleet-manager/internal/central/test" - "github.com/stackrox/acs-fleet-manager/pkg/api" - "github.com/stackrox/acs-fleet-manager/test/mocks" -) - -func mockedClusterWithMetricsInfo(computeNodes int) (*clustersmgmtv1.Cluster, error) { - clusterBuilder := mocks.GetMockClusterBuilder(nil) - clusterNodeBuilder := clustersmgmtv1.NewClusterNodes() - clusterNodeBuilder.Compute(computeNodes) - clusterBuilder.Nodes(clusterNodeBuilder) - return clusterBuilder.Build() -} - -func TestDataPlaneClusterStatus(t *testing.T) { - ocmServerBuilder := mocks.NewMockConfigurableServerBuilder() - mockedGetClusterResponse, err := mockedClusterWithMetricsInfo(mocks.MockClusterComputeNodes) - if err != nil { - t.Fatalf("%s", err.Error()) - } - - ocmServerBuilder.SetClusterGetResponse(mockedGetClusterResponse, nil) - ocmServer := ocmServerBuilder.Build() - defer ocmServer.Close() - h, _, tearDown := test.NewCentralHelper(t, ocmServer) - defer tearDown() - - clusterID := api.NewID() - token := h.CreateDataPlaneJWTString() - - config := private.NewConfiguration() - config.BasePath = fmt.Sprintf("http://%s", test.TestServices.ServerConfig.BindAddress) - config.DefaultHeader = map[string]string{ - "Authorization": "Bearer " + token, - } - privateClient := private.NewAPIClient(config) - - db := test.TestServices.DBFactory.New() - cluster := &api.Cluster{ - Meta: api.Meta{ - ID: clusterID, - }, - ClusterID: clusterID, - MultiAZ: true, - Region: "baremetal", - CloudProvider: "baremetal", - Status: api.ClusterReady, - IdentityProviderID: "some-id", - ClusterDNS: "some-cluster-dns", - ProviderType: api.ClusterProviderStandalone, - } - - err = db.Create(cluster).Error - Expect(err).NotTo(HaveOccurred()) - - resp, err := privateClient.AgentClustersApi.UpdateAgentClusterStatus(context.Background(), clusterID, private.DataPlaneClusterUpdateStatusRequest{ - Addons: []private.DataPlaneClusterUpdateStatusRequestAddons{ - { - Id: "acs-fleetshard", - Version: "0.2.0", - SourceImage: "quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac", - PackageImage: "quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c", - ParametersSHA256Sum: "f54d2c5cb370f4f87a31ccd8f72d97a85d89838720bd69278d1d40ee1cea00dc", // pragma: allowlist secret - }, - }, - }) - Expect(err).NotTo(HaveOccurred()) - Expect(resp.StatusCode).To(Equal(http.StatusOK)) - - clusterDetails := &api.Cluster{ - ClusterID: cluster.ID, - } - - err = db.Where(clusterDetails).First(cluster).Error - Expect(err).ToNot(HaveOccurred()) - - Expect(cluster.Addons).NotTo(BeEmpty()) - - var addonInstallations []dbapi.AddonInstallation - err = json.Unmarshal(cluster.Addons, &addonInstallations) - Expect(err).ToNot(HaveOccurred()) - Expect(addonInstallations).To(HaveLen(1)) - - fleetshardAddon := addonInstallations[0] - Expect(fleetshardAddon.ID).To(Equal("acs-fleetshard")) - Expect(fleetshardAddon.Version).To(Equal("0.2.0")) - Expect(fleetshardAddon.SourceImage).To(Equal("quay.io/osd-addons/acs-fleetshard-index@sha256:71eaaccb4d3962043eac953fb3c19a6cc6a88b18c472dd264efc5eb3da4960ac")) - Expect(fleetshardAddon.PackageImage).To(Equal("quay.io/osd-addons/acs-fleetshard-package@sha256:3e4fc039662b876c83dd4b48a9608d6867a12ab4932c5b7297bfbe50ba8ee61c")) - Expect(fleetshardAddon.ParametersSHA256Sum).To(Equal("f54d2c5cb370f4f87a31ccd8f72d97a85d89838720bd69278d1d40ee1cea00dc")) // pragma: allowlist secret -} diff --git a/openapi/fleet-manager-private.yaml b/openapi/fleet-manager-private.yaml index f875ef2231..84f7fe6db1 100644 --- a/openapi/fleet-manager-private.yaml +++ b/openapi/fleet-manager-private.yaml @@ -22,46 +22,6 @@ tags: paths: # Endpoints for data plane communications - "/api/rhacs/v1/agent-clusters/{id}/status": - put: - tags: - - Agent Clusters - parameters: - - $ref: "fleet-manager.yaml#/components/parameters/id" - requestBody: - description: Cluster status update data - content: - application/json: - schema: - $ref: "#/components/schemas/DataPlaneClusterUpdateStatusRequest" - required: true - responses: - "200": - description: Cluster status is updated - "400": - content: - application/json: - schema: - $ref: "fleet-manager.yaml#/components/schemas/Error" - examples: - 400InvalidIdExample: - $ref: "#/components/examples/400InvalidIdExample" - description: id value is not valid - "404": - content: - application/json: - schema: - $ref: "fleet-manager.yaml#/components/schemas/Error" - examples: - 404Example: - $ref: "fleet-manager.yaml#/components/examples/404Example" - # This is deliberate to hide the endpoints for unauthorised users - description: Auth token is not valid. - security: - - Bearer: [ ] - operationId: updateAgentClusterStatus - summary: Update the status of an agent cluster - "/api/rhacs/v1/agent-clusters/{id}/centrals/status": put: tags: @@ -176,43 +136,6 @@ paths: operationId: getCentral summary: Get the ManagedaCentral for the specified agent cluster and centralId - "/api/rhacs/v1/agent-clusters/{id}": - get: - tags: - - Agent Clusters - parameters: - - $ref: "fleet-manager.yaml#/components/parameters/id" - responses: - "200": - description: The Data Plane Cluster Agent configuration - content: - application/json: - schema: - $ref: "#/components/schemas/DataplaneClusterAgentConfig" - "400": - content: - application/json: - schema: - $ref: "fleet-manager.yaml#/components/schemas/Error" - examples: - 400InvalidIdExample: - $ref: "#/components/examples/400InvalidIdExample" - description: id value is not valid - "404": - content: - application/json: - schema: - $ref: "fleet-manager.yaml#/components/schemas/Error" - examples: - 404Example: - $ref: "fleet-manager.yaml#/components/examples/404Example" - # This is deliberate to hide the endpoints for unauthorised users - description: Auth token is not valid. - security: - - Bearer: [ ] - operationId: getDataPlaneClusterAgentConfig - summary: Get the data plane cluster agent configuration - components: schemas: ListReference: @@ -385,25 +308,6 @@ components: items: type: object - DataPlaneClusterUpdateStatusRequest: - description: "Schema for the request to update a data plane cluster's status" - type: object - properties: - addons: - type: array - items: - type: object - properties: - id: - type: string - version: - type: string - sourceImage: - type: string - packageImage: - type: string - parametersSHA256Sum: - type: string DataPlaneCentralStatus: description: "Schema of the status object for a Central" type: object diff --git a/pkg/api/cluster_types.go b/pkg/api/cluster_types.go index 00b30b7d79..1488917215 100644 --- a/pkg/api/cluster_types.go +++ b/pkg/api/cluster_types.go @@ -154,8 +154,6 @@ type Cluster struct { SupportedInstanceType string `json:"supported_instance_type"` // The cluster is "schedulable" if tenants can be placed there. Schedulable bool `json:"schedulable"` - // stores the actual information about addons installed on the cluster - Addons JSON `json:"addons"` } // BeforeCreate ... diff --git a/pkg/client/fleetmanager/client.go b/pkg/client/fleetmanager/client.go index d1be389088..26c44c6333 100644 --- a/pkg/client/fleetmanager/client.go +++ b/pkg/client/fleetmanager/client.go @@ -26,7 +26,6 @@ type PrivateAPI interface { GetCentral(ctx context.Context, centralID string) (private.ManagedCentral, *http.Response, error) GetCentrals(ctx context.Context, id string) (private.ManagedCentralList, *http.Response, error) UpdateCentralClusterStatus(ctx context.Context, id string, requestBody map[string]private.DataPlaneCentralStatus) (*http.Response, error) - UpdateAgentClusterStatus(ctx context.Context, id string, request private.DataPlaneClusterUpdateStatusRequest) (*http.Response, error) } // AdminAPI is a wrapper interface for the fleetmanager client admin API. diff --git a/pkg/client/fleetmanager/mocks/client_moq.go b/pkg/client/fleetmanager/mocks/client_moq.go index 1a3d37e141..ab34285272 100644 --- a/pkg/client/fleetmanager/mocks/client_moq.go +++ b/pkg/client/fleetmanager/mocks/client_moq.go @@ -369,9 +369,6 @@ var _ fleetmanager.PrivateAPI = &PrivateAPIMock{} // GetCentralsFunc: func(ctx context.Context, id string) (private.ManagedCentralList, *http.Response, error) { // panic("mock out the GetCentrals method") // }, -// UpdateAgentClusterStatusFunc: func(ctx context.Context, id string, request private.DataPlaneClusterUpdateStatusRequest) (*http.Response, error) { -// panic("mock out the UpdateAgentClusterStatus method") -// }, // UpdateCentralClusterStatusFunc: func(ctx context.Context, id string, requestBody map[string]private.DataPlaneCentralStatus) (*http.Response, error) { // panic("mock out the UpdateCentralClusterStatus method") // }, @@ -388,9 +385,6 @@ type PrivateAPIMock struct { // GetCentralsFunc mocks the GetCentrals method. GetCentralsFunc func(ctx context.Context, id string) (private.ManagedCentralList, *http.Response, error) - // UpdateAgentClusterStatusFunc mocks the UpdateAgentClusterStatus method. - UpdateAgentClusterStatusFunc func(ctx context.Context, id string, request private.DataPlaneClusterUpdateStatusRequest) (*http.Response, error) - // UpdateCentralClusterStatusFunc mocks the UpdateCentralClusterStatus method. UpdateCentralClusterStatusFunc func(ctx context.Context, id string, requestBody map[string]private.DataPlaneCentralStatus) (*http.Response, error) @@ -410,15 +404,6 @@ type PrivateAPIMock struct { // ID is the id argument value. ID string } - // UpdateAgentClusterStatus holds details about calls to the UpdateAgentClusterStatus method. - UpdateAgentClusterStatus []struct { - // Ctx is the ctx argument value. - Ctx context.Context - // ID is the id argument value. - ID string - // Request is the request argument value. - Request private.DataPlaneClusterUpdateStatusRequest - } // UpdateCentralClusterStatus holds details about calls to the UpdateCentralClusterStatus method. UpdateCentralClusterStatus []struct { // Ctx is the ctx argument value. @@ -431,7 +416,6 @@ type PrivateAPIMock struct { } lockGetCentral sync.RWMutex lockGetCentrals sync.RWMutex - lockUpdateAgentClusterStatus sync.RWMutex lockUpdateCentralClusterStatus sync.RWMutex } @@ -507,46 +491,6 @@ func (mock *PrivateAPIMock) GetCentralsCalls() []struct { return calls } -// UpdateAgentClusterStatus calls UpdateAgentClusterStatusFunc. -func (mock *PrivateAPIMock) UpdateAgentClusterStatus(ctx context.Context, id string, request private.DataPlaneClusterUpdateStatusRequest) (*http.Response, error) { - if mock.UpdateAgentClusterStatusFunc == nil { - panic("PrivateAPIMock.UpdateAgentClusterStatusFunc: method is nil but PrivateAPI.UpdateAgentClusterStatus was just called") - } - callInfo := struct { - Ctx context.Context - ID string - Request private.DataPlaneClusterUpdateStatusRequest - }{ - Ctx: ctx, - ID: id, - Request: request, - } - mock.lockUpdateAgentClusterStatus.Lock() - mock.calls.UpdateAgentClusterStatus = append(mock.calls.UpdateAgentClusterStatus, callInfo) - mock.lockUpdateAgentClusterStatus.Unlock() - return mock.UpdateAgentClusterStatusFunc(ctx, id, request) -} - -// UpdateAgentClusterStatusCalls gets all the calls that were made to UpdateAgentClusterStatus. -// Check the length with: -// -// len(mockedPrivateAPI.UpdateAgentClusterStatusCalls()) -func (mock *PrivateAPIMock) UpdateAgentClusterStatusCalls() []struct { - Ctx context.Context - ID string - Request private.DataPlaneClusterUpdateStatusRequest -} { - var calls []struct { - Ctx context.Context - ID string - Request private.DataPlaneClusterUpdateStatusRequest - } - mock.lockUpdateAgentClusterStatus.RLock() - calls = mock.calls.UpdateAgentClusterStatus - mock.lockUpdateAgentClusterStatus.RUnlock() - return calls -} - // UpdateCentralClusterStatus calls UpdateCentralClusterStatusFunc. func (mock *PrivateAPIMock) UpdateCentralClusterStatus(ctx context.Context, id string, requestBody map[string]private.DataPlaneCentralStatus) (*http.Response, error) { if mock.UpdateCentralClusterStatusFunc == nil { diff --git a/pkg/client/ocm/client.go b/pkg/client/ocm/client.go index 1c063ab20c..0d7b608b6e 100644 --- a/pkg/client/ocm/client.go +++ b/pkg/client/ocm/client.go @@ -4,7 +4,6 @@ import ( sdkClient "github.com/openshift-online/ocm-sdk-go" amsv1 "github.com/openshift-online/ocm-sdk-go/accountsmgmt/v1" clustersmgmtv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" - serviceErrors "github.com/stackrox/acs-fleet-manager/pkg/errors" ) //go:generate moq -rm -out mocks/client_moq.go -pkg mocks . Client @@ -17,12 +16,6 @@ type Client interface { GetClusterStatus(id string) (*clustersmgmtv1.ClusterStatus, error) GetCloudProviders() (*clustersmgmtv1.CloudProviderList, error) GetRegions(provider *clustersmgmtv1.CloudProvider) (*clustersmgmtv1.CloudRegionList, error) - GetAddonInstallation(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *serviceErrors.ServiceError) - CreateAddonInstallation(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error - UpdateAddonInstallation(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error - DeleteAddonInstallation(clusterID string, addonID string) error - GetAddon(addonID string) (*clustersmgmtv1.AddOn, error) - GetAddonVersion(addonID string, version string) (*clustersmgmtv1.AddOnVersion, error) GetClusterDNS(clusterID string) (string, error) CreateIdentityProvider(clusterID string, identityProvider *clustersmgmtv1.IdentityProvider) (*clustersmgmtv1.IdentityProvider, error) DeleteCluster(clusterID string) (int, error) diff --git a/pkg/client/ocm/impl/addon_config.go b/pkg/client/ocm/impl/addon_config.go deleted file mode 100644 index 6d4ea239ff..0000000000 --- a/pkg/client/ocm/impl/addon_config.go +++ /dev/null @@ -1,60 +0,0 @@ -package impl - -import ( - "fmt" - - "github.com/spf13/pflag" - "github.com/stackrox/acs-fleet-manager/pkg/shared" -) - -// AddonConfig addon service configuration -type AddonConfig struct { - URL string - ClientID string - ClientIDFile string - ClientSecret string - ClientSecretFile string - SelfToken string - SelfTokenFile string - InheritFleetshardSyncImageTag bool - FleetshardSyncImageTag string -} - -// NewAddonConfig creates a new instance of AddonConfig -func NewAddonConfig() *AddonConfig { - return &AddonConfig{ - URL: "https://api.openshift.com", - ClientIDFile: "secrets/ocm-addon-service.clientId", - ClientSecretFile: "secrets/ocm-addon-service.clientSecret", // pragma: allowlist secret - SelfTokenFile: "secrets/ocm-addon-service.token", - InheritFleetshardSyncImageTag: true, - } -} - -// AddFlags ... -func (c *AddonConfig) AddFlags(fs *pflag.FlagSet) { - fs.StringVar(&c.ClientIDFile, "ocm-addon-client-id-file", c.ClientIDFile, "File containing OCM API privileged account client-id") - fs.StringVar(&c.ClientSecretFile, "ocm-addon-client-secret-file", c.ClientSecretFile, "File containing OCM API privileged account client-secret") - fs.StringVar(&c.SelfTokenFile, "addon-self-token-file", c.SelfTokenFile, "File containing OCM API privileged offline SSO token") - fs.StringVar(&c.URL, "ocm-addon-url", c.URL, "The base URL of the OCM API, integration by default") - fs.BoolVar(&c.InheritFleetshardSyncImageTag, "inherit-fleetshard-sync-image-tag", c.InheritFleetshardSyncImageTag, "Enable fleetshard-sync image tag") - fs.StringVar(&c.FleetshardSyncImageTag, "fleetshard-sync-image-tag", c.FleetshardSyncImageTag, "Fleetshard-sync image tag") -} - -// ReadFiles ... -func (c *AddonConfig) ReadFiles() error { - err := shared.ReadFileValueString(c.ClientIDFile, &c.ClientID) - if err != nil { - return fmt.Errorf("reading client ID file: %w", err) - } - err = shared.ReadFileValueString(c.ClientSecretFile, &c.ClientSecret) - if err != nil { - return fmt.Errorf("reading client secret file: %w", err) - } - err = shared.ReadFileValueString(c.SelfTokenFile, &c.SelfToken) - if err != nil && (c.ClientSecret == "" || c.ClientID == "") { - return fmt.Errorf("reading self token file: %w", err) - } - - return nil -} diff --git a/pkg/client/ocm/impl/client_impl.go b/pkg/client/ocm/impl/client_impl.go index d8ab118965..b1143cef24 100644 --- a/pkg/client/ocm/impl/client_impl.go +++ b/pkg/client/ocm/impl/client_impl.go @@ -279,90 +279,6 @@ func (c *client) GetRegions(provider *clustersmgmtv1.CloudProvider) (*clustersmg return regionList, nil } -func (c *client) GetAddon(addonID string) (*clustersmgmtv1.AddOn, error) { - if c.connection == nil { - return nil, serviceErrors.InvalidOCMConnection() - } - - resp, err := c.connection.ClustersMgmt().V1().Addons().Addon(addonID).Get().Send() - if err != nil { - if resp != nil && resp.Status() == http.StatusNotFound { - return nil, serviceErrors.NotFound("") - } - return nil, serviceErrors.GeneralError("sending GetAddon request: %v", err) - } - - return resp.Body(), nil -} - -func (c *client) GetAddonVersion(addonID string, versionID string) (*clustersmgmtv1.AddOnVersion, error) { - if c.connection == nil { - return nil, serviceErrors.InvalidOCMConnection() - } - - resp, err := c.connection.ClustersMgmt().V1().Addons().Addon(addonID).Versions().Version(versionID).Get().Send() - if err != nil { - if resp != nil && resp.Status() == http.StatusNotFound { - return nil, serviceErrors.NotFound("") - } - return nil, serviceErrors.GeneralError("sending GetAddonVersion request: %v", err) - } - - return resp.Body(), nil -} - -// CreateAddonInstallation creates a new addon for a cluster with given ID -func (c *client) CreateAddonInstallation(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { - if c.connection == nil { - return serviceErrors.InvalidOCMConnection() - } - _, err := c.connection.ClustersMgmt().V1().Clusters().Cluster(clusterID).Addons().Add().Body(addon).Send() - if err != nil { - return fmt.Errorf("sending CreateAddonInstallation request: %w", err) - } - return nil -} - -// GetAddonInstallation returns the addon installed on a cluster with given ID -func (c *client) GetAddonInstallation(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *serviceErrors.ServiceError) { - if c.connection == nil { - return nil, serviceErrors.InvalidOCMConnection() - } - resp, err := c.connection.ClustersMgmt().V1().Clusters().Cluster(clusterID).Addons().Addoninstallation(addonID).Get().Send() - if err != nil { - if resp != nil && resp.Status() == http.StatusNotFound { - return nil, serviceErrors.NotFound("") - } - return nil, serviceErrors.GeneralError("sending GetAddonInstallation request: %v", err) - } - - return resp.Body(), nil -} - -// UpdateAddonInstallation updates the existing addon on a cluster with given ID -func (c *client) UpdateAddonInstallation(clusterID string, addonInstallation *clustersmgmtv1.AddOnInstallation) error { - if c.connection == nil { - return serviceErrors.InvalidOCMConnection() - } - _, err := c.connection.ClustersMgmt().V1().Clusters().Cluster(clusterID).Addons().Addoninstallation(addonInstallation.ID()).Update().Body(addonInstallation).Send() - if err != nil { - return fmt.Errorf("sending UpdateAddonInstallation request: %w", err) - } - return nil -} - -// DeleteAddonInstallation deletes the addon on a cluster with given ID -func (c *client) DeleteAddonInstallation(clusterID string, addonInstallationID string) error { - if c.connection == nil { - return serviceErrors.InvalidOCMConnection() - } - _, err := c.connection.ClustersMgmt().V1().Clusters().Cluster(clusterID).Addons().Addoninstallation(addonInstallationID).Delete().Send() - if err != nil { - return fmt.Errorf("sending DeleteAddonInstallation request: %w", err) - } - return nil -} - // GetClusterDNS ... func (c *client) GetClusterDNS(clusterID string) (string, error) { if clusterID == "" { diff --git a/pkg/client/ocm/mocks/client_moq.go b/pkg/client/ocm/mocks/client_moq.go index fa37f6c724..a7a0e76689 100644 --- a/pkg/client/ocm/mocks/client_moq.go +++ b/pkg/client/ocm/mocks/client_moq.go @@ -8,7 +8,6 @@ import ( amsv1 "github.com/openshift-online/ocm-sdk-go/accountsmgmt/v1" clustersmgmtv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" "github.com/stackrox/acs-fleet-manager/pkg/client/ocm" - serviceErrors "github.com/stackrox/acs-fleet-manager/pkg/errors" "sync" ) @@ -28,18 +27,12 @@ var _ ocm.Client = &ClientMock{} // ConnectionFunc: func() *sdkClient.Connection { // panic("mock out the Connection method") // }, -// CreateAddonInstallationFunc: func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { -// panic("mock out the CreateAddonInstallation method") -// }, // CreateClusterFunc: func(cluster *clustersmgmtv1.Cluster) (*clustersmgmtv1.Cluster, error) { // panic("mock out the CreateCluster method") // }, // CreateIdentityProviderFunc: func(clusterID string, identityProvider *clustersmgmtv1.IdentityProvider) (*clustersmgmtv1.IdentityProvider, error) { // panic("mock out the CreateIdentityProvider method") // }, -// DeleteAddonInstallationFunc: func(clusterID string, addonID string) error { -// panic("mock out the DeleteAddonInstallation method") -// }, // DeleteClusterFunc: func(clusterID string) (int, error) { // panic("mock out the DeleteCluster method") // }, @@ -49,15 +42,6 @@ var _ ocm.Client = &ClientMock{} // FindSubscriptionsFunc: func(query string) (*amsv1.SubscriptionsListResponse, error) { // panic("mock out the FindSubscriptions method") // }, -// GetAddonFunc: func(addonID string) (*clustersmgmtv1.AddOn, error) { -// panic("mock out the GetAddon method") -// }, -// GetAddonInstallationFunc: func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *serviceErrors.ServiceError) { -// panic("mock out the GetAddonInstallation method") -// }, -// GetAddonVersionFunc: func(addonID string, version string) (*clustersmgmtv1.AddOnVersion, error) { -// panic("mock out the GetAddonVersion method") -// }, // GetCloudProvidersFunc: func() (*clustersmgmtv1.CloudProviderList, error) { // panic("mock out the GetCloudProviders method") // }, @@ -94,9 +78,6 @@ var _ ocm.Client = &ClientMock{} // GetRequiresTermsAcceptanceFunc: func(username string) (bool, string, error) { // panic("mock out the GetRequiresTermsAcceptance method") // }, -// UpdateAddonInstallationFunc: func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { -// panic("mock out the UpdateAddonInstallation method") -// }, // } // // // use mockedClient in code that requires ocm.Client @@ -110,18 +91,12 @@ type ClientMock struct { // ConnectionFunc mocks the Connection method. ConnectionFunc func() *sdkClient.Connection - // CreateAddonInstallationFunc mocks the CreateAddonInstallation method. - CreateAddonInstallationFunc func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error - // CreateClusterFunc mocks the CreateCluster method. CreateClusterFunc func(cluster *clustersmgmtv1.Cluster) (*clustersmgmtv1.Cluster, error) // CreateIdentityProviderFunc mocks the CreateIdentityProvider method. CreateIdentityProviderFunc func(clusterID string, identityProvider *clustersmgmtv1.IdentityProvider) (*clustersmgmtv1.IdentityProvider, error) - // DeleteAddonInstallationFunc mocks the DeleteAddonInstallation method. - DeleteAddonInstallationFunc func(clusterID string, addonID string) error - // DeleteClusterFunc mocks the DeleteCluster method. DeleteClusterFunc func(clusterID string) (int, error) @@ -131,15 +106,6 @@ type ClientMock struct { // FindSubscriptionsFunc mocks the FindSubscriptions method. FindSubscriptionsFunc func(query string) (*amsv1.SubscriptionsListResponse, error) - // GetAddonFunc mocks the GetAddon method. - GetAddonFunc func(addonID string) (*clustersmgmtv1.AddOn, error) - - // GetAddonInstallationFunc mocks the GetAddonInstallation method. - GetAddonInstallationFunc func(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *serviceErrors.ServiceError) - - // GetAddonVersionFunc mocks the GetAddonVersion method. - GetAddonVersionFunc func(addonID string, version string) (*clustersmgmtv1.AddOnVersion, error) - // GetCloudProvidersFunc mocks the GetCloudProviders method. GetCloudProvidersFunc func() (*clustersmgmtv1.CloudProviderList, error) @@ -176,9 +142,6 @@ type ClientMock struct { // GetRequiresTermsAcceptanceFunc mocks the GetRequiresTermsAcceptance method. GetRequiresTermsAcceptanceFunc func(username string) (bool, string, error) - // UpdateAddonInstallationFunc mocks the UpdateAddonInstallation method. - UpdateAddonInstallationFunc func(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error - // calls tracks calls to the methods. calls struct { // ClusterAuthorization holds details about calls to the ClusterAuthorization method. @@ -189,13 +152,6 @@ type ClientMock struct { // Connection holds details about calls to the Connection method. Connection []struct { } - // CreateAddonInstallation holds details about calls to the CreateAddonInstallation method. - CreateAddonInstallation []struct { - // ClusterID is the clusterID argument value. - ClusterID string - // Addon is the addon argument value. - Addon *clustersmgmtv1.AddOnInstallation - } // CreateCluster holds details about calls to the CreateCluster method. CreateCluster []struct { // Cluster is the cluster argument value. @@ -208,13 +164,6 @@ type ClientMock struct { // IdentityProvider is the identityProvider argument value. IdentityProvider *clustersmgmtv1.IdentityProvider } - // DeleteAddonInstallation holds details about calls to the DeleteAddonInstallation method. - DeleteAddonInstallation []struct { - // ClusterID is the clusterID argument value. - ClusterID string - // AddonID is the addonID argument value. - AddonID string - } // DeleteCluster holds details about calls to the DeleteCluster method. DeleteCluster []struct { // ClusterID is the clusterID argument value. @@ -230,25 +179,6 @@ type ClientMock struct { // Query is the query argument value. Query string } - // GetAddon holds details about calls to the GetAddon method. - GetAddon []struct { - // AddonID is the addonID argument value. - AddonID string - } - // GetAddonInstallation holds details about calls to the GetAddonInstallation method. - GetAddonInstallation []struct { - // ClusterID is the clusterID argument value. - ClusterID string - // AddonID is the addonID argument value. - AddonID string - } - // GetAddonVersion holds details about calls to the GetAddonVersion method. - GetAddonVersion []struct { - // AddonID is the addonID argument value. - AddonID string - // Version is the version argument value. - Version string - } // GetCloudProviders holds details about calls to the GetCloudProviders method. GetCloudProviders []struct { } @@ -313,26 +243,14 @@ type ClientMock struct { // Username is the username argument value. Username string } - // UpdateAddonInstallation holds details about calls to the UpdateAddonInstallation method. - UpdateAddonInstallation []struct { - // ClusterID is the clusterID argument value. - ClusterID string - // Addon is the addon argument value. - Addon *clustersmgmtv1.AddOnInstallation - } } lockClusterAuthorization sync.RWMutex lockConnection sync.RWMutex - lockCreateAddonInstallation sync.RWMutex lockCreateCluster sync.RWMutex lockCreateIdentityProvider sync.RWMutex - lockDeleteAddonInstallation sync.RWMutex lockDeleteCluster sync.RWMutex lockDeleteSubscription sync.RWMutex lockFindSubscriptions sync.RWMutex - lockGetAddon sync.RWMutex - lockGetAddonInstallation sync.RWMutex - lockGetAddonVersion sync.RWMutex lockGetCloudProviders sync.RWMutex lockGetCluster sync.RWMutex lockGetClusterDNS sync.RWMutex @@ -345,7 +263,6 @@ type ClientMock struct { lockGetQuotaCostsForProduct sync.RWMutex lockGetRegions sync.RWMutex lockGetRequiresTermsAcceptance sync.RWMutex - lockUpdateAddonInstallation sync.RWMutex } // ClusterAuthorization calls ClusterAuthorizationFunc. @@ -407,42 +324,6 @@ func (mock *ClientMock) ConnectionCalls() []struct { return calls } -// CreateAddonInstallation calls CreateAddonInstallationFunc. -func (mock *ClientMock) CreateAddonInstallation(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { - if mock.CreateAddonInstallationFunc == nil { - panic("ClientMock.CreateAddonInstallationFunc: method is nil but Client.CreateAddonInstallation was just called") - } - callInfo := struct { - ClusterID string - Addon *clustersmgmtv1.AddOnInstallation - }{ - ClusterID: clusterID, - Addon: addon, - } - mock.lockCreateAddonInstallation.Lock() - mock.calls.CreateAddonInstallation = append(mock.calls.CreateAddonInstallation, callInfo) - mock.lockCreateAddonInstallation.Unlock() - return mock.CreateAddonInstallationFunc(clusterID, addon) -} - -// CreateAddonInstallationCalls gets all the calls that were made to CreateAddonInstallation. -// Check the length with: -// -// len(mockedClient.CreateAddonInstallationCalls()) -func (mock *ClientMock) CreateAddonInstallationCalls() []struct { - ClusterID string - Addon *clustersmgmtv1.AddOnInstallation -} { - var calls []struct { - ClusterID string - Addon *clustersmgmtv1.AddOnInstallation - } - mock.lockCreateAddonInstallation.RLock() - calls = mock.calls.CreateAddonInstallation - mock.lockCreateAddonInstallation.RUnlock() - return calls -} - // CreateCluster calls CreateClusterFunc. func (mock *ClientMock) CreateCluster(cluster *clustersmgmtv1.Cluster) (*clustersmgmtv1.Cluster, error) { if mock.CreateClusterFunc == nil { @@ -511,42 +392,6 @@ func (mock *ClientMock) CreateIdentityProviderCalls() []struct { return calls } -// DeleteAddonInstallation calls DeleteAddonInstallationFunc. -func (mock *ClientMock) DeleteAddonInstallation(clusterID string, addonID string) error { - if mock.DeleteAddonInstallationFunc == nil { - panic("ClientMock.DeleteAddonInstallationFunc: method is nil but Client.DeleteAddonInstallation was just called") - } - callInfo := struct { - ClusterID string - AddonID string - }{ - ClusterID: clusterID, - AddonID: addonID, - } - mock.lockDeleteAddonInstallation.Lock() - mock.calls.DeleteAddonInstallation = append(mock.calls.DeleteAddonInstallation, callInfo) - mock.lockDeleteAddonInstallation.Unlock() - return mock.DeleteAddonInstallationFunc(clusterID, addonID) -} - -// DeleteAddonInstallationCalls gets all the calls that were made to DeleteAddonInstallation. -// Check the length with: -// -// len(mockedClient.DeleteAddonInstallationCalls()) -func (mock *ClientMock) DeleteAddonInstallationCalls() []struct { - ClusterID string - AddonID string -} { - var calls []struct { - ClusterID string - AddonID string - } - mock.lockDeleteAddonInstallation.RLock() - calls = mock.calls.DeleteAddonInstallation - mock.lockDeleteAddonInstallation.RUnlock() - return calls -} - // DeleteCluster calls DeleteClusterFunc. func (mock *ClientMock) DeleteCluster(clusterID string) (int, error) { if mock.DeleteClusterFunc == nil { @@ -643,110 +488,6 @@ func (mock *ClientMock) FindSubscriptionsCalls() []struct { return calls } -// GetAddon calls GetAddonFunc. -func (mock *ClientMock) GetAddon(addonID string) (*clustersmgmtv1.AddOn, error) { - if mock.GetAddonFunc == nil { - panic("ClientMock.GetAddonFunc: method is nil but Client.GetAddon was just called") - } - callInfo := struct { - AddonID string - }{ - AddonID: addonID, - } - mock.lockGetAddon.Lock() - mock.calls.GetAddon = append(mock.calls.GetAddon, callInfo) - mock.lockGetAddon.Unlock() - return mock.GetAddonFunc(addonID) -} - -// GetAddonCalls gets all the calls that were made to GetAddon. -// Check the length with: -// -// len(mockedClient.GetAddonCalls()) -func (mock *ClientMock) GetAddonCalls() []struct { - AddonID string -} { - var calls []struct { - AddonID string - } - mock.lockGetAddon.RLock() - calls = mock.calls.GetAddon - mock.lockGetAddon.RUnlock() - return calls -} - -// GetAddonInstallation calls GetAddonInstallationFunc. -func (mock *ClientMock) GetAddonInstallation(clusterID string, addonID string) (*clustersmgmtv1.AddOnInstallation, *serviceErrors.ServiceError) { - if mock.GetAddonInstallationFunc == nil { - panic("ClientMock.GetAddonInstallationFunc: method is nil but Client.GetAddonInstallation was just called") - } - callInfo := struct { - ClusterID string - AddonID string - }{ - ClusterID: clusterID, - AddonID: addonID, - } - mock.lockGetAddonInstallation.Lock() - mock.calls.GetAddonInstallation = append(mock.calls.GetAddonInstallation, callInfo) - mock.lockGetAddonInstallation.Unlock() - return mock.GetAddonInstallationFunc(clusterID, addonID) -} - -// GetAddonInstallationCalls gets all the calls that were made to GetAddonInstallation. -// Check the length with: -// -// len(mockedClient.GetAddonInstallationCalls()) -func (mock *ClientMock) GetAddonInstallationCalls() []struct { - ClusterID string - AddonID string -} { - var calls []struct { - ClusterID string - AddonID string - } - mock.lockGetAddonInstallation.RLock() - calls = mock.calls.GetAddonInstallation - mock.lockGetAddonInstallation.RUnlock() - return calls -} - -// GetAddonVersion calls GetAddonVersionFunc. -func (mock *ClientMock) GetAddonVersion(addonID string, version string) (*clustersmgmtv1.AddOnVersion, error) { - if mock.GetAddonVersionFunc == nil { - panic("ClientMock.GetAddonVersionFunc: method is nil but Client.GetAddonVersion was just called") - } - callInfo := struct { - AddonID string - Version string - }{ - AddonID: addonID, - Version: version, - } - mock.lockGetAddonVersion.Lock() - mock.calls.GetAddonVersion = append(mock.calls.GetAddonVersion, callInfo) - mock.lockGetAddonVersion.Unlock() - return mock.GetAddonVersionFunc(addonID, version) -} - -// GetAddonVersionCalls gets all the calls that were made to GetAddonVersion. -// Check the length with: -// -// len(mockedClient.GetAddonVersionCalls()) -func (mock *ClientMock) GetAddonVersionCalls() []struct { - AddonID string - Version string -} { - var calls []struct { - AddonID string - Version string - } - mock.lockGetAddonVersion.RLock() - calls = mock.calls.GetAddonVersion - mock.lockGetAddonVersion.RUnlock() - return calls -} - // GetCloudProviders calls GetCloudProvidersFunc. func (mock *ClientMock) GetCloudProviders() (*clustersmgmtv1.CloudProviderList, error) { if mock.GetCloudProvidersFunc == nil { @@ -1137,39 +878,3 @@ func (mock *ClientMock) GetRequiresTermsAcceptanceCalls() []struct { mock.lockGetRequiresTermsAcceptance.RUnlock() return calls } - -// UpdateAddonInstallation calls UpdateAddonInstallationFunc. -func (mock *ClientMock) UpdateAddonInstallation(clusterID string, addon *clustersmgmtv1.AddOnInstallation) error { - if mock.UpdateAddonInstallationFunc == nil { - panic("ClientMock.UpdateAddonInstallationFunc: method is nil but Client.UpdateAddonInstallation was just called") - } - callInfo := struct { - ClusterID string - Addon *clustersmgmtv1.AddOnInstallation - }{ - ClusterID: clusterID, - Addon: addon, - } - mock.lockUpdateAddonInstallation.Lock() - mock.calls.UpdateAddonInstallation = append(mock.calls.UpdateAddonInstallation, callInfo) - mock.lockUpdateAddonInstallation.Unlock() - return mock.UpdateAddonInstallationFunc(clusterID, addon) -} - -// UpdateAddonInstallationCalls gets all the calls that were made to UpdateAddonInstallation. -// Check the length with: -// -// len(mockedClient.UpdateAddonInstallationCalls()) -func (mock *ClientMock) UpdateAddonInstallationCalls() []struct { - ClusterID string - Addon *clustersmgmtv1.AddOnInstallation -} { - var calls []struct { - ClusterID string - Addon *clustersmgmtv1.AddOnInstallation - } - mock.lockUpdateAddonInstallation.RLock() - calls = mock.calls.UpdateAddonInstallation - mock.lockUpdateAddonInstallation.RUnlock() - return calls -} diff --git a/pkg/features/list.go b/pkg/features/list.go index 0eb1103782..7045d7e727 100644 --- a/pkg/features/list.go +++ b/pkg/features/list.go @@ -7,9 +7,6 @@ var ( // GitOpsCentrals enables the GitOps for Central instances GitOpsCentrals = registerFeature("GitOps for Central instances", "RHACS_GITOPS_ENABLED", true) - // AddonAutoUpgrade enables addon auto upgrade feature - AddonAutoUpgrade = registerFeature("Addon auto upgrade", "RHACS_ADDON_AUTO_UPGRADE", true) - // ClusterMigration enables the feature to migrate a tenant to another cluster ClusterMigration = registerFeature("Cluster migraiton", "RHACS_CLUSTER_MIGRATION", true) ) diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index 59957bd7e3..2eb3219224 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -68,9 +68,6 @@ const ( // ClusterStatusCapacityUsed - metric name for the current number of instances ClusterStatusCapacityUsed = "cluster_status_capacity_used" - // ClusterAddonStatusMetric - metric name for the cluster addon status represented by ClusterAddonStatus - ClusterAddonStatusMetric = "cluster_addon_status" - // GitopsConfigProviderErrorCount - metric name for the number of errors encountered while fetching GitOps config GitopsConfigProviderErrorCount = "gitops_config_provider_error_count" @@ -156,11 +153,6 @@ var clusterStatusCapacityLabels = []string{ LabelClusterID, } -var clusterAddonStatusLabels = []string{ - LabelID, - LabelClusterName, -} - // #### Metrics for Dataplane clusters - Start #### // create a new histogramVec for cluster creation duration var requestClusterCreationDurationMetric = prometheus.NewHistogramVec( @@ -630,37 +622,6 @@ func init() { GitopsConfigProviderErrorCounter.WithLabelValues().Add(0) } -// AddonStatus represents the status of the addon installation on a Data Plane cluster -type AddonStatus int - -const ( - // AddonHealthy the addon is healthy and up-to-date with the existing config - AddonHealthy AddonStatus = iota - // AddonUpgrade the addon is upgrading - AddonUpgrade - // AddonUnhealthy the addon is unhealthy, something goes wrong - AddonUnhealthy -) - -// clusterAddonStatusMetric create a new GaugeVec for cluster addon upgrade started timestamp -var clusterAddonStatusMetric = prometheus.NewGaugeVec( - prometheus.GaugeOpts{ - Subsystem: FleetManager, - Name: ClusterAddonStatusMetric, - Help: "metric name for the time period after the addon is upgraded in OCM but not yet installed on a cluster in seconds", - }, - clusterAddonStatusLabels, -) - -// UpdateClusterAddonStatusMetric updates ClusterAddonStatusMetric Metric -func UpdateClusterAddonStatusMetric(addonID, clusterName string, status AddonStatus) { - labels := prometheus.Labels{ - LabelID: addonID, - LabelClusterName: clusterName, - } - clusterAddonStatusMetric.With(labels).Set(float64(status)) -} - // UpdateDatabaseQueryDurationMetric Update the observatorium request duration metric with the following labels: // - status: (i.e. "success" or "failure") // - queryType: (i.e. "SELECT", "UPDATE", "INSERT", "DELETE") @@ -685,7 +646,6 @@ func init() { prometheus.MustRegister(centralPerClusterCountMetric) prometheus.MustRegister(clusterStatusCapacityMaxMetric) prometheus.MustRegister(clusterStatusCapacityUsedMetric) - prometheus.MustRegister(clusterAddonStatusMetric) prometheus.MustRegister(GitopsConfigProviderErrorCounter) // metrics for Centrals @@ -745,7 +705,6 @@ func Reset() { centralPerClusterCountMetric.Reset() clusterStatusCapacityMaxMetric.Reset() clusterStatusCapacityUsedMetric.Reset() - clusterAddonStatusMetric.Reset() GitopsConfigProviderErrorCounter.Reset() requestCentralCreationDurationMetric.Reset() diff --git a/pkg/providers/core.go b/pkg/providers/core.go index ab9cdaca97..a049a28cc7 100644 --- a/pkg/providers/core.go +++ b/pkg/providers/core.go @@ -34,7 +34,6 @@ func CoreConfigProviders() di.Option { di.Provide(db.NewDatabaseConfig, di.As(new(environments.ConfigModule))), di.Provide(server.NewServerConfig, di.As(new(environments.ConfigModule))), di.Provide(ocm.NewOCMConfig, di.As(new(environments.ConfigModule))), - di.Provide(ocm.NewAddonConfig, di.As(new(environments.ConfigModule))), di.Provide(iam.NewIAMConfig, di.As(new(environments.ConfigModule))), di.Provide(acl.NewAccessControlListConfig, di.As(new(environments.ConfigModule))), di.Provide(quotamanagement.NewQuotaManagementListConfig, di.As(new(environments.ConfigModule))), diff --git a/pkg/shared/addon.go b/pkg/shared/addon.go deleted file mode 100644 index 55d37b3fda..0000000000 --- a/pkg/shared/addon.go +++ /dev/null @@ -1,38 +0,0 @@ -package shared - -import ( - "crypto/sha256" - "fmt" - "sort" - - "golang.org/x/exp/maps" -) - -// AddonParameters addon parameters -type AddonParameters map[string]string - -// Addon contains information about the addons on the cluster -type Addon struct { - ID string - Version string - SourceImage string - PackageImage string - Parameters AddonParameters -} - -// SHA256Sum returns SHA256 checksum of the addon parameters -func (p AddonParameters) SHA256Sum() string { - keys := maps.Keys(p) - sort.Strings(keys) // to make hash generation deterministic - - h := sha256.New() - - for _, k := range keys { - v := p[k] - b := sha256.Sum256([]byte(k)) - h.Write(b[:]) - b = sha256.Sum256([]byte(v)) - h.Write(b[:]) - } - return fmt.Sprintf("%x", h.Sum(nil)) -} diff --git a/pkg/shared/addon_test.go b/pkg/shared/addon_test.go deleted file mode 100644 index c3e4de7bb2..0000000000 --- a/pkg/shared/addon_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package shared - -import ( - "testing" - - . "github.com/onsi/gomega" -) - -func TestParametersSHA256Sum(t *testing.T) { - RegisterTestingT(t) - addon := Addon{ - Parameters: map[string]string{ - "acscsEnvironment": "test", - "fleetshardSyncFleetManagerEndpoint": "http://localhost:8000", - "fleetshardSyncResourcesLimitsCpu": "500m", - "fleetshardSyncResourcesLimitsMemory": "512Mi", - "fleetshardSyncResourcesRequestsCpu": "200m", - "fleetshardSyncResourcesRequestsMemory": "512Mi", - }, - } - - Expect(addon.Parameters.SHA256Sum()).To(Equal("d6b805642f9227dd0424814728a96894b301d2d97d0a197e5fe8735ea5ea15ed")) // pragma: allowlist secret -} diff --git a/templates/secrets-template.yml b/templates/secrets-template.yml index a6afd3d3cd..5843924d67 100644 --- a/templates/secrets-template.yml +++ b/templates/secrets-template.yml @@ -41,16 +41,6 @@ parameters: - name: OCM_SERVICE_TOKEN description: Offline token used to interact with other UHC services -- name: OCM_ADDON_SERVICE_CLIENT_ID - description: Client id used to interact with OCM Addon Service - -- name: OCM_ADDON_SERVICE_CLIENT_SECRET - description: Client secret used to interact with OCM Addon Service - -- name: OCM_ADDON_SERVICE_TOKEN - description: Offline token used to interact with OCM Addon Service - - - name: AWS_ACCESS_KEY description: AWS access key used to create CCS clusters @@ -95,9 +85,6 @@ objects: ocm-service.clientId: ${OCM_SERVICE_CLIENT_ID} ocm-service.clientSecret: ${OCM_SERVICE_CLIENT_SECRET} ocm-service.token: ${OCM_SERVICE_TOKEN} - ocm-addon-service.clientId: ${OCM_ADDON_SERVICE_CLIENT_ID} - ocm-addon-service.clientSecret: ${OCM_ADDON_SERVICE_CLIENT_SECRET} - ocm-addon-service.token: ${OCM_ADDON_SERVICE_TOKEN} aws.accesskey: ${AWS_ACCESS_KEY} aws.accountid: ${AWS_ACCOUNT_ID} aws.secretaccesskey: ${AWS_SECRET_ACCESS_KEY} diff --git a/templates/service-template.yml b/templates/service-template.yml index 55c306ad6b..182e0eeb4d 100644 --- a/templates/service-template.yml +++ b/templates/service-template.yml @@ -316,14 +316,6 @@ parameters: description: Enable leader election value: "true" -- name: OCM_ADDON_SERVICE_URL - displayName: The base URL of the OCM API for the addon service - value: "https://api.openshift.com" - -- name: OCM_ADDON_SERVICE_INHERIT_FLEETSHARD_SYNC_IMAGE_TAG - description: Sets the provided fleetshard image tag if the addon parameter value is 'inherit'" - value: "true" - - name: DATAPLANE_OIDC_ISSUERS description: List of DataPlane OpenID Connect issuers that should be verified for issued tokens. value: "[]" @@ -896,12 +888,6 @@ objects: - --central-idp-issuer=${CENTRAL_IDP_ISSUER} - --ocm-client-id-file=/secrets/fleet-manager-credentials/ocm-service.clientId - --ocm-client-secret-file=/secrets/fleet-manager-credentials/ocm-service.clientSecret - - --ocm-addon-url=${OCM_ADDON_SERVICE_URL} - - --ocm-addon-client-id-file=/secrets/fleet-manager-credentials/ocm-addon-service.clientId - - --ocm-addon-client-secret-file=/secrets/fleet-manager-credentials/ocm-addon-service.clientSecret - - --inherit-fleetshard-sync-image-tag=${OCM_ADDON_SERVICE_INHERIT_FLEETSHARD_SYNC_IMAGE_TAG} - - --addon-self-token-file=/secrets/fleet-manager-credentials/ocm-addon-service.token - - --fleetshard-sync-image-tag=${IMAGE_TAG} - --self-token-file=/secrets/service/ocm-service.token - --ocm-base-url=${OCM_URL} - --ams-base-url=${AMS_URL} diff --git a/test/mocks/api_server.go b/test/mocks/api_server.go index 510fe09408..906616c594 100644 --- a/test/mocks/api_server.go +++ b/test/mocks/api_server.go @@ -55,8 +55,6 @@ const ( EndpointPathCloudProviderRegion = "/api/clusters_mgmt/v1/cloud_providers/{providerID}/regions/{regionID}" // EndpointPathClusterStatus ocm cluster management cluster status endpoint EndpointPathClusterStatus = "/api/clusters_mgmt/v1/clusters/{id}/status" - // EndpointPathClusterAddons ocm cluster management cluster addons endpoint - EndpointPathClusterAddons = "/api/clusters_mgmt/v1/clusters/{id}/addons" // EndpointPathMachinePools ocm cluster management machine pools endpoint EndpointPathMachinePools = "/api/clusters_mgmt/v1/clusters/{id}/machine_pools" // EndpointPathMachinePool ocm cluster management machine pool endpoint @@ -94,12 +92,6 @@ const ( MockIngressHref = "/api/clusters_mgmt/v1/clusters/000/ingresses/i8y1" // MockIngressListening default mock ingress listening used in the mock ocm server MockIngressListening = clustersmgmtv1.ListeningMethodExternal - // MockClusterAddonID default mock cluster addon ID - MockClusterAddonID = "acs-fleetshard-dev" - // MockClusterAddonState default mock cluster addon state - MockClusterAddonState = clustersmgmtv1.AddOnInstallationStateReady - // MockClusterAddonDescription default mock cluster addon description - MockClusterAddonDescription = "InstallWaiting" // MockMachinePoolID default machine pool ID MockMachinePoolID = "managed" // MockMachinePoolReplicas default number of machine pool replicas @@ -133,8 +125,6 @@ var ( EndpointCloudProviderRegionsGet = Endpoint{EndpointPathCloudProviderRegions, http.MethodGet} EndpointCloudProviderRegionGet = Endpoint{EndpointPathCloudProviderRegion, http.MethodGet} EndpointClusterStatusGet = Endpoint{EndpointPathClusterStatus, http.MethodGet} - EndpointClusterAddonsGet = Endpoint{EndpointPathClusterAddons, http.MethodGet} - EndpointClusterAddonPost = Endpoint{EndpointPathClusterAddons, http.MethodPost} EndpointMachinePoolsGet = Endpoint{EndpointPathMachinePools, http.MethodGet} EndpointMachinePoolPost = Endpoint{EndpointPathMachinePools, http.MethodPost} EndpointMachinePoolPatch = Endpoint{EndpointPathMachinePool, http.MethodPatch} @@ -153,23 +143,21 @@ var ( // to override these values, do not set them directly e.g. mocks.MockSyncset = ... // instead use the Set*Response functions provided by MockConfigurableServerBuilder e.g. SetClusterGetResponse(...) var ( - MockIdentityProvider *clustersmgmtv1.IdentityProvider - MockSyncset *clustersmgmtv1.Syncset - MockIngressList *clustersmgmtv1.IngressList - MockCloudProvider *clustersmgmtv1.CloudProvider - MockCloudProviderList *clustersmgmtv1.CloudProviderList - MockCloudProviderRegion *clustersmgmtv1.CloudRegion - MockCloudProviderRegionList *clustersmgmtv1.CloudRegionList - MockClusterStatus *clustersmgmtv1.ClusterStatus - MockClusterAddonInstallation *clustersmgmtv1.AddOnInstallation - MockClusterAddonInstallationList *clustersmgmtv1.AddOnInstallationList - MockMachinePoolList *clustersmgmtv1.MachinePoolList - MockMachinePool *clustersmgmtv1.MachinePool - MockCluster *clustersmgmtv1.Cluster - MockClusterAuthorization *amsv1.ClusterAuthorizationResponse - MockSubscription *amsv1.Subscription - MockSubscriptionSearch []*amsv1.Subscription - MockTermsReview *authorizationsv1.TermsReviewResponse + MockIdentityProvider *clustersmgmtv1.IdentityProvider + MockSyncset *clustersmgmtv1.Syncset + MockIngressList *clustersmgmtv1.IngressList + MockCloudProvider *clustersmgmtv1.CloudProvider + MockCloudProviderList *clustersmgmtv1.CloudProviderList + MockCloudProviderRegion *clustersmgmtv1.CloudRegion + MockCloudProviderRegionList *clustersmgmtv1.CloudRegionList + MockClusterStatus *clustersmgmtv1.ClusterStatus + MockMachinePoolList *clustersmgmtv1.MachinePoolList + MockMachinePool *clustersmgmtv1.MachinePool + MockCluster *clustersmgmtv1.Cluster + MockClusterAuthorization *amsv1.ClusterAuthorizationResponse + MockSubscription *amsv1.Subscription + MockSubscriptionSearch []*amsv1.Subscription + MockTermsReview *authorizationsv1.TermsReviewResponse ) // routerSwapper is an http.Handler that allows you to swap mux routers. @@ -288,8 +276,6 @@ func getDefaultHandlerRegister() (HandlerRegister, error) { EndpointCloudProviderRegionsGet: buildMockRequestHandler(MockCloudProviderRegionList, nil), EndpointCloudProviderRegionGet: buildMockRequestHandler(MockCloudProviderRegion, nil), EndpointClusterStatusGet: buildMockRequestHandler(MockClusterStatus, nil), - EndpointClusterAddonsGet: buildMockRequestHandler(MockClusterAddonInstallationList, nil), - EndpointClusterAddonPost: buildMockRequestHandler(MockClusterAddonInstallation, nil), EndpointMachinePoolsGet: buildMockRequestHandler(MockMachinePoolList, nil), EndpointMachinePoolGet: buildMockRequestHandler(MockMachinePool, nil), EndpointMachinePoolPatch: buildMockRequestHandler(MockMachinePool, nil), @@ -427,29 +413,6 @@ func marshalOCMType(t interface{}, w io.Writer) error { return fmt.Errorf("encoding CloudRegionList: %w", err) } return nil - // handle cluster addon installations - case *clustersmgmtv1.AddOnInstallation: - err := clustersmgmtv1.MarshalAddOnInstallation(v, w) - if err != nil { - return fmt.Errorf("marshalling AddOnInstallation: %w", err) - } - return nil - case []*clustersmgmtv1.AddOnInstallation: - err := clustersmgmtv1.MarshalAddOnInstallationList(v, w) - if err != nil { - return fmt.Errorf("marshalling AddOnInstallationList: %w", err) - } - return nil - case *clustersmgmtv1.AddOnInstallationList: - ocmList, err := NewOCMList().WithItems(v.Slice()) - if err != nil { - return err - } - err = json.NewEncoder(w).Encode(ocmList) - if err != nil { - return fmt.Errorf("encoding AddOnInstallationList: %w", err) - } - return nil case *clustersmgmtv1.MachinePool: err := clustersmgmtv1.MarshalMachinePool(v, w) if err != nil { @@ -632,14 +595,6 @@ func init() { if err != nil { panic(err) } - MockClusterAddonInstallation, err = GetMockClusterAddonInstallation(nil, "") - if err != nil { - panic(err) - } - MockClusterAddonInstallationList, err = GetMockClusterAddonInstallationList(nil) - if err != nil { - panic(err) - } MockCluster, err = GetMockCluster(nil) if err != nil { panic(err) @@ -840,65 +795,6 @@ func GetMockClusterStatusBuilder(modifyFn func(*clustersmgmtv1.ClusterStatusBuil return builder } -// GetMockClusterAddonBuilder for emulated OCM server -func GetMockClusterAddonBuilder(modifyFn func(*clustersmgmtv1.AddOnBuilder), addonID string) *clustersmgmtv1.AddOnBuilder { - if addonID == "" { - addonID = MockClusterAddonID - } - - builder := clustersmgmtv1.NewAddOn(). - ID(addonID). - HREF(fmt.Sprintf("/api/clusters_mgmt/v1/addons/%s", addonID)) - if modifyFn != nil { - modifyFn(builder) - } - return builder -} - -// GetMockClusterAddonInstallationBuilder for emulated OCM server -func GetMockClusterAddonInstallationBuilder(modifyFn func(*clustersmgmtv1.AddOnInstallationBuilder), addonID string) *clustersmgmtv1.AddOnInstallationBuilder { - if addonID == "" { - addonID = MockClusterAddonID - } - addonInstallation := clustersmgmtv1.NewAddOnInstallation(). - ID(addonID). - HREF(fmt.Sprintf("/api/clusters_mgmt/v1/clusters/%s/addons/%s", MockClusterID, addonID)). - Addon(GetMockClusterAddonBuilder(nil, addonID)). - State(MockClusterAddonState). - StateDescription(MockClusterAddonDescription) - - if modifyFn != nil { - modifyFn(addonInstallation) - } - return addonInstallation -} - -// GetMockClusterAddonInstallation for emulated OCM server -func GetMockClusterAddonInstallation(modifyFn func(*clustersmgmtv1.AddOnInstallation, error), addonID string) (*clustersmgmtv1.AddOnInstallation, error) { - addonInstall, err := GetMockClusterAddonInstallationBuilder(nil, addonID).Build() - if modifyFn != nil { - modifyFn(addonInstall, err) - } - if err != nil { - return addonInstall, fmt.Errorf("building AddOnInstallation: %w", err) - } - return addonInstall, nil -} - -// GetMockClusterAddonInstallationList for emulated OCM server -func GetMockClusterAddonInstallationList(modifyFn func(*clustersmgmtv1.AddOnInstallationList, error)) (*clustersmgmtv1.AddOnInstallationList, error) { - list, err := clustersmgmtv1.NewAddOnInstallationList().Items( - GetMockClusterAddonInstallationBuilder(nil, MockClusterAddonID)). - Build() - if modifyFn != nil { - modifyFn(list, err) - } - if err != nil { - return list, fmt.Errorf("building AddOnInstallationList: %w", err) - } - return list, nil -} - // GetMockClusterNodesBuilder for emulated OCM server func GetMockClusterNodesBuilder(modifyFn func(*clustersmgmtv1.ClusterNodesBuilder)) *clustersmgmtv1.ClusterNodesBuilder { builder := clustersmgmtv1.NewClusterNodes().