This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Greenhouse API

This section of the Greenhouse documentation aims to help you learn more about the different API resources and how they are used.

1 - Organizations

An Organization is the top-level entity within Greenhouse. Each Organization represents a different tenant within Greenhouse and is provided with a dedicated Namespace in the Greenhouse cluster.

Example Organization Spec

apiVersion: greenhouse.sap/v1alpha1
kind: Organization
metadata:
  name: example-organization
spec:
  authentication:
    oidc:
      issuer: https://accounts.example.com
      clientId: example-client-id

Writing an Organization Spec

DisplayName

.spec.displayName is a human-friendly name for the Organization. This field is optional; if not provided, it defaults to the value of metadata.name.

Authentication

OIDC

.spec.authentication.oidc is used to configure how members of the Organization will authenticate to Greenhouse. Greenhouse IDProxy is using Dex to provide the OIDC authentication for multiple Organizations. Each Organization receives their own Dex connector.

The config requires issuer, the URL of the identity provider, and clientIDReference and clientSecretReference, which reference Kubernetes Secrets containing the OIDC client ID and client secret, respectively.

spec:
  authentication:
    oidc:
      issuer: https://accounts.example.com
      clientIdReference:
        name: oidc-client-id-secret
        key: client-id
      clientSecretReference:
        name: oidc-client-secret
        key: client-secret

.authentication.oidc.redirectURI is an optional field to specify a custom redirect URI for OIDC authentication. If not provided, it defaults to the Greenhouse ID Proxy (auth.<greenhouse domain name>).

.authentication.oidc.oauth2ClientRedirectURIs is an optional list of URIs that are added to the Dex connector as allowed redirect URIs for OAuth2 clients.

SCIM

.spec.authentication.scim is used by Greenhouse to retrieve the members of a Team from the Organization’s identity provider. This field is optional; if not provided, Greenhouse will not attempt to sync users via SCIM.

The configuration requires baseURL, the URL of the SCIM endpoint, and authType, which specifies the authentication method to use when connecting to the SCIM endpoint. Supported methods are basic and token.

spec:
  authentication:
    scim:
      baseURL: https://scim.example.com
      authType: token
      bearerToken:
        secret:
          name: scim-bearer-token-secret
          key: bearer-token
      bearerPrefix: Bearer
      bearerHeader: Authorization

.authentication.scim.bearerPrefix is an optional field to specify a custom prefix for the bearer token in the authorization header. If not provided, it defaults to Bearer.

.authentication.scim.bearerHeader is an optional field to specify a custom header name for the bearer token. If not provided, it defaults to Authorization.

MappedOrgAdminIdPGroup

.spec.mappedOrgAdminIdPGroup is an optional field that specifies the name of an identity provider group whose members will be granted Organization Admin privileges within Greenhouse. If this field is not provided, no users will be granted Organization Admin privileges.

Working with Organizations

Role-Based Access Control within the Organization namespace

Greenhouse provisions a set of default Roles and RoleBindings within each Organization’s Namespace to facilitate Role-Based Access Control (RBAC). These roles can be used by the Organization Admins as a starting point to manage access to resources within their Organization.

The following roles are seeded for each Organization:

NameDescriptionApiGroupsResourcesVerbsCluster scoped
role:<org-name>:adminAn admin of a Greenhouse Organization. This entails the permissions of role:<org-name>:cluster-admin and role:<org-name>:plugin-admingreenhouse.sap/v1alpha1**-
v1secrets*-
""pods, replicasets, deployments, statefulsets, daemonsets, cronjobs, jobs, configmapsget, list, watch-
monitoring.coreos.comalertmanagers, alertmanagerconfigsget, list, watch-
role:<org-name>:cluster-adminAn admin of Greenhouse Clusters within an Organizationgreenhouse.sap/v1alpha1clusters, teamrolebindings*-
v1secretscreate, update, patch-
role:<org-name>:plugin-adminAn admin of Greenhouse Plugins within an Organizationgreenhouse.sap/v1alpha1plugins, pluginpresets, catalogs, plugindefinitions*-
v1secretscreate, update, patch-
organization:<org-name>A member of a Greenhouse Organizationgreenhouse.sap/v1alpha1*get, list, watch-
organization:<org-name>A member of a Greenhouse Organizationgreenhouse.sap/v1alpha1organizations, clusterplugindefinitionsget, list, watchx

