Skip to content

Commit

Permalink
Add code for building and running helm operator binary (#110)
Browse files Browse the repository at this point in the history
* [Helm] Add client package

* [Helm] Add libraries of Helm operator

* [Helm] Move library packages and add helm binary

The following changes are made in this PR:
1. Add code for building and running helm operator binary
2. Move pkg/internal/controllerutil out of internal/ dir
3. Add separate helpers to read watches.yaml file for helm operator
4. Move `diff.go` and `types.go` from `pkg/internal` to `internal/`

* [Helm] Remove  from SupportsOwnerReference

Signed-off-by: varshaprasad96 <varshaprasad96@gmail.com>

* [test] test ci

Signed-off-by: varshaprasad96 <varshaprasad96@gmail.com>

* modify setOwnerReference to accept unstructred.Unstructured

Signed-off-by: varshaprasad96 <varshaprasad96@gmail.com>

* rearrange helm library related code to internal/legacy/
  • Loading branch information
varshaprasad96 committed Nov 2, 2021
1 parent 1780093 commit 1e7e868
Show file tree
Hide file tree
Showing 39 changed files with 3,094 additions and 17 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ require (
github.com/onsi/gomega v1.14.0
github.com/operator-framework/operator-lib v0.3.0
github.com/prometheus/client_golang v1.11.0
github.com/sergi/go-diff v1.1.0
github.com/sirupsen/logrus v1.8.1
github.com/spf13/afero v1.2.2
github.com/spf13/cobra v1.1.3
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.7.0
gomodules.xyz/jsonpatch/v2 v2.2.0
gomodules.xyz/jsonpatch/v3 v3.0.1
helm.sh/helm/v3 v3.6.2
k8s.io/api v0.22.1
k8s.io/apiextensions-apiserver v0.22.1
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1263,6 +1263,10 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T
gomodules.xyz/jsonpatch/v2 v2.1.0/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU=
gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY=
gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY=
gomodules.xyz/jsonpatch/v3 v3.0.1 h1:Te7hKxV52TKCbNYq3t84tzKav3xhThdvSsSp/W89IyI=
gomodules.xyz/jsonpatch/v3 v3.0.1/go.mod h1:CBhndykehEwTOlEfnsfJwvkFQbSN8YZFr9M+cIHAJto=
gomodules.xyz/orderedmap v0.1.0 h1:fM/+TGh/O1KkqGR5xjTKg6bU8OKBkg7p0Y+x/J9m8Os=
gomodules.xyz/orderedmap v0.1.0/go.mod h1:g9/TPUCm1t2gwD3j3zfV8uylyYhVdCNSi+xCEIu7yTU=
google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
Expand Down
221 changes: 221 additions & 0 deletions internal/cmd/helm-operator/run/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
// Copyright 2020 The Operator-SDK Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package run

import (
"errors"
"flag"
"fmt"
"os"
"runtime"
"strings"

"github.com/operator-framework/helm-operator-plugins/internal/flags"
"github.com/operator-framework/helm-operator-plugins/internal/legacy/controller"
"github.com/operator-framework/helm-operator-plugins/internal/legacy/release"
watches "github.com/operator-framework/helm-operator-plugins/internal/legacy/watches"
"github.com/operator-framework/helm-operator-plugins/internal/metrics"
"github.com/operator-framework/helm-operator-plugins/internal/version"
helmmgr "github.com/operator-framework/helm-operator-plugins/pkg/manager"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client/config"
"sigs.k8s.io/controller-runtime/pkg/healthz"
logf "sigs.k8s.io/controller-runtime/pkg/log"
zapf "sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/manager/signals"
crmetrics "sigs.k8s.io/controller-runtime/pkg/metrics"
)

var log = logf.Log.WithName("cmd")

func printVersion() {
log.Info("Version",
"Go Version", runtime.Version(),
"GOOS", runtime.GOOS,
"GOARCH", runtime.GOARCH,
"helm-operator", version.GitVersion,
"commit", version.GitCommit)
}

func NewCmd() *cobra.Command {
f := &flags.Flags{}
zapfs := flag.NewFlagSet("zap", flag.ExitOnError)
opts := &zapf.Options{}
opts.BindFlags(zapfs)

cmd := &cobra.Command{
Use: "run",
Short: "Run the operator",
Run: func(cmd *cobra.Command, _ []string) {
logf.SetLogger(zapf.New(zapf.UseFlagOptions(opts)))
run(cmd, f)
},
}

f.AddTo(cmd.Flags())
cmd.Flags().AddGoFlagSet(zapfs)
return cmd
}

func run(cmd *cobra.Command, f *flags.Flags) {
printVersion()
metrics.RegisterBuildInfo(crmetrics.Registry)

// Load config options from the config at f.ManagerConfigPath.
// These options will not override those set by flags.
var (
options manager.Options
err error
)
if f.ManagerConfigPath != "" {
cfgLoader := ctrl.ConfigFile().AtPath(f.ManagerConfigPath)
if options, err = options.AndFrom(cfgLoader); err != nil {
log.Error(err, "Unable to load the manager config file")
os.Exit(1)
}
}
exitIfUnsupported(options)

cfg, err := config.GetConfig()
if err != nil {
log.Error(err, "Failed to get config.")
os.Exit(1)
}

// TODO(2.0.0): remove
// Deprecated: OPERATOR_NAME environment variable is an artifact of the
// legacy operator-sdk project scaffolding. Flag `--leader-election-id`
// should be used instead.
if operatorName, found := os.LookupEnv("OPERATOR_NAME"); found {
log.Info("Environment variable OPERATOR_NAME has been deprecated, use --leader-election-id instead.")
if cmd.Flags().Changed("leader-election-id") {
log.Info("Ignoring OPERATOR_NAME environment variable since --leader-election-id is set")
} else if options.LeaderElectionID == "" {
// Only set leader election ID using OPERATOR_NAME if unset everywhere else,
// since this env var is deprecated.
options.LeaderElectionID = operatorName
}
}

//TODO(2.0.0): remove the following checks. they are required just because of the flags deprecation
if cmd.Flags().Changed("leader-elect") && cmd.Flags().Changed("enable-leader-election") {
log.Error(errors.New("only one of --leader-elect and --enable-leader-election may be set"), "invalid flags usage")
os.Exit(1)
}

if cmd.Flags().Changed("metrics-addr") && cmd.Flags().Changed("metrics-bind-address") {
log.Error(errors.New("only one of --metrics-addr and --metrics-bind-address may be set"), "invalid flags usage")
os.Exit(1)
}

// Set default manager options
options = f.ToManagerOptions(options)

if options.NewClient == nil {
options.NewClient = helmmgr.NewCachingClientFunc()
}
namespace, found := os.LookupEnv(helmmgr.WatchNamespaceEnvVar)
log = log.WithValues("Namespace", namespace)
if found {
log.V(1).Info(fmt.Sprintf("Setting namespace with value in %s", helmmgr.WatchNamespaceEnvVar))
if namespace == metav1.NamespaceAll {
log.Info("Watching all namespaces.")
options.Namespace = metav1.NamespaceAll
} else {
if strings.Contains(namespace, ",") {
log.Info("Watching multiple namespaces.")
options.NewCache = cache.MultiNamespacedCacheBuilder(strings.Split(namespace, ","))
} else {
log.Info("Watching single namespace.")
options.Namespace = namespace
}
}
} else if options.Namespace == "" {
log.Info(fmt.Sprintf("Watch namespaces not configured by environment variable %s or file. "+
"Watching all namespaces.", helmmgr.WatchNamespaceEnvVar))
options.Namespace = metav1.NamespaceAll
}

mgr, err := manager.New(cfg, options)
if err != nil {
log.Error(err, "Failed to create a new manager")
os.Exit(1)
}

if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
log.Error(err, "Unable to set up health check")
os.Exit(1)
}
if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
log.Error(err, "Unable to set up ready check")
os.Exit(1)
}

ws, err := watches.Load(f.WatchesFile)
if err != nil {
log.Error(err, "Failed to create new manager factories.")
os.Exit(1)
}

for _, w := range ws {
// Register the controller with the factory.
err := controller.Add(mgr, controller.WatchOptions{
Namespace: namespace,
GVK: w.GroupVersionKind,
ManagerFactory: release.NewManagerFactory(mgr, w.ChartDir),
ReconcilePeriod: f.ReconcilePeriod,
WatchDependentResources: *w.WatchDependentResources,
OverrideValues: w.OverrideValues,
MaxConcurrentReconciles: f.MaxConcurrentReconciles,
Selector: w.Selector,
})
if err != nil {
log.Error(err, "Failed to add manager factory to controller.")
os.Exit(1)
}
}

// Start the Cmd
if err = mgr.Start(signals.SetupSignalHandler()); err != nil {
log.Error(err, "Manager exited non-zero.")
os.Exit(1)
}

}

// exitIfUnsupported prints an error containing unsupported field names and exits
// if any of those fields are not their default values.
func exitIfUnsupported(options manager.Options) {
var keys []string
// The below options are webhook-specific, which is not supported by ansible.
if options.CertDir != "" {
keys = append(keys, "certDir")
}
if options.Host != "" {
keys = append(keys, "host")
}
if options.Port != 0 {
keys = append(keys, "port")
}

if len(keys) > 0 {
log.Error(fmt.Errorf("%s set in manager options", strings.Join(keys, ", ")), "unsupported fields")
os.Exit(1)
}
}
File renamed without changes.
Loading

0 comments on commit 1e7e868

Please sign in to comment.