Skip to content

Commit

Permalink
[SECURESIGN-1393] Migrate rekor
Browse files Browse the repository at this point in the history
  • Loading branch information
bouskaJ committed Jan 17, 2025
1 parent e7134b1 commit 14b456e
Show file tree
Hide file tree
Showing 7 changed files with 351 additions and 468 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ import (
rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1"
"github.com/securesign/operator/internal/controller/common/action"
"github.com/securesign/operator/internal/controller/common/utils"
"github.com/securesign/operator/internal/controller/common/utils/kubernetes"
"github.com/securesign/operator/internal/controller/common/utils/kubernetes/ensure"
"github.com/securesign/operator/internal/controller/constants"
"github.com/securesign/operator/internal/controller/labels"
"github.com/securesign/operator/internal/controller/rekor/actions"
"golang.org/x/exp/maps"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)

func NewBackfillRedisCronJobAction() action.Action[*rhtasv1alpha1.Rekor] {
Expand All @@ -37,67 +40,45 @@ func (i backfillRedisCronJob) CanHandle(_ context.Context, instance *rhtasv1alph

func (i backfillRedisCronJob) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) *action.Result {
var (
err error
updated bool
err error
result controllerutil.OperationResult
)

if _, err := cron.ParseStandard(instance.Spec.BackFillRedis.Schedule); err != nil {
return i.Failed(fmt.Errorf("could not create backfill redis cron job: %w", err))
return i.Error(ctx, reconcile.TerminalError(fmt.Errorf("could not create backfill redis cron job: %w", err)), instance,
metav1.Condition{
Type: actions.RedisCondition,
Status: metav1.ConditionFalse,
Reason: constants.Failure,
Message: err.Error(),
},
)
}

labels := labels.For(actions.BackfillRedisCronJobName, actions.BackfillRedisCronJobName, instance.Name)
backfillRedisCronJob := &batchv1.CronJob{
ObjectMeta: metav1.ObjectMeta{
Name: actions.BackfillRedisCronJobName,
Namespace: instance.Namespace,
Labels: labels,
},
Spec: batchv1.CronJobSpec{
Schedule: instance.Spec.BackFillRedis.Schedule,
JobTemplate: batchv1.JobTemplateSpec{
Spec: batchv1.JobSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
ServiceAccountName: actions.RBACName,
RestartPolicy: "OnFailure",
Containers: []corev1.Container{
{
Name: actions.BackfillRedisCronJobName,
Image: constants.BackfillRedisImage,
Command: []string{"/bin/sh", "-c"},
Args: []string{
fmt.Sprintf(`endIndex=$(curl -sS http://%s/api/v1/log | sed -E 's/.*"treeSize":([0-9]+).*/\1/'); endIndex=$((endIndex-1)); if [ $endIndex -lt 0 ]; then echo "info: no rekor entries found"; exit 0; fi; backfill-redis --redis-hostname=rekor-redis --redis-port=6379 --rekor-address=http://%s --start=0 --end=$endIndex`, actions.ServerComponentName, actions.ServerComponentName),
},
},
},
},
},
},

if result, err = kubernetes.CreateOrUpdate(ctx, i.Client,
&batchv1.CronJob{
ObjectMeta: metav1.ObjectMeta{
Name: actions.BackfillRedisCronJobName,
Namespace: instance.Namespace,
},
},
i.ensureBacfillCronJob(instance),
ensure.ControllerReference[*batchv1.CronJob](instance, i.Client),
ensure.Labels[*batchv1.CronJob](maps.Keys(labels), labels),
); err != nil {
return i.Error(ctx, fmt.Errorf("could not create %s CronJob: %w", actions.BackfillRedisCronJobName, err), instance,
metav1.Condition{
Type: actions.RedisCondition,
Status: metav1.ConditionFalse,
Reason: constants.Failure,
Message: err.Error(),
},
)
}

if err = controllerutil.SetControllerReference(instance, backfillRedisCronJob, i.Client.Scheme()); err != nil {
return i.Failed(fmt.Errorf("could not set controller reference for backfill redis cron job: %w", err))
}

if updated, err = i.Ensure(ctx, backfillRedisCronJob); err != nil {
meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{
Type: actions.RedisCondition,
Status: metav1.ConditionFalse,
Reason: constants.Failure,
Message: err.Error(),
})
meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{
Type: constants.Ready,
Status: metav1.ConditionFalse,
Reason: constants.Failure,
Message: err.Error(),
})
return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create backfill redis cron job: %w", err), instance)
}

