Beispiel #1
0
    def init(self):
        self.namespace = "default"

        self.k8s_manifests = []

        logger.debug("Given config: %s", self.config)
        if self.config.get("namespace"):
            self.namespace = self.config.get("namespace")

        logger.info("Using namespace %s", self.namespace)
        if self.container:
            self.kubectl = self._find_kubectl(Utils.getRoot())
            kube_conf_path = "/etc/kubernetes"
            if not os.path.exists(kube_conf_path):
                if self.dryrun:
                    logger.info("DRY-RUN: link %s from %s%s" %
                                (kube_conf_path, HOST_DIR, kube_conf_path))
                else:
                    os.symlink(
                        os.path.join(Utils.getRoot(),
                                     kube_conf_path.lstrip("/")),
                        kube_conf_path)
        else:
            self.kubectl = self._find_kubectl()

        if not self.dryrun:
            if not os.access(self.kubectl, os.X_OK):
                raise ProviderFailedException("Command: " + self.kubectl +
                                              " not found")

            # Check if Kubernetes config file is accessible
            self.checkConfigFile()
Beispiel #2
0
    def __init__(self, app_spec, destination=None, answers_file=None):
        """
        init function for NuleculeManager. Sets a few instance variables.

        Args:
            app_spec: either a path to an unpacked nulecule app or a
                      container image name where a nulecule can be found
            destination: where to unpack a nulecule to if it isn't local
        """
        self.answers = copy.deepcopy(DEFAULT_ANSWERS)
        self.answers_format = None
        self.answers_file = None  # The path to an answer file
        self.app_path = None  # The path where the app resides or will reside
        self.image = None     # The container image to pull the app from

        # Adjust app_spec, destination, and answer file paths if absolute.
        if os.path.isabs(app_spec):
            app_spec = os.path.join(Utils.getRoot(),
                                    app_spec.lstrip('/'))
        if destination and os.path.isabs(destination):
            destination = os.path.join(Utils.getRoot(),
                                       destination.lstrip('/'))
        if answers_file and os.path.isabs(answers_file):
            answers_file = os.path.join(Utils.getRoot(),
                                        answers_file.lstrip('/'))

        # Determine if the user passed us an image or a path to an app
        if not os.path.exists(app_spec):
            self.image = app_spec
        else:
            self.app_path = app_spec

        # Doesn't make sense to provide an app path and destination
        if self.app_path and destination:
            raise NuleculeException(
                "You can't provide a local path and destination.")

        # If the user provided an image, make sure we have a destination
        if self.image:
            if destination:
                self.app_path = destination
            else:
                self.app_path = Utils.getNewAppCacheDir(self.image)

        logger.debug("NuleculeManager init app_path: %s", self.app_path)
        logger.debug("NuleculeManager init    image: %s", self.image)

        # Set where the main nulecule file should be
        self.main_file = os.path.join(self.app_path, MAIN_FILE)

        # If user provided a path to answers then make sure it exists. If they
        # didn't provide one then use the one in the app dir if it exists.
        if answers_file:
            self.answers_file = answers_file
            if not os.path.isfile(self.answers_file):
                raise NuleculeException(
                    "Path for answers doesn't exist: %s" % self.answers_file)
        else:
            if os.path.isfile(os.path.join(self.app_path, ANSWERS_FILE)):
                self.answers_file = os.path.join(self.app_path, ANSWERS_FILE)
Beispiel #3
0
    def init(self):
        self.namespace = "default"

        self.k8s_manifests = []

        logger.debug("Given config: %s", self.config)
        if self.config.get("namespace"):
            self.namespace = self.config.get("namespace")

        logger.info("Using namespace %s", self.namespace)
        if self.container:
            self.kubectl = self._find_kubectl(Utils.getRoot())
            kube_conf_path = "/etc/kubernetes"
            host_kube_conf_path = os.path.join(Utils.getRoot(), kube_conf_path.lstrip("/"))
            if not os.path.exists(kube_conf_path) and os.path.exists(host_kube_conf_path):
                if self.dryrun:
                    logger.info("DRY-RUN: link %s from %s" % (kube_conf_path, host_kube_conf_path))
                else:
                    os.symlink(host_kube_conf_path, kube_conf_path)
        else:
            self.kubectl = self._find_kubectl()

        if not self.dryrun:
            if not os.access(self.kubectl, os.X_OK):
                raise ProviderFailedException("Command: " + self.kubectl + " not found")

            # Check if Kubernetes config file is accessible, but only
            # if one was provided by the user; config file is optional.
            if self.config_file:
                self.checkConfigFile()
