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

[Operator] Ability to change operator namespace #454

Merged
merged 2 commits into from
Sep 29, 2020
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
3 changes: 2 additions & 1 deletion api-operator/deploy/controller-artifacts/operator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: api-operator
namespace: wso2-system
spec:
replicas: 1
selector:
Expand Down Expand Up @@ -46,3 +45,5 @@ spec:
fieldPath: metadata.name
- name: OPERATOR_NAME
value: "api-operator"
- name: ARTIFACTS_NAMESPACE
value: "wso2-system"
1 change: 0 additions & 1 deletion api-operator/deploy/controller-artifacts/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ kind: ClusterRole
metadata:
creationTimestamp: null
name: api-operator
namespace: wso2-system
rules:
- apiGroups:
- ""
Expand Down
1 change: 0 additions & 1 deletion api-operator/deploy/controller-artifacts/role_binding.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: api-operator
namespace: wso2-system
subjects:
- kind: ServiceAccount
name: api-operator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,3 @@ apiVersion: v1
kind: ServiceAccount
metadata:
name: api-operator
namespace: wso2-system
9 changes: 0 additions & 9 deletions api-operator/deploy/controller-configs/controller_conf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: controller-config
namespace: wso2-system
data:
#mgw toolkit image to initialize/setup the micro gw project
mgwToolkitImg: wso2am/wso2micro-gw-toolkit:3.2.0
Expand Down Expand Up @@ -63,7 +62,6 @@ apiVersion: v1
kind: Secret
metadata:
name: apim-secret
namespace: wso2-system
type: Opaque
data:
#Base64 encoded username and password for APIM
Expand All @@ -75,7 +73,6 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: apim-config
namespace: wso2-system
data:
#By default hostname verification is disabled. In a production scenario, this has to be enabled.
verifyHostname: "false"
Expand Down Expand Up @@ -155,7 +152,6 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: hpa-configs
namespace: wso2-system
data:
# Horizontal Pod Auto-Scaling for Micro-Gateways
# Maximum number of replicas for the Horizontal Pod Auto-scale. Default-> maxReplicas: "5"
Expand Down Expand Up @@ -221,7 +217,6 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: ingress-configs
namespace: wso2-system
data:
ingress.properties: |
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
Expand All @@ -244,7 +239,6 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: kaniko-arguments
namespace: wso2-system
data:
kanikoArguments: |
#kaniko additional flags should go here: Please refer https://github.com/GoogleContainerTools/kaniko#additional-flags
Expand All @@ -254,7 +248,6 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: route-configs
namespace: wso2-system
data:
route.properties: |
openshift.io/host.generated: false
Expand All @@ -271,7 +264,6 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: istio-configs
namespace: wso2-system
data:
#Gateway name
gatewayName: "wso2-gateway"
Expand Down Expand Up @@ -304,7 +296,6 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: mgw-deployment-configs
namespace: wso2-system
data:
mgwConfigMaps: |
# Config Maps to be added to mgw deployment. This is an example
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ apiVersion: wso2.com/v1alpha1
kind: Security
metadata:
name: default-security-jwt
namespace: wso2-system
spec:
type: JWT
securityConfig:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: docker-registry-config
namespace: wso2-system
data:
#docker registry type which the mgw image to be pushed. supported types: DOCKER_HUB, AMAZON_ECR, GCR, HTTP. Default-> registryType: DOCKER_HUB
registryType: DOCKER_HUB
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: dockerfile-template
namespace: wso2-system
data:
dockerFile.gotmpl: |

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: mgw-conf-mustache
namespace: wso2-system
data:
mgwConf.gotmpl: |

Expand Down
18 changes: 11 additions & 7 deletions api-operator/pkg/analytics/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ const (
portConst = "port"
)