if updated {
if result != controllerutil.OperationResultNone {
meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{
Type: constants.Ready,
Status: metav1.ConditionFalse,
Expand All @@ -109,3 +90,21 @@ func (i backfillRedisCronJob) Handle(ctx context.Context, instance *rhtasv1alpha
return i.Continue()
}
}

func (i backfillRedisCronJob) ensureBacfillCronJob(instance *rhtasv1alpha1.Rekor) func(*batchv1.CronJob) error {
return func(job *batchv1.CronJob) error {
job.Spec.Schedule = instance.Spec.BackFillRedis.Schedule
templateSpec := &job.Spec.JobTemplate.Spec.Template.Spec
templateSpec.ServiceAccountName = actions.RBACName
templateSpec.RestartPolicy = "OnFailure"

container := kubernetes.FindContainerByNameOrCreate(templateSpec, actions.BackfillRedisCronJobName)

container.Image = constants.BackfillRedisImage
container.Command = []string{"/bin/sh", "-c"}
container.Args = []string{
fmt.Sprintf(`endIndex=$(curl -sS http://%s/api/v1/log | sed -E 's/.*"treeSize":([0-9]+).*/\1/'); endIndex=$((endIndex-1)); if [ $endIndex -lt 0 ]; then echo "info: no rekor entries found"; exit 0; fi; backfill-redis --redis-hostname=rekor-redis --redis-port=6379 --rekor-address=http://%s --start=0 --end=$endIndex`, actions.ServerComponentName, actions.ServerComponentName),
}
return nil
}
}
108 changes: 86 additions & 22 deletions internal/controller/rekor/actions/redis/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,25 @@ import (
"fmt"

"github.com/securesign/operator/internal/controller/common/action"
cutils "github.com/securesign/operator/internal/controller/common/utils"
"github.com/securesign/operator/internal/controller/common/utils/kubernetes"
"github.com/securesign/operator/internal/controller/common/utils/kubernetes/ensure"
"github.com/securesign/operator/internal/controller/constants"
"github.com/securesign/operator/internal/controller/labels"
"github.com/securesign/operator/internal/controller/rekor/actions"
"github.com/securesign/operator/internal/controller/rekor/utils"
"golang.org/x/exp/maps"
v1 "k8s.io/api/apps/v1"
core "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"

rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1"
)

const storageVolumeName = "storage"

func NewDeployAction() action.Action[*rhtasv1alpha1.Rekor] {
return &deployAction{}
}
Expand All @@ -35,32 +43,34 @@ func (i deployAction) CanHandle(_ context.Context, instance *rhtasv1alpha1.Rekor

func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) *action.Result {
var (
err error
updated bool
err error
result controllerutil.OperationResult
)
labels := labels.For(actions.RedisComponentName, actions.RedisDeploymentName, instance.Name)
dp := utils.CreateRedisDeployment(instance.Namespace, actions.RedisDeploymentName, actions.RBACName, labels)
if err = controllerutil.SetControllerReference(instance, dp, i.Client.Scheme()); err != nil {
return i.Failed(fmt.Errorf("could not set controller reference for Deployment: %w", err))
}

if updated, err = i.Ensure(ctx, dp); err != nil {
meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{
Type: actions.RedisCondition,
Status: metav1.ConditionFalse,
Reason: constants.Failure,
Message: err.Error(),
})
meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{
Type: constants.Ready,
Status: metav1.ConditionFalse,
Reason: constants.Failure,
Message: err.Error(),
})
return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create Rekor redis: %w", err), instance)
if result, err = kubernetes.CreateOrUpdate(ctx, i.Client,
&v1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: actions.RedisDeploymentName,
Namespace: instance.Namespace,
},
},
i.ensureRedisDeployment(actions.RBACName, labels),
ensure.ControllerReference[*v1.Deployment](instance, i.Client),
ensure.Labels[*v1.Deployment](maps.Keys(labels), labels),
ensure.Proxy(),
); err != nil {
return i.Error(ctx, fmt.Errorf("could not create %s deployment: %w", actions.RedisDeploymentName, err), instance,
metav1.Condition{
Type: actions.RedisCondition,
Status: metav1.ConditionFalse,
Reason: constants.Failure,
Message: err.Error(),
},
)
}

if updated {
if result != controllerutil.OperationResultNone {
meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{
Type: actions.RedisCondition,
Status: metav1.ConditionFalse,
Expand All @@ -73,3 +83,57 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor)
}

}

func (i deployAction) ensureRedisDeployment(sa string, labels map[string]string) func(*v1.Deployment) error {
return func(dp *v1.Deployment) error {

spec := &dp.Spec
spec.Replicas = cutils.Pointer[int32](1)
spec.Selector = &metav1.LabelSelector{
MatchLabels: labels,
}

template := &spec.Template
template.Labels = labels
template.Spec.ServiceAccountName = sa

container := kubernetes.FindContainerByNameOrCreate(&template.Spec, actions.RedisDeploymentName)
container.Image = constants.RekorRedisImage
port := kubernetes.FindPortByNameOrCreate(container, "redis")
port.Protocol = core.ProtocolTCP
port.ContainerPort = 6379

if container.LivenessProbe == nil {
container.LivenessProbe = &core.Probe{}
}
if container.LivenessProbe.HTTPGet == nil {
container.LivenessProbe.HTTPGet = &core.HTTPGetAction{}
}
container.LivenessProbe.HTTPGet.Path = "/healthz"
container.LivenessProbe.HTTPGet.Port = intstr.FromInt32(5555)

if container.ReadinessProbe == nil {
container.ReadinessProbe = &core.Probe{}
}
if container.ReadinessProbe.Exec == nil {
container.ReadinessProbe.Exec = &core.ExecAction{}
}

container.ReadinessProbe.Exec.Command = []string{
"/bin/sh",
"-c",
"-i",
"test $(redis-cli -h 127.0.0.1 ping) = 'PONG'",
}
container.ReadinessProbe.InitialDelaySeconds = 5

volumeMount := kubernetes.FindVolumeMountByNameOrCreate(container, storageVolumeName)
volumeMount.MountPath = "/data"

volume := kubernetes.FindVolumeByNameOrCreate(&template.Spec, storageVolumeName)
if volume.EmptyDir == nil {
volume.EmptyDir = &core.EmptyDirVolumeSource{}
}
return nil
}
}
Loading

0 comments on commit 14b456e

Please sign in to comment.