Beispiel #4
0
    def __init__(self, app_spec, destination=None, answers_file=None):
        """
        init function for NuleculeManager. Sets a few instance variables.

        Args:
            app_spec: either a path to an unpacked nulecule app or a
                      container image name where a nulecule can be found
            destination: where to unpack a nulecule to if it isn't local
        """
        self.answers = copy.deepcopy(DEFAULT_ANSWERS)
        self.answers_format = None
        self.answers_file = None  # The path to an answer file
        self.app_path = None  # The path where the app resides or will reside
        self.image = None  # The container image to pull the app from

        # Adjust app_spec, destination, and answer file paths if absolute.
        if os.path.isabs(app_spec):
            app_spec = os.path.join(Utils.getRoot(), app_spec.lstrip('/'))
        if destination and os.path.isabs(destination):
            destination = os.path.join(Utils.getRoot(),
                                       destination.lstrip('/'))
        if answers_file and os.path.isabs(answers_file):
            answers_file = os.path.join(Utils.getRoot(),
                                        answers_file.lstrip('/'))

        # Determine if the user passed us an image or a path to an app
        if not os.path.exists(app_spec):
            self.image = app_spec
        else:
            self.app_path = app_spec

        # Doesn't make sense to provide an app path and destination
        if self.app_path and destination:
            raise NuleculeException(
                "You can't provide a local path and destination.")

        # If the user provided an image, make sure we have a destination
        if self.image:
            if destination:
                self.app_path = destination
            else:
                self.app_path = Utils.getNewAppCacheDir(self.image)

        logger.debug("NuleculeManager init app_path: %s", self.app_path)
        logger.debug("NuleculeManager init    image: %s", self.image)

        # Set where the main nulecule file should be
        self.main_file = os.path.join(self.app_path, MAIN_FILE)

        # If user provided a path to answers then make sure it exists. If they
        # didn't provide one then use the one in the app dir if it exists.
        if answers_file:
            self.answers_file = answers_file
            if not os.path.isfile(self.answers_file):
                raise NuleculeException("Path for answers doesn't exist: %s" %
                                        self.answers_file)
        else:
            if os.path.isfile(os.path.join(self.app_path, ANSWERS_FILE)):
                self.answers_file = os.path.join(self.app_path, ANSWERS_FILE)
Beispiel #5
0
    def run(self):
        self.set_arguments()
        args = self.parser.parse_args()
        if args.verbose:
            set_logging(level=logging.DEBUG)
        elif args.quiet:
            set_logging(level=logging.WARNING)
        else:
            set_logging(level=logging.INFO)

        lock = LockFile(os.path.join(Utils.getRoot(), LOCK_FILE))
        try:
            lock.acquire(timeout=-1)
            args.func(args)
        except AttributeError:
            if hasattr(args, 'func'):
                raise
            else:
                self.parser.print_help()
        except KeyboardInterrupt:
            pass
        except AlreadyLocked:
            logger.error("Could not proceed - there is probably another instance of Atomic App running on this machine.")
        except Exception as ex:
            if args.verbose:
                raise
            else:
                logger.error("Exception caught: %s", repr(ex))
                logger.error(
                    "Run the command again with -v option to get more information.")
        finally:
            if lock.i_am_locking():
                lock.release()
Beispiel #6
0
    def init(self):
        self.namespace = "default"

        self.k8s_manifests = []

        logger.debug("Given config: %s", self.config)
        if self.config.get("namespace"):
            self.namespace = self.config.get("namespace")

        logger.info("Using namespace %s", self.namespace)
        if self.container:
            self.kubectl = self._find_kubectl(Utils.getRoot())
            kube_conf_path = "/etc/kubernetes"
            host_kube_conf_path = Utils.get_real_abspath(kube_conf_path)
            if not os.path.exists(kube_conf_path) and os.path.exists(host_kube_conf_path):
                if self.dryrun:
                    logger.info("DRY-RUN: link %s from %s" % (kube_conf_path, host_kube_conf_path))
                else:
                    os.symlink(host_kube_conf_path, kube_conf_path)
        else:
            self.kubectl = self._find_kubectl()

        if not self.dryrun:
            if not os.access(self.kubectl, os.X_OK):
                raise ProviderFailedException("Command: " + self.kubectl + " not found")

            # Check if Kubernetes config file is accessible, but only
            # if one was provided by the user; config file is optional.
            if self.config_file:
                self.checkConfigFile()
