Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support reading database ServerConfig credentials from k8s secrets #143

Merged
merged 16 commits into from
Jun 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ jobs:
build:
name: Build & Test
runs-on: ubuntu-latest
outputs:
registry: ${{ steps.registry.outputs.registry }} # workaround since env is not available outside of steps, i.e. in calling external workflows like we later do in e2e-test

steps:
- id: registry
run: echo "registry=${{ env.REGISTRY }}" >> "$GITHUB_OUTPUT"

- name: Check out the code
uses: actions/checkout@v2
with:
Expand Down Expand Up @@ -59,6 +65,15 @@ jobs:
build-args: |
"VERSION=0.0.${{ github.run_id }}"

helm-e2e-test:
uses: otterize/helm-charts/.github/workflows/e2e-test.yaml@main
name: Trigger e2e tests from helm charts repo
secrets: inherit
with:
gcr-registry: ${{ needs.build.outputs.registry }}
credentials-operator-tag: ${{ github.sha }}
needs:
- build

tag-latest:
name: Tag latest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,17 +296,86 @@ func (e *Reconciler) runAlterPasswordForSecrets(ctx context.Context, secrets []v
return nil
}

func (e *Reconciler) extractDBCredentials(ctx context.Context, namespace string, credentialsSpec otterizev1alpha3.DatabaseCredentials) (databaseconfigurator.DatabaseCredentials, error) {
creds := databaseconfigurator.DatabaseCredentials{}
if credentialsSpec.Username != "" {
creds.Username = credentialsSpec.Username
}
if credentialsSpec.Password != "" {
creds.Password = credentialsSpec.Password
}
if credentialsSpec.SecretRef != nil {
secret := v1.Secret{}
name := credentialsSpec.SecretRef.Name
if credentialsSpec.SecretRef.Namespace != "" {
namespace = credentialsSpec.SecretRef.Namespace
}
err := e.client.Get(ctx, client.ObjectKey{Name: name, Namespace: namespace}, &secret)
if err != nil {
return creds, errors.Wrap(err)
}
if username, ok := secret.Data[credentialsSpec.SecretRef.UsernameKey]; ok {
creds.Username = string(username)
}
if password, ok := secret.Data[credentialsSpec.SecretRef.PasswordKey]; ok {
creds.Password = string(password)
}
}

if creds.Username == "" || creds.Password == "" {
return creds, errors.New("credentials missing either username or password")
}

return creds, nil
}

func (e *Reconciler) createPostgresDBConfigurator(ctx context.Context, pgServerConfig otterizev1alpha3.PostgreSQLServerConfig) (databaseconfigurator.DatabaseConfigurator, error) {
credentials, err := e.extractDBCredentials(ctx, pgServerConfig.Namespace, pgServerConfig.Spec.Credentials)
if err != nil {
return nil, errors.Wrap(err)
}

dbInfo := postgres.PostgresDatabaseInfo{
Credentials: credentials,
Address: pgServerConfig.Spec.Address,
}

dbconfigurator, err := postgres.NewPostgresConfigurator(ctx, dbInfo)
if err != nil {
return nil, errors.Wrap(err)
}
return dbconfigurator, nil
}

func (e *Reconciler) createMySQLDBConfigurator(ctx context.Context, mySQLServerConfig otterizev1alpha3.MySQLServerConfig) (databaseconfigurator.DatabaseConfigurator, error) {
credentials, err := e.extractDBCredentials(ctx, mySQLServerConfig.Namespace, mySQLServerConfig.Spec.Credentials)
if err != nil {
return nil, errors.Wrap(err)
}

dbInfo := mysql.MySQLDatabaseInfo{
Credentials: credentials,
Address: mySQLServerConfig.Spec.Address,
}

dbconfigurator, err := mysql.NewMySQLConfigurator(ctx, dbInfo)
if err != nil {
return nil, errors.Wrap(err)
}
return dbconfigurator, nil
}