func Handle(client *client.Client, userNamespace string) error {
func Handle(client *client.Client, userNamespace string, artifactsNamespace string) error {
analyticsConf := k8s.NewConfMap()
errConf := k8s.Get(client, types.NamespacedName{Namespace: wso2NameSpaceConst, Name: analyticsConfName}, analyticsConf)
errConf := k8s.Get(client, types.NamespacedName{Namespace: artifactsNamespace, Name: analyticsConfName}, analyticsConf)
if errConf != nil {
logger.Info("Disabling analytics since the analytics configuration related config map not found")
mgw.Configs.AnalyticsEnabled = false
Expand All @@ -61,20 +61,24 @@ func Handle(client *client.Client, userNamespace string) error {
// gets the data from analytics secret
analyticsSecret := k8s.NewSecret()
errSecret := k8s.Get(client, types.NamespacedName{
Namespace: wso2NameSpaceConst,
Namespace: artifactsNamespace,
Name: analyticsConf.Data[analyticsSecretConst],
}, analyticsSecret)

if errSecret == nil && isValidSecret(analyticsSecret) {
analyticsCertSecretName := string(analyticsSecret.Data[certConst])
analyticsCertSecret := k8s.NewSecret()
// checks if the certificate exists in the namespace of the API
errCertNs := k8s.Get(client, types.NamespacedName{Name: analyticsCertSecretName, Namespace: userNamespace}, analyticsCertSecret)
errCertNs := k8s.Get(client,
types.NamespacedName{Name: analyticsCertSecretName, Namespace: userNamespace}, analyticsCertSecret)
if errCertNs != nil {
logger.Info("Analytics certificate is not found in the user namespace. Finding it in system namespace", "user_namespace", userNamespace, "system_namespace", wso2NameSpaceConst)
errCopyCert := k8s.Get(client, types.NamespacedName{Name: analyticsCertSecretName, Namespace: wso2NameSpaceConst}, analyticsCertSecret)
logger.Info("Analytics certificate is not found in the user namespace. Finding it in system namespace",
"user_namespace", userNamespace, "system_namespace", artifactsNamespace)
errCopyCert := k8s.Get(client,
types.NamespacedName{Name: analyticsCertSecretName, Namespace: artifactsNamespace}, analyticsCertSecret)
if errCopyCert != nil {
logger.Error(errCopyCert, "Error getting analytics certificate in the system namespace", "system_namespace", wso2NameSpaceConst)
logger.Error(errCopyCert, "Error getting analytics certificate in the system namespace",
"system_namespace", artifactsNamespace)
return errCopyCert
}
// copy to user namespace
Expand Down
71 changes: 51 additions & 20 deletions api-operator/pkg/controller/api/api_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package api
import (
"context"
"fmt"
"github.com/operator-framework/operator-sdk/pkg/k8sutil"
"github.com/wso2/k8s-api-operator/api-operator/pkg/analytics"
wso2v1alpha1 "github.com/wso2/k8s-api-operator/api-operator/pkg/apis/wso2/v1alpha1"
"github.com/wso2/k8s-api-operator/api-operator/pkg/endpoints"
Expand Down Expand Up @@ -128,6 +129,32 @@ func (r *ReconcileAPI) Reconcile(request reconcile.Request) (reconcile.Result, e
kaniko.InitJobVolumes()
mgw.InitContainers()

operatorNs, opErr := k8sutil.GetOperatorNamespace()
if opErr != nil {
reqLogger.Error(opErr, "Cannot get the operator namespace")
operatorNs = wso2NameSpaceConst
} else {
reqLogger.Info("Operator deployement namespace","current", operatorNs, "default", wso2NameSpaceConst)
}

depFound := &appsv1.Deployment{}
errDeploy := k8s.Get(&r.client, types.NamespacedName{Name: "api-operator", Namespace: operatorNs}, depFound)
if errDeploy != nil {
reqLogger.Error(errDeploy, "Cannot find the operator deployment!")
}
var artifactNs string
envs := []corev1.EnvVar{}
envs = depFound.Spec.Template.Spec.Containers[0].Env
for i := 0; i < len(envs); i++ {
if envs[i].Name == artifactNamespaceConst {
artifactNs = envs[i].Value
break
}
}
if artifactNs != "" {
reqLogger.Info("Namespace of artifacts in env", artifactNamespaceConst, artifactNs)
}

var apiVersion string // API version - for the tag of final MGW docker image

apiBasePathMap := make(map[string]string) // API base paths with versions
Expand Down Expand Up @@ -155,25 +182,25 @@ func (r *ReconcileAPI) Reconcile(request reconcile.Request) (reconcile.Result, e
operatorOwner, ownerErr := getOperatorOwner(&r.client)
if ownerErr != nil {
reqLogger.Info("Operator was not found. No owner will be set for the artifacts",
"operator_namespace", wso2NameSpaceConst)
"operator_namespace", operatorNs)
}
userNamespace := instance.Namespace

//get configurations file for the controller
controlConf := k8s.NewConfMap()
errConf := k8s.Get(&r.client, types.NamespacedName{Namespace: wso2NameSpaceConst, Name: controllerConfName},
errConf := k8s.Get(&r.client, types.NamespacedName{Namespace: artifactNs, Name: controllerConfName},
controlConf)
//get docker registry configs
dockerRegistryConf := k8s.NewConfMap()
errRegConf := k8s.Get(&r.client, types.NamespacedName{Namespace: wso2NameSpaceConst, Name: dockerRegConfigs},
errRegConf := k8s.Get(&r.client, types.NamespacedName{Namespace: artifactNs, Name: dockerRegConfigs},
dockerRegistryConf)
//get ingress configs
ingressConf := k8s.NewConfMap()
errIngressConf := k8s.Get(&r.client, types.NamespacedName{Namespace: wso2NameSpaceConst, Name: ingressConfigs},
errIngressConf := k8s.Get(&r.client, types.NamespacedName{Namespace: artifactNs, Name: ingressConfigs},
ingressConf)
//get openshift configs
OpenshiftConf := k8s.NewConfMap()
errOpenshiftConf := k8s.Get(&r.client, types.NamespacedName{Namespace: wso2NameSpaceConst, Name: openShiftConfigs},
errOpenshiftConf := k8s.Get(&r.client, types.NamespacedName{Namespace: artifactNs, Name: openShiftConfigs},
OpenshiftConf)
confErrs := []error{errConf, errRegConf, errIngressConf, errOpenshiftConf}
for _, err := range confErrs {
Expand Down Expand Up @@ -226,7 +253,7 @@ func (r *ReconcileAPI) Reconcile(request reconcile.Request) (reconcile.Result, e
// this is to verify HPA configs prior running kaniko job and creating MGW image
// otherwise user may have to wait long time to know the error in configs
mgw.Configs.ObservabilityEnabled = strings.EqualFold(controlConfigData[observabilityEnabledConfigKey], "true")
if err := mgw.ValidateHpaConfigs(&r.client); err != nil {
if err := mgw.ValidateHpaConfigs(&r.client, artifactNs); err != nil {
reqLogger.Error(err, "Invalid HPA configs. Requeue request after 10 seconds")
// Return and requeue request since config mismatch. User should reconfigure configs to proceed.
return reconcile.Result{RequeueAfter: 10 * time.Second}, nil
Expand All @@ -236,7 +263,7 @@ func (r *ReconcileAPI) Reconcile(request reconcile.Request) (reconcile.Result, e
var istioConfigs *mgw.IstioConfigs
if strings.EqualFold(operatorMode, istioMode) {
// validate Istio configs and setting configs
istioConfigs, err = mgw.ValidateIstioConfigs(&r.client, instance)
istioConfigs, err = mgw.ValidateIstioConfigs(&r.client, instance, artifactNs)
if err != nil {
reqLogger.Error(err, "Invalid Istio configs. Requeue request after 10 seconds")
// Return and requeue request since config mismatch. User should reconfigure configs to proceed.
Expand Down Expand Up @@ -369,7 +396,7 @@ func (r *ReconcileAPI) Reconcile(request reconcile.Request) (reconcile.Result, e
if !isDefinedSecurity && resourceLevelSec == 0 {
reqLogger.Info("Use default security")

defaultJwtConfArray, err := security.Default(&r.client, userNamespace, ownerRef)
defaultJwtConfArray, err := security.Default(&r.client, userNamespace, ownerRef, artifactNs)
mgw.Configs.JwtConfigs = defaultJwtConfArray
if err != nil {
return reconcile.Result{}, err
Expand All @@ -393,7 +420,7 @@ func (r *ReconcileAPI) Reconcile(request reconcile.Request) (reconcile.Result, e
mgwDockerImage.Tag = mgwDockerImage.Tag + "-" + instance.Spec.UpdateTimeStamp
}

errReg := registry.SetRegistry(&r.client, userNamespace, mgwDockerImage)
errReg := registry.SetRegistry(&r.client, userNamespace, mgwDockerImage, artifactNs)
if errReg != nil {
reqLogger.Error(errReg, "Error setting docker registry", "docker_image", mgwDockerImage)
return reconcile.Result{}, errReg
Expand All @@ -406,7 +433,7 @@ func (r *ReconcileAPI) Reconcile(request reconcile.Request) (reconcile.Result, e
"Skipping kaniko job. Image specified in API CRD.")
} else {
// check if the image already exists
imageExist, errImage := registry.IsImageExist(&r.client)
imageExist, errImage := registry.IsImageExist(&r.client, artifactNs)
if errImage != nil {
reqLogger.Info("Error finding the MGW image in registry. Continue with creating Kaniko job",
"mgw_docker_image", mgwDockerImage)
Expand All @@ -422,7 +449,7 @@ func (r *ReconcileAPI) Reconcile(request reconcile.Request) (reconcile.Result, e
"Handling analytics & interceptors, rendering dockerfile & mgw configs, and creating the Kaniko job.")
// handling analytics
reqLogger.Info("Handling analytics")
if err := analytics.Handle(&r.client, userNamespace); err != nil {
if err := analytics.Handle(&r.client, userNamespace, artifactNs); err != nil {
reqLogger.Error(err, "Error handling analytics")
r.recorder.Event(instance, eventTypeError, "Configs", "Error while handling analytics.")
return reconcile.Result{}, err
Expand All @@ -438,7 +465,7 @@ func (r *ReconcileAPI) Reconcile(request reconcile.Request) (reconcile.Result, e

// handling Kaniko docker file
reqLogger.Info("Rendering the dockerfile for Kaniko job and adding volumes to the Kaniko job")
if err := kaniko.HandleDockerFile(&r.client, userNamespace, instance.Name, ownerRef); err != nil {
if err := kaniko.HandleDockerFile(&r.client, userNamespace, instance.Name, ownerRef, artifactNs); err != nil {
reqLogger.Error(err, "Error rendering the docker file for Kaniko job and adding volumes to the Kaniko job")
r.recorder.Event(instance, eventTypeError, "KanikoJob",
"Error rendering the dockerfile for kaniko job.")
Expand All @@ -447,20 +474,20 @@ func (r *ReconcileAPI) Reconcile(request reconcile.Request) (reconcile.Result, e

// setting the MGW configs from APIM configmap
reqLogger.Info("Setting the MGW configs from APIM configmap")
if err := mgw.SetApimConfigs(&r.client); err != nil {
if err := mgw.SetApimConfigs(&r.client, artifactNs); err != nil {
reqLogger.Error(err, "Error Setting the MGW configs from APIM configmap")
return reconcile.Result{}, err
}

// rendering MGW config file
reqLogger.Info("Rendering and adding the MGW configuration file to cluster")
if err := mgw.ApplyConfFile(&r.client, userNamespace, instance.Name, ownerRef); err != nil {
if err := mgw.ApplyConfFile(&r.client, userNamespace, instance.Name, ownerRef, artifactNs); err != nil {
reqLogger.Error(err, "Error rendering and adding the MGW configuration file to cluster")
return reconcile.Result{}, err
}

kanikoArgs := k8s.NewConfMap()
err = k8s.Get(&r.client, types.NamespacedName{Namespace: wso2NameSpaceConst, Name: kanikoArgsConfigs}, kanikoArgs)
err = k8s.Get(&r.client, types.NamespacedName{Namespace: artifactNs, Name: kanikoArgsConfigs}, kanikoArgs)
if err != nil && errors.IsNotFound(err) {
reqLogger.Info("No kaniko-arguments config map is available in wso2-system namespace")
}
Expand Down Expand Up @@ -525,7 +552,7 @@ func (r *ReconcileAPI) Reconcile(request reconcile.Request) (reconcile.Result, e
if deployMgwRuntime {
reqLogger.Info("Deploying MGW runtime image")
// create MGW deployment in k8s cluster
mgwDeployment, errDeploy := mgw.Deployment(&r.client, instance, controlConfigData, ownerRef)
mgwDeployment, errDeploy := mgw.Deployment(&r.client, instance, controlConfigData, ownerRef, artifactNs)
r.recorder.Event(instance, corev1.EventTypeNormal, "MGWRuntime",
fmt.Sprintf("Deploying MGW runtime: %s.", mgwDeployment.Name))
if errDeploy != nil {
Expand Down Expand Up @@ -555,7 +582,7 @@ func (r *ReconcileAPI) Reconcile(request reconcile.Request) (reconcile.Result, e
}

// create horizontal pod auto-scalar
hpaV2beta1, hpaV2beta2 := mgw.HPA(&r.client, instance, mgwDeployment, ownerRef)
hpaV2beta1, hpaV2beta2 := mgw.HPA(&r.client, instance, mgwDeployment, ownerRef, artifactNs)
if hpaV2beta1 != nil && hpaV2beta2 == nil {
if errHpaV2beta1 := k8s.CreateIfNotExists(&r.client, hpaV2beta1); errHpaV2beta1 != nil {
reqLogger.Error(errHpaV2beta1, "Error creating the horizontal pod auto-scalar with HPA version v2beta1", "hpa_name", hpaV2beta1.Name)
Expand All @@ -571,7 +598,7 @@ func (r *ReconcileAPI) Reconcile(request reconcile.Request) (reconcile.Result, e

reqLogger.Info("Operator mode", "mode", operatorMode)
if strings.EqualFold(operatorMode, ingressMode) || instance.Spec.IngressHostname != "" {
errIng := mgw.ApplyIngressResource(&r.client, instance, apiBasePathMap, ownerRef)
errIng := mgw.ApplyIngressResource(&r.client, instance, apiBasePathMap, ownerRef, artifactNs)
r.recorder.Event(instance, corev1.EventTypeNormal, "Ingress", "Applying Ingress resources.")
if errIng != nil {
reqLogger.Error(errIng, "Error creating the ingress resource")
Expand All @@ -580,7 +607,7 @@ func (r *ReconcileAPI) Reconcile(request reconcile.Request) (reconcile.Result, e
}
}
if strings.EqualFold(operatorMode, routeMode) {
rutErr := mgw.ApplyRouteResource(&r.client, instance, apiBasePathMap, ownerRef)
rutErr := mgw.ApplyRouteResource(&r.client, instance, apiBasePathMap, ownerRef, artifactNs)
r.recorder.Event(instance, corev1.EventTypeNormal, "Route", "Applying Route resources.")
if rutErr != nil {
r.recorder.Event(instance, eventTypeError, "Route", "Error creating Route resources.")
Expand Down Expand Up @@ -676,7 +703,11 @@ func setApiDependent(client *client.Client, api *wso2v1alpha1.API, ownerRef *[]m
// getOperatorOwner returns the owner reference of the operator
func getOperatorOwner(client *client.Client) (*[]metav1.OwnerReference, error) {
depFound := &appsv1.Deployment{}
errDeploy := k8s.Get(client, types.NamespacedName{Name: "api_operator", Namespace: wso2NameSpaceConst}, depFound)
operatorNs, errNs := k8sutil.GetOperatorNamespace()
if errNs != nil {
operatorNs = wso2NameSpaceConst
}
errDeploy := k8s.Get(client, types.NamespacedName{Name: "api-operator", Namespace: operatorNs}, depFound)
if errDeploy != nil {
var noOwner []metav1.OwnerReference
return &noOwner, errDeploy
Expand Down
Loading