Next Steps

2 - PluginDefinitions

A PluginDefinition brings either a UI application, a Helm chart deployment, or both, to the Greenhouse platform. The Helm chart for a PluginDefinition can be used to deploy infrastructure components to a Kubernetes cluster managed with Greenhouse. The PluginDefinition provides an opinionated way to configure, integrate and deploy these components with Greenhouse.

Example PluginDefinition Spec

apiVersion: greenhouse.sap/v1alpha1
kind: PluginDefinition
metadata:
  name: alerts
  namespace: example-organization
spec:
  description: The Alerts Plugin consists of both Prometheus Alertmanager and Supernova,
    the holistic alert management UI
  displayName: Alerts
  docMarkDownUrl: https://raw.githubusercontent.com/cloudoperators/greenhouse-extensions/main/alerts/README.md
  helmChart:
    name: alerts
    repository: oci://ghcr.io/cloudoperators/greenhouse-extensions/charts
    version: 4.0.3
  icon: https://raw.githubusercontent.com/cloudoperators/greenhouse-extensions/main/alerts/logo.png
  uiApplication:
    name: supernova
    version: latest
  version: 5.0.3
  weight: 0

Writing a PluginDefinition Spec

.spec.displayName is a human-readable name for the PluginDefinition. This field is optional; if not provided, it defaults to the value of metadata.name. This name is used in the Greenhouse UI to display the PluginDefinition in the Catalog of available PluginDefinitions.

.spec.version specifies the semantic version of the PluginDefinition. This versions the combination of Helm chart, UI application and any options provided in the PluginDefinition. The version should be incremented whenever any of these fields are updated.

.spec.uiApplication is an optional field that specifies the UI application associated with the PluginDefinition. The UI application will be made available in the Greenhouse UI when a Plugin is created from this PluginDefinition.

spec:
  uiApplication:
    name: supernova
    version: latest
  weight: 0
  icon: https://raw.githubusercontent.com/cloudoperators/greenhouse-extensions/main/alerts/logo.png
  docMarkDownUrl: https://raw.githubusercontent.com/cloudoperators/greenhouse-extensions/main/alerts/README.md

The fields weight and icon are optional and are used to customize the appearance of the Plugin in the Greenhouse UI sidebar. The optional field docMarkDownUrl can be used to provide a link to documentation for the PluginDefinition, which will be displayed in the entry of available PluginDefinitions in the Greenhouse UI.

.spec.helmChart is an optional field that specifies the Helm chart that is deployed when creating a Plugin from this PluginDefinition.

spec:
  helmChart:
    name: alerts
    repository: oci://ghcr.io/cloudoperators/greenhouse-extensions/charts
    version: 4.0.3

.spec.options is an optional field that specifies default configuration options for the PluginDefinition. These options will be pre-filled when creating a Plugin from this PluginDefinition, but can be overridden by the user.

spec:
  options:
  - description: Alertmanager API Endpoint URL
    name: endpoint
    required: true
    type: string
  - description: FilterLabels are the labels shown in the filter dropdown, enabling
      users to filter alerts based on specific criteria. The format is a list of strings.
    name: filterLabels
    required: false
    type: list
  - default: false
    description: Install Prometheus Operator CRDs if kube-monitoring has not already
      installed them.
    name: alerts.crds.enabled
    required: false
    type: bool

.required indicates whether the option is mandatory when creating a Plugin from this PluginDefinition. .default contains the default value for the option if the Plugin does not provide a value for it. .type is used to enforce validation of the value. The following types are supported: string, bool, int, list, map and secret.

| ℹ️ The type secret requires a secret reference, disallowing clear-text credentials. Vault/OpenBao references will be allowed with 1211|

Next Steps

3 - PluginPresets

A PluginPreset is used to configure Plugins for a set of Clusters. This allows administrators to define standard configurations for Clusters in the same environment or with similar requirements. Greenhouse will create Plugins based on the PluginPreset for each Cluster that matches the specified selector.

Example PluginPreset Spec

apiVersion: greenhouse.sap/v1alpha1
kind: PluginPreset
metadata:
  name: perses-preset
  namespace: example-organization
