public ServiceInstance(Service service) { this.service = service; this.id = getName(service); ServiceSpec spec = KubernetesHelper.getOrCreateSpec(service); List<ServicePort> ports = spec.getPorts(); if (spec.getPortalIP().equals(HEADLESS_PORTAL_IP)) { // do nothing service is headless } else if (ports != null && !ports.isEmpty()) { for (ServicePort servicePort : ports) { servicePorts.add(toNamedServicePort(id, servicePort)); } } else { throw new IllegalArgumentException( "Service: " + id + " doesn't have a valid port configuration."); } this.selector = KubernetesHelper.getSelector(service); Objects.notNull(this.selector, "No selector for service " + id); if (selector.isEmpty()) { throw new IllegalArgumentException("Empty selector for service " + id); } this.filter = KubernetesHelper.createPodFilter(selector); // TODO should we use some service metadata to choose the load balancer? this.loadBalancer = new RoundRobinLoadBalancer(); }
public static List<String> toServiceEndpointUrl(String serviceId, String serviceProtocol) { List<String> endpoints = new ArrayList<>(); String namespace = Systems.getEnvVarOrSystemProperty(KUBERNETES_NAMESPACE, DEFAULT_NAMESPACE); String serviceProto = serviceProtocol != null ? serviceProtocol : DEFAULT_PROTO; try { for (String endpoint : KubernetesHelper.lookupServiceInDns(serviceId)) { endpoints.add(serviceProto + "://" + endpoint); } } catch (UnknownHostException e) { // ignore and fallback to the api. } if (!endpoints.isEmpty()) { return endpoints; } for (io.fabric8.kubernetes.api.model.Endpoints item : KUBERNETES.getEndpoints(namespace).getItems()) { if (item.getMetadata().getName().equals(serviceId) && (namespace == null || namespace.equals(item.getMetadata().getNamespace()))) { for (EndpointSubset subset : item.getSubsets()) { for (EndpointAddress address : subset.getAddresses()) { endpoints.add(serviceProto + "://" + address.getIp()); } } break; } } return endpoints; }
public static void cleanupAllMatching( KubernetesClient client, String key, Session session, List<Throwable> errors) throws MultiException { Map<String, String> labels = Collections.singletonMap(key, session.getId()); Filter<Pod> podFilter = KubernetesHelper.createPodFilter(labels); Filter<Service> serviceFilter = KubernetesHelper.createServiceFilter(labels); Filter<ReplicationController> replicationControllerFilter = KubernetesHelper.createReplicationControllerFilter(labels); /** Lets use a loop to ensure we really do delete all the matching resources */ for (int i = 0; i < 10; i++) { try { deleteReplicationControllers(client, session.getLogger(), replicationControllerFilter); } catch (MultiException e) { errors.addAll(Arrays.asList(e.getCauses())); } try { deletePods(client, session.getLogger(), podFilter); } catch (MultiException e) { errors.addAll(Arrays.asList(e.getCauses())); } try { deleteServices(client, session.getLogger(), serviceFilter); } catch (MultiException e) { errors.addAll(Arrays.asList(e.getCauses())); } // lets see if there are any matching podList left PodList podList = client.getPods(); List<Pod> filteredPods = Filters.filter(notNullList(podList.getItems()), podFilter); if (filteredPods.isEmpty()) { return; } else { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
private static ServicePort toNamedServicePort(String serviceId, ServicePort servicePort) { String portName = servicePort.getName(); String protocol = servicePort.getProtocol(); Integer nodePort = servicePort.getNodePort(); IntOrString targetPort = servicePort.getTargetPort(); String name = !Strings.isNullOrBlank(portName) ? portName : serviceId + "-" + targetPort.toString(); int port = KubernetesHelper.intOrStringToInteger(targetPort, "service: " + name); return new ServicePort(name, nodePort, port, protocol, targetPort); }
@Test public void testParsePodList() throws Exception { KubernetesList podList = assertParseExampleFile("pod-list.json", KubernetesList.class); List<HasMetadata> items = podList.getItems(); assertNotEmpty("items", items); Pod pod = (Pod) items.get(0); assertNotNull("pod1", pod); assertEquals("pod1.name", "my-pod-1", KubernetesHelper.getName(pod)); PodSpec podSpec = pod.getSpec(); assertNotNull("pod1.podSpec", podSpec); List<Container> containers = podSpec.getContainers(); assertNotEmpty("pod1.podSpec.containers", containers); Container container = containers.get(0); assertNotNull("pod1.podSpec.container[0]", container); assertEquals("pod1.podSpec.container[0].name", "nginx", container.getName()); assertEquals("pod1.podSpec.container[0].image", "dockerfile/nginx", container.getImage()); LOG.info("pod1 container1 " + container); String json = KubernetesHelper.toJson(podList); LOG.info("Got JSON: " + json); }
public static void displaySessionStatus(KubernetesClient client, Session session) throws MultiException { Map<String, String> labels = Collections.singletonMap(Constants.ARQ_KEY, session.getId()); Filter<Pod> podFilter = KubernetesHelper.createPodFilter(labels); Filter<Service> serviceFilter = KubernetesHelper.createServiceFilter(labels); Filter<ReplicationController> replicationControllerFilter = KubernetesHelper.createReplicationControllerFilter(labels); for (ReplicationController replicationController : client.getReplicationControllers().getItems()) { if (replicationControllerFilter.matches(replicationController)) { session.getLogger().info("Replication controller:" + getId(replicationController)); } } for (Pod pod : client.getPods().getItems()) { if (podFilter.matches(pod)) { session .getLogger() .info("Pod:" + getId(pod) + " Status:" + pod.getCurrentState().getStatus()); } } for (Service service : client.getServices().getItems()) { if (serviceFilter.matches(service)) { session .getLogger() .info( "Service:" + getId(service) + " IP:" + getPortalIP(service) + " Port:" + getPort(service)); } } }
protected static void listPods(Kubernetes kube) { System.out.println("Looking up pods"); PodList pods = kube.getPods(Kubernetes.NAMESPACE_ALL); // System.out.println("Got pods: " + pods); List<Pod> items = pods.getItems(); for (Pod item : items) { System.out.println("Pod " + getId(item) + " created: " + item.getCreationTimestamp()); PodState desiredState = item.getDesiredState(); if (desiredState != null) { ContainerManifest manifest = desiredState.getManifest(); if (manifest != null) { List<Container> containers = manifest.getContainers(); if (containers != null) { for (Container container : containers) { System.out.println( "Container " + container.getImage() + " " + container.getCommand() + " ports: " + container.getPorts()); } } } } Map<String, ContainerStatus> currentContainers = KubernetesHelper.getCurrentContainers(item); System.out.println("Has " + currentContainers.size() + " container(s)"); Set<Map.Entry<String, ContainerStatus>> entries = currentContainers.entrySet(); for (Map.Entry<String, ContainerStatus> entry : entries) { String id = entry.getKey(); ContainerStatus info = entry.getValue(); System.out.println("Current container: " + id + " info: " + info); } } System.out.println(); }
public class DevOpsEditStep extends AbstractDevOpsCommand implements UIWizardStep { private static final transient Logger LOG = LoggerFactory.getLogger(DevOpsEditStep.class); private static final String DEFAULT_MAVEN_FLOW = "workflows/maven/CanaryReleaseStageAndApprovePromote.groovy"; public static final String JENKINSFILE = "Jenkinsfile"; private String jenkinsFilePrefix = "workflows/"; @Inject @WithAttributes( label = "Pipeline", required = false, description = "The Jenkinsfile used to define the Continous Delivery pipeline") private UIInput<PipelineDTO> pipeline; @Inject @WithAttributes( label = "Copy pipeline to project", required = false, description = "Should we copy the pipeline definition (in the Jenkinsfile) into the project source code") private UIInput<Boolean> copyPipelineToProject; @Inject @WithAttributes( label = "Chat room", required = false, description = "Name of chat room to use for this project") private UIInput<String> chatRoom; @Inject @WithAttributes( label = "IssueTracker Project name", required = false, description = "Name of the issue tracker project") private UIInput<String> issueProjectName; @Inject @WithAttributes( label = "Code review", required = false, description = "Enable code review of all commits") private UIInput<Boolean> codeReview; private String namespace = KubernetesHelper.defaultNamespace(); private LetsChatClient letsChat; private TaigaClient taiga; private List<InputComponent> inputComponents; @Override public UICommandMetadata getMetadata(UIContext context) { return Metadata.forCommand(getClass()) .category(Categories.create(AbstractDevOpsCommand.CATEGORY)) .name(AbstractDevOpsCommand.CATEGORY + ": Configure") .description("Configure the Pipeline for the new project"); } @Override public void initializeUI(UIBuilder builder) throws Exception { final UIContext context = builder.getUIContext(); copyPipelineToProject.setValue(Boolean.TRUE); pipeline.setCompleter( new UICompleter<PipelineDTO>() { @Override public Iterable<PipelineDTO> getCompletionProposals( UIContext context, InputComponent<?, PipelineDTO> input, String value) { return getPipelines(context, true); } }); pipeline.setValueConverter( new Converter<String, PipelineDTO>() { @Override public PipelineDTO convert(String text) { return getPipelineForValue(context, text); } }); pipeline.addValueChangeListener( new ValueChangeListener() { @Override public void valueChanged(ValueChangeEvent event) { String value = event.getNewValue() != null ? event.getNewValue().toString() : null; if (value != null) { String description = getDescriptionForFlow(value); pipeline.setNote(description != null ? description : ""); } else { pipeline.setNote(""); } boolean canCopy = Strings.isNotBlank(value); copyPipelineToProject.setEnabled(canCopy); } }); if (getCurrentSelectedProject(context) != null) { PipelineDTO defaultValue = getPipelineForValue(context, DEFAULT_MAVEN_FLOW); if (defaultValue != null) { pipeline.setDefaultValue(defaultValue); pipeline.setValue(defaultValue); } } chatRoom.setCompleter( new UICompleter<String>() { @Override public Iterable<String> getCompletionProposals( UIContext context, InputComponent<?, String> input, String value) { return filterCompletions(getChatRoomNames(), value); } }); chatRoom.addValueChangeListener( new ValueChangeListener() { @Override public void valueChanged(ValueChangeEvent event) { String value = event.getNewValue() != null ? event.getNewValue().toString() : null; if (value != null) { String description = getDescriptionForChatRoom(value); chatRoom.setNote(description != null ? description : ""); } else { chatRoom.setNote(""); } } }); issueProjectName.setCompleter( new UICompleter<String>() { @Override public Iterable<String> getCompletionProposals( UIContext context, InputComponent<?, String> input, String value) { return filterCompletions(getIssueProjectNames(), value); } }); issueProjectName.addValueChangeListener( new ValueChangeListener() { @Override public void valueChanged(ValueChangeEvent event) { String value = event.getNewValue() != null ? event.getNewValue().toString() : null; if (value != null) { String description = getDescriptionForIssueProject(value); issueProjectName.setNote(description != null ? description : ""); } else { issueProjectName.setNote(""); } } }); // lets initialise the data from the current config if it exists ProjectConfig config = null; Project project = getCurrentSelectedProject(context); File configFile = getProjectConfigFile(context, getSelectedProject(context)); if (configFile != null && configFile.exists()) { config = ProjectConfigs.parseProjectConfig(configFile); } if (config != null) { PipelineDTO flow = getPipelineForValue(context, config.getPipeline()); if (flow != null) { CommandHelpers.setInitialComponentValue(this.pipeline, flow); } CommandHelpers.setInitialComponentValue(chatRoom, config.getChatRoom()); CommandHelpers.setInitialComponentValue(issueProjectName, config.getIssueProjectName()); CommandHelpers.setInitialComponentValue(codeReview, config.getCodeReview()); } inputComponents = new ArrayList<>(); File jenkinsFile = CommandHelpers.getProjectContextFile(context, project, "Jenkinsfile"); boolean hasJenkinsFile = Files.isFile(jenkinsFile); LOG.debug("Has Jenkinsfile " + hasJenkinsFile + " with file: " + jenkinsFile); if (!hasJenkinsFile) { inputComponents.addAll( CommandHelpers.addInputComponents(builder, pipeline, copyPipelineToProject)); } inputComponents.addAll( CommandHelpers.addInputComponents(builder, chatRoom, issueProjectName, codeReview)); } public static Iterable<String> filterCompletions(Iterable<String> values, String inputValue) { boolean ignoreFilteringAsItBreaksHawtio = true; if (ignoreFilteringAsItBreaksHawtio) { return values; } else { List<String> answer = new ArrayList<>(); String lowerInputValue = inputValue.toLowerCase(); for (String value : values) { if (value != null) { if (value.toLowerCase().contains(lowerInputValue)) { answer.add(value); } } } return answer; } } @Override public NavigationResult next(UINavigationContext context) throws Exception { return null; } @Override public Result execute(UIExecutionContext context) throws Exception { LOG.info("Creating the fabric8.yml file"); String fileName = ProjectConfigs.FILE_NAME; Project project = getSelectedProject(context); File configFile = getProjectConfigFile(context.getUIContext(), getSelectedProject(context)); if (configFile == null) { // lets not fail as we typically want to execute SaveDevOpsStep next... return Results.success(); } ProjectConfig config = null; boolean hasFile = false; if (configFile.exists()) { config = ProjectConfigs.parseProjectConfig(configFile); hasFile = true; } if (config == null) { config = new ProjectConfig(); } CommandHelpers.putComponentValuesInAttributeMap(context, inputComponents); updateConfiguration(context, config); LOG.info("Result: " + config); String message; if (config.isEmpty() && !hasFile) { message = "No " + fileName + " need be generated as there is no configuration"; return Results.success(message); } else { String operation = "Updated"; if (!configFile.exists()) { operation = "Created"; } ProjectConfigs.saveConfig(config, configFile); message = operation + " " + fileName; } // now lets update the devops stuff UIContext uiContext = context.getUIContext(); Map<Object, Object> attributeMap = uiContext.getAttributeMap(); String gitUrl = getStringAttribute(attributeMap, "gitUrl"); if (Strings.isNullOrBlank(gitUrl)) { gitUrl = getStringAttribute(attributeMap, "gitAddress"); } Object object = attributeMap.get(Project.class); String user = getStringAttribute(attributeMap, "gitUser"); String named = getStringAttribute(attributeMap, "projectName"); ; File basedir = CommandHelpers.getBaseDir(project); if (basedir == null && configFile != null) { basedir = configFile.getParentFile(); } if (object instanceof Project) { Project newProject = (Project) object; MetadataFacet facet = newProject.getFacet(MetadataFacet.class); if (facet != null) { if (Strings.isNullOrBlank(named)) { named = facet.getProjectName(); } if (Strings.isNullOrBlank(gitUrl)) { String address = getStringAttribute(attributeMap, "gitAddress"); gitUrl = address + user + "/" + named + ".git"; } } else { LOG.error("No MetadataFacet for newly created project " + newProject); } } else { // updating an existing project - so lets try find the git url from the current source code if (Strings.isNullOrBlank(gitUrl)) { gitUrl = GitHelpers.extractGitUrl(basedir); } if (basedir != null) { if (Strings.isNullOrBlank(named)) { named = basedir.getName(); } } } // lets default the environments from the pipeline PipelineDTO pipelineValue = pipeline.getValue(); LOG.info("Using pipeline " + pipelineValue); String buildName = config.getBuildName(); if (Strings.isNotBlank(buildName)) { if (pipelineValue != null) { List<String> environments = pipelineValue.getEnvironments(); if (environments == null) { environments = new ArrayList<>(); } LinkedHashMap<String, String> environmentMap = new LinkedHashMap<>(); if (environments.isEmpty()) { environmentMap.put("Current", namespace); } else { for (String environment : environments) { String envNamespace = namespace + "-" + environment.toLowerCase(); environmentMap.put(environment, envNamespace); } } config.setEnvironments(environmentMap); } } LOG.info("Configured project " + buildName + " environments: " + config.getEnvironments()); ProjectConfigs.defaultEnvironments(config, namespace); String projectName = config.getBuildName(); if (Strings.isNullOrBlank(projectName)) { projectName = named; config.setBuildName(projectName); } LOG.info("Project name is: " + projectName); if (Strings.isNotBlank(projectName) && project != null) { MavenFacet maven = project.getFacet(MavenFacet.class); Model pom = maven.getModel(); if (pom != null && !isFunktionParentPom(project) && !isFabric8MavenPlugin3OrGreater(project)) { Properties properties = pom.getProperties(); boolean updated = false; updated = MavenHelpers.updatePomProperty( properties, "fabric8.label.project", projectName, updated); updated = MavenHelpers.updatePomProperty( properties, "fabric8.label.version", "${project.version}", updated); if (updated) { LOG.info("Updating pom.xml properties!"); maven.setModel(pom); } else { LOG.warn("Did not update pom.xml properties!"); } } else { LOG.warn("No pom.xml found!"); } } Boolean copyFlowToProjectValue = copyPipelineToProject.getValue(); if (copyFlowToProjectValue != null && copyFlowToProjectValue.booleanValue()) { if (basedir == null || !basedir.isDirectory()) { LOG.warn("Cannot copy the pipeline to the project as no basedir!"); } else { String flow = null; PipelineDTO pipelineDTO = pipelineValue; if (pipelineDTO != null) { flow = pipelineDTO.getValue(); } if (Strings.isNullOrBlank(flow)) { LOG.warn("Cannot copy the pipeline to the project as no pipeline selected!"); } else { String flowText = getFlowContent(flow, uiContext); if (Strings.isNullOrBlank(flowText)) { LOG.warn( "Cannot copy the pipeline to the project as no pipeline text could be loaded!"); } else { flowText = Strings.replaceAllWithoutRegex(flowText, "GIT_URL", "'" + gitUrl + "'"); File newFile = new File(basedir, ProjectConfigs.LOCAL_FLOW_FILE_NAME); Files.writeToFile(newFile, flowText.getBytes()); LOG.info("Written pipeline to " + newFile); if (config != null) { config.setPipeline(null); config.setUseLocalFlow(true); } } } } } final DevOpsConnector connector = new DevOpsConnector(); connector.setProjectConfig(config); connector.setTryLoadConfigFileFromRemoteGit(false); connector.setUsername(user); connector.setPassword(getStringAttribute(attributeMap, "gitPassword")); connector.setBranch(getStringAttribute(attributeMap, "gitBranch", "master")); connector.setBasedir(basedir); connector.setGitUrl(gitUrl); connector.setRepoName(named); connector.setRegisterWebHooks(true); // lets not trigger the jenkins webhook yet as the git push should trigger the build connector.setTriggerJenkinsJob(false); LOG.info("Using connector: " + connector); /* attributeMap.put("registerWebHooks", new Runnable() { @Override public void run() { LOG.info("Now registering webhooks!"); connector.registerWebHooks(); } }); */ try { connector.execute(); } catch (Exception e) { LOG.error("Failed to update DevOps resources: " + e, e); } return Results.success(message); } protected String getStringAttribute( Map<Object, Object> attributeMap, String name, String defaultValue) { String answer = getStringAttribute(attributeMap, name); return Strings.isNullOrBlank(answer) ? defaultValue : answer; } protected String getStringAttribute(Map<Object, Object> attributeMap, String name) { Object value = attributeMap.get(name); if (value != null) { return value.toString(); } return null; } protected String getDescriptionForFlow(String flow) { return null; } protected String getFlowContent(String flow, UIContext context) { File dir = getJenkinsWorkflowFolder(context); if (dir != null) { File file = new File(dir, flow); if (file.isFile() && file.exists()) { try { return IOHelpers.readFully(file); } catch (IOException e) { LOG.warn("Failed to load local pipeline " + file + ". " + e, e); } } } return null; } protected PipelineDTO getPipelineForValue(UIContext context, String value) { if (Strings.isNotBlank(value)) { Iterable<PipelineDTO> pipelines = getPipelines(context, false); for (PipelineDTO pipelineDTO : pipelines) { if (pipelineDTO.getValue().equals(value) || pipelineDTO.toString().equals(value)) { return pipelineDTO; } } } return null; } protected Iterable<PipelineDTO> getPipelines(UIContext context, boolean filterPipelines) { Set<String> builders = null; ProjectOverviewDTO projectOveriew = null; if (filterPipelines) { projectOveriew = getProjectOverview(context); builders = projectOveriew.getBuilders(); } File dir = getJenkinsWorkflowFolder(context); Set<String> buildersFound = new HashSet<>(); if (dir != null) { Filter<File> filter = new Filter<File>() { @Override public boolean matches(File file) { return file.isFile() && Objects.equal(JENKINSFILE, file.getName()); } }; Set<File> files = Files.findRecursive(dir, filter); List<PipelineDTO> pipelines = new ArrayList<>(); for (File file : files) { try { String relativePath = Files.getRelativePath(dir, file); String value = Strings.stripPrefix(relativePath, "/"); String label = value; String postfix = "/" + JENKINSFILE; if (label.endsWith(postfix)) { label = label.substring(0, label.length() - postfix.length()); } if (label.startsWith(jenkinsFilePrefix)) { label = label.substring(jenkinsFilePrefix.length()); } // Lets ignore the fabric8 specific pipelines if (label.startsWith("fabric8-release/")) { continue; } String builder = null; int idx = label.indexOf("/"); if (idx > 0) { builder = label.substring(0, idx); if (filterPipelines && !builders.contains(builder)) { // ignore this builder continue; } else { buildersFound.add(builder); } } String descriptionMarkdown = null; File markdownFile = new File(file.getParentFile(), "ReadMe.md"); if (Files.isFile(markdownFile)) { descriptionMarkdown = IOHelpers.readFully(markdownFile); } PipelineDTO pipeline = new PipelineDTO(value, label, builder, descriptionMarkdown); File yamlFile = new File(file.getParentFile(), "metadata.yml"); if (Files.isFile(yamlFile)) { PipelineMetadata metadata = null; try { metadata = loadYaml(yamlFile, PipelineMetadata.class); } catch (IOException e) { LOG.warn("Failed to parse yaml file " + yamlFile + ". " + e, e); } if (metadata != null) { metadata.configurePipeline(pipeline); } } pipelines.add(pipeline); } catch (IOException e) { LOG.warn( "Failed to find relative path for folder " + dir + " and file " + file + ". " + e, e); } } if (buildersFound.size() == 1) { // lets trim the builder prefix from the labels for (String first : buildersFound) { String prefix = first + "/"; for (PipelineDTO pipeline : pipelines) { String label = pipeline.getLabel(); if (label.startsWith(prefix)) { label = label.substring(prefix.length()); pipeline.setLabel(label); } } break; } } Collections.sort(pipelines); return pipelines; } else { LOG.warn("No jenkinsWorkflowFolder!"); return new ArrayList<>(); } } protected File getJenkinsWorkflowFolder(UIContext context) { File dir = null; Object workflowFolder = context.getAttributeMap().get("jenkinsWorkflowFolder"); if (workflowFolder instanceof File) { dir = (File) workflowFolder; } return dir; } protected String getDescriptionForIssueProject(String value) { return null; } protected Iterable<String> getIssueProjectNames() { Set<String> answer = new TreeSet<>(); try { TaigaClient letschat = getTaiga(); if (letschat != null) { List<ProjectDTO> projects = null; try { projects = letschat.getProjects(); } catch (Exception e) { LOG.warn("Failed to load chat projects! " + e, e); } if (projects != null) { for (ProjectDTO project : projects) { String name = project.getName(); if (name != null) { answer.add(name); } } } } } catch (Exception e) { LOG.warn("Failed to get issue project names: " + e, e); } return answer; } protected String getDescriptionForChatRoom(String chatRoom) { return null; } protected Iterable<String> getChatRoomNames() { Set<String> answer = new TreeSet<>(); try { LetsChatClient letschat = getLetsChat(); if (letschat != null) { List<RoomDTO> rooms = null; try { rooms = letschat.getRooms(); } catch (Exception e) { LOG.warn("Failed to load chat rooms! " + e, e); } if (rooms != null) { for (RoomDTO room : rooms) { String name = room.getSlug(); if (name != null) { answer.add(name); } } } } } catch (Exception e) { LOG.warn("Failed to find chat room names: " + e, e); } return answer; } public LetsChatClient getLetsChat() { if (letsChat == null) { letsChat = LetsChatKubernetes.createLetsChat(getKubernetes()); } return letsChat; } public void setLetsChat(LetsChatClient letsChat) { this.letsChat = letsChat; } public TaigaClient getTaiga() { if (taiga == null) { taiga = TaigaKubernetes.createTaiga(getKubernetes(), namespace); } return taiga; } public void setTaiga(TaigaClient taiga) { this.taiga = taiga; } }
/** An abstract base class for kubernetes related commands */ public abstract class AbstractKubernetesCommand extends AbstractProjectCommand implements UICommand { public static String CATEGORY = "Kubernetes"; private static String namespace = KubernetesHelper.defaultNamespace(); private KubernetesClient kubernetes; @Inject private ProjectFactory projectFactory; /* @Inject */ UIProvider uiProvider; @Inject @WithAttributes(name = "kubernetesUrl", label = "The URL where the kubernetes master is running") UIInput<String> kubernetesUrl; @Override protected boolean isProjectRequired() { return false; } @Override protected ProjectFactory getProjectFactory() { return projectFactory; } public KubernetesClient getKubernetes() { if (kubernetes == null) { String kubernetesAddress = kubernetesUrl.getValue(); if (Strings.isNotBlank(kubernetesAddress)) { kubernetes = new DefaultKubernetesClient( new ConfigBuilder().withMasterUrl(kubernetesAddress).build()); } else { kubernetes = new DefaultKubernetesClient(); } } Objects.notNull(kubernetes, "kubernetes"); return kubernetes; } public void setKubernetes(KubernetesClient kubernetes) { this.kubernetes = kubernetes; } public boolean isGUI() { return getUiProvider().isGUI(); } public UIOutput getOutput() { UIProvider provider = getUiProvider(); return provider != null ? provider.getOutput() : null; } public UIProvider getUiProvider() { return uiProvider; } public void setUiProvider(UIProvider uiProvider) { this.uiProvider = uiProvider; } @Override public void initializeUI(UIBuilder uiBuilder) throws Exception {} /** Prints the given table and returns success */ protected Result tableResults(TablePrinter table) { table.print(getOut()); return Results.success(); } public PrintStream getOut() { UIOutput output = getOutput(); if (output != null) { return output.out(); } else { return System.out; } } public String getNamespace() { return namespace; } public void setNamespace(String namespace) { AbstractKubernetesCommand.namespace = namespace; } }