Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(feat): automatically delete temporary resources #248

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion api/v1/agentconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ type AgentConfigSpec struct {
// +optional
VolumeSize string `json:"volumeSize,omitempty" mapstructure:"volumeSize,omitempty"`

// TTLSecondsAfterFinished set the time limit of the lifetime of a Job
// that has finished execution.
// +kubebuilder:default:=600
TTLSecondsAfterFinished *int32 `json:"ttlSecondsAfterFinished,omitempty" mapstructure:"ttlSecondsAftterFinished,omitempty"`
schristoff marked this conversation as resolved.
Show resolved Hide resolved

// PullPolicy specifies when to pull the Porter Agent image. The default
// is to use PullAlways when the tag is canary or latest, and PullIfNotPresent
// otherwise.
Expand Down Expand Up @@ -327,11 +332,16 @@ func (c AgentConfigSpecAdapter) GetInstallationServiceAccount() string {
return c.original.InstallationServiceAccount
}

// SetRetryAnnotation flags the resource to retry its last operation.
// GetRetryLimit returns the config value of RetryLimit
func (c *AgentConfigSpecAdapter) GetRetryLimit() *int32 {
return c.original.RetryLimit
}

// GetTTLSecondsAfterFinished returns the config value of TTLSecondsAfterFinished
func (c *AgentConfigSpecAdapter) GetTTLSecondsAfterFinished() *int32 {
return c.original.TTLSecondsAfterFinished
}

func (c AgentConfigSpecAdapter) ToPorterDocument() ([]byte, error) {
raw := struct {
SchemaType string `yaml:"schemaType"`
Expand Down
22 changes: 22 additions & 0 deletions api/v1/agentconfig_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,28 @@ func TestAgentConfigSpecAdapter_GetRetryLimit(t *testing.T) {
}
}

func TestAgentConfigSpecAdapter_GetTTLSecondsAfterFinished(t *testing.T) {
// var testdataDefault int32 = 600
var testdatauserSubmitted int32 = 700
testCases := []struct {
name string
TTLSecondsAfterFinished *int32
expected *int32
}{
// {name: "default", TTLSecondsAfterFinished: nil, expected: &testdataDefault},
schristoff marked this conversation as resolved.
Show resolved Hide resolved
{name: "user submitted", TTLSecondsAfterFinished: &testdatauserSubmitted, expected: &testdatauserSubmitted},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
adapter := NewAgentConfigSpecAdapter(AgentConfigSpec{
TTLSecondsAfterFinished: tc.TTLSecondsAfterFinished,
})
result := adapter.GetTTLSecondsAfterFinished()
schristoff marked this conversation as resolved.
Show resolved Hide resolved
require.Equal(t, tc.expected, result)
})
}
}

func TestHashString(t *testing.T) {
str := hashString("fake-string")
assert.Equal(t, "ab19e45285992b247dd281213f803479", str)
Expand Down
5 changes: 5 additions & 0 deletions api/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions config/crd/bases/getporter.org_agentconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ spec:
Porter will request when running the Porter Agent. It is used to
determine what the storage class will be for the volume requested
type: string
ttlSecondsAfterFinished:
default: 600
description: TTLSecondsAfterFinished set the time limit of the lifetime
of a Job that has finished execution.
format: int32
type: integer
volumeSize:
description: VolumeSize is the size of the persistent volume that
Porter will request when running the Porter Agent. It is used to
Expand Down
28 changes: 10 additions & 18 deletions controllers/agentaction_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)

// +kubebuilder:rbac:groups=getporter.org,resources=agentconfigs,verbs=get;list;watch;create;update;patch;delete
Expand Down Expand Up @@ -301,8 +302,7 @@ func (r *AgentActionReconciler) createConfigSecret(ctx context.Context, log logr
ObjectMeta: metav1.ObjectMeta{
GenerateName: action.Name + "-",
Namespace: action.Namespace,
Labels: labels,
},
Labels: labels},
Type: corev1.SecretTypeOpaque,
Immutable: ptr.To(true),
Data: map[string][]byte{
Expand Down Expand Up @@ -337,8 +337,7 @@ func (r *AgentActionReconciler) createWorkdirSecret(ctx context.Context, log log
ObjectMeta: metav1.ObjectMeta{
GenerateName: action.Name + "-",
Namespace: action.Namespace,
Labels: labels,
},
Labels: labels},
Type: corev1.SecretTypeOpaque,
Immutable: ptr.To(true),
Data: action.Spec.Files,
Expand Down Expand Up @@ -407,21 +406,11 @@ func (r *AgentActionReconciler) createAgentJob(ctx context.Context, log logr.Log
ObjectMeta: metav1.ObjectMeta{
GenerateName: action.Name + "-",
Namespace: action.Namespace,
Labels: labels,
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: action.APIVersion,
Kind: action.Kind,
Name: action.Name,
UID: action.UID,
Controller: ptr.To(true),
BlockOwnerDeletion: ptr.To(true),
},
},
},
Labels: labels},
Spec: batchv1.JobSpec{
Completions: ptr.To(int32(1)),
BackoffLimit: agentCfg.GetRetryLimit(),
Completions: ptr.To(int32(1)),
BackoffLimit: agentCfg.GetRetryLimit(),
TTLSecondsAfterFinished: agentCfg.GetTTLSecondsAfterFinished(),
schristoff marked this conversation as resolved.
Show resolved Hide resolved
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
GenerateName: action.Name + "-",
Expand Down Expand Up @@ -461,6 +450,9 @@ func (r *AgentActionReconciler) createAgentJob(ctx context.Context, log logr.Log
},
},
}
if err := controllerutil.SetControllerReference(action, &porterJob, r.Scheme); err != nil {
return porterJob, errors.Wrap(err, "error attaching controller reference to agent job")
}

if err := r.Create(ctx, &porterJob); err != nil {
// If we can't create the job, try to log the job's yaml to help with troubleshooting
Expand Down
1 change: 1 addition & 0 deletions controllers/agentaction_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ func TestAgentActionReconciler_createAgentVolume(t *testing.T) {
}
spec := porterv1.NewAgentConfigSpecAdapter(agentCfg)
pvc, err := controller.createAgentVolume(context.Background(), logr.Discard(), action, spec)

require.NoError(t, err)

// Verify the pvc properties
Expand Down
63 changes: 26 additions & 37 deletions controllers/agentconfig_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/utils/ptr"

ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
Expand Down Expand Up @@ -62,6 +61,7 @@ func (r *AgentConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request)
}
return ctrl.Result{}, err
}

agentCfg := porterv1.NewAgentConfigAdapter(*agentCfgData)