spec:
  clusterOptionOverrides:
    - clusterName: example-cluster
      overrides:
      - name: perses.serviceMonitor.selfMonitor
        value: true
      - name: perses.serviceMonitor.labels
        value:
          plugin: kube-monitoring
  clusterSelector:
    matchExpressions:
    - key: cluster-type
      operator: In
      values:
      - observability
  deletionPolicy: Delete
  plugin:
    optionValues:
    - name: perses.sidecar.enabled
      value: true
    pluginDefinitionRef:
      kind: ClusterPluginDefinition
      name: perses
    releaseName: perses
    releaseNamespace: kube-monitoring

Writing a PluginPreset Spec

.spec.plugin is the template for the Plugins that will be created for each matching Cluster. This field has the same structure as the PluginSpec. Only .spec.clusterName is not allowed in the PluginPreset’s Plugin template, as the Cluster name is determined by the matching Clusters.

spec:
  plugin:
    optionValues:
    - name: perses.sidecar.enabled
      value: true
    pluginDefinitionRef:
      kind: ClusterPluginDefinition
      name: perses
    releaseName: perses
    releaseNamespace: kube-monitoring

.spec.clusterSelector is a required field that specifies the label selector used to list the Clusters for which Plugins will be created based on this PluginPreset.

spec:
  clusterSelector:
    matchExpressions:
    - key: cluster-type
      operator: In
      values:
      - observability

| ⚠️ Changing the clusterSelector may result in the creation or deletion of Plugins for Clusters that start or stop matching the selector. |

.spec.clusterOptionOverrides is an optional field that can be used to provide per-Cluster overrides for the Plugin’s OptionValues. This can be used to customize the configuration of the Plugin for specific Clusters.

spec:
  clusterOptionOverrides:
    - clusterName: example-cluster
      overrides:
      - name: perses.serviceMonitor.selfMonitor
        value: true

.spec.deletionPolicy is an optional field that specifies the behaviour when a PluginPreset is deleted. The possible values are Delete and Retain. If set to Delete (the default), all Plugins created by the PluginPreset will also be deleted when the PluginPreset is deleted. If set to Retain, the Plugins will remain after the PluginPreset is deleted or if the Cluster stops matching the selector.

Next Steps

4 - Plugins

A Plugin is an instance of a PluginDefinition and is used to deploy infrastructure components such as observability, compliance or system components to a Kubernetes cluster managed with Greenhouse. A Plugin provides the specific configuration for deploying the Helm chart associated with the referenced PluginDefinition to a specific cluster.

Example Plugin Spec

apiVersion: greenhouse.sap/v1alpha1
kind: Plugin
metadata:
  name: alerts-plugin
  namespace: example-organization
spec:
  clusterName: example-cluster
  displayName: Example Alerts Plugin
  optionValues:
  - name: image.tag
    value: foobar
  pluginDefinitionRef:
    kind: PluginDefinition
    name: alerts
  releaseName: alerts
  releaseNamespace: kube-monitoring

Writing a Plugin Spec

.spec.displayName is an optional human-readable name that is used to display the Plugin in the Greenhouse UI. If not provided, it defaults to the value of metadata.name.

.spec.clusterName is the name of the Cluster resource where the Helm chart associated with the PluginDefinition will be deployed.

.spec.pluginDefinitionRef is the required and immutable reference to a PluginDefinition resource that defines the Helm chart and UI application associated with this Plugin.

spec:
  pluginDefinitionRef:
    kind: PluginDefinition
    name: alerts

.spec.releaseName is the optional and immutable name of the Helm release that will be created when deploying the Plugin to the target cluster. If not provided it defaults to the name of the PluginDefinition’s Helm chart.

.spec.releaseNamespace is the optional and immutable Kubernetes namespace in the target cluster where the Helm release will be deployed. If not provided, it defaults to the name of the Organization.

.spec.optionValues is an optional list of Helm chart values that will be used to customize the deployment of the Helm chart associated with the PluginDefinition. These values are used to set Options required by the PluginDefinition or to override provided default values.

  optionValues:
  - name: image.tag
    value: foobar
  - name: secret
    valueFrom:
      secret:
        name: alerts-secret
        key: secret-key

| ℹ️ A defaulting webhook automatically merges the OptionValues with the defaults set in the PluginDefinition. The defaulting does not update OptionValues when the defaults change and does not remove values when they are removed from the PluginDefinition. |

