<commit_before>/*
 * Copyright 2017 Rundeck, Inc. (http://rundeck.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.rundeck.client.tool;

import com.simplifyops.toolbelt.*;
import com.simplifyops.toolbelt.format.json.jackson.JsonFormatter;
import com.simplifyops.toolbelt.format.yaml.snakeyaml.YamlFormatter;
import com.simplifyops.toolbelt.input.jewelcli.JewelInput;
import org.rundeck.client.RundeckClient;
import org.rundeck.client.api.RundeckApi;
import org.rundeck.client.api.model.*;
import org.rundeck.client.tool.commands.*;
import org.rundeck.client.util.Client;
import org.rundeck.client.util.ConfigSource;
import org.rundeck.client.util.Env;
import org.rundeck.client.util.ExtConfigSource;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;

import java.util.*;
import java.util.function.Function;

import static org.rundeck.client.RundeckClient.ENV_INSECURE_SSL;


/**
 * Entrypoint for commandline
 */
public class Main {

    public static final String ENV_USER = "RD_USER";
    public static final String ENV_PASSWORD = "<PASSWORD>";
    public static final String ENV_TOKEN = "RD_TOKEN";
    public static final String ENV_URL = "RD_URL";
    public static final String ENV_AUTH_PROMPT = "RD_AUTH_PROMPT";
    public static final String ENV_DEBUG = "RD_DEBUG";
    public static final String ENV_HTTP_TIMEOUT = "RD_HTTP_TIMEOUT";
    public static final String ENV_CONNECT_RETRY = "RD_CONNECT_RETRY";

    public static void main(String[] args) throws CommandRunFailure {
        tool(new Rd(new Env())).runMain(args, true);
    }


    private static void setupFormat(final ToolBelt belt, AppConfig config) {
        final String format = config.get("RD_FORMAT");
        if ("yaml".equalsIgnoreCase(format)) {
            configYamlFormat(belt, config);
        } else if ("json".equalsIgnoreCase(format)) {
            configJsonFormat(belt);
        } else {
            configNiceFormat(belt);
        }
    }

    private static void configNiceFormat(final ToolBelt belt) {
        NiceFormatter formatter = new NiceFormatter(null) {
            @Override
            public String format(final Object o) {
                if (o instanceof Formatable) {
                    Formatable o1 = (Formatable) o;
                    Map<?, ?> map = o1.asMap();
                    if (null != map) {
                        return super.format(map);
                    }
                    List<?> objects = o1.asList();
                    if (null != objects) {
                        return super.format(objects);
                    }
                }
                return super.format(o);
            }
        };
        formatter.setCollectionIndicator("");
        belt.formatter(formatter);
        belt.channels().info(new FormattedOutput(
                belt.defaultOutput(),
                new PrefixFormatter("# ", belt.defaultBaseFormatter())
        ));
    }

    private static void configJsonFormat(final ToolBelt belt) {
        belt.formatter(new JsonFormatter());
        belt.channels().infoEnabled(false);
        belt.channels().warningEnabled(false);
        belt.channels().errorEnabled(false);
    }

    private static void configYamlFormat(final ToolBelt belt, final AppConfig config) {
        DumperOptions dumperOptions = new DumperOptions();
        dumperOptions.setDefaultFlowStyle(
                "BLOCK".equalsIgnoreCase(config.getString("RD_YAML_FLOW", "BLOCK")) ?
                DumperOptions.FlowStyle.BLOCK :
                DumperOptions.FlowStyle.FLOW
        );
        dumperOptions.setPrettyFlow(config.getBool("RD_YAML_PRETTY", true));
        Representer representer = new Representer();
        representer.addClassTag(JobItem.class, Tag.MAP);
        representer.addClassTag(ScheduledJobItem.class, Tag.MAP);
        representer.addClassTag(DateInfo.class, Tag.MAP);
        representer.addClassTag(Execution.class, Tag.MAP);
        belt.formatter(new YamlFormatter(representer, dumperOptions));
        belt.channels().infoEnabled(false);
        belt.channels().warningEnabled(false);
        belt.channels().errorEnabled(false);
    }

