def _recreate_webhook_configuration(self, app_op, app):
        webhook = self._get_webhook_configuration(app_op)
        if webhook:
            LOG.info(
                "Validating webhook already present on system. Nothing to be done."
            )
            return

        dbapi_instance = app_op._dbapi
        db_app = dbapi_instance.kube_app_get(app.name)

        user_overrides = self._get_helm_user_overrides(
            dbapi_instance,
            db_app,
            app_constants.HELM_CHART_INGRESS_NGINX,
            app_constants.HELM_NS_NGINX_INGRESS_CONTROLLER,
        )

        if REAPPLY_ADMISSION_WEBHOOK_OVERRIDE not in user_overrides:
            LOG.info(
                "Override for admission webhook not found. Nothing to be done."
            )
            return

        original_overrides = user_overrides.replace(
            DISABLE_ADMISSION_WEBHOOK_OVERRIDE_CREATION,
            "").replace(REAPPLY_ADMISSION_WEBHOOK_OVERRIDE, "")

        updated_overrides = CREATE_ADMISSION_WEBHOOK_OVERRIDE + ": %s\n" % time(
        ) + original_overrides

        self._update_helm_user_overrides(
            dbapi_instance,
            db_app,
            app_constants.HELM_CHART_INGRESS_NGINX,
            app_constants.HELM_NS_NGINX_INGRESS_CONTROLLER,
            updated_overrides,
        )

        # Reapply the application to ensure the validating webhook is recreated
        lifecycle_hook_info = LifecycleHookInfo()
        lifecycle_hook_info.operation = constants.APP_APPLY_OP
        app_op.perform_app_apply(app._kube_app,
                                 constants.APP_LIFECYCLE_MODE_AUTO,
                                 lifecycle_hook_info)

        if BACKUP_ADMISSION_WEBHOOK_OVERRIDE in original_overrides:
            original_overrides = original_overrides.replace(
                BACKUP_ADMISSION_WEBHOOK_OVERRIDE,
                CREATE_ADMISSION_WEBHOOK_OVERRIDE,
            )

        self._update_helm_user_overrides(
            dbapi_instance,
            db_app,
            app_constants.HELM_CHART_INGRESS_NGINX,
            app_constants.HELM_NS_NGINX_INGRESS_CONTROLLER,
            original_overrides,
        )
コード例 #2
0
ファイル: kube_app.py プロジェクト: starlingx/config
    def delete(self, name, force=None):
        """Delete the application with the given name

        :param name: application name
        """
        try:
            db_app = objects.kube_app.get_by_name(pecan.request.context, name)
        except exception.KubeAppNotFound:
            LOG.error("Received a request to delete app %s which does not "
                      "exist." % name)
            raise wsme.exc.ClientSideError(
                _("Application-delete rejected: application not found."))

        if db_app.status not in [
                constants.APP_UPLOAD_SUCCESS, constants.APP_UPLOAD_FAILURE
        ]:
            raise wsme.exc.ClientSideError(
                _("Application-delete rejected: operation is not allowed "
                  "while the current status is {}.".format(db_app.status)))

        try:
            lifecycle_hook_info = LifecycleHookInfo()
            lifecycle_hook_info.init(
                constants.APP_LIFECYCLE_MODE_MANUAL,
                constants.APP_LIFECYCLE_TYPE_SEMANTIC_CHECK,
                constants.APP_LIFECYCLE_TIMING_PRE, constants.APP_DELETE_OP)
            # Converting string to boolean
            if force == 'True':
                force = True
            else:
                force = False

            lifecycle_hook_info.extra = {
                constants.APP_LIFECYCLE_FORCE_OPERATION: force
            }
            self._app_lifecycle_actions(db_app, lifecycle_hook_info)
        except rpc_common.RemoteError as e:
            raise wsme.exc.ClientSideError(
                _("Application-delete rejected: " + str(e.value)))
        except Exception as e:
            raise wsme.exc.ClientSideError(
                _("Application-delete rejected: " + six.text_type(e)))

        lifecycle_hook_info = LifecycleHookInfo()
        lifecycle_hook_info.mode = constants.APP_LIFECYCLE_MODE_MANUAL

        response = pecan.request.rpcapi.perform_app_delete(
            pecan.request.context,
            db_app,
            lifecycle_hook_info=lifecycle_hook_info)
        if response:
            raise wsme.exc.ClientSideError(_("%s." % response))