.spec.waitFor is an optional field that specifies PluginPresets or Plugins which have to be successfully deployed before this Plugin can be deployed. This can be used to express dependencies between Plugins. This can be useful if one Plugin depends on Custom Resource Definitions or other resources created by another Plugin.

spec:
  waitFor:
  - pluginRef:
      pluginPreset: ingress-nginx
  - pluginRef:
      name: cert-manager-example-cluster

| ℹ️ The dependency on a PluginPreset ensures that a Plugin created by this PluginPreset has been deployed to the same cluster. The dependency on a Plugin is fulfilled if the referenced Plugin is deployed to the same cluster. |

.spec.ignoreDifferences is an optional field that is used to suppress specific differences detected by the drift detection of the deployment tool. This can be useful to ignore differences in fields that are managed by other controllers or tools. Example configuration when using Flux as the deployment tool.

spec:
  ignoreDifferences:
  - group: apps
    version: v1
    kind: Deployment
    paths:
    - /spec/replicas

| ⚠️ The ignoreDifferences field is only supported when using Flux as the deployment tool. It is ignored when using the legacy Helm controller. |

Working with Plugins

Choosing the deployment tool

The annotation greenhouse.sap/deployment-tool can be added to a Plugin resource to choose the deployment tool used to deploy the Helm release. Supported values are flux and legacy.

Suspending the Plugin’s reconciliation

The annotation greenhouse.sap/suspend can be added to a Plugin resource to temporarily suspend the reconciliation of the Plugin. This results in no changes on the Plugin or referenced resources being applied until the annotation is removed. This also includes upgrades of the Helm release on the target cluster. This also blocks the deletion of the Plugin resource until the annotation is removed.

Triggering reconciliation of the Plugin’s managed resources

The annotation greenhouse.sap/reconcile can be added to a Plugin resource to trigger a reconciliation of the Plugin and its managed resources. When the Plugin is deployed using FluxCD this annotation is propagated to the Flux HelmRelease resource and triggers a reconciliation of the Helm release on the target cluster. This can be useful to trigger a reconciliation even if no changes were made to the Plugin resource.

Next Steps

5 - Catalogs

A Catalog is a collection of PluginDefinitions that can be made available to Organizations within Greenhouse. Catalogs allow organization admins to manage the lifecycle of PluginDefinitions by controlling which version of a PluginDefinition is deployed to their cluster fleet.

The Catalog API is currently in alpha and is still under active development and is subjected to change.

Example

The following is an example of a Greenhouse Catalog that reconciles the PluginDefinition manifests stored in a Git Repository.

apiVersion: greenhouse.sap/v1alpha1
kind: Catalog
metadata:
  name: greenhouse-extensions
  namespace: <organization-namespace>
spec:
  sources:
    - repository: https://github.com/cloudoperators/greenhouse-extensions
      resources:
        - alerts/plugindefinition.yaml
        - audit-logs/plugindefinition.yaml
        - cert-manager/plugindefinition.yaml
        - external-dns/plugindefinition.yaml
        - repo-guard/plugindefinition.yaml
        - ingress-nginx/plugindefinition.yaml
        - kube-monitoring/plugindefinition.yaml
        - logs/plugindefinition.yaml
        - perses/plugindefinition.yaml
        - thanos/plugindefinition.yaml
      ref:
        branch: main

In the above example:

  • The Greenhouse Catalog references a Git Repository targeting the main branch.
  • The Catalog is configured to target specific PluginDefinition manifests stored in a path within the repository specified under .spec.sources[].resources[].
  • The Catalog watches for changes in the specified Git Repository branch and reconciles the PluginDefinitions in the Organization namespace accordingly.

Writing a Catalog Spec

Sources

.spec.sources is a list of sources from which the Catalog will fetch PluginDefinition manifests. Currently, only Git repositories are supported as sources. Each source requires a repository URL and a list of resources that specify the paths to the PluginDefinition manifests within the repository. The ref field is used to specify the branch, tag, or commit SHA to fetch from the repository.

⚠️ Each Organization has a dedicated ServiceAccount used to apply the Catalog resources. This ServiceAccount only has permissions to apply PluginDefinitions into the Organization’s Namespace. It will not be possible to bring other Kinds using the Catalog.

Repository

.spec.sources[].repository is used to specify the URL of the Git repository containing the PluginDefinition manifests.