Beispiel #7
0
    def run(self):
        cmdline = sys.argv[1:]  # Grab args from cmdline

        # If we are running in an openshift pod (via `oc new-app`) then
        # there is no cmdline but we want to default to "atomicapp run".
        # In this case copy files to cwd and use the working directory.
        if Utils.running_on_openshift():
            cmdline = 'run -v --dest=none /{}'.format(APP_ENT_PATH).split()

        # We want to be able to place options anywhere on the command
        # line. We have added all global options to each subparser,
        # but subparsers require all options to be after the 'action'
        # keyword. In order to handle this we just need to figure out
        # what subparser will be used and move it's keyword to the front
        # of the line.
        # NOTE: Also allow "mode" to override 'action' if specified
        args, _ = self.parser.parse_known_args(cmdline)
        cmdline.remove(args.action)     # Remove 'action' from the cmdline
        if args.mode:
            args.action = args.mode     # Allow mode to override 'action'
        cmdline.insert(0, args.action)  # Place 'action' at front
        logger.info("Action/Mode Selected is: %s" % args.action)

        # Finally, parse args and give error if necessary
        args = self.parser.parse_args(cmdline)

        # Set logging level
        if args.verbose:
            set_logging(level=logging.DEBUG)
        elif args.quiet:
            set_logging(level=logging.WARNING)
        else:
            set_logging(level=logging.INFO)

        lock = LockFile(os.path.join(Utils.getRoot(), LOCK_FILE))
        try:
            lock.acquire(timeout=-1)
            args.func(args)
        except AttributeError:
            if hasattr(args, 'func'):
                raise
            else:
                self.parser.print_help()
        except KeyboardInterrupt:
            pass
        except AlreadyLocked:
            logger.error("Could not proceed - there is probably another instance of Atomic App running on this machine.")
        except Exception as ex:
            if args.verbose:
                raise
            else:
                logger.error("Exception caught: %s", repr(ex))
                logger.error(
                    "Run the command again with -v option to get more information.")
        finally:
            if lock.i_am_locking():
                lock.release()
Beispiel #8
0
    def init(self):
        self.cli = find_executable(self.cli_str)
        if self.container and not self.cli:
            host_path = []
            for path in os.environ.get("PATH").split(":"):
                host_path.append(os.path.join(Utils.getRoot(), path.lstrip("/")))
            self.cli = find_binary(self.cli_str, path=":".join(host_path))
            if not self.cli:
                # if run as non-root we need a symlink in the container
                os.symlink(os.path.join(Utils.getRoot(), "usr/bin/oc"), "/usr/bin/oc")
                self.cli = "/usr/bin/oc"

        if not self.dryrun:
            if not self.cli or not os.access(self.cli, os.X_OK):
                raise ProviderFailedException("Command %s not found" % self.cli)
            else:
                logger.debug("Using %s to run OpenShift commands.", self.cli)

            # Check if the required OpenShift config file is accessible.
            self.checkConfigFile()
Beispiel #9
0
    def init(self):
        self.cli = find_executable(self.cli_str)
        if self.container and not self.cli:
            host_path = []
            for path in os.environ.get("PATH").split(":"):
                host_path.append(os.path.join(Utils.getRoot(), path.lstrip("/")))
            self.cli = find_binary(self.cli_str, path=":".join(host_path))
            if not self.cli:
                # if run as non-root we need a symlink in the container
                os.symlink(os.path.join(Utils.getRoot(), "usr/bin/oc"), "/usr/bin/oc")
                self.cli = "/usr/bin/oc"

        if not self.dryrun:
            if not self.cli or not os.access(self.cli, os.X_OK):
                raise ProviderFailedException("Command %s not found" % self.cli)
            else:
                logger.debug("Using %s to run OpenShift commands.", self.cli)

            # Check if OpenShift config file is accessible
            self.checkConfigFile()
Beispiel #10
0
    def init(self):
        self.oc_artifacts = {}

        logger.debug("Given config: %s", self.config)
        if self.config.get("namespace"):
            self.namespace = self.config.get("namespace")

        logger.info("Using namespace %s", self.namespace)

        self._process_artifacts()

        if self.dryrun:
            return
        '''
        Config_file:
            If a config_file has been provided, use the configuration
            from the file and load the associated generated file.
            If a config_file exists (--provider-config) use that.

        Params:
            If any provider specific parameters have been provided,
            load the configuration through the answers.conf file

        .kube/config:
            If no config file or params are provided by user then try to find and
            use a config file at the default location.

        no config at all:
            If no .kube/config file can be found then try to connect to the default
            unauthenticated http://localhost:8080/api end-point.
        '''

        default_config_loc = os.path.join(Utils.getRoot(),
                                          Utils.getUserHome().strip('/'),
                                          '.kube/config')

        if self.config_file:
            logger.debug("Provider configuration provided")
            self.api = Client(KubeConfig.from_file(self.config_file),
                              "openshift")
        elif self._check_required_params():
            logger.debug("Generating .kube/config from given parameters")
            self.api = Client(self._from_required_params(), "openshift")
        elif os.path.isfile(default_config_loc):
            logger.debug(
                ".kube/config exists, using default configuration file")
            self.api = Client(KubeConfig.from_file(default_config_loc),
                              "openshift")
        else:
            self.config["provider-api"] = OC_DEFAULT_API
            self.api = Client(self._from_required_params(), "openshift")

        self._check_namespaces()
