Skip to content

Commit

Permalink
release radix-operator (#1094)
Browse files Browse the repository at this point in the history
* set certificate private key rotation policy to always

* apply-config-job (#1087)

* Added apply-config pipeline job type

* Added apply-config pipeline job type

* Set version

* Added unit-tests

* fix-apply-config-dns-aliases (#1093)

* Added unit-tests

* Fixed dns-alias deletion

* Added unit-tests

* Set version

---------

Co-authored-by: Nils Gustav Stråbø <[email protected]>
Co-authored-by: Nils Gustav Stråbø <[email protected]>
  • Loading branch information
3 people authored Apr 19, 2024
1 parent 61f4d18 commit 50ffb6a
Show file tree
Hide file tree
Showing 15 changed files with 184 additions and 31 deletions.
4 changes: 2 additions & 2 deletions charts/radix-operator/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
apiVersion: v2
name: radix-operator
version: 1.31.2
appVersion: 1.51.1
version: 1.31.4
appVersion: 1.51.3
kubeVersion: ">=1.24.0"
description: Radix Operator
keywords:
Expand Down
11 changes: 11 additions & 0 deletions pipeline-runner/model/pipelineInfo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,17 @@ func Test_BuildAndDefaultNoPushOnlyPipeline(t *testing.T) {
assert.Equal(t, "run pipelines completed", p.Steps[3].SucceededMsg())
}

func Test_ApplyConfigPipeline(t *testing.T) {
pipelineType, _ := pipeline.GetPipelineFromName(string(v1.ApplyConfig))

p, _ := model.InitPipeline(pipelineType, getPipelineArguments(), prepareTektonPipelineStep, applyConfigStep)
assert.Equal(t, v1.ApplyConfig, p.Definition.Type)
assert.False(t, p.PipelineArguments.PushImage)
assert.Equal(t, 2, len(p.Steps))
assert.Equal(t, "pipelines prepared", p.Steps[0].SucceededMsg())
assert.Equal(t, "config applied", p.Steps[1].SucceededMsg())
}

func Test_GetImageTagNamesFromArgs(t *testing.T) {
pipelineType, _ := pipeline.GetPipelineFromName(string(v1.Deploy))
type scenario struct {
Expand Down
44 changes: 44 additions & 0 deletions pipeline-runner/steps/apply_radixconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,50 @@ func (s *applyConfigTestSuite) Test_Deploy_BuildJobInDeployPiplineShouldFail() {
s.ErrorIs(err, steps.ErrDeployOnlyPipelineDoesNotSupportBuild)
}

func (s *applyConfigTestSuite) Test_ApplyConfig_ShouldNotFail() {
appName := "anyapp"
prepareConfigMapName := "preparecm"
type scenario struct {
name string
componentBuilder *utils.RadixApplicationComponentBuilder
jobComponentBuilder *utils.RadixApplicationJobComponentBuilder
}
scenarios := []scenario{
{name: "no components"},
{name: "with a component", componentBuilder: pointers.Ptr(utils.NewApplicationComponentBuilder().WithPort("any", 8080).WithName("comp1"))},
{name: "with a job-component", jobComponentBuilder: pointers.Ptr(utils.NewApplicationJobComponentBuilder().WithSchedulerPort(pointers.Ptr[int32](8080)).WithName("job1"))},
}

for _, ts := range scenarios {
s.T().Run(ts.name, func(t *testing.T) {
s.SetupTest()
rr := utils.NewRegistrationBuilder().WithName(appName).BuildRR()
_, _ = s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{})
raBuilder := utils.NewRadixApplicationBuilder().
WithAppName(appName).
WithEnvironment("dev", "anybranch")
if ts.componentBuilder != nil {
raBuilder = raBuilder.WithComponent(*ts.componentBuilder)
}
if ts.jobComponentBuilder != nil {
raBuilder = raBuilder.WithJobComponent(*ts.jobComponentBuilder)
}
ra := raBuilder.BuildRA()
s.Require().NoError(internaltest.CreatePreparePipelineConfigMapResponse(s.kubeClient, prepareConfigMapName, appName, ra, nil))

pipeline := model.PipelineInfo{
PipelineArguments: model.PipelineArguments{},
RadixConfigMapName: prepareConfigMapName,
}

applyStep := steps.NewApplyConfigStep()
applyStep.Init(s.kubeClient, s.radixClient, s.kubeUtil, s.promClient, rr)
err := applyStep.Run(&pipeline)
s.NoError(err)
})
}
}

func (s *applyConfigTestSuite) Test_Deploy_ComponentImageTagName() {
appName := "anyapp"
prepareConfigMapName := "preparecm"
Expand Down
14 changes: 13 additions & 1 deletion pipeline-runner/steps/prepare_pipelines.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func (cli *PreparePipelinesStepImplementation) Run(pipelineInfo *model.PipelineI
commitID := pipelineInfo.PipelineArguments.CommitID
appName := cli.GetAppName()
namespace := utils.GetAppNamespace(appName)
log.Info().Msgf("Prepare pipelines app %s for branch %s and commit %s", appName, branch, commitID)
logPipelineInfo(pipelineInfo.Definition.Type, appName, branch, commitID)

if pipelineInfo.IsPipelineType(radixv1.Promote) {
sourceDeploymentGitCommitHash, sourceDeploymentGitBranch, err := cli.getSourceDeploymentGitInfo(appName, pipelineInfo.PipelineArguments.FromEnvironment, pipelineInfo.PipelineArguments.DeploymentName)
Expand Down Expand Up @@ -102,6 +102,18 @@ func (cli *PreparePipelinesStepImplementation) Run(pipelineInfo *model.PipelineI
return cli.jobWaiter.Wait(job)
}

func logPipelineInfo(pipelineType radixv1.RadixPipelineType, appName, branch, commitID string) {
stringBuilder := strings.Builder{}
stringBuilder.WriteString(fmt.Sprintf("Prepare pipeline %s for the app %s", pipelineType, appName))
if len(branch) > 0 {
stringBuilder.WriteString(fmt.Sprintf(", the branch %s", branch))
}
if len(branch) > 0 {
stringBuilder.WriteString(fmt.Sprintf(", the commit %s", commitID))
}
log.Info().Msg(stringBuilder.String())
}

func (cli *PreparePipelinesStepImplementation) getPreparePipelinesJobConfig(pipelineInfo *model.PipelineInfo) *batchv1.Job {
appName := cli.GetAppName()
registration := cli.GetRegistration()
Expand Down
2 changes: 2 additions & 0 deletions pkg/apis/deployment/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4034,6 +4034,7 @@ func Test_ExternalDNS_Legacy_ResourcesMigrated(t *testing.T) {
SecretTemplate: &cmv1.CertificateSecretTemplate{
Labels: map[string]string{kube.RadixAppLabel: appName, kube.RadixExternalAliasFQDNLabel: fqdnAutomation},
},
PrivateKey: &cmv1.CertificatePrivateKey{RotationPolicy: cmv1.RotationPolicyAlways},
}
assert.Equal(t, expectedCertSpec, cert.Spec)
}
Expand Down Expand Up @@ -4097,6 +4098,7 @@ func Test_ExternalDNS_ContainsAllResources(t *testing.T) {
SecretTemplate: &cmv1.CertificateSecretTemplate{
Labels: map[string]string{kube.RadixAppLabel: appName, kube.RadixExternalAliasFQDNLabel: fqdn},
},
PrivateKey: &cmv1.CertificatePrivateKey{RotationPolicy: cmv1.RotationPolicyAlways},
}
assert.Equal(t, expectedCertSpec, cert.Spec)
}
Expand Down
3 changes: 3 additions & 0 deletions pkg/apis/deployment/externaldns.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ func (deploy *Deployment) createOrUpdateExternalDnsCertificate(externalDns radix
SecretTemplate: &cmv1.CertificateSecretTemplate{
Labels: radixlabels.ForExternalDNSTLSSecret(deploy.registration.Name, externalDns),
},
PrivateKey: &cmv1.CertificatePrivateKey{
RotationPolicy: cmv1.RotationPolicyAlways,
},
},
}

Expand Down
5 changes: 3 additions & 2 deletions pkg/apis/environment/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,10 @@ func (env *Environment) handleDeletedRadixEnvironmentDependencies(re *v1.RadixEn
return err
}
env.logger.Debug().Msgf("delete %d RadixDNSAlias(es)", len(radixDNSAliasList.Items))
return env.kubeutil.DeleteRadixDNSAliases(slice.Reduce(radixDNSAliasList.Items, []*v1.RadixDNSAlias{}, func(acc []*v1.RadixDNSAlias, radixDNSAlias v1.RadixDNSAlias) []*v1.RadixDNSAlias {
dnsAliases := slice.Reduce(radixDNSAliasList.Items, []*v1.RadixDNSAlias{}, func(acc []*v1.RadixDNSAlias, radixDNSAlias v1.RadixDNSAlias) []*v1.RadixDNSAlias {
return append(acc, &radixDNSAlias)
})...)
})
return env.kubeutil.DeleteRadixDNSAliases(dnsAliases...)
}

// ApplyNamespace sets up namespace metadata and applies configuration to kubernetes
Expand Down
2 changes: 1 addition & 1 deletion pkg/apis/job/job_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,12 +222,12 @@ func (s *RadixJobTestSuite) TestObjectSynced_PipelineJobCreated() {
fmt.Sprintf("--AZURE_SUBSCRIPTION_ID=%s", s.config.subscriptionID),
"--RADIX_RESERVED_APP_DNS_ALIASES=api=radix-api",
"--RADIX_RESERVED_DNS_ALIASES=grafana",
"--RADIX_FILE_NAME=/workspace/radixconfig.yaml",
fmt.Sprintf("--IMAGE_TAG=%s", imageTag),
fmt.Sprintf("--BRANCH=%s", branch),
fmt.Sprintf("--COMMIT_ID=%s", commitID),
"--PUSH_IMAGE=1",
"--USE_CACHE=",
"--RADIX_FILE_NAME=/workspace/radixconfig.yaml",
},
SecurityContext: &corev1.SecurityContext{
Privileged: pointers.Ptr(false),
Expand Down
12 changes: 5 additions & 7 deletions pkg/apis/job/kubejob.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ func (job *Job) getPipelineJobArguments(appName, jobName string, jobSpec v1.Radi
if job.radixJob.Spec.TektonImage != "" {
radixTektonImage = fmt.Sprintf("%s:%s", tektonImage, job.radixJob.Spec.TektonImage)
}
radixConfigFullName := jobSpec.RadixConfigFullName
if len(radixConfigFullName) == 0 {
radixConfigFullName = fmt.Sprintf("%s/%s", git.Workspace, defaults.DefaultRadixConfigFileName)
}

// Base arguments for all types of pipeline
args := []string{
Expand All @@ -175,32 +179,26 @@ func (job *Job) getPipelineJobArguments(appName, jobName string, jobSpec v1.Radi
fmt.Sprintf("--%s=%s", defaults.AzureSubscriptionIdEnvironmentVariable, subscriptionId),
fmt.Sprintf("--%s=%s", defaults.RadixReservedAppDNSAliasesEnvironmentVariable, maps.ToString(job.config.DNSConfig.ReservedAppDNSAliases)),
fmt.Sprintf("--%s=%s", defaults.RadixReservedDNSAliasesEnvironmentVariable, strings.Join(job.config.DNSConfig.ReservedDNSAliases, ",")),
fmt.Sprintf("--%s=%s", defaults.RadixConfigFileEnvironmentVariable, radixConfigFullName),
}

radixConfigFullName := jobSpec.RadixConfigFullName
if len(radixConfigFullName) == 0 {
radixConfigFullName = fmt.Sprintf("%s/%s", git.Workspace, defaults.DefaultRadixConfigFileName)
}
switch pipeline.Type {
case v1.BuildDeploy, v1.Build:
args = append(args, fmt.Sprintf("--%s=%s", defaults.RadixImageTagEnvironmentVariable, jobSpec.Build.ImageTag))
args = append(args, fmt.Sprintf("--%s=%s", defaults.RadixBranchEnvironmentVariable, jobSpec.Build.Branch))
args = append(args, fmt.Sprintf("--%s=%s", defaults.RadixCommitIdEnvironmentVariable, jobSpec.Build.CommitID))
args = append(args, fmt.Sprintf("--%s=%s", defaults.RadixPushImageEnvironmentVariable, getPushImageTag(jobSpec.Build.PushImage)))
args = append(args, fmt.Sprintf("--%s=%s", defaults.RadixUseCacheEnvironmentVariable, useImageBuilderCache))
args = append(args, fmt.Sprintf("--%s=%s", defaults.RadixConfigFileEnvironmentVariable, radixConfigFullName))
case v1.Promote:
args = append(args, fmt.Sprintf("--%s=%s", defaults.RadixPromoteDeploymentEnvironmentVariable, jobSpec.Promote.DeploymentName))
args = append(args, fmt.Sprintf("--%s=%s", defaults.RadixPromoteFromEnvironmentEnvironmentVariable, jobSpec.Promote.FromEnvironment))
args = append(args, fmt.Sprintf("--%s=%s", defaults.RadixPromoteToEnvironmentEnvironmentVariable, jobSpec.Promote.ToEnvironment))
args = append(args, fmt.Sprintf("--%s=%s", defaults.RadixConfigFileEnvironmentVariable, radixConfigFullName))
case v1.Deploy:
args = append(args, fmt.Sprintf("--%s=%s", defaults.RadixPromoteToEnvironmentEnvironmentVariable, jobSpec.Deploy.ToEnvironment))
args = append(args, fmt.Sprintf("--%s=%s", defaults.RadixCommitIdEnvironmentVariable, jobSpec.Deploy.CommitID))
for componentName, imageTagName := range jobSpec.Deploy.ImageTagNames {
args = append(args, fmt.Sprintf("--%s=%s=%s", defaults.RadixImageTagNameEnvironmentVariable, componentName, imageTagName))
}
args = append(args, fmt.Sprintf("--%s=%s", defaults.RadixConfigFileEnvironmentVariable, radixConfigFullName))
args = append(args, fmt.Sprintf("--%s=%s", defaults.RadixComponentsToDeployVariable, strings.Join(jobSpec.Deploy.ComponentsToDeploy, ",")))
}

Expand Down
12 changes: 8 additions & 4 deletions pkg/apis/kube/radix_dns_alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package kube

import (
"context"
"errors"
"fmt"

"github.com/equinor/radix-common/utils/slice"
Expand Down Expand Up @@ -84,11 +85,14 @@ func (kubeutil *Kube) UpdateRadixDNSAlias(radixDNSAlias *radixv1.RadixDNSAlias)

// DeleteRadixDNSAliases Delete RadixDNSAliases
func (kubeutil *Kube) DeleteRadixDNSAliases(radixDNSAliases ...*radixv1.RadixDNSAlias) error {
var errs []error
for _, radixDNSAlias := range radixDNSAliases {
err := kubeutil.radixclient.RadixV1().RadixDNSAliases().Delete(context.Background(), radixDNSAlias.GetName(), metav1.DeleteOptions{})
if err != nil {
return err
if radixDNSAlias.ObjectMeta.DeletionTimestamp != nil {
continue
}
if err := kubeutil.radixclient.RadixV1().RadixDNSAliases().Delete(context.Background(), radixDNSAlias.GetName(), metav1.DeleteOptions{}); err != nil {
errs = append(errs, err)
}
}
return nil
return errors.Join(errs...)
}
6 changes: 5 additions & 1 deletion pkg/apis/pipeline/pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ func GetSupportedPipelines() []Definition {
PreparePipelinesStep,
ApplyConfigStep,
RunPipelinesStep,
DeployStep}}}
DeployStep}},
{v1.ApplyConfig, []StepType{
PreparePipelinesStep,
ApplyConfigStep}},
}
}

// GetPipelineFromName Gets pipeline from string
Expand Down
4 changes: 4 additions & 0 deletions pkg/apis/pipeline/pipeline_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ func Test_StringToPipelineToString(t *testing.T) {
p, _ = GetPipelineFromName("build")

assert.Equal(t, "build", string(p.Type))

p, _ = GetPipelineFromName("apply-config")

assert.Equal(t, "apply-config", string(p.Type))
}
1 change: 1 addition & 0 deletions pkg/apis/radix/v1/radixjobtypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const (
BuildDeploy RadixPipelineType = "build-deploy"
Promote RadixPipelineType = "promote"
Deploy RadixPipelineType = "deploy"
ApplyConfig RadixPipelineType = "apply-config"
)

// RadixBuildSpec is the spec for a build job
Expand Down
48 changes: 41 additions & 7 deletions radix-operator/dnsalias/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"reflect"

radixutils "github.com/equinor/radix-common/utils"
"github.com/equinor/radix-common/utils/slice"
"github.com/equinor/radix-operator/pkg/apis/metrics"
radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1"
radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels"
Expand Down Expand Up @@ -60,6 +61,7 @@ func NewController(kubeClient kubernetes.Interface,
addEventHandlersForRadixDeployments(radixInformerFactory, controller, radixClient, &logger)
addEventHandlersForIngresses(kubeInformerFactory, controller, &logger)
addEventHandlersForRadixRegistrations(radixInformerFactory, controller, radixClient, &logger)
addEventHandlersForRadixApplication(radixInformerFactory, controller, radixClient, &logger)
return controller
}

Expand All @@ -72,15 +74,46 @@ func addEventHandlersForRadixRegistrations(radixInformerFactory informers.Shared
if oldRR.GetResourceVersion() == newRR.GetResourceVersion() &&
radixutils.ArrayEqualElements(oldRR.Spec.AdGroups, newRR.Spec.AdGroups) &&
radixutils.ArrayEqualElements(oldRR.Spec.ReaderAdGroups, newRR.Spec.ReaderAdGroups) {
return // updating RadixDeployment has the same resource version. Do nothing.
return // updating RadixRegistration has the same resource version. Do nothing.
}
enqueueRadixDNSAliasesForAppName(controller, radixClient, newRR.GetName(), logger)
},
}); err != nil {
panic(err)
}
}

