public void execute()

in src/main/java/co/elastic/support/diagnostics/commands/CheckPlatformDetails.java [37:191]


    public void execute(DiagnosticContext context) {

        try {
            // Cached from previous executions
            RestClient restClient = context.resourceCache.getRestClient(Constants.restInputHost);

            // Populate the node metadata
            Map<String, RestEntry> calls = context.fullElasticRestCalls;
            RestEntry entry = calls.get("nodes");
            String url = entry.getUrl().replace("?human", "/os,process,settings,transport,http?human");
            RestResult result = restClient.execQuery(url);

            // Initialize to empty node which mimimizes NPE opportunities
            JsonNode infoNodes = JsonYamlUtils.mapper.createObjectNode();
            if (result.getStatus() == 200) {
                infoNodes = JsonYamlUtils.createJsonNodeFromString(result.toString());
            }

            context.clusterName = infoNodes.path("cluster_name").asText();

            List<ProcessProfile> nodeProfiles = getNodeNetworkAndLogInfo(infoNodes);

            // See if this cluster is dockerized - if so, don't bother checking for a master
            // to go to
            // because the port information in its output is not reliable.
            for (ProcessProfile profile : nodeProfiles) {
                if (profile.isDocker) {
                    context.dockerPresent = true;
                    break;
                }
            }

            // Removed temporarily until I put in an option to bypass this feature due to
            // issue where master was inaccessible via http from another node even though it
            // had http configured.
            /*
             * if (!context.dockerPresent) {
             * // Get the master node id and flag the master node profile
             * entry = calls.get("master");
             * result = restClient.execQuery(entry.getUrl());
             * JsonNode currentMaster = JsonYamlUtils.mapper.createObjectNode();
             * if (result.getStatus() == 200) {
             * // Strip off the array brackets since there's only one at each end
             * String mod = result.toString();
             * mod = mod.substring(1, (mod.length() - 1));
             * currentMaster = JsonYamlUtils.createJsonNodeFromString(mod);
             * }
             * String currentMasterId = currentMaster.path("id").asText();
             * ProcessProfile masterNode = findMasterNode(currentMasterId, nodeProfiles);
             *
             * // If the master node has an http listener configured then we'll use that for
             * the
             * // REST calls. Set up a rest client and add it to the resources.
             * if (differentInstances(context.diagnosticInputs.host,
             * context.diagnosticInputs.port, masterNode.host, masterNode.httpPort) &&
             * masterNode.isHttp) {
             * RestClient masterRestClient = RestClient.getClient(
             * masterNode.host,
             * masterNode.httpPort,
             * context.diagnosticInputs.scheme,
             * context.diagnosticInputs.user,
             * context.diagnosticInputs.password,
             * context.diagnosticInputs.proxyHost,
             * context.diagnosticInputs.proxyPort,
             * context.diagnosticInputs.proxyUser,
             * context.diagnosticInputs.proxyPassword,
             * context.diagnosticInputs.pkiKeystore,
             * context.diagnosticInputs.pkiKeystorePass,
             * context.diagnosticInputs.skipVerification,
             * context.diagsConfig.connectionTimeout,
             * context.diagsConfig.connectionRequestTimeout,
             * context.diagsConfig.socketTimeout);
             *
             * ResourceCache.addRestClient(Constants.restTargetHost, masterRestClient);
             * }
             * }
             */

            SystemCommand syscmd = null;
            switch (context.diagnosticInputs.diagType) {
                case Constants.remote:
                    // If Docker containers flag it for no syscalls or logs
                    String targetOS;
                    if (context.dockerPresent) {
                        context.runSystemCalls = false;
                        // We really don't have any way of really knowing
                        // what the enclosing platform is. So this may fail...
                        logger.warn(Constants.CONSOLE,
                                "Docker containers detected on remote platform - unable to determine host OS. Linux will be used but if another operating system is present the Docker diagnostic calls may fail.");
                        targetOS = Constants.linuxPlatform;
                        // break;
                    } else {
                        // check for input host in bound addresses
                        context.targetNode = findRemoteTargetNode(
                                context.diagnosticInputs.host, nodeProfiles);
                        targetOS = context.targetNode.os;
                    }

                    syscmd = new RemoteSystem(
                            targetOS,
                            context.diagnosticInputs.remoteUser,
                            context.diagnosticInputs.remotePassword,
                            context.diagnosticInputs.host,
                            context.diagnosticInputs.remotePort,
                            context.diagnosticInputs.keyfile,
                            context.diagnosticInputs.keyfilePassword,
                            context.diagnosticInputs.knownHostsFile,
                            context.diagnosticInputs.trustRemote,
                            context.diagnosticInputs.isSudo);
                    context.resourceCache.addSystemCommand(Constants.systemCommands, syscmd);

                    break;

                case Constants.local:
                    if (context.dockerPresent) {
                        context.runSystemCalls = false;

                        // We do need a system command local to run the docker calls
                        syscmd = new LocalSystem(SystemUtils.parseOperatingSystemName(SystemProperties.osName));
                        context.resourceCache.addSystemCommand(Constants.systemCommands, syscmd);
                        break;
                    }

                    // Find out which node we're going to obtain logs and system commands from.
                    // First check: if it's a one node cluster, we're done.
                    if (nodeProfiles.size() == 1) {
                        context.targetNode = nodeProfiles.get(0);
                    }

                    // check against the local network interfaces
                    context.targetNode = findLocalTargetNode(
                            context.diagnosticInputs.host, nodeProfiles);

                    syscmd = new LocalSystem(context.targetNode.os);
                    context.resourceCache.addSystemCommand(Constants.systemCommands, syscmd);

                    break;

                default:
                    // If it's not one of the above types it shouldn't be here but try to keep
                    // going...
                    context.runSystemCalls = false;
                    logger.warn(Constants.CONSOLE,
                            "Error occurred checking the network hosts information. Bypassing system calls.");
                    throw new RuntimeException("Host/Platform check error.");

            }

        } catch (Exception e) {
            // Try to keep going even if this didn't work.
            logger.error(Constants.CONSOLE, "Error: {}", e.getMessage());
            logger.error("Error checking node metadata and deployment info.", e);
            context.runSystemCalls = false;
        }
    }