Beispiel #11
0
    def init(self):
        self.k8s_artifacts = {}

        logger.debug("Given config: %s", self.config)
        if self.config.get("namespace"):
            self.namespace = self.config.get("namespace")

        logger.info("Using namespace %s", self.namespace)

        self._process_artifacts()

        if self.dryrun:
            return

        '''
        Config_file:
            If a config_file has been provided, use the configuration
            from the file and load the associated generated file.
            If a config_file exists (--provider-config) use that.

        Params:
            If any provider specific parameters have been provided,
            load the configuration through the answers.conf file

        .kube/config:
            If no config file or params are provided by user then try to find and
            use a config file at the default location.

        no config at all:
            If no .kube/config file can be found then try to connect to the default
            unauthenticated http://localhost:8080/api end-point.
        '''

        default_config_loc = os.path.join(
            Utils.getRoot(), Utils.getUserHome().strip('/'), '.kube/config')

        if self.config_file:
            logger.debug("Provider configuration provided")
            self.api = Client(KubeConfig.from_file(self.config_file), "kubernetes")
        elif self._check_required_params():
            logger.debug("Generating .kube/config from given parameters")
            self.api = Client(self._from_required_params(), "kubernetes")
        elif os.path.isfile(default_config_loc):
            logger.debug(".kube/config exists, using default configuration file")
            self.api = Client(KubeConfig.from_file(default_config_loc), "kubernetes")
        else:
            self.config["provider-api"] = K8S_DEFAULT_API
            self.api = Client(self._from_required_params(), "kubernetes")

        # Check if the namespace that the app is being deployed to is available
        self._check_namespaces()
Beispiel #12
0
    def init(self):
        self.namespace = "default"

        self.k8s_manifests = []

        logger.debug("Given config: %s", self.config)
        if self.config.get("namespace"):
            self.namespace = self.config.get("namespace")

        logger.info("Using namespace %s", self.namespace)
        if self.container:
            self.kubectl = self._find_kubectl(Utils.getRoot())
            kube_conf_path = "/etc/kubernetes"
            if not os.path.exists(kube_conf_path):
                if self.dryrun:
                    logger.info("DRY-RUN: link %s from %s%s" % (kube_conf_path, HOST_DIR, kube_conf_path))
                else:
                    os.symlink(os.path.join(Utils.getRoot(), kube_conf_path.lstrip("/")), kube_conf_path)
        else:
            self.kubectl = self._find_kubectl()

        if not self.dryrun:
            if not os.access(self.kubectl, os.X_OK):
                raise ProviderFailedException("Command: " + self.kubectl + " not found")
Beispiel #13
0
    def run(self):
        self.set_arguments()  # Set our arguments
        cmdline = sys.argv[1:]  # Grab args from cmdline

        # We want to be able to place options anywhere on the command
        # line. We have added all global options to each subparser,
        # but subparsers require all options to be after the 'action'
        # keyword. In order to handle this we just need to figure out
        # what subparser will be used and move it's keyword to the front
        # of the line.
        args, _ = self.parser.parse_known_args(cmdline)
        cmdline.remove(args.action)  # Remove 'action' from the cmdline
        cmdline.insert(0, args.action)  # Place 'action' at front

        # Finally, parse args and give error if necessary
        args = self.parser.parse_args(cmdline)
        if args.verbose:
            set_logging(level=logging.DEBUG)
        elif args.quiet:
            set_logging(level=logging.WARNING)
        else:
            set_logging(level=logging.INFO)

        lock = LockFile(os.path.join(Utils.getRoot(), LOCK_FILE))
        try:
            lock.acquire(timeout=-1)
            args.func(args)
        except AttributeError:
            if hasattr(args, "func"):
                raise
            else:
                self.parser.print_help()
        except KeyboardInterrupt:
            pass
        except AlreadyLocked:
            logger.error(
                "Could not proceed - there is probably another instance of Atomic App running on this machine."
            )
        except Exception as ex:
            if args.verbose:
                raise
            else:
                logger.error("Exception caught: %s", repr(ex))
                logger.error("Run the command again with -v option to get more information.")
        finally:
            if lock.i_am_locking():
                lock.release()
Beispiel #14
0
    def run(self):
        self.set_arguments()
        args = self.parser.parse_args()
        if args.verbose:
            set_logging(level=logging.DEBUG)
        elif args.quiet:
            set_logging(level=logging.WARNING)
        else:
            set_logging(level=logging.INFO)

        lock = LockFile(os.path.join(Utils.getRoot(), LOCK_FILE))
        try:
            lock.acquire(timeout=-1)
            args.func(args)
        except AttributeError:
            if hasattr(args, 'func'):
                raise
            else:
                self.parser.print_help()
        except KeyboardInterrupt:
            pass
        except AlreadyLocked:
            logger.error(
                "Could not proceed - there is probably another instance of Atomic App running on this machine."
            )
        except Exception as ex:
            if args.verbose:
                raise
            else:
                logger.error("Exception caught: %s", repr(ex))
                logger.error(
                    "Run the command again with -v option to get more information."
                )
        finally:
            if lock.i_am_locking():
                lock.release()