func addEventHandlersForRadixApplication(radixInformerFactory informers.SharedInformerFactory, controller *common.Controller, radixClient radixclient.Interface, logger *zerolog.Logger) {
informer := radixInformerFactory.Radix().V1().RadixApplications()
if _, err := informer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
UpdateFunc: func(oldObj, newObj interface{}) {
oldRA := oldObj.(*radixv1.RadixApplication)
newRA := newObj.(*radixv1.RadixApplication)
if oldRA.GetResourceVersion() == newRA.GetResourceVersion() ||
equalDNSAliases(oldRA.Spec.DNSAlias, newRA.Spec.DNSAlias) {
return // updating RadixApplication has the same resource version and DNS aliases. Do nothing.
}
enqueueRadixDNSAliasesForRadixRegistration(controller, radixClient, newRR, logger)
enqueueRadixDNSAliasesForAppName(controller, radixClient, newRA.GetName(), logger)
},
}); err != nil {
panic(err)
}
}

func equalDNSAliases(dnsAliases1, dnsAliases2 []radixv1.DNSAlias) bool {
if len(dnsAliases1) != len(dnsAliases2) {
return false
}
dnsAlias1Map := slice.Reduce(dnsAliases1, make(map[string]radixv1.DNSAlias), func(acc map[string]radixv1.DNSAlias, dnsAlias radixv1.DNSAlias) map[string]radixv1.DNSAlias {
acc[dnsAlias.Alias] = dnsAlias
return acc
})
return slice.All(dnsAliases2, func(dnsAlias2 radixv1.DNSAlias) bool {
dnsAlias1, ok := dnsAlias1Map[dnsAlias2.Alias]
return ok && dnsAlias1.Environment == dnsAlias2.Environment && dnsAlias1.Component == dnsAlias2.Component
})
}

