func describeProjectAndServer(f formatter, project *projectapi.Project, server string) string { if len(server) == 0 { return fmt.Sprintf("In project %s on server %s\n", projectapi.DisplayNameAndNameForProject(project), server) } return fmt.Sprintf("In project %s on server %s\n", projectapi.DisplayNameAndNameForProject(project), server) }
func describeProjectAndServer(project *projectapi.Project, server string) string { if server != "" { return fmt.Sprintf("In project %s on server %s\n", projectapi.DisplayNameAndNameForProject(project), server) } else { return fmt.Sprintf("In project %s\n", projectapi.DisplayNameAndNameForProject(project)) } }
// Describe returns the description of a project func (d *ProjectStatusDescriber) Describe(namespace, name string) (string, error) { g, err := d.MakeGraph(namespace) if err != nil { return "", err } project, err := d.C.Projects().Get(namespace) if err != nil { return "", err } coveredNodes := graphview.IntSet{} services, coveredByServices := graphview.AllServiceGroups(g, coveredNodes) coveredNodes.Insert(coveredByServices.List()...) standaloneDCs, coveredByDCs := graphview.AllDeploymentConfigPipelines(g, coveredNodes) coveredNodes.Insert(coveredByDCs.List()...) standaloneBCs, coveredByBCs := graphview.AllImagePipelinesFromBuildConfig(g, coveredNodes) coveredNodes.Insert(coveredByBCs.List()...) return tabbedString(func(out *tabwriter.Writer) error { indent := " " fmt.Fprintf(out, "In project %s\n", projectapi.DisplayNameAndNameForProject(project)) for _, service := range services { fmt.Fprintln(out) printLines(out, indent, 0, describeServiceInServiceGroup(service)...) for _, dcPipeline := range service.DeploymentConfigPipelines { printLines(out, indent, 1, describeDeploymentInServiceGroup(dcPipeline)...) } } for _, standaloneDC := range standaloneDCs { fmt.Fprintln(out) printLines(out, indent, 0, describeDeploymentInServiceGroup(standaloneDC)...) } for _, standaloneBC := range standaloneBCs { fmt.Fprintln(out) printLines(out, indent, 0, describeStandaloneBuildGroup(standaloneBC, namespace)...) printLines(out, indent, 1, describeAdditionalBuildDetail(standaloneBC.Build, true)...) } if (len(services) == 0) && (len(standaloneDCs) == 0) && (len(standaloneBCs) == 0) { fmt.Fprintln(out) fmt.Fprintln(out, "You have no services, deployment configs, or build configs.") fmt.Fprintln(out, "Run 'oc new-app' to create an application.") } else { fmt.Fprintln(out) fmt.Fprintln(out, "To see more, use 'oc describe service <name>' or 'oc describe dc <name>'.") fmt.Fprintln(out, "You can use 'oc get all' to see a list of other objects.") } return nil }) }
// RunProjects lists all projects a user belongs to func (o ProjectsOptions) RunProjects() error { config := o.Config clientCfg := o.ClientConfig out := o.Out var currentProject string currentContext := config.Contexts[config.CurrentContext] if currentContext != nil { currentProject = currentContext.Namespace } var currentProjectExists bool var currentProjectErr error client := o.Client if len(currentProject) > 0 { if _, currentProjectErr := client.Projects().Get(currentProject); currentProjectErr == nil { currentProjectExists = true } } var defaultContextName string if currentContext != nil { defaultContextName = cliconfig.GetContextNickname(currentContext.Namespace, currentContext.Cluster, currentContext.AuthInfo) } var msg string projects, err := getProjects(client) if err == nil { switch len(projects) { case 0: msg += "You are not a member of any projects. You can request a project to be created with the 'new-project' command." case 1: if o.DisplayShort { msg += fmt.Sprintf("%s", api.DisplayNameAndNameForProject(&projects[0])) } else { msg += fmt.Sprintf("You have one project on this server: %q.", api.DisplayNameAndNameForProject(&projects[0])) } default: asterisk := "" count := 0 if !o.DisplayShort { msg += fmt.Sprintf("You have access to the following projects and can switch between them with '%s project <projectname>':\n", o.CommandName) } sort.Sort(SortByProjectName(projects)) for _, project := range projects { count = count + 1 displayName := project.Annotations["openshift.io/display-name"] linebreak := "\n" if len(displayName) == 0 { displayName = project.Annotations["displayName"] } if currentProjectExists && !o.DisplayShort { asterisk = " " if currentProject == project.Name { asterisk = " * " } } if len(displayName) > 0 && displayName != project.Name && !o.DisplayShort { msg += fmt.Sprintf("\n"+asterisk+"%s - %s", project.Name, displayName) } else { if o.DisplayShort && count == 1 { linebreak = "" } msg += fmt.Sprintf(linebreak+asterisk+"%s", project.Name) } } } fmt.Println(msg) if len(projects) > 0 && !o.DisplayShort { if !currentProjectExists { if clientcmd.IsForbidden(currentProjectErr) { fmt.Printf("You do not have rights to view project %q. Please switch to an existing one.\n", currentProject) } return currentProjectErr } // if they specified a project name and got a generated context, then only show the information they care about. They won't recognize // a context name they didn't choose if config.CurrentContext == defaultContextName { fmt.Fprintf(out, "\nUsing project %q on server %q.\n", currentProject, clientCfg.Host) } else { fmt.Fprintf(out, "\nUsing project %q from context named %q on server %q.\n", currentProject, config.CurrentContext, clientCfg.Host) } } return nil } return err }
// RunProject contains all the necessary functionality for the OpenShift cli project command func (o ProjectOptions) RunProject() error { config := o.Config clientCfg := o.ClientConfig out := o.Out // No argument provided, we will just print info if len(o.ProjectName) == 0 { currentContext := config.Contexts[config.CurrentContext] currentProject := currentContext.Namespace if len(currentProject) > 0 { if o.DisplayShort { fmt.Fprintln(out, currentProject) return nil } _, err := o.Client.Projects().Get(currentProject) if err != nil { if kapierrors.IsNotFound(err) { return fmt.Errorf("the project %q specified in your config does not exist.", currentProject) } if clientcmd.IsForbidden(err) { return fmt.Errorf("you do not have rights to view project %q.", currentProject) } return err } if config.CurrentContext != currentProject { if len(currentProject) > 0 { fmt.Fprintf(out, "Using project %q from context named %q on server %q.\n", currentProject, config.CurrentContext, clientCfg.Host) } else { fmt.Fprintf(out, "Using context named %q on server %q.\n", config.CurrentContext, clientCfg.Host) } } else { fmt.Fprintf(out, "Using project %q on server %q.\n", currentProject, clientCfg.Host) } } else { if o.DisplayShort { return fmt.Errorf("no project has been set") } fmt.Fprintf(out, "No project has been set. Pass a project name to make that the default.\n") } return nil } // We have an argument that can be either a context or project argument := o.ProjectName contextInUse := "" namespaceInUse := "" contextNameIsGenerated := false // Check if argument is an existing context, if so just set it as the context in use. // If not a context then we will try to handle it as a project. if context, contextExists := config.Contexts[argument]; !o.ProjectOnly && contextExists { contextInUse = argument namespaceInUse = context.Namespace config.CurrentContext = argument } else { if !o.SkipAccessValidation { _, err := o.Client.Projects().Get(argument) if err != nil { if isNotFound, isForbidden := kapierrors.IsNotFound(err), clientcmd.IsForbidden(err); isNotFound || isForbidden { var msg string if isForbidden { msg = fmt.Sprintf("You are not a member of project %q.", argument) } else { msg = fmt.Sprintf("A project named %q does not exist on %q.", argument, clientCfg.Host) } projects, err := getProjects(o.Client) if err == nil { switch len(projects) { case 0: msg += "\nYou are not a member of any projects. You can request a project to be created with the 'new-project' command." case 1: msg += fmt.Sprintf("\nYou have one project on this server: %s", api.DisplayNameAndNameForProject(&projects[0])) default: msg += "\nYour projects are:" for _, project := range projects { msg += fmt.Sprintf("\n* %s", api.DisplayNameAndNameForProject(&project)) } } } if hasMultipleServers(config) { msg += "\nTo see projects on another server, pass '--server=<server>'." } return errors.New(msg) } return err } } projectName := argument kubeconfig, err := cliconfig.CreateConfig(projectName, o.ClientConfig) if err != nil { return err } merged, err := cliconfig.MergeConfig(config, *kubeconfig) if err != nil { return err } config = *merged namespaceInUse = projectName contextInUse = merged.CurrentContext contextNameIsGenerated = true } if err := kubecmdconfig.ModifyConfig(o.PathOptions, config, true); err != nil { return err } if o.DisplayShort { fmt.Fprintln(out, namespaceInUse) return nil } if contextInUse != namespaceInUse && !contextNameIsGenerated { if len(namespaceInUse) > 0 { fmt.Fprintf(out, "Now using project %q from context named %q on server %q.\n", namespaceInUse, contextInUse, clientCfg.Host) } else { fmt.Fprintf(out, "Now using context named %q on server %q.\n", contextInUse, clientCfg.Host) } } else { fmt.Fprintf(out, "Now using project %q on server %q.\n", namespaceInUse, clientCfg.Host) } return nil }
// RunProject contains all the necessary functionality for the OpenShift cli project command func (o ProjectOptions) RunProject() error { config := o.Config clientCfg := o.ClientConfig out := o.Out // No argument provided, we will just print info if len(o.ProjectName) == 0 { currentContext := config.Contexts[config.CurrentContext] currentProject := currentContext.Namespace if len(currentProject) > 0 { if o.DisplayShort { fmt.Fprintln(out, currentProject) return nil } _, err := o.Client.Projects().Get(currentProject) if err != nil { if kapierrors.IsNotFound(err) { return fmt.Errorf("the project %q specified in your config does not exist.", currentProject) } if clientcmd.IsForbidden(err) { return fmt.Errorf("you do not have rights to view project %q.", currentProject) } return err } defaultContextName := cliconfig.GetContextNickname(currentContext.Namespace, currentContext.Cluster, currentContext.AuthInfo) // if they specified a project name and got a generated context, then only show the information they care about. They won't recognize // a context name they didn't choose if config.CurrentContext == defaultContextName { fmt.Fprintf(out, "Using project %q on server %q.\n", currentProject, clientCfg.Host) } else { fmt.Fprintf(out, "Using project %q from context named %q on server %q.\n", currentProject, config.CurrentContext, clientCfg.Host) } } else { if o.DisplayShort { return fmt.Errorf("no project has been set") } fmt.Fprintf(out, "No project has been set. Pass a project name to make that the default.\n") } return nil } // We have an argument that can be either a context or project argument := o.ProjectName contextInUse := "" namespaceInUse := "" // Check if argument is an existing context, if so just set it as the context in use. // If not a context then we will try to handle it as a project. if context, contextExists := config.Contexts[argument]; !o.ProjectOnly && contextExists { contextInUse = argument namespaceInUse = context.Namespace config.CurrentContext = argument } else { if !o.SkipAccessValidation { _, err := o.Client.Projects().Get(argument) if err != nil { if isNotFound, isForbidden := kapierrors.IsNotFound(err), clientcmd.IsForbidden(err); isNotFound || isForbidden { var msg string if isForbidden { msg = fmt.Sprintf("You are not a member of project %q.", argument) } else { msg = fmt.Sprintf("A project named %q does not exist on %q.", argument, clientCfg.Host) } projects, err := getProjects(o.Client) if err == nil { switch len(projects) { case 0: msg += "\nYou are not a member of any projects. You can request a project to be created with the 'new-project' command." case 1: msg += fmt.Sprintf("\nYou have one project on this server: %s", api.DisplayNameAndNameForProject(&projects[0])) default: msg += "\nYour projects are:" for _, project := range projects { msg += fmt.Sprintf("\n* %s", api.DisplayNameAndNameForProject(&project)) } } } if hasMultipleServers(config) { msg += "\nTo see projects on another server, pass '--server=<server>'." } return errors.New(msg) } return err } } projectName := argument kubeconfig, err := cliconfig.CreateConfig(projectName, o.ClientConfig) if err != nil { return err } merged, err := cliconfig.MergeConfig(config, *kubeconfig) if err != nil { return err } config = *merged namespaceInUse = projectName contextInUse = merged.CurrentContext } if err := kubecmdconfig.ModifyConfig(o.PathOptions, config, true); err != nil { return err } if o.DisplayShort { fmt.Fprintln(out, namespaceInUse) return nil } // calculate what name we'd generate for the context. If the context has the same name, don't drop it into the output, because the user won't // recognize the name since they didn't choose it. defaultContextName := cliconfig.GetContextNickname(namespaceInUse, config.Contexts[contextInUse].Cluster, config.Contexts[contextInUse].AuthInfo) switch { // if there is no namespace, then the only information we can provide is the context and server case (len(namespaceInUse) == 0): fmt.Fprintf(out, "Now using context named %q on server %q.\n", contextInUse, clientCfg.Host) // if they specified a project name and got a generated context, then only show the information they care about. They won't recognize // a context name they didn't choose case (argument == namespaceInUse) && (contextInUse == defaultContextName): fmt.Fprintf(out, "Now using project %q on server %q.\n", namespaceInUse, clientCfg.Host) // in all other cases, display all information default: fmt.Fprintf(out, "Now using project %q from context named %q on server %q.\n", namespaceInUse, contextInUse, clientCfg.Host) } return nil }
// Describe returns the description of a project func (d *ProjectStatusDescriber) Describe(namespace, name string) (string, error) { g, err := d.MakeGraph(namespace) if err != nil { return "", err } project, err := d.C.Projects().Get(namespace) if err != nil { return "", err } coveredNodes := graphview.IntSet{} services, coveredByServices := graphview.AllServiceGroups(g, coveredNodes) coveredNodes.Insert(coveredByServices.List()...) standaloneDCs, coveredByDCs := graphview.AllDeploymentConfigPipelines(g, coveredNodes) coveredNodes.Insert(coveredByDCs.List()...) standaloneRCs, coveredByRCs := graphview.AllReplicationControllers(g, coveredNodes) coveredNodes.Insert(coveredByRCs.List()...) standaloneImages, coveredByImages := graphview.AllImagePipelinesFromBuildConfig(g, coveredNodes) coveredNodes.Insert(coveredByImages.List()...) return tabbedString(func(out *tabwriter.Writer) error { indent := " " fmt.Fprintf(out, "In project %s\n", projectapi.DisplayNameAndNameForProject(project)) for _, service := range services { fmt.Fprintln(out) printLines(out, indent, 0, describeServiceInServiceGroup(service)...) for _, dcPipeline := range service.DeploymentConfigPipelines { printLines(out, indent, 1, describeDeploymentInServiceGroup(dcPipeline)...) } rcNode: for _, rcNode := range service.FulfillingRCs { for _, coveredDC := range service.FulfillingDCs { if deployedges.BelongsToDeploymentConfig(coveredDC.DeploymentConfig, rcNode.ReplicationController) { continue rcNode } } printLines(out, indent, 1, describeRCInServiceGroup(rcNode)...) } pod: for _, podNode := range service.FulfillingPods { // skip pods that have been displayed in a roll-up of RCs and DCs (by implicit usage of RCs) for _, coveredRC := range service.FulfillingRCs { if g.Edge(podNode, coveredRC) != nil { continue pod } } printLines(out, indent, 1, describePodInServiceGroup(podNode)...) } } for _, standaloneDC := range standaloneDCs { fmt.Fprintln(out) printLines(out, indent, 0, describeDeploymentInServiceGroup(standaloneDC)...) } for _, standaloneImage := range standaloneImages { fmt.Fprintln(out) printLines(out, indent, 0, describeStandaloneBuildGroup(standaloneImage, namespace)...) printLines(out, indent, 1, describeAdditionalBuildDetail(standaloneImage.Build, standaloneImage.LastSuccessfulBuild, standaloneImage.LastUnsuccessfulBuild, standaloneImage.ActiveBuilds, standaloneImage.DestinationResolved, true)...) } for _, standaloneRC := range standaloneRCs { fmt.Fprintln(out) printLines(out, indent, 0, describeRCInServiceGroup(standaloneRC.RC)...) } // always output warnings fmt.Fprintln(out) allMarkers := osgraph.Markers{} for _, scanner := range getMarkerScanners() { allMarkers = append(allMarkers, scanner(g)...) } sort.Stable(osgraph.ByKey(allMarkers)) sort.Stable(osgraph.ByNodeID(allMarkers)) if errorMarkers := allMarkers.BySeverity(osgraph.ErrorSeverity); len(errorMarkers) > 0 { fmt.Fprintln(out, "Errors:") for _, marker := range errorMarkers { fmt.Fprintln(out, indent+marker.Message) } } if warningMarkers := allMarkers.BySeverity(osgraph.WarningSeverity); len(warningMarkers) > 0 { fmt.Fprintln(out, "Warnings:") for _, marker := range warningMarkers { fmt.Fprintln(out, indent+marker.Message) } } if (len(services) == 0) && (len(standaloneDCs) == 0) && (len(standaloneImages) == 0) { fmt.Fprintln(out, "You have no services, deployment configs, or build configs.") fmt.Fprintln(out, "Run 'oc new-app' to create an application.") } else { fmt.Fprintln(out, "To see more, use 'oc describe service <name>' or 'oc describe dc <name>'.") fmt.Fprintln(out, "You can use 'oc get all' to see a list of other objects.") } return nil }) }
// Describe returns the description of a project func (d *ProjectStatusDescriber) Describe(namespace, name string) (string, error) { g, err := d.MakeGraph(namespace) if err != nil { return "", err } project, err := d.C.Projects().Get(namespace) if err != nil { return "", err } coveredNodes := graphview.IntSet{} services, coveredByServices := graphview.AllServiceGroups(g, coveredNodes) coveredNodes.Insert(coveredByServices.List()...) standaloneDCs, coveredByDCs := graphview.AllDeploymentConfigPipelines(g, coveredNodes) coveredNodes.Insert(coveredByDCs.List()...) standaloneRCs, coveredByRCs := graphview.AllReplicationControllers(g, coveredNodes) coveredNodes.Insert(coveredByRCs.List()...) standaloneImages, coveredByImages := graphview.AllImagePipelinesFromBuildConfig(g, coveredNodes) coveredNodes.Insert(coveredByImages.List()...) return tabbedString(func(out *tabwriter.Writer) error { indent := " " fmt.Fprintf(out, "In project %s\n", projectapi.DisplayNameAndNameForProject(project)) for _, service := range services { fmt.Fprintln(out) printLines(out, indent, 0, describeServiceInServiceGroup(service)...) for _, dcPipeline := range service.DeploymentConfigPipelines { printLines(out, indent, 1, describeDeploymentInServiceGroup(dcPipeline)...) } rcNode: for _, rcNode := range service.FulfillingRCs { for _, coveredDC := range service.FulfillingDCs { if deployedges.BelongsToDeploymentConfig(coveredDC.DeploymentConfig, rcNode.ReplicationController) { continue rcNode } } printLines(out, indent, 1, describeRCInServiceGroup(rcNode)...) } pod: for _, podNode := range service.FulfillingPods { // skip pods that have been displayed in a roll-up of RCs and DCs (by implicit usage of RCs) for _, coveredRC := range service.FulfillingRCs { if g.EdgeBetween(podNode, coveredRC) != nil { continue pod } } printLines(out, indent, 1, describePodInServiceGroup(podNode)...) } } for _, standaloneDC := range standaloneDCs { fmt.Fprintln(out) printLines(out, indent, 0, describeDeploymentInServiceGroup(standaloneDC)...) } for _, standaloneImage := range standaloneImages { fmt.Fprintln(out) printLines(out, indent, 0, describeStandaloneBuildGroup(standaloneImage, namespace)...) printLines(out, indent, 1, describeAdditionalBuildDetail(standaloneImage.Build, standaloneImage.LastSuccessfulBuild, standaloneImage.LastUnsuccessfulBuild, standaloneImage.ActiveBuilds, standaloneImage.DestinationResolved, true)...) } for _, standaloneRC := range standaloneRCs { fmt.Fprintln(out) printLines(out, indent, 0, describeRCInServiceGroup(standaloneRC.RC)...) } if (len(services) == 0) && (len(standaloneDCs) == 0) && (len(standaloneImages) == 0) { fmt.Fprintln(out) fmt.Fprintln(out, "You have no services, deployment configs, or build configs.") fmt.Fprintln(out, "Run 'oc new-app' to create an application.") } else { fmt.Fprintln(out) if hasUnresolvedImageStreamTag(g) { fmt.Fprintln(out, "Warning: Some of your builds are pointing to image streams, but the administrator has not configured the integrated Docker registry (oadm registry).") } if lines, _ := describeBadPodSpecs(out, g); len(lines) > 0 { fmt.Fprintln(out, strings.Join(lines, "\n")) } fmt.Fprintln(out, "To see more, use 'oc describe service <name>' or 'oc describe dc <name>'.") fmt.Fprintln(out, "You can use 'oc get all' to see a list of other objects.") } return nil }) }
// Describe returns the description of a project func (d *ProjectStatusDescriber) Describe(namespace, name string) (string, error) { project, err := d.C.Projects().Get(namespace) if err != nil { return "", err } svcs, err := d.K.Services(namespace).List(labels.Everything()) if err != nil { return "", err } bcs, err := d.C.BuildConfigs(namespace).List(labels.Everything(), fields.Everything()) if err != nil { return "", err } dcs, err := d.C.DeploymentConfigs(namespace).List(labels.Everything(), fields.Everything()) if err != nil { return "", err } builds := &buildapi.BuildList{} if len(bcs.Items) > 0 { if b, err := d.C.Builds(namespace).List(labels.Everything(), fields.Everything()); err == nil { builds = b } } rcs, err := d.K.ReplicationControllers(namespace).List(labels.Everything()) if err != nil { rcs = &kapi.ReplicationControllerList{} } g := graph.New() for i := range bcs.Items { build := buildgraph.EnsureBuildConfigNode(g, &bcs.Items[i]) buildedges.AddInputOutputEdges(g, build) buildedges.JoinBuilds(build, builds.Items) } for i := range dcs.Items { deploy := deploygraph.EnsureDeploymentConfigNode(g, &dcs.Items[i]) deployedges.AddTriggerEdges(g, deploy) deployedges.JoinDeployments(deploy, rcs.Items) } for i := range svcs.Items { service := kubegraph.EnsureServiceNode(g, &svcs.Items[i]) kubeedges.AddExposedPodTemplateSpecEdges(g, service) } groups := graphveneers.ServiceAndDeploymentGroups(g) return tabbedString(func(out *tabwriter.Writer) error { indent := " " fmt.Fprintf(out, "In project %s\n", projectapi.DisplayNameAndNameForProject(project)) for _, group := range groups { if len(group.Builds) != 0 { for _, build := range group.Builds { fmt.Fprintln(out) printLines(out, indent, 0, describeStandaloneBuildGroup(build, namespace)...) printLines(out, indent, 1, describeAdditionalBuildDetail(build.Build, true)...) } continue } if len(group.Services) == 0 { for _, deploy := range group.Deployments { fmt.Fprintln(out) printLines(out, indent, 0, describeDeploymentInServiceGroup(deploy)...) } continue } fmt.Fprintln(out) for _, svc := range group.Services { printLines(out, indent, 0, describeServiceInServiceGroup(svc)...) } for _, deploy := range group.Deployments { printLines(out, indent, 1, describeDeploymentInServiceGroup(deploy)...) } } if len(groups) == 0 { fmt.Fprintln(out, "\nYou have no Services, DeploymentConfigs, or BuildConfigs. 'oc new-app' can be used to create applications from scratch from existing Docker images and templates.") } else { fmt.Fprintln(out, "\nTo see more information about a Service or DeploymentConfig, use 'oc describe service <name>' or 'oc describe dc <name>'.") fmt.Fprintln(out, "You can use 'oc get all' to see lists of each of the types described above.") } return nil }) }
// Describe returns the description of a project func (d *ProjectStatusDescriber) Describe(namespace, name string) (string, error) { g, err := d.MakeGraph(namespace) if err != nil { return "", err } project, err := d.C.Projects().Get(namespace) if err != nil { return "", err } coveredNodes := graphview.IntSet{} services, coveredByServices := graphview.AllServiceGroups(g, coveredNodes) coveredNodes.Insert(coveredByServices.List()...) standaloneDCs, coveredByDCs := graphview.AllDeploymentConfigPipelines(g, coveredNodes) coveredNodes.Insert(coveredByDCs.List()...) standaloneImages, coveredByImages := graphview.AllImagePipelinesFromBuildConfig(g, coveredNodes) coveredNodes.Insert(coveredByImages.List()...) return tabbedString(func(out *tabwriter.Writer) error { indent := " " fmt.Fprintf(out, "In project %s\n", projectapi.DisplayNameAndNameForProject(project)) for _, service := range services { fmt.Fprintln(out) printLines(out, indent, 0, describeServiceInServiceGroup(service)...) for _, dcPipeline := range service.DeploymentConfigPipelines { printLines(out, indent, 1, describeDeploymentInServiceGroup(dcPipeline)...) } } for _, standaloneDC := range standaloneDCs { fmt.Fprintln(out) printLines(out, indent, 0, describeDeploymentInServiceGroup(standaloneDC)...) } for _, standaloneImage := range standaloneImages { fmt.Fprintln(out) printLines(out, indent, 0, describeStandaloneBuildGroup(standaloneImage, namespace)...) printLines(out, indent, 1, describeAdditionalBuildDetail(standaloneImage.Build, standaloneImage.LastSuccessfulBuild, standaloneImage.LastUnsuccessfulBuild, standaloneImage.ActiveBuilds, standaloneImage.DestinationResolved, true)...) } if (len(services) == 0) && (len(standaloneDCs) == 0) && (len(standaloneImages) == 0) { fmt.Fprintln(out) fmt.Fprintln(out, "You have no services, deployment configs, or build configs.") fmt.Fprintln(out, "Run 'oc new-app' to create an application.") } else { fmt.Fprintln(out) if hasUnresolvedImageStreamTag(g) { fmt.Fprintln(out, "Warning: Some of your builds are pointing to image streams, but the administrator has not configured the integrated Docker registry (oadm registry).") } fmt.Fprintln(out, "To see more, use 'oc describe service <name>' or 'oc describe dc <name>'.") fmt.Fprintln(out, "You can use 'oc get all' to see a list of other objects.") } return nil }) }