Merge pull request 'steps' (#8) from steps into master

Reviewed-on: http://git.desmojim.fr/jandre/formol/pulls/8
This commit is contained in:
jandre 2021-06-04 21:25:22 +00:00
commit 97ac4d5cc4
14 changed files with 87 additions and 43 deletions

View File

@ -1,6 +1,6 @@
# Image URL to use all building/pushing image targets # Image URL to use all building/pushing image targets
IMG ?= desmo999r/formolcontroller:latest IMG ?= desmo999r/formolcontroller:0.2.0
# Produce CRDs that work back to Kubernetes 1.11 (no version conversion) # Produce CRDs that work back to Kubernetes 1.11 (no version conversion)
#CRD_OPTIONS ?= "crd:trivialVersions=true" #CRD_OPTIONS ?= "crd:trivialVersions=true"
CRD_OPTIONS ?= "crd:trivialVersions=true,crdVersions=v1" CRD_OPTIONS ?= "crd:trivialVersions=true,crdVersions=v1"

View File

@ -30,8 +30,6 @@ const (
type Step struct { type Step struct {
Name string `json:"name"` Name string `json:"name"`
// +optional // +optional
Env []corev1.EnvVar `json:"env,omitempty"`
// +optional
Finalize *bool `json:"finalize,omitempty"` Finalize *bool `json:"finalize,omitempty"`
} }
@ -46,6 +44,8 @@ type Target struct {
Kind string `json:"kind"` Kind string `json:"kind"`
Name string `json:"name"` Name string `json:"name"`
// +optional // +optional
ContainerName string `json:"containerName"`
// +optional
ApiVersion string `json:"apiVersion,omitempty"` ApiVersion string `json:"apiVersion,omitempty"`
// +optional // +optional
VolumeMounts []corev1.VolumeMount `json:"volumeMounts,omitempty"` VolumeMounts []corev1.VolumeMount `json:"volumeMounts,omitempty"`

View File

@ -19,6 +19,8 @@ const (
RESTORE_ANNOTATION = "restore" RESTORE_ANNOTATION = "restore"
// the name of the sidecar container // the name of the sidecar container
SIDECARCONTAINER_NAME string = "formol" SIDECARCONTAINER_NAME string = "formol"
// the name of the container we backup when there are more than 1 container in the pod
TARGETCONTAINER_TAG string = "FORMOL_TARGET"
// Used by both the backupsession and restoresession controllers to identified the target deployment // Used by both the backupsession and restoresession controllers to identified the target deployment
TARGET_NAME string = "TARGET_NAME" TARGET_NAME string = "TARGET_NAME"
// Used by restoresession controller // Used by restoresession controller

View File

@ -569,13 +569,6 @@ func (in *S3) DeepCopy() *S3 {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Step) DeepCopyInto(out *Step) { func (in *Step) DeepCopyInto(out *Step) {
*out = *in *out = *in
if in.Env != nil {
in, out := &in.Env, &out.Env
*out = make([]v1.EnvVar, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Finalize != nil { if in.Finalize != nil {
in, out := &in.Finalize, &out.Finalize in, out := &in.Finalize, &out.Finalize
*out = new(bool) *out = new(bool)

View File

@ -5,4 +5,4 @@ kind: Kustomization
images: images:
- name: controller - name: controller
newName: desmo999r/formolcontroller newName: desmo999r/formolcontroller
newTag: latest newTag: 0.2.0

View File

@ -51,6 +51,8 @@ var _ reconcile.Reconciler = &BackupConfigurationReconciler{}
// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=apps,resources=replicasets,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=apps,resources=replicasets,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch // +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch
// +kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch
// +kubebuilder:rbac:groups=core,resources=configmaps,verbs=get;list;watch
// +kubebuilder:rbac:groups=core,resources=serviceaccounts,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=core,resources=serviceaccounts,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=roles,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=roles,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=rolebindings,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=rolebindings,verbs=get;list;watch;create;update;patch;delete
@ -212,11 +214,19 @@ func (r *BackupConfigurationReconciler) Reconcile(ctx context.Context, req recon
return err return err
} }
log.V(1).Info("got deployment", "Deployment", deployment) log.V(1).Info("got deployment", "Deployment", deployment)
for _, container := range deployment.Spec.Template.Spec.Containers { for i, container := range deployment.Spec.Template.Spec.Containers {
if container.Name == formolv1alpha1.SIDECARCONTAINER_NAME { if container.Name == formolv1alpha1.SIDECARCONTAINER_NAME {
log.V(0).Info("There is already a backup sidecar container. Skipping", "container", container) log.V(0).Info("There is already a backup sidecar container. Skipping", "container", container)
return nil return nil
} }
if target.ContainerName != "" && target.ContainerName == container.Name {
// Put a tag so we can find what container we are supposed to backup
// and what process we are supposed to chroot to run the init steps
deployment.Spec.Template.Spec.Containers[i].Env = append(container.Env, corev1.EnvVar{
Name: formolv1alpha1.TARGETCONTAINER_TAG,
Value: "True",
})
}
} }
sidecar := corev1.Container{ sidecar := corev1.Container{
Name: formolv1alpha1.SIDECARCONTAINER_NAME, Name: formolv1alpha1.SIDECARCONTAINER_NAME,

View File

@ -62,12 +62,6 @@ var _ = Describe("Testing BackupConf controller", func() {
Steps: []formolv1alpha1.Step{ Steps: []formolv1alpha1.Step{
formolv1alpha1.Step{ formolv1alpha1.Step{
Name: TestBackupFuncName, Name: TestBackupFuncName,
Env: []corev1.EnvVar{
corev1.EnvVar{
Name: "foo",
Value: "bar",
},
},
}, },
}, },
}, },

View File

@ -124,8 +124,8 @@ func (r *BackupSessionReconciler) Reconcile(ctx context.Context, req reconcile.R
TTLSecondsAfterFinished: &jobTtl, TTLSecondsAfterFinished: &jobTtl,
Template: corev1.PodTemplateSpec{ Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{ Spec: corev1.PodSpec{
InitContainers: []corev1.Container{}, InitContainers: deleteSnapshots[1:],
Containers: deleteSnapshots, Containers: []corev1.Container{deleteSnapshots[0]},
RestartPolicy: corev1.RestartPolicyOnFailure, RestartPolicy: corev1.RestartPolicyOnFailure,
}, },
}, },
@ -212,7 +212,7 @@ func (r *BackupSessionReconciler) Reconcile(ctx context.Context, req reconcile.R
return err return err
} }
function.Spec.Name = function.Name function.Spec.Name = function.Name
function.Spec.Env = append(step.Env, backupSessionEnv...) function.Spec.Env = append(function.Spec.Env, backupSessionEnv...)
function.Spec.VolumeMounts = append(function.Spec.VolumeMounts, output) function.Spec.VolumeMounts = append(function.Spec.VolumeMounts, output)
job.Spec.Template.Spec.InitContainers = append(job.Spec.Template.Spec.InitContainers, function.Spec) job.Spec.Template.Spec.InitContainers = append(job.Spec.Template.Spec.InitContainers, function.Spec)
} }

View File

@ -200,7 +200,7 @@ func (r *RestoreSessionReconciler) Reconcile(ctx context.Context, req reconcile.
return err return err
} }
function.Spec.Name = function.Name function.Spec.Name = function.Name
function.Spec.Env = append(step.Env, restoreSessionEnv...) function.Spec.Env = append(function.Spec.Env, restoreSessionEnv...)
function.Spec.VolumeMounts = append(function.Spec.VolumeMounts, output) function.Spec.VolumeMounts = append(function.Spec.VolumeMounts, output)
job.Spec.Template.Spec.InitContainers = append(job.Spec.Template.Spec.InitContainers, function.Spec) job.Spec.Template.Spec.InitContainers = append(job.Spec.Template.Spec.InitContainers, function.Spec)
} }

View File

@ -159,6 +159,12 @@ var (
Name: "backup-func", Name: "backup-func",
Image: "myimage", Image: "myimage",
Args: []string{"a", "set", "of", "args"}, Args: []string{"a", "set", "of", "args"},
Env: []corev1.EnvVar{
corev1.EnvVar{
Name: "foo",
Value: "bar",
},
},
}, },
} }
testBackupConf = &formolv1alpha1.BackupConfiguration{ testBackupConf = &formolv1alpha1.BackupConfiguration{
@ -201,12 +207,6 @@ var (
}, },
formolv1alpha1.Step{ formolv1alpha1.Step{
Name: TestBackupFuncName, Name: TestBackupFuncName,
Env: []corev1.EnvVar{
corev1.EnvVar{
Name: "foo",
Value: "bar",
},
},
}, },
}, },
}, },

