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

feat: improve configuration parsing #24

Merged
merged 18 commits into from
Nov 21, 2023
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
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:

- uses: actions/setup-go@v4
with:
go-version: '1.21.3'
go-version: '1.21.4'

- name: make verify
run: make verify
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/foss.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Set up Go 1.x
uses: actions/setup-go@v4
with:
go-version: '1.21.3'
go-version: '1.21.4'
id: go

- name: Checkout code
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
- run: git fetch --force --tags
- uses: actions/setup-go@v4
with:
go-version: '1.21.3'
go-version: '1.21.4'

- name: Synopsys Detect
run: |
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: MIT
# Build the manager binary
FROM golang:1.21.3 as builder
FROM golang:1.21.4 as builder
ARG TARGETOS
ARG TARGETARCH

Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,12 @@ export GARM_OPERATOR_VERSION=<garm-operator-version>
export GARM_SERVER_URL=<garm-server-url>
export GARM_SERVER_USERNAME=<garm-server-username>
export GARM_SERVER_PASSWORD=<garm-server-password>
export OPERATOR_WATCH_NAMESPACE=<operator-watch-namespace>
curl -L https://github.com/mercedes-benz/garm-operator/releases/download/${GARM_OPERATOR_VERSION}/garm-operator-all.yaml | envsubst | kubectl apply -f -
```

The full configuration parsing documentation can be found in the [configuration parsing guide](./docs/config/configuration-parsing.md)

#### Custom Resources

The CRD documentation can be also seen via [docs.crds.dev](https://doc.crds.dev/github.com/mercedes-benz/garm-operator).
Expand Down
153 changes: 57 additions & 96 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,23 @@
package main

import (
"errors"
"flag"
"fmt"
"os"
"time"

"github.com/spf13/pflag"
"gopkg.in/yaml.v2"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth"
"k8s.io/klog/v2"
"k8s.io/klog/v2/klogr"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/healthz"

garmoperatorv1alpha1 "github.com/mercedes-benz/garm-operator/api/v1alpha1"
"github.com/mercedes-benz/garm-operator/internal/controller"
"github.com/mercedes-benz/garm-operator/pkg/config"
"github.com/mercedes-benz/garm-operator/pkg/flags"
)

var (
Expand All @@ -36,68 +35,45 @@ func init() {
}

func main() {
var (
metricsAddr string
enableLeaderElection bool
probeAddr string
syncPeriod time.Duration

watchNamespace string

garmServer string
garmUsername string
garmPassword string
)

flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
"Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")
flag.DurationVar(&syncPeriod, "sync-period", 5*time.Minute,
"The minimum interval at which watched resources are reconciled (e.g. 15m)")

flag.StringVar(&watchNamespace, "namespace", "",
"Namespace that the controller watches to reconcile garm objects. If unspecified, the controller watches for garm objects across all namespaces.")

flag.StringVar(&garmServer, "garm-server", "", "The address of the GARM server")
flag.StringVar(&garmUsername, "garm-username", "", "The username for the GARM server")
flag.StringVar(&garmPassword, "garm-password", "", "The password for the GARM server")

klog.InitFlags(flag.CommandLine)
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.Parse()
ctrl.SetLogger(klogr.New())

// configure garm client from environment variables
if len(os.Getenv("GARM_SERVER")) > 0 {
setupLog.Info("Using garm-server from environment variable")
garmServer = os.Getenv("GARM_SERVER")
}
if len(os.Getenv("GARM_USERNAME")) > 0 {
setupLog.Info("Using garm-username from environment variable")
garmUsername = os.Getenv("GARM_USERNAME")
}
if len(os.Getenv("GARM_PASSWORD")) > 0 {
setupLog.Info("Using garm-password from environment variable")
garmPassword = os.Getenv("GARM_PASSWORD")
// initiate flags
f := flags.InitiateFlags()

// retrieve config flag value for GenerateConfig() function
configFile := f.Lookup("config").Value.String()

// call GenerateConfig() function from config package
if err := config.GenerateConfig(f, configFile); err != nil {
setupLog.Error(err, "failed to read config")
os.Exit(1)
}
if len(os.Getenv("WATCH_NAMESPACE")) > 0 {
setupLog.Info("using watch-namespace from environment variable")
watchNamespace = os.Getenv("WATCH_NAMESPACE")

// check if dry-run flag is set to true
dryRun, _ := f.GetBool("dry-run")

// perform dry-run if enabled and print out the generated Config as yaml
if dryRun {
yamlConfig, err := yaml.Marshal(config.Config)
if err != nil {
setupLog.Error(err, "failed to marshal config as yaml")
os.Exit(1)
}
fmt.Printf("generated Config as yaml:\n%s\n", yamlConfig)
os.Exit(0)
}

var watchNamespaces []string
if watchNamespace != "" {
watchNamespaces = []string{watchNamespace}
if config.Config.Operator.WatchNamespace != "" {
watchNamespaces = []string{config.Config.Operator.WatchNamespace}
}

mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
MetricsBindAddress: metricsAddr,
MetricsBindAddress: config.Config.Operator.MetricsBindAddress,
Port: 9443,
HealthProbeBindAddress: probeAddr,
LeaderElection: enableLeaderElection,
HealthProbeBindAddress: config.Config.Operator.HealthProbeBindAddress,
LeaderElection: config.Config.Operator.LeaderElection,
LeaderElectionID: "b608d8b3.mercedes-benz.com",
// LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily
// when the Manager ends. This requires the binary to immediately end when the
Expand All @@ -113,38 +89,25 @@ func main() {
//
// Default Sync Period = 10 hours.
// Set default via flag to 5 minutes
SyncPeriod: &syncPeriod,
SyncPeriod: &config.Config.Operator.SyncPeriod,
Cache: cache.Options{
Namespaces: watchNamespaces,
SyncPeriod: &syncPeriod,
SyncPeriod: &config.Config.Operator.SyncPeriod,
},
})
if err != nil {
setupLog.Error(err, "unable to start manager")
os.Exit(1)
}

if garmServer == "" {
setupLog.Error(errors.New("unable to fetch garm server from either flag or os_env"), "unable to start manager")
os.Exit(1)
}
if garmUsername == "" {
setupLog.Error(errors.New("unable to fetch garm username from either flag or os_env"), "unable to start manager")
os.Exit(1)
}
if garmPassword == "" {
setupLog.Error(errors.New("unable to fetch garm password from either flag or os_env"), "unable to start manager")
os.Exit(1)
}

if err = (&controller.EnterpriseReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Recorder: mgr.GetEventRecorderFor("enterprise-controller"),

BaseURL: garmServer,
Username: garmUsername,
Password: garmPassword,
BaseURL: config.Config.Garm.Server,
Username: config.Config.Garm.Username,
Password: config.Config.Garm.Password,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Enterprise")
os.Exit(1)
Expand All @@ -154,37 +117,35 @@ func main() {
Scheme: mgr.GetScheme(),
Recorder: mgr.GetEventRecorderFor("pool-controller"),

BaseURL: garmServer,
Username: garmUsername,
Password: garmPassword,
BaseURL: config.Config.Garm.Server,
Username: config.Config.Garm.Username,
Password: config.Config.Garm.Password,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Pool")
os.Exit(1)
}

if os.Getenv("CREATE_WEBHOOK") == "true" {
if err = (&garmoperatorv1alpha1.Pool{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create webhook", "webhook", "Pool")
os.Exit(1)
}
if err = (&garmoperatorv1alpha1.Image{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create webhook", "webhook", "Image")
os.Exit(1)
}
if err = (&garmoperatorv1alpha1.Repository{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create webhook", "webhook", "Repository")
os.Exit(1)
}
if err = (&garmoperatorv1alpha1.Pool{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create webhook", "webhook", "Pool")
os.Exit(1)
}
if err = (&garmoperatorv1alpha1.Image{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create webhook", "webhook", "Image")
os.Exit(1)
}
if err = (&garmoperatorv1alpha1.Repository{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create webhook", "webhook", "Repository")
os.Exit(1)
}

if err = (&controller.OrganizationReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Recorder: mgr.GetEventRecorderFor("organization-controller"),

BaseURL: garmServer,
Username: garmUsername,
Password: garmPassword,
BaseURL: config.Config.Garm.Server,
Username: config.Config.Garm.Username,
Password: config.Config.Garm.Password,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Organization")
os.Exit(1)
Expand All @@ -195,9 +156,9 @@ func main() {
Scheme: mgr.GetScheme(),
Recorder: mgr.GetEventRecorderFor("repository-controller"),

BaseURL: garmServer,
Username: garmUsername,
Password: garmPassword,
BaseURL: config.Config.Garm.Server,
Username: config.Config.Garm.Username,
Password: config.Config.Garm.Password,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Repository")
os.Exit(1)
Expand Down
8 changes: 1 addition & 7 deletions config/manager/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,8 @@ spec:
- --garm-server=$GARM_SERVER_URL
- --garm-username=$GARM_SERVER_USERNAME
- --garm-password=$GARM_SERVER_PASSWORD
- --operator-watch-namespace=$OPERATOR_WATCH_NAMESPACE
image: controller:latest
env:
- name: CREATE_WEBHOOK
value: "true"
- name: WATCH_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
name: manager
securityContext:
allowPrivilegeEscalation: false
Expand Down
Loading