diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 7de8612..f199769 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2024-10-07 18:05:57 UTC using RuboCop version 1.66.1. +# on 2024-10-07 22:05:47 UTC using RuboCop version 1.66.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -70,7 +70,7 @@ Metrics/MethodLength: # Offense count: 1 # Configuration parameters: CountComments, CountAsOne. Metrics/ModuleLength: - Max: 183 + Max: 188 # Offense count: 1 # This cop supports unsafe autocorrection (--autocorrect-all). @@ -139,7 +139,7 @@ RSpec/MultipleMemoizedHelpers: RSpec/NestedGroups: Max: 4 -# Offense count: 37 +# Offense count: 38 # Configuration parameters: Include, CustomTransform, IgnoreMethods, IgnoreMetadata. # Include: **/*_spec.rb RSpec/SpecFilePathFormat: @@ -162,7 +162,7 @@ Style/MissingRespondToMissing: Exclude: - 'lib/droplet_kit/client.rb' -# Offense count: 5 +# Offense count: 6 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: AllowMethodsWithArguments, AllowedMethods, AllowedPatterns, AllowComments. # AllowedMethods: define_method @@ -171,6 +171,7 @@ Style/SymbolProc: - 'lib/droplet_kit/resources/container_registry_resource.rb' - 'lib/droplet_kit/resources/droplet_action_resource.rb' - 'lib/droplet_kit/resources/kubernetes_cluster_resource.rb' + - 'lib/droplet_kit/resources/one_click_resource.rb' - 'lib/tasks/resource_doc.rake' # Offense count: 106 diff --git a/README.md b/README.md index 4ce6d77..565c2b3 100644 --- a/README.md +++ b/README.md @@ -675,6 +675,16 @@ Actions supported: * `client.container_registry_repository.delete_tag(registry_name: 'registry', repository: 'repo', tag: 'tag')` * `client.container_registry_repository.delete_manifest(registry_name: 'registry', repository: 'repo', manifest_digest: 'sha256:cb8a924afdf0229ef7515d9e5b3024e23b3eb03ddbba287f4a19c6ac90b8d221')` +## 1-Click Applications resource + + client = DropletKit::Client.new(access_token: 'TOKEN') + client.one_clicks #=> DropletKit::OneClickResource + +Actions supported: + +* `client.one_clicks.all(type: 'kubernetes|droplet')` +* `client.one_clicks.create_kubernetes(one_click_kubernetes)` + ## Contributing 1. Fork it ( https://github.com/digitalocean/droplet_kit/fork ) diff --git a/lib/droplet_kit.rb b/lib/droplet_kit.rb index bd468a1..50679e0 100644 --- a/lib/droplet_kit.rb +++ b/lib/droplet_kit.rb @@ -79,6 +79,8 @@ module DropletKit autoload :VPC, 'droplet_kit/models/vpc' autoload :VPCMember, 'droplet_kit/models/vpc_member' autoload :VPCPeering, 'droplet_kit/models/vpc_peering' + autoload :OneClick, 'droplet_kit/models/one_click' + autoload :OneClickKubernetes, 'droplet_kit/models/one_click_kubernetes' # Resources autoload :DropletResource, 'droplet_kit/resources/droplet_resource' @@ -115,6 +117,7 @@ module DropletKit autoload :KubernetesOptionsResource, 'droplet_kit/resources/kubernetes_options_resource' autoload :VPCResource, 'droplet_kit/resources/vpc_resource' autoload :VPCPeeringResource, 'droplet_kit/resources/vpc_peering_resource' + autoload :OneClickResource, 'droplet_kit/resources/one_click_resource' # JSON Maps autoload :DropletMapping, 'droplet_kit/mappings/droplet_mapping' @@ -187,6 +190,8 @@ module DropletKit autoload :VPCMapping, 'droplet_kit/mappings/vpc_mapping' autoload :VPCMemberMapping, 'droplet_kit/mappings/vpc_member_mapping' autoload :VPCPeeringMapping, 'droplet_kit/mappings/vpc_peering_mapping' + autoload :OneClickMapping, 'droplet_kit/mappings/one_click_mapping' + autoload :OneClickKubernetesMapping, 'droplet_kit/mappings/one_click_kubernetes_mapping' # Utils autoload :PaginatedResource, 'droplet_kit/paginated_resource' diff --git a/lib/droplet_kit/client.rb b/lib/droplet_kit/client.rb index 49a8989..a9b307a 100644 --- a/lib/droplet_kit/client.rb +++ b/lib/droplet_kit/client.rb @@ -81,7 +81,8 @@ def self.resources volumes: VolumeResource, volume_actions: VolumeActionResource, vpcs: VPCResource, - vpc_peerings: VPCPeeringResource + vpc_peerings: VPCPeeringResource, + one_clicks: OneClickResource } end diff --git a/lib/droplet_kit/mappings/one_click_kubernetes_mapping.rb b/lib/droplet_kit/mappings/one_click_kubernetes_mapping.rb new file mode 100644 index 0000000..71f09ec --- /dev/null +++ b/lib/droplet_kit/mappings/one_click_kubernetes_mapping.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module DropletKit + class OneClickKubernetesMapping + include Kartograph::DSL + + kartograph do + mapping OneClickKubernetes + + scoped :create do + property :addon_slugs + property :cluster_uuid + end + end + end +end diff --git a/lib/droplet_kit/mappings/one_click_mapping.rb b/lib/droplet_kit/mappings/one_click_mapping.rb new file mode 100644 index 0000000..20e722f --- /dev/null +++ b/lib/droplet_kit/mappings/one_click_mapping.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module DropletKit + class OneClickMapping + include Kartograph::DSL + + kartograph do + mapping OneClick + root_key plural: '1_clicks', scopes: [:read] + + scoped :read do + property :slug + property :type + end + end + end +end diff --git a/lib/droplet_kit/models/one_click.rb b/lib/droplet_kit/models/one_click.rb new file mode 100644 index 0000000..54057fb --- /dev/null +++ b/lib/droplet_kit/models/one_click.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +module DropletKit + class OneClick < BaseModel + attribute :slug + attribute :type + end +end diff --git a/lib/droplet_kit/models/one_click_kubernetes.rb b/lib/droplet_kit/models/one_click_kubernetes.rb new file mode 100644 index 0000000..eecf441 --- /dev/null +++ b/lib/droplet_kit/models/one_click_kubernetes.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +module DropletKit + class OneClickKubernetes < BaseModel + attribute :addon_slugs + attribute :cluster_uuid + end +end diff --git a/lib/droplet_kit/resources/one_click_resource.rb b/lib/droplet_kit/resources/one_click_resource.rb new file mode 100644 index 0000000..817179f --- /dev/null +++ b/lib/droplet_kit/resources/one_click_resource.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module DropletKit + class OneClickResource < ResourceKit::Resource + include ErrorHandlingResourcable + + resources do + action :all, 'GET /v2/1-clicks' do + query_keys :type + + handler(200) do |response| + OneClickMapping.extract_collection(response.body, :read) + end + end + + action :create_kubernetes, 'POST /v2/1-clicks/kubernetes' do + body { |object| OneClickKubernetesMapping.representation_for(:create, object) } + + handler(200) { |response| response.body } + end + end + end +end diff --git a/spec/fixtures/one_clicks/all.json b/spec/fixtures/one_clicks/all.json new file mode 100644 index 0000000..e438cb5 --- /dev/null +++ b/spec/fixtures/one_clicks/all.json @@ -0,0 +1,12 @@ +{ + "1_clicks": [ + { + "slug": "monitoring", + "type": "kubernetes" + }, + { + "slug": "wordpress-18-04", + "type": "droplet" + } + ] +} diff --git a/spec/fixtures/one_clicks/create_kubernetes.json b/spec/fixtures/one_clicks/create_kubernetes.json new file mode 100644 index 0000000..9842033 --- /dev/null +++ b/spec/fixtures/one_clicks/create_kubernetes.json @@ -0,0 +1 @@ +{ "message": "Successfully kicked off addon job." } \ No newline at end of file diff --git a/spec/lib/droplet_kit/resources/one_click_resource_spec.rb b/spec/lib/droplet_kit/resources/one_click_resource_spec.rb new file mode 100644 index 0000000..17ff3f5 --- /dev/null +++ b/spec/lib/droplet_kit/resources/one_click_resource_spec.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe DropletKit::OneClickResource do + subject(:resource) { described_class.new(connection: connection) } + + include_context 'resources' + + describe '#all' do + it 'returns kubernetes 1-click apps' do + stub_do_api('/v2/1-clicks?type=kubernetes', :get).to_return(body: api_fixture('one_clicks/all')) + one_clicks = resource.all(type: 'kubernetes') + expect(one_clicks).to all(be_a(DropletKit::OneClick)) + + expect(one_clicks.first.slug).to eq('monitoring') + expect(one_clicks.first.type).to eq('kubernetes') + end + + it 'returns droplet 1-click apps' do + stub_do_api('/v2/1-clicks?type=droplet', :get).to_return(body: api_fixture('one_clicks/all')) + one_clicks = resource.all(type: 'droplet') + expect(one_clicks).to all(be_a(DropletKit::OneClick)) + + expect(one_clicks.last.slug).to eq('wordpress-18-04') + expect(one_clicks.last.type).to eq('droplet') + end + + it_behaves_like 'resource that handles common errors' do + let(:path) { '/v2/1-clicks' } + let(:method) { :get } + let(:action) { :all } + let(:arguments) { { type: 'kubernetes' } } + end + end + + describe '#create_kubernetes' do + context 'with a successful create' do + it 'returns a message' do + one_click_kubernetes = DropletKit::OneClickKubernetes.new( + addon_slugs: %w[slug1 slug2], + cluster_uuid: '177dc8c-12c1-4483-af1c-877eed0f14cb' + ) + + json = DropletKit::OneClickKubernetesMapping.representation_for(:create, one_click_kubernetes) + stub_do_api('/v2/1-clicks/kubernetes', :post).with(body: json).to_return(body: api_fixture('one_clicks/create_kubernetes'), status: 200) + response = resource.create_kubernetes(one_click_kubernetes) + expect(response).to eq('{ "message": "Successfully kicked off addon job." }') + end + end + end +end