feat: enable running ZITADEL offline (#1894)

* feat: enable running ZITADEL offline

* refactor: move operator image to common images

* test: remove empty test
This commit is contained in:
Elio Bischof 2021-06-25 10:56:22 +02:00 committed by GitHub
parent c6c60d1d2a
commit b2b53ae9e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 408 additions and 127 deletions

46
operator/common/images.go Normal file
View File

@ -0,0 +1,46 @@
package common
type image string
func (i image) String() string { return string(i) }
type dockerhubImage image
type zitadelImage image
const (
CockroachImage dockerhubImage = "cockroachdb/cockroach:v20.2.3"
PostgresImage dockerhubImage = "postgres:9.6.17"
FlywayImage dockerhubImage = "flyway/flyway:7.5.1"
AlpineImage dockerhubImage = "alpine:3.11"
ZITADELImage zitadelImage = "caos/zitadel"
BackupImage zitadelImage = "caos/zitadel-crbackup"
ZITADELOperatorImage zitadelImage = "caos/zitadel-operator"
)
func (z zitadelImage) Reference(customImageRegistry, version string) string {
reg := "ghcr.io"
if customImageRegistry != "" {
reg = customImageRegistry
}
return concat(image(z), reg, version)
}
func (d dockerhubImage) Reference(customImageRegistry string) string {
return concat(image(d), customImageRegistry, "")
}
func concat(img image, customImageRegistry, version string) string {
str := img.String()
if customImageRegistry != "" {
str = customImageRegistry + "/" + str
}
if version != "" {
str = str + ":" + version
}
return str
}

View File

@ -0,0 +1,106 @@
package common
import (
"errors"
"fmt"
"strings"
"testing"
)
func TestDockerHubReference(t *testing.T) {
imgs := []dockerhubImage{CockroachImage, PostgresImage, FlywayImage, AlpineImage}
type args struct {
customImageRegistry string
}
tests := []struct {
name string
args args
test func(result string) error
}{{
name: "Image should be pulled from docker hub by default",
args: args{
customImageRegistry: "",
},
test: func(result string) error {
return expectRegistry(result, "")
},
}, {
name: "Given a custom image registry, the registry should be prepended",
args: args{
customImageRegistry: "myreg.io",
},
test: func(result string) error {
return expectRegistry(result, "myreg.io")
},
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
for i := range imgs {
got := imgs[i].Reference(tt.args.customImageRegistry)
if err := tt.test(got); err != nil {
t.Error(fmt.Errorf("DockerHubReference(%s): %w", imgs[i], err))
}
}
})
}
}
func TestZITADELReference(t *testing.T) {
imgs := []zitadelImage{ZITADELImage, BackupImage}
dummyVersion := "v99.99.99"
type args struct {
customImageRegistry string
}
tests := []struct {
name string
args args
test func(result string) error
}{{
name: "Image should be pulled from GHCR by default",
args: args{
customImageRegistry: "",
},
test: func(result string) error {
return expectRegistry(result, "ghcr.io/")
},
}, {
name: "Given a random docker hub image and a custom image registry, the registry should be prepended",
args: args{
customImageRegistry: "myreg.io",
},
test: func(result string) error {
return expectRegistry(result, "myreg.io")
},
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
for i := range imgs {
got := imgs[i].Reference(tt.args.customImageRegistry, dummyVersion)
if err := tt.test(got); err != nil {
t.Error(fmt.Errorf("ZITADELReference(%s): %w", imgs[i], err))
}
}
})
}
}
func expectRegistry(result, expect string) error {
if !strings.HasPrefix(result, expect) {
return fmt.Errorf("image is not prefixed by the registry %s", expect)
}
points := strings.Count(result[:strings.Index(result, ":")], ".")
if expect == "" && points > 1 {
return errors.New("doesn't look like a docker image")
}
if points > 1 {
return errors.New("too many points")
}
return nil
}

View File

@ -24,6 +24,7 @@ func Adapt(
tolerations []corev1.Toleration, tolerations []corev1.Toleration,
version string, version string,
features []string, features []string,
customImageRegistry string,
) ( ) (
operator.QueryFunc, operator.QueryFunc,
operator.DestroyFunc, operator.DestroyFunc,
@ -51,6 +52,7 @@ func Adapt(
tolerations, tolerations,
version, version,
features, features,
customImageRegistry,
)(monitor, desiredTree, currentTree) )(monitor, desiredTree, currentTree)
default: default:
return nil, nil, nil, nil, nil, false, errors.Errorf("unknown database kind %s", desiredTree.Common.Kind) return nil, nil, nil, nil, nil, false, errors.Errorf("unknown database kind %s", desiredTree.Common.Kind)

View File