Beispiel #15
0
    def run(self):
        cmdline = sys.argv[1:]  # Grab args from cmdline

        # Initial setup of logging (to allow for a few early debug statements)
        Logging.setup_logging(verbose=True, quiet=False)

        # If we are running in an openshift pod (via `oc new-app`) then
        # there is no cmdline but we want to default to "atomicapp run".
        if Utils.running_on_openshift():
            cmdline = 'run -v --dest=none --provider=openshift /{}'
            cmdline = cmdline.format(APP_ENT_PATH).split()  # now a list

        # If the user has elected to provide all arguments via the
        # ATOMICAPP_ARGS environment variable then set it now
        argstr = os.environ.get('ATOMICAPP_ARGS')
        if argstr:
            logger.debug("Setting cmdline args to: {}".format(argstr))
            cmdline = argstr.split()

        # If the user has elected to provide some arguments via the
        # ATOMICAPP_APPEND_ARGS environment variable then add those now
        argstr = os.environ.get('ATOMICAPP_APPEND_ARGS')
        if argstr:
            logger.debug("Appending args to cmdline: {}".format(argstr))
            cmdline.extend(argstr.split())

        # We want to be able to place options anywhere on the command
        # line. We have added all global options to each subparser,
        # but subparsers require all options to be after the 'action'
        # keyword. In order to handle this we just need to figure out
        # what subparser will be used and move it's keyword to the front
        # of the line.
        # NOTE: Also allow "mode" to override 'action' if specified
        args, _ = self.parser.parse_known_args(cmdline)
        cmdline.remove(args.action)     # Remove 'action' from the cmdline
        if args.mode:
            args.action = args.mode     # Allow mode to override 'action'
        cmdline.insert(0, args.action)  # Place 'action' at front

        # Finally, parse args and give error if necessary
        args = self.parser.parse_args(cmdline)

        # Setup logging (now with arguments from cmdline) and log a few msgs
        Logging.setup_logging(args.verbose, args.quiet, args.logtype)
        logger.info("Action/Mode Selected is: %s" % args.action)
        logger.debug("Final parsed cmdline: {}".format(' '.join(cmdline)))

        # In the case of Atomic CLI we want to allow the user to specify
        # a directory if they want to for "run". For that reason we won't
        # default the RUN label for Atomic App to provide an app_spec argument.
        # In this case pick up app_spec from $IMAGE env var (set by RUN label).
        if args.app_spec is None:
            if os.environ.get('IMAGE') is not None:
                logger.debug("Setting app_spec based on $IMAGE env var")
                args.app_spec = os.environ['IMAGE']
            else:
                print("Error. Too few arguments. Must provide app_spec.")
                print("Run with '--help' for more info")
                sys.exit(1)

        # Take the arguments that correspond to "answers" config file data
        # and make a dictionary of it to pass along in args.
        setattr(args, 'cli_answers', {})
        for item in ['providerapi', 'providercafile',
                     'providerconfig', 'providertlsverify', 'namespace']:
            if hasattr(args, item) and getattr(args, item) is not None:
                args.cli_answers[item] = getattr(args, item)

        lock = LockFile(os.path.join(Utils.getRoot(), LOCK_FILE))
        try:
            lock.acquire(timeout=-1)
            args.func(args)
        except AttributeError:
            if hasattr(args, 'func'):
                raise
            else:
                self.parser.print_help()
        except KeyboardInterrupt:
            pass
        except AlreadyLocked:
            logger.error("Could not proceed - there is probably another instance of Atomic App running on this machine.")
        except Exception as ex:
            if args.verbose:
                raise
            else:
                logger.error("Exception caught: %s", repr(ex))
                logger.error(
                    "Run the command again with -v option to get more information.")
        finally:
            if lock.i_am_locking():
                lock.release()
