Skip to content

Commit

Permalink
Change scope of test-operator to namespace
Browse files Browse the repository at this point in the history
Test-operator is currently designed to be a cluster scoped
operator. This means it can watch and modify resources across all
OCP cluster.

This patch changes the operator to namespace scoped operator. By
default it is going to watch only:

  - openstack-test-operator namespace: This is a namespace where
    we recommend to install the test-operator. Prior to the
    installation we recommend to create an OperatorGroup with
    targetNamespaces value set to openstack-test-operator and
    openstack.

  - openstack: This is a namespace where the openstack controll
    plane is deployed. Test-operator requires an access to this
    namespace in order to read openstack specific CMs and Secrets
    (e.g., clouds.yaml).
  • Loading branch information
lpiwowar committed Dec 11, 2024
1 parent b2b1b46 commit 7fd0f3a
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 55 deletions.
5 changes: 5 additions & 0 deletions config/manager/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -101,5 +101,10 @@ spec:
requests:
cpu: 10m
memory: 128Mi
env:
- name: WATCH_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.annotations['olm.targetNamespaces']
serviceAccountName: controller-manager
terminationGracePeriodSeconds: 10
3 changes: 2 additions & 1 deletion config/rbac/role.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
kind: Role
metadata:
name: manager-role
namespace: <namespace>
rules:
- apiGroups:
- ""
Expand Down
5 changes: 3 additions & 2 deletions config/rbac/role_binding.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/name: clusterrolebinding
Expand All @@ -11,9 +11,10 @@ metadata:
name: manager-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
kind: Role
name: manager-role
subjects:
- kind: ServiceAccount
name: controller-manager
namespace: system

27 changes: 14 additions & 13 deletions controllers/ansibletest_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,19 @@ func (r *AnsibleTestReconciler) GetLogger(ctx context.Context) logr.Logger {
return log.FromContext(ctx).WithName("Controllers").WithName("AnsibleTest")
}

// +kubebuilder:rbac:groups=test.openstack.org,resources=ansibletests,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=test.openstack.org,resources=ansibletests/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=test.openstack.org,resources=ansibletests/finalizers,verbs=update;patch
// +kubebuilder:rbac:groups=batch,resources=jobs,verbs=get;list;watch;create;patch;update;delete;
// +kubebuilder:rbac:groups=k8s.cni.cncf.io,resources=network-attachment-definitions,verbs=get;list;watch
// +kubebuilder:rbac:groups="rbac.authorization.k8s.io",resources=roles,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups="rbac.authorization.k8s.io",resources=rolebindings,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups="security.openshift.io",resourceNames=anyuid;privileged;nonroot;nonroot-v2,resources=securitycontextconstraints,verbs=use
// +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch
// +kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update;patch;delete;
// +kubebuilder:rbac:groups="",resources=pods,verbs=create;delete;get;list;patch;update;watch
// +kubebuilder:rbac:groups="",resources=persistentvolumeclaims,verbs=get;list;create;update;watch;patch;delete
// +kubebuilder:rbac:groups="",resources=serviceaccounts,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups=test.openstack.org,namespace=<namespace>,resources=ansibletests,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=test.openstack.org,namespace=<namespace>,resources=ansibletests/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=test.openstack.org,namespace=<namespace>,resources=ansibletests/finalizers,verbs=update;patch
// +kubebuilder:rbac:groups=batch,namespace=<namespace>,resources=jobs,verbs=get;list;watch;create;patch;update;delete;
// +kubebuilder:rbac:groups=k8s.cni.cncf.io,namespace=<namespace>,resources=network-attachment-definitions,verbs=get;list;watch
// +kubebuilder:rbac:groups="rbac.authorization.k8s.io",namespace=<namespace>,resources=roles,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups="rbac.authorization.k8s.io",namespace=<namespace>,resources=rolebindings,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups="security.openshift.io",namespace=<namespace>,resourceNames=anyuid;privileged;nonroot;nonroot-v2,resources=securitycontextconstraints,verbs=use
// +kubebuilder:rbac:groups="",resources=secrets,namespace=<namespace>,verbs=get;list;watch
// +kubebuilder:rbac:groups="",resources=configmaps,namespace=<namespace>,verbs=get;list;watch;create;update;patch;delete;
// +kubebuilder:rbac:groups="",resources=pods,namespace=<namespace>,verbs=create;delete;get;list;patch;update;watch
// +kubebuilder:rbac:groups="",resources=persistentvolumeclaims,namespace=<namespace>,verbs=get;list;create;update;watch;patch;delete
// +kubebuilder:rbac:groups="",resources=serviceaccounts,namespace=<namespace>,verbs=get;list;watch;create;update;patch