@ -9,6 +9,7 @@ import (
"github.com/caos/orbos/pkg/secret/read" "github.com/caos/orbos/pkg/secret/read"
"github.com/caos/orbos/pkg/tree" "github.com/caos/orbos/pkg/tree"
"github.com/caos/zitadel/operator" "github.com/caos/zitadel/operator"
"github.com/caos/zitadel/operator/common"
"github.com/caos/zitadel/operator/database/kinds/backups/bucket/backup" "github.com/caos/zitadel/operator/database/kinds/backups/bucket/backup"
"github.com/caos/zitadel/operator/database/kinds/backups/bucket/clean" "github.com/caos/zitadel/operator/database/kinds/backups/bucket/clean"
"github.com/caos/zitadel/operator/database/kinds/backups/bucket/restore" "github.com/caos/zitadel/operator/database/kinds/backups/bucket/restore"
@ -32,6 +33,7 @@ func AdaptFunc(
tolerations []corev1.Toleration, tolerations []corev1.Toleration,
version string, version string,
features []string, features []string,
customImageRegistry string,
) operator.AdaptFunc { ) operator.AdaptFunc {
return func( return func(
monitor mntr.Monitor, monitor mntr.Monitor,
@ -66,6 +68,8 @@ func AdaptFunc(
return nil, nil, nil, nil, nil, false, err return nil, nil, nil, nil, nil, false, err
} }
image := common.BackupImage.Reference(customImageRegistry, version)
_, destroyB, err := backup.AdaptFunc( _, destroyB, err := backup.AdaptFunc(
internalMonitor, internalMonitor,
name, name,
@ -81,7 +85,7 @@ func AdaptFunc(
nodeselector, nodeselector,
tolerations, tolerations,
features, features,
version, image,
) )
if err != nil { if err != nil {
return nil, nil, nil, nil, nil, false, err return nil, nil, nil, nil, nil, false, err
@ -100,7 +104,7 @@ func AdaptFunc(
checkDBReady, checkDBReady,
secretName, secretName,
secretKey, secretKey,
version, image,
) )
if err != nil { if err != nil {
return nil, nil, nil, nil, nil, false, err return nil, nil, nil, nil, nil, false, err
@ -117,7 +121,7 @@ func AdaptFunc(
checkDBReady, checkDBReady,
secretName, secretName,
secretKey, secretKey,
version, image,
) )
if err != nil { if err != nil {
return nil, nil, nil, nil, nil, false, err return nil, nil, nil, nil, nil, false, err
@ -183,7 +187,7 @@ func AdaptFunc(
nodeselector, nodeselector,
tolerations, tolerations,
features, features,
version, image,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@ -202,7 +206,7 @@ func AdaptFunc(
checkDBReady, checkDBReady,
secretName, secretName,
secretKey, secretKey,
version, image,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@ -219,7 +223,7 @@ func AdaptFunc(
checkDBReady, checkDBReady,
secretName, secretName,
secretKey, secretKey,
version, image,
) )
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -71,6 +71,7 @@ func TestBucket_Secrets(t *testing.T) {
tolerations, tolerations,
version, version,
features, features,
"",
)( )(
monitor, monitor,
desired, desired,
@ -143,6 +144,7 @@ func TestBucket_AdaptBackup(t *testing.T) {
tolerations, tolerations,
version, version,
features, features,
"",
)( )(
monitor, monitor,
desired, desired,
@ -217,6 +219,7 @@ func TestBucket_AdaptInstantBackup(t *testing.T) {
tolerations, tolerations,
version, version,
features, features,
"",
)( )(
monitor, monitor,
desired, desired,
@ -292,6 +295,7 @@ func TestBucket_AdaptRestore(t *testing.T) {
tolerations, tolerations,
version, version,
features, features,
"",
)( )(
monitor, monitor,
desired, desired,
@ -367,6 +371,7 @@ func TestBucket_AdaptClean(t *testing.T) {
tolerations, tolerations,
version, version,
features, features,
"",
)( )(
monitor, monitor,
desired, desired,

View File

@ -21,7 +21,6 @@ const (
backupNameEnv = "BACKUP_NAME" backupNameEnv = "BACKUP_NAME"
cronJobNamePrefix = "backup-" cronJobNamePrefix = "backup-"
internalSecretName = "client-certs" internalSecretName = "client-certs"
image = "ghcr.io/caos/zitadel-crbackup"
rootSecretName = "cockroachdb.client.root" rootSecretName = "cockroachdb.client.root"
timeout = 15 * time.Minute timeout = 15 * time.Minute
Normal = "backup" Normal = "backup"
@ -43,7 +42,7 @@ func AdaptFunc(
nodeselector map[string]string, nodeselector map[string]string,
tolerations []corev1.Toleration, tolerations []corev1.Toleration,
features []string, features []string,
version string, image string,
) ( ) (
queryFunc operator.QueryFunc, queryFunc operator.QueryFunc,
destroyFunc operator.DestroyFunc, destroyFunc operator.DestroyFunc,
@ -63,8 +62,8 @@ func AdaptFunc(
secretName, secretName,
secretKey, secretKey,
backupName, backupName,
version,
command, command,
image,
) )
destroyers := []operator.DestroyFunc{} destroyers := []operator.DestroyFunc{}

View File

@ -29,7 +29,7 @@ func TestBackup_AdaptInstantBackup1(t *testing.T) {
tolerations := []corev1.Toleration{ tolerations := []corev1.Toleration{
{Key: "testKey", Operator: "testOp"}} {Key: "testKey", Operator: "testOp"}}
backupName := "testName" backupName := "testName"
version := "testVersion" image := "testImage"
secretKey := "testKey" secretKey := "testKey"
secretName := "testSecretName" secretName := "testSecretName"
jobName := GetJobName(backupName) jobName := GetJobName(backupName)
@ -49,13 +49,13 @@ func TestBackup_AdaptInstantBackup1(t *testing.T) {
secretName, secretName,
secretKey, secretKey,
backupName, backupName,
version,
getBackupCommand( getBackupCommand(
timestamp, timestamp,
databases, databases,
bucketName, bucketName,
backupName, backupName,
), ),
image,
), ),
) )
@ -77,7 +77,7 @@ func TestBackup_AdaptInstantBackup1(t *testing.T) {
nodeselector, nodeselector,
tolerations, tolerations,
features, features,
version, image,
) )
assert.NoError(t, err) assert.NoError(t, err)
@ -101,7 +101,7 @@ func TestBackup_AdaptInstantBackup2(t *testing.T) {
tolerations := []corev1.Toleration{ tolerations := []corev1.Toleration{
{Key: "testKey2", Operator: "testOp2"}} {Key: "testKey2", Operator: "testOp2"}}
backupName := "testName2" backupName := "testName2"
version := "testVersion2" image := "testImage2"
secretKey := "testKey2" secretKey := "testKey2"
secretName := "testSecretName2" secretName := "testSecretName2"
jobName := GetJobName(backupName) jobName := GetJobName(backupName)
@ -121,13 +121,13 @@ func TestBackup_AdaptInstantBackup2(t *testing.T) {
secretName, secretName,
secretKey, secretKey,
backupName, backupName,
version,
getBackupCommand( getBackupCommand(
timestamp, timestamp,
databases, databases,
bucketName, bucketName,
backupName, backupName,
), ),
image,
), ),
) )
@ -149,7 +149,7 @@ func TestBackup_AdaptInstantBackup2(t *testing.T) {
nodeselector, nodeselector,
tolerations, tolerations,
features, features,
version, image,
) )
assert.NoError(t, err) assert.NoError(t, err)
@ -173,7 +173,7 @@ func TestBackup_AdaptBackup1(t *testing.T) {
tolerations := []corev1.Toleration{ tolerations := []corev1.Toleration{
{Key: "testKey", Operator: "testOp"}} {Key: "testKey", Operator: "testOp"}}
backupName := "testName" backupName := "testName"
version := "testVersion" image := "testImage"
secretKey := "testKey" secretKey := "testKey"
secretName := "testSecretName" secretName := "testSecretName"
jobName := GetJobName(backupName) jobName := GetJobName(backupName)
@ -194,13 +194,13 @@ func TestBackup_AdaptBackup1(t *testing.T) {
secretName, secretName,
secretKey, secretKey,
backupName, backupName,
version,
getBackupCommand( getBackupCommand(
timestamp, timestamp,
databases, databases,
bucketName, bucketName,
backupName, backupName,
), ),
image,
), ),
) )
@ -221,7 +221,7 @@ func TestBackup_AdaptBackup1(t *testing.T) {
nodeselector, nodeselector,
tolerations, tolerations,
features, features,
version, image,
) )
assert.NoError(t, err) assert.NoError(t, err)
@ -245,7 +245,7 @@ func TestBackup_AdaptBackup2(t *testing.T) {
tolerations := []corev1.Toleration{ tolerations := []corev1.Toleration{
{Key: "testKey2", Operator: "testOp2"}} {Key: "testKey2", Operator: "testOp2"}}
backupName := "testName2" backupName := "testName2"
version := "testVersion2" image := "testImage2"
secretKey := "testKey2" secretKey := "testKey2"
secretName := "testSecretName2" secretName := "testSecretName2"
jobName := GetJobName(backupName) jobName := GetJobName(backupName)
@ -266,13 +266,13 @@ func TestBackup_AdaptBackup2(t *testing.T) {
secretName, secretName,
secretKey, secretKey,
backupName, backupName,
version,
getBackupCommand( getBackupCommand(
timestamp, timestamp,
databases, databases,
bucketName, bucketName,
backupName, backupName,
), ),
image,
), ),
) )
@ -293,7 +293,7 @@ func TestBackup_AdaptBackup2(t *testing.T) {
nodeselector, nodeselector,
tolerations, tolerations,
features, features,
version, image,
) )
assert.NoError(t, err) assert.NoError(t, err)

View File

@ -52,8 +52,8 @@ func getJobSpecDef(
secretName string, secretName string,
secretKey string, secretKey string,
backupName string, backupName string,
version string,
command string, command string,
image string,
) batchv1.JobSpec { ) batchv1.JobSpec {
return batchv1.JobSpec{ return batchv1.JobSpec{
Template: corev1.PodTemplateSpec{ Template: corev1.PodTemplateSpec{
@ -63,7 +63,7 @@ func getJobSpecDef(
Tolerations: tolerations, Tolerations: tolerations,
Containers: []corev1.Container{{ Containers: []corev1.Container{{
Name: backupName, Name: backupName,
Image: image + ":" + version, Image: image,
Command: []string{ Command: []string{
"/bin/bash", "/bin/bash",
"-c", "-c",

View File

@ -1,11 +1,12 @@
package backup package backup
import ( import (
"testing"
"github.com/caos/zitadel/operator/helpers" "github.com/caos/zitadel/operator/helpers"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
batchv1 "k8s.io/api/batch/v1" batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"testing"
) )
func TestBackup_JobSpec1(t *testing.T) { func TestBackup_JobSpec1(t *testing.T) {
@ -13,10 +14,10 @@ func TestBackup_JobSpec1(t *testing.T) {
tolerations := []corev1.Toleration{ tolerations := []corev1.Toleration{
{Key: "testKey", Operator: "testOp"}} {Key: "testKey", Operator: "testOp"}}
backupName := "testName" backupName := "testName"
version := "testVersion"
command := "test" command := "test"
secretKey := "testKey" secretKey := "testKey"
secretName := "testSecretName" secretName := "testSecretName"
image := "testImage"
equals := batchv1.JobSpec{ equals := batchv1.JobSpec{
Template: corev1.PodTemplateSpec{ Template: corev1.PodTemplateSpec{
@ -26,7 +27,7 @@ func TestBackup_JobSpec1(t *testing.T) {
Tolerations: tolerations, Tolerations: tolerations,
Containers: []corev1.Container{{ Containers: []corev1.Container{{
Name: backupName, Name: backupName,
Image: image + ":" + version, Image: image,
Command: []string{ Command: []string{
"/bin/bash", "/bin/bash",
"-c", "-c",
@ -62,7 +63,7 @@ func TestBackup_JobSpec1(t *testing.T) {
}, },
} }
assert.Equal(t, equals, getJobSpecDef(nodeselector, tolerations, secretName, secretKey, backupName, version, command)) assert.Equal(t, equals, getJobSpecDef(nodeselector, tolerations, secretName, secretKey, backupName, command, image))
} }
func TestBackup_JobSpec2(t *testing.T) { func TestBackup_JobSpec2(t *testing.T) {
@ -70,10 +71,10 @@ func TestBackup_JobSpec2(t *testing.T) {
tolerations := []corev1.Toleration{ tolerations := []corev1.Toleration{
{Key: "testKey2", Operator: "testOp2"}} {Key: "testKey2", Operator: "testOp2"}}
backupName := "testName2" backupName := "testName2"
version := "testVersion2"
command := "test2" command := "test2"
secretKey := "testKey2" secretKey := "testKey2"
secretName := "testSecretName2" secretName := "testSecretName2"
image := "testImage2"
equals := batchv1.JobSpec{ equals := batchv1.JobSpec{
Template: corev1.PodTemplateSpec{ Template: corev1.PodTemplateSpec{
@ -83,7 +84,7 @@ func TestBackup_JobSpec2(t *testing.T) {
Tolerations: tolerations, Tolerations: tolerations,
Containers: []corev1.Container{{ Containers: []corev1.Container{{
Name: backupName, Name: backupName,
Image: image + ":" + version, Image: image,
Command: []string{ Command: []string{
"/bin/bash", "/bin/bash",
"-c", "-c",
@ -119,5 +120,5 @@ func TestBackup_JobSpec2(t *testing.T) {
}, },
} }
assert.Equal(t, equals, getJobSpecDef(nodeselector, tolerations, secretName, secretKey, backupName, version, command)) assert.Equal(t, equals, getJobSpecDef(nodeselector, tolerations, secretName, secretKey, backupName, command, image))
} }

View File

@ -18,7 +18,6 @@ const (
certPath = "/cockroach/cockroach-certs" certPath = "/cockroach/cockroach-certs"
secretPath = "/secrets/sa.json" secretPath = "/secrets/sa.json"
internalSecretName = "client-certs" internalSecretName = "client-certs"
image = "ghcr.io/caos/zitadel-crbackup"
rootSecretName = "cockroachdb.client.root" rootSecretName = "cockroachdb.client.root"
jobPrefix = "backup-" jobPrefix = "backup-"
jobSuffix = "-clean" jobSuffix = "-clean"
@ -36,7 +35,7 @@ func AdaptFunc(
checkDBReady operator.EnsureFunc, checkDBReady operator.EnsureFunc,
secretName string, secretName string,
secretKey string, secretKey string,
version string, image string,
) ( ) (
queryFunc operator.QueryFunc, queryFunc operator.QueryFunc,
destroyFunc operator.DestroyFunc, destroyFunc operator.DestroyFunc,
@ -52,8 +51,9 @@ func AdaptFunc(
tolerations, tolerations,
secretName, secretName,
secretKey, secretKey,
version, command,
command) image,
)
destroyJ, err := job.AdaptFuncToDestroy(jobDef.Namespace, jobDef.Name) destroyJ, err := job.AdaptFuncToDestroy(jobDef.Namespace, jobDef.Name)
if err != nil { if err != nil {

View File

@ -24,7 +24,7 @@ func TestBackup_Adapt1(t *testing.T) {
tolerations := []corev1.Toleration{ tolerations := []corev1.Toleration{
{Key: "testKey", Operator: "testOp"}} {Key: "testKey", Operator: "testOp"}}
backupName := "testName" backupName := "testName"
version := "testVersion" image := "testImage"
secretKey := "testKey" secretKey := "testKey"
secretName := "testSecretName" secretName := "testSecretName"
jobName := GetJobName(backupName) jobName := GetJobName(backupName)
@ -42,10 +42,10 @@ func TestBackup_Adapt1(t *testing.T) {
tolerations, tolerations,
secretName, secretName,
secretKey, secretKey,
version,
getCommand( getCommand(
databases, databases,
), ),
image,
) )
client.EXPECT().ApplyJob(jobDef).Times(1).Return(nil) client.EXPECT().ApplyJob(jobDef).Times(1).Return(nil)
@ -62,7 +62,7 @@ func TestBackup_Adapt1(t *testing.T) {
checkDBReady, checkDBReady,
secretName, secretName,
secretKey, secretKey,
version, image,
) )
assert.NoError(t, err) assert.NoError(t, err)
@ -82,7 +82,7 @@ func TestBackup_Adapt2(t *testing.T) {
tolerations := []corev1.Toleration{ tolerations := []corev1.Toleration{
{Key: "testKey2", Operator: "testOp2"}} {Key: "testKey2", Operator: "testOp2"}}
backupName := "testName2" backupName := "testName2"
version := "testVersion2" image := "testImage2"
secretKey := "testKey2" secretKey := "testKey2"
secretName := "testSecretName2" secretName := "testSecretName2"
jobName := GetJobName(backupName) jobName := GetJobName(backupName)
@ -100,10 +100,10 @@ func TestBackup_Adapt2(t *testing.T) {
tolerations, tolerations,
secretName, secretName,
secretKey, secretKey,
version,
getCommand( getCommand(
databases, databases,
), ),
image,
) )
client.EXPECT().ApplyJob(jobDef).Times(1).Return(nil) client.EXPECT().ApplyJob(jobDef).Times(1).Return(nil)
@ -120,7 +120,7 @@ func TestBackup_Adapt2(t *testing.T) {
checkDBReady, checkDBReady,
secretName, secretName,
secretKey, secretKey,
version, image,
) )
assert.NoError(t, err) assert.NoError(t, err)

View File

@ -15,8 +15,8 @@ func getJob(
tolerations []corev1.Toleration, tolerations []corev1.Toleration,
secretName string, secretName string,
secretKey string, secretKey string,
version string,
command string, command string,
image string,
) *batchv1.Job { ) *batchv1.Job {
return &batchv1.Job{ return &batchv1.Job{
@ -33,7 +33,7 @@ func getJob(
RestartPolicy: corev1.RestartPolicyNever, RestartPolicy: corev1.RestartPolicyNever,
Containers: []corev1.Container{{ Containers: []corev1.Container{{
Name: nameLabels.Name(), Name: nameLabels.Name(),
Image: image + ":" + version, Image: image,
Command: []string{ Command: []string{
"/bin/bash", "/bin/bash",
"-c", "-c",

View File

@ -1,25 +1,26 @@
package clean package clean
import ( import (
"testing"
"github.com/caos/orbos/pkg/labels" "github.com/caos/orbos/pkg/labels"
"github.com/caos/zitadel/operator/helpers" "github.com/caos/zitadel/operator/helpers"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
batchv1 "k8s.io/api/batch/v1" batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"testing"
) )
func TestBackup_Job1(t *testing.T) { func TestBackup_Job1(t *testing.T) {
nodeselector := map[string]string{"test": "test"} nodeselector := map[string]string{"test": "test"}
tolerations := []corev1.Toleration{ tolerations := []corev1.Toleration{
{Key: "testKey", Operator: "testOp"}} {Key: "testKey", Operator: "testOp"}}
version := "testVersion"
command := "test" command := "test"
secretKey := "testKey" secretKey := "testKey"
secretName := "testSecretName" secretName := "testSecretName"
jobName := "testJob" jobName := "testJob"
namespace := "testNs" namespace := "testNs"
image := "testImage"
k8sLabels := map[string]string{ k8sLabels := map[string]string{
"app.kubernetes.io/component": "testComponent", "app.kubernetes.io/component": "testComponent",
@ -47,7 +48,7 @@ func TestBackup_Job1(t *testing.T) {
Tolerations: tolerations, Tolerations: tolerations,
Containers: []corev1.Container{{ Containers: []corev1.Container{{
Name: jobName, Name: jobName,
Image: image + ":" + version, Image: image,
Command: []string{ Command: []string{
"/bin/bash", "/bin/bash",
"-c", "-c",
@ -84,19 +85,19 @@ func TestBackup_Job1(t *testing.T) {
}, },
} }
assert.Equal(t, equals, getJob(namespace, nameLabels, nodeselector, tolerations, secretName, secretKey, version, command)) assert.Equal(t, equals, getJob(namespace, nameLabels, nodeselector, tolerations, secretName, secretKey, command, image))
} }
func TestBackup_Job2(t *testing.T) { func TestBackup_Job2(t *testing.T) {
nodeselector := map[string]string{"test2": "test2"} nodeselector := map[string]string{"test2": "test2"}
tolerations := []corev1.Toleration{ tolerations := []corev1.Toleration{
{Key: "testKey2", Operator: "testOp2"}} {Key: "testKey2", Operator: "testOp2"}}
version := "testVersion2"
command := "test2" command := "test2"
secretKey := "testKey2" secretKey := "testKey2"
secretName := "testSecretName2" secretName := "testSecretName2"
jobName := "testJob2" jobName := "testJob2"
namespace := "testNs2" namespace := "testNs2"
image := "testImage2"
k8sLabels := map[string]string{ k8sLabels := map[string]string{
"app.kubernetes.io/component": "testComponent2", "app.kubernetes.io/component": "testComponent2",
"app.kubernetes.io/managed-by": "testOp2", "app.kubernetes.io/managed-by": "testOp2",
@ -123,7 +124,7 @@ func TestBackup_Job2(t *testing.T) {
Tolerations: tolerations, Tolerations: tolerations,
Containers: []corev1.Container{{ Containers: []corev1.Container{{
Name: jobName, Name: jobName,
Image: image + ":" + version, Image: image,
Command: []string{ Command: []string{
"/bin/bash", "/bin/bash",
"-c", "-c",
@ -160,5 +161,5 @@ func TestBackup_Job2(t *testing.T) {
}, },
} }
assert.Equal(t, equals, getJob(namespace, nameLabels, nodeselector, tolerations, secretName, secretKey, version, command)) assert.Equal(t, equals, getJob(namespace, nameLabels, nodeselector, tolerations, secretName, secretKey, command, image))
} }

View File

@ -19,7 +19,6 @@ const (
secretPath = "/secrets/sa.json" secretPath = "/secrets/sa.json"
jobPrefix = "backup-" jobPrefix = "backup-"
jobSuffix = "-restore" jobSuffix = "-restore"
image = "ghcr.io/caos/zitadel-crbackup"
internalSecretName = "client-certs" internalSecretName = "client-certs"
rootSecretName = "cockroachdb.client.root" rootSecretName = "cockroachdb.client.root"
timeout = 15 * time.Minute timeout = 15 * time.Minute
@ -38,7 +37,7 @@ func AdaptFunc(
checkDBReady operator.EnsureFunc, checkDBReady operator.EnsureFunc,
secretName string, secretName string,
secretKey string, secretKey string,
version string, image string,
) ( ) (
queryFunc operator.QueryFunc, queryFunc operator.QueryFunc,
destroyFunc operator.DestroyFunc, destroyFunc operator.DestroyFunc,
@ -60,8 +59,8 @@ func AdaptFunc(
tolerations, tolerations,
secretName, secretName,
secretKey, secretKey,
version, command,
command) image)
destroyJ, err := job.AdaptFuncToDestroy(jobName, namespace) destroyJ, err := job.AdaptFuncToDestroy(jobName, namespace)
if err != nil { if err != nil {

View File

@ -26,7 +26,7 @@ func TestBackup_Adapt1(t *testing.T) {
timestamp := "testTs" timestamp := "testTs"
backupName := "testName2" backupName := "testName2"
bucketName := "testBucket2" bucketName := "testBucket2"
version := "testVersion" image := "testImage2"
secretKey := "testKey" secretKey := "testKey"
secretName := "testSecretName" secretName := "testSecretName"
jobName := GetJobName(backupName) jobName := GetJobName(backupName)
@ -44,13 +44,13 @@ func TestBackup_Adapt1(t *testing.T) {
tolerations, tolerations,
secretName, secretName,
secretKey, secretKey,
version,
getCommand( getCommand(
timestamp, timestamp,
databases, databases,
bucketName, bucketName,
backupName, backupName,
), ),
image,
) )
client.EXPECT().ApplyJob(jobDef).Times(1).Return(nil) client.EXPECT().ApplyJob(jobDef).Times(1).Return(nil)
@ -69,7 +69,7 @@ func TestBackup_Adapt1(t *testing.T) {
checkDBReady, checkDBReady,
secretName, secretName,
secretKey, secretKey,
version, image,
) )
assert.NoError(t, err) assert.NoError(t, err)
@ -91,7 +91,7 @@ func TestBackup_Adapt2(t *testing.T) {
timestamp := "testTs" timestamp := "testTs"
backupName := "testName2" backupName := "testName2"
bucketName := "testBucket2" bucketName := "testBucket2"
version := "testVersion2" image := "testImage2"
secretKey := "testKey2" secretKey := "testKey2"
secretName := "testSecretName2" secretName := "testSecretName2"
jobName := GetJobName(backupName) jobName := GetJobName(backupName)
@ -109,13 +109,13 @@ func TestBackup_Adapt2(t *testing.T) {
tolerations, tolerations,
secretName, secretName,
secretKey, secretKey,
version,
getCommand( getCommand(
timestamp, timestamp,
databases, databases,
bucketName, bucketName,
backupName, backupName,
), ),
image,
) )
client.EXPECT().ApplyJob(jobDef).Times(1).Return(nil) client.EXPECT().ApplyJob(jobDef).Times(1).Return(nil)
@ -134,7 +134,7 @@ func TestBackup_Adapt2(t *testing.T) {
checkDBReady, checkDBReady,
secretName, secretName,
secretKey, secretKey,
version, image,
) )
assert.NoError(t, err) assert.NoError(t, err)

View File

@ -15,9 +15,8 @@ func getJob(
tolerations []corev1.Toleration, tolerations []corev1.Toleration,
secretName string, secretName string,
secretKey string, secretKey string,
version string,
command string, command string,
image string,
) *batchv1.Job { ) *batchv1.Job {
return &batchv1.Job{ return &batchv1.Job{
ObjectMeta: v1.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
@ -33,7 +32,7 @@ func getJob(
RestartPolicy: corev1.RestartPolicyNever, RestartPolicy: corev1.RestartPolicyNever,
Containers: []corev1.Container{{ Containers: []corev1.Container{{
Name: nameLabels.Name(), Name: nameLabels.Name(),
Image: image + ":" + version, Image: image,
Command: []string{ Command: []string{
"/bin/bash", "/bin/bash",
"-c", "-c",

View File

@ -1,25 +1,26 @@
package restore package restore
import ( import (
"testing"
"github.com/caos/orbos/pkg/labels" "github.com/caos/orbos/pkg/labels"
"github.com/caos/zitadel/operator/helpers" "github.com/caos/zitadel/operator/helpers"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
batchv1 "k8s.io/api/batch/v1" batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"testing"
) )
func TestBackup_Job1(t *testing.T) { func TestBackup_Job1(t *testing.T) {
nodeselector := map[string]string{"test": "test"} nodeselector := map[string]string{"test": "test"}
tolerations := []corev1.Toleration{ tolerations := []corev1.Toleration{
{Key: "testKey", Operator: "testOp"}} {Key: "testKey", Operator: "testOp"}}
version := "testVersion"
command := "test" command := "test"
secretKey := "testKey" secretKey := "testKey"
secretName := "testSecretName" secretName := "testSecretName"
jobName := "testJob" jobName := "testJob"
namespace := "testNs" namespace := "testNs"
image := "testImage"
k8sLabels := map[string]string{ k8sLabels := map[string]string{
"app.kubernetes.io/component": "testComponent", "app.kubernetes.io/component": "testComponent",
"app.kubernetes.io/managed-by": "testOp", "app.kubernetes.io/managed-by": "testOp",
@ -46,7 +47,7 @@ func TestBackup_Job1(t *testing.T) {
Tolerations: tolerations, Tolerations: tolerations,
Containers: []corev1.Container{{ Containers: []corev1.Container{{
Name: jobName, Name: jobName,
Image: image + ":" + version, Image: image,
Command: []string{ Command: []string{
"/bin/bash", "/bin/bash",
"-c", "-c",
@ -83,19 +84,19 @@ func TestBackup_Job1(t *testing.T) {
}, },
} }
assert.Equal(t, equals, getJob(namespace, nameLabels, nodeselector, tolerations, secretName, secretKey, version, command)) assert.Equal(t, equals, getJob(namespace, nameLabels, nodeselector, tolerations, secretName, secretKey, command, image))
} }
func TestBackup_Job2(t *testing.T) { func TestBackup_Job2(t *testing.T) {
nodeselector := map[string]string{"test2": "test2"} nodeselector := map[string]string{"test2": "test2"}
tolerations := []corev1.Toleration{ tolerations := []corev1.Toleration{
{Key: "testKey2", Operator: "testOp2"}} {Key: "testKey2", Operator: "testOp2"}}
version := "testVersion2"
command := "test2" command := "test2"
secretKey := "testKey2" secretKey := "testKey2"
secretName := "testSecretName2" secretName := "testSecretName2"
jobName := "testJob2" jobName := "testJob2"
namespace := "testNs2" namespace := "testNs2"
testImage := "testImage2"
k8sLabels := map[string]string{ k8sLabels := map[string]string{
"app.kubernetes.io/component": "testComponent2", "app.kubernetes.io/component": "testComponent2",
"app.kubernetes.io/managed-by": "testOp2", "app.kubernetes.io/managed-by": "testOp2",
@ -122,7 +123,7 @@ func TestBackup_Job2(t *testing.T) {
Tolerations: tolerations, Tolerations: tolerations,
Containers: []corev1.Container{{ Containers: []corev1.Container{{
Name: jobName, Name: jobName,
Image: image + ":" + version, Image: testImage,
Command: []string{ Command: []string{
"/bin/bash", "/bin/bash",
"-c", "-c",
@ -159,5 +160,5 @@ func TestBackup_Job2(t *testing.T) {
}, },
} }
assert.Equal(t, equals, getJob(namespace, nameLabels, nodeselector, tolerations, secretName, secretKey, version, command)) assert.Equal(t, equals, getJob(namespace, nameLabels, nodeselector, tolerations, secretName, secretKey, command, testImage))
} }

View File

@ -31,6 +31,7 @@ func Adapt(
tolerations []core.Toleration, tolerations []core.Toleration,
version string, version string,
features []string, features []string,
customImageRegistry string,
) ( ) (
query operator.QueryFunc, query operator.QueryFunc,
destroy operator.DestroyFunc, destroy operator.DestroyFunc,
@ -45,7 +46,16 @@ func Adapt(
switch desiredTree.Common.Kind { switch desiredTree.Common.Kind {
case "databases.caos.ch/CockroachDB": case "databases.caos.ch/CockroachDB":
return managed.Adapter(componentLabels, namespace, timestamp, nodeselector, tolerations, version, features)(internalMonitor, desiredTree, currentTree) return managed.Adapter(
componentLabels,
namespace,
timestamp,
nodeselector,
tolerations,
version,
features,
customImageRegistry,
)(internalMonitor, desiredTree, currentTree)
case "databases.caos.ch/ProvidedDatabase": case "databases.caos.ch/ProvidedDatabase":
return provided.Adapter()(internalMonitor, desiredTree, currentTree) return provided.Adapter()(internalMonitor, desiredTree, currentTree)
default: default:

View File

@ -4,6 +4,8 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/caos/zitadel/operator/common"
"github.com/caos/zitadel/operator" "github.com/caos/zitadel/operator"
"github.com/caos/orbos/pkg/labels" "github.com/caos/orbos/pkg/labels"
@ -44,6 +46,7 @@ func Adapter(
tolerations []corev1.Toleration, tolerations []corev1.Toleration,
version string, version string,
features []string, features []string,
customImageRegistry string,
) operator.AdaptFunc { ) operator.AdaptFunc {
return func( return func(
@ -114,7 +117,7 @@ func Adapter(
cockroachSelector, cockroachSelector,
desiredKind.Spec.Force, desiredKind.Spec.Force,
namespace, namespace,
image, common.CockroachImage.Reference(customImageRegistry),
serviceAccountName, serviceAccountName,
desiredKind.Spec.ReplicaCount, desiredKind.Spec.ReplicaCount,
desiredKind.Spec.StorageCapacity, desiredKind.Spec.StorageCapacity,
@ -219,6 +222,7 @@ func Adapter(
tolerations, tolerations,
version, version,
features, features,
customImageRegistry,
) )
if err != nil { if err != nil {
return nil, nil, nil, nil, nil, false, err return nil, nil, nil, nil, nil, false, err

View File

@ -84,7 +84,7 @@ func TestManaged_AdaptBucketBackup(t *testing.T) {
bucket.SetBackup(k8sClient, namespace, labels, saJson) bucket.SetBackup(k8sClient, namespace, labels, saJson)
k8sClient.EXPECT().WaitUntilStatefulsetIsReady(namespace, SfsName, true, true, 60*time.Second) k8sClient.EXPECT().WaitUntilStatefulsetIsReady(namespace, SfsName, true, true, 60*time.Second)
query, _, _, _, _, _, err := Adapter(componentLabels, namespace, timestamp, nodeselector, tolerations, version, features)(monitor, desired, &tree.Tree{}) query, _, _, _, _, _, err := Adapter(componentLabels, namespace, timestamp, nodeselector, tolerations, version, features, "")(monitor, desired, &tree.Tree{})
assert.NoError(t, err) assert.NoError(t, err)
databases := []string{"test1", "test2"} databases := []string{"test1", "test2"}
@ -124,7 +124,7 @@ func TestManaged_AdaptBucketInstantBackup(t *testing.T) {
desired := getTreeWithDBAndBackup(t, masterkey, saJson, backupName) desired := getTreeWithDBAndBackup(t, masterkey, saJson, backupName)
query, _, _, _, _, _, err := Adapter(componentLabels, namespace, timestamp, nodeselector, tolerations, version, features)(monitor, desired, &tree.Tree{}) query, _, _, _, _, _, err := Adapter(componentLabels, namespace, timestamp, nodeselector, tolerations, version, features, "")(monitor, desired, &tree.Tree{})
assert.NoError(t, err) assert.NoError(t, err)
databases := []string{"test1", "test2"} databases := []string{"test1", "test2"}
@ -165,7 +165,7 @@ func TestManaged_AdaptBucketCleanAndRestore(t *testing.T) {
desired := getTreeWithDBAndBackup(t, masterkey, saJson, backupName) desired := getTreeWithDBAndBackup(t, masterkey, saJson, backupName)
query, _, _, _, _, _, err := Adapter(componentLabels, namespace, timestamp, nodeselector, tolerations, version, features)(monitor, desired, &tree.Tree{}) query, _, _, _, _, _, err := Adapter(componentLabels, namespace, timestamp, nodeselector, tolerations, version, features, "")(monitor, desired, &tree.Tree{})
assert.NoError(t, err) assert.NoError(t, err)
databases := []string{"test1", "test2"} databases := []string{"test1", "test2"}

View File

@ -133,7 +133,16 @@ func TestManaged_Adapt1(t *testing.T) {
dbCurrent.EXPECT().SetCertificateKey(gomock.Any()).MinTimes(1).MaxTimes(1) dbCurrent.EXPECT().SetCertificateKey(gomock.Any()).MinTimes(1).MaxTimes(1)
k8sClient.EXPECT().ApplySecret(gomock.Any()).MinTimes(1).MaxTimes(1) k8sClient.EXPECT().ApplySecret(gomock.Any()).MinTimes(1).MaxTimes(1)
query, _, _, _, _, _, err := Adapter(componentLabels, namespace, timestamp, nodeselector, tolerations, version, features)(monitor, desired, &tree.Tree{}) query, _, _, _, _, _, err := Adapter(
componentLabels,
namespace,
timestamp,
nodeselector,
tolerations,
version,
features,
"",
)(monitor, desired, &tree.Tree{})
assert.NoError(t, err) assert.NoError(t, err)
ensure, err := query(k8sClient, queried) ensure, err := query(k8sClient, queried)
@ -245,7 +254,16 @@ func TestManaged_Adapt2(t *testing.T) {
dbCurrent.EXPECT().SetCertificateKey(gomock.Any()).MinTimes(1).MaxTimes(1) dbCurrent.EXPECT().SetCertificateKey(gomock.Any()).MinTimes(1).MaxTimes(1)
k8sClient.EXPECT().ApplySecret(gomock.Any()).MinTimes(1).MaxTimes(1) k8sClient.EXPECT().ApplySecret(gomock.Any()).MinTimes(1).MaxTimes(1)
query, _, _, _, _, _, err := Adapter(componentLabels, namespace, timestamp, nodeselector, tolerations, version, features)(monitor, desired, &tree.Tree{}) query, _, _, _, _, _, err := Adapter(
componentLabels,
namespace,
timestamp,
nodeselector,
tolerations,
version,
features,
"",
)(monitor, desired, &tree.Tree{})
assert.NoError(t, err) assert.NoError(t, err)
ensure, err := query(k8sClient, queried) ensure, err := query(k8sClient, queried)

View File

@ -85,6 +85,7 @@ func AdaptFunc(
desiredKind.Spec.Tolerations, desiredKind.Spec.Tolerations,
desiredKind.Spec.Version, desiredKind.Spec.Version,
features, features,
desiredKind.Spec.CustomImageRegistry,
) )
if err != nil { if err != nil {
return nil, nil, nil, nil, nil, migrate, err return nil, nil, nil, nil, nil, migrate, err

View File

@ -19,8 +19,8 @@ type Spec struct {
Tolerations []corev1.Toleration `json:"tolerations,omitempty" yaml:"tolerations,omitempty"` Tolerations []corev1.Toleration `json:"tolerations,omitempty" yaml:"tolerations,omitempty"`
Version string `json:"version,omitempty" yaml:"version,omitempty"` Version string `json:"version,omitempty" yaml:"version,omitempty"`
SelfReconciling bool `json:"selfReconciling" yaml:"selfReconciling"` SelfReconciling bool `json:"selfReconciling" yaml:"selfReconciling"`
//Use this registry to pull the Database operator image from //Use this registry to pull container images from
//@default: ghcr.io //@default: <multiple public registries>
CustomImageRegistry string `json:"customImageRegistry,omitempty" yaml:"customImageRegistry,omitempty"` CustomImageRegistry string `json:"customImageRegistry,omitempty" yaml:"customImageRegistry,omitempty"`
} }

View File

@ -24,11 +24,6 @@ func Reconcile(
return err return err
} }
imageRegistry := spec.CustomImageRegistry
if imageRegistry == "" {
imageRegistry = "ghcr.io"
}
if spec.SelfReconciling { if spec.SelfReconciling {
desiredTree := &tree.Tree{ desiredTree := &tree.Tree{
Common: &tree.Common{ Common: &tree.Common{
@ -37,7 +32,7 @@ func Reconcile(
}, },
} }
if err := zitadelKubernetes.EnsureDatabaseArtifacts(monitor, treelabels.MustForAPI(desiredTree, mustDatabaseOperator(&spec.Version)), k8sClient, spec.Version, spec.NodeSelector, spec.Tolerations, imageRegistry, gitops); err != nil { if err := zitadelKubernetes.EnsureDatabaseArtifacts(monitor, treelabels.MustForAPI(desiredTree, mustDatabaseOperator(&spec.Version)), k8sClient, spec.Version, spec.NodeSelector, spec.Tolerations, spec.CustomImageRegistry, gitops); err != nil {
recMonitor.Error(errors.Wrap(err, "Failed to deploy database-operator into k8s-cluster")) recMonitor.Error(errors.Wrap(err, "Failed to deploy database-operator into k8s-cluster"))
return err return err
} }

View File

@ -27,6 +27,7 @@ func Adapt(
action string, action string,
version *string, version *string,
features []string, features []string,
customImageRegistry string,
) ( ) (
query operator.QueryFunc, query operator.QueryFunc,
destroy operator.DestroyFunc, destroy operator.DestroyFunc,
@ -46,7 +47,17 @@ func Adapt(
switch desiredTree.Common.Kind { switch desiredTree.Common.Kind {
case "zitadel.caos.ch/ZITADEL": case "zitadel.caos.ch/ZITADEL":
apiLabels := labels.MustForAPI(operatorLabels, "ZITADEL", desiredTree.Common.Version) apiLabels := labels.MustForAPI(operatorLabels, "ZITADEL", desiredTree.Common.Version)
return zitadel.AdaptFunc(apiLabels, nodeselector, tolerations, dbClient, namespace, action, version, features)(monitor, desiredTree, currentTree) return zitadel.AdaptFunc(
apiLabels,
nodeselector,
tolerations,
dbClient,
namespace,
action,
version,
features,
customImageRegistry,
)(monitor, desiredTree, currentTree)
default: default:
return nil, nil, nil, nil, nil, false, errors.Errorf("unknown iam kind %s", desiredTree.Common.Kind) return nil, nil, nil, nil, nil, false, errors.Errorf("unknown iam kind %s", desiredTree.Common.Kind)
} }

View File

@ -35,6 +35,7 @@ func AdaptFunc(
action string, action string,
version *string, version *string,
features []string, features []string,
customImageRegistry string,
) operator.AdaptFunc { ) operator.AdaptFunc {
return func( return func(
monitor mntr.Monitor, monitor mntr.Monitor,
@ -141,6 +142,7 @@ func AdaptFunc(
usersWithoutPWs, usersWithoutPWs,
nodeselector, nodeselector,
tolerations, tolerations,
customImageRegistry,
) )
if err != nil { if err != nil {
return nil, nil, nil, nil, nil, false, err return nil, nil, nil, nil, nil, false, err
@ -162,6 +164,7 @@ func AdaptFunc(
consoleCMName, consoleCMName,
secretVarsName, secretVarsName,
secretPasswordName, secretPasswordName,
customImageRegistry,
) )
if err != nil { if err != nil {
return nil, nil, nil, nil, nil, false, err return nil, nil, nil, nil, nil, false, err
@ -189,6 +192,7 @@ func AdaptFunc(
migration.GetDoneFunc(monitor, namespace, action), migration.GetDoneFunc(monitor, namespace, action),
configuration.GetReadyFunc(monitor, namespace, secretName, secretVarsName, secretPasswordName, cmName, consoleCMName), configuration.GetReadyFunc(monitor, namespace, secretName, secretVarsName, secretPasswordName, cmName, consoleCMName),
setup.GetDoneFunc(monitor, namespace, action), setup.GetDoneFunc(monitor, namespace, action),
customImageRegistry,
) )
if err != nil { if err != nil {
return nil, nil, nil, nil, nil, false, err return nil, nil, nil, nil, nil, false, err

View File

@ -21,8 +21,7 @@ const (
containerName = "zitadel" containerName = "zitadel"
RunAsUser = int64(1000) RunAsUser = int64(1000)
//zitadelImage can be found in github.com/caos/zitadel repo //zitadelImage can be found in github.com/caos/zitadel repo
zitadelImage = "ghcr.io/caos/zitadel" timeout = 60 * time.Second
timeout = 60 * time.Second
) )
func AdaptFunc( func AdaptFunc(
@ -47,6 +46,7 @@ func AdaptFunc(
migrationDone operator.EnsureFunc, migrationDone operator.EnsureFunc,
configurationDone operator.EnsureFunc, configurationDone operator.EnsureFunc,
setupDone operator.EnsureFunc, setupDone operator.EnsureFunc,
customImageRegistry string,
) ( ) (
func( func(
necessaryUsers map[string]string, necessaryUsers map[string]string,
@ -93,6 +93,7 @@ func AdaptFunc(
consoleCMName, consoleCMName,
secretVarsName, secretVarsName,
secretPasswordsName, secretPasswordsName,
customImageRegistry,
) )
hashes, err := getConfigurationHashes(k8sClient, queried, necessaryUsers) hashes, err := getConfigurationHashes(k8sClient, queried, necessaryUsers)
@ -126,7 +127,26 @@ func AdaptFunc(
} }
func deploymentDef(nameLabels *labels.Name, namespace string, replicaCount int, podSelector *labels.Selector, nodeSelector map[string]string, tolerations []corev1.Toleration, affinity *k8s.Affinity, users []string, version *string, resources *k8s.Resources, cmName string, certPath string, secretName string, secretPath string, consoleCMName string, secretVarsName string, secretPasswordsName string) *appsv1.Deployment { func deploymentDef(
nameLabels *labels.Name,
namespace string,
replicaCount int,
podSelector *labels.Selector,
nodeSelector map[string]string,
tolerations []corev1.Toleration,
affinity *k8s.Affinity,
users []string,
version *string,
resources *k8s.Resources,
cmName string,
certPath string,
secretName string,
secretPath string,
consoleCMName string,
secretVarsName string,
secretPasswordsName string,
customImageRegistry string,
) *appsv1.Deployment {
deploymentDef := &appsv1.Deployment{ deploymentDef := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: nameLabels.Name(), Name: nameLabels.Name(),
@ -161,6 +181,7 @@ func deploymentDef(nameLabels *labels.Name, namespace string, replicaCount int,
dbSecrets, dbSecrets,
users, users,
RunAsUser, RunAsUser,
customImageRegistry,
), ),
}, },
Containers: []corev1.Container{ Containers: []corev1.Container{
@ -180,6 +201,7 @@ func deploymentDef(nameLabels *labels.Name, namespace string, replicaCount int,
users, users,
dbSecrets, dbSecrets,
"start", "start",
customImageRegistry,
), ),
}, },
Volumes: GetVolumes( Volumes: GetVolumes(

View File

@ -32,6 +32,8 @@ func TestDeployment_Adapt(t *testing.T) {
secretName := "testSecret" secretName := "testSecret"
consoleCMName := "testConsoleCM" consoleCMName := "testConsoleCM"
cmName := "testCM" cmName := "testCM"
customImageRegistry := ""
usersMap := map[string]string{"test": "test"} usersMap := map[string]string{"test": "test"}
users := []string{} users := []string{}
for _, user := range usersMap { for _, user := range usersMap {
@ -86,6 +88,7 @@ func TestDeployment_Adapt(t *testing.T) {
dbSecrets, dbSecrets,
users, users,
RunAsUser, RunAsUser,
customImageRegistry,
), ),
}, },
Containers: []corev1.Container{ Containers: []corev1.Container{
@ -105,6 +108,7 @@ func TestDeployment_Adapt(t *testing.T) {
users, users,
dbSecrets, dbSecrets,
"start", "start",
customImageRegistry,
), ),
}, },
Volumes: GetVolumes( Volumes: GetVolumes(
@ -154,6 +158,7 @@ func TestDeployment_Adapt(t *testing.T) {
migrationDone, migrationDone,
configurationDone, configurationDone,
setupDone, setupDone,
customImageRegistry,
) )
assert.NoError(t, err) assert.NoError(t, err)
queried := map[string]interface{}{} queried := map[string]interface{}{}

View File

@ -4,6 +4,8 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/caos/zitadel/operator/common"
"github.com/caos/orbos/pkg/kubernetes/k8s" "github.com/caos/orbos/pkg/kubernetes/k8s"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/intstr"
@ -25,6 +27,7 @@ func GetContainer(
users []string, users []string,
dbSecrets string, dbSecrets string,
command string, command string,
customImageRegistry string,
) corev1.Container { ) corev1.Container {
envVars := []corev1.EnvVar{ envVars := []corev1.EnvVar{
@ -107,7 +110,7 @@ func GetContainer(
RunAsNonRoot: &runAsNonRoot, RunAsNonRoot: &runAsNonRoot,
}, },
Name: containerName, Name: containerName,
Image: zitadelImage + ":" + version, Image: common.ZITADELImage.Reference(customImageRegistry, version),
ImagePullPolicy: corev1.PullIfNotPresent, ImagePullPolicy: corev1.PullIfNotPresent,
Ports: []corev1.ContainerPort{ Ports: []corev1.ContainerPort{
{Name: "grpc", ContainerPort: 50001}, {Name: "grpc", ContainerPort: 50001},

View File

@ -1,13 +1,17 @@
package deployment package deployment
import ( import (
"fmt"
"testing"
"github.com/caos/zitadel/operator/common"
"github.com/caos/orbos/pkg/kubernetes/k8s" "github.com/caos/orbos/pkg/kubernetes/k8s"
"github.com/caos/zitadel/operator/helpers" "github.com/caos/zitadel/operator/helpers"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/intstr"
"testing"
) )
func TestDeployment_GetContainer(t *testing.T) { func TestDeployment_GetContainer(t *testing.T) {
@ -108,7 +112,7 @@ func TestDeployment_GetContainer(t *testing.T) {
RunAsNonRoot: helpers.PointerBool(true), RunAsNonRoot: helpers.PointerBool(true),
}, },
Name: containerName, Name: containerName,
Image: zitadelImage + ":" + version, Image: fmt.Sprintf("ghcr.io/%s:%s", common.ZITADELImage, version),
ImagePullPolicy: corev1.PullIfNotPresent, ImagePullPolicy: corev1.PullIfNotPresent,
Ports: []corev1.ContainerPort{ Ports: []corev1.ContainerPort{
{Name: "grpc", ContainerPort: 50001}, {Name: "grpc", ContainerPort: 50001},
@ -164,6 +168,7 @@ func TestDeployment_GetContainer(t *testing.T) {
users, users,
dbSecrets, dbSecrets,
"start", "start",
"",
) )
assert.Equal(t, equals, container) assert.Equal(t, equals, container)

View File

@ -1,10 +1,13 @@
package deployment package deployment
import ( import (
corev1 "k8s.io/api/core/v1"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
"github.com/caos/zitadel/operator/common"
corev1 "k8s.io/api/core/v1"
) )
const ( const (
@ -17,6 +20,7 @@ func GetInitContainer(
dbSecrets string, dbSecrets string,
users []string, users []string,
runAsUser int64, runAsUser int64,
customImageRegistry string,
) corev1.Container { ) corev1.Container {
initVolumeMounts := []corev1.VolumeMount{ initVolumeMounts := []corev1.VolumeMount{
@ -47,7 +51,7 @@ func GetInitContainer(
return corev1.Container{ return corev1.Container{
Name: "fix-permissions", Name: "fix-permissions",
Image: "alpine:3.11", Image: common.AlpineImage.Reference(customImageRegistry),
Command: []string{"/bin/sh", "-c"}, Command: []string{"/bin/sh", "-c"},
Args: []string{strings.Join(initCommands, " && ")}, Args: []string{strings.Join(initCommands, " && ")},
VolumeMounts: initVolumeMounts, VolumeMounts: initVolumeMounts,

View File

@ -1,10 +1,11 @@
package deployment package deployment
import ( import (
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
"strings" "strings"
"testing" "testing"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
) )
func TestDeployment_GetInitContainer(t *testing.T) { func TestDeployment_GetInitContainer(t *testing.T) {
@ -35,7 +36,7 @@ func TestDeployment_GetInitContainer(t *testing.T) {
TerminationMessagePath: "/dev/termination-log", TerminationMessagePath: "/dev/termination-log",
} }
init := GetInitContainer(rootSecret, dbSecrets, users, RunAsUser) init := GetInitContainer(rootSecret, dbSecrets, users, RunAsUser, "")
assert.Equal(t, equals, init) assert.Equal(t, equals, init)
} }
@ -68,7 +69,7 @@ func TestDeployment_GetInitContainer1(t *testing.T) {
ImagePullPolicy: corev1.PullIfNotPresent, ImagePullPolicy: corev1.PullIfNotPresent,
} }
init := GetInitContainer(rootSecret, dbSecrets, users, RunAsUser) init := GetInitContainer(rootSecret, dbSecrets, users, RunAsUser, "")
assert.Equal(t, equals, init) assert.Equal(t, equals, init)
} }
@ -104,7 +105,7 @@ func TestDeployment_GetInitContainer2(t *testing.T) {
TerminationMessagePath: "/dev/termination-log", TerminationMessagePath: "/dev/termination-log",
} }
init := GetInitContainer(rootSecret, dbSecrets, users, RunAsUser) init := GetInitContainer(rootSecret, dbSecrets, users, RunAsUser, "")
assert.Equal(t, equals, init) assert.Equal(t, equals, init)
} }

View File

@ -4,13 +4,14 @@ import (
"crypto/sha512" "crypto/sha512"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"github.com/pkg/errors"
"github.com/rakyll/statik/fs"
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
"sort" "sort"
"github.com/pkg/errors"
"github.com/rakyll/statik/fs"
"github.com/caos/orbos/mntr" "github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes" "github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/orbos/pkg/kubernetes/resources/configmap" "github.com/caos/orbos/pkg/kubernetes/resources/configmap"
@ -49,6 +50,7 @@ func AdaptFunc(
users []string, users []string,
nodeselector map[string]string, nodeselector map[string]string,
tolerations []corev1.Toleration, tolerations []corev1.Toleration,
customImageRegistry string,
) ( ) (
operator.QueryFunc, operator.QueryFunc,
operator.DestroyFunc, operator.DestroyFunc,
@ -103,9 +105,9 @@ func AdaptFunc(
Spec: corev1.PodSpec{ Spec: corev1.PodSpec{
NodeSelector: nodeselector, NodeSelector: nodeselector,
Tolerations: tolerations, Tolerations: tolerations,
InitContainers: getPreContainer(dbHost, dbPort, migrationUser, secretPasswordName), InitContainers: getPreContainer(dbHost, dbPort, migrationUser, secretPasswordName, customImageRegistry),
Containers: []corev1.Container{ Containers: []corev1.Container{
getMigrationContainer(dbHost, dbPort, migrationUser, secretPasswordName, users), getMigrationContainer(dbHost, dbPort, migrationUser, secretPasswordName, users, customImageRegistry),
}, },
RestartPolicy: "Never", RestartPolicy: "Never",
DNSPolicy: "ClusterFirst", DNSPolicy: "ClusterFirst",

View File

@ -99,9 +99,9 @@ func TestMigration_AdaptFunc(t *testing.T) {
Spec: corev1.PodSpec{ Spec: corev1.PodSpec{
NodeSelector: nodeselector, NodeSelector: nodeselector,
Tolerations: tolerations, Tolerations: tolerations,
InitContainers: getPreContainer(dbHost, dbPort, migrationUser, secretPasswordName), InitContainers: getPreContainer(dbHost, dbPort, migrationUser, secretPasswordName, ""),
Containers: []corev1.Container{ Containers: []corev1.Container{
getMigrationContainer(dbHost, dbPort, migrationUser, secretPasswordName, users), getMigrationContainer(dbHost, dbPort, migrationUser, secretPasswordName, users, ""),
}, },
RestartPolicy: "Never", RestartPolicy: "Never",
DNSPolicy: "ClusterFirst", DNSPolicy: "ClusterFirst",
@ -163,6 +163,7 @@ func TestMigration_AdaptFunc(t *testing.T) {
users, users,
nodeselector, nodeselector,
tolerations, tolerations,
"",
) )
queried := map[string]interface{}{} queried := map[string]interface{}{}

View File

@ -3,6 +3,8 @@ package migration
import ( import (
"strings" "strings"
"github.com/caos/zitadel/operator/common"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
) )
@ -12,10 +14,12 @@ func getMigrationContainer(
migrationUser string, migrationUser string,
secretPasswordName string, secretPasswordName string,
users []string, users []string,
customImageRegistry string,
) corev1.Container { ) corev1.Container {
return corev1.Container{ return corev1.Container{
Name: "db-migration", Name: "db-migration",
Image: "flyway/flyway:7.5.1", Image: common.FlywayImage.Reference(customImageRegistry),
Args: []string{ Args: []string{
"-url=jdbc:postgresql://" + dbHost + ":" + dbPort + "/defaultdb?&sslmode=verify-full&ssl=true&sslrootcert=" + rootUserPath + "/ca.crt&sslfactory=org.postgresql.ssl.NonValidatingFactory", "-url=jdbc:postgresql://" + dbHost + ":" + dbPort + "/defaultdb?&sslmode=verify-full&ssl=true&sslrootcert=" + rootUserPath + "/ca.crt&sslfactory=org.postgresql.ssl.NonValidatingFactory",
"-locations=filesystem:" + migrationsPath, "-locations=filesystem:" + migrationsPath,

View File

@ -1,8 +1,11 @@
package migration package migration
import ( import (
corev1 "k8s.io/api/core/v1"
"strings" "strings"
"github.com/caos/zitadel/operator/common"
corev1 "k8s.io/api/core/v1"
) )
func getPostContainers( func getPostContainers(
@ -10,11 +13,13 @@ func getPostContainers(
dbPort string, dbPort string,
migrationUser string, migrationUser string,
secretPasswordName string, secretPasswordName string,
customImageRegistry string,
) []corev1.Container { ) []corev1.Container {
return []corev1.Container{ return []corev1.Container{
{ {
Name: "delete-flyway-user", Name: "delete-flyway-user",
Image: "cockroachdb/cockroach:v20.2.3", Image: common.CockroachImage.Reference(customImageRegistry),
Command: []string{"/bin/bash", "-c", "--"}, Command: []string{"/bin/bash", "-c", "--"},
Args: []string{ Args: []string{
strings.Join([]string{ strings.Join([]string{

View File

@ -1,8 +1,11 @@
package migration package migration
import ( import (
corev1 "k8s.io/api/core/v1"
"strings" "strings"
"github.com/caos/zitadel/operator/common"
corev1 "k8s.io/api/core/v1"
) )
func getPreContainer( func getPreContainer(
@ -10,11 +13,13 @@ func getPreContainer(
dbPort string, dbPort string,
migrationUser string, migrationUser string,
secretPasswordName string, secretPasswordName string,
customImageRegistry string,
) []corev1.Container { ) []corev1.Container {
return []corev1.Container{ return []corev1.Container{
{ {
Name: "check-db-ready", Name: "check-db-ready",
Image: "postgres:9.6.17", Image: common.PostgresImage.Reference(customImageRegistry),
Command: []string{ Command: []string{
"sh", "sh",
"-c", "-c",
@ -26,7 +31,7 @@ func getPreContainer(
}, },
{ {
Name: "create-flyway-user", Name: "create-flyway-user",
Image: "cockroachdb/cockroach:v20.2.3", Image: common.CockroachImage.Reference(customImageRegistry),
Env: baseEnvVars(envMigrationUser, envMigrationPW, migrationUser, secretPasswordName), Env: baseEnvVars(envMigrationUser, envMigrationPW, migrationUser, secretPasswordName),
VolumeMounts: []corev1.VolumeMount{{ VolumeMounts: []corev1.VolumeMount{{
Name: rootUserInternal, Name: rootUserInternal,

View File

@ -1,9 +1,10 @@
package migration package migration
import ( import (
"github.com/stretchr/testify/assert"
"strings" "strings"
"testing" "testing"
"github.com/stretchr/testify/assert"
) )
func TestMigration_CreateUserCommand(t *testing.T) { func TestMigration_CreateUserCommand(t *testing.T) {

View File

@ -37,6 +37,7 @@ func AdaptFunc(
consoleCMName string, consoleCMName string,
secretVarsName string, secretVarsName string,
secretPasswordsName string, secretPasswordsName string,
customImageRegistry string,
) ( ) (
func( func(
necessaryUsers map[string]string, necessaryUsers map[string]string,
@ -82,9 +83,9 @@ func AdaptFunc(
secretVarsName, secretVarsName,
secretPasswordsName, secretPasswordsName,
namespace, namespace,
componentLabels,
nodeselector, nodeselector,
tolerations, tolerations,
customImageRegistry,
) )
hashes, err := getConfigurationHashes(k8sClient, queried, necessaryUsers) hashes, err := getConfigurationHashes(k8sClient, queried, necessaryUsers)
@ -115,13 +116,30 @@ func AdaptFunc(
} }
func jobDef(name *labels.Name, users []string, version *string, resources *k8s.Resources, cmName string, certPath string, secretName string, secretPath string, consoleCMName string, secretVarsName string, secretPasswordsName string, namespace string, componentLabels *labels.Component, nodeselector map[string]string, tolerations []corev1.Toleration) *batchv1.Job { func jobDef(
name *labels.Name,
users []string,
version *string,
resources *k8s.Resources,
cmName string,
certPath string,
secretName string,
secretPath string,
consoleCMName string,
secretVarsName string,
secretPasswordsName string,
namespace string,
nodeselector map[string]string,
tolerations []corev1.Toleration,
customImageRegistry string,
) *batchv1.Job {
initContainers := []corev1.Container{ initContainers := []corev1.Container{
deployment.GetInitContainer( deployment.GetInitContainer(
rootSecret, rootSecret,
dbSecrets, dbSecrets,
users, users,
deployment.RunAsUser, deployment.RunAsUser,
customImageRegistry,
)} )}
containers := []corev1.Container{ containers := []corev1.Container{
@ -141,6 +159,7 @@ func jobDef(name *labels.Name, users []string, version *string, resources *k8s.R
users, users,
dbSecrets, dbSecrets,
"setup", "setup",
customImageRegistry,
)} )}
volumes := deployment.GetVolumes(secretName, secretPasswordsName, consoleCMName, users) volumes := deployment.GetVolumes(secretName, secretPasswordsName, consoleCMName, users)

View File

@ -60,7 +60,7 @@ func TestSetup_AdaptFunc(t *testing.T) {
}, },
} }
initContainers := []corev1.Container{deployment.GetInitContainer(rootSecret, dbSecrets, users, deployment.RunAsUser)} initContainers := []corev1.Container{deployment.GetInitContainer(rootSecret, dbSecrets, users, deployment.RunAsUser, "")}
containers := []corev1.Container{deployment.GetContainer( containers := []corev1.Container{deployment.GetContainer(
containerName, containerName,
version, version,
@ -77,6 +77,7 @@ func TestSetup_AdaptFunc(t *testing.T) {
users, users,
dbSecrets, dbSecrets,
"setup", "setup",
"",
)} )}
volumes := deployment.GetVolumes(secretName, secretPasswordsName, consoleCMName, users) volumes := deployment.GetVolumes(secretName, secretPasswordsName, consoleCMName, users)
@ -133,6 +134,7 @@ func TestSetup_AdaptFunc(t *testing.T) {
consoleCMName, consoleCMName,
secretVarsName, secretVarsName,
secretPasswordsName, secretPasswordsName,
"",
) )
queried := map[string]interface{}{} queried := map[string]interface{}{}

View File

@ -93,6 +93,7 @@ func AdaptFunc(
action, action,
&desiredKind.Spec.Version, &desiredKind.Spec.Version,
features, features,
desiredKind.Spec.CustomImageRegistry,
) )
if err != nil { if err != nil {
return nil, nil, nil, nil, nil, false, err return nil, nil, nil, nil, nil, false, err

View File

@ -19,8 +19,8 @@ type Spec struct {
Tolerations []corev1.Toleration `json:"tolerations,omitempty" yaml:"tolerations,omitempty"` Tolerations []corev1.Toleration `json:"tolerations,omitempty" yaml:"tolerations,omitempty"`
Version string `json:"version,omitempty" yaml:"version,omitempty"` Version string `json:"version,omitempty" yaml:"version,omitempty"`
SelfReconciling bool `json:"selfReconciling" yaml:"selfReconciling"` SelfReconciling bool `json:"selfReconciling" yaml:"selfReconciling"`
//Use this registry to pull the zitadel operator image from //Use this registry to pull container images from
//@default: ghcr.io //@default: <multiple public registries>
CustomImageRegistry string `json:"customImageRegistry,omitempty" yaml:"customImageRegistry,omitempty"` CustomImageRegistry string `json:"customImageRegistry,omitempty" yaml:"customImageRegistry,omitempty"`
} }

View File

@ -24,11 +24,6 @@ func Reconcile(
return err return err
} }
imageRegistry := spec.CustomImageRegistry
if imageRegistry == "" {
imageRegistry = "ghcr.io"
}
if spec.SelfReconciling { if spec.SelfReconciling {
desiredTree := &tree.Tree{ desiredTree := &tree.Tree{
Common: &tree.Common{ Common: &tree.Common{
@ -37,7 +32,7 @@ func Reconcile(
}, },
} }
if err := kubernetes.EnsureZitadelOperatorArtifacts(monitor, treelabels.MustForAPI(desiredTree, mustZITADELOperator(&spec.Version)), k8sClient, spec.Version, spec.NodeSelector, spec.Tolerations, imageRegistry, gitops); err != nil { if err := kubernetes.EnsureZitadelOperatorArtifacts(monitor, treelabels.MustForAPI(desiredTree, mustZITADELOperator(&spec.Version)), k8sClient, spec.Version, spec.NodeSelector, spec.Tolerations, spec.CustomImageRegistry, gitops); err != nil {
recMonitor.Error(errors.Wrap(err, "Failed to deploy zitadel-operator into k8s-cluster")) recMonitor.Error(errors.Wrap(err, "Failed to deploy zitadel-operator into k8s-cluster"))
return err return err
} }

View File

@ -1,7 +1,7 @@
package kubernetes package kubernetes
import ( import (
"fmt" "github.com/caos/zitadel/operator/common"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@ -23,7 +23,7 @@ func EnsureZitadelOperatorArtifacts(
version string, version string,
nodeselector map[string]string, nodeselector map[string]string,
tolerations []core.Toleration, tolerations []core.Toleration,
imageRegistry string, customImageRegistry string,
gitops bool, gitops bool,
) error { ) error {
@ -268,7 +268,7 @@ status:
Containers: []core.Container{{ Containers: []core.Container{{
Name: "zitadel", Name: "zitadel",
ImagePullPolicy: core.PullIfNotPresent, ImagePullPolicy: core.PullIfNotPresent,
Image: fmt.Sprintf("%s/caos/zitadel-operator:%s", imageRegistry, version), Image: common.ZITADELOperatorImage.Reference(customImageRegistry, version),
Command: cmd, Command: cmd,
Args: []string{}, Args: []string{},
Ports: []core.ContainerPort{{ Ports: []core.ContainerPort{{
@ -329,7 +329,7 @@ func EnsureDatabaseArtifacts(
version string, version string,
nodeselector map[string]string, nodeselector map[string]string,
tolerations []core.Toleration, tolerations []core.Toleration,
imageRegistry string, customImageRegistry string,
gitops bool) error { gitops bool) error {
monitor.WithFields(map[string]interface{}{ monitor.WithFields(map[string]interface{}{
@ -566,7 +566,7 @@ status:
Containers: []core.Container{{ Containers: []core.Container{{
Name: "database", Name: "database",
ImagePullPolicy: core.PullIfNotPresent, ImagePullPolicy: core.PullIfNotPresent,
Image: fmt.Sprintf("%s/caos/zitadel-operator:%s", imageRegistry, version), Image: common.ZITADELOperatorImage.Reference(customImageRegistry, version),
Command: cmd, Command: cmd,
Args: []string{}, Args: []string{},
Ports: []core.ContainerPort{{ Ports: []core.ContainerPort{{