Example #1
0
    def create(self, *args, **kwargs):  # noqa
        """
        Create a application with an initial config, release, domain
        and k8s resource if needed
        """
        try:
            cfg = self.config_set.latest()
        except Config.DoesNotExist:
            cfg = Config.objects.create(owner=self.owner, app=self)

        # Only create if no release can be found
        try:
            rel = self.release_set.latest()
        except Release.DoesNotExist:
            rel = Release.objects.create(version=1,
                                         owner=self.owner,
                                         app=self,
                                         config=cfg,
                                         build=None)

        # create required minimum resources in k8s for the application
        namespace = self.id
        service = self.id
        try:
            self.log('creating Namespace {} and services'.format(namespace),
                     level=logging.DEBUG)
            # Create essential resources
            try:
                self._scheduler.get_namespace(namespace)
            except KubeException:
                self._scheduler.create_namespace(namespace)

            try:
                self._scheduler.get_service(namespace, service)
            except KubeException:
                self._scheduler.create_service(namespace, service)
        except KubeException as e:
            # Blow it all away only if something horrible happens
            try:
                self._scheduler.delete_namespace(namespace)
            except KubeException as e:
                # Just feed into the item below
                raise ServiceUnavailable(
                    'Could not delete the Namespace in Kubernetes') from e

            raise ServiceUnavailable(
                'Kubernetes resources could not be created') from e

        # Attach the platform specific application sub domain to the k8s service
        # Only attach it on first release in case a customer has remove the app domain
        if rel.version == 1 and not Domain.objects.filter(
                domain=self.id).exists():
            Domain(owner=self.owner, app=self, domain=self.id).save()
Example #2
0
    def create(self, *args, **kwargs):  # noqa
        """
        Create a application with an initial config, settings, release, domain
        and k8s resource if needed
        """
        try:
            cfg = self.config_set.latest()
        except Config.DoesNotExist:
            cfg = Config.objects.create(owner=self.owner, app=self)

        # Only create if no release can be found
        try:
            rel = self.release_set.latest()
        except Release.DoesNotExist:
            rel = Release.objects.create(
                version=1, owner=self.owner, app=self,
                config=cfg, build=None
            )

        # create required minimum resources in k8s for the application
        namespace = self.id
        ingress = self.id
        service = self.id
        quota_name = '{}-quota'.format(self.id)
        try:
            self.log('creating Namespace {} and services'.format(namespace), level=logging.DEBUG)
            # Create essential resources
            try:
                self._scheduler.ns.get(namespace)
            except KubeException:
                try:
                    self._scheduler.ns.create(namespace, settings.ENABLE_ISTIO_INJECTION)
                except KubeException as e:
                    raise ServiceUnavailable('Could not create the Namespace in Kubernetes') from e

            if settings.KUBERNETES_NAMESPACE_DEFAULT_QUOTA_SPEC != '':
                quota_spec = json.loads(settings.KUBERNETES_NAMESPACE_DEFAULT_QUOTA_SPEC)
                self.log('creating Quota {} for namespace {}'.format(quota_name, namespace),
                         level=logging.DEBUG)
                try:
                    self._scheduler.quota.get(namespace, quota_name)
                except KubeException:
                    self._scheduler.quota.create(namespace, quota_name, data=quota_spec)

            try:
                self._scheduler.svc.get(namespace, service)
            except KubeException:
                self._scheduler.svc.create(namespace, service)
        except KubeException as e:
            # Blow it all away only if something horrible happens
            try:
                self._scheduler.ns.delete(namespace)
            except KubeException as e:
                # Just feed into the item below
                raise ServiceUnavailable('Could not delete the Namespace in Kubernetes') from e

            raise ServiceUnavailable('Kubernetes resources could not be created') from e

        try:
            # In order to create an ingress, we must first have a namespace.
            if settings.EXPERIMENTAL_NATIVE_INGRESS:
                if ingress == "":
                    raise ServiceUnavailable('Empty hostname')
                try:
                    self._scheduler.ingress.get(ingress)
                except KubeException:
                    self.log("creating Ingress {}".format(namespace), level=logging.INFO)
                    self._scheduler.ingress.create(ingress,
                                                   namespace,
                                                   settings.EXPERIMENTAL_NATIVE_INGRESS_HOSTNAME,
                                                   settings.EXPERIMENTAL_NATIVE_INGRESS_CLASS)
        except KubeException as e:
            raise ServiceUnavailable('Could not create Ingress in Kubernetes') from e
        try:
            self.appsettings_set.latest()
        except AppSettings.DoesNotExist:
            AppSettings.objects.create(owner=self.owner, app=self)
        try:
            self.tls_set.latest()
        except TLS.DoesNotExist:
            TLS.objects.create(owner=self.owner, app=self)
        # Attach the platform specific application sub domain to the k8s service
        # Only attach it on first release in case a customer has remove the app domain
        if rel.version == 1 and not Domain.objects.filter(domain=self.id).exists():
            Domain(owner=self.owner, app=self, domain=self.id).save()