// Reconcile - AnsibleTest
func (r *AnsibleTestReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, _err error) {
Expand All @@ -76,6 +76,7 @@ func (r *AnsibleTestReconciler) Reconcile(ctx context.Context, req ctrl.Request)
if k8s_errors.IsNotFound(err) {
return ctrl.Result{}, nil
}

return ctrl.Result{}, err
}

Expand Down
26 changes: 13 additions & 13 deletions controllers/horizontest_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,19 @@ func (r *HorizonTestReconciler) GetLogger(ctx context.Context) logr.Logger {
return log.FromContext(ctx).WithName("Controllers").WithName("HorizonTest")
}

// +kubebuilder:rbac:groups=test.openstack.org,resources=horizontests,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=test.openstack.org,resources=horizontests/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=test.openstack.org,resources=horizontests/finalizers,verbs=update;patch
// +kubebuilder:rbac:groups=batch,resources=jobs,verbs=get;list;watch;create;patch;update;delete;
// +kubebuilder:rbac:groups=k8s.cni.cncf.io,resources=network-attachment-definitions,verbs=get;list;watch
// +kubebuilder:rbac:groups="rbac.authorization.k8s.io",resources=roles,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups="rbac.authorization.k8s.io",resources=rolebindings,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups="security.openshift.io",resourceNames=anyuid;privileged;nonroot;nonroot-v2,resources=securitycontextconstraints,verbs=use
// +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch
// +kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update;patch;delete;
// +kubebuilder:rbac:groups="",resources=pods,verbs=create;delete;get;list;patch;update;watch
// +kubebuilder:rbac:groups="",resources=persistentvolumeclaims,verbs=get;list;create;update;watch;patch;delete
// +kubebuilder:rbac:groups="",resources=serviceaccounts,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups=test.openstack.org,namespace=<namespace>,resources=horizontests,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=test.openstack.org,namespace=<namespace>,resources=horizontests/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=test.openstack.org,namespace=<namespace>,resources=horizontests/finalizers,verbs=update;patch
// +kubebuilder:rbac:groups=batch,namespace=<namespace>,resources=jobs,verbs=get;list;watch;create;patch;update;delete;
// +kubebuilder:rbac:groups=k8s.cni.cncf.io,namespace=<namespace>,resources=network-attachment-definitions,verbs=get;list;watch
// +kubebuilder:rbac:groups="rbac.authorization.k8s.io",namespace=<namespace>,resources=roles,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups="rbac.authorization.k8s.io",namespace=<namespace>,resources=rolebindings,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups="security.openshift.io",namespace=<namespace>,resourceNames=anyuid;privileged;nonroot;nonroot-v2,resources=securitycontextconstraints,verbs=use
// +kubebuilder:rbac:groups="",resources=secrets,namespace=<namespace>,verbs=get;list;watch
// +kubebuilder:rbac:groups="",resources=configmaps,namespace=<namespace>,verbs=get;list;watch;create;update;patch;delete;
// +kubebuilder:rbac:groups="",resources=pods,namespace=<namespace>,verbs=create;delete;get;list;patch;update;watch
// +kubebuilder:rbac:groups="",resources=persistentvolumeclaims,namespace=<namespace>,verbs=get;list;create;update;watch;patch;delete
// +kubebuilder:rbac:groups="",resources=serviceaccounts,namespace=<namespace>,verbs=get;list;watch;create;update;patch

