diff --git a/compcheck/comp_check.go b/compcheck/comp_check.go index 5e4271811..ae0213ba3 100644 --- a/compcheck/comp_check.go +++ b/compcheck/comp_check.go @@ -361,6 +361,14 @@ func deployCompatible(getDeviceHandler exchange.DeviceHandler, if !privOutput.Compatible { return createCompCheckOutput(pcOutput, privOutput, nil, nil, checkAllSvcs, msgPrinter), nil } + + privOutput, err = patternClusterNSCompatible(serviceDefResolverHandler, getPatterns, ccInput, privOutput.Input, true, msgPrinter) + if err != nil { + return nil, err + } + if !privOutput.Compatible { + return createCompCheckOutput(pcOutput, privOutput, nil, nil, checkAllSvcs, msgPrinter), nil + } } // check user input for those services that are compatible @@ -902,7 +910,11 @@ func CheckClusterNamespaceCompatibility(nodeType string, nodeNamespace string, n // the case where the namespace in the deployment policy or pattern is not defined. if !nodeIsNamespaceScoped { - return true, svcNamespace, "" + if svcNamespace != "" { + return true, svcNamespace, "" + } else { + return true, nodeNamespace, "" + } } else { if svcNamespace == "" || nodeNamespace == svcNamespace { return true, nodeNamespace, "" @@ -912,6 +924,66 @@ func CheckClusterNamespaceCompatibility(nodeType string, nodeNamespace string, n } } +// getDeviceHandler, getBusinessPolicies, getPatterns, true, msgPrinter +func patternClusterNSCompatible(serviceDefResolverHandler exchange.ServiceDefResolverHandler, + getPatterns exchange.PatternHandler, + ccInput *CompCheck, ccResource *CompCheckResource, + inspectOperator bool, msgPrinter *message.Printer) (*CompCheckOutput, error) { + + // get default message printer if nil + if msgPrinter == nil { + msgPrinter = i18n.GetMessagePrinter() + } + + patternDef, err := processPattern(getPatterns, ccInput.PatternId, ccInput.Pattern, msgPrinter) + if err != nil { + return nil, err + } + + patternClusterNS := patternDef.GetClusterNamespace() + if ccInput.NodeType == persistence.DEVICE_TYPE_DEVICE { + return NewCompCheckOutput(true, nil, nil), nil + } + + compatible := true + reason := "" + if !ccInput.NodeNamespaceScoped { + var clusterDeployment interface{} + // for cluster scoped agent, no need to check embedded svc namespace + compatible, _, reason = CheckClusterNamespaceCompatibility(ccInput.NodeType, ccInput.NodeClusterNS, ccInput.NodeNamespaceScoped, patternClusterNS, clusterDeployment, ccInput.PatternId, false, msgPrinter) + if !compatible { + return NewCompCheckOutput(false, map[string]string{ccInput.PatternId: fmt.Sprintf("Cluster namespace %v in this pattern is incompatible: %v", patternClusterNS, reason)}, nil), nil + } else { + return NewCompCheckOutput(compatible, nil, ccResource), nil + } + } + + // check cluster namespace compatibility for namespace scoped agent + messages := map[string]string{} + for _, svcRef := range getWorkloadsFromPattern(patternDef, ccResource.NodeArch) { + for _, workload := range svcRef.ServiceVersions { + topSvc, topId, _, _ := GetServiceAndDeps(svcRef.ServiceURL, svcRef.ServiceOrg, workload.Version, svcRef.ServiceArch, ccInput.Service, + ccResource.DepServices, serviceDefResolverHandler, msgPrinter) + + if err != nil { + return nil, err + } + + compatible, _, reason = CheckClusterNamespaceCompatibility(ccInput.NodeType, ccInput.NodeClusterNS, ccInput.NodeNamespaceScoped, patternClusterNS, topSvc.GetClusterDeployment(), ccInput.PatternId, true, msgPrinter) + if !compatible { + messages[topId] = fmt.Sprintf("Cluster namespace is incompatible, reason: %v", reason) + } + } + } + if len(messages) == 0 { + // no incompatible entry + return NewCompCheckOutput(true, nil, ccResource), nil + } + + return NewCompCheckOutput(false, messages, ccResource), nil + +} + // Get the dependent services for the given service. // It goes to the dependentServices to find a dependent first. If not found // it will go to the exchange to get the dependents.