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

com.atlassian.bamboo.specs.util.BambooServer Maven / Gradle / Ivy

There is a newer version: 10.1.0
Show newest version
package com.atlassian.bamboo.specs.util;

import com.atlassian.bamboo.specs.api.builders.RootEntityPropertiesBuilder;
import com.atlassian.bamboo.specs.api.exceptions.BambooSpecsPublishingException;
import com.atlassian.bamboo.specs.api.exceptions.BambooSpecsPublishingException.ErrorType;
import com.atlassian.bamboo.specs.api.rsbs.RunnerSettings;
import com.atlassian.bamboo.specs.exceptions.BambooSpecsRestRequestException;
import com.atlassian.bamboo.specs.util.Logger.LogLevel;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.conn.UnsupportedSchemeException;
import org.jetbrains.annotations.NotNull;

import java.io.BufferedWriter;
import java.io.IOException;
import java.net.ConnectException;
import java.net.URI;
import java.net.UnknownHostException;
import java.nio.file.Files;
import java.nio.file.Path;

/**
 * Represents an instance of Bamboo server for publishing {@link RootEntityPropertiesBuilder entities}.
 */
public class BambooServer {
    private static final Logger log = Logger.getLogger(BambooServer.class);

    private final URI baseUrl;
    private final AuthenticationProvider authenticationProvider;


    /**
     * Create an instance of Bamboo server.
     * @param baseUrl                base URL of the Bamboo server, e.g. http://bamboo.example.com/ (ignored when in RSS mode)
    */
    public BambooServer(@NotNull String baseUrl) {
        this(baseUrl, RunnerSettings.isRestEnabled() ? new FileAuthenticationProvider() : new SimpleUserPasswordCredentials("none", "none"));
    }

    /**
     * Create an instance of Bamboo server with specified {@link AuthenticationProvider}.
     *
     * @param baseUrl                base URL of the Bamboo server, e.g. http://bamboo.example.com/ (ignored when in RSS mode)
     * @param authenticationProvider credentials to use for contacting Bamboo (ignored when in RSS mode)
     */
    public BambooServer(@NotNull String baseUrl, @NotNull AuthenticationProvider authenticationProvider) {
        this.baseUrl = URI.create(baseUrl + '/');
        this.authenticationProvider = authenticationProvider;
    }

    /**
     * Get base URL for the Bamboo server.
     */
    public URI getBaseUrl() {
        return baseUrl;
    }

    /**
     * Publishes the given entity to Bamboo server. The exact behavior of this method depends on the state of {@link RunnerSettings}.
     * In RSS mode, url and authentication parameters are ignored and calling this method on any BambooServer object results in publishing the object to the current
     * Bamboo instance. When publishing using Maven profile (mvn -Ppublish-specs) the Specs objects are sent to a Bamboo instance located at {@link #baseUrl}.
     *
     * See also: {@link com.atlassian.bamboo.specs.api.context.RssRuntimeContext}
     *
     * @param entityProperties entity to publish
     * @return result of the publishing
     * @throws BambooSpecsPublishingException if publishing fails
     */
    public Object publish(@NotNull final RootEntityPropertiesBuilder entityProperties) {
        log.info("Publishing " + entityProperties.humanReadableId());

        final String yaml = BambooSpecSerializer.dump(entityProperties);

        final Path yamlDir = RunnerSettings.getYamlDir();
        if (yamlDir != null) {
            // let's group entities of the same type in a common subdirectory
            final Path subDir = yamlDir.resolve(getSubdirectoryName(entityProperties));
            try {
                Files.createDirectories(subDir);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            final Path outputPath = subDir.resolve(YamlFile.getFileName(entityProperties, yaml));
            log.info("Writing specs into " + outputPath);
            try (BufferedWriter bw = Files.newBufferedWriter(outputPath)) {
                bw.write(yaml);
            } catch (final IOException e) {
                throw new RuntimeException(e);
            }
        }

        if (!RunnerSettings.isRestEnabled()) {
            return new Object();
        }

        final RestTaskFactory.RestTask restTask = RestTaskFactory.create(getBaseUrl(), authenticationProvider, entityProperties, yaml);
        final RestTaskResult result = SendQueue.put(restTask);

        if (result.getException() != null) {
            final BambooSpecsPublishingException exception = translateException(entityProperties, result.getException());
            log.info(exception.getMessage());
            if (StringUtils.isNotEmpty(exception.getDebugMessage())) {
                LogUtils.hintLogLevel(log, LogLevel.DEBUG);
                log.debug(exception.getDebugMessage());
            }
            throw exception;
        } else {
            log.info("Successfully published " + entityProperties.humanReadableId());
            return result.getResult();
        }
    }

    private static String getSubdirectoryName(@NotNull final RootEntityPropertiesBuilder entityProperties) {
        return entityProperties.humanReadableType().replaceAll("\\W", "-");
    }

    @NotNull
    private BambooSpecsPublishingException translateException(@NotNull RootEntityPropertiesBuilder entityProperties,
                                                              @NotNull Exception exception) {
        if (exception instanceof UnknownHostException) {
            return new BambooSpecsPublishingException(
                    entityProperties,
                    ErrorType.UNKNOWN_HOST,
                    String.format("Could not reach Bamboo at %s - please make sure the URL is correct and that there are no network problems", getBaseUrl()),
                    null,
                    exception);
        } else if (exception instanceof ConnectException) {
            return new BambooSpecsPublishingException(
                    entityProperties,
                    ErrorType.CONNECTION_ERROR,
                    String.format("Could not connect to Bamboo at %s - please make sure the URL is correct and that Bamboo is running", getBaseUrl()),
                    null,
                    exception);
        } else if (exception instanceof ClientProtocolException
                || exception instanceof UnsupportedSchemeException) {
            return new BambooSpecsPublishingException(
                    entityProperties,
                    ErrorType.PROTOCOL_ERROR,
                    String.format("Could not connect to Bamboo at %s - please make sure the URL is valid and that it uses HTTP(S) protocol", getBaseUrl()),
                    null,
                    exception);
        } else if (exception instanceof BambooSpecsRestRequestException) {
            return translateRestException(entityProperties, (BambooSpecsRestRequestException) exception);
        } else {
            // unknown error - throw generic exception
            return new BambooSpecsPublishingException(entityProperties, null, null, null, exception);
        }
    }

    @NotNull
    private BambooSpecsPublishingException translateRestException(@NotNull RootEntityPropertiesBuilder entityProperties,
                                                                  @NotNull BambooSpecsRestRequestException restException) {
        switch (restException.getStatusCode()) {
            case HttpStatus.SC_UNAUTHORIZED: {
                final String errorMessage = String.format(
                        "Could not authenticate user in Bamboo at %s - please make sure the credentials are correct: %s",
                        getBaseUrl(), authenticationProvider);
                return new BambooSpecsPublishingException(
                        entityProperties,
                        ErrorType.UNAUTHORIZED,
                        errorMessage,
                        restException.getResponseEntity(),
                        restException);
            }
            default: {
                final String errorMessage = StringUtils.defaultString(
                        restException.getMessage(),
                        String.format("Unknown response from Bamboo at %s (HTTP %d)", getBaseUrl(), restException.getStatusCode()));
                return new BambooSpecsPublishingException(
                        entityProperties,
                        null,
                        errorMessage,
                        restException.getResponseEntity(),
                        restException);
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy