diff --git a/lib/travis/api/v3/artifacts_client.rb b/lib/travis/api/v3/artifacts_client.rb new file mode 100644 index 0000000000..53f19fbfe2 --- /dev/null +++ b/lib/travis/api/v3/artifacts_client.rb @@ -0,0 +1,108 @@ +# frozen_string_literal: true + +module Travis::API::V3 + class ArtifactsClient + class ConfigurationError < StandardError; end + + def initialize(user_id) + @user_id = user_id + end + + def create_config(config, image_name = nil) + response = connection.post("/api/config/create", config: config, imageName: image_name) + + handle_errors_and_respond(response) do |body| + body + end + end + + def update_config(config, image_name = nil) + response = connection.post("/api/config/update", config: config, imageName: image_name) + + handle_errors_and_respond(response) do |body| + body + end + end + + def image_logs(image_name) + response = connection.get("/api/#{CGI.escape(image_name)}/logs") + + handle_errors_and_respond(response) do |body| + body + end + end + + def image_info(image_name) + response = connection.get("/api/#{CGI.escape(image_name)}/info") + + handle_errors_and_respond(response) do |body| + body + end + end + + def delete_image(image_name) + response = connection.delete("/api/#{CGI.escape(image_name)}") + + handle_errors_and_respond(response) + + true + end + + def image_build_status(image_name) + response = connection.get("/api/#{CGI.escape(image_name)}/build_status") + + handle_errors_and_respond(response) do |body| + body + end + end + + private + + def handle_errors_and_respond(response) + case response.status + when 200, 201 + yield(response.body.transform_keys { |key| key.to_s.underscore }) if block_given? + when 202 + true + when 204 + true + when 400 + raise Travis::API::V3::ClientError, response.body.fetch('errors', response.body.fetch('Errors', [])).join("\n") + when 403 + raise Travis::API::V3::InsufficientAccess, response.body['rejection_code'] + when 404 + raise Travis::API::V3::NotFound, response.body.fetch('errors', response.body.fetch('Errors', [])).join("\n") + when 422 + raise Travis::API::V3::UnprocessableEntity, response.body.fetch('errors', response.body.fetch('Errors', [])).join("\n") + else + raise Travis::API::V3::ServerError, 'Artifacts API failed' + end + end + + def connection(timeout: 10) + @connection ||= Faraday.new(url: artifacts_url, ssl: { ca_path: '/usr/lib/ssl/certs' }) do |conn| + conn.basic_auth '_', artifacts_auth_key + conn.headers['X-Travis-User-Id'] = @user_id.to_s + conn.headers['Content-Type'] = 'application/json' + conn.request :json + conn.response :json + conn.options[:open_timeout] = timeout + conn.options[:timeout] = timeout + conn.use OpenCensus::Trace::Integrations::FaradayMiddleware if Travis::Api::App::Middleware::OpenCensus.enabled? + conn.adapter :net_http + end + end + + def artifacts_url + Travis.config.artifacts.url || raise(ConfigurationError, 'No artifacts url configured') + end + + def artifacts_auth_key + Travis.config.artifacts.auth_key || raise(ConfigurationError, 'No artifacts auth key configured') + end + + def query_string_from_params(params) + params.delete_if { |_, v| v.nil? || v.empty? }.to_query + end + end +end diff --git a/lib/travis/api/v3/queries/artifacts_config.rb b/lib/travis/api/v3/queries/artifacts_config.rb new file mode 100644 index 0000000000..ddafdde0c0 --- /dev/null +++ b/lib/travis/api/v3/queries/artifacts_config.rb @@ -0,0 +1,17 @@ +module Travis::API::V3 + class Queries::ArtifactsConfig < Query + params :config, :image_name + + def create(user_id) + artifacts_client(user_id).create_config(params['config'], params['image_name']) + end + + def update(user_id) + artifacts_client(user_id).update_config(params['config'], params['image_name']) + end + + def artifacts_client(user_id) + @_artifacts_client ||= ArtifactsClient.new(user_id) + end + end +end diff --git a/lib/travis/api/v3/queries/artifacts_image.rb b/lib/travis/api/v3/queries/artifacts_image.rb new file mode 100644 index 0000000000..1e98831a5a --- /dev/null +++ b/lib/travis/api/v3/queries/artifacts_image.rb @@ -0,0 +1,25 @@ +module Travis::API::V3 + class Queries::ArtifactsImage < Query + params :image_name + + def logs(user_id) + artifacts_client(user_id).image_logs(params['image_name']) + end + + def info(user_id) + artifacts_client(user_id).image_info(params['image_name']) + end + + def delete(user_id) + artifacts_client(user_id).delete_image(params['image_name']) + end + + def build_status(user_id) + artifacts_client(user_id).image_build_status(params['image_name']) + end + + def artifacts_client(user_id) + @_artifacts_client ||= ArtifactsClient.new(user_id) + end + end +end diff --git a/lib/travis/api/v3/renderer/artifacts_config.rb b/lib/travis/api/v3/renderer/artifacts_config.rb new file mode 100644 index 0000000000..ac0f35c7a5 --- /dev/null +++ b/lib/travis/api/v3/renderer/artifacts_config.rb @@ -0,0 +1,23 @@ +module Travis::API::V3 + module Renderer::ArtifactsConfig + extend self + + AVAILABLE_ATTRIBUTES = [:id, :image_name, :is_valid, :is_pushed, :push_sha, :warnings] + + def available_attributes + AVAILABLE_ATTRIBUTES + end + + def render(object, **) + { + '@type': 'artifacts_config'.freeze, + id: object['id'], + image_name: object['image_name'], + is_valid: object['is_valid'], + is_pushed: object['is_pushed'], + push_sha: object['push_sha'], + warnings: object['warnings'] + } + end + end +end \ No newline at end of file diff --git a/lib/travis/api/v3/renderer/artifacts_image_build_status.rb b/lib/travis/api/v3/renderer/artifacts_image_build_status.rb new file mode 100644 index 0000000000..212be87fce --- /dev/null +++ b/lib/travis/api/v3/renderer/artifacts_image_build_status.rb @@ -0,0 +1,19 @@ +module Travis::API::V3 + module Renderer::ArtifactsImageBuildStatus + extend self + + AVAILABLE_ATTRIBUTES = [:name, :status] + + def available_attributes + AVAILABLE_ATTRIBUTES + end + + def render(object, **) + { + '@type': 'artifacts_image_build_status'.freeze, + name: object['name'], + status: object['status'] + } + end + end +end \ No newline at end of file diff --git a/lib/travis/api/v3/renderer/artifacts_image_info.rb b/lib/travis/api/v3/renderer/artifacts_image_info.rb new file mode 100644 index 0000000000..fd4e772dee --- /dev/null +++ b/lib/travis/api/v3/renderer/artifacts_image_info.rb @@ -0,0 +1,21 @@ +module Travis::API::V3 + module Renderer::ArtifactsImageInfo + extend self + + AVAILABLE_ATTRIBUTES = [:name, :config_content, :description, :image_size] + + def available_attributes + AVAILABLE_ATTRIBUTES + end + + def render(object, **) + { + '@type': 'artifacts_image_info'.freeze, + name: object['name'], + config_content: object['config_content'], + description: object['description'], + image_size: object['image_size'] + } + end + end +end \ No newline at end of file diff --git a/lib/travis/api/v3/renderer/artifacts_image_logs.rb b/lib/travis/api/v3/renderer/artifacts_image_logs.rb new file mode 100644 index 0000000000..a7f8beb760 --- /dev/null +++ b/lib/travis/api/v3/renderer/artifacts_image_logs.rb @@ -0,0 +1,19 @@ +module Travis::API::V3 + module Renderer::ArtifactsImageLogs + extend self + + AVAILABLE_ATTRIBUTES = [:name, :log] + + def available_attributes + AVAILABLE_ATTRIBUTES + end + + def render(object, **) + { + '@type': 'artifacts_image_logs'.freeze, + name: object['name'], + log: object['log'] + } + end + end +end \ No newline at end of file diff --git a/lib/travis/api/v3/routes.rb b/lib/travis/api/v3/routes.rb index 5ecd8407fa..447ec6251f 100644 --- a/lib/travis/api/v3/routes.rb +++ b/lib/travis/api/v3/routes.rb @@ -426,5 +426,25 @@ module Routes route '/leads' post :create end + + hidden_resource :artifacts do + route '/artifacts' + + hidden_resource :artifacts_config, as: :config do + route '/config' + + post :create, '/create' + post :update, '/update' + end + + hidden_resource :artifacts_image do + route '/{image_name}' + + get :logs, '/logs' + get :info, '/info' + get :build_status, '/build_status' + delete :delete + end + end end end diff --git a/lib/travis/api/v3/services.rb b/lib/travis/api/v3/services.rb index dc47f38fde..bd5646cbd5 100644 --- a/lib/travis/api/v3/services.rb +++ b/lib/travis/api/v3/services.rb @@ -5,6 +5,8 @@ module Services Accounts = Module.new { extend Services } Active = Module.new { extend Services } Allowance = Module.new { extend Services } + ArtifactsConfig = Module.new { extend Services } + ArtifactsImage = Module.new { extend Services } BetaFeature = Module.new { extend Services } BetaFeatures = Module.new { extend Services } BetaMigrationRequest = Module.new { extend Services } diff --git a/lib/travis/api/v3/services/artifacts_config/create.rb b/lib/travis/api/v3/services/artifacts_config/create.rb new file mode 100644 index 0000000000..1b4a7e0f6f --- /dev/null +++ b/lib/travis/api/v3/services/artifacts_config/create.rb @@ -0,0 +1,10 @@ +module Travis::API::V3 + class Services::ArtifactsConfig::Create < Service + params :config, :image_name + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:artifacts_config).create(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/artifacts_config/update.rb b/lib/travis/api/v3/services/artifacts_config/update.rb new file mode 100644 index 0000000000..2881c58ffb --- /dev/null +++ b/lib/travis/api/v3/services/artifacts_config/update.rb @@ -0,0 +1,10 @@ +module Travis::API::V3 + class Services::ArtifactsConfig::Update < Service + params :config, :image_name + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:artifacts_config).update(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/artifacts_image/build_status.rb b/lib/travis/api/v3/services/artifacts_image/build_status.rb new file mode 100644 index 0000000000..68d587b893 --- /dev/null +++ b/lib/travis/api/v3/services/artifacts_image/build_status.rb @@ -0,0 +1,12 @@ +module Travis::API::V3 + class Services::ArtifactsImage::BuildStatus < Service + params :image_name + result_type :artifacts_image_build_status + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:artifacts_image).build_status(access_control.user.id) + end + end + end + \ No newline at end of file diff --git a/lib/travis/api/v3/services/artifacts_image/delete.rb b/lib/travis/api/v3/services/artifacts_image/delete.rb new file mode 100644 index 0000000000..498e758b1f --- /dev/null +++ b/lib/travis/api/v3/services/artifacts_image/delete.rb @@ -0,0 +1,10 @@ +module Travis::API::V3 + class Services::ArtifactsImage::Delete < Service + params :image_name + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + query(:artifacts_image).delete(access_control.user.id) and deleted + end + end +end diff --git a/lib/travis/api/v3/services/artifacts_image/info.rb b/lib/travis/api/v3/services/artifacts_image/info.rb new file mode 100644 index 0000000000..ce63c876b9 --- /dev/null +++ b/lib/travis/api/v3/services/artifacts_image/info.rb @@ -0,0 +1,11 @@ +module Travis::API::V3 + class Services::ArtifactsImage::Info < Service + params :image_name + result_type :artifacts_image_info + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:artifacts_image).info(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/artifacts_image/logs.rb b/lib/travis/api/v3/services/artifacts_image/logs.rb new file mode 100644 index 0000000000..bed9897199 --- /dev/null +++ b/lib/travis/api/v3/services/artifacts_image/logs.rb @@ -0,0 +1,11 @@ +module Travis::API::V3 + class Services::ArtifactsImage::Logs < Service + params :image_name + result_type :artifacts_image_logs + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:artifacts_image).logs(access_control.user.id) + end + end +end diff --git a/lib/travis/config/defaults.rb b/lib/travis/config/defaults.rb index caedc2019c..f948dde159 100644 --- a/lib/travis/config/defaults.rb +++ b/lib/travis/config/defaults.rb @@ -88,7 +88,8 @@ def fallback_logs_api_auth_token force_authentication: false, yml: { url: 'https://yml.travis-ci.org', token: 'secret', auth_key: 'abc123' }, read_only: ENV['READ_ONLY'] || false, - vcs: {} + vcs: {}, + artifacts: { url: 'http://artifacts:5001', auth_key: 'VALIDTOKEN' } default :_access => [:key]