Resources

.spec.sources[].resources is a list of file paths within the repository that point to the PluginDefinition manifests to be included in the Catalog.

Empty resources list will result in an error.

Ref

.spec.sources[].ref is used to specify the branch, tag, or commit SHA to fetch from the repository.

Available fields are:

  • sha - The commit SHA to fetch.
  • tag - The tag to fetch.
  • branch - The branch that is targeted.

The priority order is: sha > tag > branch. If multiple fields are specified, the field with the highest priority will be used.

When multiple sources are defined with the same repository and ref, a duplicate error will be raised.

Interval (Optional)

.spec.sources[].interval is an optional field that specifies how often the Catalog should check for updates in the source repository. The default value is 1h (1 hour) if not specified.

The value must be in a Go recognized duration format, e.g. 5m0s to reconcile the source every 5 minutes.

Secret Reference (Optional)

.spec.sources[].secretName is an optional field that specifies a reference to a Kubernetes Secret name containing credentials for accessing private Git repositories.

The following are the types of authentication supported:

The Secret must be in the same namespace as the Catalog resource.

Overrides (Optional)

.spec.sources[].overrides is an optional field that allows specifying overrides for specific PluginDefinitions in the Catalog. This can be used to customize certain fields of PluginDefinitions.

Currently, you can override the following fields:

  • alias field to override metadata.name of the PluginDefinition
  • repository field to override the helm chart repository in the PluginDefinition spec

Working with Catalog

Configuring Secret for Basic Authentication:

To authenticate towards a Git repository over HTTPS using basic access authentication (in other words: using a username and password), the referenced Secret is expected to contain .data.username and .data.password values.

apiVersion: v1
kind: Secret
metadata:
  name: git-credentials
  namespace: <catalog-namespace>
type: Opaque
data:
  username: <BASE64>
  password: <BASE64>

password is the Personal Access Token (PAT) for accessing the Git repository.

Configure Secret for GitHub App authentication:

Pre-requisites:

  • Register the GitHub App with the necessary permissions and generate a private key for the app.

  • Install the app in the organization/account configuring access to the necessary repositories.

To authenticate towards a GitHub repository using a GitHub App, the referenced secret is expected to contain the following values:

  • Get the App ID from the app settings page at https://github.com/settings/apps/<app-name>.
  • Get the App Installation ID from the app installations page at https://github.com/settings/installations. Click the installed app, the URL will contain the installation ID https://github.com/settings/installations/<installation-id>. For organizations, the first part of the URL may be different, but it follows the same pattern.
  • The private key that was generated in the pre-requisites.
  • (Optional) GitHub Enterprise Server users can set the base URL to http(s)://HOSTNAME/api/v3.
  • (Optional) If GitHub Enterprise Server uses a private CA, include its bundle (root and any intermediates) in ca.crt. If the ca.crt is specified, then it will be used for TLS verification for all API / Git over HTTPS requests to the GitHub Enterprise Server.
apiVersion: v1
kind: Secret
metadata:
  name: github-app-credentials
  namespace: <catalog-namespace>
type: Opaque
stringData:
  githubAppID: "5001"
  githubAppInstallationID: "1005"
  githubAppBaseURL: "github.enterprise.example.com/api/v3" #optional, required only for GitHub Enterprise Server users
  githubAppPrivateKey: |
    -----BEGIN RSA PRIVATE KEY-----
    .....
    -----END RSA PRIVATE KEY-----    
  ca.crt: | #optional, for GitHub Enterprise Server users
    -----BEGIN CERTIFICATE-----
    ...
    -----END CERTIFICATE-----

Minimum required permissions for the GitHub App or Personal Access Token (PAT) is content read access for the target repository.

Configuring Overrides for PluginDefinitions

If you want to bring in multiple versions of the same PluginDefinition, you can use the alias option to reference the PluginDefinition under a different name.

Example:

spec:
  sources:
    - repository: https://github.com/cloudoperators/greenhouse-extensions
      resources:
        - perses/plugindefinition.yaml
      ref:
        branch: main
      overrides:
        - name: perses
          alias: perses-latest
    - repository: https://github.com/cloudoperators/greenhouse-extensions
      resources:
        - perses/plugindefinition.yaml
      ref:
        sha: <commit-sha>
      overrides:
        - name: perses
          alias: perses-stable