View File

@ -217,7 +217,7 @@ func CreateFormolRBAC(cl client.Client, saName string, namespace string) error {
rbacv1.PolicyRule{ rbacv1.PolicyRule{
Verbs: []string{"get", "list", "watch"}, Verbs: []string{"get", "list", "watch"},
APIGroups: []string{""}, APIGroups: []string{""},
Resources: []string{"pods"}, Resources: []string{"pods", "secrets", "configmaps"},
}, },
rbacv1.PolicyRule{ rbacv1.PolicyRule{
Verbs: []string{"get", "list", "watch"}, Verbs: []string{"get", "list", "watch"},
@ -281,7 +281,7 @@ func CreateBackupSessionListenerRBAC(cl client.Client, saName string, namespace
rbacv1.PolicyRule{ rbacv1.PolicyRule{
Verbs: []string{"get", "list", "watch"}, Verbs: []string{"get", "list", "watch"},
APIGroups: []string{""}, APIGroups: []string{""},
Resources: []string{"pods"}, Resources: []string{"pods", "secrets", "configmaps"},
}, },
rbacv1.PolicyRule{ rbacv1.PolicyRule{
Verbs: []string{"get", "list", "watch"}, Verbs: []string{"get", "list", "watch"},

View File

@ -17,6 +17,14 @@ data:
node.session.auth.password: VHJtK1lZaXZvMUNZSGszcGFGVWMrcTdCMmdJPQo= node.session.auth.password: VHJtK1lZaXZvMUNZSGszcGFGVWMrcTdCMmdJPQo=
--- ---
apiVersion: v1 apiVersion: v1
kind: Secret
metadata:
namespace: demo
name: with-envfrom-secret
data:
title: dmVyeXNlY3JldA==
---
apiVersion: v1
kind: PersistentVolume kind: PersistentVolume
metadata: metadata:
name: demo-pv name: demo-pv
@ -82,6 +90,39 @@ spec:
name: restore-pg name: restore-pg
image: desmo999r/formolcli:latest image: desmo999r/formolcli:latest
args: ["postgres", "restore", "--hostname", $(PGHOST), "--database", $(PGDATABASE), "--username", $(PGUSER), "--password", $(PGPASSWD), "--file", "/output/backup-pg.sql"] args: ["postgres", "restore", "--hostname", $(PGHOST), "--database", $(PGDATABASE), "--username", $(PGUSER), "--password", $(PGPASSWD), "--file", "/output/backup-pg.sql"]
env:
- name: PGHOST
value: postgres
- name: PGDATABASE
value: demopostgres
- name: PGUSER
value: demopostgres
- name: PGPASSWD
value: password123!
---
apiVersion: formol.desmojim.fr/v1alpha1
kind: Function
metadata:
name: with-envfrom
namespace: demo
spec:
name: with-envfrom
command: ["touch", $(title)]
envFrom:
- secretRef:
name: with-envfrom-secret
---
apiVersion: formol.desmojim.fr/v1alpha1
kind: Function
metadata:
name: with-env
namespace: demo
spec:
name: with-env
command: ["touch", $(TESTFILE)]
env:
- name: TESTFILE
value: /data/testfile
--- ---
apiVersion: formol.desmojim.fr/v1alpha1 apiVersion: formol.desmojim.fr/v1alpha1
kind: Function kind: Function
@ -92,6 +133,15 @@ spec:
name: backup-pg name: backup-pg
image: desmo999r/formolcli:latest image: desmo999r/formolcli:latest
args: ["postgres", "backup", "--hostname", $(PGHOST), "--database", $(PGDATABASE), "--username", $(PGUSER), "--password", $(PGPASSWD), "--file", "/output/backup-pg.sql"] args: ["postgres", "backup", "--hostname", $(PGHOST), "--database", $(PGDATABASE), "--username", $(PGUSER), "--password", $(PGPASSWD), "--file", "/output/backup-pg.sql"]
env:
- name: PGHOST
value: postgres
- name: PGDATABASE
value: demopostgres
- name: PGUSER
value: demopostgres
- name: PGPASSWD
value: password123!
--- ---
apiVersion: formol.desmojim.fr/v1alpha1 apiVersion: formol.desmojim.fr/v1alpha1
kind: Function kind: Function

View File

@ -6,6 +6,7 @@ metadata:
namespace: demo namespace: demo
spec: spec:
suspend: true suspend: true
image: desmo999r/formolcli:latest
repository: repo-minio repository: repo-minio
schedule: "15 * * * *" schedule: "15 * * * *"
targets: targets:
@ -14,6 +15,8 @@ spec:
name: nginx-deployment name: nginx-deployment
steps: steps:
- name: maintenance-on - name: maintenance-on
- name: with-env
- name: with-envfrom
- name: maintenance-off - name: maintenance-off
finalize: true finalize: true
volumeMounts: volumeMounts:
@ -21,19 +24,10 @@ spec:
mountPath: /data mountPath: /data
paths: paths:
- /data - /data
- kind: Job # - kind: Job
name: backup-pg # name: backup-pg
steps: # steps:
- name: backup-pg # - name: backup-pg
env:
- name: PGHOST
value: postgres
- name: PGDATABASE
value: demopostgres
- name: PGUSER
value: demopostgres
- name: PGPASSWD
value: password123!
keep: keep:
last: 5 last: 5
daily: 2 daily: 2

View File

@ -1 +1,2 @@
NAMESPACE=demo; for i in $(kubectl -n $NAMESPACE get bs | awk 'NR>1 { print $1 }'); do kubectl -n $NAMESPACE get bs -o json $i | sed '/finalizers/,+2d' | curl -vvv -X PUT -H 'Content-type: application/json' -d @- http://127.0.0.1:8001/apis/formol.desmojim.fr/v1alpha1/namespaces/$NAMESPACE/backupsessions/$i; kubectl -n $NAMESPACE delete bs $i; done NAMESPACE=demo; for i in $(kubectl -n $NAMESPACE get bs | awk 'NR>1 { print $1 }'); do kubectl -n $NAMESPACE get bs -o json $i | sed '/finalizers/,+2d' | curl -vvv -X PUT -H 'Content-type: application/json' -d @- http://127.0.0.1:8001/apis/formol.desmojim.fr/v1alpha1/namespaces/$NAMESPACE/backupsessions/$i; kubectl -n $NAMESPACE delete bs $i; done
NAMESPACE=demo; for i in $(kubectl -n $NAMESPACE get bs | awk 'NR>1 { if ($3 == "New") { print $1 }}'); do kubectl -n $NAMESPACE get bs -o json $i | sed '/finalizers/,+2d' | curl -vvv -X PUT -H 'Content-type: application/json' -d @- http://127.0.0.1:8001/apis/formol.desmojim.fr/v1alpha1/namespaces/$NAMESPACE/backupsessions/$i; kubectl -n $NAMESPACE delete bs $i; done