Ejemplo n.º 1
1
func installTemplates(kc *k8sclient.Client, c *oclient.Client, fac *cmdutil.Factory, v string, templateUrl string, dockerRegistry string, arch string, domain string) error {
	ns, _, err := fac.DefaultNamespace()
	if err != nil {
		util.Fatal("No default namespace")
		return err
	}
	templates := c.Templates(ns)

	uri := fmt.Sprintf(templateUrl, v)
	util.Infof("Downloading apps from: %v\n", uri)
	resp, err := http.Get(uri)
	if err != nil {
		util.Fatalf("Cannot get fabric8 template to deploy: %v", err)
	}
	defer resp.Body.Close()

	tmpFileName := path.Join(os.TempDir(), "fabric8-template-distros.tar.gz")
	t, err := os.OpenFile(tmpFileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
	if err != nil {
		return err
	}
	defer t.Close()

	_, err = io.Copy(t, resp.Body)
	if err != nil {
		return err
	}

	r, err := zip.OpenReader(tmpFileName)
	if err != nil {
		return err
	}
	defer r.Close()

	typeOfMaster := util.TypeOfMaster(kc)

	for _, f := range r.File {
		mode := f.FileHeader.Mode()
		if mode.IsDir() {
			continue
		}

		rc, err := f.Open()
		if err != nil {
			return err
		}
		defer rc.Close()

		jsonData, err := ioutil.ReadAll(rc)
		if err != nil {
			util.Fatalf("Cannot get fabric8 template to deploy: %v", err)
		}
		jsonData, err = adaptFabric8ImagesInResourceDescriptor(jsonData, dockerRegistry, arch)
		if err != nil {
			util.Fatalf("Cannot append docker registry: %v", err)
		}
		jsonData = replaceDomain(jsonData, domain, ns, typeOfMaster)

		var v1tmpl tapiv1.Template
		lowerName := strings.ToLower(f.Name)

		// if the folder starts with kubernetes/ or openshift/ then lets filter based on the cluster:
		if strings.HasPrefix(lowerName, "kubernetes/") && typeOfMaster != util.Kubernetes {
			//util.Info("Ignoring as on openshift!")
			continue
		}
		if strings.HasPrefix(lowerName, "openshift/") && typeOfMaster == util.Kubernetes {
			//util.Info("Ignoring as on kubernetes!")
			continue
		}
		configMapKeySuffix := ".json"
		if strings.HasSuffix(lowerName, ".yml") || strings.HasSuffix(lowerName, ".yaml") {
			configMapKeySuffix = ".yml"
			err = yaml.Unmarshal(jsonData, &v1tmpl)

		} else if strings.HasSuffix(lowerName, ".json") {
			err = json.Unmarshal(jsonData, &v1tmpl)
		} else {
			continue
		}
		if err != nil {
			util.Fatalf("Cannot unmarshall the fabric8 template %s to deploy: %v", f.Name, err)
		}
		util.Infof("Loading template %s\n", f.Name)

		var tmpl tapi.Template

		err = api.Scheme.Convert(&v1tmpl, &tmpl)
		if err != nil {
			util.Fatalf("Cannot get fabric8 template to deploy: %v", err)
			return err
		}

		name := tmpl.ObjectMeta.Name
		template := true
		if len(name) <= 0 {
			template = false
			name = f.Name
			idx := strings.LastIndex(name, "/")
			if idx > 0 {
				name = name[idx+1:]
			}
			idx = strings.Index(name, ".")
			if idx > 0 {
				name = name[0:idx]
			}

		}
		if typeOfMaster == util.Kubernetes {
			appName := name
			name = "catalog-" + appName

			// lets install ConfigMaps for the templates
			// TODO should the name have a prefix?
			configmap := api.ConfigMap{
				ObjectMeta: api.ObjectMeta{
					Name:      name,
					Namespace: ns,
					Labels: map[string]string{
						"name":     appName,
						"provider": "fabric8.io",
						"kind":     "catalog",
					},
				},
				Data: map[string]string{
					name + configMapKeySuffix: string(jsonData),
				},
			}
			configmaps := kc.ConfigMaps(ns)
			_, err = configmaps.Get(name)
			if err == nil {
				err = configmaps.Delete(name)
				if err != nil {
					util.Errorf("Could not delete configmap %s due to: %v\n", name, err)
				}
			}
			_, err = configmaps.Create(&configmap)
			if err != nil {
				util.Fatalf("Failed to create configmap %v", err)
				return err
			}
		} else {
			if !template {
				templateName := name
				var v1List v1.List
				if configMapKeySuffix == ".json" {
					err = json.Unmarshal(jsonData, &v1List)
				} else {
					err = yaml.Unmarshal(jsonData, &v1List)
				}
				if err != nil {
					util.Fatalf("Cannot unmarshal List %s to deploy. error: %v\ntemplate: %s", templateName, err, string(jsonData))
				}
				if len(v1List.Items) == 0 {
					// lets check if its an RC / ReplicaSet or something
					_, groupVersionKind, err := api.Codecs.UniversalDeserializer().Decode(jsonData, nil, nil)
					if err != nil {
						printResult(templateName, Failure, err)
					} else {
						kind := groupVersionKind.Kind
						util.Infof("Processing resource of kind: %s version: %s\n", kind, groupVersionKind.Version)
						if len(kind) <= 0 {
							printResult(templateName, Failure, fmt.Errorf("Could not find kind from json %s", string(jsonData)))
						} else {
							util.Warnf("Cannot yet process kind %s, kind for %s\n", kind, templateName)
							continue
						}
					}
				} else {
					var kubeList api.List
					err = api.Scheme.Convert(&v1List, &kubeList)
					if err != nil {
						util.Fatalf("Cannot convert %s List to deploy: %v", templateName, err)
					}
					tmpl = tapi.Template{
						ObjectMeta: api.ObjectMeta{
							Name:      name,
							Namespace: ns,
							Labels: map[string]string{
								"name":     name,
								"provider": "fabric8.io",
							},
						},
						Objects: kubeList.Items,
					}
				}
			}

			// remove newlines from description to avoid breaking `oc get template`
			description := tmpl.ObjectMeta.Annotations["description"]
			if len(description) > 0 {
				tmpl.ObjectMeta.Annotations["description"] = strings.Replace(description, "\n", " ", -1)
			}

			// lets install the OpenShift templates
			_, err = templates.Get(name)
			if err == nil {
				err = templates.Delete(name)
				if err != nil {
					util.Errorf("Could not delete template %s due to: %v\n", name, err)
				}
			}
			_, err = templates.Create(&tmpl)
			if err != nil {
				util.Warnf("Failed to create template %v", err)
				return err
			}
		}
	}
	return nil
}
Ejemplo n.º 2
0
func install(isMinishift bool) {

	writeFileLocation := getFabric8BinLocation()

	err := os.MkdirAll(writeFileLocation, 0700)
	if err != nil {
		util.Errorf("Unable to create directory to download files %s %v\n", writeFileLocation, err)
	}

	err = downloadDriver()
	if err != nil {
		util.Warnf("Unable to download driver %v\n", err)
	}

	d := getDownloadProperties(isMinishift)
	err = downloadKubernetes(d)
	if err != nil {
		util.Warnf("Unable to download kubernetes distro %v\n", err)
	}

	err = downloadKubectlClient()
	if err != nil {
		util.Warnf("Unable to download client %v\n", err)
	}

	if d.isMiniShift {
		err = downloadOpenShiftClient()
		if err != nil {
			util.Warnf("Unable to download client %v\n", err)
		}
	}

}
Ejemplo n.º 3
0
func copyEndpoints(c *k8sclient.Client, fromNs string, toNs string, names []string) error {
	var answer error
	for _, name := range names {
		item, err := c.Endpoints(fromNs).Get(name)
		if err != nil {
			util.Warnf("No endpoint called %s found in namespace %s", name, fromNs)
			answer = err
		}
		name := item.Name
		objectMeta := item.ObjectMeta

		current, err := c.Endpoints(toNs).Get(name)
		if current == nil || err != nil {
			// lets create the endpoint
			newEndpoints := &api.Endpoints{
				ObjectMeta: api.ObjectMeta{
					Name:        name,
					Labels:      objectMeta.Labels,
					Annotations: objectMeta.Annotations,
				},
				Subsets: item.Subsets,
			}
			_, err = c.Endpoints(toNs).Create(newEndpoints)
			if err != nil {
				return err
			}
			util.Infof("Created endpoint %s in namespace %s\n", name, toNs)
		}
	}
	return answer
}
Ejemplo n.º 4
0
func processResource(c *k8sclient.Client, b []byte, ns string, kind string) error {
	util.Infof("Processing resource kind: %s in namespace %s\n", kind, ns)
	req := c.Post().Body(b)
	if kind == "Deployment" {
		req.AbsPath("apis", "extensions/v1beta1", "namespaces", ns, strings.ToLower(kind+"s"))
	} else if kind == "BuildConfig" || kind == "DeploymentConfig" || kind == "Template" || kind == "PolicyBinding" || kind == "Role" || kind == "RoleBinding" {
		req.AbsPath("oapi", "v1", "namespaces", ns, strings.ToLower(kind+"s"))
	} else if kind == "OAuthClient" || kind == "Project" || kind == "ProjectRequest" {
		req.AbsPath("oapi", "v1", strings.ToLower(kind+"s"))
	} else if kind == "Namespace" {
		req.AbsPath("api", "v1", "namespaces")
	} else {
		req.Namespace(ns).Resource(strings.ToLower(kind + "s"))
	}
	res := req.Do()
	if res.Error() != nil {
		err := res.Error()
		if err != nil {
			util.Warnf("Failed to create %s: %v", kind, err)
			return err
		}
	}
	var statusCode int
	res.StatusCode(&statusCode)
	if statusCode != http.StatusCreated {
		return fmt.Errorf("Failed to create %s: %d", kind, statusCode)
	}
	return nil
}
Ejemplo n.º 5
0
func addIngressInfraLabel(c *k8sclient.Client, ns string) string {
	nodeClient := c.Nodes()
	nodes, err := nodeClient.List(api.ListOptions{})
	if err != nil {
		util.Errorf("\nUnable to find any nodes: %s\n", err)
	}
	changed := false
	hasExistingExposeIPLabel, externalNodeName := hasExistingLabel(nodes, externalIPLabel)
	if externalNodeName != "" {
		return externalNodeName
	}
	if !hasExistingExposeIPLabel && len(nodes.Items) > 0 {
		for _, node := range nodes.Items {
			if !node.Spec.Unschedulable {
				changed = addLabelIfNotExist(&node.ObjectMeta, externalIPLabel, "true")
				if changed {
					_, err = nodeClient.Update(&node)
					if err != nil {
						printError("Failed to label node with ", err)
					}
					return node.Name
				}
			}
		}
	}
	if !changed && !hasExistingExposeIPLabel {
		util.Warnf("Unable to add label for ingress controller to run on a specific node, please add manually: kubectl label node [your node name] %s=true", externalIPLabel)
	}
	return ""
}
Ejemplo n.º 6
0
// NewCmdInstall installs the dependencies to run the fabric8 microservices platform
func NewCmdInstall(f *cmdutil.Factory) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "install",
		Short: "Installs the dependencies to locally run the fabric8 microservices platform",
		Long:  `Installs the dependencies to locally run the fabric8 microservices platform`,

		Run: func(cmd *cobra.Command, args []string) {

			if runtime.GOOS == "windows" {
				util.Errorf("%s is not yet supported by gofabric8 install", runtime.GOOS)
			}

			isMinishift := cmd.Flags().Lookup(minishiftFlag).Value.String() == "true"

			home := os.Getenv("HOME")
			if home == "" {
				util.Error("No $HOME environment variable found")
			}
			writeFileLocation = home + binLocation

			err := os.MkdirAll(writeFileLocation, 0700)
			if err != nil {
				util.Errorf("Unable to create directory to download files %s %v\n", writeFileLocation, err)
			}

			err = downloadDriver()
			if err != nil {
				util.Warnf("Unable to download driver %v\n", err)
			}

			err = downloadKubernetes(isMinishift)
			if err != nil {
				util.Warnf("Unable to download kubernetes distro %v\n", err)
			}

			err = downloadClient(isMinishift)
			if err != nil {
				util.Warnf("Unable to download client %v\n", err)
			}

		},
	}
	cmd.PersistentFlags().Bool(minishiftFlag, false, "Install minishift rather than minikube")
	return cmd
}
Ejemplo n.º 7
0
func NewCmdRun(f *cmdutil.Factory) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "run",
		Short: "Runs a fabric8 microservice from one of the installed templates",
		Long:  `runs a fabric8 microservice from one of the installed templates`,
		PreRun: func(cmd *cobra.Command, args []string) {
			showBanner()
		},
		Run: func(cmd *cobra.Command, args []string) {
			c, cfg := client.NewClient(f)
			ns, _, _ := f.DefaultNamespace()

			if len(args) == 0 {
				util.Info("Please specify a template name to run\n")
				return
			}
			domain := cmd.Flags().Lookup(domainFlag).Value.String()
			apiserver := cmd.Flags().Lookup(apiServerFlag).Value.String()
			pv := cmd.Flags().Lookup(pvFlag).Value.String() == "true"

			typeOfMaster := util.TypeOfMaster(c)

			util.Info("Running an app template to your ")
			util.Success(string(typeOfMaster))
			util.Info(" installation at ")
			util.Success(cfg.Host)
			util.Info(" for domain ")
			util.Success(domain)
			util.Info(" in namespace ")
			util.Successf("%s\n\n", ns)

			if len(apiserver) == 0 {
				apiserver = domain
			}

			yes := cmd.Flags().Lookup(yesFlag).Value.String() == "false"
			if strings.Contains(domain, "=") {
				util.Warnf("\nInvalid domain: %s\n\n", domain)

			} else if confirmAction(yes) {
				oc, _ := client.NewOpenShiftClient(cfg)
				initSchema()

				for _, app := range args {
					runTemplate(c, oc, app, ns, domain, apiserver, pv)
				}
			}
		},
	}
	cmd.PersistentFlags().StringP(domainFlag, "d", defaultDomain(), "The domain name to append to the service name to access web applications")
	cmd.PersistentFlags().String(apiServerFlag, "", "overrides the api server url")
	cmd.PersistentFlags().Bool(pvFlag, true, "Enable the use of persistence (enabling the PersistentVolumeClaims)?")
	return cmd
}
Ejemplo n.º 8
0
func waitForDeploymentConfig(c *oclient.Client, ns string, name string, sleepMillis time.Duration) error {
	util.Infof("DeploymentConfig %s in namespace %s waiting for it to be ready...\n", name, ns)
	for {
		deployment, err := c.DeploymentConfigs(ns).Get(name)
		if err != nil {
			util.Warnf("Cannot find DeploymentConfig %s in namepsace %s due to %s\n", name, ns, err)
			return err
		}
		if deployment.Status.Replicas == 0 {
			util.Warnf("No replicas for DeploymentConfig %s in namespace %s\n", name, ns)
		}
		available := deployment.Status.AvailableReplicas
		unavailable := deployment.Status.UnavailableReplicas
		if unavailable == 0 && available > 0 {
			util.Infof("DeploymentConfig %s now has %d available replicas\n", name, available)
			return nil
		}
		//util.Infof("DeploymentConfig %s has %d available replicas and %d unavailable\n", name, available, unavailable)
		time.Sleep(sleepMillis)
	}
}
Ejemplo n.º 9
0
func NewCmdDeploy(f *cmdutil.Factory) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "deploy",
		Short: "Deploy fabric8 to your Kubernetes or OpenShift environment",
		Long:  `deploy fabric8 to your Kubernetes or OpenShift environment`,
		PreRun: func(cmd *cobra.Command, args []string) {
			showBanner()
		},
		Run: func(cmd *cobra.Command, args []string) {
			c, cfg := client.NewClient(f)
			ns, _, _ := f.DefaultNamespace()

			domain := cmd.Flags().Lookup(domainFlag).Value.String()
			apiserver := cmd.Flags().Lookup(apiServerFlag).Value.String()
			arch := cmd.Flags().Lookup(archFlag).Value.String()

			typeOfMaster := util.TypeOfMaster(c)

			util.Info("Deploying fabric8 to your ")
			util.Success(string(typeOfMaster))
			util.Info(" installation at ")
			util.Success(cfg.Host)
			util.Info(" for domain ")
			util.Success(domain)
			util.Info(" in namespace ")
			util.Successf("%s\n\n", ns)

			useIngress := cmd.Flags().Lookup(useIngressFlag).Value.String() == "true"
			deployConsole := cmd.Flags().Lookup(consoleFlag).Value.String() == "true"

			mavenRepo := cmd.Flags().Lookup(mavenRepoFlag).Value.String()
			if !strings.HasSuffix(mavenRepo, "/") {
				mavenRepo = mavenRepo + "/"
			}
			util.Info("Loading fabric8 releases from maven repository:")
			util.Successf("%s\n", mavenRepo)

			dockerRegistry := cmd.Flags().Lookup(dockerRegistryFlag).Value.String()
			if len(dockerRegistry) > 0 {
				util.Infof("Loading fabric8 docker images from docker registry: %s\n", dockerRegistry)
			}

			if len(apiserver) == 0 {
				apiserver = domain
			}

			if strings.Contains(domain, "=") {
				util.Warnf("\nInvalid domain: %s\n\n", domain)
			} else if confirmAction(cmd.Flags()) {
				v := cmd.Flags().Lookup("fabric8-version").Value.String()

				consoleVersion := f8ConsoleVersion(mavenRepo, v, typeOfMaster)

				versioniPaaS := cmd.Flags().Lookup(versioniPaaSFlag).Value.String()
				versioniPaaS = versionForUrl(versioniPaaS, urlJoin(mavenRepo, iPaaSMetadataUrl))

				versionDevOps := cmd.Flags().Lookup(versionDevOpsFlag).Value.String()
				versionDevOps = versionForUrl(versionDevOps, urlJoin(mavenRepo, devOpsMetadataUrl))

				versionKubeflix := cmd.Flags().Lookup(versionKubeflixFlag).Value.String()
				versionKubeflix = versionForUrl(versionKubeflix, urlJoin(mavenRepo, kubeflixMetadataUrl))

				versionZipkin := cmd.Flags().Lookup(versionZipkinFlag).Value.String()
				versionZipkin = versionForUrl(versionZipkin, urlJoin(mavenRepo, zipkinMetadataUrl))

				util.Warnf("\nStarting fabric8 console deployment using %s...\n\n", consoleVersion)

				oc, _ := client.NewOpenShiftClient(cfg)

				aapi.AddToScheme(api.Scheme)
				aapiv1.AddToScheme(api.Scheme)
				tapi.AddToScheme(api.Scheme)
				tapiv1.AddToScheme(api.Scheme)

				if typeOfMaster == util.Kubernetes {
					uri := fmt.Sprintf(urlJoin(mavenRepo, baseConsoleKubernetesUrl), consoleVersion)
					if fabric8ImageAdaptionNeeded(dockerRegistry, arch) {
						jsonData, err := loadJsonDataAndAdaptFabric8Images(uri, dockerRegistry, arch)
						if err == nil {
							tmpFileName := "/tmp/fabric8-console.json"
							t, err := os.OpenFile(tmpFileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
							if err != nil {
								util.Fatalf("Cannot open the converted fabric8 console template file: %v", err)
							}
							defer t.Close()

							_, err = io.Copy(t, bytes.NewReader(jsonData))
							if err != nil {
								util.Fatalf("Cannot write the converted fabric8 console template file: %v", err)
							}
							uri = tmpFileName
						}
					}
					filenames := []string{uri}

					if deployConsole {
						createCmd := &cobra.Command{}
						cmdutil.AddValidateFlags(createCmd)
						cmdutil.AddOutputFlagsForMutation(createCmd)
						cmdutil.AddApplyAnnotationFlags(createCmd)
						cmdutil.AddRecordFlag(createCmd)
						err := kcmd.RunCreate(f, createCmd, ioutil.Discard, &kcmd.CreateOptions{Filenames: filenames})
						if err != nil {
							printResult("fabric8 console", Failure, err)
						} else {
							printResult("fabric8 console", Success, nil)
						}
					}
					printAddServiceAccount(c, f, "fluentd")
					printAddServiceAccount(c, f, "registry")
				} else {
					r, err := verifyRestrictedSecurityContextConstraints(c, f)
					printResult("SecurityContextConstraints restricted", r, err)
					r, err = deployFabric8SecurityContextConstraints(c, f, ns)
					printResult("SecurityContextConstraints fabric8", r, err)
					r, err = deployFabric8SASSecurityContextConstraints(c, f, ns)
					printResult("SecurityContextConstraints "+Fabric8SASSCC, r, err)

					printAddClusterRoleToUser(oc, f, "cluster-admin", "system:serviceaccount:"+ns+":fabric8")
					printAddClusterRoleToUser(oc, f, "cluster-admin", "system:serviceaccount:"+ns+":jenkins")
					printAddClusterRoleToUser(oc, f, "cluster-reader", "system:serviceaccount:"+ns+":metrics")
					printAddClusterRoleToUser(oc, f, "cluster-reader", "system:serviceaccount:"+ns+":fluentd")

					printAddServiceAccount(c, f, "fluentd")
					printAddServiceAccount(c, f, "registry")
					printAddServiceAccount(c, f, "router")

					if cmd.Flags().Lookup(templatesFlag).Value.String() == "true" {
						if deployConsole {
							uri := fmt.Sprintf(urlJoin(mavenRepo, baseConsoleUrl), consoleVersion)
							jsonData, err := loadJsonDataAndAdaptFabric8Images(uri, dockerRegistry, arch)
							if err != nil {
								printError("failed to apply docker registry prefix", err)
							}

							// lets delete the OAuthClient first as the domain may have changed
							oc.OAuthClients().Delete("fabric8")
							createTemplate(jsonData, "fabric8 console", ns, domain, apiserver, c)
						}
					} else {
						printError("Ignoring the deploy of the fabric8 console", nil)
					}
				}
				if deployConsole {
					println("Created fabric8 console")
				}

				if cmd.Flags().Lookup(templatesFlag).Value.String() == "true" {
					println("Installing templates!")
					printError("Install DevOps templates", installTemplates(c, oc, f, versionDevOps, urlJoin(mavenRepo, devopsTemplatesDistroUrl), dockerRegistry, arch, domain))
					printError("Install iPaaS templates", installTemplates(c, oc, f, versioniPaaS, urlJoin(mavenRepo, iPaaSTemplatesDistroUrl), dockerRegistry, arch, domain))
					printError("Install Kubeflix templates", installTemplates(c, oc, f, versionKubeflix, urlJoin(mavenRepo, kubeflixTemplatesDistroUrl), dockerRegistry, arch, domain))
					printError("Install Zipkin templates", installTemplates(c, oc, f, versionZipkin, urlJoin(mavenRepo, zipkinTemplatesDistroUrl), dockerRegistry, arch, domain))
				} else {
					printError("Ignoring the deploy of templates", nil)
				}

				appToRun := cmd.Flags().Lookup(runFlag).Value.String()
				if len(appToRun) > 0 {
					runTemplate(c, oc, appToRun, ns, domain, apiserver)
				}

				if typeOfMaster == util.Kubernetes {
					if useIngress {
						runTemplate(c, oc, "ingress-nginx", ns, domain, apiserver)

						printError("Create ingress resources", createIngressForDomain(ns, domain, c, f))
					}
				} else {
					printError("Create route resources", createRoutesForDomain(ns, domain, c, oc, f))
				}

				// lets label the namespace/project as a developer team
				nss := c.Namespaces()
				namespace, err := nss.Get(ns)
				if err != nil {
					printError("Failed to load namespace", err)
				} else {
					if addLabelIfNotxisEt(&namespace.ObjectMeta, typeLabel, teamTypeLabelValue) {
						_, err = nss.Update(namespace)
						if err != nil {
							printError("Failed to label namespace", err)
						}
					}
				}
			}
		},
	}
	cmd.PersistentFlags().StringP("domain", "d", defaultDomain(), "The domain name to append to the service name to access web applications")
	cmd.PersistentFlags().String("api-server", "", "overrides the api server url")
	cmd.PersistentFlags().String(archFlag, goruntime.GOARCH, "CPU architecture for referencing Docker images with this as a name suffix")
	cmd.PersistentFlags().String(versioniPaaSFlag, "latest", "The version to use for the Fabric8 iPaaS templates")
	cmd.PersistentFlags().String(versionDevOpsFlag, "latest", "The version to use for the Fabric8 DevOps templates")
	cmd.PersistentFlags().String(versionKubeflixFlag, "latest", "The version to use for the Kubeflix templates")
	cmd.PersistentFlags().String(versionZipkinFlag, "latest", "The version to use for the Zipkin templates")
	cmd.PersistentFlags().String(mavenRepoFlag, "https://repo1.maven.org/maven2/", "The maven repo used to find releases of fabric8")
	cmd.PersistentFlags().String(dockerRegistryFlag, "", "The docker registry used to download fabric8 images. Typically used to point to a staging registry")
	cmd.PersistentFlags().String(runFlag, "", "The name of the fabric8 app to startup. e.g. use `--app=cd-pipeline` to run the main CI/CD pipeline app")
	cmd.PersistentFlags().Bool(templatesFlag, true, "Should the standard Fabric8 templates be installed?")
	cmd.PersistentFlags().Bool(consoleFlag, true, "Should the Fabric8 console be deployed?")
	cmd.PersistentFlags().Bool(useIngressFlag, true, "Should Ingress be enabled by default?")
	return cmd
}
Ejemplo n.º 10
0
func deploy(f *cmdutil.Factory, d DefaultFabric8Deployment) {
	c, cfg := client.NewClient(f)
	ns, _, _ := f.DefaultNamespace()

	domain := d.domain
	dockerRegistry := d.dockerRegistry

	mini, err := util.IsMini()
	if err != nil {
		util.Failuref("error checking if minikube or minishift %v", err)
	}

	packageName := d.packageName
	if len(packageName) == 0 {
		util.Fatalf("Missing value for --%s", packageFlag)
	}

	typeOfMaster := util.TypeOfMaster(c)

	// extract the ip address from the URL
	u, err := url.Parse(cfg.Host)
	if err != nil {
		util.Fatalf("%s", err)
	}

	ip, _, err := net.SplitHostPort(u.Host)
	if err != nil && !strings.Contains(err.Error(), "missing port in address") {
		util.Fatalf("%s", err)
	}

	// default xip domain if local deployment incase users deploy ingress controller or router
	if mini && typeOfMaster == util.OpenShift {
		domain = ip + ".xip.io"
	}

	// default to the server from the current context
	apiserver := u.Host
	if d.apiserver != "" {
		apiserver = d.apiserver
	}

	util.Info("Deploying fabric8 to your ")
	util.Success(string(typeOfMaster))
	util.Info(" installation at ")
	util.Success(cfg.Host)
	util.Info(" for domain ")
	util.Success(domain)
	util.Info(" in namespace ")
	util.Successf("%s\n\n", ns)

	mavenRepo := d.mavenRepo
	if !strings.HasSuffix(mavenRepo, "/") {
		mavenRepo = mavenRepo + "/"
	}
	util.Info("Loading fabric8 releases from maven repository:")
	util.Successf("%s\n", mavenRepo)

	if len(dockerRegistry) > 0 {
		util.Infof("Loading fabric8 docker images from docker registry: %s\n", dockerRegistry)
	}

	if len(apiserver) == 0 {
		apiserver = domain
	}

	if len(d.appToRun) > 0 {
		util.Warn("Please note that the --app parameter is now deprecated.\n")
		util.Warn("Please use the --package argument to specify a package like `platform`, `console`, `ipaas` or to refer to a URL or file of the YAML package to install\n")
	}

	if strings.Contains(domain, "=") {
		util.Warnf("\nInvalid domain: %s\n\n", domain)
	} else if confirmAction(d.yes) {

		oc, _ := client.NewOpenShiftClient(cfg)

		initSchema()

		ensureNamespaceExists(c, oc, ns)

		versionPlatform := ""
		baseUri := ""
		switch packageName {
		case "":
		case platformPackage:
			baseUri = platformPackageUrlPrefix
			versionPlatform = versionForUrl(d.versionPlatform, urlJoin(mavenRepo, platformMetadataUrl))
			logPackageVersion(packageName, versionPlatform)
		case consolePackage:
			baseUri = consolePackageUrlPrefix
			versionPlatform = versionForUrl(d.versionPlatform, urlJoin(mavenRepo, consolePackageMetadataUrl))
			logPackageVersion(packageName, versionPlatform)
		case iPaaSPackage:
			baseUri = ipaasPackageUrlPrefix
			versionPlatform = versionForUrl(d.versioniPaaS, urlJoin(mavenRepo, ipaasMetadataUrl))
			logPackageVersion(packageName, versionPlatform)
		default:
			baseUri = ""
		}
		uri := ""
		if len(baseUri) > 0 {
			uri = fmt.Sprintf(urlJoin(mavenRepo, baseUri), versionPlatform)

		} else {
			// lets assume the package is a file or a uri already
			if strings.Contains(packageName, "://") {
				uri = packageName
			} else {
				d, err := os.Stat(packageName)
				if err != nil {
					util.Fatalf("package %s not recognised and is not a local file %s\n", packageName, err)
				}
				if m := d.Mode(); m.IsDir() {
					util.Fatalf("package %s not recognised and is not a local file %s\n", packageName, err)
				}
				absFile, err := filepath.Abs(packageName)
				if err != nil {
					util.Fatalf("package %s not recognised and is not a local file %s\n", packageName, err)
				}
				uri = "file://" + absFile
			}
		}

		if typeOfMaster == util.Kubernetes {
			if !strings.HasPrefix(uri, "file://") {
				uri += "kubernetes.yml"
			}
		} else {
			if !strings.HasPrefix(uri, "file://") {
				uri += "openshift.yml"
			}

			r, err := verifyRestrictedSecurityContextConstraints(c, f)
			printResult("SecurityContextConstraints restricted", r, err)
			r, err = deployFabric8SecurityContextConstraints(c, f, ns)
			printResult("SecurityContextConstraints fabric8", r, err)
			r, err = deployFabric8SASSecurityContextConstraints(c, f, ns)
			printResult("SecurityContextConstraints "+Fabric8SASSCC, r, err)

			printAddClusterRoleToUser(oc, f, "cluster-admin", "system:serviceaccount:"+ns+":fabric8")

			// TODO replace all of this with the necessary RoleBindings inside the OpenShift YAML...
			printAddClusterRoleToUser(oc, f, "cluster-admin", "system:serviceaccount:"+ns+":jenkins")

			printAddClusterRoleToUser(oc, f, "cluster-admin", "system:serviceaccount:"+ns+":configmapcontroller")
			printAddClusterRoleToUser(oc, f, "cluster-admin", "system:serviceaccount:"+ns+":exposecontroller")

			printAddClusterRoleToUser(oc, f, "cluster-reader", "system:serviceaccount:"+ns+":metrics")
			printAddClusterRoleToUser(oc, f, "cluster-reader", "system:serviceaccount:"+ns+":fluentd")

			printAddClusterRoleToGroup(oc, f, "cluster-reader", "system:serviceaccounts")

			printAddServiceAccount(c, f, "fluentd")
			printAddServiceAccount(c, f, "registry")
			printAddServiceAccount(c, f, "router")
		}

		// now lets apply this template
		util.Infof("Now about to install package %s\n", uri)

		yamlData := []byte{}
		format := "yaml"

		if strings.HasPrefix(uri, "file://") {
			fileName := strings.TrimPrefix(uri, "file://")
			if strings.HasSuffix(fileName, ".json") {
				format = "json"
			}
			yamlData, err = ioutil.ReadFile(fileName)
			if err != nil {
				util.Fatalf("Cannot load file %s got: %v", fileName, err)
			}
		} else {
			resp, err := http.Get(uri)
			if err != nil {
				util.Fatalf("Cannot load YAML package at %s got: %v", uri, err)
			}
			defer resp.Body.Close()
			yamlData, err = ioutil.ReadAll(resp.Body)
			if err != nil {
				util.Fatalf("Cannot load YAML from %s got: %v", uri, err)
			}
		}
		createTemplate(yamlData, format, packageName, ns, domain, apiserver, c, oc, d.pv)

		externalNodeName := ""
		if typeOfMaster == util.Kubernetes {
			if !mini && d.useIngress {
				ensureNamespaceExists(c, oc, fabric8SystemNamespace)
				util.Infof("ns is %s\n", ns)
				runTemplate(c, oc, "ingress-nginx", ns, domain, apiserver, d.pv)
				externalNodeName = addIngressInfraLabel(c, ns)
			}
		}

		updateExposeControllerConfig(c, ns, apiserver, domain, mini, d.useLoadbalancer)

		mini, _ := util.IsMini()
		if mini {
			createMissingPVs(c, ns)
		}

		printSummary(typeOfMaster, externalNodeName, ns, domain, c)
		if d.openConsole {
			openService(ns, "fabric8", c, false, true)
		}
	}
}
Ejemplo n.º 11
0
func check(e error) {
	if e != nil {
		util.Warnf("Warning: %s\n", e)
	}
}
Ejemplo n.º 12
0
func NewCmdDeploy(f *cmdutil.Factory) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "deploy",
		Short: "Deploy fabric8 to your Kubernetes or OpenShift environment",
		Long:  `deploy fabric8 to your Kubernetes or OpenShift environment`,
		PreRun: func(cmd *cobra.Command, args []string) {
			showBanner()
		},
		Run: func(cmd *cobra.Command, args []string) {
			c, cfg := client.NewClient(f)
			ns, _, _ := f.DefaultNamespace()
			util.Info("Deploying fabric8 to your ")
			util.Success(string(util.TypeOfMaster(c)))
			util.Info(" installation at ")
			util.Success(cfg.Host)
			util.Info(" in namespace ")
			util.Successf("%s\n\n", ns)

			if confirmAction(cmd.Flags()) {
				v := cmd.Flags().Lookup("version").Value.String()

				typeOfMaster := util.TypeOfMaster(c)
				v = f8Version(v, typeOfMaster)

				versioniPaaS := cmd.Flags().Lookup(versioniPaaSFlag).Value.String()
				versioniPaaS = versionForUrl(versioniPaaS, iPaaSMetadataUrl)

				util.Warnf("\nStarting deployment of %s...\n\n", v)

				if typeOfMaster == util.Kubernetes {
					uri := fmt.Sprintf(baseConsoleKubernetesUrl, v)
					filenames := []string{uri}

					createCmd := cobra.Command{}
					createCmd.Flags().StringSlice("filename", filenames, "")
					err := kcmd.RunCreate(f, &createCmd, ioutil.Discard)
					if err != nil {
						printResult("fabric8 console", Failure, err)
					} else {
						printResult("fabric8 console", Success, nil)
					}
				} else {
					oc, _ := client.NewOpenShiftClient(cfg)

					r, err := verifyRestrictedSecurityContextConstraints(c, f)
					printResult("SecurityContextConstraints restricted", r, err)
					r, err = deployFabric8SecurityContextConstraints(c, f, ns)
					printResult("SecurityContextConstraints fabric8", r, err)

					printAddClusterRoleToUser(oc, f, "cluster-admin", "system:serviceaccount:"+ns+":fabric8")
					printAddClusterRoleToUser(oc, f, "cluster-admin", "system:serviceaccount:"+ns+":jenkins")
					printAddClusterRoleToUser(oc, f, "cluster-reader", "system:serviceaccount:"+ns+":metrics")

					printAddServiceAccount(c, f, "metrics")
					printAddServiceAccount(c, f, "router")

					if cmd.Flags().Lookup(templatesFlag).Value.String() == "true" {
						uri := fmt.Sprintf(baseConsoleUrl, v)
						resp, err := http.Get(uri)
						if err != nil {
							util.Fatalf("Cannot get fabric8 template to deploy: %v", err)
						}
						defer resp.Body.Close()
						jsonData, err := ioutil.ReadAll(resp.Body)
						if err != nil {
							util.Fatalf("Cannot get fabric8 template to deploy: %v", err)
						}
						var v1tmpl tapiv1.Template
						err = json.Unmarshal(jsonData, &v1tmpl)
						if err != nil {
							util.Fatalf("Cannot get fabric8 template to deploy: %v", err)
						}
						var tmpl tapi.Template

						err = api.Scheme.Convert(&v1tmpl, &tmpl)
						if err != nil {
							util.Fatalf("Cannot get fabric8 template to deploy: %v", err)
						}

						generators := map[string]generator.Generator{
							"expression": generator.NewExpressionValueGenerator(rand.New(rand.NewSource(time.Now().UnixNano()))),
						}
						p := template.NewProcessor(generators)

						tmpl.Parameters = append(tmpl.Parameters, tapi.Parameter{
							Name:  "DOMAIN",
							Value: cmd.Flags().Lookup("domain").Value.String(),
						})

						p.Process(&tmpl)

						for _, o := range tmpl.Objects {
							switch o := o.(type) {
							case *runtime.Unstructured:
								var b []byte
								b, err = json.Marshal(o.Object)
								if err != nil {
									break
								}
								req := c.Post().Body(b)
								if o.Kind != "OAuthClient" {
									req.Namespace(ns).Resource(strings.ToLower(o.TypeMeta.Kind + "s"))
								} else {
									req.AbsPath("oapi", "v1", strings.ToLower(o.TypeMeta.Kind+"s"))
								}
								res := req.Do()
								if res.Error() != nil {
									err = res.Error()
									break
								}
								var statusCode int
								res.StatusCode(&statusCode)
								if statusCode != http.StatusCreated {
									err = fmt.Errorf("Failed to create %s: %d", o.TypeMeta.Kind, statusCode)
									break
								}
							}
						}

						if err != nil {
							printResult("fabric8 console", Failure, err)
						} else {
							printResult("fabric8 console", Success, nil)
						}
					} else {
						printError("Ignoring the deploy of the fabric8 console", nil)
					}

					if cmd.Flags().Lookup(templatesFlag).Value.String() == "true" {
						printError("Install DevOps templates", installTemplates(oc, f, v, templatesDistroUrl))
						printError("Install iPaaS templates", installTemplates(oc, f, versioniPaaS, iPaaSTemplatesDistroUrl))
					} else {
						printError("Ignoring the deploy of templates", nil)
					}

					domain := cmd.Flags().Lookup(domainFlag).Value.String()

					printError("Create routes", createRoutesForDomain(ns, domain, c, oc, f))
				}
			}
		},
	}
	cmd.PersistentFlags().StringP("domain", "d", defaultDomain(), "The domain name to append to the service name to access web applications")
	cmd.PersistentFlags().StringP(versioniPaaSFlag, "", "latest", "The version to use for the Fabric8 iPaaS templates")
	cmd.PersistentFlags().Bool(templatesFlag, true, "Should the standard Fabric8 templates be installed?")
	cmd.PersistentFlags().Bool(consoleFlag, true, "Should the Fabric8 console be deployed?")
	return cmd
}
Ejemplo n.º 13
0
func NewCmdDeploy(f *cmdutil.Factory) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "deploy",
		Short: "Deploy fabric8 to your Kubernetes or OpenShift environment",
		Long:  `deploy fabric8 to your Kubernetes or OpenShift environment`,
		PreRun: func(cmd *cobra.Command, args []string) {
			showBanner()
		},
		Run: func(cmd *cobra.Command, args []string) {
			c, cfg := client.NewClient(f)
			ns, _, _ := f.DefaultNamespace()

			domain := cmd.Flags().Lookup(domainFlag).Value.String()
			apiserver := cmd.Flags().Lookup(apiServerFlag).Value.String()
			arch := cmd.Flags().Lookup(archFlag).Value.String()
			mini := isMini(c, ns)
			typeOfMaster := util.TypeOfMaster(c)

			// extract the ip address from the URL
			ip := strings.Split(cfg.Host, ":")[1]
			ip = strings.Replace(ip, "/", "", 2)

			if mini && typeOfMaster == util.OpenShift {
				domain = ip + ".xip.io"
				apiserver = ip
			}

			util.Info("Deploying fabric8 to your ")
			util.Success(string(typeOfMaster))
			util.Info(" installation at ")
			util.Success(cfg.Host)
			util.Info(" for domain ")
			util.Success(domain)
			util.Info(" in namespace ")
			util.Successf("%s\n\n", ns)

			useIngress := cmd.Flags().Lookup(useIngressFlag).Value.String() == "true"
			deployConsole := cmd.Flags().Lookup(consoleFlag).Value.String() == "true"

			pv, err := shouldEnablePV(c, cmd.Flags())
			if err != nil {
				util.Fatalf("No nodes available, something bad has happened: %v", err)
			}

			mavenRepo := cmd.Flags().Lookup(mavenRepoFlag).Value.String()
			if !strings.HasSuffix(mavenRepo, "/") {
				mavenRepo = mavenRepo + "/"
			}
			util.Info("Loading fabric8 releases from maven repository:")
			util.Successf("%s\n", mavenRepo)

			dockerRegistry := cmd.Flags().Lookup(dockerRegistryFlag).Value.String()
			if len(dockerRegistry) > 0 {
				util.Infof("Loading fabric8 docker images from docker registry: %s\n", dockerRegistry)
			}

			if len(apiserver) == 0 {
				apiserver = domain
			}

			if strings.Contains(domain, "=") {
				util.Warnf("\nInvalid domain: %s\n\n", domain)
			} else if confirmAction(cmd.Flags()) {
				v := cmd.Flags().Lookup("fabric8-version").Value.String()

				consoleVersion := f8ConsoleVersion(mavenRepo, v, typeOfMaster)

				versioniPaaS := cmd.Flags().Lookup(versioniPaaSFlag).Value.String()
				versioniPaaS = versionForUrl(versioniPaaS, urlJoin(mavenRepo, iPaaSMetadataUrl))

				versionDevOps := cmd.Flags().Lookup(versionDevOpsFlag).Value.String()
				versionDevOps = versionForUrl(versionDevOps, urlJoin(mavenRepo, devOpsMetadataUrl))

				versionKubeflix := cmd.Flags().Lookup(versionKubeflixFlag).Value.String()
				versionKubeflix = versionForUrl(versionKubeflix, urlJoin(mavenRepo, kubeflixMetadataUrl))

				versionZipkin := cmd.Flags().Lookup(versionZipkinFlag).Value.String()
				versionZipkin = versionForUrl(versionZipkin, urlJoin(mavenRepo, zipkinMetadataUrl))

				util.Warnf("\nStarting fabric8 console deployment using %s...\n\n", consoleVersion)

				oc, _ := client.NewOpenShiftClient(cfg)

				initSchema()

				if typeOfMaster == util.Kubernetes {
					uri := fmt.Sprintf(urlJoin(mavenRepo, baseConsoleKubernetesUrl), consoleVersion)
					if fabric8ImageAdaptionNeeded(dockerRegistry, arch) {
						jsonData, err := loadJsonDataAndAdaptFabric8Images(uri, dockerRegistry, arch)
						if err == nil {
							tmpFileName := path.Join(os.TempDir(), "fabric8-console.json")
							t, err := os.OpenFile(tmpFileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
							if err != nil {
								util.Fatalf("Cannot open the converted fabric8 console template file: %v", err)
							}
							defer t.Close()

							_, err = io.Copy(t, bytes.NewReader(jsonData))
							if err != nil {
								util.Fatalf("Cannot write the converted fabric8 console template file: %v", err)
							}
							uri = tmpFileName
						}
					}
					filenames := []string{uri}

					if deployConsole {
						createCmd := &cobra.Command{}
						cmdutil.AddValidateFlags(createCmd)
						cmdutil.AddOutputFlagsForMutation(createCmd)
						cmdutil.AddApplyAnnotationFlags(createCmd)
						cmdutil.AddRecordFlag(createCmd)
						err := kcmd.RunCreate(f, createCmd, ioutil.Discard, &kcmd.CreateOptions{Filenames: filenames})
						if err != nil {
							printResult("fabric8 console", Failure, err)
						} else {
							printResult("fabric8 console", Success, nil)
						}
					}
					printAddServiceAccount(c, f, "fluentd")
					printAddServiceAccount(c, f, "registry")
				} else {
					r, err := verifyRestrictedSecurityContextConstraints(c, f)
					printResult("SecurityContextConstraints restricted", r, err)
					r, err = deployFabric8SecurityContextConstraints(c, f, ns)
					printResult("SecurityContextConstraints fabric8", r, err)
					r, err = deployFabric8SASSecurityContextConstraints(c, f, ns)
					printResult("SecurityContextConstraints "+Fabric8SASSCC, r, err)

					printAddClusterRoleToUser(oc, f, "cluster-admin", "system:serviceaccount:"+ns+":fabric8")
					printAddClusterRoleToUser(oc, f, "cluster-admin", "system:serviceaccount:"+ns+":jenkins")
					printAddClusterRoleToUser(oc, f, "cluster-admin", "system:serviceaccount:"+ns+":exposecontroller")
					printAddClusterRoleToUser(oc, f, "cluster-reader", "system:serviceaccount:"+ns+":metrics")
					printAddClusterRoleToUser(oc, f, "cluster-reader", "system:serviceaccount:"+ns+":fluentd")

					printAddClusterRoleToGroup(oc, f, "cluster-reader", "system:serviceaccounts")

					printAddServiceAccount(c, f, "fluentd")
					printAddServiceAccount(c, f, "registry")
					printAddServiceAccount(c, f, "router")

					if cmd.Flags().Lookup(templatesFlag).Value.String() == "true" {
						if deployConsole {
							uri := fmt.Sprintf(urlJoin(mavenRepo, baseConsoleUrl), consoleVersion)
							format := "json"
							jsonData, err := loadJsonDataAndAdaptFabric8Images(uri, dockerRegistry, arch)
							if err != nil {
								printError("failed to apply docker registry prefix", err)
							}

							// lets delete the OAuthClient first as the domain may have changed
							oc.OAuthClients().Delete("fabric8")
							createTemplate(jsonData, format, "fabric8 console", ns, domain, apiserver, c, oc, pv)

							oac, err := oc.OAuthClients().Get("fabric8")
							if err != nil {
								printError("failed to get the OAuthClient called fabric8", err)
							}

							// lets add the nodePort URL to the OAuthClient
							service, err := c.Services(ns).Get("fabric8")
							if err != nil {
								printError("failed to get the Service called fabric8", err)
							}
							port := 0
							for _, p := range service.Spec.Ports {
								port = p.NodePort
							}
							if port == 0 {
								printError("failed to find nodePort on the Service called fabric8", err)
							}
							ip := apiserver
							redirectURL := fmt.Sprintf("http://%s:%d", ip, port)
							println("Adding OAuthClient redirectURL: " + redirectURL)
							oac.RedirectURIs = append(oac.RedirectURIs, redirectURL)
							oac.ResourceVersion = ""
							oc.OAuthClients().Delete("fabric8")
							_, err = oc.OAuthClients().Create(oac)
							if err != nil {
								printError("failed to create the OAuthClient called fabric8", err)
							}

						}
					} else {
						printError("Ignoring the deploy of the fabric8 console", nil)
					}
				}
				if deployConsole {
					println("Created fabric8 console")
				}

				if cmd.Flags().Lookup(templatesFlag).Value.String() == "true" {
					println("Installing templates!")
					printError("Install DevOps templates", installTemplates(c, oc, f, versionDevOps, urlJoin(mavenRepo, devopsTemplatesDistroUrl), dockerRegistry, arch, domain))
					printError("Install iPaaS templates", installTemplates(c, oc, f, versioniPaaS, urlJoin(mavenRepo, iPaaSTemplatesDistroUrl), dockerRegistry, arch, domain))
					printError("Install Kubeflix templates", installTemplates(c, oc, f, versionKubeflix, urlJoin(mavenRepo, kubeflixTemplatesDistroUrl), dockerRegistry, arch, domain))
					printError("Install Zipkin templates", installTemplates(c, oc, f, versionZipkin, urlJoin(mavenRepo, zipkinTemplatesDistroUrl), dockerRegistry, arch, domain))
				} else {
					printError("Ignoring the deploy of templates", nil)
				}

				runTemplate(c, oc, "exposecontroller", ns, domain, apiserver, pv)
				externalNodeName := ""
				if typeOfMaster == util.Kubernetes {
					if useIngress && !mini {
						runTemplate(c, oc, "ingress-nginx", ns, domain, apiserver, pv)
						externalNodeName = addIngressInfraLabel(c, ns)
					}
				}

				// create a populate the exposecontroller config map
				cfgms := c.ConfigMaps(ns)
				useLoadBalancer := cmd.Flags().Lookup(useLoadbalancerFlag).Value.String() == "true"
				_, err := cfgms.Get(exposecontrollerCM)
				if err == nil {
					util.Infof("\nRecreating configmap %s \n", exposecontrollerCM)
					err = cfgms.Delete(exposecontrollerCM)
					if err != nil {
						printError("\nError deleting ConfigMap: "+exposecontrollerCM, err)
					}
				}

				configMap := kapi.ConfigMap{
					ObjectMeta: kapi.ObjectMeta{
						Name: exposecontrollerCM,
						Labels: map[string]string{
							"provider": "fabric8.io",
						},
					},
					Data: map[string]string{
						"domain":   domain,
						exposeRule: defaultExposeRule(c, mini, useLoadBalancer),
					},
				}
				_, err = cfgms.Create(&configMap)
				if err != nil {
					printError("Failed to create ConfigMap: "+exposecontrollerCM, err)
				}

				appToRun := cmd.Flags().Lookup(runFlag).Value.String()
				if len(appToRun) > 0 {
					runTemplate(c, oc, appToRun, ns, domain, apiserver, pv)

					// lets create any missing PVs if on minikube or minishift
					found, pendingClaimNames := findPendingPVS(c, ns)
					if found {
						createPV(c, ns, pendingClaimNames, cmd)
					}
				}

				// lets label the namespace/project as a developer team
				nss := c.Namespaces()
				namespace, err := nss.Get(ns)
				if err != nil {
					printError("Failed to load namespace", err)
				} else {
					changed := addLabelIfNotExist(&namespace.ObjectMeta, typeLabel, teamTypeLabelValue)
					if len(domain) > 0 {
						if addAnnotationIfNotExist(&namespace.ObjectMeta, domainAnnotation, domain) {
							changed = true
						}
					}
					if changed {
						_, err = nss.Update(namespace)
						if err != nil {
							printError("Failed to label and annotate namespace", err)
						}
					}
				}

				// lets ensure that there is a `fabric8-environments` ConfigMap so that the current namespace
				// shows up as a Team page in the console
				_, err = cfgms.Get(fabric8Environments)
				if err != nil {
					configMap := kapi.ConfigMap{
						ObjectMeta: kapi.ObjectMeta{
							Name: fabric8Environments,
							Labels: map[string]string{
								"provider": "fabric8.io",
								"kind":     "environments",
							},
						},
					}
					_, err = cfgms.Create(&configMap)
					if err != nil {
						printError("Failed to create ConfigMap: "+fabric8Environments, err)
					}
				}

				nodeClient := c.Nodes()
				nodes, err := nodeClient.List(api.ListOptions{})
				changed := false

				for _, node := range nodes.Items {
					// if running on a single node then we can use node ports to access kubernetes services
					if len(nodes.Items) == 1 {
						changed = addAnnotationIfNotExist(&node.ObjectMeta, externalIPNodeLabel, ip)
					}
					changed = addAnnotationIfNotExist(&node.ObjectMeta, externalAPIServerAddressLabel, cfg.Host)
					if changed {
						_, err = nodeClient.Update(&node)
						if err != nil {
							printError("Failed to annotate node with ", err)
						}
					}
				}
				printSummary(typeOfMaster, externalNodeName, mini, ns, domain)

				openService(ns, "fabric8", c, false)
			}
		},
	}
	cmd.PersistentFlags().StringP(domainFlag, "d", defaultDomain(), "The domain name to append to the service name to access web applications")
	cmd.PersistentFlags().String(apiServerFlag, "", "overrides the api server url")
	cmd.PersistentFlags().String(archFlag, goruntime.GOARCH, "CPU architecture for referencing Docker images with this as a name suffix")
	cmd.PersistentFlags().String(versioniPaaSFlag, "latest", "The version to use for the Fabric8 iPaaS templates")
	cmd.PersistentFlags().String(versionDevOpsFlag, "latest", "The version to use for the Fabric8 DevOps templates")
	cmd.PersistentFlags().String(versionKubeflixFlag, "latest", "The version to use for the Kubeflix templates")
	cmd.PersistentFlags().String(versionZipkinFlag, "latest", "The version to use for the Zipkin templates")
	cmd.PersistentFlags().String(mavenRepoFlag, "https://repo1.maven.org/maven2/", "The maven repo used to find releases of fabric8")
	cmd.PersistentFlags().String(dockerRegistryFlag, "", "The docker registry used to download fabric8 images. Typically used to point to a staging registry")
	cmd.PersistentFlags().String(runFlag, "cd-pipeline", "The name of the fabric8 app to startup. e.g. use `--app=cd-pipeline` to run the main CI/CD pipeline app")
	cmd.PersistentFlags().Bool(pvFlag, true, "Enable the use of persistence (Not currently supported on the CDK)")
	cmd.PersistentFlags().Bool(noPVFlag, false, "(Deprecated use --pv=false to disable instead) Disable the use of persistence (disabling the PersistentVolumeClaims)?")
	cmd.PersistentFlags().Bool(templatesFlag, true, "Should the standard Fabric8 templates be installed?")
	cmd.PersistentFlags().Bool(consoleFlag, true, "Should the Fabric8 console be deployed?")
	cmd.PersistentFlags().Bool(useIngressFlag, true, "Should Ingress NGINX controller be enabled by default when deploying to Kubernetes?")
	cmd.PersistentFlags().Bool(useLoadbalancerFlag, false, "Should Cloud Provider LoadBalancer be used to expose services when running to Kubernetes? (overrides ingress)")

	return cmd
}