コード例 #3
0
    def post(self, body):
        """Uploading an application to be deployed by Armada"""
        tarfile = body.get('tarfile')
        name = body.get('name', '')
        version = body.get('app_version', '')
        name, version, mname, mfile = self._check_tarfile(
            tarfile, name, version, constants.APP_UPLOAD_OP)

        try:
            objects.kube_app.get_by_name(pecan.request.context, name)
            raise wsme.exc.ClientSideError(
                _("Application-upload rejected: application {} already exists."
                  .format(name)))
        except exception.KubeAppNotFound:
            pass

        # Create a database entry and make an rpc async request to upload
        # the application
        app_data = {
            'name': name,
            'app_version': version,
            'manifest_name': mname,
            'manifest_file': os.path.basename(mfile),
            'status': constants.APP_UPLOAD_IN_PROGRESS
        }
        try:
            new_app = pecan.request.dbapi.kube_app_create(app_data)
        except exception.SysinvException as e:
            LOG.exception(e)
            raise

        lifecycle_hook_info = LifecycleHookInfo()
        lifecycle_hook_info.mode = constants.APP_LIFECYCLE_MODE_MANUAL

        pecan.request.rpcapi.perform_app_upload(
            pecan.request.context,
            new_app,
            tarfile,
            lifecycle_hook_info=lifecycle_hook_info)
        return KubeApp.convert_with_links(new_app)
コード例 #4
0
    def update(self, body):
        """Update the applied application to a different version"""
        tarfile = body.get('tarfile')
        name = body.get('name', '')
        version = body.get('app_version', '')
        name, version, mname, mfile = self._check_tarfile(
            tarfile, name, version, constants.APP_UPDATE_OP)

        reuse_overrides_flag = body.get('reuse_user_overrides', None)
        if reuse_overrides_flag is None:
            # None means let the application decide
            reuse_overrides = None
        elif reuse_overrides_flag in ['true', 'True']:
            reuse_overrides = True
        elif reuse_overrides_flag in ['false', 'False']:
            reuse_overrides = False
        else:
            raise wsme.exc.ClientSideError(
                _("Application-update rejected: "
                  "invalid reuse_user_overrides setting."))

        try:
            applied_app = objects.kube_app.get_by_name(pecan.request.context,
                                                       name)
        except exception.KubeAppNotFound:
            LOG.error(
                "Received a request to update app %s which does not exist." %
                name)
            raise wsme.exc.ClientSideError(
                _("Application-update rejected: application not found."))

        try:
            lifecycle_hook_info = LifecycleHookInfo()
            lifecycle_hook_info.init(
                constants.APP_LIFECYCLE_MODE_MANUAL,
                constants.APP_LIFECYCLE_TYPE_SEMANTIC_CHECK,
                constants.APP_LIFECYCLE_TIMING_PRE, constants.APP_UPDATE_OP)
            self._app_lifecycle_actions(applied_app, lifecycle_hook_info)
        except Exception as e:
            raise wsme.exc.ClientSideError(
                _("Application-update rejected: " + str(e.message)))

        if applied_app.status == constants.APP_UPDATE_IN_PROGRESS:
            raise wsme.exc.ClientSideError(
                _("Application-update rejected: update is already "
                  "in progress."))
        elif applied_app.status != constants.APP_APPLY_SUCCESS:
            raise wsme.exc.ClientSideError(
                _("Application-update rejected: operation is not allowed "
                  "while the current status is {}.".format(
                      applied_app.status)))

        if applied_app.app_version == version:
            raise wsme.exc.ClientSideError(
                _("Application-update rejected: the version %s is already "
                  "applied." % version))
        # Set the status for the current applied app to inactive
        applied_app.status = constants.APP_INACTIVE_STATE
        applied_app.progress = None
        applied_app.save()

        # If the version has ever applied before(inactive app found),
        # use armada rollback to apply application later, otherwise,
        # use armada apply.
        # On the AIO-SX, always use armada apply even it was applied
        # before, issue on AIO-SX(replicas is 1) to leverage rollback,
        # armada/helm rollback --wait does not wait for pods to be
        # ready before it returns.
        # related to helm issue,
        # https://github.com/helm/helm/issues/4210
        # https://github.com/helm/helm/issues/2006
        try:
            target_app = objects.kube_app.get_inactive_app_by_name_version(
                pecan.request.context, name, version)
            target_app.status = constants.APP_UPDATE_IN_PROGRESS
            target_app.save()
            if cutils.is_aio_simplex_system(pecan.request.dbapi):
                operation = constants.APP_APPLY_OP
            else:
                operation = constants.APP_ROLLBACK_OP
        except exception.KubeAppInactiveNotFound:
            target_app_data = {
                'name': name,
                'app_version': version,
                'manifest_name': mname,
                'manifest_file': os.path.basename(mfile),
                'status': constants.APP_UPDATE_IN_PROGRESS,
                'active': True
            }
            operation = constants.APP_APPLY_OP

            try:
                target_app = pecan.request.dbapi.kube_app_create(
                    target_app_data)
            except exception.KubeAppAlreadyExists as e:
                applied_app.status = constants.APP_APPLY_SUCCESS
                applied_app.progress = constants.APP_PROGRESS_COMPLETED
                applied_app.save()
                LOG.exception(e)
                raise wsme.exc.ClientSideError(
                    _("Application-update failed: Unable to start application update, "
                      "application info update failed."))

        lifecycle_hook_info = LifecycleHookInfo()
        lifecycle_hook_info.mode = constants.APP_LIFECYCLE_MODE_MANUAL

        pecan.request.rpcapi.perform_app_update(pecan.request.context,
                                                applied_app, target_app,
                                                tarfile, operation,
                                                lifecycle_hook_info,
                                                reuse_overrides)

        return KubeApp.convert_with_links(target_app)
