Skip to content

Commit

Permalink
Ensure Tekton* CR get the operatorVersion label.
Browse files Browse the repository at this point in the history
Prior to this change, only `TektonConfig` has the
`operator.tekton.dev/release-version` label set to the "current"
release. This was leading to some confusion around figuring out which
operator version "updated" those files last.

With this change, all `Tekton*` CR (`TektonPipeline`, …) as well as
OpenShift specifices (`PipelinesAsCode`, …) will have this label set
if not present.

Signed-off-by: Vincent Demeester <[email protected]>
  • Loading branch information
vdemeester authored and tekton-robot committed Jan 11, 2024
1 parent a97f4de commit ec5275f
Show file tree
Hide file tree
Showing 13 changed files with 108 additions and 47 deletions.
2 changes: 1 addition & 1 deletion pkg/reconciler/kubernetes/tektonpipeline/reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const (
type Reconciler struct {
// installer Set client to do CRUD operations for components
installerSetClient *client.InstallerSetClient
//manifest has the source manifest of Tekton Pipeline for a
// manifest has the source manifest of Tekton Pipeline for a
// particular version
manifest mf.Manifest
// Platform-specific behavior to affect the transform
Expand Down
18 changes: 13 additions & 5 deletions pkg/reconciler/openshift/tektonconfig/extension.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,33 @@ import (
pkgCommon "github.com/tektoncd/operator/pkg/common"
"github.com/tektoncd/operator/pkg/reconciler/common"
"github.com/tektoncd/operator/pkg/reconciler/openshift/tektonconfig/extension"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
nsV1 "k8s.io/client-go/informers/core/v1"
rbacV1 "k8s.io/client-go/informers/rbac/v1"
"k8s.io/client-go/kubernetes"

kubeclient "knative.dev/pkg/client/injection/kube/client"
namespaceinformer "knative.dev/pkg/client/injection/kube/informers/core/v1/namespace"
rbacInformer "knative.dev/pkg/client/injection/kube/informers/rbac/v1/clusterrolebinding"
"knative.dev/pkg/logging"
)

const (
versionKey = "VERSION"
)

func OpenShiftExtension(ctx context.Context) common.Extension {
logger := logging.FromContext(ctx)
operatorVer, err := common.OperatorVersion(ctx)
if err != nil {
logger.Fatal(err)
}
return openshiftExtension{
operatorClientSet: operatorclient.Get(ctx),
kubeClientSet: kubeclient.Get(ctx),
rbacInformer: rbacInformer.Get(ctx),
nsInformer: namespaceinformer.Get(ctx),
securityClientSet: pkgCommon.GetSecurityClient(ctx),
operatorVersion: operatorVer,
}
}

Expand All @@ -63,6 +68,8 @@ type openshiftExtension struct {
// OpenShift clientsets are a bit... special, we need to get each
// clientset separately
securityClientSet *security.Clientset

operatorVersion string
}

func (oe openshiftExtension) Transformers(comp v1alpha1.TektonComponent) []mf.Transformer {
Expand All @@ -72,8 +79,8 @@ func (oe openshiftExtension) Transformers(comp v1alpha1.TektonComponent) []mf.Tr
common.ReplaceNamespaceInClusterRoleBinding(comp.GetSpec().GetTargetNamespace()),
}
}
func (oe openshiftExtension) PreReconcile(ctx context.Context, tc v1alpha1.TektonComponent) error {

func (oe openshiftExtension) PreReconcile(ctx context.Context, tc v1alpha1.TektonComponent) error {
config := tc.(*v1alpha1.TektonConfig)
r := rbac{
kubeClientSet: oe.kubeClientSet,
Expand Down Expand Up @@ -134,7 +141,7 @@ func (oe openshiftExtension) PostReconcile(ctx context.Context, comp v1alpha1.Te
configInstance := comp.(*v1alpha1.TektonConfig)

if configInstance.Spec.Profile == v1alpha1.ProfileAll {
if _, err := extension.EnsureTektonAddonExists(ctx, oe.operatorClientSet.OperatorV1alpha1().TektonAddons(), configInstance); err != nil {
if _, err := extension.EnsureTektonAddonExists(ctx, oe.operatorClientSet.OperatorV1alpha1().TektonAddons(), configInstance, oe.operatorVersion); err != nil {
configInstance.Status.MarkComponentNotReady(fmt.Sprintf("TektonAddon: %s", err.Error()))
return v1alpha1.REQUEUE_EVENT_AFTER
}
Expand All @@ -147,7 +154,7 @@ func (oe openshiftExtension) PostReconcile(ctx context.Context, comp v1alpha1.Te

pac := configInstance.Spec.Platforms.OpenShift.PipelinesAsCode
if pac != nil && *pac.Enable {
if _, err := extension.EnsureOpenShiftPipelinesAsCodeExists(ctx, oe.operatorClientSet.OperatorV1alpha1().OpenShiftPipelinesAsCodes(), configInstance); err != nil {
if _, err := extension.EnsureOpenShiftPipelinesAsCodeExists(ctx, oe.operatorClientSet.OperatorV1alpha1().OpenShiftPipelinesAsCodes(), configInstance, oe.operatorVersion); err != nil {
configInstance.Status.MarkComponentNotReady(fmt.Sprintf("OpenShiftPipelinesAsCode: %s", err.Error()))
return v1alpha1.REQUEUE_EVENT_AFTER
}
Expand All @@ -158,6 +165,7 @@ func (oe openshiftExtension) PostReconcile(ctx context.Context, comp v1alpha1.Te
}
return nil
}

func (oe openshiftExtension) Finalize(ctx context.Context, comp v1alpha1.TektonComponent) error {
configInstance := comp.(*v1alpha1.TektonConfig)
if configInstance.Spec.Profile == v1alpha1.ProfileAll {
Expand Down
21 changes: 15 additions & 6 deletions pkg/reconciler/openshift/tektonconfig/extension/addon.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,19 @@ import (
"knative.dev/pkg/apis"
)

func EnsureTektonAddonExists(ctx context.Context, clients op.TektonAddonInterface, config *v1alpha1.TektonConfig) (*v1alpha1.TektonAddon, error) {
func EnsureTektonAddonExists(ctx context.Context, clients op.TektonAddonInterface, config *v1alpha1.TektonConfig, operatorVersion string) (*v1alpha1.TektonAddon, error) {
taCR, err := GetAddon(ctx, clients, v1alpha1.AddonResourceName)

if err != nil {
if !apierrs.IsNotFound(err) {
return nil, err
}
if _, err = createAddon(ctx, clients, config); err != nil {
if _, err = createAddon(ctx, clients, config, operatorVersion); err != nil {
return nil, err
}
return nil, v1alpha1.RECONCILE_AGAIN_ERR
}

taCR, err = updateAddon(ctx, taCR, config, clients)
taCR, err = updateAddon(ctx, taCR, config, clients, operatorVersion)
if err != nil {
return nil, err
}
Expand All @@ -58,13 +57,16 @@ func EnsureTektonAddonExists(ctx context.Context, clients op.TektonAddonInterfac
return taCR, err
}

func createAddon(ctx context.Context, clients op.TektonAddonInterface, config *v1alpha1.TektonConfig) (*v1alpha1.TektonAddon, error) {
func createAddon(ctx context.Context, clients op.TektonAddonInterface, config *v1alpha1.TektonConfig, operatorVersion string) (*v1alpha1.TektonAddon, error) {
ownerRef := *metav1.NewControllerRef(config, config.GroupVersionKind())

taCR := &v1alpha1.TektonAddon{
ObjectMeta: metav1.ObjectMeta{
Name: v1alpha1.AddonResourceName,
OwnerReferences: []metav1.OwnerReference{ownerRef},
Labels: map[string]string{
v1alpha1.ReleaseVersionKey: operatorVersion,
},
},
Spec: v1alpha1.TektonAddonSpec{
CommonSpec: v1alpha1.CommonSpec{
Expand All @@ -87,7 +89,8 @@ func GetAddon(ctx context.Context, clients op.TektonAddonInterface, name string)
}

func updateAddon(ctx context.Context, taCR *v1alpha1.TektonAddon, config *v1alpha1.TektonConfig,
clients op.TektonAddonInterface) (*v1alpha1.TektonAddon, error) {
clients op.TektonAddonInterface, operatorVersion string,
) (*v1alpha1.TektonAddon, error) {
// if the addon spec is changed then update the instance
updated := false

Expand All @@ -112,6 +115,12 @@ func updateAddon(ctx context.Context, taCR *v1alpha1.TektonAddon, config *v1alph
updated = true
}

oldLabels, oldHasLabels := taCR.ObjectMeta.Labels[v1alpha1.ReleaseVersionKey]
if !oldHasLabels || (oldLabels != operatorVersion) {
taCR.ObjectMeta.Labels[v1alpha1.ReleaseVersionKey] = operatorVersion
updated = true
}

if updated {
_, err := clients.Update(ctx, taCR, metav1.UpdateOptions{})
if err != nil {
Expand Down
14 changes: 7 additions & 7 deletions pkg/reconciler/openshift/tektonconfig/extension/addon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,34 +37,34 @@ func TestEnsureTektonAddonCRExists(t *testing.T) {
tConfig := pipeline.GetTektonConfig()

// first invocation should create instance as it is non-existent and return RECONCILE_AGAIN_ERR
_, err := EnsureTektonAddonExists(ctx, c.OperatorV1alpha1().TektonAddons(), tConfig)
_, err := EnsureTektonAddonExists(ctx, c.OperatorV1alpha1().TektonAddons(), tConfig, "v0.70.0")
util.AssertEqual(t, err, v1alpha1.RECONCILE_AGAIN_ERR)

// during second invocation instance exists but waiting on dependencies (pipeline, triggers)
// hence returns DEPENDENCY_UPGRADE_PENDING_ERR
_, err = EnsureTektonAddonExists(ctx, c.OperatorV1alpha1().TektonAddons(), tConfig)
_, err = EnsureTektonAddonExists(ctx, c.OperatorV1alpha1().TektonAddons(), tConfig, "v0.70.0")
util.AssertEqual(t, err, v1alpha1.RECONCILE_AGAIN_ERR)

// make upgrade checks pass
makeUpgradeCheckPass(t, ctx, c.OperatorV1alpha1().TektonAddons())

// next invocation should return RECONCILE_AGAIN_ERR as Dashboard is waiting for installation (prereconcile, postreconcile, installersets...)
_, err = EnsureTektonAddonExists(ctx, c.OperatorV1alpha1().TektonAddons(), tConfig)
_, err = EnsureTektonAddonExists(ctx, c.OperatorV1alpha1().TektonAddons(), tConfig, "v0.70.0")
util.AssertEqual(t, err, v1alpha1.RECONCILE_AGAIN_ERR)

// mark the instance ready
markAddonsReady(t, ctx, c.OperatorV1alpha1().TektonAddons())

// next invocation should return nil error as the instance is ready
_, err = EnsureTektonAddonExists(ctx, c.OperatorV1alpha1().TektonAddons(), tConfig)
_, err = EnsureTektonAddonExists(ctx, c.OperatorV1alpha1().TektonAddons(), tConfig, "v0.70.0")
util.AssertEqual(t, err, nil)

// test update propagation from tektonConfig
tConfig.Spec.TargetNamespace = "foobar"
_, err = EnsureTektonAddonExists(ctx, c.OperatorV1alpha1().TektonAddons(), tConfig)
_, err = EnsureTektonAddonExists(ctx, c.OperatorV1alpha1().TektonAddons(), tConfig, "v0.70.0")
util.AssertEqual(t, err, v1alpha1.RECONCILE_AGAIN_ERR)

_, err = EnsureTektonAddonExists(ctx, c.OperatorV1alpha1().TektonAddons(), tConfig)
_, err = EnsureTektonAddonExists(ctx, c.OperatorV1alpha1().TektonAddons(), tConfig, "v0.70.0")
util.AssertEqual(t, err, nil)
}

Expand All @@ -78,7 +78,7 @@ func TestEnsureTektonAddonCRNotExists(t *testing.T) {

// create an instance for testing other cases
tConfig := pipeline.GetTektonConfig()
_, err = EnsureTektonAddonExists(ctx, c.OperatorV1alpha1().TektonAddons(), tConfig)
_, err = EnsureTektonAddonExists(ctx, c.OperatorV1alpha1().TektonAddons(), tConfig, "v0.70.0")
util.AssertEqual(t, err, v1alpha1.RECONCILE_AGAIN_ERR)

// when an instance exists the first invoacation should make the delete API call and
Expand Down
20 changes: 15 additions & 5 deletions pkg/reconciler/openshift/tektonconfig/extension/pipelinesascode.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,19 @@ import (
"knative.dev/pkg/apis"
)

func EnsureOpenShiftPipelinesAsCodeExists(ctx context.Context, clients op.OpenShiftPipelinesAsCodeInterface, config *v1alpha1.TektonConfig) (*v1alpha1.OpenShiftPipelinesAsCode, error) {
func EnsureOpenShiftPipelinesAsCodeExists(ctx context.Context, clients op.OpenShiftPipelinesAsCodeInterface, config *v1alpha1.TektonConfig, operatorVersion string) (*v1alpha1.OpenShiftPipelinesAsCode, error) {
opacCR, err := GetPAC(ctx, clients, v1alpha1.OpenShiftPipelinesAsCodeName)
if err != nil {
if !apierrs.IsNotFound(err) {
return nil, err
}
if _, err = createOPAC(ctx, clients, config); err != nil {
if _, err = createOPAC(ctx, clients, config, operatorVersion); err != nil {
return nil, err
}
return nil, v1alpha1.RECONCILE_AGAIN_ERR
}

opacCR, err = updateOPAC(ctx, opacCR, config, clients)
opacCR, err = updateOPAC(ctx, opacCR, config, clients, operatorVersion)
if err != nil {
return nil, err
}
Expand All @@ -57,13 +57,16 @@ func EnsureOpenShiftPipelinesAsCodeExists(ctx context.Context, clients op.OpenSh
return opacCR, err
}

func createOPAC(ctx context.Context, clients op.OpenShiftPipelinesAsCodeInterface, config *v1alpha1.TektonConfig) (*v1alpha1.OpenShiftPipelinesAsCode, error) {
func createOPAC(ctx context.Context, clients op.OpenShiftPipelinesAsCodeInterface, config *v1alpha1.TektonConfig, operatorVersion string) (*v1alpha1.OpenShiftPipelinesAsCode, error) {
ownerRef := *metav1.NewControllerRef(config, config.GroupVersionKind())

opacCR := &v1alpha1.OpenShiftPipelinesAsCode{
ObjectMeta: metav1.ObjectMeta{
Name: v1alpha1.OpenShiftPipelinesAsCodeName,
OwnerReferences: []metav1.OwnerReference{ownerRef},
Labels: map[string]string{
v1alpha1.ReleaseVersionKey: operatorVersion,
},
},
Spec: v1alpha1.OpenShiftPipelinesAsCodeSpec{
CommonSpec: v1alpha1.CommonSpec{
Expand All @@ -86,7 +89,8 @@ func GetPAC(ctx context.Context, clients op.OpenShiftPipelinesAsCodeInterface, n
}

func updateOPAC(ctx context.Context, opacCR *v1alpha1.OpenShiftPipelinesAsCode, config *v1alpha1.TektonConfig,
clients op.OpenShiftPipelinesAsCodeInterface) (*v1alpha1.OpenShiftPipelinesAsCode, error) {
clients op.OpenShiftPipelinesAsCodeInterface, operatorVersion string,
) (*v1alpha1.OpenShiftPipelinesAsCode, error) {
// if the pac spec is changed then update the instance
updated := false

Expand Down Expand Up @@ -116,6 +120,12 @@ func updateOPAC(ctx context.Context, opacCR *v1alpha1.OpenShiftPipelinesAsCode,
updated = true
}

oldLabels, oldHasLabels := opacCR.ObjectMeta.Labels[v1alpha1.ReleaseVersionKey]
if !oldHasLabels || (oldLabels != operatorVersion) {
opacCR.ObjectMeta.Labels[v1alpha1.ReleaseVersionKey] = operatorVersion
updated = true
}

if updated {
_, err := clients.Update(ctx, opacCR, metav1.UpdateOptions{})
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,27 +39,27 @@ func TestEnsureOpenShiftPipelinesAsCodeExists(t *testing.T) {

tConfig.SetDefaults(ctx)
// first invocation should create instance as it is non-existent and return RECONCILE_AGAIN_ERR
_, err := EnsureOpenShiftPipelinesAsCodeExists(ctx, c.OperatorV1alpha1().OpenShiftPipelinesAsCodes(), tConfig)
_, err := EnsureOpenShiftPipelinesAsCodeExists(ctx, c.OperatorV1alpha1().OpenShiftPipelinesAsCodes(), tConfig, "v0.70.0")
util.AssertEqual(t, err, v1alpha1.RECONCILE_AGAIN_ERR)

// during second invocation instance exists but waiting on dependencies (pipeline, triggers)
// hence returns DEPENDENCY_UPGRADE_PENDING_ERR
_, err = EnsureOpenShiftPipelinesAsCodeExists(ctx, c.OperatorV1alpha1().OpenShiftPipelinesAsCodes(), tConfig)
_, err = EnsureOpenShiftPipelinesAsCodeExists(ctx, c.OperatorV1alpha1().OpenShiftPipelinesAsCodes(), tConfig, "v0.70.0")
util.AssertEqual(t, err, v1alpha1.RECONCILE_AGAIN_ERR)

// mark the instance ready
markOPACReady(t, ctx, c.OperatorV1alpha1().OpenShiftPipelinesAsCodes())

// next invocation should return nil error as the instance is ready
_, err = EnsureOpenShiftPipelinesAsCodeExists(ctx, c.OperatorV1alpha1().OpenShiftPipelinesAsCodes(), tConfig)
_, err = EnsureOpenShiftPipelinesAsCodeExists(ctx, c.OperatorV1alpha1().OpenShiftPipelinesAsCodes(), tConfig, "v0.70.0")
util.AssertEqual(t, err, nil)

// test update propagation from tektonConfig
tConfig.Spec.TargetNamespace = "foobar"
_, err = EnsureOpenShiftPipelinesAsCodeExists(ctx, c.OperatorV1alpha1().OpenShiftPipelinesAsCodes(), tConfig)
_, err = EnsureOpenShiftPipelinesAsCodeExists(ctx, c.OperatorV1alpha1().OpenShiftPipelinesAsCodes(), tConfig, "v0.70.0")
util.AssertEqual(t, err, v1alpha1.RECONCILE_AGAIN_ERR)

_, err = EnsureOpenShiftPipelinesAsCodeExists(ctx, c.OperatorV1alpha1().OpenShiftPipelinesAsCodes(), tConfig)
_, err = EnsureOpenShiftPipelinesAsCodeExists(ctx, c.OperatorV1alpha1().OpenShiftPipelinesAsCodes(), tConfig, "v0.70.0")
util.AssertEqual(t, err, nil)
}

Expand All @@ -76,7 +76,7 @@ func TestEnsureOpenShiftPipelinesAsCodeCRNotExists(t *testing.T) {
// create an instance for testing other cases
tConfig := pipeline.GetTektonConfig()
tConfig.SetDefaults(ctx)
_, err = EnsureOpenShiftPipelinesAsCodeExists(ctx, c.OperatorV1alpha1().OpenShiftPipelinesAsCodes(), tConfig)
_, err = EnsureOpenShiftPipelinesAsCodeExists(ctx, c.OperatorV1alpha1().OpenShiftPipelinesAsCodes(), tConfig, "v0.70.0")
util.AssertEqual(t, err, v1alpha1.RECONCILE_AGAIN_ERR)

// when an instance exists the first invoacation should make the delete API call and
Expand Down
13 changes: 11 additions & 2 deletions pkg/reconciler/shared/tektonconfig/chain/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import (

func EnsureTektonChainExists(ctx context.Context, clients op.TektonChainInterface, tc *v1alpha1.TektonChain) (*v1alpha1.TektonChain, error) {
tcCR, err := GetChain(ctx, clients, v1alpha1.ChainResourceName)

if err != nil {
if !apierrs.IsNotFound(err) {
return nil, err
Expand Down Expand Up @@ -118,6 +117,13 @@ func UpdateChain(ctx context.Context, old *v1alpha1.TektonChain, new *v1alpha1.T
updated = true
}

oldLabels, oldHasLabels := old.ObjectMeta.Labels[v1alpha1.ReleaseVersionKey]
newLabels, newHasLabels := new.ObjectMeta.Labels[v1alpha1.ReleaseVersionKey]
if !oldHasLabels || (newHasLabels && oldLabels != newLabels) {
old.ObjectMeta.Labels[v1alpha1.ReleaseVersionKey] = newLabels
updated = true
}

if updated {
_, err := clients.Update(ctx, old, metav1.UpdateOptions{})
if err != nil {
Expand All @@ -138,12 +144,15 @@ func isTektonChainReady(s *v1alpha1.TektonChain) (bool, error) {
return s.Status.IsReady(), nil
}

func GetTektonChainCR(config *v1alpha1.TektonConfig) *v1alpha1.TektonChain {
func GetTektonChainCR(config *v1alpha1.TektonConfig, operatorVersion string) *v1alpha1.TektonChain {
ownerRef := *metav1.NewControllerRef(config, config.GroupVersionKind())
return &v1alpha1.TektonChain{
ObjectMeta: metav1.ObjectMeta{
Name: v1alpha1.ChainResourceName,
OwnerReferences: []metav1.OwnerReference{ownerRef},
Labels: map[string]string{
v1alpha1.ReleaseVersionKey: operatorVersion,
},
},
Spec: v1alpha1.TektonChainSpec{
CommonSpec: v1alpha1.CommonSpec{
Expand Down
4 changes: 2 additions & 2 deletions pkg/reconciler/shared/tektonconfig/chain/chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import (
func TestEnsureTektonChainExists(t *testing.T) {
ctx, _, _ := ts.SetupFakeContextWithCancel(t)
c := fake.Get(ctx)
tt := GetTektonChainCR(getTektonConfig())
tt := GetTektonChainCR(getTektonConfig(), "v0.70.0")

// first invocation should create instance as it is non-existent and return RECONCILE_AGAIN_ERR
_, err := EnsureTektonChainExists(ctx, c.OperatorV1alpha1().TektonChains(), tt)
Expand Down Expand Up @@ -76,7 +76,7 @@ func TestEnsureTektonChainCRNotExists(t *testing.T) {
util.AssertEqual(t, err, nil)

// create an instance for testing other cases
tt := GetTektonChainCR(getTektonConfig())
tt := GetTektonChainCR(getTektonConfig(), "v0.70.0")
_, err = EnsureTektonChainExists(ctx, c.OperatorV1alpha1().TektonChains(), tt)
util.AssertEqual(t, err, v1alpha1.RECONCILE_AGAIN_ERR)

Expand Down
Loading

0 comments on commit ec5275f

Please sign in to comment.