overrides[].name must match the metadata.name of the PluginDefinition being overridden.

Each PluginDefinition has a helm chart reference in its spec. If you want to override the helm chart repository, you can do that in overrides

Example:

spec:
  sources:
    - repository: https://github.com/cloudoperators/greenhouse-extensions
      resources:
        - perses/plugindefinition.yaml
      ref:
        branch: main
      overrides:
        - name: perses
          repository: oci://your-registry.io/some-repo/perses-chart

Suspending the Catalog’s reconciliation

The annotation greenhouse.sap/suspend can be added to a Catalog resource to temporarily suspend reconciliation. When this annotation is present, the Catalog controller will set it’s underlying Flux resources to suspended state. Any changes made to the Catalog .spec will be ignored while the annotation is present. To resume reconciliation, simply remove the annotation from the Catalog resource. The annotation also blocks the deletion of the Catalog resource until the annotation is removed.

Triggering reconciliation of the Catalog’s managed resources

The Catalog resource orchestrates a combination of Flux resources to fetch and apply PluginDefinitions. The Flux resources managed by Catalog have their own reconciliation intervals. To trigger an immediate reconciliation of the Catalog and its managed resources, the annotation greenhouse.sap/reconcile can be set. This can be useful to trigger an immediate reconciliation when the source repository has changed, and you want to apply the changes without waiting for the next scheduled reconciliation.

Troubleshooting

Greenhouse uses FluxCD under the hood to reconcile Catalog sources and for each source a map of grouped status inventory is shown.

Run kubectl get cat -n <organization-namespace> to see the reconciliation status.

NAMESPACE    NAME                     READY
greenhouse   greenhouse-extensions    True

Run kubectl describe cat greenhouse-extenions -n greenhouse to see the reconciliation status conditions

Status:
  Inventory:
    github-com-cloudoperators-greenhouse-extensions-main-9689366613293914683:
      Kind:     GitRepository
      Message:  stored artifact for revision 'main@sha1:50cbc65c8e8ea390cb947f2a53e8f3dd33265417'
      Name:     repository-9689366613293914683
      Ready:    True
      Kind:     ArtifactGenerator
      Message:  reconciliation succeeded, generated 1 artifact(s)
      Name:     generator-9689366613293914683
      Ready:    True
      Kind:     ExternalArtifact
      Message:  Artifact is ready
      Name:     artifact-9689366613293914683
      Ready:    True
      Kind:     Kustomization
      Message:  Applied revision: latest@sha256:a6114ad3b1c591f1585d78818320d603e78d29b04f527c88321027c59372d506
      Name:     kustomize-9689366613293914683
      Ready:    True
  Status Conditions:
    Conditions:
      Last Transition Time:  2025-10-31T00:14:59Z
      Message:               all catalog objects are ready
      Reason:                CatalogReady
      Status:                True
      Type:                  Ready

Run kubectl get gitrepository repository-9689366613293914683 -n greenhouse to see the GitRepository status

NAME                             URL                                                       AGE     READY   STATUS
repository-9689366613293914683   https://github.com/cloudoperators/greenhouse-extensions   7d10h   True    stored artifact for revision 'main@sha1:50cbc65c8e8ea390cb947f2a53e8f3dd33265417'

Run kubectl describe gitrepository repository-9689366613293914683 -n greenhouse to see the reconciliation status conditions of the GitRepository

...
Spec:
  Interval:  60m0s
  Provider:  generic
  Ref:
    Branch:  main
  Timeout:   60s
  URL:       https://github.com/cloudoperators/greenhouse-extensions
Status:
  Artifact:
    Digest:            sha256:b2662d5c547a7b499c2030e9f646d292413e9745f1a8be9759a212375bc93b42
    Last Update Time:  2025-10-30T12:12:00Z
    Path:              gitrepository/greenhouse/repository-9689366613293914683/50cbc65c8e8ea390cb947f2a53e8f3dd33265417.tar.gz
    Revision:          main@sha1:50cbc65c8e8ea390cb947f2a53e8f3dd33265417
    Size:              7668967
    URL:               http://source-controller.flux-system.svc.cluster.local./gitrepository/greenhouse/repository-9689366613293914683/50cbc65c8e8ea390cb947f2a53e8f3dd33265417.tar.gz
  Conditions:
    Last Transition Time:  2025-10-30T12:12:00Z
    Message:               stored artifact for revision 'main@sha1:50cbc65c8e8ea390cb947f2a53e8f3dd33265417'
    Observed Generation:   2
    Reason:                Succeeded
    Status:                True
    Type:                  Ready
    Last Transition Time:  2025-10-30T12:12:00Z
    Message:               stored artifact for revision 'main@sha1:50cbc65c8e8ea390cb947f2a53e8f3dd33265417'
    Observed Generation:   2
    Reason:                Succeeded
    Status:                True
    Type:                  ArtifactInStorage
  Observed Generation:     2
