Skip to content

Commit

Permalink
Option to disable the default creation of RBAC resources
Browse files Browse the repository at this point in the history
  • Loading branch information
savitaashture committed Sep 28, 2021
1 parent b925224 commit 526e072
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 19 deletions.
4 changes: 2 additions & 2 deletions pkg/apis/operator/v1alpha1/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ func (c *CommonSpec) GetTargetNamespace() string {

// Param declares an string value to use for the parameter called name.
type Param struct {
Name string `json:"name"`
Value string `json:"value"`
Name string `json:"name,omitempty"`
Value string `json:"value,omitempty"`
}

// ParamValue defines a default value and possible values for a param
Expand Down
7 changes: 7 additions & 0 deletions pkg/apis/operator/v1alpha1/tektonconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ type TektonConfigSpec struct {
// Dashboard holds the customizable options for dashboards component
// +optional
Dashboard Dashboard `json:"dashboard,omitempty"`
// Params is the list of params passed for all platforms
// +optional
Params []Param `json:"params,omitempty"`
}

// TektonConfigStatus defines the observed state of TektonConfig
Expand All @@ -97,6 +100,10 @@ type TektonConfigStatus struct {
// The version of the installed release
// +optional
Version string `json:"version,omitempty"`

// The current installer set name
// +optional
TektonInstallerSet map[string]string `json:"tektonInstallerSet,omitempty"`
}

// TektonConfigList contains a list of TektonConfig
Expand Down
12 changes: 12 additions & 0 deletions pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go

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

13 changes: 7 additions & 6 deletions pkg/reconciler/openshift/tektonconfig/extension.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,11 @@ func (oe openshiftExtension) PreReconcile(ctx context.Context, tc v1alpha1.Tekto
}

r := rbac{
kubeClientSet: oe.kubeClientSet,
operatorClientSet: oe.operatorClientSet,
ownerRef: configOwnerRef(tc),
version: os.Getenv(versionKey),
kubeClientSet: oe.kubeClientSet,
operatorClientSet: oe.operatorClientSet,
version: os.Getenv(versionKey),
disableRbacResourcesForOpenshift: config.Spec.Params,
tektonConfig: config,
}
return r.createResources(ctx)
}
Expand Down Expand Up @@ -103,6 +104,6 @@ func (oe openshiftExtension) Finalize(ctx context.Context, comp v1alpha1.TektonC
}

