Skip to content

Commit

Permalink
Add support for k8ify.imagePullSecret label
Browse files Browse the repository at this point in the history
  • Loading branch information
martini-source committed Nov 18, 2024
1 parent 1951858 commit e04420d
Show file tree
Hide file tree
Showing 20 changed files with 613 additions and 5 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ Service Labels

| Label | Effect |
| ------ | ------- |
| `k8ify.imagePullSecret: $env_var` | Creates an ImagePullSecret from the referenced environment variable. Can be used once per service|
| `k8ify.singleton: true` | Compose service is only deployed once per environment instead of once per `$ref` per environment |
| `k8ify.expose: $host` | The first port is exposed to the internet via a HTTPS ingress with the host name set to `$host` |
| `k8ify.expose.$port: $host` | The port `$port` is exposed to the internet via a HTTPS ingress with the host name set to `$host` |
Expand Down
35 changes: 33 additions & 2 deletions pkg/converter/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package converter

import (
"fmt"
v1 "k8s.io/api/policy/v1"
"log"
"maps"
"os"
Expand All @@ -11,6 +10,8 @@ import (
"strconv"
"strings"

v1 "k8s.io/api/policy/v1"

composeTypes "github.com/compose-spec/compose-go/types"
"github.com/sirupsen/logrus"
"github.com/vshn/k8ify/pkg/ir"
Expand Down Expand Up @@ -120,6 +121,18 @@ func composeServiceToSecret(workload *ir.Service, refSlug string, labels map[str
return &secret
}

func composeServiceToPullSecret(authConf string, name string, labels map[string]string) *core.Secret {
secret := core.Secret{}
secret.APIVersion = "v1"
secret.Kind = "Secret"
secret.Type = core.SecretTypeDockerConfigJson
secret.Name = name + "-imagePull"
secret.Labels = labels
secret.Annotations = util.Annotations(labels, "Secret")
secret.StringData = map[string]string{".dockerconfigjson": authConf}
return &secret
}

func composeServiceToDeployment(
workload *ir.Service,
refSlug string,
Expand Down Expand Up @@ -234,13 +247,30 @@ func composeServiceToPodTemplate(
if secret != nil {
secrets = append(secrets, *secret)
}

imagePullSecretReference := []core.LocalObjectReference{}
if util.ImagePullSecret(workload.AsCompose().Labels) != nil {
imagePullSecret := composeServiceToPullSecret(
*util.ImagePullSecret(workload.AsCompose().Labels),
workload.Name+refSlug,
labels)
secrets = append(secrets, *imagePullSecret)
imagePullSecretReference = append(imagePullSecretReference, core.LocalObjectReference{Name: imagePullSecret.Name + "-secret"})
}
for _, part := range workload.GetParts() {
c, s, cvs := composeServiceToContainer(part, refSlug, projectVolumes, labels)
containers = append(containers, c)
if s != nil {
secrets = append(secrets, *s)
}
if util.ImagePullSecret(part.AsCompose().Labels) != nil {
imagePullSecret := composeServiceToPullSecret(
*util.ImagePullSecret(part.AsCompose().Labels),
part.Name+refSlug,
labels)
secrets = append(secrets, *imagePullSecret)
imagePullSecretReference = append(imagePullSecretReference, core.LocalObjectReference{Name: imagePullSecret.Name + "-secret"})

}
maps.Copy(volumes, cvs)
}

Expand All @@ -259,6 +289,7 @@ func composeServiceToPodTemplate(

podSpec := core.PodSpec{
EnableServiceLinks: &enableServiceLinks,
ImagePullSecrets: imagePullSecretReference,
Containers: containers,
RestartPolicy: core.RestartPolicyAlways,
Volumes: volumesArray,
Expand Down
5 changes: 3 additions & 2 deletions pkg/ir/ir.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package ir

import (
"strconv"
"strings"

composeTypes "github.com/compose-spec/compose-go/types"
"github.com/vshn/k8ify/pkg/util"
"k8s.io/apimachinery/pkg/api/resource"
"strconv"
"strings"
)

type Inputs struct {
Expand Down
7 changes: 6 additions & 1 deletion pkg/util/configutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ package util

import (
"fmt"
core "k8s.io/api/core/v1"
"maps"
"os"
"regexp"
"strconv"
"strings"

core "k8s.io/api/core/v1"

"github.com/docker/go-units"
"github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/api/resource"
Expand Down Expand Up @@ -106,6 +107,10 @@ func PartOf(labels map[string]string) *string {
return GetOptional(labels, "k8ify.partOf")
}

func ImagePullSecret(labels map[string]string) *string {
return GetOptional(labels, "k8ify.imagePullSecret")
}

// StorageSize determines the requested storage size for a volume, or a
// fallback value.
func StorageSize(labels map[string]string, fallback string) resource.Quantity {
Expand Down
55 changes: 55 additions & 0 deletions tests/golden/imagepullsecrets.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
environments:
prod:
vars:
REGULAR_DEPLOYMENT_IMAGEPULLSECRET: |
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "foo"
}
}
}
REGULAR_STATEFULLSET_IMAGEPULLSECRET: |
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "bar"
}
}
}
PART_OF_DEPLOYMENT_IMAGEPULLSECRET: |
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "foo-baz"
}
}
}
PART_OF_DEPLOYMENT_SIDECAR_IMAGEPULLSECRET: |
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "foo-baz-part"
}
}
}
PART_OF_STATEFULLSET_IMAGEPULLSECRET: |
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "bar-baz"
}
}
}
PART_OF_STATEFULLSET_SIDECAR_IMMAGEPULLSECRET: |
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "bar-baz-part"
}
}
}
FOO : "one"
BAR : "two"
BAZ : "three"
76 changes: 76 additions & 0 deletions tests/golden/imagepullsecrets/docker-compose-prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
version: '3.4'
services:
regular-deployment:
image: nginx
labels:
k8ify.imagePullSecret: '$REGULAR_DEPLOYMENT_IMAGEPULLSECRET'
environment:
- FOO
- BAR=${BAR}
- something_else=${BAZ}
- "PASSWORD=$_ref_:mongodb-secret:password"
- "FOOREF=$_ref_:foo:fooooooo"
- "BARREF=$_ref_:bar:baaaaaar"

