Skip to content

Commit

Permalink
Scaffold code in cmd/manager/main.go for Go operators and add logic…
Browse files Browse the repository at this point in the history
… to Ansible/Helm operators to handle [multinamespace caching] (#2522)

**Motivation for the change:**

- Integration with OLM: See that OLM allows and config the MultiNamespace via the option  `targetNamespaces` via the OperatorGroup. We are also in the olm commands setting these values in the WATCH-NAMESPACE EnvVar. 

- Address the requirements requested in tasks such as #2494, #2078, (which are a very common scenario in the channels: I as an operator dev, would like to deploy the operator in the nsA and WATCH the resources in the nsB and do not all cluster ), 

Closes #2361
  • Loading branch information
camilamacedo86 authored Feb 18, 2020
1 parent 7a3da2f commit 9ed25ae
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 37 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- Added support for relative Ansible roles and playbooks paths in the Ansible operator's file. ([#2273](https://github.com/operator-framework/operator-sdk/pull/2273))
- Add Prometheus metrics support to Ansible-based operators. ([#2179](https://github.com/operator-framework/operator-sdk/pull/2179))
- On `generate csv`, populate a CSV manifest’s `spec.icon`, `spec.keywords`, and `spec.mantainers` fields with empty values to better inform users how to add data. ([#2521](https://github.com/operator-framework/operator-sdk/pull/2521))
- Scaffold code in `cmd/manager/main.go` for Go operators and add logic to Ansible/Helm operators to handle [multinamespace caching](https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/cache#MultiNamespacedCacheBuilder) if `WATCH_NAMESPACE` contains multiple namespaces. ([#2522](https://github.com/operator-framework/operator-sdk/pull/2522))

### Changed
- Ansible scaffolding has been rewritten to be simpler and make use of newer features of Ansible and Molecule.
Expand Down
20 changes: 17 additions & 3 deletions internal/scaffold/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import (
"fmt"
"os"
"runtime"
"strings"
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
_ "k8s.io/client-go/plugin/pkg/client/auth"
Expand All @@ -62,6 +63,7 @@ import (
"github.com/spf13/pflag"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client/config"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/manager"
Expand Down Expand Up @@ -127,11 +129,23 @@ func main() {
os.Exit(1)
}
// Create a new Cmd to provide shared dependencies and start components
mgr, err := manager.New(cfg, manager.Options{
// Set default manager options
options := manager.Options{
Namespace: namespace,
MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
})
}
// Add support for MultiNamespace set in WATCH_NAMESPACE (e.g ns1,ns2)
// Note that this is not intended to be used for excluding namespaces, this is better done via a Predicate
// Also note that you may face performance issues when using this with a high number of namespaces.
// More Info: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/cache#MultiNamespacedCacheBuilder
if strings.Contains(namespace, ",") {
options.Namespace = ""
options.NewCache = cache.MultiNamespacedCacheBuilder(strings.Split(namespace, ","))
}
// Create a new manager to provide shared dependencies and start components
mgr, err := manager.New(cfg, options)
if err != nil {
log.Error(err, "")
os.Exit(1)
Expand Down
20 changes: 17 additions & 3 deletions internal/scaffold/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
"fmt"
"os"
"runtime"
"strings"
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
_ "k8s.io/client-go/plugin/pkg/client/auth"
Expand All @@ -61,6 +62,7 @@ import (
"github.com/spf13/pflag"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client/config"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/manager"
Expand Down Expand Up @@ -126,11 +128,23 @@ func main() {
os.Exit(1)
}
// Create a new Cmd to provide shared dependencies and start components
mgr, err := manager.New(cfg, manager.Options{
// Set default manager options
options := manager.Options{
Namespace: namespace,
MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
})
}
// Add support for MultiNamespace set in WATCH_NAMESPACE (e.g ns1,ns2)
// Note that this is not intended to be used for excluding namespaces, this is better done via a Predicate
// Also note that you may face performance issues when using this with a high number of namespaces.
// More Info: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/cache#MultiNamespacedCacheBuilder
if strings.Contains(namespace, ",") {
options.Namespace = ""
options.NewCache = cache.MultiNamespacedCacheBuilder(strings.Split(namespace, ","))
}
// Create a new manager to provide shared dependencies and start components
mgr, err := manager.New(cfg, options)
if err != nil {
log.Error(err, "")
os.Exit(1)
Expand Down
42 changes: 29 additions & 13 deletions pkg/ansible/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"fmt"
"os"
"runtime"
"strings"

"github.com/operator-framework/operator-sdk/pkg/ansible/controller"
aoflags "github.com/operator-framework/operator-sdk/pkg/ansible/flags"
Expand Down Expand Up @@ -64,24 +65,15 @@ func printVersion() {
func Run(flags *aoflags.AnsibleOperatorFlags) error {
printVersion()

namespace, found := os.LookupEnv(k8sutil.WatchNamespaceEnvVar)
log = log.WithValues("Namespace", namespace)
if found {
log.Info("Watching namespace.")
} else {
log.Info(fmt.Sprintf("%v environment variable not set. This operator is watching all namespaces.",
k8sutil.WatchNamespaceEnvVar))
namespace = metav1.NamespaceAll
}

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

// Set default manager options
// TODO: probably should expose the host & port as an environment variables
mgr, err := manager.New(cfg, manager.Options{
Namespace: namespace,
options := manager.Options{
MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
NewClient: func(cache cache.Cache, config *rest.Config, options client.Options) (client.Client, error) {
c, err := client.New(config, options)
Expand All @@ -94,7 +86,31 @@ func Run(flags *aoflags.AnsibleOperatorFlags) error {
StatusClient: c,
}, nil
},
})
}

namespace, found := os.LookupEnv(k8sutil.WatchNamespaceEnvVar)
log = log.WithValues("Namespace", namespace)
if found {
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 {
log.Info(fmt.Sprintf("%v environment variable not set. Watching all namespaces.",
k8sutil.WatchNamespaceEnvVar))
options.Namespace = metav1.NamespaceAll
}

// Create a new manager to provide shared dependencies and start components
mgr, err := manager.New(cfg, options)
if err != nil {
log.Error(err, "Failed to create a new manager.")
return err
Expand Down
45 changes: 28 additions & 17 deletions pkg/helm/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"fmt"
"os"
"runtime"
"strings"

"github.com/operator-framework/operator-sdk/pkg/helm/controller"
hoflags "github.com/operator-framework/operator-sdk/pkg/helm/flags"
Expand Down Expand Up @@ -61,27 +62,14 @@ func printVersion() {
func Run(flags *hoflags.HelmOperatorFlags) error {
printVersion()

namespace, found := os.LookupEnv(k8sutil.WatchNamespaceEnvVar)
log = log.WithValues("Namespace", namespace)
if found {
if namespace == metav1.NamespaceAll {
log.Info("Watching all namespaces.")
} else {
log.Info("Watching single namespace.")
}
} else {
log.Info(fmt.Sprintf("%v environment variable not set. Watching all namespaces.",
k8sutil.WatchNamespaceEnvVar))
namespace = metav1.NamespaceAll
}

cfg, err := config.GetConfig()
if err != nil {
log.Error(err, "Failed to get config.")
return err
}
mgr, err := manager.New(cfg, manager.Options{
Namespace: namespace,

// Set default manager options
options := manager.Options{
MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
NewClient: func(cache cache.Cache, config *rest.Config, options crclient.Options) (crclient.Client, error) {
c, err := crclient.New(config, options)
Expand All @@ -94,7 +82,30 @@ func Run(flags *hoflags.HelmOperatorFlags) error {
StatusClient: c,
}, nil
},
})
}

namespace, found := os.LookupEnv(k8sutil.WatchNamespaceEnvVar)
log = log.WithValues("Namespace", namespace)
if found {
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 {
log.Info(fmt.Sprintf("%v environment variable not set. Watching all namespaces.",
k8sutil.WatchNamespaceEnvVar))
options.Namespace = metav1.NamespaceAll
}

mgr, err := manager.New(cfg, options)
if err != nil {
log.Error(err, "Failed to create a new manager.")
return err
Expand Down
2 changes: 1 addition & 1 deletion test/test-framework/cmd/manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func main() {
os.Exit(1)
}

// Create a new Cmd to provide shared dependencies and start components
// Create a new manager to provide shared dependencies and start components
mgr, err := manager.New(cfg, manager.Options{
Namespace: namespace,
MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
Expand Down

0 comments on commit 9ed25ae

Please sign in to comment.