diff options
Diffstat (limited to 'src/dcm/pkg/module/apply.go')
-rw-r--r-- | src/dcm/pkg/module/apply.go | 172 |
1 files changed, 94 insertions, 78 deletions
diff --git a/src/dcm/pkg/module/apply.go b/src/dcm/pkg/module/apply.go index b5ef61c2..3770457a 100644 --- a/src/dcm/pkg/module/apply.go +++ b/src/dcm/pkg/module/apply.go @@ -84,33 +84,36 @@ type RoleRef struct { ApiGroup string `yaml:"apiGroup"` } -func createNamespace(logicalcloud LogicalCloud) (string, error) { +func createNamespace(logicalcloud LogicalCloud) (string, string, error) { + + name := logicalcloud.Specification.NameSpace namespace := Resource{ ApiVersion: "v1", Kind: "Namespace", MetaData: MetaDatas{ - Name: logicalcloud.Specification.NameSpace, + Name: name, }, } nsData, err := yaml.Marshal(&namespace) if err != nil { - return "", err + return "", "", err } - return string(nsData), nil + return string(nsData), strings.Join([]string{name, "+Namespace"}, ""), nil } -func createRole(logicalcloud LogicalCloud) (string, error) { +func createRole(logicalcloud LogicalCloud) (string, string, error) { userPermissions := logicalcloud.Specification.User.UserPermissions[0] + name := strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "-role"}, "") role := Resource{ ApiVersion: "rbac.authorization.k8s.io/v1beta1", Kind: "Role", MetaData: MetaDatas{ - Name: strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "-role"}, ""), + Name: name, Namespace: logicalcloud.Specification.NameSpace, }, Rules: []RoleRules{RoleRules{ @@ -123,19 +126,21 @@ func createRole(logicalcloud LogicalCloud) (string, error) { roleData, err := yaml.Marshal(&role) if err != nil { - return "", err + return "", "", err } - return string(roleData), nil + return string(roleData), strings.Join([]string{name, "+Role"}, ""), nil } -func createRoleBinding(logicalcloud LogicalCloud) (string, error) { +func createRoleBinding(logicalcloud LogicalCloud) (string, string, error) { + + name := strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "-roleBinding"}, "") roleBinding := Resource{ ApiVersion: "rbac.authorization.k8s.io/v1beta1", Kind: "RoleBinding", MetaData: MetaDatas{ - Name: strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "-roleBinding"}, ""), + Name: name, Namespace: logicalcloud.Specification.NameSpace, }, Subjects: []RoleSubjects{RoleSubjects{ @@ -154,19 +159,22 @@ func createRoleBinding(logicalcloud LogicalCloud) (string, error) { rBData, err := yaml.Marshal(&roleBinding) if err != nil { - return "", err + return "", "", err } - return string(rBData), nil + return string(rBData), strings.Join([]string{name, "+RoleBinding"}, ""), nil } -func createQuota(quota []Quota, namespace string) (string, error) { +func createQuota(quota []Quota, namespace string) (string, string, error) { + lcQuota := quota[0] + name := lcQuota.MetaData.QuotaName + q := Resource{ ApiVersion: "v1", Kind: "ResourceQuota", MetaData: MetaDatas{ - Name: lcQuota.MetaData.QuotaName, + Name: name, Namespace: namespace, }, Specification: Specs{ @@ -176,26 +184,28 @@ func createQuota(quota []Quota, namespace string) (string, error) { qData, err := yaml.Marshal(&q) if err != nil { - return "", err + return "", "", err } - return string(qData), nil + return string(qData), strings.Join([]string{name, "+ResourceQuota"}, ""), nil } -func createUserCSR(logicalcloud LogicalCloud) (string, string, error) { +func createUserCSR(logicalcloud LogicalCloud) (string, string, string, error) { + KEYSIZE := 4096 userName := logicalcloud.Specification.User.UserName + name := strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "-user-csr"}, "") key, err := rsa.GenerateKey(rand.Reader, KEYSIZE) if err != nil { - return "", "", err + return "", "", "", err } csrTemplate := x509.CertificateRequest{Subject: pkix.Name{CommonName: userName}} csrCert, err := x509.CreateCertificateRequest(rand.Reader, &csrTemplate, key) if err != nil { - return "", "", err + return "", "", "", err } //Encode csr @@ -208,8 +218,7 @@ func createUserCSR(logicalcloud LogicalCloud) (string, string, error) { ApiVersion: "certificates.k8s.io/v1beta1", Kind: "CertificateSigningRequest", MetaData: MetaDatas{ - Name: strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "-user-csr"}, ""), - // Namespace: logicalcloud.Specification.NameSpace, + Name: name, }, Specification: Specs{ Request: base64.StdEncoding.EncodeToString(csr), @@ -219,7 +228,7 @@ func createUserCSR(logicalcloud LogicalCloud) (string, string, error) { csrData, err := yaml.Marshal(&csrObj) if err != nil { - return "", "", err + return "", "", "", err } keyData := base64.StdEncoding.EncodeToString(pem.EncodeToMemory( @@ -229,10 +238,10 @@ func createUserCSR(logicalcloud LogicalCloud) (string, string, error) { }, )) if err != nil { - return "", "", err + return "", "", "", err } - return string(csrData), string(keyData), nil + return string(csrData), string(keyData), strings.Join([]string{name, "+CertificateSigningRequest"}, ""), nil } func createApprovalSubresource(logicalcloud LogicalCloud) (string, error) { @@ -313,49 +322,74 @@ func Apply(project string, logicalcloud LogicalCloud, clusterList []Cluster, APP := "logical-cloud" logicalCloudName := logicalcloud.MetaData.LogicalCloudName - //Resource Names - namespaceName := strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "+namespace"}, "") - roleName := strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "+role"}, "") - roleBindingName := strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "+roleBinding"}, "") - quotaName := strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "+quota"}, "") - csrName := strings.Join([]string{logicalcloud.MetaData.LogicalCloudName, "+CertificateSigningRequest"}, "") + lcclient := NewLogicalCloudClient() + lckey := LogicalCloudKey{ + LogicalCloudName: logicalcloud.MetaData.LogicalCloudName, + Project: project, + } + + // Check if there was a previous context for this logical cloud + ac, cid, err := lcclient.GetLogicalCloudContext(project, logicalCloudName) + if cid != "" { + // Make sure rsync status for this logical cloud is Terminated, + // otherwise we can't re-apply logical cloud yet + acStatus, _ := getAppContextStatus(ac) + switch acStatus.Status { + case appcontext.AppContextStatusEnum.Terminated: + // We now know Logical Cloud has terminated, so let's update the entry before we process the apply + err = db.DBconn.RemoveTag(lcclient.storeName, lckey, lcclient.tagContext) + if err != nil { + return pkgerrors.Wrap(err, "Error removing lccontext tag from Logical Cloud") + } + // And fully delete the old AppContext + err := ac.DeleteCompositeApp() + if err != nil { + return pkgerrors.Wrap(err, "Error deleting AppContext CompositeApp Logical Cloud") + } + case appcontext.AppContextStatusEnum.Terminating: + return pkgerrors.New("The Logical Cloud can't be re-applied yet, it is being terminated.") + case appcontext.AppContextStatusEnum.Instantiated: + return pkgerrors.New("The Logical Cloud is already applied.") + default: + return pkgerrors.New("The Logical Cloud can't be applied at this point.") + } + } // Get resources to be added - namespace, err := createNamespace(logicalcloud) + namespace, namespaceName, err := createNamespace(logicalcloud) if err != nil { return pkgerrors.Wrap(err, "Error Creating Namespace YAML for logical cloud") } - role, err := createRole(logicalcloud) + role, roleName, err := createRole(logicalcloud) if err != nil { return pkgerrors.Wrap(err, "Error Creating Role YAML for logical cloud") } - roleBinding, err := createRoleBinding(logicalcloud) + roleBinding, roleBindingName, err := createRoleBinding(logicalcloud) if err != nil { return pkgerrors.Wrap(err, "Error Creating RoleBinding YAML for logical cloud") } - quota, err := createQuota(quotaList, logicalcloud.Specification.NameSpace) + quota, quotaName, err := createQuota(quotaList, logicalcloud.Specification.NameSpace) if err != nil { return pkgerrors.Wrap(err, "Error Creating Quota YAML for logical cloud") } - csr, key, err := createUserCSR(logicalcloud) + csr, key, csrName, err := createUserCSR(logicalcloud) if err != nil { return pkgerrors.Wrap(err, "Error Creating User CSR and Key for logical cloud") } approval, err := createApprovalSubresource(logicalcloud) + // From this point on, we are dealing with a new context (not "ac" from above) context := appcontext.AppContext{} ctxVal, err := context.InitAppContext() if err != nil { return pkgerrors.Wrap(err, "Error creating AppContext") } - fmt.Printf("%v\n", ctxVal) - handle, err := context.CreateCompositeApp() if err != nil { return pkgerrors.Wrap(err, "Error creating AppContext CompositeApp") @@ -432,10 +466,6 @@ func Apply(project string, logicalcloud LogicalCloud, clusterList []Cluster, } // Add private key to MongoDB - lckey := LogicalCloudKey{ - LogicalCloudName: logicalcloud.MetaData.LogicalCloudName, - Project: project, - } err = db.DBconn.Insert("orchestrator", lckey, nil, "privatekey", key) if err != nil { cleanuperr := context.DeleteCompositeApp() @@ -573,10 +603,6 @@ func Apply(project string, logicalcloud LogicalCloud, clusterList []Cluster, _, err = context.AddInstruction(handle, "app", "dependency", string(appDependency)) } // save the context in the logicalcloud db record - lckey := LogicalCloudKey{ - LogicalCloudName: logicalcloud.MetaData.LogicalCloudName, - Project: project, - } err = db.DBconn.Insert("orchestrator", lckey, nil, "lccontext", ctxVal) if err != nil { cleanuperr := context.DeleteCompositeApp() @@ -605,40 +631,30 @@ func Terminate(project string, logicalcloud LogicalCloud, clusterList []Cluster, logicalCloudName := logicalcloud.MetaData.LogicalCloudName - _, ctxVal, err := NewLogicalCloudClient().GetLogicalCloudContext(project, logicalCloudName) - if err != nil { - return pkgerrors.Wrapf(err, "Error finding AppContext for Logical Cloud: %v", logicalCloudName) - } + lcclient := NewLogicalCloudClient() - // call resource synchronizer to delete the CRs from every cluster of the logical cloud - err = callRsyncUninstall(ctxVal) + ac, cid, err := lcclient.GetLogicalCloudContext(project, logicalCloudName) if err != nil { - return err + return pkgerrors.Wrapf(err, "Logical Cloud doesn't seem applied: %v", logicalCloudName) + } + + // Check if there was a previous context for this logical cloud + if cid != "" { + // Make sure rsync status for this logical cloud is Terminated, + // otherwise we can't re-apply logical cloud yet + acStatus, _ := getAppContextStatus(ac) + switch acStatus.Status { + case appcontext.AppContextStatusEnum.Terminated: + return pkgerrors.New("The Logical Cloud has already been terminated: " + logicalCloudName) + case appcontext.AppContextStatusEnum.Terminating: + return pkgerrors.New("The Logical Cloud is already being terminated: " + logicalCloudName) + case appcontext.AppContextStatusEnum.Instantiated: + // call resource synchronizer to delete the CRs from every cluster of the logical cloud + err = callRsyncUninstall(cid) + return err + default: + return pkgerrors.New("The Logical Cloud can't be deleted at this point: " + logicalCloudName) + } } - - // TODO: status handling for logical cloud after terminate: - // rsync updates the status of the appcontext to Terminated - // dcm should launch thread to observe status of appcontext before concluding logical cloud is terminated - // dcm should somewhat mimic the status tracking of rsync - // logical cloud might be in a non-applied non-terminated state for a long period of time......... - - // // remove the app context - // err = context.DeleteCompositeApp() - // if err != nil { - // return pkgerrors.Wrap(err, "Error deleting AppContext CompositeApp") - // } - - // remove the app context field from the cluster db record - // lckey := LogicalCloudKey{ - // LogicalCloudName: logicalcloud.MetaData.LogicalCloudName, - // Project: project, - // } - // err = db.DBconn.RemoveTag("orchestrator", lckey, "lccontext") - // if err != nil { - // log.Warn("Error removing AppContext from Logical Cloud", log.Fields{ - // "logical-cloud": logicalCloudName, - // }) - // } - - return nil + return pkgerrors.New("Logical Cloud is not applied: " + logicalCloudName) } |