// configOwnerRef returns owner reference pointing to passed instance
func configOwnerRef(tc v1alpha1.TektonComponent) metav1.OwnerReference {
return *metav1.NewControllerRef(tc, tc.GroupVersionKind())
func configOwnerRef(tc v1alpha1.TektonInstallerSet) metav1.OwnerReference {
return *metav1.NewControllerRef(&tc, tc.GetGroupVersionKind())
}
196 changes: 187 additions & 9 deletions pkg/reconciler/openshift/tektonconfig/rbac.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"fmt"
"regexp"

"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
clientset "github.com/tektoncd/operator/pkg/client/clientset/versioned"
"github.com/tektoncd/operator/pkg/reconciler/common"
corev1 "k8s.io/api/core/v1"
Expand All @@ -41,22 +42,29 @@ const (
trustedCABundleConfigMap = "config-trusted-cabundle"
clusterInterceptors = "openshift-pipelines-clusterinterceptors"
namespaceVersionLabel = "openshift-pipelines.tekton.dev/namespace-reconcile-version"
createdByKey = "operator.tekton.dev/created-by"
createdByValue = "RBAC"
releaseVersionKey = "operator.tekton.dev/release-version"
targetNamespaceKey = "operator.tekton.dev/target-namespace"
componentName = "rbacTaskInstallerSet"
)

// Namespace Regex to ignore the namespace for creating rbac resources.
var nsRegex = regexp.MustCompile(common.NamespaceIgnorePattern)

type rbac struct {
kubeClientSet kubernetes.Interface
operatorClientSet clientset.Interface
ownerRef metav1.OwnerReference
version string
kubeClientSet kubernetes.Interface
operatorClientSet clientset.Interface
ownerRef metav1.OwnerReference
version string
disableRbacResourcesForOpenshift []v1alpha1.Param
tektonConfig *v1alpha1.TektonConfig
}

func (r *rbac) cleanUp(ctx context.Context) error {

// fetch the list of all namespaces which have label
// `openshift-pipelines.tekton.dev/namespace-ready: <release-version>`
// `openshift-pipelines.tekton.dev/namespace-reconcile-version: <release-version>`
namespaces, err := r.kubeClientSet.CoreV1().Namespaces().List(ctx, metav1.ListOptions{
LabelSelector: fmt.Sprintf("%s = %s", namespaceVersionLabel, r.version),
})
Expand All @@ -75,35 +83,94 @@ func (r *rbac) cleanUp(ctx context.Context) error {
return nil
}

// getRbacResource returns list of namespaces where rbac resources need to be created.
func (r *rbac) getRbacResource(ctx context.Context, n corev1.Namespace, rbacNamespaces []corev1.Namespace) ([]corev1.Namespace, error) {
if len(r.disableRbacResourcesForOpenshift) == 0 {
rbacNamespaces = append(rbacNamespaces, n)
}
for _, v := range r.disableRbacResourcesForOpenshift {
// check for param name and if its matches to createRbacResource then disable auto creation of RBAC resources by deleting installerSet
if v.Name == "createRbacResource" {
if v.Value == "false" {
if err := r.deleteInstallerSet(ctx, r.tektonConfig, componentName); err != nil {
return nil, err
}
} else {
rbacNamespaces = append(rbacNamespaces, n)
}
} else {
rbacNamespaces = append(rbacNamespaces, n)
}
continue
}
return rbacNamespaces, nil
}

func (r *rbac) createResources(ctx context.Context) error {

logger := logging.FromContext(ctx)

// fetch the list of all namespaces which doesn't have label
// `openshift-pipelines.tekton.dev/namespace-ready: <release-version>`
// `openshift-pipelines.tekton.dev/namespace-reconcile-version: <release-version>`
namespaces, err := r.kubeClientSet.CoreV1().Namespaces().List(ctx, metav1.ListOptions{
LabelSelector: fmt.Sprintf("%s != %s", namespaceVersionLabel, r.version),
})
if err != nil {
return err
}

namespacesWithVersionLabel, err := r.kubeClientSet.CoreV1().Namespaces().List(ctx, metav1.ListOptions{
LabelSelector: fmt.Sprintf("%s = %s", namespaceVersionLabel, r.version),
})
if err != nil {
return err
}

// list of namespaces rbac resources need to be created
var rbacNamespaces []corev1.Namespace

for _, n := range namespacesWithVersionLabel.Items {
rbacNamespaces, err = r.getRbacResource(ctx, n, rbacNamespaces)
if err != nil {
return err
}
}

// filter namespaces:
// ignore ns with name passing regex `^(openshift|kube)-`
for _, n := range namespaces.Items {
if ignore := nsRegex.MatchString(n.GetName()); ignore {
continue
}
rbacNamespaces = append(rbacNamespaces, n)
rbacNamespaces, err = r.getRbacResource(ctx, n, rbacNamespaces)
if err != nil {
return err
}
}

if len(rbacNamespaces) == 0 {
return nil
}

exist, err := checkIfInstallerSetExist(ctx, r.operatorClientSet, r.version, r.tektonConfig, componentName)
if err != nil {
return err
}
if !exist {
if err := createInstallerSet(ctx, r.operatorClientSet, r.tektonConfig,
r.version, componentName, "rbac-resources"); err != nil {
return err
}
}

getdIs, err := r.operatorClientSet.OperatorV1alpha1().TektonInstallerSets().
Get(ctx, "rbac-resources", metav1.GetOptions{})
if err != nil {
return err
}

r.ownerRef = configOwnerRef(*getdIs)

// Maintaining a separate cluster role for the scc declaration.
// to assist us in managing this the scc association in a
// granular way.
Expand Down Expand Up @@ -136,7 +203,7 @@ func (r *rbac) createResources(ctx context.Context) error {
return err
}

// Add `openshift-pipelines.tekton.dev/namespace-ready` label to namespace
// Add `openshift-pipelines.tekton.dev/namespace-reconcile-version` label to namespace
// so that rbac won't loop on it again
nsLabels := n.GetLabels()
if len(nsLabels) == 0 {
Expand Down Expand Up @@ -384,7 +451,7 @@ func (r *rbac) updateRoleBinding(ctx context.Context, rb *rbacv1.RoleBinding, sa
rb.SetOwnerReferences(ownerRef)

if hasSubject && (len(ownerRef) != 0) {
logger.Info("rolebinding is up to date", "action", "none")
logger.Info("rolebinding is up to date ", "action ", "none")
return nil
}

Expand Down Expand Up @@ -586,3 +653,114 @@ func (r *rbac) updateOwnerRefs(ownerRef []metav1.OwnerReference) []metav1.OwnerR
}
return ownerRef
}

func createInstallerSet(ctx context.Context, oc clientset.Interface, ta *v1alpha1.TektonConfig,
releaseVersion, component, installerSetName string) error {

is := makeInstallerSet(ta, installerSetName, releaseVersion)

createdIs, err := oc.OperatorV1alpha1().TektonInstallerSets().
Create(ctx, is, metav1.CreateOptions{})
if err != nil && !errors.IsAlreadyExists(err) {
return err
}

if len(ta.Status.TektonInstallerSet) == 0 {
ta.Status.TektonInstallerSet = map[string]string{}
}

// Update the status of addon with created installerSet name
ta.Status.TektonInstallerSet[component] = createdIs.Name
ta.Status.SetVersion(releaseVersion)

_, err = oc.OperatorV1alpha1().TektonConfigs().
UpdateStatus(ctx, ta, metav1.UpdateOptions{})

return err
}

func makeInstallerSet(tc *v1alpha1.TektonConfig, name, releaseVersion string) *v1alpha1.TektonInstallerSet {
ownerRef := *metav1.NewControllerRef(tc, tc.GetGroupVersionKind())
return &v1alpha1.TektonInstallerSet{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Labels: map[string]string{
createdByKey: createdByValue,
},
Annotations: map[string]string{
releaseVersionKey: releaseVersion,
targetNamespaceKey: tc.Spec.TargetNamespace,
},
OwnerReferences: []metav1.OwnerReference{ownerRef},
},
}
}

func (r *rbac) deleteInstallerSet(ctx context.Context, tc *v1alpha1.TektonConfig, component string) error {

compInstallerSet, ok := tc.Status.TektonInstallerSet[component]
if !ok {
return nil
}

if compInstallerSet != "" {
// delete the installer set
err := r.operatorClientSet.OperatorV1alpha1().TektonInstallerSets().
Delete(ctx, tc.Status.TektonInstallerSet[component], metav1.DeleteOptions{})
if err != nil && !errors.IsNotFound(err) {
return err
}

// clear the name of installer set from TektonAddon status
delete(tc.Status.TektonInstallerSet, component)
_, err = r.operatorClientSet.OperatorV1alpha1().TektonConfigs().
UpdateStatus(ctx, tc, metav1.UpdateOptions{})
if err != nil && !errors.IsNotFound(err) {
return err
}
}

return nil
}

// checkIfInstallerSetExist checks if installer set exists for a component and return true/false based on it
// and if installer set which already exist is of older version then it deletes and return false to create a new
// installer set
func checkIfInstallerSetExist(ctx context.Context, oc clientset.Interface, relVersion string,
tc *v1alpha1.TektonConfig, component string) (bool, error) {

// Check if installer set is already created
compInstallerSet, ok := tc.Status.TektonInstallerSet[component]
if !ok {
return false, nil
}

if compInstallerSet != "" {
// if already created then check which version it is
ctIs, err := oc.OperatorV1alpha1().TektonInstallerSets().
Get(ctx, compInstallerSet, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
return false, nil
}
return false, err
}

if version, ok := ctIs.Annotations[releaseVersionKey]; ok && version == relVersion {
// if installer set already exist and release version is same
// then ignore and move on
return true, nil
}

// release version doesn't exist or is different from expected
// deleted existing InstallerSet and create a new one

err = oc.OperatorV1alpha1().TektonInstallerSets().
Delete(ctx, compInstallerSet, metav1.DeleteOptions{})
if err != nil {
return false, err
}
}

return false, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ type LRUCache interface {
// Clears all cache entries.
Purge()

// Resizes cache, returning number evicted
Resize(int) int
// Resizes cache, returning number evicted
Resize(int) int
}

0 comments on commit 526e072

Please sign in to comment.