Example #1
0
func describeGeneratedJob(out io.Writer, ref app.ComponentReference, pod *kapi.Pod, secret *kapi.Secret, baseNamespace string) {
	refInput := ref.Input()
	generatorInput := refInput.ResolvedMatch.GeneratorInput
	hasToken := generatorInput.Token != nil

	fmt.Fprintf(out, "--> Installing application from %q\n", refInput)
	if locatedImage := describeLocatedImage(refInput, baseNamespace); len(locatedImage) > 0 {
		fmt.Fprintf(out, "    * %s\n", locatedImage)
	}

	fmt.Fprintf(out, "    * Install will run in pod %q\n", localOrRemoteName(pod.ObjectMeta, baseNamespace))
	switch {
	case secret != nil:
		fmt.Fprintf(out, "    * The pod has access to your current session token through the secret %q\n", localOrRemoteName(secret.ObjectMeta, baseNamespace))
		fmt.Fprintf(out, "    * If you cancel the install, you should delete the secret or log out of your session\n")
	case hasToken && generatorInput.Token.Env != nil:
		fmt.Fprintf(out, "    * The pod has access to your current session token via environment variable %s\n", *generatorInput.Token.Env)
		fmt.Fprintf(out, "    * If you cancel the install, you should delete the pod or log out of your session\n")
	case hasToken:
		fmt.Fprintf(out, "    * The pod has access to your current session token. Please delete the pod if you cancel the install\n")
	}
	if hasToken {
		fmt.Fprintf(out, "--> WARNING: The pod requires access to your current session token to install this image. Only\n")
		fmt.Fprintf(out, "      grant access to images whose source you trust. The image will be able to perform any\n")
		fmt.Fprintf(out, "      action you can take on the cluster.\n")
	}
}
Example #2
0
func describeGeneratedTemplate(out io.Writer, ref app.ComponentReference, result *templateapi.Template, baseNamespace string) {
	fmt.Fprintf(out, "--> Deploying template %s for %q\n", localOrRemoteName(ref.Input().ResolvedMatch.Template.ObjectMeta, baseNamespace), ref.Input())
	if len(result.Parameters) > 0 {
		fmt.Fprintf(out, "     With parameters:\n")
		for _, p := range result.Parameters {
			name := p.DisplayName
			if len(name) == 0 {
				name = p.Name
			}
			var generated string
			if len(p.Generate) > 0 {
				generated = " # generated"
			}
			fmt.Fprintf(out, "      %s=%s%s\n", name, p.Value, generated)
		}
	}
}
Example #3
0
func describeGeneratedJob(out io.Writer, ref app.ComponentReference, pod *kapi.Pod, secret *kapi.Secret, baseNamespace string) {
	refInput := ref.Input()
	generatorInput := refInput.ResolvedMatch.GeneratorInput
	hasToken := generatorInput.Token != nil

	fmt.Fprintf(out, "--> Installing application from %q\n", refInput)
	if locatedImage := describeLocatedImage(refInput, baseNamespace); len(locatedImage) > 0 {
		fmt.Fprintf(out, "    * %s\n", locatedImage)
	}

	fmt.Fprintf(out, "    * Install will run in pod %s\n", localOrRemoteName(pod.ObjectMeta, baseNamespace))
	switch {
	case secret != nil:
		fmt.Fprintf(out, "    * The pod has access to your current session token through the secret %s.\n", localOrRemoteName(secret.ObjectMeta, baseNamespace))
		fmt.Fprintf(out, "      If you cancel the install, you should delete the secret or log out of your session.\n")
	case hasToken && generatorInput.Token.Env != nil:
		fmt.Fprintf(out, "    * The pod has access to your current session token via environment variable %s.\n", *generatorInput.Token.Env)
		fmt.Fprintf(out, "      If you cancel the install, you should delete the pod or log out of your session.\n")
	case hasToken && generatorInput.Token.ServiceAccount:
		fmt.Fprintf(out, "    * The pod will use the 'installer' service account. If this account does not exist\n")
		fmt.Fprintf(out, "      with sufficient permissions, you may need to ask a project admin set it up.\n")
	case hasToken:
		fmt.Fprintf(out, "    * The pod has access to your current session token. Please delete the pod if you cancel the install.\n")
	}
	if hasToken {
		if generatorInput.Token.ServiceAccount {
			fmt.Fprintf(out, "--> WARNING: The pod requires access to the 'installer' service account to install this\n")
			fmt.Fprintf(out, "      image. Only grant access to images whose source you trust. The image will be able\n")
			fmt.Fprintf(out, "      to act as an editor within this project.\n")
		} else {
			fmt.Fprintf(out, "--> WARNING: The pod requires access to your current session token to install this image. Only\n")
			fmt.Fprintf(out, "      grant access to images whose source you trust. The image will be able to perform any\n")
			fmt.Fprintf(out, "      action you can take on the cluster.\n")
		}
	}
}
Example #4
0
func describeBuildPipelineWithImage(out io.Writer, ref app.ComponentReference, pipeline *app.Pipeline, baseNamespace string) {
	refInput := ref.Input()
	match := refInput.ResolvedMatch

	if locatedImage := describeLocatedImage(refInput, baseNamespace); len(locatedImage) > 0 {
		fmt.Fprintf(out, "--> %s\n", locatedImage)
	}

	trackedImage := extractFirstImageStreamTag(true, pipeline.InputImage, pipeline.Image)
	if len(trackedImage) > 0 {
		fmt.Fprintf(out, "    * An image stream will be created as %q that will track this image\n", trackedImage)
	}
	if pipeline.Build != nil {
		if refInput.Uses != nil && refInput.Uses.Info() != nil {
			matches := []string{}
			for _, t := range refInput.Uses.Info().Types {
				if len(t.Platform) == 0 {
					continue
				}
				if len(t.Version) > 0 {
					matches = append(matches, fmt.Sprintf("%s %s", t.Platform, t.Version))
				}
				matches = append(matches, t.Platform)
			}
			if len(matches) > 0 {
				fmt.Fprintf(out, "    * The source repository appears to match: %s\n", strings.Join(matches, ", "))
			}
		}
		var strategy string
		if pipeline.Build.Strategy.IsDockerBuild {
			strategy = "Docker"
		} else {
			strategy = "source"
		}
		var source string
		switch s := pipeline.Build.Source; {
		case s.Binary:
			source = "binary input"
		case len(s.DockerfileContents) > 0:
			source = "a predefined Dockerfile"
		case s.URL != nil:
			source = fmt.Sprintf("source code from %s", s.URL)
		default:
			source = "<unknown>"
		}

		fmt.Fprintf(out, "    * A %s build using %s will be created\n", strategy, source)
		if buildOut, err := pipeline.Build.Output.BuildOutput(); err == nil && buildOut != nil && buildOut.To != nil {
			switch to := buildOut.To; {
			case to.Kind == "ImageStreamTag":
				fmt.Fprintf(out, "      * The resulting image will be pushed to image stream %q\n", to.Name)
			case to.Kind == "DockerImage":
				fmt.Fprintf(out, "      * The resulting image will be pushed with Docker to %q\n", to.Name)
			default:
				fmt.Fprintf(out, "      * The resulting image will be pushed to %s %q\n", to.Kind, to.Name)
			}
		}
		if len(trackedImage) > 0 && !pipeline.Build.Source.Binary {
			fmt.Fprintf(out, "      * Every time %q changes a new build will be triggered\n", trackedImage)
		}
	}
	if pipeline.Deployment != nil {
		if len(pipeline.Deployment.Images) > 1 {
			fmt.Fprintf(out, "    * This image will be deployed as part of deployment config %q\n", pipeline.Deployment.Name)
		} else {
			fmt.Fprintf(out, "    * This image will be deployed in deployment config %q\n", pipeline.Deployment.Name)
		}

		if pipeline.Image != nil && pipeline.Image.HasEmptyDir {
			fmt.Fprintf(out, "    * This image declares volumes and will default to use non-persistent, host-local storage.\n")
			fmt.Fprintf(out, "      You can add persistent volumes later by running 'volume dc/%s --add ...'\n", pipeline.Deployment.Name)
		}
	}
	if match.Image != nil {
		if pipeline.Deployment != nil {
			ports := sets.NewString()
			if match.Image.Config != nil {
				for k := range match.Image.Config.ExposedPorts {
					ports.Insert(k)
				}
			}
			switch len(ports) {
			case 0:
				fmt.Fprintf(out, "    * The image does not expose any ports - if you want to load balance or send traffic to this component\n")
				fmt.Fprintf(out, "      you will need to create a service with 'expose dc/%s --port=[port]' later\n", pipeline.Deployment.Name)
			default:
				orderedPorts := ports.List()
				sort.Sort(sort.StringSlice(orderedPorts))
				if len(orderedPorts) == 1 {
					fmt.Fprintf(out, "    * Port %s will be load balanced by service %q\n", orderedPorts[0], pipeline.Deployment.Name)
				} else {
					fmt.Fprintf(out, "    * Ports %s will be load balanced by service %q\n", strings.Join(orderedPorts, ", "), pipeline.Deployment.Name)
				}
			}
		}
	}
}
Example #5
0
func describeBuildPipelineWithImage(out io.Writer, ref app.ComponentReference, pipeline *app.Pipeline, baseNamespace string) {
	refInput := ref.Input()
	match := refInput.ResolvedMatch

	if locatedImage := describeLocatedImage(refInput, baseNamespace); len(locatedImage) > 0 {
		fmt.Fprintf(out, "--> %s\n", locatedImage)
		annotations := inputAnnotations(refInput.ResolvedMatch)
		if desc := annotations["io.k8s.display-name"]; len(desc) > 0 {
			fmt.Fprintln(out)
			fmt.Fprintf(out, "    %s \n", desc)
			fmt.Fprintf(out, "    %s \n", strings.Repeat("-", len(desc)))
		} else {
			fmt.Fprintln(out)
		}
		if desc := annotations["io.k8s.description"]; len(desc) > 0 {
			fmt.Fprintf(out, "    %s\n\n", desc)
		}
		if desc := annotations["io.openshift.tags"]; len(desc) > 0 {
			desc = strings.Join(strings.Split(desc, ","), ", ")
			fmt.Fprintf(out, "    Tags: %s\n\n", desc)
		}
	}

	if pipeline.Build == nil {
		trackedImage := extractFirstImageStreamTag(true, pipeline.InputImage, pipeline.Image)
		if len(trackedImage) > 0 {
			fmt.Fprintf(out, "    * An image stream will be created as %q that will track this image\n", trackedImage)
		}
	} else {
		trackedImage := extractFirstImageStreamTag(true, pipeline.InputImage)
		if len(trackedImage) > 0 {
			fmt.Fprintf(out, "    * An image stream will be created as %q that will track the source image\n", trackedImage)
		}
		if refInput.Uses != nil && refInput.Uses.Info() != nil {
			matches := []string{}
			for _, t := range refInput.Uses.Info().Types {
				if len(t.Platform) == 0 {
					continue
				}
				if len(t.Version) > 0 {
					matches = append(matches, fmt.Sprintf("%s %s", t.Platform, t.Version))
				}
				matches = append(matches, t.Platform)
			}
			if len(matches) > 0 && !pipeline.Build.Strategy.IsDockerBuild {
				fmt.Fprintf(out, "    * The source repository appears to match: %s\n", strings.Join(matches, ", "))
			}
		}
		var strategy string
		if pipeline.Build.Strategy.IsDockerBuild {
			strategy = "Docker"
		} else {
			strategy = "source"
		}
		noSource := false
		var source string
		switch s := pipeline.Build.Source; {
		case s.Binary:
			noSource = true
			source = "binary input"
		case len(s.DockerfileContents) > 0:
			source = "a predefined Dockerfile"
		case s.URL != nil && len(s.URL.Host) > 0:
			source = fmt.Sprintf("source code from %s", s.URL)
		case s.URL != nil:
			noSource = true
			source = "uploaded code"
		default:
			source = "<unknown>"
		}

		fmt.Fprintf(out, "    * A %s build using %s will be created\n", strategy, source)
		if buildOut, err := pipeline.Build.Output.BuildOutput(); err == nil && buildOut != nil && buildOut.To != nil {
			switch to := buildOut.To; {
			case to.Kind == "ImageStreamTag":
				fmt.Fprintf(out, "      * The resulting image will be pushed to image stream %q\n", to.Name)
			case to.Kind == "DockerImage":
				fmt.Fprintf(out, "      * The resulting image will be pushed with Docker to %q\n", to.Name)
			default:
				fmt.Fprintf(out, "      * The resulting image will be pushed to %s %q\n", to.Kind, to.Name)
			}
		}

		if noSource {
			// if we have no source, the user must always provide the source from the local dir(binary build)
			fmt.Fprintf(out, "      * Use 'start-build --from-dir=DIR|--from-repo=DIR|--from-file=FILE' to trigger a new build\n")
			fmt.Fprintf(out, "      * WARNING: a binary build was created, you must specify one of --from-dir|--from-file|--from-repo when starting builds\n")
		} else {
			if len(trackedImage) > 0 {
				// if we have a trackedImage/ICT and we have source, the build will be triggered automatically.
				fmt.Fprintf(out, "      * Every time %q changes a new build will be triggered\n", trackedImage)
			} else {
				// if we have source (but not a tracked image), the user must manually trigger a build.
				fmt.Fprintf(out, "      * Use 'start-build to trigger a new build\n")
			}
		}
	}
	if pipeline.Deployment != nil {
		if pipeline.Deployment.AsTest {
			if len(pipeline.Deployment.Images) > 1 {
				fmt.Fprintf(out, "    * This image will be test deployed as part of deployment config %q\n", pipeline.Deployment.Name)
			} else {
				fmt.Fprintf(out, "    * This image will be test deployed in deployment config %q\n", pipeline.Deployment.Name)
			}
		} else {
			if len(pipeline.Deployment.Images) > 1 {
				fmt.Fprintf(out, "    * This image will be deployed as part of deployment config %q\n", pipeline.Deployment.Name)
			} else {
				fmt.Fprintf(out, "    * This image will be deployed in deployment config %q\n", pipeline.Deployment.Name)
			}
		}
	}
	if match != nil && match.Image != nil {
		if pipeline.Deployment != nil {
			ports := sets.NewString()
			if match.Image.Config != nil {
				for k := range match.Image.Config.ExposedPorts {
					ports.Insert(k)
				}
			}
			switch len(ports) {
			case 0:
				fmt.Fprintf(out, "    * The image does not expose any ports - if you want to load balance or send traffic to this component\n")
				fmt.Fprintf(out, "      you will need to create a service with 'expose dc/%s --port=[port]' later\n", pipeline.Deployment.Name)
			default:
				orderedPorts := ports.List()
				sort.Sort(sort.StringSlice(orderedPorts))
				if len(orderedPorts) == 1 {
					fmt.Fprintf(out, "    * Port %s will be load balanced by service %q\n", orderedPorts[0], pipeline.Deployment.Name)
				} else {
					fmt.Fprintf(out, "    * Ports %s will be load balanced by service %q\n", strings.Join(orderedPorts, ", "), pipeline.Deployment.Name)
				}
				fmt.Fprintf(out, "      * Other containers can access this service through the hostname %q\n", pipeline.Deployment.Name)
			}
			if hasEmptyDir(match.Image) {
				fmt.Fprintf(out, "    * This image declares volumes and will default to use non-persistent, host-local storage.\n")
				fmt.Fprintf(out, "      You can add persistent volumes later by running 'volume dc/%s --add ...'\n", pipeline.Deployment.Name)
			}
			if hasRootUser(match.Image) {
				fmt.Fprintf(out, "    * WARNING: Image %q runs as the 'root' user which may not be permitted by your cluster administrator\n", match.Name)
			}
		}
	}
	fmt.Fprintln(out)
}