Events:
  Type    Reason                 Age                   From               Message
  ----    ------                 ----                  ----               -------
  Normal  GitOperationSucceeded  4m40s (x51 over 12h)  source-controller  no changes since last reconcilation: observed revision 'main@sha1:50cbc65c8e8ea390cb947f2a53e8f3dd33265417'

In case of authentication failures due to invalid credentials, you will see errors in the GitRepository status conditions. (The same error message and ready status will also be reflected in the Catalog .status.inventory for the respective source.)

  - message: >-
      failed to checkout and determine revision: unable to list remote for
      'https://github.com/cloudoperators/greenhouse-extensions': authentication
      required: Invalid username or token.
    observedGeneration: 3
    reason: GitOperationFailed
    status: "False"
    type: Ready

PluginDefinitions referenced in .spec.sources[].resources are accumulated using Flux ArtifactGenerator. Run kubectl get artifactgenerator generator-9689366613293914683 -n greenhouse to see the status.

NAME                            AGE     READY   STATUS
generator-9689366613293914683   7d11h   True    reconciliation succeeded, generated 1 artifact(s)

Run kubectl describe artifactgenerator generator-9689366613293914683 -n greenhouse to see the reconciliation status conditions of the ArtifactGenerator

Status:
  Conditions:
    Last Transition Time:  2025-10-31T00:14:59Z
    Message:               reconciliation succeeded, generated 1 artifact(s)
    Observed Generation:   2
    Reason:                Succeeded
    Status:                True
    Type:                  Ready
  Inventory:
    Digest:                 sha256:a6114ad3b1c591f1585d78818320d603e78d29b04f527c88321027c59372d506
    Filename:               2528970247.tar.gz
    Name:                   artifact-9689366613293914683
    Namespace:              greenhouse
  Observed Sources Digest:  sha256:bc9221b47aecc3f4c75f41b8657a3a7c985823487da94b8521803251a3628030

If there was an error accumulating the manifests, you will see errors in the ArtifactGenerator status conditions. (The same error message and ready status will also be reflected in the Catalog .status.inventory for the respective source.)

  - message: >-
      artifact-9689366613293914683 build failed: failed to apply copy
      operations: failed to apply copy operation from
      '@catalog/thanos/plugindefinition.yamls' to
      '@artifact/catalogs/thanos/plugindefinition.yamls': source
      'thanos/plugindefinition.yamls' does not exist
    observedGeneration: 3
    reason: BuildFailed
    status: "False"
    type: Ready

Finally, the accumulated manifests are applied using Flux Kustomization. Run kubectl get kustomization kustomize-9689366613293914683 -n greenhouse to see the status.

NAME                            AGE     READY   STATUS
kustomize-9689366613293914683   7d11h   True    Applied revision: latest@sha256:a6114ad3b1c591f1585d78818320d603e78d29b04f527c88321027c59372d506

Run kubectl describe kustomization kustomize-9689366613293914683 -n greenhouse to see the reconciliation status conditions of the Kustomization

In case of permissions issues, you will see errors in the Kustomization status conditions. (The same error message and ready status will also be reflected in the Catalog .status.inventory for the respective source.)

  - lastTransitionTime: "2025-10-31T00:45:08Z"
    message: >
      PluginDefinition/greenhouse/cert-manager dry-run failed
      (Forbidden): plugindefinitions.greenhouse.sap "cert-manager" is
      forbidden: User "system:serviceaccount:greenhouse:greenhouse-catalog-sa"
      cannot patch resource "plugindefinitions" in API group
      "greenhouse.sap" at the cluster scope
    observedGeneration: 4
    reason: ReconciliationFailed
    status: "False"
    type: Ready

Next Steps