// Reconcile - HorizonTest
func (r *HorizonTestReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, _err error) {
Expand Down
26 changes: 13 additions & 13 deletions controllers/tempest_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,19 @@ func (r *TempestReconciler) GetLogger(ctx context.Context) logr.Logger {
return log.FromContext(ctx).WithName("Controllers").WithName("Tempest")
}

// +kubebuilder:rbac:groups=test.openstack.org,resources=tempests,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=test.openstack.org,resources=tempests/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=test.openstack.org,resources=tempests/finalizers,verbs=update;patch
// +kubebuilder:rbac:groups=batch,resources=jobs,verbs=get;list;watch;create;patch;update;delete;
// +kubebuilder:rbac:groups=k8s.cni.cncf.io,resources=network-attachment-definitions,verbs=get;list;watch
// +kubebuilder:rbac:groups="rbac.authorization.k8s.io",resources=roles,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups="rbac.authorization.k8s.io",resources=rolebindings,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups="security.openshift.io",resourceNames=anyuid;privileged;nonroot;nonroot-v2,resources=securitycontextconstraints,verbs=use
// +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch
// +kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update;patch;delete;
// +kubebuilder:rbac:groups="",resources=pods,verbs=create;delete;get;list;patch;update;watch
// +kubebuilder:rbac:groups="",resources=persistentvolumeclaims,verbs=get;list;create;update;watch;patch;delete
// +kubebuilder:rbac:groups="",resources=serviceaccounts,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups=test.openstack.org,namespace=<namespace>,resources=tempests,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=test.openstack.org,namespace=<namespace>,resources=tempests/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=test.openstack.org,namespace=<namespace>,resources=tempests/finalizers,verbs=update;patch
// +kubebuilder:rbac:groups=batch,resources=jobs,namespace=<namespace>,verbs=get;list;watch;create;patch;update;delete;
// +kubebuilder:rbac:groups=k8s.cni.cncf.io,namespace=<namespace>,resources=network-attachment-definitions,verbs=get;list;watch
// +kubebuilder:rbac:groups="rbac.authorization.k8s.io",namespace=<namespace>,resources=roles,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups="rbac.authorization.k8s.io",namespace=<namespace>,resources=rolebindings,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups="security.openshift.io",namespace=<namespace>,resourceNames=anyuid;privileged;nonroot;nonroot-v2,resources=securitycontextconstraints,verbs=use
// +kubebuilder:rbac:groups="",resources=secrets,namespace=<namespace>,verbs=get;list;watch
// +kubebuilder:rbac:groups="",resources=configmaps,namespace=<namespace>,verbs=get;list;watch;create;update;patch;delete;
// +kubebuilder:rbac:groups="",resources=pods,namespace=<namespace>,verbs=create;delete;get;list;patch;update;watch
// +kubebuilder:rbac:groups="",resources=persistentvolumeclaims,namespace=<namespace>,verbs=get;list;create;update;watch;patch;delete
// +kubebuilder:rbac:groups="",resources=serviceaccounts,namespace=<namespace>,verbs=get;list;watch;create;update;patch

// Reconcile - Tempest
func (r *TempestReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, _err error) {
Expand Down
27 changes: 14 additions & 13 deletions controllers/tobiko_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,19 @@ func (r *TobikoReconciler) GetLogger(ctx context.Context) logr.Logger {
return log.FromContext(ctx).WithName("Controllers").WithName("Tobiko")
}

// +kubebuilder:rbac:groups=test.openstack.org,resources=tobikoes,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=test.openstack.org,resources=tobikoes/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=test.openstack.org,resources=tobikoes/finalizers,verbs=update;patch
// +kubebuilder:rbac:groups=batch,resources=jobs,verbs=get;list;watch;create;patch;update;delete;
// +kubebuilder:rbac:groups=k8s.cni.cncf.io,resources=network-attachment-definitions,verbs=get;list;watch
// +kubebuilder:rbac:groups="rbac.authorization.k8s.io",resources=roles,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups="rbac.authorization.k8s.io",resources=rolebindings,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups="security.openshift.io",resourceNames=anyuid;privileged;nonroot;nonroot-v2,resources=securitycontextconstraints,verbs=use
// +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch
// +kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update;patch;delete;
// +kubebuilder:rbac:groups="",resources=pods,verbs=create;delete;get;list;patch;update;watch
// +kubebuilder:rbac:groups="",resources=persistentvolumeclaims,verbs=get;list;create;update;watch;patch;delete
// +kubebuilder:rbac:groups="",resources=serviceaccounts,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups=test.openstack.org,namespace=<namespace>,resources=tobikoes,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=test.openstack.org,namespace=<namespace>,resources=tobikoes/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=test.openstack.org,namespace=<namespace>,resources=tobikoes/finalizers,verbs=update;patch
// +kubebuilder:rbac:groups=batch,namespace=<namespace>,resources=jobs,verbs=get;list;watch;create;patch;update;delete;
// +kubebuilder:rbac:groups=k8s.cni.cncf.io,namespace=<namespace>,resources=network-attachment-definitions,verbs=get;list;watch
// +kubebuilder:rbac:groups="rbac.authorization.k8s.io",namespace=<namespace>,resources=roles,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups="rbac.authorization.k8s.io",namespace=<namespace>,resources=rolebindings,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups="security.openshift.io",namespace=<namespace>,resourceNames=anyuid;privileged;nonroot;nonroot-v2,resources=securitycontextconstraints,verbs=use
// +kubebuilder:rbac:groups="",namespace=<namespace>,resources=secrets,verbs=get;list;watch
// +kubebuilder:rbac:groups="",namespace=<namespace>,resources=configmaps,verbs=get;list;watch;create;update;patch;delete;
// +kubebuilder:rbac:groups="",namespace=<namespace>,resources=pods,verbs=create;delete;get;list;patch;update;watch
// +kubebuilder:rbac:groups="",namespace=<namespace>,resources=persistentvolumeclaims,verbs=get;list;create;update;watch;patch;delete
// +kubebuilder:rbac:groups="",namespace=<namespace>,resources=serviceaccounts,verbs=get;list;watch;create;update;patch

// Reconcile - Tobiko
func (r *TobikoReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, _err error) {
Expand All @@ -77,6 +77,7 @@ func (r *TobikoReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res
if k8s_errors.IsNotFound(err) {
return ctrl.Result{}, nil
}

return ctrl.Result{}, err
}

Expand Down
32 changes: 32 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package main
import (
"crypto/tls"
"flag"
"fmt"
"os"
"strings"

Expand All @@ -31,6 +32,7 @@ import (
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client/config"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
Expand All @@ -56,6 +58,21 @@ func init() {
//+kubebuilder:scaffold:scheme
}

// getWatchNamespace returns the Namespace the operator should be watching for changes
func getWatchNamespace() ([]string, error) {
// WatchNamespaceEnvVar is the constant for env variable WATCH_NAMESPACE
// which specifies the Namespace to watch.
// An empty value means the operator is running with cluster scope.
var watchNamespaceEnvVar = "WATCH_NAMESPACE"

ns, found := os.LookupEnv(watchNamespaceEnvVar)
if !found {
return []string{}, fmt.Errorf("%s must be set", watchNamespaceEnvVar)
}

return strings.Split(ns, ","), nil
}

func main() {
var metricsAddr string
var enableLeaderElection bool
Expand All @@ -82,6 +99,17 @@ func main() {
c.NextProtos = []string{"http/1.1"}
}

watchNamespace, err := getWatchNamespace()
if err != nil {
setupLog.Error(err, "unable to get WatchNamespace, "+
"the manager will watch and manage resources in all namespaces")
}

defaultNamespaces := map[string]cache.Config{}
for _, namespace := range watchNamespace {
defaultNamespaces[namespace] = cache.Config{}
}

mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
Metrics: metricsserver.Options{
Expand All @@ -106,7 +134,11 @@ func main() {
// if you are doing or is intended to do any operation such as perform cleanups
// after the manager stops then its usage might be unsafe.
// LeaderElectionReleaseOnCancel: true,
Cache: cache.Options{
DefaultNamespaces: defaultNamespaces,
},
})

if err != nil {
setupLog.Error(err, "unable to start manager")
os.Exit(1)
Expand Down

0 comments on commit 7fd0f3a

Please sign in to comment.