Skip to content

Commit

Permalink
Adds params to customize TektonAddon component on OpenShift
Browse files Browse the repository at this point in the history
- This adds params in TektonConfig which would be copied to Tekton Addon
CR to customize installation of different components of Addons.
- If the params are not passed in TektonConfig CR, controller will add them
with default values.
- User can change values in TektonConfig to change the component installation
of Addon.
- If Addon is created through TektonConfig CR, and if later values are changed in
Addon CR, it will get overwritten by TektonConfig CR values.

Signed-off-by: Shivam Mukhade <smukhade@redhat.com>
  • Loading branch information
SM43 authored and tekton-robot committed Jun 15, 2021
1 parent 5bf5620 commit e657bbb
Show file tree
Hide file tree
Showing 22 changed files with 522 additions and 18 deletions.
12 changes: 12 additions & 0 deletions config/base/300-operator_v1alpha1_addon_crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,18 @@ spec:
targetNamespace:
description: namespace where tekton addons will be installed
type: string
params:
type: array
description: list of params to customize installation of components
items:
type: object
properties:
name:
description: name of param
type: string
value:
description: value of param
type: string
type: object
status:
description: Status defines the observed state of TektonAddon
Expand Down
16 changes: 16 additions & 0 deletions config/base/300-operator_v1alpha1_config_crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,22 @@ spec:
type: integer
default: 1
type: object
addon:
type: object
description: defines fields to customize installation of addon components
properties:
params:
type: array
description: list of params to customize installation of addon components
items:
type: object
properties:
name:
description: name of param
type: string
value:
description: value of param
type: string
type: object
status:
description: Status defines the observed state of TektonConfig
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,9 @@ metadata:
spec:
profile: all
targetNamespace: openshift-pipelines
addon:
params:
- name: clusterTasks
value: "true"
- name: pipelineTemplates
value: "true"
12 changes: 12 additions & 0 deletions pkg/apis/operator/v1alpha1/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,15 @@ type CommonSpec struct {
func (c *CommonSpec) GetTargetNamespace() string {
return c.TargetNamespace
}

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

// ParamValue defines a default value and possible values for a param
type ParamValue struct {
Default string
Possible []string
}
3 changes: 3 additions & 0 deletions pkg/apis/operator/v1alpha1/tektonaddon_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ func (tp *TektonAddon) GetStatus() TektonComponentStatus {
// TektonAddonSpec defines the desired state of TektonAddon
type TektonAddonSpec struct {
CommonSpec `json:",inline"`
// The params to customize different components of Addon
// +optional
Params []Param `json:"params,omitempty"`
}

// TektonAddonStatus defines the observed state of TektonAddon
Expand Down
8 changes: 8 additions & 0 deletions pkg/apis/operator/v1alpha1/tektonconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ type TektonConfigSpec struct {
// +optional
Pruner Prune `json:"pruner,omitempty"`
CommonSpec `json:",inline"`
Addon Addon `json:"addon,omitempty"`
}

// TektonConfigStatus defines the observed state of TektonConfig
Expand All @@ -89,3 +90,10 @@ type TektonConfigList struct {
metav1.ListMeta `json:"metadata,omitempty"`
Items []TektonConfig `json:"items"`
}

// Addon defines the field to customize Addon component
type Addon struct {
// Params is the list of params passed for Addon customization
// +optional
Params []Param `json:"params,omitempty"`
}
66 changes: 65 additions & 1 deletion 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.

2 changes: 1 addition & 1 deletion pkg/reconciler/common/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func Install(ctx context.Context, manifest *mf.Manifest, instance v1alpha1.Tekto
}

// Uninstall removes all resources
func Uninstall(ctx context.Context, manifest *mf.Manifest) error {
func Uninstall(ctx context.Context, manifest *mf.Manifest, instance v1alpha1.TektonComponent) error {
if err := manifest.Filter(mf.Not(mf.Any(role, rolebinding))).Delete(); err != nil {
return fmt.Errorf("failed to remove non-crd/non-rbac resources: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/reconciler/common/install_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ func TestUninstall(t *testing.T) {
t.Fatalf("Failed to generate manifest: %v", err)
}

if err := Uninstall(context.TODO(), &manifest); err != nil {
if err := Uninstall(context.TODO(), &manifest, nil); err != nil {
t.Fatalf("Uninstall() = %v, want no error", err)
}

Expand Down
89 changes: 89 additions & 0 deletions pkg/reconciler/common/validate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
Copyright 2021 The Tekton Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package common

import (
"context"
"fmt"
"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
"knative.dev/pkg/logging"
)

// ValidateParamsAndSetDefault validates the params and their values with the component params passed
// If the params from spec is missing some params then this will add them with default values
// If there is need to check any special conditions, a func can be passed to validate the same params
// which will be called before setting the default values
func ValidateParamsAndSetDefault(ctx context.Context, params *[]v1alpha1.Param,
componentParams map[string]v1alpha1.ParamValue, validateCond func(params *[]v1alpha1.Param) error) (bool, error) {

updated := false
logger := logging.FromContext(ctx)

// Validate all params passed are valid and have valid values
for _, p := range *params {
pv, ok := componentParams[p.Name]
if !ok {
logger.Error("invalid param: %s")
return updated, fmt.Errorf("invalid param : %s", p.Name)
}
if !isParamValueValid(p.Value, pv.Possible) {
msg := fmt.Sprintf("invalid value (%s) for param: %s", p.Value, p.Name)
logger.Error(msg)
return updated, fmt.Errorf(msg)
}
}

err := validateCond(params)
if err != nil {
return false, err
}

// Parse params and convert in a map
specParams := ParseParams(*params)

// If a param is not passed, add the param with default value
for d := range componentParams {
_, ok := specParams[d]
if !ok {
*params = append(*params,
v1alpha1.Param{
Name: d,
Value: componentParams[d].Default,
})
updated = true
}
}
return updated, nil
}

// ParseParams returns the params passed in a map
func ParseParams(params []v1alpha1.Param) map[string]string {
paramsMap := map[string]string{}
for _, p := range params {
paramsMap[p.Name] = p.Value
}
return paramsMap
}

func isParamValueValid(value string, possible []string) bool {
for _, v := range possible {
if v == value {
return true
}
}
return false
}
83 changes: 83 additions & 0 deletions pkg/reconciler/common/validate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
Copyright 2021 The Tekton Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package common

import (
"context"
"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
"gotest.tools/assert"
"testing"
)

func nullFunc() func(params *[]v1alpha1.Param) error {
return func(params *[]v1alpha1.Param) error {
return nil
}
}

func TestValidateParamsAndSetDefault(t *testing.T) {

componentParams := map[string]v1alpha1.ParamValue{
"valid": v1alpha1.ParamValue{
Default: "param",
Possible: []string{"param", "param1"},
},
"newParam": v1alpha1.ParamValue{
Default: "newValue",
Possible: []string{"newValue", "newValue1"},
},
}

t.Run("Invalid Param", func(t *testing.T) {
params := []v1alpha1.Param{
{Name: "foo", Value: "bar"},
}
_, err := ValidateParamsAndSetDefault(context.TODO(), &params, componentParams, nullFunc())
assert.Error(t, err, "invalid param : foo")
})

t.Run("Invalid Param Value", func(t *testing.T) {
params := []v1alpha1.Param{
{Name: "valid", Value: "bar"},
}
_, err := ValidateParamsAndSetDefault(context.TODO(), &params, componentParams, nullFunc())
assert.Error(t, err, "invalid value (bar) for param: valid")
})

t.Run("All params are defined so no error", func(t *testing.T) {
params := []v1alpha1.Param{
{Name: "valid", Value: "param1"},
{Name: "newParam", Value: "newValue"},
}
updated, err := ValidateParamsAndSetDefault(context.TODO(), &params, componentParams, nullFunc())
assert.NilError(t, err)
assert.Equal(t, updated, false)
})

t.Run("Some params are missing", func(t *testing.T) {
params := []v1alpha1.Param{
{Name: "valid", Value: "param1"},
}
updated, err := ValidateParamsAndSetDefault(context.TODO(), &params, componentParams, nullFunc())
assert.NilError(t, err)
// since some params are added to spec, updated should be true
assert.Equal(t, updated, true)
// missing params will be added with default value
assert.Equal(t, params[1].Name, "newParam")
assert.Equal(t, params[1].Value, "newValue")
})
}
Loading

0 comments on commit e657bbb

Please # to comment.