Skip to content

Commit

Permalink
Bug fixes for management namespaces (#151)
Browse files Browse the repository at this point in the history
* Changes to user guide

Signed-off-by: Mandana Vaziri <[email protected]>

* Bug fix in management namespace

Signed-off-by: Mandana Vaziri <[email protected]>
  • Loading branch information
vazirim authored Jun 17, 2020
1 parent 74e1842 commit 03815a7
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 102 deletions.
37 changes: 37 additions & 0 deletions docs/user-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,42 @@ mybinding Opaque 6 102s
When a binding and service are created in the same namespace, there is an ownership relationship. So when when the service is deleted, so is the binding. This relationship does not exist if they are not in the same namespace (since Kubernetes disallows it).
In this case, the binding needs to be deleted manually and will not be deleted when the services is deleted.

Bindings can also be created by specifying Roles and ServiceIds. The following example shows a binding yaml with a specific Role:

```yaml
apiVersion: ibmcloud.ibm.com/v1alpha1
kind: Binding
metadata:
name: binding-myes
spec:
serviceName: myes
role: Editor
```

The strings allowed for Roles depend on the service for which credentials are being created. When the role is not specified, the operator lists all the roles for that service types and picks the first one in that list, which defaults to `Manager` for most services.

ServiceIds can be specified by passing a parameter in the binding yaml:

```yaml
apiVersion: ibmcloud.ibm.com/v1alpha1
kind: Binding
metadata:
name: binding-translator
spec:
serviceName: mytranslator
secretName: translator-secret
parameters:
- name: serviceid_crn
value: <crn:v1:bluemix:public:iam-identity::...>
```

The serviceId crn can be obtained with the following command:

```bash
ibmcloud iam service-id <serviceId-name>
```


#### Referencing existing credentials

When many bindings are needed on the same service, it is possible to link to the same set of credentials on the service instance,
Expand Down Expand Up @@ -273,6 +309,7 @@ ibmcloud resource service-key <name-of-credentials>
If the binding is deleted, this does not cause the deletion of the
corresponding credentials.


### Deleting a Binding

To delete a binding with name `mybinding`, run:
Expand Down
181 changes: 79 additions & 102 deletions pkg/controller/service/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/IBM-Cloud/bluemix-go/api/resource/resourcev1/catalog"
"github.com/IBM-Cloud/bluemix-go/api/resource/resourcev1/controller"
bxcontroller "github.com/IBM-Cloud/bluemix-go/api/resource/resourcev1/controller"
"github.com/IBM-Cloud/bluemix-go/api/resource/resourcev1/management"
"github.com/IBM-Cloud/bluemix-go/crn"
bxendpoints "github.com/IBM-Cloud/bluemix-go/endpoints"
"github.com/IBM-Cloud/bluemix-go/models"
Expand Down Expand Up @@ -77,61 +78,75 @@ type IBMCloudInfo struct {
Context icv1.ResourceContext
}

func getBxConfig(r client.Client, instance *ibmcloudv1alpha1.Service) (bx.Config, error) {
c := bx.Config{
EndpointLocator: bxendpoints.NewEndpointLocator("us-south"), // TODO: hard wired to us-south!!
func getConfigOrSecret(r client.Client, instanceNamespace string, objName string, obj runtime.Object) error {
defaultNamespace, isManagement := getDefaultNamespace(r)
if isManagement {
objName = instanceNamespace + "-" + objName
err := r.Get(context.TODO(), types.NamespacedName{Name: objName, Namespace: defaultNamespace}, obj)
if err != nil {
logt.Info("Unable to find secret or config in namespace", objName, defaultNamespace)
return err
}
return nil
}
err := r.Get(context.TODO(), types.NamespacedName{Name: objName, Namespace: instanceNamespace}, obj)
if err != nil {
if strings.Contains(err.Error(), "not found") {
err = r.Get(context.TODO(), types.NamespacedName{Name: objName, Namespace: defaultNamespace}, obj)
if err != nil {
logt.Info("Unable to find secret or config in namespace", objName, defaultNamespace)
return err
}
return nil
}
return err
}
return nil
}

func getDefaultNamespace(r client.Client) (string, bool) {
if controllerNamespace == "" {
controllerNamespace = os.Getenv("CONTROLLER_NAMESPACE")
}
cm := &v1.ConfigMap{}
err := r.Get(context.Background(), types.NamespacedName{Namespace: controllerNamespace, Name: seedInstall}, cm)
if err != nil {
return "default", false
}

// There exists an ico-management configmap in the controller namespace
return cm.Data["namespace"], true
}

func getBxConfig(r client.Client, instance *ibmcloudv1alpha1.Service) (bx.Config, error) {
secretName := seedSecret
secretNameSpace := instance.ObjectMeta.Namespace

secret := &v1.Secret{}
err := r.Get(context.TODO(), types.NamespacedName{Name: secretName, Namespace: secretNameSpace}, secret)

err := getConfigOrSecret(r, secretNameSpace, secretName, secret)
if err != nil {
if strings.Contains(err.Error(), "not found") {
namespace := getDefaultNamespace(r)
if namespace != "default" {
secretName = secretNameSpace + "-" + secretName
}
err = r.Get(context.TODO(), types.NamespacedName{Name: secretName, Namespace: namespace}, secret)
if err != nil {
logt.Info("Unable to get secret in namespace", namespace, err)
return c, err
}
} else {
logt.Info("Unable to get secret", "Error", err)
return c, err
}
logt.Info("Unable to get IBM Cloud Operator secret in namespace", secretNameSpace, err)
return bx.Config{}, err
}

APIKey := string(secret.Data["api-key"])

regionb, ok := secret.Data["region"]
if !ok {
logt.Info("set default region to us-south")
logt.Info("Setting default region to us-south")
regionb = []byte("us-south")
}
region := string(regionb)
c := bx.Config{
EndpointLocator: bxendpoints.NewEndpointLocator(region),
}
c.Region = region
c.BluemixAPIKey = APIKey

return c, nil
}

func getDefaultNamespace(r client.Client) string {
if controllerNamespace == "" {
controllerNamespace = os.Getenv("CONTROLLER_NAMESPACE")
}
cm := &v1.ConfigMap{}
err := r.Get(context.Background(), types.NamespacedName{Namespace: controllerNamespace, Name: seedInstall}, cm)
if err != nil {
return "default"
}

// There exists an ico-management configmap in the controller namespace
return cm.Data["namespace"]
}

func getIBMCloudDefaultContext(r client.Client, instance *ibmcloudv1alpha1.Service) (icv1.ResourceContext, error) {
// If the object already has the context set in its Status, then we don't read from the configmap
if !reflect.DeepEqual(instance.Status.Context, icv1.ResourceContext{}) {
Expand All @@ -142,24 +157,12 @@ func getIBMCloudDefaultContext(r client.Client, instance *ibmcloudv1alpha1.Servi
cmName := seedDefaults
cmNameSpace := instance.ObjectMeta.Namespace

err := r.Get(context.Background(), types.NamespacedName{Namespace: cmNameSpace, Name: cmName}, cm)
err := getConfigOrSecret(r, cmNameSpace, cmName, cm)
if err != nil {
if strings.Contains(err.Error(), "not found") {
namespace := getDefaultNamespace(r)
if namespace != "default" {
cmName = cmNameSpace + "-" + cmName
}
err = r.Get(context.TODO(), types.NamespacedName{Name: cmName, Namespace: namespace}, cm)
if err != nil {
logt.Info("Failed to find ConfigMap in namespace (in Service)", namespace, err)
return icv1.ResourceContext{}, err
}
} else {
logt.Info("Failed to find ConfigMap in namespace (in Service)", cmNameSpace, err)
return icv1.ResourceContext{}, err
}

logt.Info("Unable to get IBM Cloud Operator configmap in namespace", cmNameSpace, err)
return icv1.ResourceContext{}, err
}

ibmCloudContext := getIBMCloudContext(instance, cm)
return ibmCloudContext, nil
}
Expand All @@ -176,6 +179,15 @@ func getIBMCloudContext(instance *ibmcloudv1alpha1.Service, cm *v1.ConfigMap) ic
}
return newContext
}
if instance.Spec.Context.Org == "" {
instance.Spec.Context.Org = cm.Data["org"]
}
if instance.Spec.Context.Space == "" {
instance.Spec.Context.Space = cm.Data["space"]
}
if instance.Spec.Context.Region == "" {
instance.Spec.Context.Region = cm.Data["region"]
}
if instance.Spec.Context.ResourceGroup == "" {
instance.Spec.Context.ResourceGroup = cm.Data["resourcegroup"]
}
Expand All @@ -193,22 +205,10 @@ func getIamToken(r client.Client, instance *ibmcloudv1alpha1.Service) (string, s
secretNameSpace := instance.ObjectMeta.Namespace

secret := &v1.Secret{}
err := r.Get(context.TODO(), types.NamespacedName{Name: secretName, Namespace: secretNameSpace}, secret)
err := getConfigOrSecret(r, secretNameSpace, secretName, secret)
if err != nil {
if strings.Contains(err.Error(), "not found") {
namespace := getDefaultNamespace(r)
if namespace != "default" {
secretName = secretNameSpace + "-" + secretName
}
err = r.Get(context.TODO(), types.NamespacedName{Name: secretName, Namespace: namespace}, secret)
if err != nil {
logt.Info("Unable to get secret in namespace", namespace, err)
return "", "", "", "", err
}
} else {
logt.Info("Unable to get secret", "Error", err)
return "", "", "", "", err
}
logt.Info("Unable to get IBM Cloud Operator IAM token in namespace", secretNameSpace, err)
return "", "", "", "", err
}

return string(secret.Data["access_token"]), string(secret.Data["refresh_token"]), string(secret.Data["uaa_refresh_token"]), string(secret.Data["uaa_token"]), nil
Expand Down Expand Up @@ -391,46 +391,23 @@ func getIBMCloudInfoHelper(r client.Client, config *bx.Config, nctx icv1.Resourc
catalogCRN = supportedDeployments[0].CatalogCRN
}

// managementClient, err := management.New(sess)
// if err != nil {
// return nil, err
// }
// var resourceGroupID string
// resGrpAPI := managementClient.ResourceGroup()
// if useCtx.ResourceGroup == "" {

// resourceGroupQuery := management.ResourceGroupQuery{
// Default: true,
// }

// grpList, err := resGrpAPI.List(&resourceGroupQuery)

// if err != nil {
// return nil, err
// }

// resourceGroupID = grpList[0].ID

// } else {
// grp, err := resGrpAPI.FindByName(nil, useCtx.ResourceGroup)
// if err != nil {
// return nil, err
// }
// resourceGroupID = grp[0].ID
// }

// if useCtx.ResourceLocation == "" {
// useCtx.ResourceLocation = useCtx.Region
// }
// check that the resourceGroup and resourceGroupId match
managementClient, err := management.New(sess)
if err != nil {
return nil, err
}
resGrpAPI := managementClient.ResourceGroup()
resGrp, err := resGrpAPI.Get(useCtx.ResourceGroupID)
if err != nil {
return nil, err
}
if resGrp.Name != useCtx.ResourceGroup {
return nil, fmt.Errorf("ResourceGroup and ResourceGroupID are not consistent: %s, %s", useCtx.ResourceGroup, useCtx.ResourceGroupID)
}

ibmCloudInfo := IBMCloudInfo{
//BXClient: bxclient, // MccpServiceAPI
ResourceClient: controllerClient, // IAMServiceAPI
CatalogClient: catalogClient,
//Account: myAccount, // *Account
//Org: myorg, //*Organization
//Space: myspace,
//Region: regionList,
ResourceClient: controllerClient, // IAMServiceAPI
CatalogClient: catalogClient,
ResourceGroupID: useCtx.ResourceGroupID,
ResourceLocation: useCtx.ResourceLocation,
Session: sess,
Expand Down

0 comments on commit 03815a7

Please sign in to comment.