Skip to content
Merged
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
57 changes: 57 additions & 0 deletions controller-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,38 @@ build_deploy_controller () {
echo "==> Controller is running"
}

clean_task_test_resources() {
kubectl -n $NS delete -f test-resources/dynamic-secret-in-task-project1-secret.yaml
kubectl -n $NS delete -f test-resources/dynamic-secret-in-task-project1.yaml
}

wait_for_task_pod_to_complete () {
POD_NAME=${1}
CHECK_COUNTER=1
echo "==> Check task progress"
until $(kubectl -n ${NS} get pods ${1} --no-headers | grep -iq "Completed")
do
echo "=====> Pods in ns ${NS}:"
kubectl -n ${NS} get pods ${1} --no-headers
if [ $CHECK_COUNTER -lt $CHECK_TIMEOUT ]; then
let CHECK_COUNTER=CHECK_COUNTER+1
echo "==> Task not completed yet"
sleep 5
else
echo "Timeout of $CHECK_TIMEOUT waiting for task to complete"
echo "=========== TASK LOG ============"
kubectl -n ${NS} logs ${1} -f
clean_task_test_resources
check_controller_log ${1}
tear_down
echo "================ END ================"
echo "============== FAILED ==============="
exit 1
fi
done
echo "==> Task completed"
}


check_lagoon_build () {
CHECK_COUNTER=1
Expand Down Expand Up @@ -169,6 +201,31 @@ kubectl -n $CONTROLLER_NAMESPACE patch lagoonbuilds.crd.lagoon.sh lagoon-build-$
sleep 10
check_lagoon_build lagoon-build-${LBUILD}

echo "==> Trigger a Task using kubectl apply to test dynamic secret mounting"

kubectl -n $NS apply -f test-resources/dynamic-secret-in-task-project1-secret.yaml
kubectl -n $NS apply -f test-resources/dynamic-secret-in-task-project1.yaml
kubectl -n $NS patch lagoontasks.crd.lagoon.sh lagoon-advanced-task-example-task-project-1 --type=merge --patch '{"metadata":{"labels":{"lagoon.sh/controller":"'$CONTROLLER_NAMESPACE'"}}}'
Comment thread
bomoko marked this conversation as resolved.
kubectl -n $NS patch lagoontasks.crd.lagoon.sh lagoon-advanced-task-example-task-project-1 --type=merge --patch '{"metadata":{"labels":{"bump":"bump"}}}'
#kubectl get lagoontasks lagoon-advanced-task-example-task-project-1 -n $NS -o yaml

# wait on pod creation
wait_for_task_pod_to_complete lagoon-advanced-task-example-task-project-1
VMDATA=$(kubectl get pod -n $NS lagoon-advanced-task-example-task-project-1 -o jsonpath='{.spec.containers[0].volumeMounts}' | jq -r '.[] | select(.name == "dynamic-test-dynamic-secret") | .mountPath')

if [ ! "$VMDATA" = "/var/run/secrets/lagoon/dynamic/test-dynamic-secret" ]; then
echo "==> Task failed to mount dynamic secret"
clean_task_test_resources
check_controller_log ${1}
tear_down
echo "============== FAILED ==============="
exit 1
else
echo "==> Dynamic secret mounting into tasks good"
clean_task_test_resources
fi


echo "==> Trigger a lagoon build using rabbitmq"
echo '
{
Expand Down
61 changes: 61 additions & 0 deletions controllers/v1beta1/task_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,40 @@ func (r *LagoonTaskReconciler) createAdvancedTask(ctx context.Context, lagoonTas
newPod.Spec.ServiceAccountName = "lagoon-deployer"
}
opLog.Info(fmt.Sprintf("Creating advanced task pod for: %s", lagoonTask.ObjectMeta.Name))

//Decorate the pod spec with additional details

//dynamic secrets
secrets, err := getSecretsForNamespace(r.Client, lagoonTask.Namespace)
secrets = filterDynamicSecrets(secrets)
if err != nil {
return err
}

const dynamicSecretVolumeNamePrefex = "dynamic-"
for _, secret := range secrets {
volumeMountName := dynamicSecretVolumeNamePrefex + secret.Name
v := corev1.Volume{
Name: volumeMountName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: secret.Name,
DefaultMode: helpers.IntPtr(444),
},
},
}
newPod.Spec.Volumes = append(newPod.Spec.Volumes, v)

//now add the volume mount
vm := corev1.VolumeMount{
Name: volumeMountName,
ReadOnly: true,
MountPath: "/var/run/secrets/lagoon/dynamic/" + secret.Name,
}

newPod.Spec.Containers[0].VolumeMounts = append(newPod.Spec.Containers[0].VolumeMounts, vm)
}

if err := r.Create(ctx, newPod); err != nil {
opLog.Info(
fmt.Sprintf(
Expand All @@ -531,6 +565,33 @@ func (r *LagoonTaskReconciler) createAdvancedTask(ctx context.Context, lagoonTas
return nil
}

// getSecretsForNamespace is a convenience function to pull a list of secrets for a given namespace
func getSecretsForNamespace(k8sClient client.Client, namespace string) (map[string]corev1.Secret, error) {
secretList := &corev1.SecretList{}
err := k8sClient.List(context.Background(), secretList, &client.ListOptions{Namespace: namespace})
if err != nil {
return nil, err
}

secrets := map[string]corev1.Secret{}
for _, secret := range secretList.Items {
secrets[secret.Name] = secret
}

return secrets, nil
}

// filterDynamicSecrets will, given a map of secrets, filter those that match the dynamic secret label
func filterDynamicSecrets(secrets map[string]corev1.Secret) map[string]corev1.Secret {
filteredSecrets := map[string]corev1.Secret{}
for secretName, secret := range secrets {
if _, ok := secret.Labels["lagoon.sh/dynamic-secret"]; ok {
filteredSecrets[secretName] = secret
}
}
return filteredSecrets
}

// check for the API/SSH settings in the task spec first, if nothing there use the one from our settings.
func (r *LagoonTaskReconciler) getTaskValue(lagoonTask *lagoonv1beta1.LagoonTask, value string) string {
switch value {
Expand Down
9 changes: 9 additions & 0 deletions test-resources/dynamic-secret-in-task-project1-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: v1
data:
secret1: YmxhaCBibGFoIGJsYWg=
kind: Secret
metadata:
labels:
lagoon.sh/dynamic-secret: "true"
name: test-dynamic-secret
type: Opaque
28 changes: 28 additions & 0 deletions test-resources/dynamic-secret-in-task-project1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
apiVersion: crd.lagoon.sh/v1beta1
kind: LagoonTask
metadata:
name: "lagoon-advanced-task-example-task-project-1"
labels:
lagoon.sh/controller: lagoon
lagoon.sh/taskStatus: Pending
lagoon.sh/taskType: advanced
spec:
advancedTask:
JSONPayload: e30=
deployerToken: false
runnerImage: hello-world
sshKey: false
environment:
environmentType: ''
id: ''
name: main
project: ngnix-example
key: kubernetes:route:migrate
misc:
id: ''
project:
id: ''
name: nginx-example
task:
id: '1'
name: lagoon-task-1234