func addEventHandlersForIngresses(kubeInformerFactory kubeinformers.SharedInformerFactory, controller *common.Controller, logger *zerolog.Logger) {
ingressInformer := kubeInformerFactory.Networking().V1().Ingresses()
if _, err := ingressInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
Expand Down Expand Up @@ -192,11 +225,11 @@ func enqueueRadixDNSAliasesForRadixDeployment(controller *common.Controller, rad
}
}

func enqueueRadixDNSAliasesForRadixRegistration(controller *common.Controller, radixClient radixclient.Interface, rr *radixv1.RadixRegistration, logger *zerolog.Logger) {
logger.Debug().Msgf("Added or updated an RadixRegistration %s. Enqueue relevant RadixDNSAliases", rr.GetName())
radixDNSAliases, err := getRadixDNSAliasForApp(radixClient, rr.GetName())
func enqueueRadixDNSAliasesForAppName(controller *common.Controller, radixClient radixclient.Interface, appName string, logger *zerolog.Logger) {
logger.Debug().Msgf("Added or updated an RadixRegistration %s. Enqueue relevant RadixDNSAliases", appName)
radixDNSAliases, err := getRadixDNSAliasForApp(radixClient, appName)
if err != nil {
logger.Error().Err(err).Msgf("failed to get list of RadixDNSAliases for the application %s", rr.GetName())
logger.Error().Err(err).Msgf("failed to get list of RadixDNSAliases for the application %s", appName)
return
}
for _, radixDNSAlias := range radixDNSAliases {
Expand Down Expand Up @@ -233,7 +266,8 @@ func deepEqual(old, new *radixv1.RadixDNSAlias) bool {
return reflect.DeepEqual(new.Spec, old.Spec) &&
reflect.DeepEqual(new.ObjectMeta.Labels, old.ObjectMeta.Labels) &&
reflect.DeepEqual(new.ObjectMeta.Annotations, old.ObjectMeta.Annotations) &&
reflect.DeepEqual(new.ObjectMeta.Finalizers, old.ObjectMeta.Finalizers)
reflect.DeepEqual(new.ObjectMeta.Finalizers, old.ObjectMeta.Finalizers) &&
reflect.DeepEqual(new.ObjectMeta.DeletionTimestamp, old.ObjectMeta.DeletionTimestamp)
}

func getOwner(radixClient radixclient.Interface, _, name string) (interface{}, error) {
Expand Down
Loading

0 comments on commit 50ffb6a

Please sign in to comment.