コード例 #5
0
    def patch(self, name, directive, values):
        """Install/update the specified application

        :param name: application name
        :param directive: either 'apply' (fresh install/update), 'remove' or 'abort'
        """
        if directive not in ['apply', 'remove', 'abort']:
            raise exception.OperationNotPermitted

        try:
            db_app = objects.kube_app.get_by_name(pecan.request.context, name)
        except exception.KubeAppNotFound:
            LOG.error("Received a request to %s app %s which does not exist." %
                      (directive, name))
            raise wsme.exc.ClientSideError(
                _("Application-{} rejected: application not found.".format(
                    directive)))

        if directive == 'apply':
            if not values:
                mode = None
            elif name not in constants.HELM_APP_APPLY_MODES.keys():
                raise wsme.exc.ClientSideError(
                    _("Application-apply rejected: Mode is not supported "
                      "for app {}.".format(name)))
            elif (values['mode'] and values['mode']
                  not in constants.HELM_APP_APPLY_MODES[name]):
                raise wsme.exc.ClientSideError(
                    _("Application-apply rejected: Mode {} for app {} is not "
                      "valid. Valid modes are {}.".format(
                          values['mode'], name,
                          constants.HELM_APP_APPLY_MODES[name])))
            else:
                mode = values['mode']

            try:
                app_helper = KubeAppHelper(pecan.request.dbapi)
                app_helper._check_app_compatibility(db_app.name,
                                                    db_app.app_version)
            except exception.IncompatibleKubeVersion as e:
                raise wsme.exc.ClientSideError(
                    _("Application-apply rejected: " + str(e)))

            if db_app.status == constants.APP_APPLY_IN_PROGRESS:
                raise wsme.exc.ClientSideError(
                    _("Application-apply rejected: install/update is already "
                      "in progress."))
            elif db_app.status not in [
                    constants.APP_UPLOAD_SUCCESS, constants.APP_APPLY_FAILURE,
                    constants.APP_APPLY_SUCCESS
            ]:
                raise wsme.exc.ClientSideError(
                    _("Application-apply rejected: operation is not allowed "
                      "while the current status is {}.".format(db_app.status)))

            try:
                lifecycle_hook_info = LifecycleHookInfo()
                lifecycle_hook_info.init(
                    constants.APP_LIFECYCLE_MODE_MANUAL,
                    constants.APP_LIFECYCLE_TYPE_SEMANTIC_CHECK,
                    constants.APP_LIFECYCLE_TIMING_PRE, constants.APP_APPLY_OP)
                self._app_lifecycle_actions(db_app, lifecycle_hook_info)
            except Exception as e:
                raise wsme.exc.ClientSideError(
                    _("Application-apply rejected: " + str(e.message)))

            db_app.status = constants.APP_APPLY_IN_PROGRESS
            db_app.progress = None
            db_app.recovery_attempts = 0
            db_app.mode = mode
            db_app.save()

            lifecycle_hook_info = LifecycleHookInfo()
            lifecycle_hook_info.mode = constants.APP_LIFECYCLE_MODE_MANUAL

            pecan.request.rpcapi.perform_app_apply(
                pecan.request.context,
                db_app,
                mode=mode,
                lifecycle_hook_info=lifecycle_hook_info)
        elif directive == 'remove':
            if db_app.status not in [
                    constants.APP_APPLY_SUCCESS, constants.APP_APPLY_FAILURE,
                    constants.APP_REMOVE_FAILURE
            ]:
                raise wsme.exc.ClientSideError(
                    _("Application-remove rejected: operation is not allowed while "
                      "the current status is {}.".format(db_app.status)))

            try:
                lifecycle_hook_info = LifecycleHookInfo()
                lifecycle_hook_info.init(
                    constants.APP_LIFECYCLE_MODE_MANUAL,
                    constants.APP_LIFECYCLE_TYPE_SEMANTIC_CHECK,
                    constants.APP_LIFECYCLE_TIMING_PRE,
                    constants.APP_REMOVE_OP)
                self._app_lifecycle_actions(db_app, lifecycle_hook_info)
            except Exception as e:
                raise wsme.exc.ClientSideError(
                    _("Application-remove rejected: " + str(e.message)))

            db_app.status = constants.APP_REMOVE_IN_PROGRESS
            db_app.progress = None
            db_app.save()

            lifecycle_hook_info = LifecycleHookInfo()
            lifecycle_hook_info.mode = constants.APP_LIFECYCLE_MODE_MANUAL

            pecan.request.rpcapi.perform_app_remove(
                pecan.request.context,
                db_app,
                lifecycle_hook_info=lifecycle_hook_info)
        else:
            if db_app.status not in [
                    constants.APP_APPLY_IN_PROGRESS,
                    constants.APP_UPDATE_IN_PROGRESS,
                    constants.APP_REMOVE_IN_PROGRESS
            ]:
                raise wsme.exc.ClientSideError(
                    _("Application-abort rejected: operation is not allowed while "
                      "the current status is {}.".format(db_app.status)))

            try:
                lifecycle_hook_info = LifecycleHookInfo()
                lifecycle_hook_info.init(
                    constants.APP_LIFECYCLE_MODE_MANUAL,
                    constants.APP_LIFECYCLE_TYPE_SEMANTIC_CHECK,
                    constants.APP_LIFECYCLE_TIMING_PRE, constants.APP_ABORT_OP)
                self._app_lifecycle_actions(db_app, lifecycle_hook_info)
            except Exception as e:
                raise wsme.exc.ClientSideError(
                    _("Application-abort rejected: " + str(e.message)))

            lifecycle_hook_info = LifecycleHookInfo()
            lifecycle_hook_info.mode = constants.APP_LIFECYCLE_MODE_MANUAL

            pecan.request.rpcapi.perform_app_abort(
                pecan.request.context,
                db_app,
                lifecycle_hook_info=lifecycle_hook_info)
        return KubeApp.convert_with_links(db_app)
