All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.cloudfoundry.multiapps.controller.process.steps.CreateOrUpdateServiceBrokerStep Maven / Gradle / Ivy

There is a newer version: 1.183.0
Show newest version
package org.cloudfoundry.multiapps.controller.process.steps;

import java.text.MessageFormat;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import jakarta.inject.Named;

import org.cloudfoundry.multiapps.common.ContentException;
import org.cloudfoundry.multiapps.common.NotFoundException;
import org.cloudfoundry.multiapps.controller.client.lib.domain.CloudApplicationExtended;
import org.cloudfoundry.multiapps.controller.core.helpers.ApplicationAttributes;
import org.cloudfoundry.multiapps.controller.core.model.SupportedParameters;
import org.cloudfoundry.multiapps.controller.core.security.serialization.SecureSerialization;
import org.cloudfoundry.multiapps.controller.process.Messages;
import org.cloudfoundry.multiapps.controller.process.util.ExceptionMessageTailMapper;
import org.cloudfoundry.multiapps.controller.process.util.ExceptionMessageTailMapper.CloudComponents;
import org.cloudfoundry.multiapps.controller.process.variables.Variables;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;

import com.sap.cloudfoundry.client.facade.CloudControllerClient;
import com.sap.cloudfoundry.client.facade.CloudOperationException;
import com.sap.cloudfoundry.client.facade.CloudServiceBrokerException;
import com.sap.cloudfoundry.client.facade.domain.CloudApplication;
import com.sap.cloudfoundry.client.facade.domain.CloudServiceBroker;
import com.sap.cloudfoundry.client.facade.domain.ImmutableCloudServiceBroker;

