Skip to content

Commit

Permalink
add support for pipelines controller statefulset ordinals
Browse files Browse the repository at this point in the history
  • Loading branch information
jkhelil committed Sep 30, 2024
1 parent 229dca3 commit 817fd30
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 0 deletions.
5 changes: 5 additions & 0 deletions pkg/apis/operator/v1alpha1/tektonpipeline_defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ func (p *Pipeline) setDefaults() {
p.EnableGitResolver = ptr.Bool(true)
}

// Statefulset Ordinals
if p.Performance.StatefulsetOrdinals == nil {
p.Performance.StatefulsetOrdinals = ptr.Bool(false)
}

// run platform specific defaulting
if IsOpenShiftPlatform() {
p.openshiftDefaulting()
Expand Down
8 changes: 8 additions & 0 deletions pkg/apis/operator/v1alpha1/tektonpipeline_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ type PipelinePerformanceProperties struct {
// +optional
PipelinePerformanceLeaderElectionConfig `json:",inline"`
// +optional
PipelinePerformanceStatefulsetOrdinalsConfig `json:",inline"`
// +optional
PipelineDeploymentPerformanceArgs `json:",inline"`
// +optional
Replicas *int32 `json:"replicas,omitempty"`
Expand All @@ -201,6 +203,12 @@ type PipelinePerformanceLeaderElectionConfig struct {
Buckets *uint `json:"buckets,omitempty"`
}

// allow to configure pipelines controller ha mode to statefulset ordinals
type PipelinePerformanceStatefulsetOrdinalsConfig struct {
//if is true, enable StatefulsetOrdinals mode
StatefulsetOrdinals *bool `json:"statefulset-ordinals"`
}

// performance configurations to tune the performance of the pipeline controller
// these properties will be added/updated as arguments in pipeline controller deployment
// https://tekton.dev/docs/pipelines/tekton-controller-performance-configuration/
Expand Down
10 changes: 10 additions & 0 deletions pkg/apis/operator/v1alpha1/tektonpipeline_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,5 +116,15 @@ func (prof *PipelinePerformanceProperties) validate(path string) *apis.FieldErro
}
}

// check for StatefulsetOrdinals and Replicas
if prof.StatefulsetOrdinals != nil && *prof.StatefulsetOrdinals {
if prof.Replicas != nil {
replicas := uint(*prof.Replicas)
if *prof.Buckets != replicas {
errs = errs.Also(apis.ErrInvalidValue(*prof.Replicas, fmt.Sprintf("%s.replicas", path), "replicas must equal buckets for statefulset ordinals"))
}
}
}

return errs
}
22 changes: 22 additions & 0 deletions pkg/apis/operator/v1alpha1/tektonpipeline_validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,11 @@ func TestTektonPipelinePerformancePropertiesValidate(t *testing.T) {
return &value
}

// return pointer value for replicas
getReplicas := func(value int32) *int32 {
return &value
}

// validate buckets minimum range
tp.Spec.PipelineProperties.Performance = PipelinePerformanceProperties{}
tp.Spec.PipelineProperties.Performance.DisableHA = false
Expand Down Expand Up @@ -310,4 +315,21 @@ func TestTektonPipelinePerformancePropertiesValidate(t *testing.T) {
tp.Spec.PipelineProperties.Performance.Buckets = getBuckets(10)
errs = tp.Validate(context.TODO())
assert.Equal(t, "", errs.Error())

// validate buckets is equal to replicas when StatefulsetOrdinals is true
tp.Spec.PipelineProperties.Performance = PipelinePerformanceProperties{}
tp.Spec.PipelineProperties.Performance.DisableHA = false
bucketValue := uint(5)
tp.Spec.PipelineProperties.Performance.Buckets = getBuckets(bucketValue)
replicaValue := int32(5)
tp.Spec.PipelineProperties.Performance.Replicas = getReplicas(replicaValue)
statefulsetOrdinals := true
tp.Spec.PipelineProperties.Performance.StatefulsetOrdinals = &statefulsetOrdinals
errs = tp.Validate(context.TODO())
assert.Equal(t, "", errs.Error())

// validate error when buckets is not equal to replicas
tp.Spec.PipelineProperties.Performance.Replicas = getReplicas(3)
errs = tp.Validate(context.TODO())
assert.Equal(t, "invalid value 3: spec.performance.replicas must equal buckets", errs.Error())
}
97 changes: 97 additions & 0 deletions pkg/reconciler/common/transformers.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ const (

runAsNonRootValue = true
allowPrivilegedEscalationValue = false

tektonPipelinesControllerName = "tekton-pipelines-controller"
tektonPipelinesServiceName = "tekton-pipelines-controller"
tektonPipelinesControllerStatefulServiceName = "STATEFUL_SERVICE_NAME"
tektonPipelinesControllerStatefulControllerOrdinal = "STATEFUL_CONTROLLER_ORDINAL"
)