コード例 #6
0
ファイル: kube_app.py プロジェクト: starlingx/config
    def post(self, body):
        """Uploading an application to be deployed by Armada"""
        tarfile_path = body.get('tarfile')
        tarfile_binary = body.get('binary_data', '')
        name = body.get('name', '')
        version = body.get('app_version', '')
        images = body.get('images', False)

        if not cutils.is_url(tarfile_path) and not os.path.exists(
                tarfile_path):
            path_tarballs = '/tmp/tarball_uploads'
            if not os.path.exists(path_tarballs):
                os.makedirs(path_tarballs)
                uid, gid = pwd.getpwnam('sysinv').pw_uid, pwd.getpwnam(
                    'sysinv').pw_uid
                os.chown(path_tarballs, uid, gid)

            # Keep unique tarball name to avoid conflicts
            tarball_name = '{}-{}'.format(time.time(),
                                          os.path.basename(tarfile_path))
            tarfile_path = os.path.join(path_tarballs, tarball_name)
            try:
                with open(tarfile_path, 'wb') as f:
                    f.write(base64.urlsafe_b64decode(tarfile_binary))
            except Exception as e:
                LOG.exception('Error: writing the tarfile: {}'.format(e))
                raise wsme.exc.ClientSideError(
                    _("Could not save the application on path {}".format(
                        tarfile_path)))

        name, version, mname, mfile = self._check_tarfile(
            tarfile_path, name, version, constants.APP_UPLOAD_OP)

        try:
            objects.kube_app.get_by_name(pecan.request.context, name)
            raise wsme.exc.ClientSideError(
                _("Application-upload rejected: application {} already exists."
                  .format(name)))
        except exception.KubeAppNotFound:
            pass

        # Create a database entry and make an rpc async request to upload
        # the application
        app_data = {
            'name': name,
            'app_version': version,
            'manifest_name': mname,
            'manifest_file': os.path.basename(mfile),
            'status': constants.APP_UPLOAD_IN_PROGRESS
        }
        try:
            new_app = pecan.request.dbapi.kube_app_create(app_data)
        except exception.SysinvException as e:
            LOG.exception(e)
            raise

        lifecycle_hook_info = LifecycleHookInfo()
        lifecycle_hook_info.mode = constants.APP_LIFECYCLE_MODE_MANUAL

        pecan.request.rpcapi.perform_app_upload(
            pecan.request.context,
            new_app,
            tarfile_path,
            lifecycle_hook_info=lifecycle_hook_info,
            images=images)
        return KubeApp.convert_with_links(new_app)