func (e *Reconciler) createDBConfigurator(
ctx context.Context,
database string,
mysqlServerConfigs []otterizev1alpha3.MySQLServerConfig,
pgServerConfigs []otterizev1alpha3.PostgreSQLServerConfig) (databaseconfigurator.DatabaseConfigurator, bool, error) {

mysqlConf, found := lo.Find(mysqlServerConfigs, func(config otterizev1alpha3.MySQLServerConfig) bool {
mysqlServerConf, found := lo.Find(mysqlServerConfigs, func(config otterizev1alpha3.MySQLServerConfig) bool {
return config.Name == database
})
if found {
dbconfigurator, err := mysql.NewMySQLConfigurator(ctx, mysqlConf.Spec)
dbconfigurator, err := e.createMySQLDBConfigurator(ctx, mysqlServerConf)
if err != nil {
return nil, false, errors.Wrap(err)
}
Expand All @@ -317,7 +386,7 @@ func (e *Reconciler) createDBConfigurator(
return config.Name == database
})
if found {
dbconfigurator, err := postgres.NewPostgresConfigurator(ctx, pgServerConf.Spec)
dbconfigurator, err := e.createPostgresDBConfigurator(ctx, pgServerConf)
if err != nil {
return nil, false, errors.Wrap(err)
}
Expand Down Expand Up @@ -359,15 +428,15 @@ func closeAllConnections(ctx context.Context, allConfigurators []databaseconfigu
func (e *Reconciler) GetAllDBConfigurators(ctx context.Context, mysqlServerConfigs []otterizev1alpha3.MySQLServerConfig, pgServerConfigs []otterizev1alpha3.PostgreSQLServerConfig) []databaseconfigurator.DatabaseConfigurator {
configurators := make([]databaseconfigurator.DatabaseConfigurator, 0)
for _, mysqlServerConfig := range mysqlServerConfigs {
dbconfigurator, err := mysql.NewMySQLConfigurator(ctx, mysqlServerConfig.Spec)
dbconfigurator, err := e.createMySQLDBConfigurator(ctx, mysqlServerConfig)
if err != nil {
logrus.WithError(err).Errorf("Failed to create configurator for MySQL server config: %s", mysqlServerConfig.Name)
continue
}
configurators = append(configurators, dbconfigurator)
}
for _, pgServerConfig := range pgServerConfigs {
dbconfigurator, err := postgres.NewPostgresConfigurator(ctx, pgServerConfig.Spec)
dbconfigurator, err := e.createPostgresDBConfigurator(ctx, pgServerConfig)
if err != nil {
logrus.WithError(err).Errorf("Failed to create configurator for PostgreSQL server config: %s", pgServerConfig.Name)
continue
Expand Down
2 changes: 1 addition & 1 deletion src/operator/go.mod

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/operator/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 12 additions & 12 deletions src/operator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,6 @@ func initSpireClient(ctx context.Context, spireServerAddr string) (spireclient.S
}

func main() {
errorreporter.Init("credentials-operator", version.Version(), viper.GetString(operatorconfig.TelemetryErrorsAPIKeyKey))
defer errorreporter.AutoNotify()
shared.RegisterPanicHandlers()

var secretsManager tls_pod.SecretsManager
var workloadRegistry tls_pod.WorkloadRegistry

Expand All @@ -132,8 +128,20 @@ func main() {
TimestampFormat: time.RFC3339,
})

signalHandlerCtx := ctrl.SetupSignalHandler()

clusterUID, err := clusterutils.GetOrCreateClusterUID(signalHandlerCtx)
if err != nil {
logrus.WithError(err).Panic("Failed obtaining cluster ID")
}
componentinfo.SetGlobalContextId(telemetrysender.Anonymize(clusterUID))

ctrl.SetLogger(logrusr.New(logrus.StandardLogger()))

errorreporter.Init(telemetriesgql.TelemetryComponentTypeCredentialsOperator, version.Version())
defer errorreporter.AutoNotify()
shared.RegisterPanicHandlers()

mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
Metrics: server.Options{
Expand All @@ -148,7 +156,6 @@ func main() {
logrus.WithError(err).Panic("unable to initialize manager")
}

signalHandlerCtx := ctrl.SetupSignalHandler()
podNamespace := os.Getenv("POD_NAMESPACE")
if podNamespace == "" {
logrus.Panic("POD_NAMESPACE environment variable is required")
Expand All @@ -166,13 +173,6 @@ func main() {
logrus.WithError(err).Panic("unable to ensure otterize CRDs")
}

clusterUID, err := clusterutils.GetOrCreateClusterUID(signalHandlerCtx)
if err != nil {
logrus.WithError(err).Panic("Failed fetching cluster UID")
}
componentinfo.SetGlobalContextId(telemetrysender.Anonymize(clusterUID))
componentinfo.SetGlobalVersion(version.Version())

serviceIdResolver := serviceidresolver.NewResolver(mgr.GetClient())
eventRecorder := mgr.GetEventRecorderFor("credentials-operator")

Expand Down
Loading