    public static Tool tool(final Rd rd) {
        ToolBelt belt = ToolBelt.belt("rd")
                                .defaultHelpCommands()
                                .ansiColorOutput(rd.isAnsiEnabled())
                                .add(
                                        new Adhoc(rd),
                                        new Jobs(rd),
                                        new Projects(rd),
                                        new Executions(rd),
                                        new Run(rd),
                                        new Keys(rd),
                                        new RDSystem(rd),
                                        new Scheduler(rd),
                                        new Tokens(rd),
                                        new Nodes(rd),
                                        new Something()
                                )
                                .bannerResource("rd-banner.txt")
                                .commandInput(new JewelInput());
        setupColor(belt, rd);
        setupFormat(belt, rd);

        boolean insecureSsl = Boolean.parseBoolean(System.getProperty(
                "rundeck.client.insecure.ssl",
                System.getenv(ENV_INSECURE_SSL)
        ));
        if (insecureSsl) {
            belt.finalOutput().warning(
                    "# WARNING: RD_INSECURE_SSL=true, no hostname or certificate trust verification will be performed");
        }
        return belt.buckle();
    }

    static class Rd extends ExtConfigSource implements RdApp, AppConfig {
        Client<RundeckApi> client;

        public Rd(final ConfigSource src) {
            super(src);
        }

        public boolean isAnsiEnabled() {
            String term = getString("TERM", null);
            String rd_color = getString("RD_COLOR", null);
            return "1".equals(rd_color) ||
                   (
                           term != null
                           && term.contains("color")
                           && !"0".equals(rd_color)
                   );
        }

        public String getDateFormat() {
            return getString("RD_DATE_FORMAT", "yyyy-MM-ddHH:mm:ssZ");
        }

