diff --git a/pkg/cmd/install.go b/pkg/cmd/install.go index 17b15c7d57..2af4b54189 100644 --- a/pkg/cmd/install.go +++ b/pkg/cmd/install.go @@ -63,6 +63,7 @@ func newCmdInstall(rootCmdOptions *RootCmdOptions) *cobra.Command { cmd.Flags().BoolVar(&impl.skipOperatorSetup, "skip-operator-setup", false, "Do not install the operator in the namespace (in case there's a global one)") cmd.Flags().BoolVar(&impl.skipClusterSetup, "skip-cluster-setup", false, "Skip the cluster-setup phase") cmd.Flags().BoolVar(&impl.exampleSetup, "example", false, "Install example integration") + cmd.Flags().BoolVar(&impl.global, "global", false, "Configure the operator to watch all namespaces") cmd.Flags().StringVarP(&impl.outputFormat, "output", "o", "", "Output format. One of: json|yaml") cmd.Flags().StringVar(&impl.registry.Organization, "organization", "", "A organization on the Docker registry that can be used to publish images") @@ -102,6 +103,7 @@ type installCmdOptions struct { skipOperatorSetup bool skipClusterSetup bool exampleSetup bool + global bool outputFormat string camelVersion string runtimeVersion string @@ -152,7 +154,12 @@ func (o *installCmdOptions) install(_ *cobra.Command, _ []string) error { namespace := o.Namespace if !o.skipOperatorSetup { - err = install.OperatorOrCollect(o.Context, c, namespace, o.operatorImage, collection) + cfg := install.OperatorConfiguration{ + CustomImage: o.operatorImage, + Namespace: namespace, + Global: o.global, + } + err = install.OperatorOrCollect(o.Context, c, cfg, collection) if err != nil { return err } diff --git a/pkg/controller/integrationplatform/integrationplatform_controller.go b/pkg/controller/integrationplatform/integrationplatform_controller.go index 0ffeaca9ce..61425ab047 100644 --- a/pkg/controller/integrationplatform/integrationplatform_controller.go +++ b/pkg/controller/integrationplatform/integrationplatform_controller.go @@ -14,6 +14,7 @@ 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 integrationplatform import ( diff --git a/pkg/install/operator.go b/pkg/install/operator.go index 8b1c8bb707..9acf70d9e5 100644 --- a/pkg/install/operator.go +++ b/pkg/install/operator.go @@ -20,47 +20,99 @@ package install import ( "context" "errors" + "strings" v1 "k8s.io/api/apps/v1" + v1beta1 "k8s.io/api/rbac/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "github.com/apache/camel-k/deploy" "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" "github.com/apache/camel-k/pkg/client" + "github.com/apache/camel-k/pkg/util/envvar" "github.com/apache/camel-k/pkg/util/knative" "github.com/apache/camel-k/pkg/util/kubernetes" "github.com/apache/camel-k/pkg/util/minishift" "github.com/apache/camel-k/pkg/util/openshift" ) +// OperatorConfiguration -- +type OperatorConfiguration struct { + CustomImage string + Namespace string + Global bool +} + // Operator installs the operator resources in the given namespace -func Operator(ctx context.Context, c client.Client, customImage string, namespace string) error { - return OperatorOrCollect(ctx, c, namespace, customImage, nil) +func Operator(ctx context.Context, c client.Client, cfg OperatorConfiguration) error { + return OperatorOrCollect(ctx, c, cfg, nil) } // OperatorOrCollect installs the operator resources or adds them to the collector if present -func OperatorOrCollect(ctx context.Context, c client.Client, namespace string, customImage string, collection *kubernetes.Collection) error { - customizer := IdentityResourceCustomizer - if customImage != "" { - customizer = func(o runtime.Object) runtime.Object { +func OperatorOrCollect(ctx context.Context, c client.Client, cfg OperatorConfiguration, collection *kubernetes.Collection) error { + customizer := func(o runtime.Object) runtime.Object { + if cfg.CustomImage != "" { if d, ok := o.(*v1.Deployment); ok { if d.Labels["camel.apache.org/component"] == "operator" { - d.Spec.Template.Spec.Containers[0].Image = customImage + d.Spec.Template.Spec.Containers[0].Image = cfg.CustomImage } } - return o } + + if cfg.Global { + if d, ok := o.(*v1.Deployment); ok { + if d.Labels["camel.apache.org/component"] == "operator" { + // Make the operator watch all namespaces + envvar.SetVal(&d.Spec.Template.Spec.Containers[0].Env, "WATCH_NAMESPACE", "") + } + } + + // Turn Role & RoleBinding into their equivalent cluster types + if r, ok := o.(*v1beta1.Role); ok { + if strings.HasPrefix(r.Name, "camel-k-operator") { + o = &v1beta1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: cfg.Namespace, + Name: r.Name, + }, + Rules: r.Rules, + } + } + } + + if rb, ok := o.(*v1beta1.RoleBinding); ok { + if strings.HasPrefix(rb.Name, "camel-k-operator") { + rb.Subjects[0].Namespace = cfg.Namespace + + o = &v1beta1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: cfg.Namespace, + Name: rb.Name, + }, + Subjects: rb.Subjects, + RoleRef: v1beta1.RoleRef{ + APIGroup: rb.RoleRef.APIGroup, + Kind: "ClusterRole", + Name: rb.RoleRef.Name, + }, + } + } + } + } + return o } + isOpenshift, err := openshift.IsOpenShift(c) if err != nil { return err } if isOpenshift { - if err := installOpenshift(ctx, c, namespace, customizer, collection); err != nil { + if err := installOpenshift(ctx, c, cfg.Namespace, customizer, collection); err != nil { return err } } else { - if err := installKubernetes(ctx, c, namespace, customizer, collection); err != nil { + if err := installKubernetes(ctx, c, cfg.Namespace, customizer, collection); err != nil { return err } } @@ -70,7 +122,7 @@ func OperatorOrCollect(ctx context.Context, c client.Client, namespace string, c return err } if isKnative { - return installKnative(ctx, c, namespace, collection) + return installKnative(ctx, c, cfg.Namespace, collection) } return nil } diff --git a/test/testing_env.go b/test/testing_env.go index 91763c69df..0db5b581c0 100644 --- a/test/testing_env.go +++ b/test/testing_env.go @@ -23,13 +23,14 @@ package test import ( "context" - "k8s.io/apimachinery/pkg/labels" "time" + "k8s.io/apimachinery/pkg/labels" + "github.com/apache/camel-k/pkg/client" "github.com/apache/camel-k/pkg/install" appsv1 "k8s.io/api/apps/v1" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" k8sclient "sigs.k8s.io/controller-runtime/pkg/client" @@ -55,7 +56,11 @@ func init() { panic(err) } - err = install.Operator(testContext, testClient, "", getTargetNamespace()) + cfg := install.OperatorConfiguration{ + Namespace: getTargetNamespace(), + } + + err = install.Operator(testContext, testClient, cfg) if err != nil { panic(err) }