Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions api/v1alpha1/catalog_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"

sourcev1 "github.com/fluxcd/source-controller/api/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

greenhousemetav1alpha1 "github.com/cloudoperators/greenhouse/api/meta/v1alpha1"
Expand Down Expand Up @@ -91,6 +92,19 @@ type CatalogOverrides struct {
// Repository is the repository to override in the PluginDefinition .spec.helmChart.repository
// +Optional
Repository string `json:"repository,omitempty"`
// OptionsOverride are the option values to override in the PluginDefinition .spec.options[]
// +Optional
OptionsOverride []OptionsOverride `json:"optionsOverride,omitempty"`
}

type OptionsOverride struct {
// Name is the name of the option value to override in the PluginDefinition
// +kubebuilder:validation:MinLength=1
// +Required
Name string `json:"name"`
// Value is the value to set as Default in the PluginDefinition option
// +Required
Value *apiextensionsv1.JSON `json:"value"`
}

type GitRef struct {
Expand Down
31 changes: 30 additions & 1 deletion api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions charts/manager/crds/greenhouse.sap_catalogs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,25 @@ spec:
to patch with an alias
minLength: 1
type: string
optionsOverride:
description: OptionsOverride are the option values to
override in the PluginDefinition .spec.options[]
items:
properties:
name:
description: Name is the name of the option value
to override in the PluginDefinition
minLength: 1
type: string
value:
description: Value is the value to set as Default
in the PluginDefinition option
x-kubernetes-preserve-unknown-fields: true
required:
- name
- value
type: object
type: array
repository:
description: Repository is the repository to override
in the PluginDefinition .spec.helmChart.repository
Expand Down
18 changes: 17 additions & 1 deletion cmd/greenhouse/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,20 @@ If you are using `postgres` as the dex storage backend, you need to set the foll
- `PG_PORT=<postgres-port>` ex: `5432` (defaults to `5432` if not set)
- `PG_USER=<postgres-user>` ex: `postgres` (defaults to `postgres` if not set)
- `PG_HOST=<postgres-host>` ex: `localhost` (required)
- `PG_PASSWORD=<postgres-password>` ex: `password` (required)
- `PG_PASSWORD=<postgres-password>` ex: `password` (required)

### Running Catalog Controller Locally

To run the Catalog Controller locally, you need to port-forward flux `source-watcher` SVC to your localhost.

Example command:

```shell
kubectl -n flux-system port-forward svc/source-watcher 5050:80
```

Then set the following environment variable when running the operator (IDE Debugger or Shell):

```shell
ARTIFACT_DOMAIN=localhost:5050
```
12 changes: 9 additions & 3 deletions cmd/greenhouse/controllers.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ var knownControllers = map[string]func(controllerName string, mgr ctrl.Manager)
"plugin": startPluginReconciler,
"pluginPreset": (&plugincontrollers.PluginPresetReconciler{}).SetupWithManager,

"catalog": (&catalog.CatalogReconciler{
Log: ctrl.Log.WithName("controllers").WithName("catalogs"),
}).SetupWithManager,
"catalog": startCatalogReconciler,
"pluginDefinition": (&plugindefinitioncontroller.PluginDefinitionReconciler{}).SetupWithManager,
"clusterPluginDefinition": (&plugindefinitioncontroller.ClusterPluginDefinitionReconciler{}).SetupWithManager,

Expand Down Expand Up @@ -107,3 +105,11 @@ func startClusterReconciler(name string, mgr ctrl.Manager) error {
RenewRemoteClusterBearerTokenAfter: renewRemoteClusterBearerTokenAfter,
}).SetupWithManager(name, mgr)
}

func startCatalogReconciler(name string, mgr ctrl.Manager) error {
return (&catalog.CatalogReconciler{
Log: ctrl.Log.WithName("controllers").WithName("catalogs"),
StoragePath: artifactStoragePath,
HttpRetry: artifactRetries,
}).SetupWithManager(name, mgr)
}
10 changes: 8 additions & 2 deletions cmd/greenhouse/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ const (
flagLeaseDuration = "leader-election-lease-duration"
flagRenewDeadline = "leader-election-renew-deadline"
flagRetryPeriod = "leader-election-retry-period"
flagArtifactStoragePath = "catalog-artifact-storage-path"
flagArtifactRetries = "catalog-http-retry"
)

var (
Expand All @@ -83,8 +85,10 @@ var (
enabledControllers []string
remoteClusterBearerTokenValidity,
renewRemoteClusterBearerTokenAfter time.Duration
kubeClientOpts clientutil.RuntimeOptions
featureFlags *features.Features
kubeClientOpts clientutil.RuntimeOptions
featureFlags *features.Features
artifactStoragePath string
artifactRetries int
)

func init() {
Expand Down Expand Up @@ -121,6 +125,8 @@ func main() {
flag.DurationVar(&leaseDuration, flagLeaseDuration, 60*time.Second, "Leader election lease duration")
flag.DurationVar(&renewDeadline, flagRenewDeadline, 30*time.Second, "Leader election renew deadline")
flag.DurationVar(&retryPeriod, flagRetryPeriod, 5*time.Second, "Leader election retry period")
flag.StringVar(&artifactStoragePath, flagArtifactStoragePath, "/tmp/data", "The path to store catalog artifacts")
flag.IntVar(&artifactRetries, flagArtifactRetries, 5, "Max number of retries to acquire artifact, default: 5 attempts")

opts := zap.Options{
Development: true,
Expand Down
51 changes: 21 additions & 30 deletions config/samples/catalog/extensions-catalog.yaml
Original file line number Diff line number Diff line change
@@ -1,46 +1,37 @@
# SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and Greenhouse contributors
# SPDX-License-Identifier: Apache-2.0

apiVersion: greenhouse.sap/v1alpha1
kind: Catalog
metadata:
name: greenhouse-extensions
namespace: greenhouse
spec:
sources:
- repository: https://github.com/cloudoperators/greenhouse-extensions
- ref:
branch: main
repository: https://github.com/cloudoperators/greenhouse-extensions
resources:
- alerts/plugindefinition.yaml
- audit-logs/plugindefinition.yaml
- cert-manager/plugindefinition.yaml
- exposed-services/plugindefinition.yaml
- external-dns/plugindefinition.yaml
- repo-guard/plugindefinition.yaml
- ingress-nginx/plugindefinition.yaml
- kube-monitoring/plugindefinition.yaml
- openbao/plugindefinition.yaml
- logs/plugindefinition.yaml
- perses/plugindefinition.yaml
- plutono/plugindefinition.yaml
- service-proxy/plugindefinition.yaml
- teams2slack/plugindefinition.yaml
- thanos/plugindefinition.yaml
ref:
branch: main
secretName: github-com-token
overrides:
- name: perses
alias: perses-some-registry-chart
repository: oci://some-registry.io/some-repo/perses-chart
- name: kube-monitoring
alias: kube-monitoring-some-registry-chart
repository: oci://some-registry.io/some-repo/kube-monitoring-chart
- repository: https://github.com/cloudoperators/greenhouse-extensions
- name: cert-manager
alias: cert-manager-overridden
optionsOverride:
- name: "cert-manager.installCRDs"
value: true
- name: cert-manager.webhook.timeoutSeconds
value: 15
- ref:
sha: ed3ff23bca21eef6cffc0956df338d8185340fc5
repository: https://github.com/cloudoperators/greenhouse-extensions
resources:
- disco/plugindefinition.yaml
ref:
sha: eafaee1d74774f74e20101307d25b29a3eb26102
- perses/plugindefinition.yaml
overrides:
- name: disco
alias: disco-some-registry-chart
repository: oci://some-registry.io/some-repo/perses-chart
- name: perses
alias: perses-overridden
optionsOverride:
- name: "perses.serviceMonitor.selector.matchLabels"
value:
foo: bar
baz: qux
16 changes: 16 additions & 0 deletions config/samples/flux/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,22 @@ images:
newName: ghcr.io/fluxcd/source-watcher

patches:
# allow greenhouse namespace to access flux artifacts
- target:
kind: NetworkPolicy
name: allow-egress
namespace: flux-system
patch: |
- op: add
path: /spec/ingress/0/from/-
value:
namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: greenhouse
podSelector:
matchLabels:
app.kubernetes.io/name: greenhouse

# do not apply image-reflector-controller and image-automation-controller
- target:
kind: Deployment
Expand Down
57 changes: 57 additions & 0 deletions docs/reference/api/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,19 @@ <h3 id="greenhouse.sap/v1alpha1.CatalogOverrides">CatalogOverrides
<p>Repository is the repository to override in the PluginDefinition .spec.helmChart.repository</p>
</td>
</tr>
<tr>
<td>
<code>optionsOverride</code><br>
<em>
<a href="#greenhouse.sap/v1alpha1.OptionsOverride">
[]OptionsOverride
</a>
</em>
</td>
<td>
<p>OptionsOverride are the option values to override in the PluginDefinition .spec.options[]</p>
</td>
</tr>
</tbody>
</table>
</div>
Expand Down Expand Up @@ -1899,6 +1912,50 @@ <h3 id="greenhouse.sap/v1alpha1.OIDCConfig">OIDCConfig
</table>
</div>
</div>
<h3 id="greenhouse.sap/v1alpha1.OptionsOverride">OptionsOverride
</h3>
<p>
(<em>Appears on:</em>
<a href="#greenhouse.sap/v1alpha1.CatalogOverrides">CatalogOverrides</a>)
</p>
<div class="md-typeset__scrollwrap">
<div class="md-typeset__table">
<table>
<thead>
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>name</code><br>
<em>
string
</em>
</td>
<td>
<p>Name is the name of the option value to override in the PluginDefinition</p>
</td>
</tr>
<tr>
<td>
<code>value</code><br>
<em>
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#json-v1-apiextensions-k8s-io">
Kubernetes apiextensions/v1.JSON
</a>
</em>
</td>
<td>
<p>Value is the value to set as Default in the PluginDefinition option</p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<h3 id="greenhouse.sap/v1alpha1.Organization">Organization
</h3>
<p>Organization is the Schema for the organizations API</p>
Expand Down
16 changes: 16 additions & 0 deletions docs/reference/api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,22 @@ components:
description: Name is the name of the PluginDefinition to patch with an alias
minLength: 1
type: string
optionsOverride:
description: OptionsOverride are the option values to override in the PluginDefinition .spec.options[]
items:
properties:
name:
description: Name is the name of the option value to override in the PluginDefinition
minLength: 1
type: string
value:
description: Value is the value to set as Default in the PluginDefinition option
x-kubernetes-preserve-unknown-fields: true
required:
- name
- value
type: object
type: array
repository:
description: Repository is the repository to override in the PluginDefinition .spec.helmChart.repository
type: string
Expand Down
10 changes: 9 additions & 1 deletion e2e/catalog/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package catalog

import (
"context"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -71,7 +72,7 @@ var _ = Describe("Catalog E2E", Ordered, func() {
env = env.WithGitHubSecret(ctx, adminClient, secretName, secretType)
}
testNamespace := env.TestNamespace
scenario := scenarios.NewScenario(adminClient, catalogYamlPath)
scenario := scenarios.NewScenario(adminClient, catalogYamlPath, secretName, strings.TrimSpace(catalogYamlPath) == "")
execute(scenario, testNamespace)
},
Entry("Catalog Branch scenario",
Expand Down Expand Up @@ -123,5 +124,12 @@ var _ = Describe("Catalog E2E", Ordered, func() {
shared.GitHubSecretTypeFake,
func(s scenarios.IScenario, ns string) { s.ExecuteGitAuthFailScenario(ctx, ns) },
),
Entry("Catalog Options Override scenario",
e2eOrgYaml,
"",
"github-com-app",
shared.GitHubSecretTypeAPP,
func(s scenarios.IScenario, ns string) { s.ExecuteOptionsOverrideScenario(ctx, ns) },
),
)
})
Loading
Loading