        @Override
        public Client<RundeckApi> getClient() throws InputError {
            if (null == client) {
                client = Main.createClient(this);
            }
            return client;
        }<commit_msg>for #117 default date format should match iso-8601<commit_after>/*
 * Copyright 2017 Rundeck, Inc. (http://rundeck.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.rundeck.client.tool;

import com.simplifyops.toolbelt.*;
import com.simplifyops.toolbelt.format.json.jackson.JsonFormatter;
import com.simplifyops.toolbelt.format.yaml.snakeyaml.YamlFormatter;
import com.simplifyops.toolbelt.input.jewelcli.JewelInput;
import org.rundeck.client.RundeckClient;
import org.rundeck.client.api.RundeckApi;
import org.rundeck.client.api.model.*;
import org.rundeck.client.tool.commands.*;
import org.rundeck.client.util.Client;
import org.rundeck.client.util.ConfigSource;
import org.rundeck.client.util.Env;
import org.rundeck.client.util.ExtConfigSource;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;

import java.util.*;
import java.util.function.Function;

import static org.rundeck.client.RundeckClient.ENV_INSECURE_SSL;


/**
 * Entrypoint for commandline
 */
public class Main {

    public static final String ENV_USER = "RD_USER";
    public static final String ENV_PASSWORD = "<PASSWORD>";
    public static final String ENV_TOKEN = "RD_TOKEN";
    public static final String ENV_URL = "RD_URL";
    public static final String ENV_AUTH_PROMPT = "RD_AUTH_PROMPT";
    public static final String ENV_DEBUG = "RD_DEBUG";
    public static final String ENV_HTTP_TIMEOUT = "RD_HTTP_TIMEOUT";
    public static final String ENV_CONNECT_RETRY = "RD_CONNECT_RETRY";

    public static void main(String[] args) throws CommandRunFailure {
        tool(new Rd(new Env())).runMain(args, true);
    }


    private static void setupFormat(final ToolBelt belt, AppConfig config) {
        final String format = config.get("RD_FORMAT");
        if ("yaml".equalsIgnoreCase(format)) {
            configYamlFormat(belt, config);
        } else if ("json".equalsIgnoreCase(format)) {
            configJsonFormat(belt);
        } else {
            configNiceFormat(belt);
        }
    }

    private static void configNiceFormat(final ToolBelt belt) {
        NiceFormatter formatter = new NiceFormatter(null) {
            @Override
            public String format(final Object o) {
                if (o instanceof Formatable) {
                    Formatable o1 = (Formatable) o;
                    Map<?, ?> map = o1.asMap();
                    if (null != map) {
                        return super.format(map);
                    }
                    List<?> objects = o1.asList();
                    if (null != objects) {
                        return super.format(objects);
                    }
                }
                return super.format(o);
            }
        };
        formatter.setCollectionIndicator("");
        belt.formatter(formatter);
        belt.channels().info(new FormattedOutput(
                belt.defaultOutput(),
                new PrefixFormatter("# ", belt.defaultBaseFormatter())
        ));
    }

    private static void configJsonFormat(final ToolBelt belt) {
        belt.formatter(new JsonFormatter());
        belt.channels().infoEnabled(false);
        belt.channels().warningEnabled(false);
        belt.channels().errorEnabled(false);
    }

    private static void configYamlFormat(final ToolBelt belt, final AppConfig config) {
        DumperOptions dumperOptions = new DumperOptions();
        dumperOptions.setDefaultFlowStyle(
                "BLOCK".equalsIgnoreCase(config.getString("RD_YAML_FLOW", "BLOCK")) ?
                DumperOptions.FlowStyle.BLOCK :
                DumperOptions.FlowStyle.FLOW
        );
        dumperOptions.setPrettyFlow(config.getBool("RD_YAML_PRETTY", true));
        Representer representer = new Representer();
        representer.addClassTag(JobItem.class, Tag.MAP);
        representer.addClassTag(ScheduledJobItem.class, Tag.MAP);
        representer.addClassTag(DateInfo.class, Tag.MAP);
        representer.addClassTag(Execution.class, Tag.MAP);
        belt.formatter(new YamlFormatter(representer, dumperOptions));
        belt.channels().infoEnabled(false);
        belt.channels().warningEnabled(false);
        belt.channels().errorEnabled(false);
    }

    public static Tool tool(final Rd rd) {
        ToolBelt belt = ToolBelt.belt("rd")
                                .defaultHelpCommands()
                                .ansiColorOutput(rd.isAnsiEnabled())
                                .add(
                                        new Adhoc(rd),
                                        new Jobs(rd),
                                        new Projects(rd),
                                        new Executions(rd),
                                        new Run(rd),
                                        new Keys(rd),
                                        new RDSystem(rd),
                                        new Scheduler(rd),
                                        new Tokens(rd),
                                        new Nodes(rd),
                                        new Something()
                                )
                                .bannerResource("rd-banner.txt")
                                .commandInput(new JewelInput());
        setupColor(belt, rd);
        setupFormat(belt, rd);

        boolean insecureSsl = Boolean.parseBoolean(System.getProperty(
                "rundeck.client.insecure.ssl",
                System.getenv(ENV_INSECURE_SSL)
        ));
        if (insecureSsl) {
            belt.finalOutput().warning(
                    "# WARNING: RD_INSECURE_SSL=true, no hostname or certificate trust verification will be performed");
        }
        return belt.buckle();
    }

    static class Rd extends ExtConfigSource implements RdApp, AppConfig {
        Client<RundeckApi> client;

        public Rd(final ConfigSource src) {
            super(src);
        }

        public boolean isAnsiEnabled() {
            String term = getString("TERM", null);
            String rd_color = getString("RD_COLOR", null);
            return "1".equals(rd_color) ||
                   (
                           term != null
                           && term.contains("color")
                           && !"0".equals(rd_color)
                   );
        }

        public String getDateFormat() {
            return getString("RD_DATE_FORMAT", "yyyy-MM-dd'T'HH:mm:ssXX");
        }

        @Override
        public Client<RundeckApi> getClient() throws InputError {
            if (null == client) {
                client = Main.createClient(this);
            }
            return client;
        }
{'fraction_non_alphanumeric': 0.09577504002227326, 'fraction_numerical': 0.0022969304656504487, 'mean_word_length': 1.8650049850448653, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 44, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '407178', 'n_tokens_mistral': 3806, 'n_tokens_neox': 3587, 'n_words': 851}