Beispiel #1
0
    def test_connection(self):
        """
        Test connection to OpenShift server

        Raises:
            ProviderFailedException - Invalid SSL/TLS certificate
        """
        logger.debug("Testing connection to OpenShift server")

        if self.provider_ca and not os.path.exists(self.provider_ca):
            raise ProviderFailedException("Unable to find CA path %s"
                                          % self.provider_ca)

        try:
            (status_code, return_data) = \
                Utils.make_rest_request("get",
                                        self.openshift_api,
                                        verify=self._requests_tls_verify())
        except SSLError as e:
            if self.provider_tls_verify:
                msg = "SSL/TLS ERROR: invalid certificate. " \
                      "Add certificate of correct Certificate Authority providing" \
                      " `%s` or you can disable SSL/TLS verification by `%s=False`" \
                      % (PROVIDER_CA_KEY, PROVIDER_TLS_VERIFY_KEY)
                raise ProviderFailedException(msg)
            else:
                # this shouldn't happen
                raise ProviderFailedException(e.message)
Beispiel #2
0
    def get_pod_status(self, namespace, pod):
        """
        Get pod status.

        Args:
            namespace (str): Openshift namespace
            pod (str): Pod name

        Returns:
            Status of pod (str)

        Raises:
            ProviderFailedException when unable to fetch Pod status.
        """
        args = {
            'namespace': namespace,
            'pod': pod,
            'access_token': self.access_token
        }
        url = urljoin(
            self.kubernetes_api,
            'namespaces/{namespace}/pods/{pod}?'
            'access_token={access_token}'.format(**args))
        (status_code, return_data) = \
            Utils.make_rest_request("get", url, verify=self._requests_tls_verify())

        if status_code != 200:
            raise ProviderFailedException(
                'Could not fetch status for pod: {namespace}/{pod}'.format(
                    namespace=namespace, pod=pod))
        return return_data['status']['phase'].lower()
Beispiel #3
0
    def stop(self):
        """ Undeploys the app by given resource manifests.
        Undeploy operation deletes Marathon apps from cluster.
        """
        for artifact in self.marathon_artifacts:
            url = urlparse.urljoin(
                self.marathon_api,
                "apps/%s" %
                artifact["id"])

            if self.dryrun:
                logger.info("DRY-RUN: %s", url)
                continue

            logger.debug("Deleting appid: %s", artifact["id"])
            (status_code, return_data) =  \
                Utils.make_rest_request("delete", url, data=artifact)
            if status_code == 200:
                logger.info(
                    "Marathon app %s sucessfully deleted.",
                    artifact["id"])
            else:
                msg = "Error deleting app: %s, Marathon API response %s - %s" % (
                    artifact["id"], status_code, return_data)
                logger.error(msg)
                raise ProviderFailedException(msg)
Beispiel #4
0
    def scale(self, url, replicas):
        """
        Scale ReplicationControllers or DeploymentConfig

        Args:
          url (str): full url for artifact
          replicas (int): number of replicas scale to
        """
        patch = [{
            "op": "replace",
            "path": "/spec/replicas",
            "value": replicas
        }]

        (status_code, return_data) = \
            Utils.make_rest_request("patch",
                                    url,
                                    data=patch,
                                    verify=self._requests_tls_verify())
        if status_code == 200:
            logger.info("Successfully scaled to %s replicas", replicas)
        else:
            msg = "%s %s" % (status_code, return_data)
            logger.error(msg)
            raise ProviderFailedException(msg)
Beispiel #5
0
 def process_template(self, url, template):
     (status_code, return_data) = \
         Utils.make_rest_request("post",
                                 url,
                                 verify=self._requests_tls_verify(),
                                 data=template)
     if status_code == 201:
         logger.info("template processed %s", template['metadata']['name'])
         logger.debug("processed template %s", return_data)
         return return_data['objects']
     else:
         msg = "%s %s" % (status_code, return_data)
         logger.error(msg)
         raise ProviderFailedException(msg)
Beispiel #6
0
 def deploy(self, url, artifact):
     (status_code, return_data) = \
         Utils.make_rest_request("post",
                                 url,
                                 verify=self._requests_tls_verify(),
                                 data=artifact)
     if status_code == 201:
         logger.info("Object %s successfully deployed.",
                     artifact['metadata']['name'])
     else:
         msg = "%s %s" % (status_code, return_data)
         logger.error(msg)
         # TODO: remove running components (issue: #428)
         raise ProviderFailedException(msg)
Beispiel #7
0
    def get_oapi_resources(self):
        """
        Get Openshift API resources
        """
        # get list of supported resources for each api
        (status_code, return_data) = \
            Utils.make_rest_request("get",
                                    self.openshift_api,
                                    verify=self._requests_tls_verify())
        if status_code == 200:
            oapi_resources = return_data["resources"]
        else:
            raise ProviderFailedException("Cannot get OpenShift resource list")

        # convert resources list of dicts to list of names
        oapi_resources = [res['name'] for res in oapi_resources]

        logger.debug("Openshift resources %s", oapi_resources)

        return oapi_resources