@Named("createOrUpdateServiceBrokerStep")
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class CreateOrUpdateServiceBrokerStep extends TimeoutAsyncFlowableStep {

    private static final Duration ASYNC_JOB_POLLING_TIMEOUT = Duration.ofMinutes(30);

    @Override
    protected StepPhase executeAsyncStep(ProcessContext context) {
        getStepLogger().debug(Messages.CREATING_SERVICE_BROKERS);

        CloudServiceBroker serviceBroker = getServiceBrokerToCreate(context);
        if (serviceBroker == null) {
            return StepPhase.DONE;
        }
        getStepLogger().debug(MessageFormat.format(Messages.SERVICE_BROKER, SecureSerialization.toJson(serviceBroker)));

        CloudControllerClient client = context.getControllerClient();
        List existingServiceBrokers = client.getServiceBrokers();
        List existingServiceBrokerNames = getServiceBrokerNames(existingServiceBrokers);

        String jobId = null;
        if (existingServiceBrokerNames.contains(serviceBroker.getName())) {
            CloudServiceBroker existingBroker = findServiceBroker(existingServiceBrokers, serviceBroker.getName());
            serviceBroker = mergeServiceBrokerMetadata(serviceBroker, existingBroker);
            jobId = updateServiceBroker(context, serviceBroker, client);
            getStepLogger().debug(MessageFormat.format(Messages.UPDATE_SERVICE_BROKER_TRIGGERED, serviceBroker.getName()));
        } else {
            jobId = createServiceBroker(context, serviceBroker, client);
            getStepLogger().debug(MessageFormat.format(Messages.CREATE_SERVICE_BROKER_TRIGGERED, serviceBroker.getName()));
        }

        if (jobId != null) {
            context.setVariable(Variables.SERVICE_BROKER_ASYNC_JOB_ID, jobId);
            context.setVariable(Variables.CREATED_OR_UPDATED_SERVICE_BROKER, serviceBroker);
            return StepPhase.POLL;
        }

        context.setVariable(Variables.CREATED_OR_UPDATED_SERVICE_BROKER, serviceBroker);
        return StepPhase.DONE;
    }

    @Override
    protected String getStepErrorMessage(ProcessContext context) {
        return Messages.ERROR_CREATING_SERVICE_BROKERS;
    }

    @Override
    protected String getStepErrorMessageAdditionalDescription(ProcessContext context) {
        String offering = context.getVariable(Variables.SERVICE_OFFERING);
        return ExceptionMessageTailMapper.map(configuration, CloudComponents.SERVICE_BROKERS, offering);
    }

    @Override
    public Duration getTimeout(ProcessContext context) {
        return ASYNC_JOB_POLLING_TIMEOUT;
    }

    @Override
    protected List getAsyncStepExecutions(ProcessContext context) {
        return List.of(new PollServiceBrokerOperationsExecution());
    }

    private CloudServiceBroker getServiceBrokerToCreate(ProcessContext context) {
        CloudApplicationExtended app = context.getVariable(Variables.APP_TO_PROCESS);
        CloudServiceBroker serviceBroker = getServiceBrokerFromApp(context, app, app.getEnv());
        if (serviceBroker == null) {
            return null;
        }
        String msg = MessageFormat.format(Messages.CONSTRUCTED_SERVICE_BROKER_FROM_APPLICATION, serviceBroker.getName(), app.getName());
        getStepLogger().debug(msg);
        return serviceBroker;
    }

    protected CloudServiceBroker getServiceBrokerFromApp(ProcessContext context, CloudApplication app, Map appEnv) {
        ApplicationAttributes appAttributes = ApplicationAttributes.fromApplication(app, appEnv);
        if (!appAttributes.get(SupportedParameters.CREATE_SERVICE_BROKER, Boolean.class, false)) {
            return null;
        }

        String serviceBrokerName = appAttributes.get(SupportedParameters.SERVICE_BROKER_NAME, String.class, app.getName());
        String serviceBrokerUsername = appAttributes.get(SupportedParameters.SERVICE_BROKER_USERNAME, String.class);
        String serviceBrokerPassword = appAttributes.get(SupportedParameters.SERVICE_BROKER_PASSWORD, String.class);
        String serviceBrokerUrl = appAttributes.get(SupportedParameters.SERVICE_BROKER_URL, String.class);
        String serviceBrokerSpaceGuid = getServiceBrokerSpaceGuid(context, appAttributes);

        if (serviceBrokerName == null) {
            throw new ContentException(Messages.MISSING_SERVICE_BROKER_NAME, app.getName());
        }
        if (serviceBrokerUsername == null) {
            throw new ContentException(Messages.MISSING_SERVICE_BROKER_USERNAME, app.getName());
        }
        if (serviceBrokerPassword == null) {
            throw new ContentException(Messages.MISSING_SERVICE_BROKER_PASSWORD, app.getName());
        }
        if (serviceBrokerUrl == null) {
            throw new ContentException(Messages.MISSING_SERVICE_BROKER_URL, app.getName());
        }

        return ImmutableCloudServiceBroker.builder()
                                          .name(serviceBrokerName)
                                          .username(serviceBrokerUsername)
                                          .password(serviceBrokerPassword)
                                          .url(serviceBrokerUrl)
                                          .spaceGuid(serviceBrokerSpaceGuid)
                                          .build();
    }

    private String getServiceBrokerSpaceGuid(ProcessContext context, ApplicationAttributes appAttributes) {
        boolean isSpaceScoped = appAttributes.get(SupportedParameters.SERVICE_BROKER_SPACE_SCOPED, Boolean.class, false);
        return isSpaceScoped ? context.getVariable(Variables.SPACE_GUID) : null;
    }

    private CloudServiceBroker findServiceBroker(List serviceBrokers, String name) {
        return serviceBrokers.stream()
                             .filter(broker -> broker.getName()
                                                     .equals(name))
                             .findFirst()
                             .orElseThrow(() -> new NotFoundException(MessageFormat.format(Messages.SERVICE_BROKER_0_DOES_NOT_EXIST,
                                                                                           name)));
    }

    private CloudServiceBroker mergeServiceBrokerMetadata(CloudServiceBroker serviceBroker, CloudServiceBroker existingBroker) {
        CloudServiceBroker mergedServiceBrokerMetadata = ImmutableCloudServiceBroker.copyOf(serviceBroker)
                                                                                    .withMetadata(existingBroker.getMetadata());
        if (existingBroker.getSpaceGuid() != null && mergedServiceBrokerMetadata.getSpaceGuid() == null) {
            getStepLogger().warn(MessageFormat.format(Messages.CANNOT_CHANGE_VISIBILITY_OF_SERVICE_BROKER_FROM_SPACE_SCOPED_TO_GLOBAL,
                                                      mergedServiceBrokerMetadata.getName()));
        } else if (existingBroker.getSpaceGuid() == null && serviceBroker.getSpaceGuid() != null) {
            getStepLogger().warn(MessageFormat.format(Messages.CANNOT_CHANGE_VISIBILITY_OF_SERVICE_BROKER_FROM_GLOBAL_TO_SPACE_SCOPED,
                                                      mergedServiceBrokerMetadata.getName()));
        }
        return mergedServiceBrokerMetadata;
    }

    public static List getServiceBrokerNames(List serviceBrokers) {
        return serviceBrokers.stream()
                             .map(CloudServiceBroker::getName)
                             .collect(Collectors.toList());
    }

    protected String updateServiceBroker(ProcessContext context, CloudServiceBroker serviceBroker, CloudControllerClient client) {
        try {
            getStepLogger().info(MessageFormat.format(Messages.UPDATING_SERVICE_BROKER, serviceBroker.getName()));
            return client.updateServiceBroker(serviceBroker);
        } catch (CloudOperationException e) {
            switch (e.getStatusCode()) {
                case NOT_IMPLEMENTED:
                    getStepLogger().warn(Messages.UPDATE_OF_SERVICE_BROKERS_FAILED_501, serviceBroker.getName());
                    return null;
                case FORBIDDEN:
                    if (shouldSucceed(context)) {
                        getStepLogger().warn(Messages.UPDATE_OF_SERVICE_BROKERS_FAILED_403, serviceBroker.getName());
                        return null;
                    }
                    context.setVariable(Variables.SERVICE_OFFERING, serviceBroker.getName());
                    throw new CloudServiceBrokerException(e);
                case BAD_GATEWAY:
                    context.setVariable(Variables.SERVICE_OFFERING, serviceBroker.getName());
                    throw new CloudServiceBrokerException(e);
                default:
                    throw e;
            }
        }
    }

    private String createServiceBroker(ProcessContext context, CloudServiceBroker serviceBroker, CloudControllerClient client) {
        try {
            getStepLogger().info(MessageFormat.format(Messages.CREATING_SERVICE_BROKER, serviceBroker.getName()));
            return client.createServiceBroker(serviceBroker);
        } catch (CloudOperationException e) {
            switch (e.getStatusCode()) {
                case FORBIDDEN:
                    if (shouldSucceed(context)) {
                        getStepLogger().warn(Messages.CREATE_OF_SERVICE_BROKERS_FAILED_403, serviceBroker.getName());
                        return null;
                    }
                    throw new CloudServiceBrokerException(e);
                case BAD_GATEWAY:
                    throw new CloudServiceBrokerException(e);
                default:
                    throw e;
            }
        }
    }

    private boolean shouldSucceed(ProcessContext context) {
        return context.getVariable(Variables.NO_FAIL_ON_MISSING_PERMISSIONS);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy