diff --git a/.golangci.yml b/.golangci.yml
index d2a3cda2e..5dcd7b559 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -2,3 +2,11 @@ version: "2"
run:
timeout: 10m
+
+linters:
+ exclusions:
+ rules:
+ # TODO(#241): Remove once TargetNamespace field is fully removed
+ - linters:
+ - staticcheck
+ text: "SA1019:.*TargetNamespace"
diff --git a/README.md b/README.md
index 6171bfc00..8b49c8c20 100644
--- a/README.md
+++ b/README.md
@@ -35,12 +35,11 @@ apiVersion: operator.shipwright.io/v1alpha1
kind: ShipwrightBuild
metadata:
name: shipwright-operator
-spec:
- targetNamespace: shipwright-build
+spec: {}
```
-The operator will deploy Shipwright Builds in the provided `targetNamespace`.
-When `.spec.targetNamespace` is not set, the namespace will default to `shipwright-build`.
+The operator will deploy Shipwright Builds in the operator's own namespace by default.
+The `.spec.targetNamespace` field is **deprecated** — if set, it is still honored but logs a deprecation warning. It will be removed in a future release.
To deploy [Shipwright Triggers](https://github.com/shipwright-io/triggers), add the `triggers` field:
diff --git a/api/v1alpha1/shipwrightbuild_types.go b/api/v1alpha1/shipwrightbuild_types.go
index 3e7c87453..f5d65905a 100644
--- a/api/v1alpha1/shipwrightbuild_types.go
+++ b/api/v1alpha1/shipwrightbuild_types.go
@@ -34,6 +34,8 @@ type TriggersSpec struct {
// ShipwrightBuildSpec defines the configuration of a Shipwright Build deployment.
type ShipwrightBuildSpec struct {
// TargetNamespace is the target namespace where Shipwright's build controller will be deployed.
+ //
+ // Deprecated: will be removed in a future release. Defaults to the operator's namespace.
TargetNamespace string `json:"targetNamespace,omitempty"`
// Triggers configures the deployment of the Shipwright Triggers component.
diff --git a/bundle/manifests/operator.shipwright.io_shipwrightbuilds.yaml b/bundle/manifests/operator.shipwright.io_shipwrightbuilds.yaml
index 5491dd09a..91d450018 100644
--- a/bundle/manifests/operator.shipwright.io_shipwrightbuilds.yaml
+++ b/bundle/manifests/operator.shipwright.io_shipwrightbuilds.yaml
@@ -42,8 +42,10 @@ spec:
Build deployment.
properties:
targetNamespace:
- description: TargetNamespace is the target namespace where Shipwright's
- build controller will be deployed.
+ description: |-
+ TargetNamespace is the target namespace where Shipwright's build controller will be deployed.
+
+ Deprecated: will be removed in a future release. Defaults to the operator's namespace.
type: string
triggers:
description: |-
diff --git a/bundle/manifests/shipwright-operator.clusterserviceversion.yaml b/bundle/manifests/shipwright-operator.clusterserviceversion.yaml
index b4497db9d..16605a28a 100644
--- a/bundle/manifests/shipwright-operator.clusterserviceversion.yaml
+++ b/bundle/manifests/shipwright-operator.clusterserviceversion.yaml
@@ -10,9 +10,7 @@ metadata:
"metadata": {
"name": "shipwright-build"
},
- "spec": {
- "targetNamespace": "shipwright-build"
- }
+ "spec": {}
}
]
capabilities: Basic Install
@@ -682,6 +680,10 @@ spec:
env:
- name: USE_MANAGED_WEBHOOK_CERTS
value: "true"
+ - name: POD_NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
image: ko://github.com/shipwright-io/operator
livenessProbe:
httpGet:
diff --git a/config/crd/bases/operator.shipwright.io_shipwrightbuilds.yaml b/config/crd/bases/operator.shipwright.io_shipwrightbuilds.yaml
index 862dc642d..afe9595fe 100644
--- a/config/crd/bases/operator.shipwright.io_shipwrightbuilds.yaml
+++ b/config/crd/bases/operator.shipwright.io_shipwrightbuilds.yaml
@@ -42,8 +42,10 @@ spec:
Build deployment.
properties:
targetNamespace:
- description: TargetNamespace is the target namespace where Shipwright's
- build controller will be deployed.
+ description: |-
+ TargetNamespace is the target namespace where Shipwright's build controller will be deployed.
+
+ Deprecated: will be removed in a future release. Defaults to the operator's namespace.
type: string
triggers:
description: |-
diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml
index 0e1da47d2..f658e4fe3 100644
--- a/config/manager/manager.yaml
+++ b/config/manager/manager.yaml
@@ -35,6 +35,10 @@ spec:
env:
- name: USE_MANAGED_WEBHOOK_CERTS
value: "true"
+ - name: POD_NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
image: ko://github.com/shipwright-io/operator
name: manager
securityContext:
diff --git a/config/samples/operator_v1alpha1_shipwrightbuild.yaml b/config/samples/operator_v1alpha1_shipwrightbuild.yaml
index 42db15567..0199e6e81 100644
--- a/config/samples/operator_v1alpha1_shipwrightbuild.yaml
+++ b/config/samples/operator_v1alpha1_shipwrightbuild.yaml
@@ -2,5 +2,4 @@ apiVersion: operator.shipwright.io/v1alpha1
kind: ShipwrightBuild
metadata:
name: shipwright-build
-spec:
- targetNamespace: shipwright-build
+spec: {}
diff --git a/controllers/shipwrightbuild_controller.go b/controllers/shipwrightbuild_controller.go
index c9b3ef704..db15e58b8 100644
--- a/controllers/shipwrightbuild_controller.go
+++ b/controllers/shipwrightbuild_controller.go
@@ -38,8 +38,6 @@ import (
const (
// FinalizerAnnotation annotation string appended on finalizer slice.
FinalizerAnnotation = "finalizer.operator.shipwright.io"
- // defaultTargetNamespace fallback namespace when `.spec.namepace` is not informed.
- defaultTargetNamespace = "shipwright-build"
// Ready object is providing service.
ConditionReady = "Ready"
@@ -64,6 +62,7 @@ type ShipwrightBuildReconciler struct {
TektonManifest manifestival.Manifest // Tekton release manifest render
BuildStrategyManifest manifestival.Manifest // Build strategies manifest to render
TriggersManifest manifestival.Manifest // Triggers manifest to render
+ OperatorNamespace string // namespace the operator is running in
}
type TektonCheckResult struct {
@@ -235,34 +234,33 @@ func (r *ShipwrightBuildReconciler) Reconcile(ctx context.Context, req ctrl.Requ
return Requeue()
}
- // selecting the target namespace based on the CRD information, when not informed using the
- // default namespace instead
targetNamespace := b.Spec.TargetNamespace
- if targetNamespace == "" {
- logger.Info(
- "Namespace is not informed! Target namespace is selected from default settings instead",
- "defaultTargetNamespace", defaultTargetNamespace,
+ if targetNamespace != "" && targetNamespace != r.OperatorNamespace {
+ logger.Info("spec.targetNamespace is deprecated, will be removed in a future release",
+ "targetNamespace", targetNamespace,
+ "operatorNamespace", r.OperatorNamespace,
)
- targetNamespace = defaultTargetNamespace
- }
- logger = logger.WithValues("targetNamespace", targetNamespace)
- // create if it does not exist
- ns := &corev1.Namespace{}
- if err := r.Get(ctx, types.NamespacedName{Name: targetNamespace}, ns); err != nil {
- if !errors.IsNotFound(err) {
- logger.Info("retrieving target namespace %s error: %s", targetNamespace, err.Error())
- return RequeueOnError(err)
- }
- ns.Name = targetNamespace
-
- if err = r.Create(ctx, ns, &client.CreateOptions{Raw: &metav1.CreateOptions{}}); err != nil {
- if !errors.IsAlreadyExists(err) {
- logger.Info("creating target namespace %s error: %s", targetNamespace, err.Error())
+ // Deprecated path: create the target namespace if it does not exist
+ ns := &corev1.Namespace{}
+ if err := r.Get(ctx, types.NamespacedName{Name: targetNamespace}, ns); err != nil {
+ if !errors.IsNotFound(err) {
+ logger.Info("retrieving target namespace %s error: %s", targetNamespace, err.Error())
return RequeueOnError(err)
}
+ ns.Name = targetNamespace
+
+ if err = r.Create(ctx, ns, &client.CreateOptions{Raw: &metav1.CreateOptions{}}); err != nil {
+ if !errors.IsAlreadyExists(err) {
+ logger.Info("creating target namespace %s error: %s", targetNamespace, err.Error())
+ return RequeueOnError(err)
+ }
+ }
+ logger.Info("created target namespace")
}
- logger.Info("created target namespace")
+ } else {
+ targetNamespace = r.OperatorNamespace
}
+ logger = logger.WithValues("targetNamespace", targetNamespace)
// ReconcileCertManager
if common.BoolFromEnvVar(UseManagedWebhookCerts) {
diff --git a/controllers/shipwrightbuild_controller_test.go b/controllers/shipwrightbuild_controller_test.go
index 30460e5d0..afaab17a2 100644
--- a/controllers/shipwrightbuild_controller_test.go
+++ b/controllers/shipwrightbuild_controller_test.go
@@ -32,6 +32,9 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)
+// testOperatorNamespace is the namespace used as the operator's namespace in unit tests.
+const testOperatorNamespace = "shipwright-operator"
+
// bootstrapShipwrightBuildReconciler start up a new instance of ShipwrightBuildReconciler which is
// ready to interact with Manifestival, returning the Manifestival instance and the client.
func bootstrapShipwrightBuildReconciler(
@@ -76,7 +79,7 @@ func bootstrapShipwrightBuildReconciler(
} else {
toClient = tektonoperatorv1alpha1client.NewSimpleClientset(tcfg)
}
- r := &ShipwrightBuildReconciler{CRDClient: crdClient.ApiextensionsV1(), TektonOperatorClient: toClient.OperatorV1alpha1(), Client: c, Scheme: s, Logger: logger}
+ r := &ShipwrightBuildReconciler{CRDClient: crdClient.ApiextensionsV1(), TektonOperatorClient: toClient.OperatorV1alpha1(), Client: c, Scheme: s, Logger: logger, OperatorNamespace: testOperatorNamespace}
// creating targetNamespace on which Shipwright-Build will be deployed against, before the other
// tests takes place
@@ -248,7 +251,7 @@ func TestShipwrightBuildReconciler_Reconcile(t *testing.T) {
targetNamespace: "namespace",
}, {
testName: "target namespace is not informed",
- targetNamespace: defaultTargetNamespace,
+ targetNamespace: testOperatorNamespace,
}}
for _, tt := range tests {
diff --git a/controllers/shipwrightbuild_rbac.go b/controllers/shipwrightbuild_rbac.go
index 85b7b2f74..b694672d1 100644
--- a/controllers/shipwrightbuild_rbac.go
+++ b/controllers/shipwrightbuild_rbac.go
@@ -9,6 +9,7 @@ package controllers
// +kubebuilder:rbac:groups=apps,resources=deployments/finalizers,resourceNames=shipwright-build-controller,verbs=update
// +kubebuilder:rbac:groups=apps,resources=deployments,resourceNames=shipwright-build-webhook,verbs=update;patch;delete
// +kubebuilder:rbac:groups=apps,resources=deployments/finalizers,resourceNames=shipwright-build-webhook,verbs=update
+// TODO(#241): Reduce to get;list;watch once TargetNamespace field is fully removed
// +kubebuilder:rbac:groups=core,resources=namespaces,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=core,resources=pods;events;configmaps;secrets;limitranges;namespaces;services,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=core,resources=serviceaccounts,verbs=get;list;watch;create
diff --git a/controllers/suite_test.go b/controllers/suite_test.go
index 456cbebc9..ee746640b 100644
--- a/controllers/suite_test.go
+++ b/controllers/suite_test.go
@@ -302,6 +302,7 @@ var _ = BeforeSuite(func() {
Client: mgr.GetClient(),
Scheme: scheme.Scheme,
Logger: ctrl.Log.WithName("controllers").WithName("shipwrightbuild"),
+ OperatorNamespace: testOperatorNamespace,
}).SetupWithManager(mgr)
Expect(err).NotTo(HaveOccurred())
diff --git a/docs/shipwrightbuild.md b/docs/shipwrightbuild.md
index cb9dc1d10..75c39d05a 100644
--- a/docs/shipwrightbuild.md
+++ b/docs/shipwrightbuild.md
@@ -29,6 +29,6 @@ When the `ShipwrightBuild` instance is created, the following components are ins
| Field | Description |
| ----- | ----------- |
-| spec.targetNamespace | The target namespace where Shipwright Build will be deployed. If omitted, this will default to `shipwright-build` |
+| spec.targetNamespace | **Deprecated.** The target namespace where Shipwright Build will be deployed. If omitted, operands are deployed in the operator's own namespace (determined by the `POD_NAMESPACE` environment variable). Setting this field still works but logs a deprecation warning. This field will be removed in a future release. |
| spec.triggers.deployment | When set to `Enabled`, deploys Shipwright Triggers alongside Build. Triggers are not deployed when this field is omitted or set to `Disabled`. Defaults to `Disabled`. |
| status.conditions | Conditions which report the status of Shipwright Build. Current reported conditions:
- `Ready` |
diff --git a/main.go b/main.go
index a9e6d130e..68e377095 100644
--- a/main.go
+++ b/main.go
@@ -27,6 +27,7 @@ import (
operatorv1alpha1 "github.com/shipwright-io/operator/api/v1alpha1"
"github.com/shipwright-io/operator/controllers"
+ "github.com/shipwright-io/operator/pkg/common"
// +kubebuilder:scaffold:imports
)
@@ -99,12 +100,19 @@ func main() {
os.Exit(1)
}
+ operatorNamespace := common.OperatorNamespace()
+ if operatorNamespace == "" {
+ operatorNamespace = common.DefaultNamespace
+ setupLog.Info("POD_NAMESPACE not set, falling back to default namespace for local development", "namespace", operatorNamespace)
+ }
+
if err = (&controllers.ShipwrightBuildReconciler{
CRDClient: crdClient,
TektonOperatorClient: tektonOperatorClient,
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Logger: ctrl.Log.WithName("controllers").WithName("ShipwrightBuild"),
+ OperatorNamespace: operatorNamespace,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "ShipwrightBuild")
os.Exit(1)
diff --git a/pkg/common/const.go b/pkg/common/const.go
index 0bb07f481..2fc1c24bf 100644
--- a/pkg/common/const.go
+++ b/pkg/common/const.go
@@ -4,6 +4,11 @@ const (
koDataPathEnv = "KO_DATA_PATH"
ShipwrightImagePrefix = "IMAGE_SHIPWRIGHT_"
+ // OperatorNamespaceEnvVar holds the operator pod's namespace.
+ OperatorNamespaceEnvVar = "POD_NAMESPACE"
+ // DefaultNamespace is the fallback namespace when POD_NAMESPACE is unset.
+ DefaultNamespace = "shipwright-build"
+
TektonOpMinSupportedVersion = "v0.50.0"
TektonOpMinSupportedMajor = 0
TektonOpMinSupportedMinor = 50
diff --git a/pkg/common/util.go b/pkg/common/util.go
index ad3b9634c..08af4abfb 100644
--- a/pkg/common/util.go
+++ b/pkg/common/util.go
@@ -242,3 +242,8 @@ func itemInSlice(item string, items []string) bool {
func IsOpenShiftPlatform() bool {
return os.Getenv("PLATFORM") == "openshift"
}
+
+// OperatorNamespace returns the operator pod's namespace from POD_NAMESPACE.
+func OperatorNamespace() string {
+ return os.Getenv(OperatorNamespaceEnvVar)
+}