Beispiel #8
0
    def delete(self, url):
        """
        Delete object on given url

        Args:
            url (str): full url for artifact

        Raises:
            ProviderFailedException: error when calling remote api
        """
        (status_code, return_data) = \
            Utils.make_rest_request("delete",
                                    url,
                                    verify=self._requests_tls_verify())
        if status_code == 200:
            logger.info("Successfully deleted.")
        else:
            msg = "%s %s" % (status_code, return_data)
            logger.error(msg)
            raise ProviderFailedException(msg)
Beispiel #9
0
    def get_kapi_resources(self):
        """
        Get kubernetes API resources
        """
        # get list of supported resources for each api
        (status_code, return_data) = \
            Utils.make_rest_request("get",
                                    self.kubernetes_api,
                                    verify=self._requests_tls_verify())
        if status_code == 200:
            kapi_resources = return_data["resources"]
        else:
            raise ProviderFailedException("Cannot get Kubernetes resource list")

        # convert resources list of dicts to list of names
        kapi_resources = [res['name'] for res in kapi_resources]

        logger.debug("Kubernetes resources %s", kapi_resources)

        return kapi_resources
Beispiel #10
0
    def run(self):
        """ Deploys the app by given resource manifests.
        """
        for artifact in self.marathon_artifacts:
            url = urlparse.urljoin(self.marathon_api, "apps/")

            if self.dryrun:
                logger.info("DRY-RUN: %s", url)
                continue

            logger.debug("Deploying appid: %s", artifact["id"])
            (status_code, return_data) = \
                Utils.make_rest_request("post", url, data=artifact)
            if status_code == 201:
                logger.info("Marathon app %s sucessfully deployed.",
                            artifact["id"])
            else:
                msg = "Error deploying app: %s, Marathon API response %s - %s" % (
                    artifact["id"], status_code, return_data)
                logger.error(msg)
                raise ProviderFailedException(msg)
Beispiel #11
0
    def scale(self, url, replicas):
        """
        Scale ReplicationControllers or DeploymentConfig

        Args:
          url (str): full url for artifact
          replicas (int): number of replicas scale to
        """
        patch = [{"op": "replace",
                  "path": "/spec/replicas",
                  "value": replicas}]

        (status_code, return_data) = \
            Utils.make_rest_request("patch",
                                    url,
                                    data=patch,
                                    verify=self._requests_tls_verify())
        if status_code == 200:
            logger.info("Successfully scaled to %s replicas", replicas)
        else:
            msg = "%s %s" % (status_code, return_data)
            logger.error(msg)
            raise ProviderFailedException(msg)
Beispiel #12
0
    def stop(self):
        """
        Undeploy application.

        Cascade the deletion of the resources managed other resource
        (e.g. ReplicationControllers created by a DeploymentConfig and
        Pods created by a ReplicationController).
        When using command line client this is done automatically
        by `oc` command.
        When using API calls we have to cascade deletion manually.
        """
        logger.debug("Starting undeploy")
        delete_artifacts = []
        for kind, objects in self.openshift_artifacts.iteritems():
            # Add deployment configs to beginning of the list so they are deleted first.
            # Do deployment config first because if you do replication controller
            # before deployment config then the deployment config will re-spawn
            # the replication controller before the deployment config is deleted.
            if kind == "deploymentconfig":
                delete_artifacts = objects + delete_artifacts
            else:
                delete_artifacts = delete_artifacts + objects

        for artifact in delete_artifacts:
            kind = artifact["kind"].lower()
            namespace = self._get_namespace(artifact)

            # Get name from metadata so we know which object to delete.
            if "metadata" in artifact and \
                    "name" in artifact["metadata"]:
                name = artifact["metadata"]["name"]
            else:
                raise ProviderFailedException("Cannot undeploy. There is no"
                                              " name in artifacts metadata "
                                              "artifact=%s" % artifact)

            logger.info("Undeploying artifact name=%s kind=%s" % (name, kind))

            # If this is a deployment config we need to delete all
            # replication controllers that were created by this.
            # Find the replication controller that was created by this deployment
            # config by querying for all replication controllers and filtering based
            # on automatically created label openshift.io/deployment-config.name
            if kind.lower() == "deploymentconfig":
                params = {"labelSelector":
                          "openshift.io/deployment-config.name=%s" % name}
                url = self._get_url(namespace,
                                    "replicationcontroller",
                                    params=params)
                (status_code, return_data) = \
                    Utils.make_rest_request("get", url, verify=self.oc._requests_tls_verify())
                if status_code != 200:
                    raise ProviderFailedException("Cannot get Replication"
                                                  "Controllers for Deployment"
                                                  "Config %s (status code %s)" %
                                                  (name, status_code))
                # kind of returned data is ReplicationControllerList
                # https://docs.openshift.com/enterprise/3.1/rest_api/kubernetes_v1.html#v1-replicationcontrollerlist
                # we need modify items to get valid ReplicationController
                items = return_data["items"]
                for item in items:
                    item["kind"] = "ReplicationController"
                    item["apiVersion"] = return_data["apiVersion"]
                # add items to list of artifact to be deleted
                delete_artifacts.extend(items)

            url = self._get_url(namespace, kind, name)

            # Scale down replication controller to 0 replicas before deleting.
            # This should take care of all pods created by this replication
            # controller and we can safely delete it.
            if kind.lower() == "replicationcontroller":
                if self.dryrun:
                    logger.info("DRY-RUN: SCALE %s down to 0", url)
                else:
                    self.oc.scale(url, 0)

            if self.dryrun:
                logger.info("DRY-RUN: DELETE %s", url)
            else:
                self.oc.delete(url)