log = log.WithValues("resourceVersion", agentCfg.ResourceVersion, "generation", agentCfg.Generation, "observedGeneration", agentCfg.Status.ObservedGeneration, "status", agentCfg.Status.Ready)
Expand All @@ -87,8 +87,12 @@ func (r *AgentConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request)
if err != nil {
return ctrl.Result{}, err
}
if processed {

if processed || agentCfg.DeletionTimestamp != nil {
err = removeAgentCfgFinalizer(ctx, log, r.Client, agentCfg)
if err != nil {
return ctrl.Result{}, err
}
log.V(Log4Debug).Info("Reconciliation complete: Finalizer has been removed from the AgentConfig.")
return ctrl.Result{}, err
}
Expand Down Expand Up @@ -132,11 +136,6 @@ func (r *AgentConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request)
if err != nil {
return ctrl.Result{}, err
}
if updated {
// if we added a finalizer, stop processing and we will finish when the updated resource is reconciled
log.V(Log4Debug).Info("Reconciliation complete: A finalizer has been set on the agent config.")
return ctrl.Result{}, nil
}

pvc, created, err := r.createEmptyPluginVolume(ctx, log, agentCfg)
if err != nil {
Expand All @@ -145,12 +144,19 @@ func (r *AgentConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request)
if created {
log.V(Log4Debug).Info("Created new temporary persistent volume claim.", "name", pvc.Name)
}

// Use porter to finish reconciling the agent config
err = r.applyAgentConfig(ctx, log, pvc, agentCfg)
if err != nil {
return ctrl.Result{}, err
}

if updated {
// if we added a finalizer, stop processing and we will finish when the updated resource is reconciled
log.V(Log4Debug).Info("Reconciliation complete: A finalizer has been set on the agent config.")
return ctrl.Result{}, nil
}

log.V(Log4Debug).Info("Reconciliation complete: A porter agent has been dispatched to apply changes to the agent config.")
return ctrl.Result{}, nil
}
Expand Down Expand Up @@ -208,16 +214,6 @@ func (r *AgentConfigReconciler) createEmptyPluginVolume(ctx context.Context, log
Namespace: agentCfg.Namespace,
Labels: labels,
Annotations: agentCfg.GetPluginsPVCNameAnnotation(),
OwnerReferences: []metav1.OwnerReference{
{ // I'm not using controllerutil.SetControllerReference because I can't track down why that throws a panic when running our tests
APIVersion: agentCfg.APIVersion,
Kind: agentCfg.Kind,
Name: agentCfg.Name,
UID: agentCfg.UID,
Controller: ptr.To(true),
BlockOwnerDeletion: ptr.To(true),
},
},
},
Spec: corev1.PersistentVolumeClaimSpec{
AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce},
Expand All @@ -232,6 +228,10 @@ func (r *AgentConfigReconciler) createEmptyPluginVolume(ctx context.Context, log
pvc.Spec.StorageClassName = &storageClassName
}

if err := controllerutil.SetControllerReference(&agentCfg.AgentConfig, pvc, r.Scheme); err != nil {
return nil, false, errors.Wrap(err, "error attaching owner reference to agent volume (pvc)")
}

if err := r.Create(ctx, pvc); err != nil {
return nil, false, errors.Wrap(err, "error creating the agent volume (pvc)")
}
Expand Down Expand Up @@ -276,16 +276,6 @@ func (r *AgentConfigReconciler) createAgentAction(ctx context.Context, log logr.
GenerateName: agentCfg.Name + "-",
Labels: labels,
Annotations: agentCfg.Annotations,
OwnerReferences: []metav1.OwnerReference{
{ // I'm not using controllerutil.SetControllerReference because I can't track down why that throws a panic when running our tests
APIVersion: agentCfg.APIVersion,
Kind: agentCfg.Kind,
Name: agentCfg.Name,
UID: agentCfg.UID,
Controller: ptr.To(true),
BlockOwnerDeletion: ptr.To(true),
},
},
},
Spec: porterv1.AgentActionSpec{
AgentConfig: agentCfgName,
Expand All @@ -302,6 +292,11 @@ func (r *AgentConfigReconciler) createAgentAction(ctx context.Context, log logr.
return nil, errors.Wrap(err, "error creating the porter agent action")
}

if err := controllerutil.SetControllerReference(&agentCfg.AgentConfig, action, r.Scheme); err != nil {
return nil, errors.Wrap(err, "error attaching owner reference"+
"while creating porter agent action")
}

log.V(Log4Debug).Info("Created porter agent action", "name", action.Name)
return action, nil
}
Expand Down Expand Up @@ -390,16 +385,6 @@ func (r *AgentConfigReconciler) createHashPVC(ctx context.Context, log logr.Logg
Name: agentCfg.GetPluginsPVCName(),
Namespace: agentCfg.Namespace,
Labels: labels,
OwnerReferences: []metav1.OwnerReference{
{ // I'm not using controllerutil.SetControllerReference because I can't track down why that throws a panic when running our tests
APIVersion: agentCfg.APIVersion,
Kind: agentCfg.Kind,
Name: agentCfg.Name,
UID: agentCfg.UID,
Controller: ptr.To(true),
BlockOwnerDeletion: ptr.To(true),
},
},
},
Spec: corev1.PersistentVolumeClaimSpec{
AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadOnlyMany},
Expand All @@ -415,6 +400,10 @@ func (r *AgentConfigReconciler) createHashPVC(ctx context.Context, log logr.Logg
pvc.Spec.StorageClassName = &storageClassName
}

if err := controllerutil.SetControllerReference(&agentCfg.AgentConfig, pvc, r.Scheme); err != nil {
return nil, errors.Wrap(err, "error attaching owner reference to agent volume (pvc)")
}

if err := r.Create(ctx, pvc); err != nil {
return nil, errors.Wrap(err, "error creating the agent volume (pvc)")
}
Expand Down
14 changes: 2 additions & 12 deletions controllers/agentconfig_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ func TestAgentConfigReconciler_Reconcile(t *testing.T) {
require.True(t, result.IsZero())

err = controller.Get(ctx, key, &agentCfgData)
if !apierrors.IsNotFound(err) {
require.NoError(t, err)
if apierrors.IsNotFound(err) {
require.Error(t, err)
}
agentCfg = porterv1.NewAgentConfigAdapter(agentCfgData)
}
Expand Down Expand Up @@ -758,16 +758,6 @@ func TestAgentConfigReconciler_createAgentAction(t *testing.T) {
Namespace: agentCfg.Namespace,
Labels: labels,
Annotations: wrapper.GetPluginsPVCNameAnnotation(),
OwnerReferences: []metav1.OwnerReference{
{ // I'm not using controllerutil.SetControllerReference because I can't track down why that throws a panic when running our tests
APIVersion: agentCfg.APIVersion,
Kind: agentCfg.Kind,
Name: agentCfg.Name,
UID: agentCfg.UID,
Controller: ptr.To(true),
BlockOwnerDeletion: ptr.To(true),
},
},
},
Spec: corev1.PersistentVolumeClaimSpec{
AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce},
Expand Down
19 changes: 6 additions & 13 deletions controllers/credentialset_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/utils/ptr"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -199,18 +198,7 @@ func newAgentAction(cs *porterv1.CredentialSet) *porterv1.AgentAction {
Namespace: cs.Namespace,
GenerateName: cs.Name + "-",
Labels: labels,
Annotations: cs.Annotations,
OwnerReferences: []metav1.OwnerReference{
{ // I'm not using controllerutil.SetControllerReference because I can't track down why that throws a panic when running our tests
APIVersion: cs.APIVersion,
Kind: cs.Kind,
Name: cs.Name,
UID: cs.UID,
Controller: ptr.To(true),
BlockOwnerDeletion: ptr.To(true),
},
},
},
Annotations: cs.Annotations},
Spec: porterv1.AgentActionSpec{
AgentConfig: cs.Spec.AgentConfig,
},
Expand All @@ -226,6 +214,7 @@ func (r *CredentialSetReconciler) createAgentAction(ctx context.Context, log log
}

action := newAgentAction(cs)

log.WithValues("action name", action.Name)
if r.shouldDelete(cs) {
log.V(Log5Trace).Info("Deleting porter credential set")
Expand All @@ -236,6 +225,10 @@ func (r *CredentialSetReconciler) createAgentAction(ctx context.Context, log log
action.Spec.Files = map[string][]byte{"credentials.yaml": credSetResourceB}
}

if err := controllerutil.SetControllerReference(cs, action, r.Scheme); err != nil {
return nil, errors.Wrap(err, "error attaching owner reference to porter agent action")
}

if err := r.Create(ctx, action); err != nil {
return nil, errors.Wrap(err, "error creating the porter credential set agent action")
}
Expand Down
Loading