Beispiel #16
0
    def _set_config_values(self):
        """
        Reads providerapi, namespace and accesstoken from answers.conf and
        corresponding values from providerconfig (if set).
        Use one that is set, if both are set and have conflicting values raise
        exception.

        Raises:
            ProviderFailedException: values in providerconfig and answers.conf
                are in conflict

        """

        # First things first, if we are running inside of an openshift pod via
        # `oc new-app` then get the config from the environment (files/env vars)
        # NOTE: pick up provider_tls_verify from answers if exists
        if Utils.running_on_openshift():
            self.providerapi = Utils.get_openshift_api_endpoint_from_env()
            self.namespace = os.environ['POD_NAMESPACE']
            self.access_token = os.environ['TOKEN_ENV_VAR']
            self.provider_ca = OPENSHIFT_POD_CA_FILE
            self.provider_tls_verify = \
                self.config.get(PROVIDER_TLS_VERIFY_KEY, True)
            return  # No need to process other information

        # initialize result to default values
        result = {PROVIDER_API_KEY: self.providerapi,
                  ACCESS_TOKEN_KEY: self.access_token,
                  NAMESPACE_KEY: self.namespace,
                  PROVIDER_TLS_VERIFY_KEY: self.provider_tls_verify,
                  PROVIDER_CA_KEY: self.provider_ca}

        # create keys in dicts and initialize values to None
        answers = {}
        providerconfig = {}
        for k in result.keys():
            answers[k] = None
            providerconfig[k] = None

        # get values from answers.conf
        for k in result.keys():
            answers[k] = self.config.get(k)

        # get values from providerconfig
        if self.config_file:
            providerconfig = self._parse_kubeconf(self.config_file)

        # decide between values from answers.conf and providerconfig
        # if only one is set use that, report if they are in conflict
        for k in result.keys():
            if answers[k] is not None and providerconfig[k] is None:
                result[k] = answers[k]
            if answers[k] is None and providerconfig[k] is not None:
                result[k] = providerconfig[k]
            if answers[k] is not None and providerconfig[k] is not None:
                if answers[k] == providerconfig[k]:
                    result[k] = answers[k]
                else:
                    msg = "There are conflicting values in %s (%s) and %s (%s)"\
                        % (self.config_file, providerconfig[k], ANSWERS_FILE,
                           answers[k])
                    logger.error(msg)
                    raise ProviderFailedException(msg)

        logger.debug("config values: %s" % result)

        # this items are required, they have to be not None
        for k in [PROVIDER_API_KEY, ACCESS_TOKEN_KEY, NAMESPACE_KEY]:
            if result[k] is None:
                msg = "You need to set %s in %s" % (k, ANSWERS_FILE)
                logger.error(msg)
                raise ProviderFailedException(msg)

        # set config values
        self.providerapi = result[PROVIDER_API_KEY]
        self.access_token = result[ACCESS_TOKEN_KEY]
        self.namespace = result[NAMESPACE_KEY]
        self.provider_tls_verify = result[PROVIDER_TLS_VERIFY_KEY]
        if result[PROVIDER_CA_KEY]:
            # if we are in container translate path to path on host
            self.provider_ca = os.path.join(Utils.getRoot(),
                                            result[PROVIDER_CA_KEY].lstrip('/'))
        else:
            self.provider_ca = None
Beispiel #17
0
    def __init__(self, app_spec, destination=None,
                 cli_answers=None, answers_file=None):
        """
        init function for NuleculeManager. Sets a few instance variables.

        Args:
            app_spec: either a path to an unpacked nulecule app or a
                      container image name where a nulecule can be found
            destination: where to unpack a nulecule to if it isn't local
            cli_answers: some answer file values provided from cli args
            answers_file: the location of the answers file
        """
        self.answers = copy.deepcopy(DEFAULT_ANSWERS)
        self.cli_answers = cli_answers
        self.answers_format = None
        self.answers_file = None  # The path to an answer file
        self.app_path = None  # The path where the app resides or will reside
        self.image = None     # The container image to pull the app from

        # Adjust app_spec, destination, and answer file paths if absolute.
        if os.path.isabs(app_spec):
            app_spec = os.path.join(Utils.getRoot(),
                                    app_spec.lstrip('/'))
        if destination and os.path.isabs(destination):
            destination = os.path.join(Utils.getRoot(),
                                       destination.lstrip('/'))
        if answers_file and os.path.isabs(answers_file):
            answers_file = os.path.join(Utils.getRoot(),
                                        answers_file.lstrip('/'))

        # If the user doesn't want the files copied to a permanent
        # location then he provides 'none'. If that is the case we'll
        # use a temporary directory
        if destination and destination.lower() == 'none':
            logger.debug("'none' destination requested. Using tmp dir")
            destination = tempfile.mkdtemp(prefix='atomicapp')

        # Determine if the user passed us an image or a path to an app
        if not os.path.exists(app_spec):
            self.image = app_spec
        else:
            self.app_path = app_spec

        # Doesn't really make much sense to provide an app path and destination,
        # but if they want to we'll simply just copy the files for them
        if self.app_path and destination:
            Utils.copy_dir(self.app_path, destination, update=True)
            self.app_path = destination

        # If the user provided an image, make sure we have a destination
        if self.image:
            if destination:
                self.app_path = destination
            else:
                self.app_path = Utils.getNewAppCacheDir(self.image)

        logger.debug("NuleculeManager init app_path: %s", self.app_path)
        logger.debug("NuleculeManager init    image: %s", self.image)

        # Create the app_path if it doesn't exist yet
        if not os.path.isdir(self.app_path):
            os.makedirs(self.app_path)

        # Set where the main nulecule file should be
        self.main_file = os.path.join(self.app_path, MAIN_FILE)

        # Process answers.
        self.answers_file = answers_file
        self._process_answers()