// transformers that are common to all components.
Expand Down Expand Up @@ -1013,3 +1018,95 @@ func AddSecretData(data map[string][]byte, annotations map[string]string) mf.Tra
return nil
}
}

// ConvertDeploymentToStatefulSet converts a Deployment tekton-pipelines-controller to a StatefulSet
func ConvertDeploymentToStatefulSet() mf.Transformer {
return func(u *unstructured.Unstructured) error {
// Check if the resource is a Deployment and has the correct name
if u.GetKind() != "Deployment" || u.GetName() != tektonPipelinesControllerName {
return nil
}

// Convert the unstructured object to a Deployment
d := &appsv1.Deployment{}
err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, d)
if err != nil {
return err
}

// Create a new StatefulSet from the Deployment
ss := &appsv1.StatefulSet{
ObjectMeta: d.ObjectMeta,
Spec: appsv1.StatefulSetSpec{
Selector: d.Spec.Selector,
ServiceName: tektonPipelinesServiceName,
Template: d.Spec.Template,
Replicas: d.Spec.Replicas,
UpdateStrategy: appsv1.StatefulSetUpdateStrategy{
Type: appsv1.RollingUpdateStatefulSetStrategyType,
},
},
}

// Convert the StatefulSet back to an unstructured object
unstrObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(ss)
if err != nil {
return err
}

// Update the original unstructured object with the StatefulSet content
u.SetUnstructuredContent(unstrObj)
u.SetKind("StatefulSet")

return nil
}
}

// AddStatefulEnvVars adds environment variables to tekton-pipelines-controller statefulset
func AddStatefulEnvVars() mf.Transformer {
return func(u *unstructured.Unstructured) error {
// Check if the resource is a StatefulSet
if u.GetKind() != "StatefulSet" || u.GetName() != tektonPipelinesControllerName {
return nil
}

// Convert the unstructured object to a StatefulSet
ss := &appsv1.StatefulSet{}
err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, ss)
if err != nil {
return err
}

// Define the new environment variables
newEnvVars := []corev1.EnvVar{
{
Name: tektonPipelinesControllerStatefulServiceName,
Value: tektonPipelinesServiceName,
},
{
Name: tektonPipelinesControllerStatefulControllerOrdinal,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.name",
},
},
},
}

// Add the new environment variables to the first container
if len(ss.Spec.Template.Spec.Containers) > 0 {
ss.Spec.Template.Spec.Containers[0].Env = append(ss.Spec.Template.Spec.Containers[0].Env, newEnvVars...)
}

// Convert the updated StatefulSet back to an unstructured object
unstrObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(ss)
if err != nil {
return err
}

// Update the original unstructured object with the modified content
u.SetUnstructuredContent(unstrObj)

return nil
}
}
4 changes: 4 additions & 0 deletions pkg/reconciler/kubernetes/tektonpipeline/transform.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ func filterAndTransform(extension common.Extension) client.FilterAndTransform {
updatePerformanceFlagsInDeployment(pipeline),
updateResolverConfigEnvironmentsInDeployment(pipeline),
}
if pipeline.Spec.Performance.StatefulsetOrdinals != nil && *pipeline.Spec.Performance.StatefulsetOrdinals {
extra = append(extra, common.ConvertDeploymentToStatefulSet(), common.AddStatefulEnvVars())
}

trns = append(trns, extra...)

if err := common.Transform(ctx, manifest, instance, trns...); err != nil {
Expand Down

0 comments on commit 817fd30

Please sign in to comment.