regular-statefullset:
image: mongodb
labels:
k8ify.imagePullSecret: '$REGULAR_STATEFULLSET_IMAGEPULLSECRET'
k8ify.singleton: true
volumes:
- regular-statefullset:/data
environment:
- FOO
- BAR=${BAR}
- something_else=${BAZ}
- "PASSWORD=$_ref_:mongodb-secret:password"
- "FOOREF=$_ref_:foo:fooooooo"
- "BARREF=$_ref_:bar:baaaaaar"

part-of-deployment:
image: nginx-frontend
labels:
k8ify.imagePullSecret: '$PART_OF_DEPLOYMENT_IMAGEPULLSECRET'
environment:
- FOO
- BAR=${BAR}
- something_else=${BAZ}
- "PASSWORD=$_ref_:mongodb-secret:password"
- "FOOREF=$_ref_:foo:fooooooo"
- "BARREF=$_ref_:bar:baaaaaar"

part-of-deployment-sidecar:
image: php-backend
labels:
k8ify.imagePullSecret: '$PART_OF_DEPLOYMENT_SIDECAR_IMAGEPULLSECRET'
k8ify.partOf: 'part-of-deployment'

part-of-statefullset:
labels:
k8ify.imagePullSecret: '$PART_OF_STATEFULLSET_IMAGEPULLSECRET'
k8ify.singleton: true
image: postgres
volumes:
- part-of-statefullset:/data
environment:
- FOO
- BAR=${BAR}
- something_else=${BAZ}
- "PASSWORD=$_ref_:mongodb-secret:password"
- "FOOREF=$_ref_:foo:fooooooo"
- "BARREF=$_ref_:bar:baaaaaar"

part-of-statefullset-sidecar:
labels:
k8ify.imagePullSecret: '$PART_OF_STATEFULLSET_SIDECAR_IMMAGEPULLSECRET'
k8ify.partOf: 'part-of-statefullset'
k8ify.singleton: true
image: pgpool

volumes:
regular-statefullset:
labels:
k8ify.singleton: true
part-of-statefullset:
labels:
k8ify.singleton: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
k8ify.ref-slug: oasp
k8ify.service: part-of-deployment
name: part-of-deployment-oasp
spec:
selector:
matchLabels:
k8ify.ref-slug: oasp
k8ify.service: part-of-deployment
strategy:
type: Recreate
template:
metadata:
creationTimestamp: null
labels:
k8ify.ref-slug: oasp
k8ify.service: part-of-deployment
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: k8ify.service
operator: In
values:
- part-of-deployment
topologyKey: kubernetes.io/hostname
containers:
- env:
- name: BARREF
valueFrom:
secretKeyRef:
key: baaaaaar
name: bar
- name: FOOREF
valueFrom:
secretKeyRef:
key: fooooooo
name: foo
- name: PASSWORD
valueFrom:
secretKeyRef:
key: password
name: mongodb-secret
envFrom:
- secretRef:
name: part-of-deployment-oasp-env
image: nginx-frontend
imagePullPolicy: Always
name: part-of-deployment-oasp
resources: {}
- image: php-backend
imagePullPolicy: Always
name: part-of-deployment-sidecar-oasp
resources: {}
enableServiceLinks: false
imagePullSecrets:
- name: part-of-deployment-oasp-imagePull-secret
- name: part-of-deployment-sidecar-oasp-imagePull-secret
restartPolicy: Always
status: {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: v1
kind: Secret
metadata:
creationTimestamp: null
labels:
k8ify.ref-slug: oasp
k8ify.service: part-of-deployment
name: part-of-deployment-oasp-env
stringData:
BAR: two
FOO: one
something_else: three
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
apiVersion: v1
kind: Secret
metadata:
creationTimestamp: null
labels:
k8ify.ref-slug: oasp
k8ify.service: part-of-deployment
name: part-of-deployment-oasp-imagePull
stringData:
.dockerconfigjson: |
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "foo-baz"
}
}
}
type: kubernetes.io/dockerconfigjson
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
apiVersion: v1
kind: Secret
metadata:
creationTimestamp: null
labels:
k8ify.ref-slug: oasp
k8ify.service: part-of-deployment
name: part-of-deployment-sidecar-oasp-imagePull
stringData:
.dockerconfigjson: |
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "foo-baz-part"
}
}
}
type: kubernetes.io/dockerconfigjson
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Secret
metadata:
creationTimestamp: null
labels:
k8ify.service: part-of-statefullset
name: part-of-statefullset-env
stringData:
BAR: two
FOO: one
something_else: three
Loading

0 comments on commit e04420d

Please sign in to comment.