Beispiel #18
0
    def __init__(self, app_spec, destination=None,
                 cli_answers=None, answers_file=None):
        """
        init function for NuleculeManager. Sets a few instance variables.

        Args:
            app_spec: either a path to an unpacked nulecule app or a
                      container image name where a nulecule can be found
            destination: where to unpack a nulecule to if it isn't local
            cli_answers: some answer file values provided from cli args
            answers_file: the location of the answers file
        """
        self.answers = copy.deepcopy(DEFAULT_ANSWERS)
        self.cli_answers = cli_answers
        self.answers_format = None
        self.answers_file = None  # The path to an answer file
        self.app_path = None  # The path where the app resides or will reside
        self.image = None     # The container image to pull the app from

        # Adjust app_spec, destination, and answer file paths if absolute.
        if os.path.isabs(app_spec):
            app_spec = os.path.join(Utils.getRoot(),
                                    app_spec.lstrip('/'))
        if destination and os.path.isabs(destination):
            destination = os.path.join(Utils.getRoot(),
                                       destination.lstrip('/'))
        if answers_file and os.path.isabs(answers_file):
            answers_file = os.path.join(Utils.getRoot(),
                                        answers_file.lstrip('/'))

        # If the user doesn't want the files copied to a permanent
        # location then he provides 'none'. If that is the case we'll
        # use a temporary directory
        if destination and destination.lower() == 'none':
            logger.debug("'none' destination requested. Using tmp dir")
            destination = tempfile.mkdtemp(prefix='atomicapp')

        # Determine if the user passed us an image or a path to an app
        if not os.path.exists(app_spec):
            self.image = app_spec
        else:
            self.app_path = app_spec

        # Doesn't really make much sense to provide an app path and destination,
        # but if they want to we'll simply just copy the files for them
        if self.app_path and destination:
            Utils.copy_dir(self.app_path, destination, update=True)
            self.app_path = destination

        # If the user provided an image, make sure we have a destination
        if self.image:
            if destination:
                self.app_path = destination
            else:
                self.app_path = Utils.getNewAppCacheDir(self.image)

        logger.debug("NuleculeManager init app_path: %s", self.app_path)
        logger.debug("NuleculeManager init image: %s", self.image)

        # Create the app_path if it doesn't exist yet
        if not os.path.isdir(self.app_path):
            os.makedirs(self.app_path)

        # Set where the main nulecule file should be
        self.main_file = os.path.join(self.app_path, MAIN_FILE)

        # Process answers.
        self.answers_file = answers_file
        self._process_answers()
Beispiel #19
0
    def __init__(self, app_spec, destination=None, answers_file=None):
        """
        init function for NuleculeManager. Sets a few instance variables.

        Args:
            app_spec: either a path to an unpacked nulecule app or a
                      container image name where a nulecule can be found
            destination: where to unpack a nulecule to if it isn't local
        """
        # Let's pass in a default format for our answers
        self.answers = copy.deepcopy(DEFAULT_ANSWERS)
        self.answers_format = None
        self.answers_file = None  # The path to an answer file
        self.app_path = None  # The path where the app resides or will reside
        self.image = None     # The container image to pull the app from

        # Adjust app_spec, destination, and answer file paths if absolute.
        if os.path.isabs(app_spec):
            app_spec = os.path.join(Utils.getRoot(),
                                    app_spec.lstrip('/'))
        if destination and os.path.isabs(destination):
            destination = os.path.join(Utils.getRoot(),
                                       destination.lstrip('/'))
        if answers_file and os.path.isabs(answers_file):
            answers_file = os.path.join(Utils.getRoot(),
                                        answers_file.lstrip('/'))

        # If the user doesn't want the files copied to a permanent
        # location then he provides 'none'. If that is the case we'll
        # use a temporary directory
        if destination and destination.lower() == 'none':
            logger.debug("'none' destination requested. Using tmp dir")
            destination = tempfile.mkdtemp(prefix='atomicapp')

        # Determine if the user passed us an image or a path to an app
        if not os.path.exists(app_spec):
            self.image = app_spec
        else:
            self.app_path = app_spec

        # Doesn't really make much sense to provide an app path and destination,
        # but if they want to we'll simply just copy the files for them
        if self.app_path and destination:
            Utils.copy_dir(self.app_path, destination, update=True)
            self.app_path = destination

        # If the user provided an image, make sure we have a destination
        if self.image:
            if destination:
                self.app_path = destination
            else:
                self.app_path = Utils.getNewAppCacheDir(self.image)

        logger.debug("NuleculeManager init app_path: %s", self.app_path)
        logger.debug("NuleculeManager init    image: %s", self.image)

        # Set where the main nulecule file should be
        self.main_file = os.path.join(self.app_path, MAIN_FILE)

        # If user provided a path to answers then make sure it exists. If they
        # didn't provide one then use the one in the app dir if it exists.
        if answers_file:
            self.answers_file = answers_file
            if not os.path.isfile(self.answers_file):
                raise NuleculeException(
                    "Path for answers doesn't exist: %s" % self.answers_file)
        else:
            if os.path.isfile(os.path.join(self.app_path, ANSWERS_FILE)):
                self.answers_file = os.path.join(self.app_path, ANSWERS_FILE)

        # TODO: put this in a better place in the future.
        # If we are running inside of an openshift pod then override
        # some of the config by detecting some values from the environment
        if Utils.running_on_openshift():
            self.answers[GLOBAL_CONF]['provider'] = 'openshift'
            self.answers[GLOBAL_CONF]['accesstoken'] = os.environ['TOKEN_ENV_VAR']
            self.answers[GLOBAL_CONF]['namespace'] = os.environ['POD_NAMESPACE']
            self.answers[GLOBAL_CONF]['providerapi'] = \
                Utils.get_openshift_api_endpoint_from_env()
