feat: comprehensive sentry instrumentation (#2023)

* feat: comprehensive sentry instrumentation

* test: pass

* fix: only fetch zitadel dsn in zitadel-operator

* chore: use dns for sentry environment as soon as parsed

* fix: trust ca certs

* ci: update orbos

* docs: add usage data explanation

* fix: dont send validation errors

* docs: improve ingestion data explanation

* style: rename flag --disable-ingestion to --disable-analytics

* fix: pass --disable-analytics flag to self deployments

* fix: destroy command for sentry

* fix: update orbos

* fix: only switch environment if analytics is enabled

* fix: ensure SENTRY_DSN is always set

* test: test empty sentry dsn

* ci: invalidate build caches

* chore: use zitadel-dev if no version is passed

* chore: combine dev releases in sentry

* refactor: only check for semrel if sentry is enabled
This commit is contained in:
Elio Bischof 2021-07-30 11:52:08 +02:00 committed by GitHub
parent e1a3cc732d
commit fbe0f311f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
67 changed files with 490 additions and 470 deletions

View File

@ -75,6 +75,8 @@ jobs:
# cache-from: type=gha,scope=${{ github.workflow }} (https://github.com/caos/zitadel/issues/2102)
cache-to: type=gha,scope=${{ github.workflow }},mode=max
outputs: type=local,dest=/tmp/zitadel
build-args: |
VERSION=${{ needs.refs.outputs.version }}
- uses: actions/upload-artifact@v2
with:
name: zitadel
@ -424,4 +426,5 @@ jobs:
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
with:
version: ${{ steps.semantic.outputs.new_release_version }}
version: zitadel-${{ needs.refs.outputs.version }}
projects: "console database-operator zitadel zitadel-operator zitadelctl"

View File

@ -111,6 +111,15 @@ See the policy [here](./SECURITY.md)
* [**OIDC for GO**](https://github.com/caos/oidc) - OpenID Connect SDK (client and server) for Go
* [**ZITADEL Tools**](https://github.com/caos/zitadel-tools) - Go tool to convert key file to privately signed JWT
## Usage Data
ZITADEL components send errors and usage data to CAOS Ltd., so that we are able to identify code improvement potential. If you don't want to send this data or don't have an internet connection, pass the global flag `--disable-analytics` when using zitadelctl. For disabling ingestion for already-running components, execute the takeoff command again with the `--disable-analytics` flag.
We try to distinguishing the environments from which events come from. As environment identifier, we enrich the events by the domain you have configured in zitadel.yml, as soon as it's available. When it's not available and you passed the --gitops flag, we defer the environment identifier from your git repository URL.
Besides from errors that don't clearly come from misconfiguration or cli misuage, we send an inital event when any binary is started. This is a "<component> invoked" event along with the flags that are passed to it, except secret values of course.
We only ingest operational data. Your ZITADEL workload data from the IAM application itself is never sent anywhere unless you chose to integrate other systems yourself.
## License
See the exact licensing terms [here](./LICENSE)

View File

@ -18,4 +18,4 @@ COPY --from=artifact /etc/ssl/certs /etc/ssl/certs
COPY --from=artifact /app /
USER zitadel
HEALTHCHECK NONE
ENTRYPOINT ["/zitadel"]
ENTRYPOINT ["/zitadel"]

View File

@ -49,11 +49,15 @@ RUN adduser -D zitadel
ARG ARCH=amd64
ARG OS=linux
RUN apk add -U --no-cache ca-certificates
COPY --from=prod-go-build /go/src/github.com/caos/zitadel/zitadelctl /app/zitadelctl
RUN chmod a+x /app/zitadelctl
## Scratch Image
FROM scratch as final
COPY --from=artifact /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=artifact /etc/passwd /etc/passwd
COPY --from=artifact /app /
USER zitadel

View File

@ -142,8 +142,9 @@ COPY --from=go-test /go/src/github.com/caos/zitadel/profile.cov profile.cov
#######################
FROM go-test as prod-go-build
ARG BUILDARCH
ARG VERSION=""
RUN CGO_ENABLED=0 GOOS=linux GOARCH=${BUILDARCH} go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o zitadel-linux-${BUILDARCH} cmd/zitadel/main.go
RUN CGO_ENABLED=0 GOOS=linux GOARCH=${BUILDARCH} go build -a -installsuffix cgo -ldflags "-X main.version=${VERSION:-'dev'} -extldflags \"-static\"" -o zitadel-linux-${BUILDARCH} cmd/zitadel/main.go
#######################
## Go dev build

View File

@ -3,7 +3,9 @@ package main
import (
"context"
"flag"
"fmt"
"os"
"regexp"
"strconv"
"time"
@ -41,6 +43,9 @@ import (
"github.com/caos/zitadel/openapi"
)
// build argument
var version = "dev"
type Config struct {
Log logging.Config
Tracing tracing.TracingConfig
@ -94,8 +99,16 @@ const (
func main() {
enableSentry, _ := strconv.ParseBool(os.Getenv("SENTRY_USAGE"))
if enableSentry {
err := sentry.Init(sentry.ClientOptions{})
sentryVersion := version
if !regexp.MustCompile("^v?[0-9]+.[0-9]+.[0-9]$").Match([]byte(version)) {
sentryVersion = "dev"
}
err := sentry.Init(sentry.ClientOptions{
Environment: os.Getenv("SENTRY_ENVIRONMENT"),
Release: fmt.Sprintf("zitadel-%s", sentryVersion),
})
if err != nil {
logging.Log("MAIN-Gnzjw").WithError(err).Fatal("sentry init failed")
}

View File

@ -21,10 +21,7 @@ func BackupCommand(getRv GetRootValues) *cobra.Command {
flags.StringVar(&backup, "backup", "", "Name used for backup folder")
cmd.RunE = func(cmd *cobra.Command, args []string) (err error) {
rv, err := getRv()
if err != nil {
return err
}
rv := getRv("backup", map[string]interface{}{"backup": backup}, "")
defer func() {
err = rv.ErrFunc(err)
}()

View File

@ -4,10 +4,11 @@ import (
"fmt"
"sort"
"github.com/spf13/cobra"
"github.com/caos/orbos/pkg/kubernetes/cli"
"github.com/caos/zitadel/pkg/databases"
"github.com/spf13/cobra"
)
func BackupListCommand(getRv GetRootValues) *cobra.Command {
@ -19,11 +20,8 @@ func BackupListCommand(getRv GetRootValues) *cobra.Command {
}
)
cmd.RunE = func(cmd *cobra.Command, args []string) error {
rv, err := getRv()
if err != nil {
return err
}
cmd.RunE = func(cmd *cobra.Command, args []string) (err error) {
rv := getRv("backuplist", nil, "")
defer func() {
err = rv.ErrFunc(err)
}()
@ -41,15 +39,13 @@ func BackupListCommand(getRv GetRootValues) *cobra.Command {
if rv.Gitops {
backupsT, err := databases.GitOpsListBackups(monitor, gitClient, k8sClient)
if err != nil {
monitor.Error(err)
return nil
return err
}
backups = backupsT
} else {
backupsT, err := databases.CrdListBackups(monitor, k8sClient)
if err != nil {
monitor.Error(err)
return nil
return err
}
backups = backupsT
}

View File

@ -3,6 +3,8 @@ package cmds
import (
"errors"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/tree"
"github.com/caos/orbos/pkg/cfg"
@ -35,13 +37,13 @@ func ConfigCommand(getRv GetRootValues, ghClientID, ghClientSecret string) *cobr
cmd.RunE = func(cmd *cobra.Command, args []string) (err error) {
rv, _ := getRv()
rv := getRv("configure", map[string]interface{}{"masterkey": newMasterKey != "", "newRepoURL": newRepoURL}, "")
defer func() {
err = rv.ErrFunc(err)
}()
if !rv.Gitops {
return errors.New("configure command is only supported with the --gitops flag")
return mntr.ToUserError(errors.New("configure command is only supported with the --gitops flag"))
}
if err := orb.Reconfigure(rv.Ctx, rv.Monitor, rv.OrbConfig, newRepoURL, newMasterKey, rv.GitClient, ghClientID, ghClientSecret); err != nil {

View File

@ -46,10 +46,7 @@ func TeardownCommand(getRv GetRootValues) *cobra.Command {
cmd.RunE = func(cmd *cobra.Command, args []string) (err error) {
rv, err := getRv()
if err != nil {
return err
}
rv := getRv("destroy", nil, "")
defer func() {
err = rv.ErrFunc(err)
}()

View File

@ -18,11 +18,14 @@ func ReadSecretCommand(getRv GetRootValues) *cobra.Command {
Long: "Print a secrets decrypted value to stdout.\nIf no path is provided, a secret can interactively be chosen from a list of all possible secrets",
Args: cobra.MaximumNArgs(1),
Example: `zitadelctl readsecret database.bucket.serviceaccountjson.encrypted > ~/googlecloudstoragesa.json`,
RunE: func(cmd *cobra.Command, args []string) error {
rv, err := getRv()
if err != nil {
return err
RunE: func(cmd *cobra.Command, args []string) (err error) {
path := ""
if len(args) > 0 {
path = args[0]
}
rv := getRv("readsecret", map[string]interface{}{"path": path}, "")
defer func() {
err = rv.ErrFunc(err)
}()
@ -31,11 +34,6 @@ func ReadSecretCommand(getRv GetRootValues) *cobra.Command {
orbConfig := rv.OrbConfig
gitClient := rv.GitClient
path := ""
if len(args) > 0 {
path = args[0]
}
k8sClient, err := cli.Client(monitor, orbConfig, gitClient, rv.Kubeconfig, rv.Gitops, true)
if err != nil && !rv.Gitops {
return err
@ -47,13 +45,11 @@ func ReadSecretCommand(getRv GetRootValues) *cobra.Command {
secrets.GetAllSecretsFunc(monitor, path == "", rv.Gitops, gitClient, k8sClient, orbConfig),
)
if err != nil {
monitor.Error(err)
return nil
return err
}
if _, err := os.Stdout.Write([]byte(value)); err != nil {
monitor.Error(err)
return nil
return err
}
return nil
},

View File

@ -2,8 +2,11 @@ package cmds
import (
"errors"
"github.com/caos/zitadel/pkg/zitadel"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes/cli"
"github.com/caos/zitadel/pkg/databases"
@ -24,11 +27,8 @@ func RestoreCommand(getRv GetRootValues) *cobra.Command {
flags := cmd.Flags()
flags.StringVar(&backup, "backup", "", "Backup used for db restore")
cmd.RunE = func(cmd *cobra.Command, args []string) error {
rv, err := getRv()
if err != nil {
return err
}
cmd.RunE = func(cmd *cobra.Command, args []string) (err error) {
rv := getRv("restore", map[string]interface{}{"backup": backup}, "")
defer func() {
err = rv.ErrFunc(err)
}()
@ -48,15 +48,13 @@ func RestoreCommand(getRv GetRootValues) *cobra.Command {
if rv.Gitops {
listT, err := databases.GitOpsListBackups(monitor, gitClient, k8sClient)
if err != nil {
monitor.Error(err)
return nil
return err
}
list = listT
} else {
listT, err := databases.CrdListBackups(monitor, k8sClient)
if err != nil {
monitor.Error(err)
return nil
return err
}
list = listT
}
@ -69,8 +67,7 @@ func RestoreCommand(getRv GetRootValues) *cobra.Command {
_, result, err := prompt.Run()
if err != nil {
monitor.Error(err)
return nil
return err
}
backup = result
}
@ -82,18 +79,15 @@ func RestoreCommand(getRv GetRootValues) *cobra.Command {
}
if !existing {
monitor.Error(errors.New("chosen backup is not existing"))
return nil
return mntr.ToUserError(errors.New("chosen backup is not existing"))
}
if rv.Gitops {
if err := zitadel.GitOpsClearMigrateRestore(monitor, gitClient, orbConfig, k8sClient, backup, &version); err != nil {
monitor.Error(err)
return err
}
} else {
if err := zitadel.CrdClearMigrateRestore(monitor, k8sClient, backup, &version); err != nil {
monitor.Error(err)
return err
}

View File

@ -22,20 +22,15 @@ type RootValues struct {
ErrFunc errFunc
}
type GetRootValues func() (*RootValues, error)
type GetRootValues func(command string, tags map[string]interface{}, component string, moreComponents ...string) *RootValues
type errFunc func(err error) error
func RootCommand(version string) (*cobra.Command, GetRootValues) {
func RootCommand(version string, monitor mntr.Monitor) (*cobra.Command, GetRootValues) {
var (
ctx = context.Background()
monitor = mntr.Monitor{
OnInfo: mntr.LogMessage,
OnChange: mntr.LogMessage,
OnError: mntr.LogError,
}
rv = &RootValues{
ctx = context.Background()
rv = &RootValues{
Ctx: ctx,
Version: version,
ErrFunc: func(err error) error {
@ -46,8 +41,9 @@ func RootCommand(version string) (*cobra.Command, GetRootValues) {
return nil
},
}
orbConfigPath string
verbose bool
orbConfigPath string
verbose bool
disableAnalytics bool
)
cmd := &cobra.Command{
Use: "zitadelctl [flags]",
@ -77,8 +73,9 @@ $ zitadelctl --gitops -f ~/.orb/myorb [command]
flags.StringVarP(&orbConfigPath, "orbconfig", "f", "~/.orb/config", "Path to the file containing the orbs git repo URL, deploy key and the master key for encrypting and decrypting secrets")
flags.StringVarP(&rv.Kubeconfig, "kubeconfig", "k", "~/.kube/config", "Path to the kubeconfig file to the cluster zitadelctl should target")
flags.BoolVar(&verbose, "verbose", false, "Print debug levelled logs")
flags.BoolVar(&disableAnalytics, "disable-analytics", false, "Don't help CAOS AG to improve ZITADEL by sending them errors and usage data")
return cmd, func() (*RootValues, error) {
return cmd, func(command string, tags map[string]interface{}, component string, moreComponents ...string) *RootValues {
if verbose {
monitor = monitor.Verbose()
@ -88,15 +85,31 @@ $ zitadelctl --gitops -f ~/.orb/myorb [command]
rv.Kubeconfig = helpers.PruneHome(rv.Kubeconfig)
rv.GitClient = git.New(ctx, monitor, "zitadel", "orbos@caos.ch")
var err error
if rv.Gitops {
prunedPath := helpers.PruneHome(orbConfigPath)
rv.OrbConfig, err = orb.ParseOrbConfig(prunedPath)
rv.OrbConfig, _ = orb.ParseOrbConfig(prunedPath)
if rv.OrbConfig == nil {
rv.OrbConfig = &orb.Orb{Path: prunedPath}
}
}
return rv, err
env := "unknown"
if orbID, err := rv.OrbConfig.ID(); err == nil {
env = orbID
}
if component == "" {
component = "zitadelctl"
}
if !disableAnalytics {
if err := mntr.Ingest(rv.Monitor, "zitadel", version, env, component, moreComponents...); err != nil {
panic(err)
}
}
rv.Monitor.WithFields(map[string]interface{}{"command": command, "gitops": rv.Gitops}).WithFields(tags).CaptureMessage("zitadelctl invoked")
return rv
}
}

View File

@ -19,11 +19,8 @@ func StartOperator(getRv GetRootValues) *cobra.Command {
flags := cmd.Flags()
flags.StringVar(&metricsAddr, "metrics-addr", "", "The address the metric endpoint binds to.")
cmd.RunE = func(cmd *cobra.Command, args []string) error {
rv, err := getRv()
if err != nil {
return err
}
cmd.RunE = func(cmd *cobra.Command, args []string) (err error) {
rv := getRv("operator", nil, "zitadel-operator", "zitadel")
defer func() {
err = rv.ErrFunc(err)
}()
@ -63,10 +60,7 @@ func StartDatabase(getRv GetRootValues) *cobra.Command {
flags.StringVar(&metricsAddr, "metrics-addr", "", "The address the metric endpoint binds to.")
cmd.RunE = func(cmd *cobra.Command, args []string) (err error) {
rv, err := getRv()
if err != nil {
return err
}
rv := getRv("database", nil, "database-operator")
defer func() {
err = rv.ErrFunc(err)
}()

View File

@ -23,11 +23,8 @@ func TakeoffCommand(getRv GetRootValues) *cobra.Command {
}
)
cmd.RunE = func(cmd *cobra.Command, args []string) error {
rv, err := getRv()
if err != nil {
return err
}
cmd.RunE = func(cmd *cobra.Command, args []string) (err error) {
rv := getRv("takeoff", nil, "")
defer func() {
err = rv.ErrFunc(err)
}()
@ -49,7 +46,6 @@ func TakeoffCommand(getRv GetRootValues) *cobra.Command {
}
if err := kubernetes.EnsureCaosSystemNamespace(monitor, k8sClient); err != nil {
monitor.Info("failed to apply common resources into k8s-cluster")
return err
}
@ -61,7 +57,6 @@ func TakeoffCommand(getRv GetRootValues) *cobra.Command {
}
if err := kubernetes.EnsureOrbconfigSecret(monitor, k8sClient, orbConfigBytes); err != nil {
monitor.Info("failed to apply configuration resources into k8s-cluster")
return err
}
}
@ -73,45 +68,23 @@ func TakeoffCommand(getRv GetRootValues) *cobra.Command {
rv.Version,
rv.Gitops,
); err != nil {
monitor.Error(err)
return err
}
if err := deployDatabase(
return deployDatabase(
monitor,
gitClient,
k8sClient,
rv.Version,
rv.Gitops,
); err != nil {
monitor.Error(err)
}
return nil
)
}
return cmd
}
func deployOperator(monitor mntr.Monitor, gitClient *git.Client, k8sClient kubernetes.ClientInt, version string, gitops bool) error {
if gitops {
if gitClient.Exists(git.ZitadelFile) {
if !gitops {
desiredTree, err := gitClient.ReadTree(git.ZitadelFile)
if err != nil {
return err
}
desired, err := orbzit.ParseDesiredV0(desiredTree)
if err != nil {
return err
}
spec := desired.Spec
// at takeoff the artifacts have to be applied
spec.SelfReconciling = true
rec, _ := orbzit.Reconcile(monitor, spec, gitops)
if err := rec(k8sClient); err != nil {
return err
}
}
} else {
// at takeoff the artifacts have to be applied
spec := &orbzit.Spec{
Version: version,
@ -119,35 +92,33 @@ func deployOperator(monitor mntr.Monitor, gitClient *git.Client, k8sClient kuber
}
rec, _ := orbzit.Reconcile(monitor, spec, gitops)
if err := rec(k8sClient); err != nil {
return err
}
return rec(k8sClient)
}
return nil
if !gitClient.Exists(git.ZitadelFile) {
monitor.WithField("file", git.ZitadelFile).Info("File not found in git, skipping deployment")
return nil
}
desiredTree, err := gitClient.ReadTree(git.ZitadelFile)
if err != nil {
return err
}
desired, err := orbzit.ParseDesiredV0(desiredTree)
if err != nil {
return err
}
spec := desired.Spec
// at takeoff the artifacts have to be applied
spec.SelfReconciling = true
rec, _ := orbzit.Reconcile(monitor, spec, gitops)
return rec(k8sClient)
}
func deployDatabase(monitor mntr.Monitor, gitClient *git.Client, k8sClient kubernetes.ClientInt, version string, gitops bool) error {
if gitops {
if gitClient.Exists(git.DatabaseFile) {
desiredTree, err := gitClient.ReadTree(git.DatabaseFile)
if err != nil {
return err
}
desired, err := orbdb.ParseDesiredV0(desiredTree)
if err != nil {
return err
}
spec := desired.Spec
if !gitops {
// at takeoff the artifacts have to be applied
spec.SelfReconciling = true
rec, _ := orbdb.Reconcile(monitor, desired.Spec, gitops)
if err := rec(k8sClient); err != nil {
return err
}
}
} else {
// at takeoff the artifacts have to be applied
spec := &orbdb.Spec{
Version: version,
@ -155,9 +126,25 @@ func deployDatabase(monitor mntr.Monitor, gitClient *git.Client, k8sClient kuber
}
rec, _ := orbdb.Reconcile(monitor, spec, gitops)
if err := rec(k8sClient); err != nil {
return err
}
return rec(k8sClient)
}
return nil
if !gitClient.Exists(git.DatabaseFile) {
monitor.WithField("file", git.DatabaseFile).Info("File not found in git, skipping deployment")
return nil
}
desiredTree, err := gitClient.ReadTree(git.DatabaseFile)
if err != nil {
return err
}
desired, err := orbdb.ParseDesiredV0(desiredTree)
if err != nil {
return err
}
spec := desired.Spec
// at takeoff the artifacts have to be applied
spec.SelfReconciling = true
rec, _ := orbdb.Reconcile(monitor, spec, gitops)
return rec(k8sClient)
}

View File

@ -35,11 +35,14 @@ cat ~/googlecloudstoragesa.json | zitadelctl writesecret database.bucket.service
flags.StringVarP(&file, "file", "s", "", "File containing the value to encrypt")
flags.BoolVar(&stdin, "stdin", false, "Value to encrypt is read from standard input")
cmd.RunE = func(cmd *cobra.Command, args []string) error {
rv, err := getRv()
if err != nil {
return err
cmd.RunE = func(cmd *cobra.Command, args []string) (err error) {
path := ""
if len(args) > 0 {
path = args[0]
}
rv := getRv("writesecret", map[string]interface{}{"path": path, "value": value != "", "file": file, "stdin": stdin}, "")
defer func() {
err = rv.ErrFunc(err)
}()
@ -50,13 +53,7 @@ cat ~/googlecloudstoragesa.json | zitadelctl writesecret database.bucket.service
s, err := key(value, file, stdin)
if err != nil {
monitor.Error(err)
return nil
}
path := ""
if len(args) > 0 {
path = args[0]
return err
}
k8sClient, err := cli.Client(monitor, orbConfig, gitClient, rv.Kubeconfig, rv.Gitops, true)
@ -64,7 +61,7 @@ cat ~/googlecloudstoragesa.json | zitadelctl writesecret database.bucket.service
return err
}
if err := secret.Write(
return secret.Write(
monitor,
k8sClient,
path,
@ -73,10 +70,7 @@ cat ~/googlecloudstoragesa.json | zitadelctl writesecret database.bucket.service
fmt.Sprintf(rv.Version),
secrets.GetAllSecretsFunc(monitor, path != "", rv.Gitops, gitClient, k8sClient, orbConfig),
secrets.PushFunc(monitor, rv.Gitops, gitClient, k8sClient),
); err != nil {
monitor.Error(err)
}
return nil
)
}
return cmd
}

View File

@ -4,6 +4,8 @@ import (
"fmt"
"os"
"github.com/caos/orbos/mntr"
"github.com/caos/zitadel/cmd/zitadelctl/cmds"
)
@ -14,7 +16,16 @@ var (
)
func main() {
rootCmd, rootValues := cmds.RootCommand(Version)
monitor := mntr.Monitor{
OnInfo: mntr.LogMessage,
OnChange: mntr.LogMessage,
OnError: mntr.LogError,
OnRecoverPanic: mntr.LogPanic,
}
defer func() { monitor.RecoverPanic(recover()) }()
rootCmd, rootValues := cmds.RootCommand(Version, monitor)
rootCmd.Version = fmt.Sprintf("%s\n", Version)
rootCmd.AddCommand(

7
go.mod
View File

@ -17,8 +17,9 @@ require (
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc
github.com/caos/logging v0.0.2
github.com/caos/oidc v0.15.7
github.com/caos/orbos v1.5.14-0.20210428081839-983ffc569980
github.com/caos/orbos v1.5.14-0.20210727080455-c90c315021f5
github.com/cockroachdb/cockroach-go/v2 v2.1.0
github.com/docker/go-metrics v0.0.1 // indirect
github.com/duo-labs/webauthn v0.0.0-20200714211715-1daaee874e43
github.com/envoyproxy/protoc-gen-validate v0.6.1
github.com/getsentry/sentry-go v0.11.0
@ -44,12 +45,14 @@ require (
github.com/kevinburke/twilio-go v0.0.0-20200810163702-320748330fac
github.com/lib/pq v1.9.0
github.com/lucasb-eyer/go-colorful v1.2.0
github.com/magefile/mage v1.10.0 // indirect
github.com/manifoldco/promptui v0.7.0
github.com/mattn/go-colorable v0.1.8 // indirect; indirect github.com/mitchellh/copystructure v1.0.0 // indirect
github.com/minio/minio-go/v7 v7.0.10
github.com/mitchellh/copystructure v1.1.2 // indirect
github.com/muesli/gamut v0.2.0
github.com/nicksnyder/go-i18n/v2 v2.1.2
github.com/opencontainers/image-spec v1.0.1 // indirect
github.com/pkg/errors v0.9.1
github.com/pquerna/otp v1.2.0
github.com/prometheus/client_golang v1.8.0 // indirect
@ -79,7 +82,7 @@ require (
google.golang.org/grpc v1.36.1
google.golang.org/protobuf v1.26.0
gopkg.in/square/go-jose.v2 v2.6.0
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
gotest.tools v2.2.0+incompatible
k8s.io/api v0.19.2
k8s.io/apiextensions-apiserver v0.19.2

22
go.sum
View File

@ -149,6 +149,26 @@ github.com/caos/oidc v0.15.7 h1:jC7ugbQG1WJbGZgCXy1fE0B1VwWKvtKXLXY/pGDybhA=
github.com/caos/oidc v0.15.7/go.mod h1:doQ1B/mGnQWbgS+UOANIQCPJe1+KACyxQ8wjV2d11h0=
github.com/caos/orbos v1.5.14-0.20210428081839-983ffc569980 h1:Fz0aYUwGMA2tsu5w7SryqFGjqGClJVHbyhBMT5SXtPU=
github.com/caos/orbos v1.5.14-0.20210428081839-983ffc569980/go.mod h1:2I8oiZb5SMRm/qTLvwpSmdV0M6ex8J/UKyxUGfKaqJo=
github.com/caos/orbos v1.5.14-0.20210714083228-b93d9fe7ffce h1:jon2Hu49yRj/Ud9yadHtq69Y0NbEe3ZrS6GGY6WSQ4w=
github.com/caos/orbos v1.5.14-0.20210714083228-b93d9fe7ffce/go.mod h1:HUMpCHr14uizCNAQ9lRQTDYBKSMw9QECTmr3h+Yrfzk=
github.com/caos/orbos v1.5.14-0.20210714084047-e8098b5c4425 h1:dWtZjqPZI+/+MN8PKq41WLxhETqbSOMe7LmsHzdGB9U=
github.com/caos/orbos v1.5.14-0.20210714084047-e8098b5c4425/go.mod h1:HUMpCHr14uizCNAQ9lRQTDYBKSMw9QECTmr3h+Yrfzk=
github.com/caos/orbos v1.5.14-0.20210714085518-c85d8aaa50a1 h1:foIqYwvIphQJxaNDsXcdQMJbrVaTWr06u30FMn+k38s=
github.com/caos/orbos v1.5.14-0.20210714085518-c85d8aaa50a1/go.mod h1:HUMpCHr14uizCNAQ9lRQTDYBKSMw9QECTmr3h+Yrfzk=
github.com/caos/orbos v1.5.14-0.20210714100409-551272c93db9 h1:UYz1WY8n8EJdUsZf6YHIhYJCiysbuCGrfuFcHtldeLE=
github.com/caos/orbos v1.5.14-0.20210714100409-551272c93db9/go.mod h1:HUMpCHr14uizCNAQ9lRQTDYBKSMw9QECTmr3h+Yrfzk=
github.com/caos/orbos v1.5.14-0.20210714140657-75d67d651032 h1:bspWDMtNxouegqibzlu2GnpNBOc5H4AjiZpQF4Zy5xk=
github.com/caos/orbos v1.5.14-0.20210714140657-75d67d651032/go.mod h1:HUMpCHr14uizCNAQ9lRQTDYBKSMw9QECTmr3h+Yrfzk=
github.com/caos/orbos v1.5.14-0.20210715071410-693c13f08917 h1:RQcvd7CZf321Chj9/qZPgA43JL5atW0pog3Q2LV9jWc=
github.com/caos/orbos v1.5.14-0.20210715071410-693c13f08917/go.mod h1:HUMpCHr14uizCNAQ9lRQTDYBKSMw9QECTmr3h+Yrfzk=
github.com/caos/orbos v1.5.14-0.20210720104010-5755dc25b89a h1:NPTYKauqeZEtkSjN0F06zjvn6bmqZXUGZ6YuITVwXUY=
github.com/caos/orbos v1.5.14-0.20210720104010-5755dc25b89a/go.mod h1:HUMpCHr14uizCNAQ9lRQTDYBKSMw9QECTmr3h+Yrfzk=
github.com/caos/orbos v1.5.14-0.20210721092606-ce76d1dca404 h1:BFivUFFntVfvKwB9k+o616KomTu6d1Rx6r0q+wfTAv8=
github.com/caos/orbos v1.5.14-0.20210721092606-ce76d1dca404/go.mod h1:HUMpCHr14uizCNAQ9lRQTDYBKSMw9QECTmr3h+Yrfzk=
github.com/caos/orbos v1.5.14-0.20210721123151-e8d9c5c2df11 h1:mQoO0LSUrY9KvepOkks8BrDfBAsiJ1P9qtZ9SO/QsPc=
github.com/caos/orbos v1.5.14-0.20210721123151-e8d9c5c2df11/go.mod h1:wLL07uotPKdNb7KPri3uTtGd2tFHZ3g7Y7wOt86+lqA=
github.com/caos/orbos v1.5.14-0.20210727080455-c90c315021f5 h1:Q/Rfq/9vZ9fNcg6YftROufGDyRJeNxmubLi0jwGJF8I=
github.com/caos/orbos v1.5.14-0.20210727080455-c90c315021f5/go.mod h1:wLL07uotPKdNb7KPri3uTtGd2tFHZ3g7Y7wOt86+lqA=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
@ -1510,6 +1530,8 @@ gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/postgres v1.0.5/go.mod h1:qrD92UurYzNctBMVCJ8C3VQEjffEuphycXtxOudXNCA=
gorm.io/gorm v1.20.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
gorm.io/gorm v1.20.6/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=

View File

@ -1,14 +1,16 @@
package operator
import (
"fmt"
"gopkg.in/yaml.v3"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/git"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/orbos/pkg/kubernetes/resources"
"github.com/caos/orbos/pkg/secret"
"github.com/caos/orbos/pkg/tree"
"github.com/pkg/errors"
"gopkg.in/yaml.v3"
)
type AdaptFunc func(
@ -84,7 +86,7 @@ func QueriersToEnsureFunc(monitor mntr.Monitor, infoLogs bool, queriers []QueryF
for _, querier := range queriers {
ensurer, err := querier(k8sClient, queried)
if err != nil {
return nil, errors.Wrap(err, "error while querying")
return nil, fmt.Errorf("error while querying: %w", err)
}
ensurers = append(ensurers, ensurer)
}
@ -101,7 +103,7 @@ func QueriersToEnsureFunc(monitor mntr.Monitor, infoLogs bool, queriers []QueryF
}
for _, ensurer := range ensurers {
if err := ensurer(k8sClient); err != nil {
return errors.Wrap(err, "error while ensuring")
return fmt.Errorf("error while ensuring: %w", err)
}
}
if infoLogs {
@ -118,7 +120,7 @@ func DestroyersToDestroyFunc(monitor mntr.Monitor, destroyers []DestroyFunc) Des
monitor.Info("destroying...")
for _, destroyer := range destroyers {
if err := destroyer(k8sClient); err != nil {
return errors.Wrap(err, "error while destroying")
return fmt.Errorf("error while destroying: %w", err)
}
}
monitor.Info("destroyed")

View File

@ -1,16 +1,19 @@
package crtlcrd
import (
"fmt"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
ctrl "sigs.k8s.io/controller-runtime"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
databasev1 "github.com/caos/zitadel/operator/api/database/v1"
zitadelv1 "github.com/caos/zitadel/operator/api/zitadel/v1"
"github.com/caos/zitadel/operator/crtlcrd/database"
"github.com/caos/zitadel/operator/crtlcrd/zitadel"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
ctrl "sigs.k8s.io/controller-runtime"
)
const (
@ -39,7 +42,7 @@ func Start(monitor mntr.Monitor, version, metricsAddr string, features ...string
LeaderElectionID: "9adsd12l.caos.ch",
})
if err != nil {
return errors.Wrap(err, "unable to start manager")
return fmt.Errorf("unable to start manager: %w", err)
}
k8sClient, err := kubernetes.NewK8sClientWithConfig(monitor, cfg)
@ -56,7 +59,7 @@ func Start(monitor mntr.Monitor, version, metricsAddr string, features ...string
Scheme: mgr.GetScheme(),
Version: version,
}).SetupWithManager(mgr); err != nil {
return errors.Wrap(err, "unable to create controller")
return fmt.Errorf("unable to create controller: %w", err)
}
case Zitadel:
if err = (&zitadel.Reconciler{
@ -65,13 +68,13 @@ func Start(monitor mntr.Monitor, version, metricsAddr string, features ...string
Scheme: mgr.GetScheme(),
Version: version,
}).SetupWithManager(mgr); err != nil {
return errors.Wrap(err, "unable to create controller")
return fmt.Errorf("unable to create controller: %w", err)
}
}
}
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
return errors.Wrap(err, "problem running manager")
return fmt.Errorf("problem running manager: %w", err)
}
return nil
}

View File

@ -1,6 +1,10 @@
package backups
import (
"fmt"
corev1 "k8s.io/api/core/v1"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/orbos/pkg/labels"
@ -8,8 +12,6 @@ import (
"github.com/caos/orbos/pkg/tree"
"github.com/caos/zitadel/operator"
"github.com/caos/zitadel/operator/database/kinds/backups/bucket"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
)
func Adapt(
@ -44,7 +46,7 @@ func Adapt(
labels.MustReplaceAPI(
labels.GetAPIFromComponent(componentLabels),
"BucketBackup",
desiredTree.Common.Version,
desiredTree.Common.Version(),
),
"backup"),
checkDBReady,
@ -56,7 +58,7 @@ func Adapt(
customImageRegistry,
)(monitor, desiredTree, currentTree)
default:
return nil, nil, nil, nil, nil, false, errors.Errorf("unknown database kind %s", desiredTree.Common.Kind)
return nil, nil, nil, nil, nil, false, mntr.ToUserError(fmt.Errorf("unknown database kind %s", desiredTree.Common.Kind))
}
}
@ -73,6 +75,6 @@ func GetBackupList(
case "databases.caos.ch/BucketBackup":
return bucket.BackupList()(monitor, k8sClient, name, desiredTree)
default:
return nil, errors.Errorf("unknown database kind %s", desiredTree.Common.Kind)
return nil, mntr.ToUserError(fmt.Errorf("unknown database kind %s", desiredTree.Common.Kind))
}
}

View File

@ -1,6 +1,10 @@
package bucket
import (
"fmt"
corev1 "k8s.io/api/core/v1"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/orbos/pkg/kubernetes/resources/secret"
@ -8,14 +12,13 @@ import (
secretpkg "github.com/caos/orbos/pkg/secret"
"github.com/caos/orbos/pkg/secret/read"
"github.com/caos/orbos/pkg/tree"
coreDB "github.com/caos/zitadel/operator/database/kinds/databases/core"
"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/clean"
"github.com/caos/zitadel/operator/database/kinds/backups/bucket/restore"
coreDB "github.com/caos/zitadel/operator/database/kinds/databases/core"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
)
const (
@ -53,7 +56,7 @@ func AdaptFunc(
desiredKind, err := ParseDesiredV0(desired)
if err != nil {
return nil, nil, nil, nil, nil, false, errors.Wrap(err, "parsing desired state failed")
return nil, nil, nil, nil, nil, false, fmt.Errorf("parsing desired state failed: %w", err)
}
desired.Parsed = desiredKind

View File

@ -39,10 +39,7 @@ func TestBucket_Secrets(t *testing.T) {
version := "testVersion2"
desired := getDesiredTree(t, masterkey, &DesiredV0{
Common: &tree.Common{
Kind: "databases.caos.ch/" + kind,
Version: kindVersion,
},
Common: tree.NewCommon("databases.caos.ch/"+kind, kindVersion, false),
Spec: &Spec{
Verbose: true,
Cron: cron,
@ -114,10 +111,7 @@ func TestBucket_AdaptBackup(t *testing.T) {
version := "testVersion2"
desired := getDesiredTree(t, masterkey, &DesiredV0{
Common: &tree.Common{
Kind: "databases.caos.ch/BucketBackup",
Version: "v0",
},
Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false),
Spec: &Spec{
Verbose: true,
Cron: cron,
@ -189,10 +183,7 @@ func TestBucket_AdaptInstantBackup(t *testing.T) {
saJson := "testSA"
desired := getDesiredTree(t, masterkey, &DesiredV0{
Common: &tree.Common{
Kind: "databases.caos.ch/BucketBackup",
Version: "v0",
},
Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false),
Spec: &Spec{
Verbose: true,
Cron: cron,
@ -265,10 +256,7 @@ func TestBucket_AdaptRestore(t *testing.T) {
saJson := "testSA"
desired := getDesiredTree(t, masterkey, &DesiredV0{
Common: &tree.Common{
Kind: "databases.caos.ch/BucketBackup",
Version: "v0",
},
Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false),
Spec: &Spec{
Verbose: true,
Cron: cron,
@ -341,10 +329,7 @@ func TestBucket_AdaptClean(t *testing.T) {
saJson := "testSA"
desired := getDesiredTree(t, masterkey, &DesiredV0{
Common: &tree.Common{
Kind: "databases.caos.ch/BucketBackup",
Version: "v0",
},
Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false),
Spec: &Spec{
Verbose: true,
Cron: cron,

View File

@ -1,10 +1,12 @@
package backup
import (
"fmt"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/zitadel/operator"
"github.com/pkg/errors"
)
func GetCleanupFunc(
@ -15,13 +17,11 @@ func GetCleanupFunc(
return func(k8sClient kubernetes.ClientInt) error {
monitor.Info("waiting for backup to be completed")
if err := k8sClient.WaitUntilJobCompleted(namespace, GetJobName(backupName), timeout); err != nil {
monitor.Error(errors.Wrap(err, "error while waiting for backup to be completed"))
return err
return fmt.Errorf("error while waiting for backup to be completed: %w", err)
}
monitor.Info("backup is completed, cleanup")
if err := k8sClient.DeleteJob(namespace, GetJobName(backupName)); err != nil {
monitor.Error(errors.Wrap(err, "error while trying to cleanup backup"))
return err
return fmt.Errorf("error while trying to cleanup backup: %w", err)
}
monitor.Info("restore backup is completed")
return nil

View File

@ -1,13 +1,14 @@
package backup
import (
"errors"
"testing"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/caos/orbos/mntr"
kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock"
"github.com/golang/mock/gomock"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
func TestBackup_Cleanup1(t *testing.T) {

View File

@ -1,10 +1,12 @@
package clean
import (
"fmt"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/zitadel/operator"
"github.com/pkg/errors"
)
func GetCleanupFunc(
@ -15,13 +17,11 @@ func GetCleanupFunc(
return func(k8sClient kubernetes.ClientInt) error {
monitor.Info("waiting for clean to be completed")
if err := k8sClient.WaitUntilJobCompleted(namespace, GetJobName(backupName), timeout); err != nil {
monitor.Error(errors.Wrap(err, "error while waiting for clean to be completed"))
return err
return fmt.Errorf("error while waiting for clean to be completed: %w", err)
}
monitor.Info("clean is completed, cleanup")
if err := k8sClient.DeleteJob(namespace, GetJobName(backupName)); err != nil {
monitor.Error(errors.Wrap(err, "error while trying to cleanup clean"))
return err
return fmt.Errorf("error while trying to cleanup clean: %w", err)
}
monitor.Info("clean cleanup is completed")
return nil

View File

@ -1,12 +1,14 @@
package clean
import (
"errors"
"testing"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/caos/orbos/mntr"
kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock"
"github.com/golang/mock/gomock"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"testing"
)
func TestBackup_Cleanup1(t *testing.T) {

View File

@ -3,9 +3,9 @@ package bucket
import (
"fmt"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/secret"
"github.com/caos/orbos/pkg/tree"
"github.com/pkg/errors"
)
type DesiredV0 struct {
@ -38,7 +38,7 @@ func ParseDesiredV0(desiredTree *tree.Tree) (*DesiredV0, error) {
}
if err := desiredTree.Original.Decode(desiredKind); err != nil {
return nil, errors.Wrap(err, "parsing desired state failed")
return nil, mntr.ToUserError(fmt.Errorf("parsing desired state failed: %w", err))
}
return desiredKind, nil

View File

@ -1,11 +1,12 @@
package bucket
import (
"testing"
"github.com/caos/orbos/pkg/secret"
"github.com/caos/orbos/pkg/tree"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
"testing"
)
const (
@ -38,10 +39,7 @@ version: v0`
var (
desired = DesiredV0{
Common: &tree.Common{
Kind: "databases.caos.ch/BucketBackup",
Version: "v0",
},
Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false),
Spec: &Spec{
Verbose: true,
Cron: cron,
@ -54,10 +52,7 @@ var (
},
}
desiredWithoutSecret = DesiredV0{
Common: &tree.Common{
Kind: "databases.caos.ch/BucketBackup",
Version: "v0",
},
Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false),
Spec: &Spec{
Verbose: true,
Cron: cron,
@ -65,10 +60,7 @@ var (
},
}
desiredEmpty = DesiredV0{
Common: &tree.Common{
Kind: "databases.caos.ch/BucketBackup",
Version: "v0",
},
Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false),
Spec: &Spec{
Verbose: false,
Cron: "",
@ -80,10 +72,7 @@ var (
}
desiredNil = DesiredV0{
Common: &tree.Common{
Kind: "databases.caos.ch/BucketBackup",
Version: "v0",
},
Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false),
}
)
@ -106,7 +95,9 @@ func getDesiredTree(t *testing.T, masterkey string, desired *DesiredV0) *tree.Tr
}
func TestBucket_DesiredParse(t *testing.T) {
assert.Equal(t, yamlFileWithoutSecret, string(marshalYaml(t, masterkey, &desiredWithoutSecret)))
result := string(marshalYaml(t, masterkey, &desiredWithoutSecret))
assert.Equal(t, yamlFileWithoutSecret, result)
desiredTree := unmarshalYaml(t, masterkey, []byte(yamlFile))
desiredKind, err := ParseDesiredV0(desiredTree)

View File

@ -1,24 +1,27 @@
package bucket
import (
"cloud.google.com/go/storage"
"context"
"fmt"
"strings"
"cloud.google.com/go/storage"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/orbos/pkg/secret/read"
"github.com/caos/orbos/pkg/tree"
"github.com/caos/zitadel/operator/database/kinds/backups/core"
"github.com/pkg/errors"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
"strings"
)
func BackupList() core.BackupListFunc {
return func(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, name string, desired *tree.Tree) ([]string, error) {
desiredKind, err := ParseDesiredV0(desired)
if err != nil {
return nil, errors.Wrap(err, "parsing desired state failed")
return nil, fmt.Errorf("parsing desired state failed: %w", err)
}
desired.Parsed = desiredKind

View File

@ -1,10 +1,11 @@
package restore
import (
"fmt"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/zitadel/operator"
"github.com/pkg/errors"
)
func GetCleanupFunc(
@ -15,13 +16,11 @@ func GetCleanupFunc(
return func(k8sClient kubernetes.ClientInt) error {
monitor.Info("waiting for restore to be completed")
if err := k8sClient.WaitUntilJobCompleted(namespace, GetJobName(backupName), timeout); err != nil {
monitor.Error(errors.Wrap(err, "error while waiting for restore to be completed"))
return err
return fmt.Errorf("error while waiting for restore to be completed: %w", err)
}
monitor.Info("restore is completed, cleanup")
if err := k8sClient.DeleteJob(namespace, GetJobName(backupName)); err != nil {
monitor.Error(errors.Wrap(err, "error while trying to cleanup restore"))
return err
return fmt.Errorf("error while trying to cleanup restore: %w", err)
}
monitor.Info("restore cleanup is completed")
return nil

View File

@ -3,6 +3,7 @@ package core
import (
"crypto/rsa"
"errors"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/orbos/pkg/tree"
"github.com/caos/zitadel/operator"
@ -48,14 +49,14 @@ func SetQueriedForDatabase(queried map[string]interface{}, databaseCurrent *tree
func SetQueriedForDatabaseDBList(queried map[string]interface{}, databases, users []string) {
currentDBList := &CurrentDBList{
Common: &tree.Common{
Kind: "DBList",
Version: "V0",
Kind: "DBList",
},
Current: &DatabaseCurrentDBList{
Databases: databases,
Users: users,
},
}
currentDBList.Common.OverwriteVersion("V0")
currentDB := &tree.Tree{
Parsed: currentDBList,

View File

@ -1,16 +1,19 @@
package databases
import (
"fmt"
core "k8s.io/api/core/v1"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/orbos/pkg/labels"
"github.com/caos/orbos/pkg/secret"
"github.com/caos/orbos/pkg/tree"
"github.com/caos/zitadel/operator"
"github.com/caos/zitadel/operator/database/kinds/databases/managed"
"github.com/caos/zitadel/operator/database/kinds/databases/provided"
"github.com/pkg/errors"
core "k8s.io/api/core/v1"
)
const (
@ -60,7 +63,7 @@ func Adapt(
case "databases.caos.ch/ProvidedDatabase":
return provided.Adapter()(internalMonitor, desiredTree, currentTree)
default:
return nil, nil, nil, nil, nil, false, errors.Errorf("unknown database kind %s", desiredTree.Common.Kind)
return nil, nil, nil, nil, nil, false, mntr.ToUserError(fmt.Errorf("unknown database kind %s: %w", desiredTree.Common.Kind, err))
}
}
@ -76,8 +79,8 @@ func GetBackupList(
case "databases.caos.ch/CockroachDB":
return managed.BackupList()(monitor, k8sClient, desiredTree)
case "databases.caos.ch/ProvidedDatabse":
return nil, errors.Errorf("no backups supported for database kind %s", desiredTree.Common.Kind)
return nil, mntr.ToUserError(fmt.Errorf("no backups supported for database kind %s", desiredTree.Common.Kind))
default:
return nil, errors.Errorf("unknown database kind %s", desiredTree.Common.Kind)
return nil, mntr.ToUserError(fmt.Errorf("unknown database kind %s", desiredTree.Common.Kind))
}
}

View File

@ -1,30 +1,28 @@
package managed
import (
"fmt"
"strconv"
"strings"
"github.com/caos/zitadel/operator/common"
"github.com/caos/zitadel/operator"
"github.com/caos/orbos/pkg/labels"
"github.com/caos/orbos/pkg/secret"
"github.com/caos/zitadel/operator/database/kinds/databases/managed/certificate"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/orbos/pkg/kubernetes/resources/pdb"
"github.com/caos/orbos/pkg/labels"
"github.com/caos/orbos/pkg/secret"
"github.com/caos/orbos/pkg/tree"
"github.com/caos/zitadel/operator"
"github.com/caos/zitadel/operator/common"
"github.com/caos/zitadel/operator/database/kinds/backups"
"github.com/caos/zitadel/operator/database/kinds/databases/core"
"github.com/caos/zitadel/operator/database/kinds/databases/managed/certificate"
"github.com/caos/zitadel/operator/database/kinds/databases/managed/rbac"
"github.com/caos/zitadel/operator/database/kinds/databases/managed/services"
"github.com/caos/zitadel/operator/database/kinds/databases/managed/statefulset"
"github.com/pkg/errors"
)
const (
@ -35,7 +33,6 @@ const (
privateServiceName = SfsName
cockroachPort = int32(26257)
cockroachHTTPPort = int32(8080)
image = "cockroachdb/cockroach:v20.2.3"
)
func Adapter(
@ -54,28 +51,38 @@ func Adapter(
desired *tree.Tree,
current *tree.Tree,
) (
operator.QueryFunc,
operator.DestroyFunc,
operator.ConfigureFunc,
map[string]*secret.Secret,
map[string]*secret.Existing,
bool,
error,
_ operator.QueryFunc,
_ operator.DestroyFunc,
_ operator.ConfigureFunc,
_ map[string]*secret.Secret,
_ map[string]*secret.Existing,
migrate bool,
err error,
) {
defer func() {
if err != nil {
err = fmt.Errorf("adapting managed database failed: %w", err)
}
}()
var (
internalMonitor = monitor.WithField("kind", "cockroachdb")
allSecrets = make(map[string]*secret.Secret)
allExisting = make(map[string]*secret.Existing)
migrate bool
)
desiredKind, err := parseDesiredV0(desired)
if err != nil {
return nil, nil, nil, nil, nil, false, errors.Wrap(err, "parsing desired state failed")
return nil, nil, nil, nil, nil, false, fmt.Errorf("parsing desired state failed: %w", err)
}
desired.Parsed = desiredKind
storageCapacity, err := resource.ParseQuantity(desiredKind.Spec.StorageCapacity)
if err != nil {
return nil, nil, nil, nil, nil, false, mntr.ToUserError(fmt.Errorf("parsing storage capacity format failed: %w", err))
}
if !monitor.IsVerbose() && desiredKind.Spec.Verbose {
internalMonitor.Verbose()
}
@ -120,7 +127,7 @@ func Adapter(
common.CockroachImage.Reference(customImageRegistry),
serviceAccountName,
desiredKind.Spec.ReplicaCount,
desiredKind.Spec.StorageCapacity,
storageCapacity,
cockroachPort,
cockroachHTTPPort,
desiredKind.Spec.StorageClass,
@ -148,10 +155,7 @@ func Adapter(
}
currentDB := &Current{
Common: &tree.Common{
Kind: "databases.caos.ch/CockroachDB",
Version: "v0",
},
Common: tree.NewCommon("databases.caos.ch/CockroachDB", "v0", false),
Current: &CurrentDB{
CA: &certificate.Current{},
},

View File

@ -21,10 +21,7 @@ import (
func getTreeWithDBAndBackup(t *testing.T, masterkey string, saJson string, backupName string) *tree.Tree {
bucketDesired := getDesiredTree(t, masterkey, &bucket.DesiredV0{
Common: &tree.Common{
Kind: "databases.caos.ch/BucketBackup",
Version: "v0",
},
Common: tree.NewCommon("databases.caos.ch/BucketBackup", "v0", false),
Spec: &bucket.Spec{
Verbose: true,
Cron: "testCron",
@ -39,10 +36,7 @@ func getTreeWithDBAndBackup(t *testing.T, masterkey string, saJson string, backu
bucketDesired.Parsed = bucketDesiredKind
return getDesiredTree(t, masterkey, &DesiredV0{
Common: &tree.Common{
Kind: "databases.caos.ch/CockroachDB",
Version: "v0",
},
Common: tree.NewCommon("databases.caos.ch/CockroachDB", "v0", false),
Spec: Spec{
Verbose: false,
ReplicaCount: 1,

View File

@ -74,10 +74,7 @@ func TestManaged_Adapt1(t *testing.T) {
queried := map[string]interface{}{}
desired := getDesiredTree(t, masterkey, &DesiredV0{
Common: &tree.Common{
Kind: "databases.caos.ch/CockroachDB",
Version: "v0",
},
Common: tree.NewCommon("databases.caos.ch/CockroachDB", "v0", false),
Spec: Spec{
Verbose: false,
ReplicaCount: 1,
@ -195,10 +192,7 @@ func TestManaged_Adapt2(t *testing.T) {
queried := map[string]interface{}{}
desired := getDesiredTree(t, masterkey, &DesiredV0{
Common: &tree.Common{
Kind: "databases.caos.ch/CockroachDB",
Version: "v0",
},
Common: tree.NewCommon("databases.caos.ch/CockroachDB", "v0", false),
Spec: Spec{
Verbose: false,
ReplicaCount: 1,

View File

@ -1,10 +1,13 @@
package managed
import (
"fmt"
corev1 "k8s.io/api/core/v1"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes/k8s"
"github.com/caos/orbos/pkg/tree"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
)
type DesiredV0 struct {
@ -32,7 +35,7 @@ func parseDesiredV0(desiredTree *tree.Tree) (*DesiredV0, error) {
}
if err := desiredTree.Original.Decode(desiredKind); err != nil {
return nil, errors.Wrap(err, "parsing desired state failed")
return nil, mntr.ToUserError(fmt.Errorf("parsing desired state failed"))
}
return desiredKind, nil

View File

@ -1,18 +1,20 @@
package managed
import (
"fmt"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/orbos/pkg/tree"
"github.com/caos/zitadel/operator/database/kinds/backups"
"github.com/pkg/errors"
)
func BackupList() func(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, desired *tree.Tree) ([]string, error) {
return func(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, desired *tree.Tree) ([]string, error) {
desiredKind, err := parseDesiredV0(desired)
if err != nil {
return nil, errors.Wrap(err, "parsing desired state failed")
return nil, fmt.Errorf("parsing desired state failed: %w", err)
}
desired.Parsed = desiredKind

View File

@ -1,14 +1,16 @@
package statefulset
import (
"errors"
"fmt"
"sort"
"strings"
"time"
"github.com/caos/orbos/pkg/labels"
"github.com/caos/zitadel/operator"
"github.com/caos/zitadel/operator/helpers"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"github.com/caos/orbos/mntr"
@ -16,11 +18,10 @@ import (
"github.com/caos/orbos/pkg/kubernetes/k8s"
"github.com/caos/orbos/pkg/kubernetes/resources"
"github.com/caos/orbos/pkg/kubernetes/resources/statefulset"
"github.com/pkg/errors"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/caos/orbos/pkg/labels"
"github.com/caos/zitadel/operator"
"github.com/caos/zitadel/operator/helpers"
)
const (
@ -55,7 +56,7 @@ func AdaptFunc(
image string,
serviceAccountName string,
replicaCount int,
storageCapacity string,
storageCapacity resource.Quantity,
dbPort int32,
httpPort int32,
storageClass string,
@ -72,11 +73,6 @@ func AdaptFunc(
) {
internalMonitor := monitor.WithField("component", "statefulset")
quantity, err := resource.ParseQuantity(storageCapacity)
if err != nil {
return nil, nil, nil, nil, nil, err
}
name := sfsSelectable.Name()
k8sSelectable := labels.MustK8sMap(sfsSelectable)
statefulsetDef := &appsv1.StatefulSet{
@ -197,7 +193,7 @@ func AdaptFunc(
},
Resources: corev1.ResourceRequirements{
Requests: corev1.ResourceList{
"storage": quantity,
"storage": storageCapacity,
},
},
StorageClassName: &storageClass,
@ -219,8 +215,7 @@ func AdaptFunc(
checkDBRunning := func(k8sClient kubernetes.ClientInt) error {
internalMonitor.Info("waiting for statefulset to be running")
if err := k8sClient.WaitUntilStatefulsetIsReady(namespace, name, true, false, 60*time.Second); err != nil {
internalMonitor.Error(errors.Wrap(err, "error while waiting for statefulset to be running"))
return err
return fmt.Errorf("error while waiting for statefulset to be running: %w", err)
}
internalMonitor.Info("statefulset is running")
return nil
@ -232,7 +227,6 @@ func AdaptFunc(
internalMonitor.Info("statefulset is not ready")
return nil
}
internalMonitor.Info("statefulset is ready")
return errors.New("statefulset is ready")
}
@ -256,8 +250,7 @@ func AdaptFunc(
checkDBReady := func(k8sClient kubernetes.ClientInt) error {
internalMonitor.Info("waiting for statefulset to be ready")
if err := k8sClient.WaitUntilStatefulsetIsReady(namespace, name, true, true, 60*time.Second); err != nil {
internalMonitor.Error(errors.Wrap(err, "error while waiting for statefulset to be ready"))
return err
return fmt.Errorf("error while waiting for statefulset to be ready: %w", err)
}
internalMonitor.Info("statefulset is ready")
return nil

View File

@ -1,6 +1,8 @@
package statefulset
import (
"testing"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes/k8s"
kubernetesmock "github.com/caos/orbos/pkg/kubernetes/mock"
@ -13,7 +15,6 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"testing"
)
func TestStatefulset_JoinExec0(t *testing.T) {
@ -291,7 +292,7 @@ func TestStatefulset_Adapt1(t *testing.T) {
image,
serviceAccountName,
replicaCount,
storageCapacity,
resource.MustParse(storageCapacity),
dbPort,
httpPort,
storageClass,
@ -487,7 +488,7 @@ func TestStatefulset_Adapt2(t *testing.T) {
image,
serviceAccountName,
replicaCount,
storageCapacity,
resource.MustParse(storageCapacity),
dbPort,
httpPort,
storageClass,

View File

@ -1,12 +1,14 @@
package provided
import (
"fmt"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/orbos/pkg/secret"
"github.com/caos/orbos/pkg/tree"
"github.com/caos/zitadel/operator"
"github.com/pkg/errors"
)
func Adapter() operator.AdaptFunc {
@ -25,15 +27,12 @@ func Adapter() operator.AdaptFunc {
) {
desiredKind, err := parseDesiredV0(desired)
if err != nil {
return nil, nil, nil, nil, nil, false, errors.Wrap(err, "parsing desired state failed")
return nil, nil, nil, nil, nil, false, fmt.Errorf("parsing desired state failed: %w", err)
}
desired.Parsed = desiredKind
currentDB := &Current{
Common: &tree.Common{
Kind: "databases.caos.ch/ProvidedDatabase",
Version: "v0",
},
Common: tree.NewCommon("databases.caos.ch/ProvidedDatabase", "v0", false),
}
current.Parsed = currentDB

View File

@ -1,8 +1,10 @@
package provided
import (
"fmt"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/tree"
"github.com/pkg/errors"
)
type DesiredV0 struct {
@ -25,7 +27,7 @@ func parseDesiredV0(desiredTree *tree.Tree) (*DesiredV0, error) {
}
if err := desiredTree.Original.Decode(desiredKind); err != nil {
return nil, errors.Wrap(err, "parsing desired state failed")
return nil, mntr.ToUserError(fmt.Errorf("parsing desired state failed: %w", err))
}
return desiredKind, nil

View File

@ -1,6 +1,8 @@
package orb
import (
"fmt"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/orbos/pkg/kubernetes/resources/namespace"
@ -8,12 +10,12 @@ import (
"github.com/caos/orbos/pkg/secret"
"github.com/caos/orbos/pkg/tree"
"github.com/caos/orbos/pkg/treelabels"
"github.com/caos/zitadel/operator"
"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/restore"
"github.com/caos/zitadel/operator/database/kinds/databases"
"github.com/pkg/errors"
)
const (
@ -45,14 +47,16 @@ func AdaptFunc(
err error,
) {
defer func() {
err = errors.Wrapf(err, "building %s failed", orbDesiredTree.Common.Kind)
if err != nil {
err = fmt.Errorf("building %s failed: %w", orbDesiredTree.Common.Kind, err)
}
}()
orbMonitor := monitor.WithField("kind", "orb")
desiredKind, err := ParseDesiredV0(orbDesiredTree)
if err != nil {
return nil, nil, nil, nil, nil, migrate, errors.Wrap(err, "parsing desired state failed")
return nil, nil, nil, nil, nil, migrate, fmt.Errorf("parsing desired state failed: %w", err)
}
orbDesiredTree.Parsed = desiredKind
currentTree = &tree.Tree{}
@ -118,10 +122,7 @@ func AdaptFunc(
}
currentTree.Parsed = &DesiredV0{
Common: &tree.Common{
Kind: "databases.caos.ch/Orb",
Version: "v0",
},
Common: tree.NewCommon("databases.caos.ch/Orb", "v0", false),
Database: databaseCurrent,
}

View File

@ -1,18 +1,20 @@
package orb
import (
"fmt"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/orbos/pkg/tree"
"github.com/caos/zitadel/operator/database/kinds/databases"
"github.com/pkg/errors"
)
func BackupListFunc() func(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, desiredTree *tree.Tree) (strings []string, err error) {
return func(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, desiredTree *tree.Tree) (strings []string, err error) {
desiredKind, err := ParseDesiredV0(desiredTree)
if err != nil {
return nil, errors.Wrap(err, "parsing desired state failed")
return nil, fmt.Errorf("parsing desired state failed: %w", err)
}
desiredTree.Parsed = desiredKind

View File

@ -1,8 +1,10 @@
package orb
import (
"fmt"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/tree"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
)
@ -28,9 +30,9 @@ func ParseDesiredV0(desiredTree *tree.Tree) (*DesiredV0, error) {
desiredKind := &DesiredV0{Common: desiredTree.Common}
if err := desiredTree.Original.Decode(desiredKind); err != nil {
return nil, errors.Wrap(err, "parsing desired state failed")
return nil, mntr.ToUserError(fmt.Errorf("parsing desired state failed: %w", err))
}
desiredKind.Common.Version = "v0"
desiredKind.Common.OverwriteVersion("v0")
return desiredKind, nil
}

View File

@ -1,14 +1,17 @@
package orb
import (
"errors"
"fmt"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/orbos/pkg/labels"
"github.com/caos/orbos/pkg/tree"
"github.com/caos/orbos/pkg/treelabels"
"github.com/caos/zitadel/operator"
zitadelKubernetes "github.com/caos/zitadel/pkg/kubernetes"
"github.com/pkg/errors"
)
func Reconcile(
@ -23,29 +26,23 @@ func Reconcile(
recMonitor := monitor.WithField("version", spec.Version)
if spec.Version == "" {
err := errors.New("No version provided for self-reconciling")
return err
return errors.New("no version provided for self-reconciling")
}
if spec.SelfReconciling {
desiredTree := &tree.Tree{
Common: &tree.Common{
Kind: "databases.caos.ch/Orb",
Version: "v0",
},
Common: tree.NewCommon("databases.caos.ch/Orb", "v0", false),
}
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"))
return err
return fmt.Errorf("failed to deploy database-operator into k8s-cluster: %w", err)
}
recMonitor.Info("Applied database-operator")
}
return nil
}, func(k8sClient kubernetes.ClientInt) error {
if err := zitadelKubernetes.DestroyDatabaseOperator(monitor, labels.MustForAPI(labels.NoopOperator("database-operator"), "database", "v0"), k8sClient, gitops); err != nil {
monitor.Error(errors.Wrap(err, "Failed to destroy database-operator in k8s-cluster"))
return err
return fmt.Errorf("failed to destroy database-operator in k8s-cluster: %w", err)
}
monitor.Info("Destroyed database-operator")
return nil

View File

@ -105,7 +105,7 @@ func getAllSecrets(
}
if len(allSecrets) == 0 && len(allExisting) == 0 {
return nil, nil, nil, errors.New("couldn't find any secrets")
return nil, nil, nil, mntr.ToUserError(errors.New("couldn't find any secrets"))
}
return allSecrets, allExisting, allTrees, nil
@ -158,7 +158,7 @@ func push(
desired, found := trees[desiredFile.WOExtension()]
if !found {
return fmt.Errorf("desired state not found for %s", desiredFile.WOExtension())
return mntr.ToUserError(fmt.Errorf("desired state not found for %s", desiredFile.WOExtension()))
}
if gitops {

View File

@ -3,16 +3,16 @@ package iam
import (
"fmt"
"github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database"
core "k8s.io/api/core/v1"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/labels"
"github.com/caos/orbos/pkg/secret"
"github.com/caos/orbos/pkg/tree"
"github.com/caos/zitadel/operator"
"github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel"
"github.com/pkg/errors"
core "k8s.io/api/core/v1"
"github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database"
)
func Adapt(
@ -46,7 +46,7 @@ func Adapt(
switch desiredTree.Common.Kind {
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,
@ -59,6 +59,6 @@ func Adapt(
customImageRegistry,
)(monitor, desiredTree, currentTree)
default:
return nil, nil, nil, nil, nil, false, errors.Errorf("unknown iam kind %s", desiredTree.Common.Kind)
return nil, nil, nil, nil, nil, false, mntr.ToUserError(fmt.Errorf("unknown iam kind %s", desiredTree.Common.Kind))
}
}

View File

@ -1,29 +1,29 @@
package zitadel
import (
"errors"
"fmt"
"strconv"
"github.com/caos/orbos/pkg/helper"
"strings"
"gopkg.in/yaml.v3"
"github.com/caos/orbos/pkg/labels"
"github.com/caos/orbos/pkg/secret"
"github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database"
"github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/setup"
core "k8s.io/api/core/v1"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/helper"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/orbos/pkg/labels"
"github.com/caos/orbos/pkg/secret"
"github.com/caos/orbos/pkg/tree"
"github.com/caos/zitadel/operator"
"github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/ambassador"
"github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/configuration"
"github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database"
"github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/deployment"
"github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/migration"
"github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/services"
"github.com/pkg/errors"
"github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/setup"
)
func AdaptFunc(
@ -54,8 +54,19 @@ func AdaptFunc(
internalMonitor := monitor.WithField("kind", "iam")
desiredKind, err := parseDesiredV0(desired)
_, _, sendAnalytics := mntr.Environment()
if sendAnalytics &&
desiredKind != nil &&
desiredKind.Spec != nil &&
desiredKind.Spec.Configuration != nil &&
desiredKind.Spec.Configuration.DNS != nil &&
desiredKind.Spec.Configuration.DNS.Domain != "" {
monitor.SwitchEnvironment(strings.ToLower(strings.ReplaceAll(desiredKind.Spec.Configuration.DNS.Domain, ".", "-")))
}
if err != nil {
return nil, nil, nil, nil, nil, false, errors.Wrap(err, "parsing desired state failed")
return nil, nil, nil, nil, nil, false, fmt.Errorf("parsing desired state failed: %w", err)
}
desired.Parsed = desiredKind
@ -114,7 +125,6 @@ func AdaptFunc(
certPath,
secretName,
secretPath,
version,
consoleCMName,
secretVarsName,
secretPasswordName,

View File

@ -38,7 +38,6 @@ func AdaptFunc(
certPath string,
secretName string,
secretPath string,
version *string,
consoleCMName string,
secretVarsName string,
secretPasswordName string,
@ -149,7 +148,6 @@ func AdaptFunc(
secretPath,
googleServiceAccountJSONPath,
zitadelKeysPath,
version,
queried,
),
)
@ -196,7 +194,6 @@ func AdaptFunc(
secretPath,
googleServiceAccountJSONPath,
zitadelKeysPath,
version,
queried,
),
),

View File

@ -34,7 +34,7 @@ func SetConfigMap(
Name: cmName,
Labels: labels,
},
Data: literalsConfigMap(desired, users, certPath, secretPath, googleServiceAccountJSONPath, zitadelKeysPath, version, queried),
Data: literalsConfigMap(desired, users, certPath, secretPath, googleServiceAccountJSONPath, zitadelKeysPath, queried),
})
}
@ -215,7 +215,6 @@ func TestConfiguration_Adapt(t *testing.T) {
certPath,
secretName,
secretPath,
&version,
consoleCMName,
secretVarsName,
secretPasswordName,
@ -325,7 +324,6 @@ func TestConfiguration_AdaptFull(t *testing.T) {
certPath,
secretName,
secretPath,
&version,
consoleCMName,
secretVarsName,
secretPasswordName,

View File

@ -19,7 +19,6 @@ type Configuration struct {
DNS *DNS `yaml:"dns"`
ClusterDNS string `yaml:"clusterdns"`
AssetStorage *AssetStorage `yaml:"assetStorage,omitempty"`
Sentry *Sentry `yaml:"sentry,omitempty"`
}
func (c *Configuration) Validate() (err error) {
@ -143,11 +142,3 @@ type Cache struct {
ShortMaxAge string `yaml:"shortMaxAge,omitempty"`
ShortSharedMaxAge string `yaml:"shortSharedMaxAge,omitempty"`
}
type Sentry struct {
SentryDSN *secret.Secret `yaml:"sentryDSN,omitempty"`
ExistingSentryDSN *secret.Existing `yaml:"existingSentryDSN,omitempty"`
Environment string `yaml:"environment,omitempty"`
Version string `yaml:"version,omitempty"`
Usage string `yaml:"usage,omitempty"`
}

View File

@ -5,6 +5,8 @@ import (
"strconv"
"strings"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/secret/read"
"github.com/caos/orbos/pkg/kubernetes"
@ -19,7 +21,6 @@ func literalsConfigMap(
desired *Configuration,
users map[string]string,
certPath, secretPath, googleServiceAccountJSONPath, zitadelKeysPath string,
version *string,
queried map[string]interface{},
) map[string]string {
@ -110,13 +111,12 @@ func literalsConfigMap(
literalsConfigMap["ZITADEL_ASSET_STORAGE_BUCKET_PREFIX"] = desired.AssetStorage.BucketPrefix
literalsConfigMap["ZITADEL_ASSET_STORAGE_MULTI_DELETE"] = strconv.FormatBool(desired.AssetStorage.MultiDelete)
}
if desired.Sentry != nil {
literalsConfigMap["SENTRY_ENVIRONMENT"] = desired.Sentry.Environment
literalsConfigMap["SENTRY_RELEASE"] = *version
literalsConfigMap["SENTRY_USAGE"] = desired.Sentry.Usage
}
}
sentryEnv, _, doIngest := mntr.Environment()
literalsConfigMap["SENTRY_ENVIRONMENT"] = sentryEnv
literalsConfigMap["SENTRY_USAGE"] = strconv.FormatBool(doIngest)
db, err := database.GetDatabaseInQueried(queried)
if err == nil {
literalsConfigMap["ZITADEL_EVENTSTORE_HOST"] = db.Host
@ -197,16 +197,13 @@ func literalsSecretVars(k8sClient kubernetes.ClientInt, desired *Configuration)
literalsSecretVars["ZITADEL_ASSET_STORAGE_SECRET_ACCESS_KEY"] = value
}
}
if desired.Sentry != nil {
as := desired.Sentry
if as.SentryDSN != nil || as.ExistingSentryDSN != nil {
value, err := read.GetSecretValue(k8sClient, as.SentryDSN, as.ExistingSentryDSN)
if err != nil {
return nil, err
}
literalsSecretVars["SENTRY_DSN"] = value
}
_, dsns, doIngest := mntr.Environment()
zitadelDsn := ""
if doIngest {
zitadelDsn = dsns["zitadel"]
}
literalsSecretVars["SENTRY_DSN"] = zitadelDsn
}
return literalsSecretVars, nil
}

View File

@ -222,7 +222,6 @@ func TestConfiguration_LiteralsConfigMap(t *testing.T) {
secretPath := "test"
googleSA := "test"
zitadelKeyPath := "test"
version := "test"
users := map[string]string{
"migration": "migration",
"management": "management",
@ -296,9 +295,11 @@ func TestConfiguration_LiteralsConfigMap(t *testing.T) {
"ZITADEL_ASSET_STORAGE_LOCATION": "",
"ZITADEL_ASSET_STORAGE_BUCKET_PREFIX": "",
"ZITADEL_ASSET_STORAGE_MULTI_DELETE": "false",
"SENTRY_ENVIRONMENT": "",
"SENTRY_USAGE": "false",
}
literals := literalsConfigMap(desiredEmpty, users, certPath, secretPath, googleSA, zitadelKeyPath, &version, queried)
literals := literalsConfigMap(desiredEmpty, users, certPath, secretPath, googleSA, zitadelKeyPath, queried)
assert.Equal(t, equals, literals)
}
@ -308,7 +309,6 @@ func TestConfiguration_LiteralsConfigMapFull(t *testing.T) {
secretPath := "test"
googleSA := "test"
zitadelKeyPath := "test"
version := "test"
users := map[string]string{
"migration": "migration2",
"management": "management2",
@ -382,8 +382,10 @@ func TestConfiguration_LiteralsConfigMapFull(t *testing.T) {
"ZITADEL_ASSET_STORAGE_LOCATION": "location",
"ZITADEL_ASSET_STORAGE_BUCKET_PREFIX": "bucketprefix",
"ZITADEL_ASSET_STORAGE_MULTI_DELETE": "false",
"SENTRY_ENVIRONMENT": "",
"SENTRY_USAGE": "false",
}
literals := literalsConfigMap(desiredFull, users, certPath, secretPath, googleSA, zitadelKeyPath, &version, queried)
literals := literalsConfigMap(desiredFull, users, certPath, secretPath, googleSA, zitadelKeyPath, queried)
assert.EqualValues(t, equals, literals)
}
@ -461,6 +463,7 @@ func TestConfiguration_LiteralsSecretVars(t *testing.T) {
"ZITADEL_TWILIO_SID": "",
"ZITADEL_ASSET_STORAGE_ACCESS_KEY_ID": "",
"ZITADEL_ASSET_STORAGE_SECRET_ACCESS_KEY": "",
"SENTRY_DSN": "",
}
literals, err := literalsSecretVars(client, desiredEmpty)
assert.NoError(t, err)
@ -477,6 +480,7 @@ func TestConfiguration_LiteralsSecretVarsFull(t *testing.T) {
"ZITADEL_TWILIO_SID": "sid",
"ZITADEL_ASSET_STORAGE_ACCESS_KEY_ID": "accesskeyid",
"ZITADEL_ASSET_STORAGE_SECRET_ACCESS_KEY": "secretaccesskey",
"SENTRY_DSN": "",
}
literals, err := literalsSecretVars(client, desiredFull)
@ -534,6 +538,7 @@ func TestConfiguration_LiteralsSecretVarsExisting(t *testing.T) {
"ZITADEL_TWILIO_SID": sid,
"ZITADEL_ASSET_STORAGE_ACCESS_KEY_ID": akid,
"ZITADEL_ASSET_STORAGE_SECRET_ACCESS_KEY": sak,
"SENTRY_DSN": "",
}
literals, err := literalsSecretVars(client, desiredFull)

View File

@ -1,9 +1,10 @@
package configuration
import (
"fmt"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/pkg/errors"
)
func GetReadyFunc(
@ -18,23 +19,23 @@ func GetReadyFunc(
return func(k8sClient kubernetes.ClientInt) error {
monitor.Debug("Waiting for configuration to be created")
if err := k8sClient.WaitForSecret(namespace, secretName, timeout); err != nil {
return errors.Wrap(err, "error while waiting for secret")
return fmt.Errorf("error while waiting for secret: %w", err)
}
if err := k8sClient.WaitForSecret(namespace, secretVarsName, timeout); err != nil {
return errors.Wrap(err, "error while waiting for vars secret ")
return fmt.Errorf("error while waiting for vars secret: %w", err)
}
if err := k8sClient.WaitForSecret(namespace, secretPasswordName, timeout); err != nil {
return errors.Wrap(err, "error while waiting for password secret")
return fmt.Errorf("error while waiting for password secret: %w", err)
}
if err := k8sClient.WaitForConfigMap(namespace, cmName, timeout); err != nil {
return errors.Wrap(err, "error while waiting for configmap")
return fmt.Errorf("error while waiting for configmap: %w", err)
}
if err := k8sClient.WaitForConfigMap(namespace, consoleCMName, timeout); err != nil {
return errors.Wrap(err, "error while waiting for console configmap")
return fmt.Errorf("error while waiting for console configmap: %w", err)
}
monitor.Debug("configuration is created")
return nil

View File

@ -1,21 +1,21 @@
package deployment
import (
"fmt"
"time"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/orbos/pkg/labels"
"github.com/caos/zitadel/operator"
"github.com/pkg/errors"
)
func GetReadyFunc(monitor mntr.Monitor, namespace string, name *labels.Name) operator.EnsureFunc {
return func(k8sClient kubernetes.ClientInt) error {
monitor.Info("waiting for deployment to be ready")
if err := k8sClient.WaitUntilDeploymentReady(namespace, name.Name(), true, true, 60*time.Second); err != nil {
monitor.Error(errors.Wrap(err, "error while waiting for deployment to be ready"))
return err
return fmt.Errorf("error while waiting for deployment to be ready: %w", err)
}
monitor.Info("deployment is ready")
return nil

View File

@ -3,11 +3,13 @@ package zitadel
import (
"fmt"
corev1 "k8s.io/api/core/v1"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes/k8s"
"github.com/caos/orbos/pkg/tree"
"github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/configuration"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
)
type DesiredV0 struct {
@ -29,7 +31,7 @@ type Spec struct {
func (s *Spec) validate() (err error) {
defer func() {
if err != nil {
err = fmt.Errorf("validating spec failed: %w", err)
err = mntr.ToUserError(fmt.Errorf("validating spec failed: %w", err))
}
}()
@ -43,8 +45,7 @@ func parseDesiredV0(desiredTree *tree.Tree) (*DesiredV0, error) {
}
if err := desiredTree.Original.Decode(desiredKind); err != nil {
return nil, errors.Wrap(err, "parsing desired state failed")
return nil, mntr.ToUserError(fmt.Errorf("parsing desired state failed: %w", err))
}
return desiredKind, nil
}

View File

@ -4,26 +4,26 @@ import (
"crypto/sha512"
"encoding/base64"
"encoding/json"
"fmt"
"os"
"path/filepath"
"regexp"
"sort"
"github.com/pkg/errors"
"github.com/rakyll/statik/fs"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/orbos/pkg/kubernetes/resources/configmap"
"github.com/caos/orbos/pkg/kubernetes/resources/job"
"github.com/caos/orbos/pkg/labels"
"github.com/caos/zitadel/operator"
"github.com/caos/zitadel/operator/helpers"
"github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
_ "github.com/caos/zitadel/statik"
)
@ -209,7 +209,7 @@ func getMigrationFiles(monitor mntr.Monitor, root string) []migration {
statikFS, err := fs.New()
if err != nil {
monitor.Error(errors.Wrap(err, "failed to load migration files"))
monitor.Error(fmt.Errorf("failed to load migration files: %w", err))
return migrations
}
err = fs.Walk(statikFS, root, func(path string, info os.FileInfo, err error) error {

View File

@ -1,10 +1,11 @@
package migration
import (
"fmt"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/zitadel/operator"
"github.com/pkg/errors"
)
func GetCleanupFunc(
@ -15,8 +16,7 @@ func GetCleanupFunc(
return func(k8sClient kubernetes.ClientInt) error {
monitor.Info("cleanup migration job")
if err := k8sClient.DeleteJob(namespace, getJobName(reason)); err != nil {
monitor.Error(errors.Wrap(err, "error during job deletion"))
return err
return fmt.Errorf("error during job deletion: %w", err)
}
monitor.Info("migration cleanup is completed")
return nil

View File

@ -1,12 +1,13 @@
package migration
import (
"fmt"
"time"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/zitadel/operator"
"github.com/pkg/errors"
)
const (
@ -21,8 +22,7 @@ func GetDoneFunc(
return func(k8sClient kubernetes.ClientInt) error {
monitor.Info("waiting for migration to be completed")
if err := k8sClient.WaitUntilJobCompleted(namespace, getJobName(reason), timeout); err != nil {
monitor.Error(errors.Wrap(err, "error while waiting for migration to be completed"))
return err
return fmt.Errorf("error while waiting for migration to be completed: %w", err)
}
monitor.Info("migration is completed")
return nil

View File

@ -125,19 +125,5 @@ func getSecretsMap(desiredKind *DesiredV0) (
secrets[secretKey] = conf.AssetStorage.SecretAccessKey
existing[secretKey] = conf.AssetStorage.ExistingSecretAccessKey
if conf.Sentry == nil {
conf.Sentry = &configuration.Sentry{}
}
if conf.Sentry.SentryDSN == nil {
conf.Sentry.SentryDSN = &secret.Secret{}
}
if conf.Sentry.ExistingSentryDSN == nil {
conf.Sentry.ExistingSentryDSN = &secret.Existing{}
}
SentryDSN := "sentrydsn"
secrets[SentryDSN] = conf.Sentry.SentryDSN
existing[SentryDSN] = conf.Sentry.ExistingSentryDSN
return secrets, existing
}

View File

@ -1,11 +1,13 @@
package setup
import (
"fmt"
"time"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/zitadel/operator"
"github.com/pkg/errors"
"time"
)
const (
@ -20,8 +22,7 @@ func GetDoneFunc(
return func(k8sClient kubernetes.ClientInt) error {
monitor.Info("waiting for setup to be completed")
if err := k8sClient.WaitUntilJobCompleted(namespace, getJobName(reason), timeout); err != nil {
monitor.Error(errors.Wrap(err, "error while waiting for setup to be completed"))
return err
return fmt.Errorf("error while waiting for setup to be completed: %w", err)
}
monitor.Info("migration is completed")
return nil

View File

@ -1,16 +1,18 @@
package orb
import (
"fmt"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/orbos/pkg/kubernetes/resources/namespace"
"github.com/caos/orbos/pkg/orb"
"github.com/caos/orbos/pkg/secret"
"github.com/caos/orbos/pkg/tree"
"github.com/caos/zitadel/operator"
"github.com/caos/zitadel/operator/zitadel/kinds/iam"
zitadeldb "github.com/caos/zitadel/operator/zitadel/kinds/iam/zitadel/database"
"github.com/pkg/errors"
)
const (
@ -38,7 +40,9 @@ func AdaptFunc(
err error,
) {
defer func() {
err = errors.Wrapf(err, "building %s failed", desiredTree.Common.Kind)
if err != nil {
err = fmt.Errorf("building %s failed: %w", desiredTree.Common.Kind, err)
}
}()
allSecrets = make(map[string]*secret.Secret)
@ -48,7 +52,7 @@ func AdaptFunc(
desiredKind, err := ParseDesiredV0(desiredTree)
if err != nil {
return nil, nil, nil, nil, nil, false, errors.Wrap(err, "parsing desired state failed")
return nil, nil, nil, nil, nil, false, fmt.Errorf("parsing desired state failed: %w", err)
}
desiredTree.Parsed = desiredKind
currentTree = &tree.Tree{}
@ -122,11 +126,8 @@ func AdaptFunc(
}
currentTree.Parsed = &DesiredV0{
Common: &tree.Common{
Kind: "zitadel.caos.ch/Orb",
Version: "v0",
},
IAM: iamCurrent,
Common: tree.NewCommon("zitadel.caos.ch/Orb", "v0", false),
IAM: iamCurrent,
}
return func(k8sClient kubernetes.ClientInt, _ map[string]interface{}) (operator.EnsureFunc, error) {

View File

@ -1,9 +1,12 @@
package orb
import (
"github.com/caos/orbos/pkg/tree"
"github.com/pkg/errors"
"fmt"
corev1 "k8s.io/api/core/v1"
"github.com/caos/orbos/mntr"
"github.com/caos/orbos/pkg/tree"
)
type DesiredV0 struct {
@ -28,9 +31,9 @@ func ParseDesiredV0(desiredTree *tree.Tree) (*DesiredV0, error) {
desiredKind := &DesiredV0{Common: desiredTree.Common}
if err := desiredTree.Original.Decode(desiredKind); err != nil {
return nil, errors.Wrap(err, "parsing desired state failed")
return nil, mntr.ToUserError(fmt.Errorf("parsing desired state failed: %w", err))
}
desiredKind.Common.Version = "v0"
desiredKind.Common.OverwriteVersion("v0")
return desiredKind, nil
}

View File

@ -1,15 +1,17 @@
package orb
import (
"errors"
"fmt"
"github.com/caos/orbos/mntr"
kubernetes2 "github.com/caos/orbos/pkg/kubernetes"
"github.com/caos/orbos/pkg/labels"
"github.com/caos/orbos/pkg/tree"
"github.com/caos/orbos/pkg/treelabels"
"github.com/caos/zitadel/operator"
"github.com/caos/zitadel/pkg/kubernetes"
"github.com/pkg/errors"
)
func Reconcile(
@ -24,17 +26,12 @@ func Reconcile(
recMonitor := monitor.WithField("version", spec.Version)
if spec.Version == "" {
err := errors.New("No version provided for self-reconciling")
recMonitor.Error(err)
return err
return mntr.ToUserError(errors.New("no version provided for self-reconciling"))
}
if spec.SelfReconciling {
desiredTree := &tree.Tree{
Common: &tree.Common{
Kind: "zitadel.caos.ch/Orb",
Version: "v0",
},
Common: tree.NewCommon("zitadel.caos.ch/Orb", "v0", false),
}
if err := kubernetes.EnsureZitadelOperatorArtifacts(monitor, treelabels.MustForAPI(desiredTree, mustZITADELOperator(&spec.Version)), k8sClient, spec.Version, spec.NodeSelector, spec.Tolerations, spec.CustomImageRegistry, gitops); err != nil {
@ -45,8 +42,7 @@ func Reconcile(
return nil
}, func(k8sClient kubernetes2.ClientInt) error {
if err := kubernetes.DestroyZitadelOperator(monitor, labels.MustForAPI(labels.NoopOperator("zitadel-operator"), "zitadel", "v0"), k8sClient, gitops); err != nil {
monitor.Error(errors.Wrap(err, "Failed to destroy zitadel-operator in k8s-cluster"))
return err
return fmt.Errorf("failed to destroy zitadel-operator in k8s-cluster: %w", err)
}
monitor.Info("Destroyed zitadel-operator")
return nil

View File

@ -256,6 +256,10 @@ status:
}}
}
if _, _, analyticsEnabled := mntr.Environment(); !analyticsEnabled {
cmd = append(cmd, "--disable-analytics")
}
deployment := &apps.Deployment{
ObjectMeta: mach.ObjectMeta{
Name: nameLabels.Name(),
@ -601,6 +605,10 @@ status:
}}
}
if _, _, analyticsEnabled := mntr.Environment(); !analyticsEnabled {
cmd = append(cmd, "--disable-analytics")
}
deployment := &apps.Deployment{
ObjectMeta: mach.ObjectMeta{
Name: nameLabels.Name(),