Beispiel #13
0
    def undeploy(self):
        """
        Undeploy application.

        Cascade the deletion of the resources managed other resource
        (e.g. ReplicationControllers created by a DeploymentConfig and
        Pods created by a ReplicationController).
        When using command line client this is done automatically
        by `oc` command.
        When using API calls we have to cascade deletion manually.
        """
        logger.debug("Starting undeploy")
        delete_artifacts = []
        for kind, objects in self.openshift_artifacts.iteritems():
            delete_artifacts.extend(objects)

        for artifact in delete_artifacts:
            kind = artifact["kind"].lower()
            namespace = self._get_namespace(artifact)

            # get name from metadata so we know which object to delete
            if "metadata" in artifact and \
                    "name" in artifact["metadata"]:
                name = artifact["metadata"]["name"]
            else:
                raise ProviderFailedException("Cannot undeploy. There is no"
                                              " name in artifacts metadata "
                                              "artifact=%s" % artifact)

            logger.info("Undeploying artifact name=%s kind=%s" % (name, kind))

            # If this is a DeploymentConfig we need to delete all
            # ReplicationControllers that were created by this DC. Find the RC
            # that belong to this DC by querying for all RC and filtering based
            # on automatically created label openshift.io/deployment-config.name
            if kind.lower() == "deploymentconfig":
                params = {"labelSelector":
                          "openshift.io/deployment-config.name=%s" % name}
                url = self._get_url(namespace,
                                    "replicationcontroller",
                                    params=params)
                (status_code, return_data) = \
                    Utils.make_rest_request("get", url, verify=self.oc._requests_tls_verify())
                if status_code != 200:
                    raise ProviderFailedException("Cannot get Replication"
                                                  "Controllers for Deployment"
                                                  "Config %s (status code %s)" %
                                                  (name, status_code))
                # kind of returned data is ReplicationControllerList
                # https://docs.openshift.com/enterprise/3.1/rest_api/kubernetes_v1.html#v1-replicationcontrollerlist
                # we need modify items to get valid ReplicationController
                items = return_data["items"]
                for item in items:
                    item["kind"] = "ReplicationController"
                    item["apiVersion"] = return_data["apiVersion"]
                # add items to list of artifact to be deleted
                delete_artifacts.extend(items)

            # If this is a ReplicationController we need to delete all
            # Pods that were created by this RC. Find the pods that
            # belong to this RC by querying for all pods and filtering
            # based on the selector used in the RC.
            if kind.lower() == "replicationcontroller":
                selector = ",".join(["%s=%s" % (k, v) for k, v in artifact["spec"]["selector"].iteritems()])
                logger.debug("Using labelSelector: %s" % selector)
                params = {"labelSelector": selector}
                url = self._get_url(namespace, "pod", params=params)
                (status_code, return_data) = \
                    Utils.make_rest_request("get", url, verify=self.oc._requests_tls_verify())
                if status_code != 200:
                    raise ProviderFailedException("Cannot get Pods for "
                                                  "ReplicationController %s"
                                                  " (status code %s)" %
                                                  (name, status_code))
                # kind of returned data is ReplicationControllerList
                # https://docs.openshift.com/enterprise/3.1/rest_api/kubernetes_v1.html#v1-podlist
                # we need to modify items to get valid Pod
                items = return_data["items"]
                for item in items:
                    item["kind"] = "Pod"
                    item["apiVersion"] = return_data["apiVersion"]
                # add items to list of artifact to be deleted
                delete_artifacts.extend(items)

            url = self._get_url(namespace, kind, name)

            if self.dryrun:
                logger.info("DRY-RUN: DELETE %s", url)
            else:
                self.oc.delete(url)