Beispiel #20
0
    def run(self):
        cmdline = sys.argv[1:]  # Grab args from cmdline

        # If we are running in an openshift pod (via `oc new-app`) then
        # there is no cmdline but we want to default to "atomicapp run".
        if Utils.running_on_openshift():
            cmdline = 'run -v --dest=none --provider=openshift /{}'
            cmdline = cmdline.format(APP_ENT_PATH).split()  # now a list

        # If the user has elected to provide all arguments via the
        # ATOMICAPP_ARGS environment variable then set it now
        argstr = os.environ.get('ATOMICAPP_ARGS')
        if argstr:
            logger.debug("Setting cmdline args to: {}".format(argstr))
            cmdline = argstr.split()

        # If the user has elected to provide some arguments via the
        # ATOMICAPP_APPEND_ARGS environment variable then add those now
        argstr = os.environ.get('ATOMICAPP_APPEND_ARGS')
        if argstr:
            logger.debug("Appending args to cmdline: {}".format(argstr))
            cmdline.extend(argstr.split())

        # We want to be able to place options anywhere on the command
        # line. We have added all global options to each subparser,
        # but subparsers require all options to be after the 'action'
        # keyword. In order to handle this we just need to figure out
        # what subparser will be used and move it's keyword to the front
        # of the line.
        # NOTE: Also allow "mode" to override 'action' if specified
        args, _ = self.parser.parse_known_args(cmdline)
        cmdline.remove(args.action)     # Remove 'action' from the cmdline
        if args.mode:
            args.action = args.mode     # Allow mode to override 'action'
        cmdline.insert(0, args.action)  # Place 'action' at front
        logger.info("Action/Mode Selected is: %s" % args.action)

        # Finally, parse args and give error if necessary
        args = self.parser.parse_args(cmdline)

        # Take the arguments that correspond to "answers" config file data
        # and make a dictionary of it to pass along in args.
        setattr(args, 'cli_answers', {})
        for item in ['providerapi', 'providercafile',
                     'providerconfig', 'providertlsverify']:
            if hasattr(args, item) and getattr(args, item) is not None:
                args.cli_answers[item] = getattr(args, item)

        # Set logging level
        if args.verbose:
            set_logging(level=logging.DEBUG)
        elif args.quiet:
            set_logging(level=logging.WARNING)
        else:
            set_logging(level=logging.INFO)

        # Now that we have set the logging level let's print out the cmdline
        logger.debug("Final parsed cmdline: {}".format(' '.join(cmdline)))

        lock = LockFile(os.path.join(Utils.getRoot(), LOCK_FILE))
        try:
            lock.acquire(timeout=-1)
            args.func(args)
        except AttributeError:
            if hasattr(args, 'func'):
                raise
            else:
                self.parser.print_help()
        except KeyboardInterrupt:
            pass
        except AlreadyLocked:
            logger.error("Could not proceed - there is probably another instance of Atomic App running on this machine.")
        except Exception as ex:
            if args.verbose:
                raise
            else:
                logger.error("Exception caught: %s", repr(ex))
                logger.error(
                    "Run the command again with -v option to get more information.")
        finally:
            if lock.i_am_locking():
                lock.release()