├── .rspec ├── .yardopts ├── lib ├── akamai_api │ ├── version.rb │ ├── cli.rb │ ├── cli │ │ ├── ccu.rb │ │ ├── eccu.rb │ │ ├── app.rb │ │ ├── ccu │ │ │ ├── base.rb │ │ │ ├── purge_renderer.rb │ │ │ ├── cp_code.rb │ │ │ ├── arl.rb │ │ │ └── status_renderer.rb │ │ ├── command.rb │ │ └── eccu │ │ │ └── entry_renderer.rb │ ├── error.rb │ ├── eccu │ │ ├── token.rb │ │ ├── not_found.rb │ │ ├── invalid_domain.rb │ │ ├── list_request.rb │ │ ├── base_request.rb │ │ ├── destroy_request.rb │ │ ├── find_request.rb │ │ ├── base_edit_request.rb │ │ ├── update_attribute_request.rb │ │ ├── publish_request.rb │ │ └── tokenizer.rb │ ├── unauthorized.rb │ ├── ccu │ │ ├── unrecognized_option.rb │ │ ├── status.rb │ │ ├── status │ │ │ ├── response.rb │ │ │ └── request.rb │ │ ├── purge.rb │ │ ├── purge_status │ │ │ ├── not_found.rb │ │ │ ├── response.rb │ │ │ └── request.rb │ │ ├── purge_status.rb │ │ ├── base_response.rb │ │ ├── error.rb │ │ └── purge │ │ │ └── response.rb │ ├── eccu.rb │ ├── eccu_request.rb │ └── eccu_parser.rb └── akamai_api.rb ├── bin └── akamai_api ├── features ├── step_definitions │ ├── contain_multiple_times_steps.rb │ └── file_named_with_content_steps.rb ├── ccu_status.feature ├── eccu_requests.feature ├── eccu_last_request.feature ├── ccu_arl_invalidate.feature ├── eccu_publish.feature ├── support │ └── env.rb ├── ccu_cpcode_remove.feature ├── ccu_cpcode_invalidate.feature ├── ccu_arl_remove.feature └── ccu_purge_status.feature ├── spec ├── fixtures │ ├── eccu │ │ ├── parser │ │ │ ├── this_dir_recursive.xml │ │ │ ├── recursive_extension.xml │ │ │ ├── this_dir_only.xml │ │ │ ├── sub_dirs.xml │ │ │ ├── dir_with_extension.xml │ │ │ ├── only_sub_dirs_extension.xml │ │ │ └── dir_with_filename.xml │ │ ├── upload │ │ │ ├── successful.xml │ │ │ └── fault.xml │ │ ├── delete │ │ │ └── successful.xml │ │ ├── set_notes │ │ │ └── successful.xml │ │ ├── set_status_change_email │ │ │ ├── fault.xml │ │ │ └── successful.xml │ │ ├── get_ids │ │ │ └── successful.xml │ │ └── get_info │ │ │ └── successful.xml │ ├── ccu │ │ └── successful_purge.json │ └── eccu_request.xml ├── lib │ └── akamai_api │ │ ├── ccu │ │ ├── base_response_spec.rb │ │ ├── status │ │ │ ├── response_spec.rb │ │ │ └── request_spec.rb │ │ ├── purge │ │ │ └── response_spec.rb │ │ └── purge_status │ │ │ ├── not_found_response_spec.rb │ │ │ ├── response_spec.rb │ │ │ └── request_spec.rb │ │ ├── cli │ │ └── ccu │ │ │ └── status_renderer_spec.rb │ │ ├── eccu_parser_spec.rb │ │ ├── eccu │ │ ├── soap_body_spec.rb │ │ ├── list_request_spec.rb │ │ ├── destroy_request_spec.rb │ │ ├── find_request_spec.rb │ │ ├── tokenizer_spec.rb │ │ └── update_attribute_request_spec.rb │ │ └── ccu_spec.rb ├── features │ ├── eccu │ │ ├── destroy_spec.rb │ │ ├── list_request_spec.rb │ │ ├── parser_integration_spec.rb │ │ ├── update_email_spec.rb │ │ ├── update_notes_spec.rb │ │ ├── publish_request_spec.rb │ │ └── find_request_spec.rb │ └── ccu │ │ └── purge_request_spec.rb └── spec_helper.rb ├── .travis.yml ├── .gitignore ├── Gemfile ├── Guardfile ├── cassettes ├── akamai_api_ccu_status │ ├── valid_credentials.yml │ └── invalid_credentials.yml ├── akamai_api_ccu_purge_status │ ├── invalid_credentials.yml │ ├── enqueued_request.yml │ ├── completed_request.yml │ └── not_found_request.yml ├── akamai_api_ccu_arl_invalidate │ ├── invalid_item.yml │ ├── single_item.yml │ ├── multiple_items.yml │ └── invalid_credentials.yml ├── akamai_api_ccu_cpcode_remove │ ├── invalid_item.yml │ ├── single_item.yml │ ├── multiple_items.yml │ └── invalid_credentials.yml ├── akamai_api_ccu_cpcode_invalidate │ ├── invalid_item.yml │ ├── single_item.yml │ ├── multiple_items.yml │ └── invalid_credentials.yml ├── akamai_api_ccu_arl_remove │ ├── invalid_item.yml │ ├── single_item.yml │ ├── multiple_items.yml │ └── invalid_credentials.yml ├── akamai_api_eccu_destroy │ ├── successful.yml │ ├── not_found_request.yml │ └── invalid_credentials.yml ├── akamai_api_eccu_update_email │ ├── successful.yml │ ├── not_found_request.yml │ └── invalid_credentials.yml ├── akamai_api_eccu_last_request │ └── invalid_credentials.yml ├── akamai_api_eccu_update_notes │ ├── successful.yml │ ├── not_found_request.yml │ └── invalid_credentials.yml ├── akamai_api_eccu_all_ids │ ├── invalid_credentials.yml │ └── successful.yml ├── akamai_api_eccu_requests │ └── invalid_credentials.yml ├── akamai_api_eccu_find │ ├── not_found_request.yml │ ├── invalid_credentials.yml │ └── successful_without_content.yml └── akamai_api_eccu_publish │ ├── invalid_domain.yml │ └── invalid_credentials.yml ├── Thorfile ├── LICENSE.txt ├── akamai_api.gemspec └── wsdls └── ccuapi.wsdl /.rspec: -------------------------------------------------------------------------------- 1 | --colour -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --protected 2 | --no-private 3 | - 4 | LICENSE.txt -------------------------------------------------------------------------------- /lib/akamai_api/version.rb: -------------------------------------------------------------------------------- 1 | module AkamaiApi 2 | VERSION = "1.2.0" 3 | end 4 | -------------------------------------------------------------------------------- /lib/akamai_api/cli.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/cli/app" 2 | 3 | module AkamaiApi::CLI 4 | end 5 | -------------------------------------------------------------------------------- /lib/akamai_api/cli/ccu.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/cli/ccu/base" 2 | 3 | module AkamaiApi::CLI::CCU 4 | end 5 | -------------------------------------------------------------------------------- /lib/akamai_api/cli/eccu.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/cli/eccu/base" 2 | 3 | module AkamaiApi::CLI::ECCU 4 | end 5 | -------------------------------------------------------------------------------- /lib/akamai_api/error.rb: -------------------------------------------------------------------------------- 1 | module AkamaiApi 2 | # Generic superclass for all specific errors that can be raised by AkamaiApi 3 | class Error < StandardError 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /bin/akamai_api: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'active_support' 3 | require 'active_support/core_ext' 4 | require 'akamai_api' 5 | require 'akamai_api/cli' 6 | 7 | AkamaiApi::CLI::App.start 8 | -------------------------------------------------------------------------------- /features/step_definitions/contain_multiple_times_steps.rb: -------------------------------------------------------------------------------- 1 | Then /^the output should contain (\d+) times:$/ do |times, content| 2 | expect(all_output.scan(content).count).to eq times.to_i 3 | end 4 | -------------------------------------------------------------------------------- /spec/fixtures/eccu/parser/this_dir_recursive.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | now 5 | 6 | 7 | -------------------------------------------------------------------------------- /features/step_definitions/file_named_with_content_steps.rb: -------------------------------------------------------------------------------- 1 | Given /^a file named "([^"]*)" with the content of "([^"]*)"$/ do |dest_file_name, source_file_name| 2 | write_file(dest_file_name, File.read(source_file_name)) 3 | end 4 | -------------------------------------------------------------------------------- /lib/akamai_api/eccu/token.rb: -------------------------------------------------------------------------------- 1 | module AkamaiApi::ECCU 2 | 3 | class Token 4 | attr_accessor :type, :value 5 | 6 | def initialize type, value 7 | @type, @value = type, value 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/akamai_api/unauthorized.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/error" 2 | 3 | module AkamaiApi 4 | # A simple subclass of {AkamaiApi::Error} representing the "invalid login credentials" error 5 | class Unauthorized < AkamaiApi::Error; end 6 | end 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | bundler_args: --without development 2 | language: ruby 3 | rvm: 2.2.5 4 | matrix: 5 | fast_finish: true 6 | script: 7 | - bundle exec thor spec 8 | - bundle exec thor features 9 | after_script: bundle exec thor coveralls 10 | -------------------------------------------------------------------------------- /lib/akamai_api/eccu/not_found.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/error" 2 | 3 | module AkamaiApi::ECCU 4 | # A simple subclass of {AkamaiApi::Error} indicating that the requested ECCU resource cannot be found 5 | class NotFound < AkamaiApi::Error; end 6 | end 7 | -------------------------------------------------------------------------------- /spec/fixtures/eccu/parser/recursive_extension.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | now 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/akamai_api/eccu/invalid_domain.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/error" 2 | 3 | module AkamaiApi::ECCU 4 | # A simple subclass of {AkamaiApi::Error} representing a domain the user is not allowed to operate on 5 | class InvalidDomain < AkamaiApi::Error 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/fixtures/eccu/parser/this_dir_only.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | now 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/akamai_api/ccu/unrecognized_option.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/error" 2 | 3 | module AkamaiApi::CCU 4 | # A simple subclass of {AkamaiApi::Error} representing an unrecognized option value provided to the CCU interface 5 | class UnrecognizedOption < AkamaiApi::Error; end 6 | end 7 | -------------------------------------------------------------------------------- /spec/fixtures/eccu/parser/sub_dirs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | now 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /spec/fixtures/ccu/successful_purge.json: -------------------------------------------------------------------------------- 1 | {"estimatedSeconds": 420, "progressUri": "/ccu/v2/purges/6a727459-cc60-11e3-bcb6-55367cb65536", "purgeId": "6a727459-cc60-11e3-bcb6-55367cb65536", "supportId": "17PY1398420021554891-311977056", "httpStatus": 201, "detail": "Request accepted.", "pingAfterSeconds": 420} 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | spec/auth.rb 19 | Gemfile.lock 20 | bin/stubs/ 21 | .idea/** 22 | *.swp 23 | -------------------------------------------------------------------------------- /spec/fixtures/eccu_request.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | now 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /spec/fixtures/eccu/parser/dir_with_extension.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | now 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /spec/fixtures/eccu/parser/only_sub_dirs_extension.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | now 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /spec/fixtures/eccu/parser/dir_with_filename.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | now 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in akamai_api.gemspec 4 | gemspec 5 | 6 | group :test do 7 | gem 'rspec', '>= 3.0.0' 8 | gem 'cucumber' 9 | gem 'aruba', '= 0.5.4' 10 | gem 'webmock' 11 | gem 'vcr' 12 | gem 'coveralls' 13 | gem 'rake' 14 | end 15 | 16 | group :development do 17 | gem 'guard-rspec' 18 | gem 'guard-cucumber' 19 | gem 'yard' 20 | gem 'redcarpet' 21 | end 22 | -------------------------------------------------------------------------------- /lib/akamai_api/eccu.rb: -------------------------------------------------------------------------------- 1 | module AkamaiApi::ECCU 2 | def self.client 3 | build_client 4 | end 5 | 6 | private 7 | 8 | def self.build_client 9 | Savon.client client_args 10 | end 11 | 12 | def self.client_args 13 | { 14 | :wsdl => File.expand_path('../../../wsdls/eccu.wsdl', __FILE__), 15 | :basic_auth => AkamaiApi.config[:auth], 16 | :log => AkamaiApi.config[:log] 17 | } 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /spec/fixtures/eccu/upload/successful.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 1234567 6 | 7 | 8 | -------------------------------------------------------------------------------- /spec/fixtures/eccu/delete/successful.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | 7 | 8 | -------------------------------------------------------------------------------- /lib/akamai_api/ccu/status.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/ccu/status/request" 2 | 3 | # This module encapsulates the classes you need to check the status of the Akamai CCU queue, 4 | # 5 | # @example Checking the status of the Akamai CCU queue 6 | # begin 7 | # res = AkamaiApi::CCU::Status::Request.execute 8 | # puts "There are #{res.queue_length} jobs in queue" 9 | # rescue AkamaiApi::Unauthorized 10 | # puts "Invalid login" 11 | # end 12 | module AkamaiApi::CCU::Status 13 | end 14 | -------------------------------------------------------------------------------- /spec/fixtures/eccu/set_notes/successful.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | 7 | 8 | -------------------------------------------------------------------------------- /spec/lib/akamai_api/ccu/base_response_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AkamaiApi::CCU::BaseResponse do 4 | subject { AkamaiApi::CCU::BaseResponse.new 'supportId' => 'foo', 'httpStatus' => 201 } 5 | 6 | it '#support_id returns the supportId attribute' do 7 | expect(subject.support_id).to eq 'foo' 8 | end 9 | 10 | %w(code http_status).each do |reader| 11 | it "##{reader} returns the httpStatus attribute" do 12 | expect(subject.send reader).to eq 201 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /spec/fixtures/eccu/set_status_change_email/fault.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | false 6 | 7 | 8 | -------------------------------------------------------------------------------- /spec/fixtures/eccu/set_status_change_email/successful.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | 7 | 8 | -------------------------------------------------------------------------------- /lib/akamai_api/ccu/status/response.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/ccu/base_response" 2 | 3 | module AkamaiApi::CCU::Status 4 | # This response class describes the status of the Akamai CCU Queue 5 | class Response < AkamaiApi::CCU::BaseResponse 6 | # @return [Fixnum] Number of jobs in queue 7 | def queue_length 8 | raw['queueLength'] 9 | end 10 | 11 | # @return [String] Message detailing the response 12 | def message 13 | raw['detail'] 14 | end 15 | alias_method :detail, :message 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | # A sample Guardfile 2 | # More info at https://github.com/guard/guard#readme 3 | 4 | guard :rspec, cmd: 'bundle exec rspec' do 5 | watch(%r{^spec/.+_spec\.rb$}) 6 | watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } 7 | watch('spec/spec_helper.rb') { "spec" } 8 | end 9 | 10 | guard 'cucumber' do 11 | watch(%r{^features/.+\.feature$}) 12 | watch(%r{^features/support/.+$}) { 'features' } 13 | watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' } 14 | end 15 | -------------------------------------------------------------------------------- /lib/akamai_api/cli/app.rb: -------------------------------------------------------------------------------- 1 | require "thor" 2 | require "akamai_api/cli/ccu" 3 | require "akamai_api/cli/eccu" 4 | 5 | module AkamaiApi::CLI 6 | class App < Thor 7 | desc 'ccu', 'CCU Interface' 8 | subcommand 'ccu', AkamaiApi::CLI::CCU::Base 9 | 10 | desc 'eccu', 'ECCU Interface' 11 | subcommand 'eccu', AkamaiApi::CLI::ECCU::Base 12 | 13 | def help *args 14 | puts 15 | puts "AkamaiApi is a command line utility to interact with Akamai CCU (Content Control Utility) and ECCU (Enhanced Content Control Utility) services." 16 | puts 17 | super 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/akamai_api/ccu/purge.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/ccu/purge/request" 2 | 3 | # This module encapsulates classes aiming to purge resources using the Akamai CCU interface. 4 | # 5 | # @example Handling a purge response 6 | # begin 7 | # req = AkamaiApi::CCU::Purge::Request.new 8 | # res = req.execute 'http://foo.bar/a.txt', 'http://www.foo.bar/a.txt' 9 | # puts "Request #{res.purge_id} was successful (#{res.message})" 10 | # rescue AkamaiApi::CCU::Error 11 | # puts "Error #{$!.code} - #{$!.message}" 12 | # rescue AkamaiApi::Unauthorized 13 | # puts "Invalid login" 14 | # end 15 | module AkamaiApi::CCU::Purge 16 | end 17 | -------------------------------------------------------------------------------- /lib/akamai_api/ccu/purge_status/not_found.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/ccu/error" 2 | 3 | module AkamaiApi::CCU::PurgeStatus 4 | # {NotFound} is raised when the requested resource cannot be found 5 | class NotFound < AkamaiApi::CCU::Error 6 | # @return [String] URI to use to check the status of the request 7 | def progress_uri 8 | raw['progressUri'] 9 | end 10 | alias_method :uri, :progress_uri 11 | 12 | # @return [Fixnum] Suggested time to wait (in seconds) before asking the status again 13 | def time_to_wait 14 | raw['pingAfterSeconds'] 15 | end 16 | alias_method :ping_after_seconds, :time_to_wait 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /spec/fixtures/eccu/get_ids/successful.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 42994282 7 | 43000154 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /lib/akamai_api/eccu/list_request.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/eccu/soap_body" 2 | require "akamai_api/eccu/base_request" 3 | 4 | module AkamaiApi::ECCU 5 | # Use the {ListRequest} class to get the list of the last submitted ECCU requests 6 | class ListRequest < BaseRequest 7 | # Returns the list of the last submitted ECCU requests 8 | # @return [Array] list of request codes 9 | def self.execute 10 | new.execute 11 | end 12 | 13 | # Returns the list of the last submitted ECCU requests 14 | # @return [Array] list of request codes 15 | def execute 16 | with_soap_error_handling do 17 | Array.wrap client_call(:get_ids)[:file_ids][:file_ids] 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/fixtures/eccu/upload/fault.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | soapenv:Server.generalException 6 | ECCU validation failed: You are not authorized to specify this digital property 7 | 8 | com.akamai.aws.util.AWSFault 9 | example.akamai.com 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /spec/lib/akamai_api/ccu/status/response_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AkamaiApi::CCU::Status::Response do 4 | let(:raw) do 5 | { 6 | 'httpStatus' => 201, 7 | 'queueLength' => 1, 8 | 'detail' => 'asd', 9 | 'supportId' => '21' 10 | } 11 | end 12 | subject { AkamaiApi::CCU::Status::Response.new raw } 13 | 14 | it '#code returns the httpStatus property' do 15 | expect(subject.code).to eq 201 16 | end 17 | 18 | it '#queue_length returns the queueLength property' do 19 | expect(subject.queue_length).to eq 1 20 | end 21 | 22 | it '#message returns the detail property' do 23 | expect(subject.message).to eq 'asd' 24 | end 25 | 26 | it '#support_id returns the supportId property' do 27 | expect(subject.support_id).to eq '21' 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/akamai_api/ccu/purge_status.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/ccu/purge_status/request" 2 | 3 | # This module encapsulates the classes you need to check the status of purge request 4 | # submitted using the Akamai CCU interface. 5 | # 6 | # @example Checking the status of a purge request 7 | # purge_id_or_progress_uri # => "/CCU/v2/purges/12345678-1234-5678-1234-123456789012" 8 | # begin 9 | # res = AkamaiApi::CCU::PurgeStatus::Request.execute purge_id_or_progress_uri 10 | # puts "Request status is '#{res.status}'" 11 | # puts "Request has been completed on '#{res.completed_at}'" if res.completed_at 12 | # rescue AkamaiApi::CCU::Error 13 | # puts "Error #{$!.code} - #{$!.message}" 14 | # rescue AkamaiApi::Unauthorized 15 | # puts "Invalid login" 16 | # end 17 | module AkamaiApi::CCU::PurgeStatus 18 | end 19 | -------------------------------------------------------------------------------- /spec/lib/akamai_api/cli/ccu/status_renderer_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module AkamaiApi 4 | describe CLI::CCU::StatusRenderer do 5 | subject { CLI::CCU::StatusRenderer.new CCU::Status::Response.new({}) } 6 | 7 | describe '#render' do 8 | it 'returns a string' do 9 | expect(subject.render).to be_a String 10 | end 11 | 12 | it 'delegates to #render_status if response is a Status::Response' do 13 | expect(subject).to receive(:queue_status) 14 | subject.render 15 | end 16 | 17 | it 'delegates to #render_purge_status if response is a PurgeStatus::Response' do 18 | subject = CLI::CCU::StatusRenderer.new CCU::PurgeStatus::Response.new({}) 19 | expect(subject).to receive(:purge_status) 20 | subject.render 21 | end 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/akamai_api.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/object/blank" 2 | require "active_support/core_ext/hash" 3 | 4 | %w(version ccu eccu eccu_request eccu_parser).each do |file| 5 | require "akamai_api/#{file}" 6 | end 7 | 8 | module AkamaiApi 9 | def self.config 10 | @config ||= { 11 | :auth => [ 12 | ENV.fetch('AKAMAI_USERNAME', ''), 13 | ENV.fetch('AKAMAI_PASSWORD', ''), 14 | ], 15 | :openapi => {}, 16 | :log => false 17 | } 18 | end 19 | 20 | def self.auth_empty? 21 | config[:auth].select { |v| v.blank? }.any? 22 | end 23 | 24 | def self.auth_ok? 25 | [:username, :password, :base_url, :client_token, :client_secret, :access_token ].all? { |k| auth.key? k } 26 | end 27 | 28 | def self.auth 29 | { username: config[:auth].first, password: config[:auth].last }.merge(config[:openapi].symbolize_keys) 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /lib/akamai_api/ccu/base_response.rb: -------------------------------------------------------------------------------- 1 | module AkamaiApi 2 | module CCU 3 | # @abstract 4 | # This class is intended as a generic superclass for all the specific responses that can be received 5 | # when doing a request through the Akamai CCU interface 6 | class BaseResponse 7 | # @return [Hash] raw Raw object describing the error. 8 | attr_reader :raw 9 | 10 | # @param [Hash] raw Raw object describing the error. 11 | def initialize raw 12 | @raw = raw 13 | end 14 | 15 | # @return [String] Reference provided to Customer Care when needed. 16 | def support_id 17 | raw['supportId'] 18 | end 19 | 20 | # @return [Fixnum] Response HTTP Status Code describing the error 21 | def code 22 | raw['httpStatus'] 23 | end 24 | alias :http_status :code 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /features/ccu_status.feature: -------------------------------------------------------------------------------- 1 | Feature: akamai_api ccu status 2 | In order to get the Akamai CCU queue status 3 | As a CLI user 4 | 5 | @vcr 6 | Scenario: invalid credentials 7 | When I run `akamai_api ccu status -u foo -p bar` 8 | Then the output should contain: 9 | """ 10 | Your login credentials are invalid. 11 | """ 12 | 13 | @vcr 14 | Scenario: valid credentials 15 | When I run `akamai_api ccu status` 16 | Then the output should contain: 17 | """ 18 | Akamai CCU Queue Status 19 | """ 20 | And the output should contain: 21 | """ 22 | * Result: 200 - The queue may take a minute to reflect new or removed requests. 23 | """ 24 | And the output should contain: 25 | """ 26 | * Support ID: 12345678901234567890-123456789 27 | """ 28 | And the output should contain: 29 | """ 30 | * Queue Length: 0 31 | """ -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_status/valid_credentials.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.ccu.akamai.com/ccu/v2/queues/default/ 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: {} 10 | response: 11 | status: 12 | code: 200 13 | message: OK 14 | headers: 15 | Date: 16 | - Tue, 20 May 2014 13:15:51 GMT 17 | Server: 18 | - Apache 19 | Content-Length: 20 | - '161' 21 | Allow: 22 | - GET, HEAD, POST 23 | Vary: 24 | - Authorization 25 | Content-Type: 26 | - application/json 27 | body: 28 | encoding: UTF-8 29 | string: '{"supportId": "12345678901234567890-123456789", "httpStatus": 200, 30 | "detail": "The queue may take a minute to reflect new or removed requests.", 31 | "queueLength": 0}' 32 | http_version: 33 | recorded_at: Tue, 20 May 2014 13:15:52 GMT 34 | recorded_with: VCR 2.9.0 35 | -------------------------------------------------------------------------------- /lib/akamai_api/cli/ccu/base.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/ccu" 2 | require "akamai_api/cli/command" 3 | require "akamai_api/cli/ccu/cp_code" 4 | require "akamai_api/cli/ccu/arl" 5 | require "akamai_api/cli/ccu/status_renderer" 6 | 7 | module AkamaiApi::CLI::CCU 8 | class Base < AkamaiApi::CLI::Command 9 | desc 'cpcode', 'CP Code CCU actions' 10 | subcommand 'cpcode', CpCode 11 | 12 | desc 'arl', 'ARL CCU actions' 13 | subcommand 'arl', Arl 14 | 15 | desc 'status [progress_uri]', 'Show the CCU queue status if no progress_uri is given, or show a CCU Purge request status if a progress uri is given' 16 | def status progress_uri = nil 17 | load_config 18 | response = AkamaiApi::CCU.status progress_uri 19 | puts StatusRenderer.new(response).render 20 | rescue AkamaiApi::CCU::Error => e 21 | puts StatusRenderer.new(e).render_error 22 | rescue AkamaiApi::Unauthorized 23 | puts 'Your login credentials are invalid.' 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /spec/lib/akamai_api/ccu/status/request_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AkamaiApi::CCU::Status::Request do 4 | it 'executes a get upon base url passing the basic auth' do 5 | fake_response = double code: 200, parsed_response: {} 6 | allow(AkamaiApi).to receive(:auth) { 'foo' } 7 | expect(AkamaiApi::CCU::Status::Request).to receive(:get).with('/', basic_auth: 'foo').and_return fake_response 8 | subject.execute 9 | end 10 | 11 | it 'raises an unauthorized error if code is 401' do 12 | fake_response = double code: 401, parsed_response: {} 13 | expect(AkamaiApi::CCU::Status::Request).to receive(:get).and_return fake_response 14 | expect { subject.execute }.to raise_error AkamaiApi::Unauthorized 15 | end 16 | 17 | it 'returns a StatusResponse' do 18 | fake_response = double code: 200, parsed_response: {} 19 | expect(AkamaiApi::CCU::Status::Request).to receive(:get).and_return fake_response 20 | expect(subject.execute).to be_a AkamaiApi::CCU::Status::Response 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_status/invalid_credentials.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.ccu.akamai.com/ccu/v2/queues/default/ 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: {} 10 | response: 11 | status: 12 | code: 401 13 | message: Unauthorized 14 | headers: 15 | Date: 16 | - Tue, 20 May 2014 13:15:50 GMT 17 | Server: 18 | - Apache 19 | Content-Length: 20 | - '146' 21 | Allow: 22 | - GET, HEAD, POST 23 | Www-Authenticate: 24 | - Basic realm="Luna Control Center" 25 | Vary: 26 | - Authorization 27 | Content-Type: 28 | - text/html;charset=utf-8 29 | body: 30 | encoding: UTF-8 31 | string: 401 Unauthorized

401 Unauthorized

You 32 | are not authorized to access that resource

33 | http_version: 34 | recorded_at: Tue, 20 May 2014 13:15:51 GMT 35 | recorded_with: VCR 2.9.0 36 | -------------------------------------------------------------------------------- /spec/features/eccu/destroy_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "Given I want to destroy a request" do 4 | subject { AkamaiApi::ECCURequest.new code: '1234' } 5 | 6 | context "when login credentials are invalid", vcr: { cassette_name: "akamai_api_eccu_destroy/invalid_credentials" } do 7 | before do 8 | allow(AkamaiApi).to receive(:config) { { auth: ['foo', 'bar'] } } 9 | allow(AkamaiApi::ECCU).to receive(:client) { AkamaiApi::ECCU.send(:build_client) } 10 | end 11 | 12 | it "raises Unauthorized" do 13 | expect { subject.destroy }.to raise_error AkamaiApi::Unauthorized 14 | end 15 | end 16 | 17 | context "when request id cannot be found", vcr: { cassette_name: "akamai_api_eccu_destroy/not_found_request" } do 18 | it "raises NotFound" do 19 | expect { subject.destroy }.to raise_error AkamaiApi::ECCU::NotFound 20 | end 21 | end 22 | 23 | context "when request id is found", vcr: { cassette_name: "akamai_api_eccu_destroy/successful" } do 24 | it "returns true" do 25 | expect(subject.destroy).to be_truthy 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /spec/features/eccu/list_request_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "Given I want to retrieve all submitted request ids" do 4 | subject { AkamaiApi::ECCURequest } 5 | 6 | context "when login credentials are invalid", vcr: { cassette_name: "akamai_api_eccu_all_ids/invalid_credentials" } do 7 | before do 8 | allow(AkamaiApi).to receive(:config) { { auth: ['foo', 'bar'] } } 9 | allow(AkamaiApi::ECCU).to receive(:client) { AkamaiApi::ECCU.send(:build_client) } 10 | end 11 | 12 | it "raises Unauthorized" do 13 | expect { subject.all_ids }.to raise_error AkamaiApi::Unauthorized 14 | end 15 | end 16 | 17 | context "when credentials are valid", vcr: { cassette_name: "akamai_api_eccu_all_ids/successful" } do 18 | it "returns a list of ids" do 19 | expect(subject.all_ids).to eq ["12341", "12342", "12343", "12344", "12345", "12346", "12347", "12348", "12349", "12350", "12351", "12352", "12353", "12354", "12355", "12356", "12357", "12358", "12359", "12360", "12361", "12362", "12363", "12364", "12365", "12366", "12367", "12368", "12369", "12370", "12371"] 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/akamai_api/ccu/error.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/error" 2 | 3 | module AkamaiApi::CCU 4 | # Error received after a request done through the Akamai CCU interface. 5 | class Error < AkamaiApi::Error 6 | # @return [Hash] raw Raw object describing the error. 7 | attr_reader :raw 8 | 9 | # @param [Hash] raw Raw object describing the error. 10 | def initialize raw 11 | @raw = raw 12 | super raw['title'] || raw['detail'] 13 | end 14 | 15 | # @return [String] Reference provided to Customer Care when needed. 16 | def support_id 17 | raw['supportId'] 18 | end 19 | 20 | # @return [String] Specific detail about the error 21 | def detail 22 | raw['detail'] 23 | end 24 | 25 | alias_method :title, :message 26 | 27 | # @return [Fixnum] Response HTTP Status Code describing the error 28 | def code 29 | raw['httpStatus'] 30 | end 31 | alias_method :http_status, :code 32 | 33 | # @return [String] URI pointing to a verbose error description 34 | def described_by 35 | raw['describedBy'] 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /spec/features/eccu/parser_integration_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | def open_expected_file( filename ) 4 | content = File.open(File.dirname(__FILE__) + "/../../fixtures/eccu/parser/#{filename}", "r").read 5 | strip_content content 6 | end 7 | 8 | def strip_content( xml ) 9 | xml.gsub(/(\n|\t|\r)/, " ").gsub(/>\s*<").strip 10 | end 11 | 12 | describe 'Some example of input -> output' do 13 | 14 | tests = { 15 | "foo/" => "this_dir_only.xml", 16 | "foo/**" => "this_dir_recursive.xml", 17 | "foo/*" => "sub_dirs.xml", 18 | "foo/*/" => "sub_dirs.xml", 19 | "foo/bar.txt" => "dir_with_filename.xml", 20 | "eccu_test/**/*.txt" => "recursive_extension.xml", 21 | "eccu_test/*/*.txt" => "only_sub_dirs_extension.xml", 22 | "eccu_test/*.txt" => "dir_with_extension.xml", 23 | } 24 | 25 | tests.each do |expression, file| 26 | context expression do 27 | let(:parser){ AkamaiApi::ECCUParser.new expression } 28 | it{ expect( strip_content( parser.xml ) ).to eq( open_expected_file(file) ) } 29 | end 30 | end 31 | 32 | end 33 | -------------------------------------------------------------------------------- /Thorfile: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | $:.unshift File.expand_path("../lib", __FILE__) 3 | 4 | require 'bundler' 5 | require 'thor/rake_compat' 6 | 7 | class Default < Thor 8 | include Thor::RakeCompat 9 | Bundler::GemHelper.install_tasks 10 | 11 | desc "build", "Build akamai_api-#{AkamaiApi::VERSION}.gem into the pkg directory" 12 | def build 13 | Rake::Task["build"].execute 14 | end 15 | 16 | desc "install", "Build and install akamai_api-#{AkamaiApi::VERSION}.gem into system gems" 17 | def install 18 | Rake::Task["install"].execute 19 | end 20 | 21 | desc "release", "Create tag v#{AkamaiApi::VERSION} and build and push akamai_api-#{AkamaiApi::VERSION}.gem to Rubygems" 22 | def release 23 | Rake::Task["release"].invoke 24 | end 25 | 26 | desc "spec", "Run RSpec code examples" 27 | def spec 28 | exec "rspec --color --format=documentation spec" 29 | end 30 | 31 | desc "features", "Run Cucumber features" 32 | def features 33 | exec "cucumber" 34 | end 35 | 36 | desc "coveralls", "Push coveralls stats" 37 | def coveralls 38 | require 'coveralls' 39 | Coveralls.push! 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Nicola Racco 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_purge_status/invalid_credentials.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | headers: 5 | Authorization: 6 | - Basic VVNFUk5BTUU6UEFTU1dPUkQ= 7 | method: get 8 | uri: https://api.ccu.akamai.com/ccu/v2/purges/12345678-1234-5678-1234-123456789012 9 | body: 10 | encoding: US-ASCII 11 | string: '' 12 | headers: {} 13 | response: 14 | status: 15 | code: 401 16 | message: Unauthorized 17 | headers: 18 | Date: 19 | - Tue, 20 May 2014 12:49:40 GMT 20 | Server: 21 | - Apache 22 | Content-Length: 23 | - '146' 24 | Allow: 25 | - GET, HEAD 26 | Www-Authenticate: 27 | - Basic realm="Luna Control Center" 28 | Vary: 29 | - Authorization 30 | Content-Type: 31 | - text/html;charset=utf-8 32 | body: 33 | encoding: UTF-8 34 | string: 401 Unauthorized

401 Unauthorized

You 35 | are not authorized to access that resource

36 | http_version: 37 | recorded_at: Tue, 20 May 2014 12:49:40 GMT 38 | recorded_with: VCR 2.9.0 39 | -------------------------------------------------------------------------------- /lib/akamai_api/eccu/base_request.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/unauthorized" 2 | 3 | module AkamaiApi::ECCU 4 | # @abstract 5 | # 6 | # This class is intended as a generic superclass for all the specific requests that can be used 7 | # with the Akamai ECCU interface 8 | class BaseRequest 9 | protected 10 | 11 | # Wrapper method that you can use inside your custom ECCU request to handle common errors 12 | # @raise [AkamaiApi::Unauthorized] when login credentials are invalid 13 | def with_soap_error_handling &block 14 | yield 15 | rescue Savon::HTTPError => e 16 | e = ::AkamaiApi::Unauthorized if e.http.code == 401 17 | raise e 18 | end 19 | 20 | # Executes a method via Savon and returns the response 21 | # @param [String] method method name to call 22 | # @param args additional arguments to pass to savon when calling the method 23 | # @return [Object] the object containing the received response 24 | def client_call method, *args 25 | client.call(method, *args).body["#{method}_response".to_sym] 26 | end 27 | 28 | def client 29 | AkamaiApi::ECCU.client 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_arl_invalidate/invalid_item.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://some-subdomain.purge.akamaiapis.net/ccu/v3/invalidate/url/production 6 | body: 7 | encoding: UTF-8 8 | string: '{"objects":["http://www.foo.bar/t.txt"]}' 9 | headers: 10 | Content-Type: 11 | - application/json 12 | response: 13 | status: 14 | code: 403 15 | message: Forbidden 16 | headers: 17 | Date: 18 | - Thu, 15 May 2014 06:51:09 GMT 19 | Server: 20 | - Apache 21 | Content-Length: 22 | - '209' 23 | Allow: 24 | - GET, HEAD, POST 25 | Vary: 26 | - Authorization 27 | Content-Type: 28 | - application/api-problem+json 29 | body: 30 | encoding: UTF-8 31 | string: '{"supportId": "12345678901234567890-123456789", "title": "unauthorized 32 | arl", "httpStatus": 403, "detail": "http://www.foo.com/bar.txt", "describedBy": 33 | "https://api.ccu.akamai.com/ccu/v2/errors/unauthorized-arl"}' 34 | http_version: 35 | recorded_at: Thu, 15 May 2014 06:51:12 GMT 36 | recorded_with: VCR 2.9.0 37 | -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_cpcode_remove/invalid_item.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://some-subdomain.purge.akamaiapis.net/ccu/v2/queues/default 6 | body: 7 | encoding: UTF-8 8 | string: '{"type":"cpcode","action":"remove","domain":"production","objects":["12345"]}' 9 | headers: 10 | Content-Type: 11 | - application/json 12 | response: 13 | status: 14 | code: 403 15 | message: Forbidden 16 | headers: 17 | Date: 18 | - Thu, 15 May 2014 06:51:09 GMT 19 | Server: 20 | - Apache 21 | Content-Length: 22 | - '209' 23 | Allow: 24 | - GET, HEAD, POST 25 | Vary: 26 | - Authorization 27 | Content-Type: 28 | - application/api-problem+json 29 | body: 30 | encoding: UTF-8 31 | string: '{"supportId": "12345678901234567890-123456789", "title": "unauthorized 32 | cpcode", "httpStatus": 403, "detail": "12345", "describedBy": 33 | "https://api.ccu.akamai.com/ccu/v2/errors/unauthorized-cpcode"}' 34 | http_version: 35 | recorded_at: Thu, 15 May 2014 06:51:12 GMT 36 | recorded_with: VCR 2.9.0 37 | -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_purge_status/enqueued_request.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.ccu.akamai.com/ccu/v2/purges/12345678-1234-5678-1234-123456789012 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: {} 10 | response: 11 | status: 12 | code: 200 13 | message: OK 14 | headers: 15 | Date: 16 | - Tue, 20 May 2014 12:49:41 GMT 17 | Server: 18 | - Apache 19 | Content-Length: 20 | - '309' 21 | Allow: 22 | - GET, HEAD 23 | Vary: 24 | - Authorization 25 | Content-Type: 26 | - application/json 27 | body: 28 | encoding: UTF-8 29 | string: '{"originalEstimatedSeconds": 420, "originalQueueLength": 0, "supportId": 30 | "12345678901234567890-123456789", "httpStatus": 200, "purgeId": "12345678-1234-5678-1234-123456789012", 31 | "completionTime": null, "submittedBy": "test1", "purgeStatus": 32 | "In-Progress", "submissionTime": "2014-05-20T08:19:21Z", "pingAfterSeconds": 60}' 33 | http_version: 34 | recorded_at: Tue, 20 May 2014 12:49:41 GMT 35 | recorded_with: VCR 2.9.0 36 | -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_cpcode_invalidate/invalid_item.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://some-subdomain.purge.akamaiapis.net/ccu/v2/queues/default 6 | body: 7 | encoding: UTF-8 8 | string: '{"type":"cpcode","action":"invalidate","domain":"production","objects":["12345"]}' 9 | headers: 10 | Content-Type: 11 | - application/json 12 | response: 13 | status: 14 | code: 403 15 | message: Forbidden 16 | headers: 17 | Date: 18 | - Thu, 15 May 2014 06:51:09 GMT 19 | Server: 20 | - Apache 21 | Content-Length: 22 | - '209' 23 | Allow: 24 | - GET, HEAD, POST 25 | Vary: 26 | - Authorization 27 | Content-Type: 28 | - application/api-problem+json 29 | body: 30 | encoding: UTF-8 31 | string: '{"supportId": "12345678901234567890-123456789", "title": "unauthorized 32 | cpcode", "httpStatus": 403, "detail": "12345", "describedBy": 33 | "https://api.ccu.akamai.com/ccu/v2/errors/unauthorized-cpcode"}' 34 | http_version: 35 | recorded_at: Thu, 15 May 2014 06:51:12 GMT 36 | recorded_with: VCR 2.9.0 37 | -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_arl_invalidate/single_item.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://some-subdomain.purge.akamaiapis.net/ccu/v3/invalidate/url/production 6 | body: 7 | encoding: UTF-8 8 | string: '{"objects":["http://www.foo.bar/t.txt"]}' 9 | headers: 10 | Content-Type: 11 | - application/json 12 | response: 13 | status: 14 | code: 201 15 | message: Created 16 | headers: 17 | Date: 18 | - Tue, 13 May 2014 15:37:48 GMT 19 | Server: 20 | - Apache 21 | Content-Length: 22 | - '268' 23 | Content-Location: 24 | - /ccu/v2/purges/12345678-1234-5678-1234-123456789012 25 | Allow: 26 | - GET, HEAD, POST 27 | Vary: 28 | - Authorization 29 | Content-Type: 30 | - application/json 31 | body: 32 | encoding: UTF-8 33 | string: '{"estimatedSeconds": 5, "purgeId": "12345678-1234-1234-1234-123456789012", "supportId": "12345678901234567890-123456789", 34 | "httpStatus": 201, "detail": "Request accepted."}' 35 | http_version: 36 | recorded_at: Tue, 13 May 2014 15:37:49 GMT 37 | recorded_with: VCR 2.9.0 38 | -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_arl_invalidate/multiple_items.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://some-subdomain.purge.akamaiapis.net/ccu/v3/invalidate/url/production 6 | body: 7 | encoding: UTF-8 8 | string: '{"objects":["http://www.foo.bar/t.txt","http://www.foo.com/baz.txt"]}' 9 | headers: 10 | Content-Type: 11 | - application/json 12 | response: 13 | status: 14 | code: 201 15 | message: Created 16 | headers: 17 | Date: 18 | - Tue, 13 May 2014 15:37:48 GMT 19 | Server: 20 | - Apache 21 | Content-Length: 22 | - '268' 23 | Content-Location: 24 | - /ccu/v2/purges/12345678-1234-5678-1234-123456789012 25 | Allow: 26 | - GET, HEAD, POST 27 | Vary: 28 | - Authorization 29 | Content-Type: 30 | - application/json 31 | body: 32 | encoding: UTF-8 33 | string: '{"purgeId": "12345678-1234-1234-1234-123456789012", "supportId": "12345678901234567890-123456789", 34 | "httpStatus": 201, "detail": "Request accepted."}' 35 | http_version: 36 | recorded_at: Tue, 13 May 2014 15:37:49 GMT 37 | recorded_with: VCR 2.9.0 38 | -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_arl_remove/invalid_item.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://some-subdomain.purge.akamaiapis.net/ccu/v2/queues/default 6 | body: 7 | encoding: UTF-8 8 | string: '{"type":"arl","action":"remove","domain":"production","objects":["http://www.foo.bar/t.txt"]}' 9 | headers: 10 | Content-Type: 11 | - application/json 12 | response: 13 | status: 14 | code: 403 15 | message: Forbidden 16 | headers: 17 | Date: 18 | - Thu, 15 May 2014 06:51:09 GMT 19 | Server: 20 | - Apache 21 | Content-Length: 22 | - '209' 23 | Allow: 24 | - GET, HEAD, POST 25 | Vary: 26 | - Authorization 27 | Content-Type: 28 | - application/api-problem+json 29 | body: 30 | encoding: UTF-8 31 | string: '{"supportId": "12345678901234567890-123456789", "title": "unauthorized 32 | arl", "httpStatus": 403, "detail": "http://www.foo.bar/t.txt", "describedBy": 33 | "https://api.ccu.akamai.com/ccu/v2/errors/unauthorized-arl"}' 34 | http_version: 35 | recorded_at: Thu, 15 May 2014 06:51:12 GMT 36 | recorded_with: VCR 2.9.0 37 | -------------------------------------------------------------------------------- /spec/features/eccu/update_email_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "Given I want to update the email of a request" do 4 | subject { AkamaiApi::ECCURequest.new code: '1234' } 5 | 6 | context "when login credentials are invalid", vcr: { cassette_name: "akamai_api_eccu_update_email/invalid_credentials" } do 7 | before do 8 | allow(AkamaiApi).to receive(:config) { { auth: ['foo', 'bar'] } } 9 | allow(AkamaiApi::ECCU).to receive(:client) { AkamaiApi::ECCU.send(:build_client) } 10 | end 11 | 12 | it "raises Unauthorized" do 13 | expect { subject.update_email! 'guest@mikamai.com' }.to raise_error AkamaiApi::Unauthorized 14 | end 15 | end 16 | 17 | context "when request id cannot be found", vcr: { cassette_name: "akamai_api_eccu_update_email/not_found_request" } do 18 | it "raises NotFound" do 19 | expect { subject.update_email! 'guest@mikamai.com' }.to raise_error AkamaiApi::ECCU::NotFound 20 | end 21 | end 22 | 23 | context "when request id is found", vcr: { cassette_name: "akamai_api_eccu_update_email/successful" } do 24 | it "returns true" do 25 | expect(subject.update_notes! 'guest@mikamai.com').to be_truthy 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/akamai_api/ccu/purge/response.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/ccu/base_response" 2 | 3 | module AkamaiApi::CCU::Purge 4 | # This class represents the response received after a successful purge request 5 | class Response < AkamaiApi::CCU::BaseResponse 6 | # @return [Fixnum] Suggested time to wait (in seconds) before asking the status again 7 | def time_to_wait 8 | raw['pingAfterSeconds'] 9 | end 10 | alias_method :ping_after_seconds, :time_to_wait 11 | 12 | # Purge Request identifier 13 | # @return [String] Purge Request identifier 14 | def purge_id 15 | raw['purgeId'] 16 | end 17 | 18 | # Message detailing the response 19 | # @return [String] message detailing the response. 20 | def message 21 | raw['detail'] 22 | end 23 | alias_method :detail, :message 24 | 25 | # @return [Fixnum] Estimated time (in seconds) for the operation to be completed 26 | def estimated_time 27 | raw['estimatedSeconds'] 28 | end 29 | alias_method :estimated_seconds, :estimated_time 30 | 31 | # @return [String] URI to use to check the status of the request 32 | def uri 33 | raw['progressUri'] 34 | end 35 | alias_method :progress_uri, :uri 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_purge_status/completed_request.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | headers: 5 | Authorization: 6 | - Basic VVNFUk5BTUU6UEFTU1dPUkQ= 7 | method: get 8 | uri: https://api.ccu.akamai.com/ccu/v2/purges/12345678-1234-5678-1234-123456789012 9 | body: 10 | encoding: US-ASCII 11 | string: '' 12 | headers: {} 13 | response: 14 | status: 15 | code: 200 16 | message: OK 17 | headers: 18 | Date: 19 | - Tue, 20 May 2014 12:49:41 GMT 20 | Server: 21 | - Apache 22 | Content-Length: 23 | - '309' 24 | Allow: 25 | - GET, HEAD 26 | Vary: 27 | - Authorization 28 | Content-Type: 29 | - application/json 30 | body: 31 | encoding: UTF-8 32 | string: '{"originalEstimatedSeconds": 420, "originalQueueLength": 0, "supportId": 33 | "12345678901234567890-123456789", "httpStatus": 200, "purgeId": "12345678-1234-5678-1234-123456789012", 34 | "completionTime": "2014-05-20T08:22:20Z", "submittedBy": "test1", "purgeStatus": 35 | "Done", "submissionTime": "2014-05-20T08:19:21Z"}' 36 | http_version: 37 | recorded_at: Tue, 20 May 2014 12:49:41 GMT 38 | recorded_with: VCR 2.9.0 39 | -------------------------------------------------------------------------------- /lib/akamai_api/eccu/destroy_request.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/eccu/base_edit_request" 2 | 3 | module AkamaiApi::ECCU 4 | # The {DestroyRequest} class is used to delete an ECCU request. 5 | # 6 | # @example 7 | # AkamaiApi::ECCU::DestroyRequest.execute(12345) 8 | class DestroyRequest < BaseEditRequest 9 | # Deletes an ECCU request 10 | # @param [Fixnum] code request code 11 | # @return [true] when the request has been deleted 12 | # @return [false] when the request cannot be deleted 13 | # @raise [AkamaiApi::Unauthorized] when login credentials are invalid 14 | # @raise [AkamaiApi::ECCU::NotFound] when no request can be found with the given code 15 | def self.execute code 16 | new(code).execute 17 | end 18 | 19 | # Deletes an ECCU request 20 | # @return [true] when the request has been deleted 21 | # @return [false] when the request cannot be deleted 22 | # @raise [AkamaiApi::Unauthorized] when login credentials are invalid 23 | # @raise [AkamaiApi::ECCU::NotFound] when no request can be found with the given code 24 | def execute 25 | with_soap_error_handling do 26 | client_call(:delete, message: request_body.to_s)[:success] 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /spec/features/eccu/update_notes_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "Given I want to update the notes of a request" do 4 | subject { AkamaiApi::ECCURequest.new code: '1234' } 5 | 6 | context "when login credentials are invalid", vcr: { cassette_name: "akamai_api_eccu_update_notes/invalid_credentials" } do 7 | before do 8 | allow(AkamaiApi).to receive(:config) { { auth: ['foo', 'bar'] } } 9 | allow(AkamaiApi::ECCU).to receive(:client) { AkamaiApi::ECCU.send(:build_client) } 10 | end 11 | 12 | it "raises Unauthorized" do 13 | expect { subject.update_notes! 'request updated using AkamaiApi' }.to raise_error AkamaiApi::Unauthorized 14 | end 15 | end 16 | 17 | context "when request id cannot be found", vcr: { cassette_name: "akamai_api_eccu_update_notes/not_found_request" } do 18 | it "raises NotFound" do 19 | expect { subject.update_notes! 'request updated using AkamaiApi' }.to raise_error AkamaiApi::ECCU::NotFound 20 | end 21 | end 22 | 23 | context "when request id is found", vcr: { cassette_name: "akamai_api_eccu_update_notes/successful" } do 24 | it "returns true" do 25 | expect(subject.update_notes! 'request updated using AkamaiApi').to be_truthy 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /akamai_api.gemspec: -------------------------------------------------------------------------------- 1 | lib = File.expand_path('../lib', __FILE__) 2 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 3 | require 'akamai_api/version' 4 | 5 | Gem::Specification.new do |gem| 6 | gem.name = "akamai_api" 7 | gem.version = AkamaiApi::VERSION 8 | gem.authors = ["Nicola Racco"] 9 | gem.email = ["nicola@nicolaracco.com"] 10 | gem.description = %q{Ruby toolkit to work with Akamai Content Control Utility API} 11 | gem.summary = %q{Ruby toolkit to work with Akamai Content Control Utility API} 12 | gem.homepage = 'https://github.com/nicolaracco/akamai_api' 13 | 14 | gem.files = `git ls-files`.split($/) 15 | gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } 16 | gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) 17 | gem.require_paths = ["lib"] 18 | gem.required_ruby_version = Gem::Requirement.new(">= 2.2.2") 19 | 20 | gem.add_dependency 'httparty', '~> 0.13.1' 21 | gem.add_dependency 'activesupport', '>= 2.3.9' 22 | gem.add_dependency 'thor', '>= 0.14.0', '< 2.0' 23 | gem.add_dependency 'savon', '~> 2.5' 24 | gem.add_dependency 'builder', '~> 3.0' 25 | gem.add_dependency 'akamai-edgegrid','~> 1.0' 26 | end 27 | -------------------------------------------------------------------------------- /features/eccu_requests.feature: -------------------------------------------------------------------------------- 1 | Feature: akamai_api eccu requests 2 | In order to get the list of the last requests made through ECCU 3 | As a CLI user 4 | 5 | @vcr 6 | Scenario: invalid credentials 7 | When I run `akamai_api eccu requests -u foo -p bar` 8 | Then the output should contain: 9 | """ 10 | Your login credentials are invalid. 11 | """ 12 | 13 | @vcr 14 | Scenario: valid credentials 15 | When I run `akamai_api eccu requests` 16 | Then the output should contain 4 times: 17 | """ 18 | * Status 19 | """ 20 | Then the output should contain: 21 | """ 22 | * Code : 112714868 23 | """ 24 | And the output should contain 4 times: 25 | """ 26 | * Status : 4000 - File successfully deployed to Akamai network (Succeeded) 27 | """ 28 | And the output should contain 3 times: 29 | """ 30 | * Property: foo.com (hostheader) 31 | """ 32 | And the output should contain 4 times: 33 | """ 34 | with exact match 35 | """ 36 | And the output should contain 4 times: 37 | """ 38 | * Notes : ECCU Request using EdgeControl 39 | """ 40 | And the output should contain 4 times: 41 | """ 42 | * Email : guest@mikamai.com 43 | """ -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_purge_status/not_found_request.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | headers: 5 | Authorization: 6 | - Basic VVNFUk5BTUU6UEFTU1dPUkQ= 7 | method: get 8 | uri: https://api.ccu.akamai.com/ccu/v2/purges/foobarbaz 9 | body: 10 | encoding: US-ASCII 11 | string: '' 12 | headers: {} 13 | response: 14 | status: 15 | code: 200 16 | message: OK 17 | headers: 18 | Date: 19 | - Tue, 20 May 2014 13:28:28 GMT 20 | Server: 21 | - Apache 22 | Content-Length: 23 | - '375' 24 | Allow: 25 | - GET, HEAD 26 | Vary: 27 | - Authorization 28 | Content-Type: 29 | - application/json 30 | body: 31 | encoding: UTF-8 32 | string: '{"purgeId": "foobarbaz", "progressUri": "/ccu/v2/purges/foobarbaz", 33 | "supportId": "12345678901234567890-123456789", "httpStatus": 200, "detail": 34 | "Please note that it can take up to a minute for the status of a recently 35 | submitted request to become visible.", "completionTime": null, "submittedBy": 36 | null, "purgeStatus": "Unknown", "submissionTime": null, "pingAfterSeconds": 37 | 60}' 38 | http_version: 39 | recorded_at: Tue, 20 May 2014 13:28:28 GMT 40 | recorded_with: VCR 2.9.0 41 | -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_cpcode_remove/single_item.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://some-subdomain.purge.akamaiapis.net/ccu/v2/queues/default 6 | body: 7 | encoding: UTF-8 8 | string: '{"type":"cpcode","action":"remove","domain":"production","objects":["12345"]}' 9 | headers: 10 | Content-Type: 11 | - application/json 12 | response: 13 | status: 14 | code: 201 15 | message: Created 16 | headers: 17 | Date: 18 | - Tue, 13 May 2014 15:37:48 GMT 19 | Server: 20 | - Apache 21 | Content-Length: 22 | - '268' 23 | Content-Location: 24 | - /ccu/v2/purges/12345678-1234-5678-1234-123456789012 25 | Allow: 26 | - GET, HEAD, POST 27 | Vary: 28 | - Authorization 29 | Content-Type: 30 | - application/json 31 | body: 32 | encoding: UTF-8 33 | string: '{"estimatedSeconds": 420, "progressUri": "/ccu/v2/purges/12345678-1234-5678-1234-123456789012", 34 | "purgeId": "12345678-1234-1234-1234-123456789012", "supportId": "12345678901234567890-123456789", 35 | "httpStatus": 201, "detail": "Request accepted.", "pingAfterSeconds": 420}' 36 | http_version: 37 | recorded_at: Tue, 13 May 2014 15:37:49 GMT 38 | recorded_with: VCR 2.9.0 39 | -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_cpcode_invalidate/single_item.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://some-subdomain.purge.akamaiapis.net/ccu/v2/queues/default 6 | body: 7 | encoding: UTF-8 8 | string: '{"type":"cpcode","action":"invalidate","domain":"production","objects":["12345"]}' 9 | headers: 10 | Content-Type: 11 | - application/json 12 | response: 13 | status: 14 | code: 201 15 | message: Created 16 | headers: 17 | Date: 18 | - Tue, 13 May 2014 15:37:48 GMT 19 | Server: 20 | - Apache 21 | Content-Length: 22 | - '268' 23 | Content-Location: 24 | - /ccu/v2/purges/12345678-1234-5678-1234-123456789012 25 | Allow: 26 | - GET, HEAD, POST 27 | Vary: 28 | - Authorization 29 | Content-Type: 30 | - application/json 31 | body: 32 | encoding: UTF-8 33 | string: '{"estimatedSeconds": 420, "progressUri": "/ccu/v2/purges/12345678-1234-5678-1234-123456789012", 34 | "purgeId": "12345678-1234-1234-1234-123456789012", "supportId": "12345678901234567890-123456789", 35 | "httpStatus": 201, "detail": "Request accepted.", "pingAfterSeconds": 420}' 36 | http_version: 37 | recorded_at: Tue, 13 May 2014 15:37:49 GMT 38 | recorded_with: VCR 2.9.0 39 | -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_cpcode_remove/multiple_items.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://some-subdomain.purge.akamaiapis.net/ccu/v2/queues/default 6 | body: 7 | encoding: UTF-8 8 | string: '{"type":"cpcode","action":"remove","domain":"production","objects":["12345","12346"]}' 9 | headers: 10 | Content-Type: 11 | - application/json 12 | response: 13 | status: 14 | code: 201 15 | message: Created 16 | headers: 17 | Date: 18 | - Tue, 13 May 2014 15:37:48 GMT 19 | Server: 20 | - Apache 21 | Content-Length: 22 | - '268' 23 | Content-Location: 24 | - /ccu/v2/purges/12345678-1234-5678-1234-123456789012 25 | Allow: 26 | - GET, HEAD, POST 27 | Vary: 28 | - Authorization 29 | Content-Type: 30 | - application/json 31 | body: 32 | encoding: UTF-8 33 | string: '{"estimatedSeconds": 420, "progressUri": "/ccu/v2/purges/12345678-1234-5678-1234-123456789012", 34 | "purgeId": "12345678-1234-1234-1234-123456789012", "supportId": "12345678901234567890-123456789", 35 | "httpStatus": 201, "detail": "Request accepted.", "pingAfterSeconds": 420}' 36 | http_version: 37 | recorded_at: Tue, 13 May 2014 15:37:49 GMT 38 | recorded_with: VCR 2.9.0 39 | -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_arl_remove/single_item.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://some-subdomain.purge.akamaiapis.net/ccu/v2/queues/default 6 | body: 7 | encoding: UTF-8 8 | string: '{"type":"arl","action":"remove","domain":"production","objects":["http://www.foo.bar/t.txt"]}' 9 | headers: 10 | Content-Type: 11 | - application/json 12 | response: 13 | status: 14 | code: 201 15 | message: Created 16 | headers: 17 | Date: 18 | - Tue, 13 May 2014 15:37:48 GMT 19 | Server: 20 | - Apache 21 | Content-Length: 22 | - '268' 23 | Content-Location: 24 | - /ccu/v2/purges/12345678-1234-5678-1234-123456789012 25 | Allow: 26 | - GET, HEAD, POST 27 | Vary: 28 | - Authorization 29 | Content-Type: 30 | - application/json 31 | body: 32 | encoding: UTF-8 33 | string: '{"estimatedSeconds": 420, "progressUri": "/ccu/v2/purges/12345678-1234-5678-1234-123456789012", 34 | "purgeId": "12345678-1234-1234-1234-123456789012", "supportId": "12345678901234567890-123456789", 35 | "httpStatus": 201, "detail": "Request accepted.", "pingAfterSeconds": 420}' 36 | http_version: 37 | recorded_at: Tue, 13 May 2014 15:37:49 GMT 38 | recorded_with: VCR 2.9.0 39 | -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_cpcode_invalidate/multiple_items.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://some-subdomain.purge.akamaiapis.net/ccu/v2/queues/default 6 | body: 7 | encoding: UTF-8 8 | string: '{"type":"cpcode","action":"invalidate","domain":"production","objects":["12345","12346"]}' 9 | headers: 10 | Content-Type: 11 | - application/json 12 | response: 13 | status: 14 | code: 201 15 | message: Created 16 | headers: 17 | Date: 18 | - Tue, 13 May 2014 15:37:48 GMT 19 | Server: 20 | - Apache 21 | Content-Length: 22 | - '268' 23 | Content-Location: 24 | - /ccu/v2/purges/12345678-1234-5678-1234-123456789012 25 | Allow: 26 | - GET, HEAD, POST 27 | Vary: 28 | - Authorization 29 | Content-Type: 30 | - application/json 31 | body: 32 | encoding: UTF-8 33 | string: '{"estimatedSeconds": 420, "progressUri": "/ccu/v2/purges/12345678-1234-5678-1234-123456789012", 34 | "purgeId": "12345678-1234-1234-1234-123456789012", "supportId": "12345678901234567890-123456789", 35 | "httpStatus": 201, "detail": "Request accepted.", "pingAfterSeconds": 420}' 36 | http_version: 37 | recorded_at: Tue, 13 May 2014 15:37:49 GMT 38 | recorded_with: VCR 2.9.0 39 | -------------------------------------------------------------------------------- /lib/akamai_api/cli/ccu/purge_renderer.rb: -------------------------------------------------------------------------------- 1 | module AkamaiApi::CLI::CCU 2 | class PurgeRenderer 3 | attr_reader :response 4 | 5 | def initialize response 6 | @response = response 7 | end 8 | 9 | def render 10 | [ 11 | "----------", 12 | render_response, 13 | "----------" 14 | ].join "\n" 15 | end 16 | 17 | def render_response 18 | if response.code == 201 19 | render_successful_response 20 | else 21 | render_error_response 22 | end 23 | end 24 | 25 | def render_error_response 26 | [ 27 | "There was an error processing your request:", 28 | "\t* Result: #{response.code} - #{response.title} (#{response.message})", 29 | "\t* Described by: #{response.described_by}" 30 | ] 31 | end 32 | 33 | def render_successful_response 34 | result = [ 35 | "Purge request successfully submitted:", 36 | "\t* Result: #{response.code} - #{response.message}", 37 | "\t* Purge ID: #{response.purge_id} | Support ID: #{response.support_id}", 38 | "\t* Estimated time: #{response.estimated_time} secs.", 39 | "\t* Progress URI: #{response.uri}", 40 | "\t* Time to wait before check: #{response.time_to_wait} secs." 41 | ] 42 | 43 | result 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /spec/features/eccu/publish_request_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "Given I want to publish a request" do 4 | subject { AkamaiApi::ECCURequest } 5 | let(:fixture_content) { File.read 'spec/fixtures/eccu_request.xml' } 6 | 7 | context "when login credentials are invalid", vcr: { cassette_name: "akamai_api_eccu_publish/invalid_credentials" } do 8 | before do 9 | allow(AkamaiApi).to receive(:config) { { auth: ['foo', 'bar'] } } 10 | allow(AkamaiApi::ECCU).to receive(:client) { AkamaiApi::ECCU.send(:build_client) } 11 | end 12 | 13 | it "raises Unauthorized" do 14 | expect { subject.publish 'foo.com', fixture_content, file_name: './publish.xml' }.to raise_error AkamaiApi::Unauthorized 15 | end 16 | end 17 | 18 | context "when property name is not found", vcr: { cassette_name: "akamai_api_eccu_publish/invalid_domain" } do 19 | it "raises InvalidDomain" do 20 | expect { subject.publish 'foobarbaz.com', fixture_content, file_name: './publish.xml' }.to raise_error AkamaiApi::ECCU::InvalidDomain 21 | end 22 | end 23 | 24 | context "when data is correct", vcr: { cassette_name: "akamai_api_eccu_publish/successful" } do 25 | it "returns the request id" do 26 | expect(subject.publish 'foo.com', fixture_content, file_name: './publish.xml').to be_a Fixnum 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /spec/lib/akamai_api/eccu_parser_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module AkamaiApi 4 | describe ECCUParser do 5 | 6 | describe 'initialize' do 7 | context 'create tokenizer' do 8 | let(:parser){ ECCUParser.new "foo/bar/*.png" } 9 | it{ expect( parser.tokenizer.class.name ).to eq( "AkamaiApi::ECCU::Tokenizer" ) } 10 | end 11 | end 12 | 13 | describe 'raises' do 14 | context 'error on empty string' do 15 | let(:parser){ ECCUParser.new "" } 16 | it { expect{ parser.xml }.to raise_error "Expression can't be empty" } 17 | end 18 | context '* as not allowed extension' do 19 | let(:parser){ ECCUParser.new "foo/*.*" } 20 | it { expect{ parser.xml }.to raise_error } 21 | end 22 | context '. as not allowed dir' do 23 | let(:parser){ ECCUParser.new "./test.png" } 24 | it { expect{ parser.xml }.to raise_error } 25 | end 26 | context '.. as not allowed dir' do 27 | let(:parser){ ECCUParser.new "../test.png" } 28 | it { expect{ parser.xml }.to raise_error } 29 | end 30 | context 'Extension will be the last element ' do 31 | let(:parser){ ECCUParser.new "foo/*.png/" } 32 | it { expect{ parser.xml }.to raise_error "Extension will be the last element" } 33 | end 34 | end 35 | 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_arl_remove/multiple_items.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://some-subdomain.purge.akamaiapis.net/ccu/v2/queues/default 6 | body: 7 | encoding: UTF-8 8 | string: '{"type":"arl","action":"remove","domain":"production","objects":["http://www.foo.com/bar.txt","http://www.foo.com/baz.txt"]}' 9 | headers: 10 | Content-Type: 11 | - application/json 12 | response: 13 | status: 14 | code: 201 15 | message: Created 16 | headers: 17 | Date: 18 | - Tue, 13 May 2014 15:37:48 GMT 19 | Server: 20 | - Apache 21 | Content-Length: 22 | - '268' 23 | Content-Location: 24 | - /ccu/v2/purges/12345678-1234-5678-1234-123456789012 25 | Allow: 26 | - GET, HEAD, POST 27 | Vary: 28 | - Authorization 29 | Content-Type: 30 | - application/json 31 | body: 32 | encoding: UTF-8 33 | string: '{"estimatedSeconds": 420, "progressUri": "/ccu/v2/purges/12345678-1234-5678-1234-123456789012", 34 | "purgeId": "12345678-1234-1234-1234-123456789012", "supportId": "12345678901234567890-123456789", 35 | "httpStatus": 201, "detail": "Request accepted.", "pingAfterSeconds": 420}' 36 | http_version: 37 | recorded_at: Tue, 13 May 2014 15:37:49 GMT 38 | recorded_with: VCR 2.9.0 39 | -------------------------------------------------------------------------------- /features/eccu_last_request.feature: -------------------------------------------------------------------------------- 1 | Feature: akamai_api eccu last_request 2 | In order to get the last request made through ECCU 3 | As a CLI user 4 | 5 | @vcr 6 | Scenario: invalid credentials 7 | When I run `akamai_api eccu last_request -u foo -p bar` 8 | Then the output should contain: 9 | """ 10 | Your login credentials are invalid. 11 | """ 12 | 13 | @vcr 14 | Scenario: valid credentials 15 | When I run `akamai_api eccu last_request` 16 | Then the output should contain: 17 | """ 18 | * Code : 115942214\n 19 | """ 20 | And the output should contain: 21 | """ 22 | * Status : 4000 - File successfully deployed to Akamai network (Succeeded) 23 | """ 24 | And the output should contain: 25 | """ 26 | 2014-05-19T16:27:34.512Z 27 | """ 28 | And the output should contain: 29 | """ 30 | * Property: foo.com (hostheader) 31 | """ 32 | And the output should contain: 33 | """ 34 | with exact match 35 | """ 36 | And the output should contain: 37 | """ 38 | * Notes : ECCU Request using EdgeControl 39 | """ 40 | And the output should contain: 41 | """ 42 | * Email : guest@mikamai.com 43 | """ 44 | And the output should contain: 45 | """ 46 | * Uploaded by test1 on 2014-05-19T15:30:13.512Z 47 | """ -------------------------------------------------------------------------------- /lib/akamai_api/ccu/status/request.rb: -------------------------------------------------------------------------------- 1 | require "httparty" 2 | require "akamai_api/unauthorized" 3 | require "akamai_api/ccu/status/response" 4 | 5 | module AkamaiApi::CCU::Status 6 | # {Request} can be used to check the status of the Akamai CCU queue 7 | class Request 8 | include HTTParty 9 | format :json 10 | base_uri 'https://api.ccu.akamai.com/ccu/v2/queues/default' 11 | 12 | # Checks the status of the Akamai CCU queue 13 | # @return [Response] a response object describing the status of the Akamai CCU queue 14 | # @raise [AkamaiApi::CCU::Error] when there is an error in the request 15 | # @raise [AkamaiApi::Unauthorized] when login credentials are invalid 16 | def self.execute 17 | new.execute 18 | end 19 | 20 | # Checks the status of the Akamai CCU queue 21 | # @return [Response] a response object describing the status of the Akamai CCU queue 22 | # @raise [AkamaiApi::CCU::Error] when there is an error in the request 23 | # @raise [AkamaiApi::Unauthorized] when login credentials are invalid 24 | def execute 25 | response = self.class.get('/', basic_auth: AkamaiApi.auth) 26 | parse_response response 27 | end 28 | 29 | private 30 | 31 | def parse_response response 32 | raise AkamaiApi::Unauthorized if response.code == 401 33 | AkamaiApi::CCU::Status::Response.new response.parsed_response 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /spec/features/eccu/find_request_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "Given I want to retrieve a request" do 4 | subject { AkamaiApi::ECCURequest } 5 | 6 | context "when login credentials are invalid", vcr: { cassette_name: "akamai_api_eccu_find/invalid_credentials" } do 7 | before do 8 | allow(AkamaiApi).to receive(:config) { { auth: ['foo', 'bar'] } } 9 | allow(AkamaiApi::ECCU).to receive(:client) { AkamaiApi::ECCU.send(:build_client) } 10 | end 11 | 12 | it "raises Unauthorized" do 13 | expect { subject.find '1234' }.to raise_error AkamaiApi::Unauthorized 14 | end 15 | end 16 | 17 | context "when request id cannot be found", vcr: { cassette_name: "akamai_api_eccu_find/not_found_request" } do 18 | it "raises NotFound" do 19 | expect { subject.find '1234' }.to raise_error AkamaiApi::ECCU::NotFound 20 | end 21 | end 22 | 23 | context "when request id is found", vcr: { cassette_name: "akamai_api_eccu_find/successful" } do 24 | it "returns an ECCURequest" do 25 | expect(subject.find '1234').to be_a AkamaiApi::ECCURequest 26 | end 27 | end 28 | 29 | context "when request id is found but verbose is false", vcr: { cassette_name: "akamai_api_eccu_find/successful_without_content" } do 30 | it "returns an ECCURequest without file content" do 31 | expect(subject.find('1234', verbose: false).file).to_not have_key :content 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /spec/lib/akamai_api/eccu/soap_body_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AkamaiApi::ECCU::SoapBody do 4 | let(:config) { double :env_namespace => '', :soap_version => '2' } 5 | 6 | describe '#string' do 7 | before { subject.string 'foo', 'sample' } 8 | 9 | it 'adds a string field' do 10 | expect(subject.to_s).to match /sample<\/foo>/ 11 | end 12 | 13 | it 'sets the correct type attribute' do 14 | expect(subject.to_s).to match // 15 | end 16 | end 17 | 18 | describe '#array' do 19 | before { subject.array 'foo', ['a', 'b'] } 20 | 21 | it 'adds an array field' do 22 | expect(subject.to_s).to match /a<\/item>b<\/item><\/foo>/ 23 | end 24 | 25 | it 'sets the correct type attribute' do 26 | expect(subject.to_s).to match /(.+)<\/foo>/m 39 | expect(Base64.decode64 match[1]).to eq 'foo' 40 | end 41 | 42 | it 'sets the correct type attribute' do 43 | expect(subject.to_s).to match / 201, 7 | "detail" => "Request accepted.", 8 | "estimatedSeconds" => 420, 9 | "purgeId" => "95b5a092-043f-4af0-843f-aaf0043faaf0", 10 | "progressUri" => "/ccu/v2/purges/95b5a092-043f-4af0-843f-aaf0043faaf0", 11 | "pingAfterSeconds" => 420, 12 | "supportId" => "17PY1321286429616716-211907680" 13 | } 14 | end 15 | subject { AkamaiApi::CCU::Purge::Response.new raw } 16 | 17 | it '#detail returns the title attribute' do 18 | expect(subject.detail).to eq 'Request accepted.' 19 | end 20 | 21 | it '#time_to_wait returns the pingAfterSeconds attribute' do 22 | expect(subject.time_to_wait).to eq 420 23 | end 24 | 25 | it '#purge_id returns the purgeId attribute' do 26 | expect(subject.purge_id).to eq "95b5a092-043f-4af0-843f-aaf0043faaf0" 27 | end 28 | 29 | it '#support_id returns the supportId attribute' do 30 | expect(subject.support_id).to eq "17PY1321286429616716-211907680" 31 | end 32 | 33 | it '#code returns the httpStatus attribute' do 34 | expect(subject.code).to eq 201 35 | end 36 | 37 | it '#estimated_time returns the estimatedSeconds attribute' do 38 | expect(subject.estimated_time).to eq 420 39 | end 40 | 41 | it '#uri returns the progressUri attribute' do 42 | expect(subject.uri).to eq "/ccu/v2/purges/95b5a092-043f-4af0-843f-aaf0043faaf0" 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_arl_invalidate/invalid_credentials.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://some-subdomain.purge.akamaiapis.net/ccu/v3/invalidate/url/production 6 | body: 7 | encoding: UTF-8 8 | string: '{"objects":["http://www.foo.bar/t.txt"]}' 9 | headers: 10 | Content-Type: 11 | - application/json 12 | Accept-Encoding: 13 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 14 | Accept: 15 | - "*/*" 16 | User-Agent: 17 | - Ruby 18 | response: 19 | status: 20 | code: 400 21 | message: Bad Request 22 | headers: 23 | Content-Length: 24 | - '428' 25 | Date: 26 | - Thu, 16 Mar 2017 07:11:10 GMT 27 | Connection: 28 | - close 29 | Content-Type: 30 | - application/problem+json 31 | body: 32 | encoding: UTF-8 33 | string: | 34 | { 35 | "type": "https://problems.purge.akamaiapis.net/-/pep-authn/request-error", 36 | "title": "Bad request", 37 | "status": 400, 38 | "detail": "Invalid client token", 39 | "instance": "https://some-subdomain.purge.akamaiapis.net/ccu/v3/invalidate/url/production", 40 | "method": "POST", 41 | "serverIp": "x.x.x.x", 42 | "clientIp": "y.y.y.y", 43 | "requestId": "1234567", 44 | "requestTime": "2017-03-16T07:11:10Z" 45 | } 46 | http_version: 47 | recorded_at: Thu, 16 Mar 2017 07:11:10 GMT 48 | recorded_with: VCR 3.0.3 49 | -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_cpcode_remove/invalid_credentials.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://some-subdomain.purge.akamaiapis.net/ccu/v2/queues/default 6 | body: 7 | encoding: UTF-8 8 | string: '{"type":"cpcode","action":"remove","domain":"production","objects":["12345"]}' 9 | headers: 10 | Content-Type: 11 | - application/json 12 | Accept-Encoding: 13 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 14 | Accept: 15 | - "*/*" 16 | User-Agent: 17 | - Ruby 18 | response: 19 | status: 20 | code: 400 21 | message: Bad Request 22 | headers: 23 | Content-Length: 24 | - '417' 25 | Date: 26 | - Sat, 11 Mar 2017 10:14:57 GMT 27 | Connection: 28 | - close 29 | Content-Type: 30 | - application/problem+json 31 | body: 32 | encoding: UTF-8 33 | string: | 34 | { 35 | "type": "https://problems.purge.akamaiapis.net/-/pep-authn/request-error", 36 | "title": "Bad request", 37 | "status": 400, 38 | "detail": "Invalid client token", 39 | "instance": "https://some-subdomain.purge.akamaiapis.net/ccu/v2/queues/default", 40 | "method": "POST", 41 | "serverIp": "x.x.x.x.", 42 | "clientIp": "y.y.y.y", 43 | "requestId": "1c1d405c", 44 | "requestTime": "2017-03-11T10:14:57Z" 45 | } 46 | http_version: 47 | recorded_at: Sat, 11 Mar 2017 10:14:57 GMT 48 | recorded_with: VCR 3.0.3 49 | -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_arl_remove/invalid_credentials.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://some-subdomain.purge.akamaiapis.net/ccu/v2/queues/default 6 | body: 7 | encoding: UTF-8 8 | string: '{"type":"arl","action":"remove","domain":"production","objects":["http://www.foo.bar/t.txt"]}' 9 | headers: 10 | Content-Type: 11 | - application/json 12 | Accept-Encoding: 13 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 14 | Accept: 15 | - "*/*" 16 | User-Agent: 17 | - Ruby 18 | response: 19 | status: 20 | code: 400 21 | message: Bad Request 22 | headers: 23 | Content-Length: 24 | - '413' 25 | Date: 26 | - Tue, 14 Mar 2017 04:47:01 GMT 27 | Connection: 28 | - close 29 | Content-Type: 30 | - application/problem+json 31 | body: 32 | encoding: UTF-8 33 | string: | 34 | { 35 | "type": "https://problems.purge.akamaiapis.net/-/pep-authn/request-error", 36 | "title": "Bad request", 37 | "status": 400, 38 | "detail": "Invalid client token", 39 | "instance": "https://some-subdomain.purge.akamaiapis.net/ccu/v2/queues/default", 40 | "method": "POST", 41 | "serverIp": "y.y.y.y", 42 | "clientIp": "x.x.x.x", 43 | "requestId": "1234567", 44 | "requestTime": "2017-03-14T04:47:01Z" 45 | } 46 | http_version: 47 | recorded_at: Tue, 14 Mar 2017 04:47:00 GMT 48 | recorded_with: VCR 3.0.3 49 | -------------------------------------------------------------------------------- /cassettes/akamai_api_ccu_cpcode_invalidate/invalid_credentials.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://some-subdomain.purge.akamaiapis.net/ccu/v2/queues/default 6 | body: 7 | encoding: UTF-8 8 | string: '{"type":"cpcode","action":"invalidate","domain":"production","objects":["12345"]}' 9 | headers: 10 | Content-Type: 11 | - application/json 12 | Accept-Encoding: 13 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 14 | Accept: 15 | - "*/*" 16 | User-Agent: 17 | - Ruby 18 | response: 19 | status: 20 | code: 400 21 | message: Bad Request 22 | headers: 23 | Content-Length: 24 | - '414' 25 | Date: 26 | - Thu, 16 Mar 2017 22:43:27 GMT 27 | Connection: 28 | - close 29 | Content-Type: 30 | - application/problem+json 31 | body: 32 | encoding: UTF-8 33 | string: | 34 | { 35 | "type": "https://problems.purge.akamaiapis.net/-/pep-authn/request-error", 36 | "title": "Bad request", 37 | "status": 400, 38 | "detail": "Invalid client token", 39 | "instance": "https://some-subdomain.purge.akamaiapis.net/ccu/v2/queues/default", 40 | "method": "POST", 41 | "serverIp": "x.x.x.x", 42 | "clientIp": "y.y.y.y", 43 | "requestId": "1234567", 44 | "requestTime": "2017-03-16T22:43:27Z" 45 | } 46 | http_version: 47 | recorded_at: Thu, 16 Mar 2017 22:43:27 GMT 48 | recorded_with: VCR 3.0.3 49 | -------------------------------------------------------------------------------- /spec/lib/akamai_api/ccu/purge_status/not_found_response_spec.rb: -------------------------------------------------------------------------------- 1 | # require 'spec_helper' 2 | 3 | # describe AkamaiApi::CCU::PurgeStatus::NotFoundResponse do 4 | # let(:raw) do 5 | # { 6 | # 'progressUri' => '/CCU/v2/purges/12345678-1234-5678-1234-123456789012', 7 | # 'purgeId' => '12345678-1234-5678-1234-123456789012', 8 | # 'supportId' => '12345678901234567890-123456789', 9 | # 'httpStatus' => 200, 10 | # 'purgeStatus' => 'Unknown', 11 | # 'pingAfterSeconds' => 60, 12 | # 'detail' => 'foobarbaz' 13 | # } 14 | # end 15 | # subject { AkamaiApi::CCU::PurgeStatus::NotFoundResponse.new raw } 16 | 17 | # it '#progress_uri returns progressUri attribute' do 18 | # expect(subject.progress_uri).to eq '/CCU/v2/purges/12345678-1234-5678-1234-123456789012' 19 | # end 20 | 21 | # it '#purge_id returns purgeId attribute' do 22 | # expect(subject.purge_id).to eq '12345678-1234-5678-1234-123456789012' 23 | # end 24 | 25 | # it '#support_id returns supportId attribute' do 26 | # expect(subject.support_id).to eq '12345678901234567890-123456789' 27 | # end 28 | 29 | # it '#code returns httpStatus attribute' do 30 | # expect(subject.code).to eq 200 31 | # end 32 | 33 | # it '#status returns purgeStatus attribute' do 34 | # expect(subject.status).to eq 'Unknown' 35 | # end 36 | 37 | # it '#message returns detail attribute' do 38 | # raw['detail'] = 'asd' 39 | # expect(subject.message).to eq 'asd' 40 | # end 41 | # end 42 | -------------------------------------------------------------------------------- /lib/akamai_api/cli/command.rb: -------------------------------------------------------------------------------- 1 | require "thor" 2 | require "active_support" 3 | require "active_support/core_ext/hash" 4 | 5 | module AkamaiApi::CLI 6 | class Command < Thor 7 | class_option :username, :type => :string, :aliases => '-u', 8 | :desc => 'Username used to authenticate on Akamai Control Panel' 9 | class_option :password, :type => :string, :aliases => '-p', 10 | :desc => 'Password used to authenticate on Akamai Control Panel' 11 | 12 | no_tasks do 13 | def load_config 14 | return if AkamaiApi.auth_ok? 15 | load_config_from_file 16 | if AkamaiApi.auth_empty? 17 | render_auth_info 18 | end 19 | end 20 | 21 | def config_file 22 | File.expand_path '~/.akamai_api.yml' 23 | end 24 | 25 | def load_config_from_file 26 | if File.exists?(config_file) 27 | AkamaiApi.config.merge! YAML::load_file(config_file).symbolize_keys 28 | else 29 | render_auth_info 30 | raise ArgumentError 31 | end 32 | end 33 | 34 | def render_auth_info 35 | puts <<-OUTPUT 36 | No authentication config found. At the very least, specify auth credentials by creating a file in your home directory named `.akamai_api.yml` with the following content:" 37 | auth: 38 | - my_username 39 | - my_password 40 | If using "ccu arl invalidate", your CCU api credentials should also be added: 41 | openapi: 42 | base_url: 43 | client_token: 44 | client_secret: 45 | access_token: 46 | OUTPUT 47 | end 48 | end 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /spec/lib/akamai_api/eccu/list_request_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AkamaiApi::ECCU::ListRequest do 4 | subject { AkamaiApi::ECCU::ListRequest.new } 5 | 6 | describe "#execute" do 7 | let(:fake_client) { double call: nil } 8 | 9 | before do 10 | allow(AkamaiApi::ECCU).to receive(:client) { fake_client } 11 | end 12 | 13 | it "calls 'get_ids' via savon" do 14 | fake_response = double body: { get_ids_response: { file_ids: { file_ids: [1,2] } } } 15 | expect(fake_client).to receive(:call).with(:get_ids).and_return fake_response 16 | subject.execute 17 | end 18 | 19 | it "returns an array of ids" do 20 | allow(fake_client).to receive(:call) { double(body: { get_ids_response: { file_ids: { file_ids: [1,2] } } }) } 21 | expect(subject.execute).to eq [1,2] 22 | end 23 | 24 | it "wraps in array if only one result is returned" do 25 | allow(fake_client).to receive(:call) { double(body: { get_ids_response: { file_ids: { file_ids: 1 } } }) } 26 | expect(subject.execute).to eq [1] 27 | end 28 | 29 | it "raises unauthorized if request raises a Savon::HTTPError with code 401" do 30 | expect(fake_client).to receive :call do 31 | raise Savon::HTTPError, double(code: 401) 32 | end 33 | expect { subject.execute }.to raise_error AkamaiApi::Unauthorized 34 | end 35 | 36 | it "raises Savon:HTTPError if request raises this exception and its code differs from 401" do 37 | expect(fake_client).to receive :call do 38 | raise Savon::HTTPError, double(code: 402) 39 | end 40 | expect { subject.execute }.to raise_error Savon::HTTPError 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/akamai_api/eccu/find_request.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/eccu/base_edit_request" 2 | require "akamai_api/eccu/find_response" 3 | 4 | module AkamaiApi::ECCU 5 | # The {FindRequest} class is used to get the details of an ECCU request. 6 | # 7 | # @example 8 | # begin 9 | # res = AkamaiApi::ECCU::FindRequest.execute 12345, false 10 | # puts "Request found, in status #{res.status[:message]}" 11 | # rescue AkamaiApi::Unauthorized 12 | # puts "Invalid credentials" 13 | # rescue AkamaiApi::NotFound 14 | # puts "No request found with the given code" 15 | # end 16 | class FindRequest < BaseEditRequest 17 | # Returns the details of an ECCU request 18 | # @param [Fixnum] code request code 19 | # @param [true,false] retrieve_content set to true if you want to retrieve request content too 20 | # @return [FindResponse] 21 | def self.execute code, retrieve_content = false 22 | new(code).execute(retrieve_content) 23 | end 24 | 25 | # Returns the details of an ECCU request 26 | # @param [true,false] retrieve_content set to true if you want to retrieve request content too 27 | # @return [FindResponse] 28 | def execute retrieve_content = false 29 | with_soap_error_handling do 30 | response = client_call :get_info, message: request_body(retrieve_content).to_s 31 | FindResponse.new response[:eccu_info] 32 | end 33 | end 34 | 35 | protected 36 | 37 | # Creates the request body filling it with all necessary arguments 38 | # @return [SoapBody] 39 | def request_body retrieve_content 40 | super do |block| 41 | block.boolean :retrieveContents, retrieve_content == true 42 | end 43 | end 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path '../../lib/akamai_api', __FILE__ 2 | require File.expand_path '../../lib/akamai_api/cli', __FILE__ 3 | 4 | begin 5 | require File.expand_path '../auth.rb', __FILE__ 6 | rescue LoadError 7 | AkamaiApi.config[:auth] = ['USERNAME', 'PASSWORD'] 8 | AkamaiApi.config[:log] = true 9 | AkamaiApi.config[:openapi] = { 10 | :base_url => "https://some-subdomain.purge.akamaiapis.net", 11 | :client_token => "client_token", 12 | :client_secret => "client_secret", 13 | :access_token => "access_token" 14 | } 15 | end 16 | require 'savon/mock/spec_helper' 17 | require 'webmock/rspec' 18 | require 'vcr' 19 | require 'coveralls' 20 | Coveralls.wear_merged! 21 | 22 | VCR.configure do |c| 23 | c.cassette_library_dir = 'cassettes' 24 | c.hook_into :webmock 25 | c.default_cassette_options = { 26 | match_requests_on: [:method, :uri, :body] 27 | } 28 | c.configure_rspec_metadata! 29 | c.after_http_request do |request| 30 | request.uri.gsub! AkamaiApi.config[:auth].first, 'USERNAME' 31 | request.uri.gsub! AkamaiApi.config[:auth].last, 'PASSWORD' 32 | request.body.gsub! "AkamaiApi #{AkamaiApi::VERSION}", "AkamaiApi VERSION" 33 | end 34 | c.before_playback do |i| 35 | i.request.uri.gsub! 'USERNAME', AkamaiApi.config[:auth].first 36 | i.request.uri.gsub! 'PASSWORD', AkamaiApi.config[:auth].last 37 | i.request.body.gsub! "AkamaiApi VERSION", "AkamaiApi #{AkamaiApi::VERSION}" 38 | end 39 | end 40 | 41 | # Savon::Spec::Fixture.path = File.expand_path '../fixtures', __FILE__ 42 | Dir[File.expand_path '../support/**/*.rb', __FILE__].each do |f| 43 | require f 44 | end 45 | 46 | RSpec.configure do |config| 47 | config.run_all_when_everything_filtered = true 48 | config.filter_run :focus 49 | 50 | config.order = 'random' 51 | end 52 | -------------------------------------------------------------------------------- /lib/akamai_api/cli/eccu/entry_renderer.rb: -------------------------------------------------------------------------------- 1 | require "active_support" 2 | require "active_support/core_ext/object/blank" 3 | 4 | module AkamaiApi::CLI::ECCU 5 | class EntryRenderer 6 | def self.render entries 7 | output = ["----------"] 8 | entries.each do |e| 9 | output.concat new(e).render_entry 10 | output << "----------" 11 | end 12 | output.join "\n" 13 | end 14 | 15 | attr_reader :entry 16 | 17 | def initialize entry 18 | @entry = entry 19 | end 20 | 21 | def render 22 | [ 23 | "----------", 24 | render_entry, 25 | "----------" 26 | ].join "\n" 27 | end 28 | 29 | def render_entry 30 | output = [ 31 | "* Code : #{entry.code}", 32 | entry_status, 33 | " #{entry.status[:updated_at]}", 34 | entry_property 35 | ] 36 | output << "* Notes : #{entry.notes}" if entry.notes.present? 37 | output << "* Email : #{entry.email}" if entry.email 38 | output << "* Uploaded by #{entry.uploaded_by} on #{entry.upload_date}" 39 | output << "* Content:\n#{entry.file[:content]}" if entry.file[:content].present? 40 | output 41 | end 42 | 43 | private 44 | 45 | def entry_property 46 | base = "* Property: #{entry.property[:name]} (#{entry.property[:type]})" 47 | if entry.property[:exact_match] 48 | [ 49 | base, 50 | " with exact match" 51 | ].join "\n" 52 | else 53 | base 54 | end 55 | end 56 | 57 | def entry_status 58 | if entry.status[:extended].present? 59 | "* Status : #{entry.status[:code]} - #{entry.status[:extended]}" 60 | else 61 | "* Status : #{entry.status[:code]}" 62 | end 63 | end 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /features/ccu_arl_invalidate.feature: -------------------------------------------------------------------------------- 1 | Feature: akamai_api ccu arl invalidate 2 | In order to remove ARLs 3 | As a CLI user 4 | 5 | @vcr 6 | Scenario: invalid credentials 7 | When I run `akamai_api ccu arl invalidate http://www.foo.bar/t.txt -u foo -p bar` 8 | Then the output should contain: 9 | """ 10 | Your login credentials are invalid. 11 | """ 12 | 13 | @vcr 14 | Scenario: invalid item 15 | When I run `akamai_api ccu arl invalidate http://www.foo.bar/t.txt` 16 | Then the output should contain: 17 | """ 18 | Error 403: 'unauthorized arl' (http://www.foo.com/bar.txt) 19 | """ 20 | And the output should contain: 21 | """ 22 | Described by: https://api.ccu.akamai.com/ccu/v2/errors/unauthorized-arl 23 | """ 24 | 25 | @vcr 26 | Scenario: single item 27 | When I run `akamai_api ccu arl invalidate http://www.foo.bar/t.txt` 28 | Then the output should contain: 29 | """ 30 | Purge request successfully submitted: 31 | """ 32 | And the output should contain: 33 | """ 34 | * Result: 201 - Request accepted. 35 | """ 36 | And the output should contain: 37 | """ 38 | * Purge ID: 12345678-1234-1234-1234-123456789012 | Support ID: 12345678901234567890-123456789 39 | """ 40 | 41 | @vcr 42 | Scenario: multiple items 43 | When I run `akamai_api ccu arl invalidate http://www.foo.bar/t.txt http://www.foo.com/baz.txt` 44 | Then the output should contain: 45 | """ 46 | Purge request successfully submitted: 47 | """ 48 | And the output should contain: 49 | """ 50 | * Result: 201 - Request accepted. 51 | """ 52 | And the output should contain: 53 | """ 54 | * Purge ID: 12345678-1234-1234-1234-123456789012 | Support ID: 12345678901234567890-123456789 55 | """ 56 | -------------------------------------------------------------------------------- /spec/fixtures/eccu/get_info/successful.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | PGVjY3U+XG4gIDxyZXZhbGlkYXRlPm5vdzwvcmV2YWxpZGF0ZT5cbjwvZWNj\ndT5cbg== 7 | File successfully deployed to Akamai network (Succeeded) 8 | 1234567 9 | 127 10 | 11 | ECCU Request using EdgeControl 12 | www.example.com 13 | true 14 | hostheader 15 | foo@example.com 16 | 4000 17 | File successfully deployed to Akamai's network 18 | 2012-09-20T07:58:10.936Z 19 | 2012-09-20T07:17:25.936Z 20 | foo 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /lib/akamai_api/eccu/base_edit_request.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/eccu/base_request" 2 | require "akamai_api/eccu/not_found" 3 | require "akamai_api/eccu/soap_body" 4 | 5 | module AkamaiApi::ECCU 6 | # @abstract 7 | # 8 | # This class is intended as a generic superclass for all requests that operate on an existing 9 | # purge request submitted through the Akamai ECCU interface. 10 | class BaseEditRequest < BaseRequest 11 | # ECCU Request code 12 | # @return [String] request code 13 | attr_reader :code 14 | 15 | # @param code ECCU request code 16 | def initialize code 17 | @code = code.to_i 18 | end 19 | 20 | protected 21 | 22 | # Creates the request body filling it with all necessary arguments 23 | # 24 | # The base implementation fills only the request code. If the request needs additional 25 | # arguments you'll want to overwrite it like the following: 26 | # class MyCustomRequest < AkamaiApi::ECCU::BaseEditRequest 27 | # def request_body code, name, surname 28 | # super code do |block| 29 | # block.string(:name, name).string(:surname, surname) 30 | # end 31 | # end 32 | # end 33 | # @return [SoapBody] 34 | def request_body *args, &block 35 | SoapBody.new.tap do |block| 36 | block.integer :fileId, code 37 | yield block if block_given? 38 | end 39 | end 40 | 41 | # Wrapper method that you can use inside your custom ECCU request to handle common errors 42 | # @raise [AkamaiApi::Unauthorized] when login credentials are invalid 43 | # @raise [AkamaiApi::ECCU::NotFound] when no request can be found with the given code 44 | def with_soap_error_handling &block 45 | super 46 | rescue Savon::SOAPFault => e 47 | e = ::AkamaiApi::ECCU::NotFound if e.to_hash[:fault][:faultstring] =~ /fileId .* does not exist/ 48 | raise e 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /features/eccu_publish.feature: -------------------------------------------------------------------------------- 1 | Feature: akamai_api eccu publish 2 | In order to publish a purge request via ECCU 3 | As a CLI user 4 | 5 | @vcr 6 | Scenario: invalid credentials 7 | Given a file named "publish.xml" with the content of "spec/fixtures/eccu_request.xml" 8 | When I run `akamai_api eccu publish_xml ./publish.xml foo.com -u foo -p bar` 9 | Then the output should contain: 10 | """ 11 | Your login credentials are invalid. 12 | """ 13 | 14 | @vcr 15 | Scenario: invalid domain 16 | Given a file named "publish.xml" with the content of "spec/fixtures/eccu_request.xml" 17 | When I run `akamai_api eccu publish_xml ./publish.xml foobarbaz.com` 18 | Then the output should contain: 19 | """ 20 | You are not authorized to specify this digital property 21 | """ 22 | 23 | @vcr 24 | Scenario: successful 25 | Given a file named "publish.xml" with the content of "spec/fixtures/eccu_request.xml" 26 | When I run `akamai_api eccu publish_xml ./publish.xml foo.com` 27 | Then the output should contain: 28 | """ 29 | Request correctly published 30 | """ 31 | And the output should contain: 32 | """ 33 | * Code : 116073578 34 | """ 35 | And the output should contain: 36 | """ 37 | * Status : 1000 38 | """ 39 | And the output should contain: 40 | """ 41 | 2014-05-20T16:49:29.026Z 42 | """ 43 | And the output should contain: 44 | """ 45 | * Property: foo.com (hostheader) 46 | """ 47 | And the output should contain: 48 | """ 49 | with exact match 50 | """ 51 | And the output should contain: 52 | """ 53 | * Notes : ECCU Request using AkamaiApi 54 | """ 55 | And the output should contain: 56 | """ 57 | * Uploaded by test1 on 2014-05-20T16:49:29.026Z 58 | """ 59 | And the output should contain: 60 | """ 61 | Content: 62 | """ -------------------------------------------------------------------------------- /lib/akamai_api/cli/ccu/cp_code.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/ccu" 2 | require "akamai_api/cli/command" 3 | require "akamai_api/cli/ccu/purge_renderer" 4 | 5 | module AkamaiApi::CLI::CCU 6 | class CpCode < AkamaiApi::CLI::Command 7 | namespace 'ccu cpcode' 8 | 9 | desc 'remove CPCODE1 CPCODE2 ...', 'Purge CP Code(s) removing them from the cache' 10 | method_option :domain, :type => :string, :aliases => '-d', 11 | :banner => 'production|staging', 12 | :desc => 'Optional argument used to specify the environment. Usually you will not need this option' 13 | method_option :banner => "foo@foo.com bar@bar.com", 14 | :desc => 'Email(s) used to send notification when the purge has been completed' 15 | def remove(*cpcodes) 16 | purge_action :remove, cpcodes 17 | end 18 | 19 | desc 'invalidate CPCODE1 CPCODE2 ...', 'Purge CP Code(s) marking their cache as expired' 20 | method_option :domain, :type => :string, :aliases => '-d', 21 | :banner => 'production|staging', 22 | :desc => 'Optional argument used to specify the environment. Usually you will not need this option' 23 | method_option :banner => "foo@foo.com bar@bar.com", 24 | :desc => 'Email(s) used to send notification when the purge has been completed' 25 | def invalidate(*cpcodes) 26 | purge_action :invalidate, cpcodes 27 | end 28 | 29 | no_tasks do 30 | def purge_action type, cpcodes 31 | if cpcodes.blank? 32 | puts 'You should provide at least one valid CP Code' 33 | return 34 | end 35 | load_config 36 | res = AkamaiApi::CCU.purge type, :cpcode, cpcodes, :domain => options[:domain] 37 | puts PurgeRenderer.new(res).render 38 | rescue AkamaiApi::CCU::Error 39 | puts StatusRenderer.new($!).render_error 40 | rescue AkamaiApi::Unauthorized 41 | puts "Your login credentials are invalid." 42 | end 43 | end 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/akamai_api/cli/ccu/arl.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/ccu" 2 | require "akamai_api/cli/command" 3 | require "akamai_api/cli/ccu/purge_renderer" 4 | 5 | module AkamaiApi::CLI::CCU 6 | class Arl < AkamaiApi::CLI::Command 7 | namespace 'ccu arl' 8 | 9 | desc 'remove http://john.com/a.txt http://www.smith.com/b.txt ...', 'Purge ARL(s) removing them from the cache' 10 | method_option :domain, :type => :string, :aliases => '-d', 11 | :banner => 'production|staging', 12 | :desc => 'Optional argument used to specify the environment. Usually you will not need this option' 13 | method_option :banner => "foo@foo.com bar@bar.com", 14 | :desc => 'Email(s) used to send notification when the purge has been completed' 15 | def remove(*arls) 16 | purge_action :remove, arls 17 | end 18 | 19 | desc 'invalidate http://john.com/a.txt http://www.smith.com/b.txt ...', 'Purge ARL(s) marking their cache as expired' 20 | method_option :domain, :type => :string, :aliases => '-d', 21 | :banner => 'production|staging', 22 | :desc => 'Optional argument used to specify the environment. Usually you will not need this option' 23 | method_option :banner => "foo@foo.com bar@bar.com", 24 | :desc => 'Email(s) used to send notification when the purge has been completed' 25 | 26 | def invalidate(*arls) 27 | purge_action :invalidate, arls 28 | end 29 | 30 | no_tasks do 31 | def purge_action type, arls 32 | raise 'You should provide at least one valid URL' if arls.blank? 33 | 34 | begin 35 | load_config 36 | rescue ArgumentError 37 | return 38 | end 39 | 40 | res = AkamaiApi::CCU.purge type, :arl, arls, :domain => options[:domain] 41 | puts PurgeRenderer.new(res).render 42 | 43 | rescue AkamaiApi::CCU::Error => e 44 | puts StatusRenderer.new($!).render_error 45 | rescue AkamaiApi::Unauthorized 46 | puts 'Your login credentials are invalid.' 47 | end 48 | end 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /lib/akamai_api/eccu/update_attribute_request.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/eccu/base_edit_request" 2 | 3 | module AkamaiApi::ECCU 4 | # {UpdateAttributeRequest} is a generic request class that can be used to update an attribute of an ECCU request. 5 | # 6 | # This class is used to update the {AkamaiApi::ECCURequest#notes} or the {AkamaiApi::ECCURequest#email} attributes 7 | # 8 | # @example 9 | # begin 10 | # res = AkamaiApi::ECCU::UpdateAttributeRequest.execute 12345, 'notes', 'my new notes' 11 | # puts "Request completed: #{res}" 12 | # rescue AkamaiApi::ECCU::NotFound 13 | # puts "No request can be found with the given code" 14 | # rescue AkamaiApi::Unauthorized 15 | # puts "Invalid login credentials" 16 | # end 17 | class UpdateAttributeRequest < BaseEditRequest 18 | # @return [String] attribute to update 19 | attr_reader :attribute 20 | 21 | # Updates an attribute of an ECCU request 22 | # @param [Fixnum] code request code 23 | # @param [String] attribute name 24 | # @param [String] value new value to set 25 | # @return [true,false] whether the request was successful or not 26 | def self.execute code, attribute, value 27 | new(code, attribute).execute(value) 28 | end 29 | 30 | # @param [Fixnum] code request code 31 | # @param [String] attribute name 32 | def initialize code, attribute 33 | super code 34 | @attribute = attribute 35 | end 36 | 37 | # Updates an attribute of an ECCU request 38 | # @param [String] value new value to set 39 | # @return [true,false] whether the request was successful or not 40 | def execute value 41 | with_soap_error_handling do 42 | client_call(:"set_#{attribute}", message: request_body(value).to_s)[:success] 43 | end 44 | end 45 | 46 | protected 47 | 48 | # Creates the request body filling it with all necessary arguments 49 | # @return [SoapBody] 50 | def request_body notes 51 | super do |block| 52 | block.string attribute_for_soap, notes 53 | end 54 | end 55 | 56 | private 57 | 58 | def attribute_for_soap 59 | attribute.to_s.camelize(:lower).to_sym 60 | end 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /features/support/env.rb: -------------------------------------------------------------------------------- 1 | require 'akamai_api' 2 | require 'akamai_api/cli' 3 | require 'aruba' 4 | require 'aruba/cucumber' 5 | require 'aruba/in_process' 6 | require 'vcr' 7 | require 'webmock' 8 | require 'coveralls' 9 | Coveralls.wear_merged! 10 | begin 11 | require File.expand_path '../auth.rb', __FILE__ 12 | rescue LoadError 13 | AkamaiApi.config[:auth] = ['USERNAME', 'PASSWORD'] 14 | AkamaiApi.config[:openapi] = { 15 | :base_url => "https://some-subdomain.purge.akamaiapis.net", 16 | :client_token => "client_token", 17 | :client_secret => "client_secret", 18 | :access_token => "access_token" 19 | } 20 | end 21 | ENV['AKAMAI_USERNAME'], ENV['AKAMAI_PASSWORD'] = AkamaiApi.config[:auth] 22 | 23 | VCR.cucumber_tags do |t| 24 | t.tag '@vcr', use_scenario_name: true 25 | end 26 | 27 | VCR.configure do |c| 28 | c.hook_into :webmock 29 | c.cassette_library_dir = 'cassettes' 30 | c.default_cassette_options = { 31 | record: :once, 32 | match_requests_on: [:method, :uri, :body] 33 | } 34 | c.after_http_request do |request| 35 | request.uri.gsub! ENV['AKAMAI_USERNAME'], 'USERNAME' 36 | request.uri.gsub! ENV['AKAMAI_PASSWORD'], 'PASSWORD' 37 | request.body.gsub! "AkamaiApi #{AkamaiApi::VERSION}", "AkamaiApi VERSION" 38 | end 39 | c.before_playback do |i| 40 | i.request.uri.gsub! 'USERNAME', ENV['AKAMAI_USERNAME'] 41 | i.request.uri.gsub! 'PASSWORD', ENV['AKAMAI_PASSWORD'] 42 | i.request.body.gsub! "AkamaiApi VERSION", "AkamaiApi #{AkamaiApi::VERSION}" 43 | end 44 | end 45 | 46 | class VcrFriendlyCLI 47 | def initialize(argv, stdin=STDIN, stdout=STDOUT, stderr=STDERR, kernel=Kernel) 48 | @argv, @stdin, @stdout, @stderr, @kernel = argv, stdin, stdout, stderr, kernel 49 | end 50 | 51 | def execute! 52 | $stdin = @stdin 53 | $stdout = @stdout 54 | @kernel.exit AkamaiApi::CLI::App.start(@argv.dup) 55 | end 56 | end 57 | 58 | Before do 59 | @aruba_timeout_seconds = 30 60 | end 61 | 62 | Before('@vcr') do 63 | Aruba::InProcess.main_class = VcrFriendlyCLI 64 | Aruba.process = Aruba::InProcess 65 | end 66 | 67 | After('@vcr') do 68 | Aruba.process = Aruba::SpawnProcess 69 | VCR.eject_cassette 70 | $stdin = STDIN 71 | $stdout = STDOUT 72 | end 73 | -------------------------------------------------------------------------------- /spec/lib/akamai_api/ccu_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AkamaiApi::CCU do 4 | subject { AkamaiApi::CCU } 5 | 6 | %w(invalidate remove).each do |action| 7 | describe "##{action}" do 8 | it 'raises error if less than 2 arguments are given' do 9 | expect { subject.send action, 'foo' }.to raise_error ArgumentError 10 | end 11 | 12 | it 'delegates to #purge with the given type' do 13 | expect(subject).to receive(:purge).with(action.to_sym, :cpcode, 'foo', domain: 'asd').and_return 'bar' 14 | expect(subject.send action, :cpcode, 'foo', domain: 'asd').to eq 'bar' 15 | end 16 | end 17 | 18 | %w(arl cpcode).each do |type| 19 | describe "##{action}_#{type}" do 20 | let(:method) { "#{action}_#{type}" } 21 | 22 | it 'raises error if less than 1 argument is given' do 23 | expect { subject.send method }.to raise_error ArgumentError 24 | end 25 | 26 | it 'delegates to #purge with the given items' do 27 | expect(subject).to receive(:purge).with(action.to_sym, type.to_sym, 'foo', domain: 'asd').and_return 'bar' 28 | expect(subject.send method, 'foo', domain: 'asd').to eq 'bar' 29 | end 30 | end 31 | end 32 | end 33 | 34 | describe '#purge' do 35 | it 'delegates to Purge::Request' do 36 | fake_request = double 37 | expect(fake_request).to receive(:execute).with('baz').and_return 'quiz' 38 | expect(AkamaiApi::CCU::Purge::Request).to receive(:new).with('foo', 'bar', domain: 'asd'). 39 | and_return fake_request 40 | expect(subject.purge 'foo', 'bar', 'baz', domain: 'asd').to eq 'quiz' 41 | end 42 | 43 | describe 'raises an error when' do 44 | it 'action is not allowed' do 45 | expect { subject.purge :sss, :cpcode, '12345' }.to raise_error AkamaiApi::CCU::UnrecognizedOption 46 | end 47 | 48 | it 'type is not allowed' do 49 | expect { subject.purge :remove, :foo, '12345' }.to raise_error AkamaiApi::CCU::UnrecognizedOption 50 | end 51 | 52 | it 'domain is specified and not allowed' do 53 | expect { subject.purge :remove, :arl, 'foo', :domain => :foo }.to raise_error 54 | end 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /cassettes/akamai_api_eccu_destroy/successful.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://control.akamai.com/webservices/services/PublishECCU 6 | body: 7 | encoding: UTF-8 8 | string: 1234 13 | headers: 14 | Soapaction: 15 | - '"delete"' 16 | Content-Type: 17 | - text/xml;charset=UTF-8 18 | Content-Length: 19 | - '497' 20 | Accept-Encoding: 21 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 22 | Accept: 23 | - '*/*' 24 | User-Agent: 25 | - Ruby 26 | Authorization: 27 | - Basic VVNFUk5BTUU6UEFTU1dPUkQ= 28 | response: 29 | status: 30 | code: 200 31 | message: OK 32 | headers: 33 | Server: 34 | - Apache 35 | Content-Type: 36 | - text/xml;charset=utf-8 37 | Content-Length: 38 | - '478' 39 | Expires: 40 | - Thu, 22 May 2014 14:53:44 GMT 41 | Cache-Control: 42 | - max-age=0, no-cache, no-store 43 | Pragma: 44 | - no-cache 45 | Date: 46 | - Thu, 22 May 2014 14:53:44 GMT 47 | Connection: 48 | - keep-alive 49 | X-Frame-Options: 50 | - SAMEORIGIN 51 | body: 52 | encoding: UTF-8 53 | string: true 57 | http_version: 58 | recorded_at: Thu, 22 May 2014 14:53:42 GMT 59 | recorded_with: VCR 2.9.0 60 | -------------------------------------------------------------------------------- /cassettes/akamai_api_eccu_update_email/successful.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://control.akamai.com/webservices/services/PublishECCU 6 | body: 7 | encoding: UTF-8 8 | string: 1234guest@mikamai.com 13 | headers: 14 | Soapaction: 15 | - '"setNotes"' 16 | Content-Type: 17 | - text/xml;charset=UTF-8 18 | Content-Length: 19 | - '555' 20 | Accept-Encoding: 21 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 22 | Accept: 23 | - '*/*' 24 | User-Agent: 25 | - Ruby 26 | Authorization: 27 | - Basic VVNFUk5BTUU6UEFTU1dPUkQ= 28 | response: 29 | status: 30 | code: 200 31 | message: OK 32 | headers: 33 | Server: 34 | - Apache 35 | Content-Type: 36 | - text/xml;charset=utf-8 37 | Content-Length: 38 | - '482' 39 | Expires: 40 | - Thu, 22 May 2014 13:29:24 GMT 41 | Cache-Control: 42 | - max-age=0, no-cache, no-store 43 | Pragma: 44 | - no-cache 45 | Date: 46 | - Thu, 22 May 2014 13:29:24 GMT 47 | Connection: 48 | - keep-alive 49 | X-Frame-Options: 50 | - SAMEORIGIN 51 | body: 52 | encoding: UTF-8 53 | string: true 57 | http_version: 58 | recorded_at: Thu, 22 May 2014 13:29:23 GMT 59 | recorded_with: VCR 2.9.0 60 | -------------------------------------------------------------------------------- /cassettes/akamai_api_eccu_last_request/invalid_credentials.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://control.akamai.com/webservices/services/PublishECCU 6 | body: 7 | encoding: UTF-8 8 | string: 12 | headers: 13 | Soapaction: 14 | - '"getIds"' 15 | Content-Type: 16 | - text/xml;charset=UTF-8 17 | Content-Length: 18 | - '457' 19 | Accept-Encoding: 20 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 21 | Accept: 22 | - '*/*' 23 | User-Agent: 24 | - Ruby 25 | response: 26 | status: 27 | code: 401 28 | message: Unauthorized 29 | headers: 30 | Server: 31 | - Apache 32 | Www-Authenticate: 33 | - Basic realm="Luna Control Center Web Services (use your Luna username and 34 | password)" 35 | Content-Length: 36 | - '401' 37 | Content-Type: 38 | - text/html; charset=iso-8859-1 39 | Expires: 40 | - Tue, 20 May 2014 15:20:36 GMT 41 | Cache-Control: 42 | - max-age=0, no-cache, no-store 43 | Pragma: 44 | - no-cache 45 | Date: 46 | - Tue, 20 May 2014 15:20:36 GMT 47 | Connection: 48 | - close 49 | X-Frame-Options: 50 | - SAMEORIGIN 51 | body: 52 | encoding: UTF-8 53 | string: | 54 | 55 | 56 | 401 Authorization Required 57 | 58 |

Authorization Required

59 |

This server could not verify that you 60 | are authorized to access the document 61 | requested. Either you supplied the wrong 62 | credentials (e.g., bad password), or your 63 | browser doesn't understand how to supply 64 | the credentials required.

65 | 66 | http_version: 67 | recorded_at: Tue, 20 May 2014 15:20:36 GMT 68 | recorded_with: VCR 2.9.0 69 | -------------------------------------------------------------------------------- /features/ccu_cpcode_remove.feature: -------------------------------------------------------------------------------- 1 | Feature: akamai_api ccu cpcode remove 2 | In order to remove CPCodes 3 | As a CLI user 4 | 5 | @vcr 6 | Scenario: invalid credentials 7 | When I run `akamai_api ccu cpcode remove 12345 -u foo -p bar` 8 | Then the output should contain: 9 | """ 10 | Your login credentials are invalid. 11 | """ 12 | 13 | @vcr 14 | Scenario: invalid item 15 | When I run `akamai_api ccu cpcode remove 12345` 16 | Then the output should contain: 17 | """ 18 | Error 403: 'unauthorized cpcode' (12345) 19 | """ 20 | And the output should contain: 21 | """ 22 | Described by: https://api.ccu.akamai.com/ccu/v2/errors/unauthorized-cpcode 23 | """ 24 | 25 | @vcr 26 | Scenario: single item 27 | When I run `akamai_api ccu cpcode remove 12345` 28 | Then the output should contain: 29 | """ 30 | Purge request successfully submitted: 31 | """ 32 | And the output should contain: 33 | """ 34 | * Result: 201 - Request accepted. 35 | """ 36 | And the output should contain: 37 | """ 38 | * Purge ID: 12345678-1234-1234-1234-123456789012 | Support ID: 12345678901234567890-123456789 39 | """ 40 | And the output should contain: 41 | """ 42 | * Estimated time: 420 secs. 43 | """ 44 | And the output should contain: 45 | """ 46 | * Progress URI: /ccu/v2/purges/12345678-1234-5678-1234-123456789012 47 | """ 48 | And the output should contain: 49 | """ 50 | * Time to wait before check: 420 secs. 51 | """ 52 | 53 | @vcr 54 | Scenario: multiple items 55 | When I run `akamai_api ccu cpcode remove 12345 12346` 56 | Then the output should contain: 57 | """ 58 | Purge request successfully submitted: 59 | """ 60 | And the output should contain: 61 | """ 62 | * Result: 201 - Request accepted. 63 | """ 64 | And the output should contain: 65 | """ 66 | * Purge ID: 12345678-1234-1234-1234-123456789012 | Support ID: 12345678901234567890-123456789 67 | """ 68 | And the output should contain: 69 | """ 70 | * Estimated time: 420 secs. 71 | """ 72 | And the output should contain: 73 | """ 74 | * Progress URI: /ccu/v2/purges/12345678-1234-5678-1234-123456789012 75 | """ 76 | And the output should contain: 77 | """ 78 | * Time to wait before check: 420 secs. 79 | """ -------------------------------------------------------------------------------- /cassettes/akamai_api_eccu_update_notes/successful.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://control.akamai.com/webservices/services/PublishECCU 6 | body: 7 | encoding: UTF-8 8 | string: 1234request 13 | updated using AkamaiApi 14 | headers: 15 | Soapaction: 16 | - '"setNotes"' 17 | Content-Type: 18 | - text/xml;charset=UTF-8 19 | Content-Length: 20 | - '569' 21 | Accept-Encoding: 22 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 23 | Accept: 24 | - '*/*' 25 | User-Agent: 26 | - Ruby 27 | Authorization: 28 | - Basic VVNFUk5BTUU6UEFTU1dPUkQ= 29 | response: 30 | status: 31 | code: 200 32 | message: OK 33 | headers: 34 | Server: 35 | - Apache 36 | Content-Type: 37 | - text/xml;charset=utf-8 38 | Content-Length: 39 | - '482' 40 | Expires: 41 | - Thu, 22 May 2014 12:57:30 GMT 42 | Cache-Control: 43 | - max-age=0, no-cache, no-store 44 | Pragma: 45 | - no-cache 46 | Date: 47 | - Thu, 22 May 2014 12:57:30 GMT 48 | Connection: 49 | - keep-alive 50 | X-Frame-Options: 51 | - SAMEORIGIN 52 | body: 53 | encoding: UTF-8 54 | string: true 58 | http_version: 59 | recorded_at: Thu, 22 May 2014 12:57:29 GMT 60 | recorded_with: VCR 2.9.0 61 | -------------------------------------------------------------------------------- /lib/akamai_api/ccu/purge_status/response.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/ccu/base_response" 2 | 3 | module AkamaiApi::CCU::PurgeStatus 4 | # This class represents a successful response and details a purge request status 5 | class Response < AkamaiApi::CCU::BaseResponse 6 | # @return [String] URI to use to check the status of the request 7 | def progress_uri 8 | raw['progressUri'] 9 | end 10 | alias_method :uri, :progress_uri 11 | 12 | # Purge Request identifier 13 | # @return [String] Purge Request identifier 14 | def purge_id 15 | raw['purgeId'] 16 | end 17 | 18 | # Status of the purge request 19 | # @return ['In-Progress'] when the request is in progress 20 | # @return ['Done'] when the request has been completed 21 | # @return ['Unknown'] 22 | def purge_status 23 | raw['purgeStatus'] 24 | end 25 | alias_method :status, :purge_status 26 | 27 | # @return [Fixnum] Suggested time to wait (in seconds) before asking the status again 28 | def time_to_wait 29 | raw['pingAfterSeconds'] 30 | end 31 | alias_method :ping_after_seconds, :time_to_wait 32 | 33 | # @return [Fixnum] Estimated time (in seconds) for the operation to be completed, calculated when the request was submitted 34 | def original_estimated_time 35 | raw['originalEstimatedSeconds'] 36 | end 37 | alias_method :original_estimated_seconds, :original_estimated_time 38 | 39 | # @return [Fixnum] Number of jobs in queue, calculated when the request was submitted 40 | def original_queue_length 41 | raw['originalQueueLength'] 42 | end 43 | 44 | # The time the request was completed 45 | # @return [Time] the time the request was completed 46 | # @return [nil] when the request has not been completed (= its status isn't 'Done') 47 | def completed_at 48 | raw['completionTime'] && Time.iso8601(raw['completionTime']) 49 | end 50 | alias_method :completion_time, :completed_at 51 | 52 | # @return [String] The request author name 53 | def submitted_by 54 | raw['submittedBy'] 55 | end 56 | 57 | # The time the request was accepted 58 | # @return [Time] the time the request was accepted 59 | # @return [nil] when the request is still not accepted (= its status is neither 'Done' nor 'In-Progress') 60 | def submitted_at 61 | raw['submissionTime'] && Time.iso8601(raw['submissionTime']) 62 | end 63 | alias_method :submission_time, :submitted_at 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /features/ccu_cpcode_invalidate.feature: -------------------------------------------------------------------------------- 1 | Feature: akamai_api ccu cpcode invalidate 2 | In order to invalidate CPCodes 3 | As a CLI user 4 | 5 | @vcr 6 | Scenario: invalid credentials 7 | When I run `akamai_api ccu cpcode invalidate 12345 -u foo -p bar` 8 | Then the output should contain: 9 | """ 10 | Your login credentials are invalid. 11 | """ 12 | 13 | @vcr 14 | Scenario: invalid item 15 | When I run `akamai_api ccu cpcode invalidate 12345` 16 | Then the output should contain: 17 | """ 18 | Error 403: 'unauthorized cpcode' (12345) 19 | """ 20 | And the output should contain: 21 | """ 22 | Described by: https://api.ccu.akamai.com/ccu/v2/errors/unauthorized-cpcode 23 | """ 24 | 25 | @vcr 26 | Scenario: single item 27 | When I run `akamai_api ccu cpcode invalidate 12345` 28 | Then the output should contain: 29 | """ 30 | Purge request successfully submitted: 31 | """ 32 | And the output should contain: 33 | """ 34 | * Result: 201 - Request accepted. 35 | """ 36 | And the output should contain: 37 | """ 38 | * Purge ID: 12345678-1234-1234-1234-123456789012 | Support ID: 12345678901234567890-123456789 39 | """ 40 | And the output should contain: 41 | """ 42 | * Estimated time: 420 secs. 43 | """ 44 | And the output should contain: 45 | """ 46 | * Progress URI: /ccu/v2/purges/12345678-1234-5678-1234-123456789012 47 | """ 48 | And the output should contain: 49 | """ 50 | * Time to wait before check: 420 secs. 51 | """ 52 | 53 | @vcr 54 | Scenario: multiple items 55 | When I run `akamai_api ccu cpcode invalidate 12345 12346` 56 | Then the output should contain: 57 | """ 58 | Purge request successfully submitted: 59 | """ 60 | And the output should contain: 61 | """ 62 | * Result: 201 - Request accepted. 63 | """ 64 | And the output should contain: 65 | """ 66 | * Purge ID: 12345678-1234-1234-1234-123456789012 | Support ID: 12345678901234567890-123456789 67 | """ 68 | And the output should contain: 69 | """ 70 | * Estimated time: 420 secs. 71 | """ 72 | And the output should contain: 73 | """ 74 | * Progress URI: /ccu/v2/purges/12345678-1234-5678-1234-123456789012 75 | """ 76 | And the output should contain: 77 | """ 78 | * Time to wait before check: 420 secs. 79 | """ -------------------------------------------------------------------------------- /cassettes/akamai_api_eccu_destroy/not_found_request.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://control.akamai.com/webservices/services/PublishECCU 6 | body: 7 | encoding: UTF-8 8 | string: 1234 13 | headers: 14 | Soapaction: 15 | - '"delete"' 16 | Content-Type: 17 | - text/xml;charset=UTF-8 18 | Content-Length: 19 | - '497' 20 | Accept-Encoding: 21 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 22 | Accept: 23 | - '*/*' 24 | User-Agent: 25 | - Ruby 26 | Authorization: 27 | - Basic VVNFUk5BTUU6UEFTU1dPUkQ= 28 | response: 29 | status: 30 | code: 500 31 | message: Internal Server Error 32 | headers: 33 | Server: 34 | - Apache 35 | Content-Type: 36 | - text/xml;charset=utf-8 37 | Expires: 38 | - Thu, 22 May 2014 14:51:42 GMT 39 | Cache-Control: 40 | - max-age=0, no-cache, no-store 41 | Pragma: 42 | - no-cache 43 | Date: 44 | - Thu, 22 May 2014 14:51:42 GMT 45 | Connection: 46 | - close 47 | X-Frame-Options: 48 | - SAMEORIGIN 49 | body: 50 | encoding: UTF-8 51 | string: soapenv:Server.generalExceptionfileId 53 | 1234 does not existcom.akamai.aws.util.AWSFaultext-tomapp1.extranet.akamai.com 55 | http_version: 56 | recorded_at: Thu, 22 May 2014 14:51:41 GMT 57 | recorded_with: VCR 2.9.0 58 | -------------------------------------------------------------------------------- /cassettes/akamai_api_eccu_all_ids/invalid_credentials.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://control.akamai.com/webservices/services/PublishECCU 6 | body: 7 | encoding: UTF-8 8 | string: 12 | headers: 13 | Soapaction: 14 | - '"getIds"' 15 | Content-Type: 16 | - text/xml;charset=UTF-8 17 | Content-Length: 18 | - '457' 19 | Accept-Encoding: 20 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 21 | Accept: 22 | - '*/*' 23 | User-Agent: 24 | - Ruby 25 | Authorization: 26 | - Basic Zm9vOmJhcg== 27 | response: 28 | status: 29 | code: 401 30 | message: Unauthorized 31 | headers: 32 | Server: 33 | - Apache 34 | Www-Authenticate: 35 | - Basic realm="Luna Control Center Web Services (use your Luna username and 36 | password)" 37 | Content-Length: 38 | - '401' 39 | Content-Type: 40 | - text/html; charset=iso-8859-1 41 | Expires: 42 | - Mon, 26 May 2014 10:47:34 GMT 43 | Cache-Control: 44 | - max-age=0, no-cache, no-store 45 | Pragma: 46 | - no-cache 47 | Date: 48 | - Mon, 26 May 2014 10:47:34 GMT 49 | Connection: 50 | - close 51 | X-Frame-Options: 52 | - SAMEORIGIN 53 | body: 54 | encoding: UTF-8 55 | string: | 56 | 57 | 58 | 401 Authorization Required 59 | 60 |

Authorization Required

61 |

This server could not verify that you 62 | are authorized to access the document 63 | requested. Either you supplied the wrong 64 | credentials (e.g., bad password), or your 65 | browser doesn't understand how to supply 66 | the credentials required.

67 | 68 | http_version: 69 | recorded_at: Mon, 26 May 2014 10:47:34 GMT 70 | recorded_with: VCR 2.9.0 71 | -------------------------------------------------------------------------------- /cassettes/akamai_api_eccu_requests/invalid_credentials.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://control.akamai.com/webservices/services/PublishECCU 6 | body: 7 | encoding: UTF-8 8 | string: 12 | headers: 13 | Soapaction: 14 | - '"getIds"' 15 | Content-Type: 16 | - text/xml;charset=UTF-8 17 | Content-Length: 18 | - '457' 19 | Accept-Encoding: 20 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 21 | Accept: 22 | - '*/*' 23 | User-Agent: 24 | - Ruby 25 | Authorization: 26 | - Basic VVNFUk5BTUU6UEFTU1dPUkQ= 27 | response: 28 | status: 29 | code: 401 30 | message: Unauthorized 31 | headers: 32 | Server: 33 | - Apache 34 | Www-Authenticate: 35 | - Basic realm="Luna Control Center Web Services (use your Luna username and 36 | password)" 37 | Content-Length: 38 | - '401' 39 | Content-Type: 40 | - text/html; charset=iso-8859-1 41 | Expires: 42 | - Tue, 20 May 2014 15:38:58 GMT 43 | Cache-Control: 44 | - max-age=0, no-cache, no-store 45 | Pragma: 46 | - no-cache 47 | Date: 48 | - Tue, 20 May 2014 15:38:58 GMT 49 | Connection: 50 | - close 51 | X-Frame-Options: 52 | - SAMEORIGIN 53 | body: 54 | encoding: UTF-8 55 | string: | 56 | 57 | 58 | 401 Authorization Required 59 | 60 |

Authorization Required

61 |

This server could not verify that you 62 | are authorized to access the document 63 | requested. Either you supplied the wrong 64 | credentials (e.g., bad password), or your 65 | browser doesn't understand how to supply 66 | the credentials required.

67 | 68 | http_version: 69 | recorded_at: Tue, 20 May 2014 15:38:58 GMT 70 | recorded_with: VCR 2.9.0 71 | -------------------------------------------------------------------------------- /features/ccu_arl_remove.feature: -------------------------------------------------------------------------------- 1 | Feature: akamai_api ccu arl remove 2 | In order to remove ARLs 3 | As a CLI user 4 | 5 | @vcr 6 | Scenario: invalid credentials 7 | When I run `akamai_api ccu arl remove http://www.foo.bar/t.txt -u foo -p bar` 8 | Then the output should contain: 9 | """ 10 | Your login credentials are invalid. 11 | """ 12 | 13 | @vcr 14 | Scenario: invalid item 15 | When I run `akamai_api ccu arl remove http://www.foo.bar/t.txt` 16 | Then the output should contain: 17 | """ 18 | Error 403: 'unauthorized arl' (http://www.foo.bar/t.txt) 19 | """ 20 | And the output should contain: 21 | """ 22 | Described by: https://api.ccu.akamai.com/ccu/v2/errors/unauthorized-arl 23 | """ 24 | 25 | @vcr 26 | Scenario: single item 27 | When I run `akamai_api ccu arl remove http://www.foo.bar/t.txt` 28 | Then the output should contain: 29 | """ 30 | Purge request successfully submitted: 31 | """ 32 | And the output should contain: 33 | """ 34 | * Result: 201 - Request accepted. 35 | """ 36 | And the output should contain: 37 | """ 38 | * Purge ID: 12345678-1234-1234-1234-123456789012 | Support ID: 12345678901234567890-123456789 39 | """ 40 | And the output should contain: 41 | """ 42 | * Estimated time: 420 secs. 43 | """ 44 | And the output should contain: 45 | """ 46 | * Progress URI: /ccu/v2/purges/12345678-1234-5678-1234-123456789012 47 | """ 48 | And the output should contain: 49 | """ 50 | * Time to wait before check: 420 secs. 51 | """ 52 | 53 | @vcr 54 | Scenario: multiple items 55 | When I run `akamai_api ccu arl remove http://www.foo.com/bar.txt http://www.foo.com/baz.txt` 56 | Then the output should contain: 57 | """ 58 | Purge request successfully submitted: 59 | """ 60 | And the output should contain: 61 | """ 62 | * Result: 201 - Request accepted. 63 | """ 64 | And the output should contain: 65 | """ 66 | * Purge ID: 12345678-1234-1234-1234-123456789012 | Support ID: 12345678901234567890-123456789 67 | """ 68 | And the output should contain: 69 | """ 70 | * Estimated time: 420 secs. 71 | """ 72 | And the output should contain: 73 | """ 74 | * Progress URI: /ccu/v2/purges/12345678-1234-5678-1234-123456789012 75 | """ 76 | And the output should contain: 77 | """ 78 | * Time to wait before check: 420 secs. 79 | """ -------------------------------------------------------------------------------- /cassettes/akamai_api_eccu_find/not_found_request.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://control.akamai.com/webservices/services/PublishECCU 6 | body: 7 | encoding: UTF-8 8 | string: 1234true 13 | headers: 14 | Soapaction: 15 | - '"getInfo"' 16 | Content-Type: 17 | - text/xml;charset=UTF-8 18 | Content-Length: 19 | - '563' 20 | Accept-Encoding: 21 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 22 | Accept: 23 | - "*/*" 24 | User-Agent: 25 | - Ruby 26 | Authorization: 27 | - Basic VVNFUk5BTUU6UEFTU1dPUkQ= 28 | response: 29 | status: 30 | code: 500 31 | message: Internal Server Error 32 | headers: 33 | Server: 34 | - Apache 35 | Content-Type: 36 | - text/xml;charset=utf-8 37 | Expires: 38 | - Fri, 23 May 2014 09:01:10 GMT 39 | Cache-Control: 40 | - max-age=0, no-cache, no-store 41 | Pragma: 42 | - no-cache 43 | Date: 44 | - Fri, 23 May 2014 09:01:10 GMT 45 | Connection: 46 | - close 47 | X-Frame-Options: 48 | - SAMEORIGIN 49 | body: 50 | encoding: UTF-8 51 | string: soapenv:Server.generalExceptionfileId 53 | 1234 does not existcom.akamai.aws.util.AWSFaultext-tomapp2.extranet.akamai.com 55 | http_version: 56 | recorded_at: Fri, 23 May 2014 09:01:10 GMT 57 | recorded_with: VCR 2.9.0 58 | -------------------------------------------------------------------------------- /cassettes/akamai_api_eccu_update_notes/not_found_request.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://control.akamai.com/webservices/services/PublishECCU 6 | body: 7 | encoding: UTF-8 8 | string: 1234request updated 13 | using AkamaiApi 14 | headers: 15 | Soapaction: 16 | - '"setNotes"' 17 | Content-Type: 18 | - text/xml;charset=UTF-8 19 | Content-Length: 20 | - '569' 21 | Accept-Encoding: 22 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 23 | Accept: 24 | - '*/*' 25 | User-Agent: 26 | - Ruby 27 | Authorization: 28 | - Basic VVNFUk5BTUU6UEFTU1dPUkQ= 29 | response: 30 | status: 31 | code: 500 32 | message: Internal Server Error 33 | headers: 34 | Server: 35 | - Apache 36 | Content-Type: 37 | - text/xml;charset=utf-8 38 | Expires: 39 | - Thu, 22 May 2014 12:50:37 GMT 40 | Cache-Control: 41 | - max-age=0, no-cache, no-store 42 | Pragma: 43 | - no-cache 44 | Date: 45 | - Thu, 22 May 2014 12:50:37 GMT 46 | Connection: 47 | - close 48 | X-Frame-Options: 49 | - SAMEORIGIN 50 | body: 51 | encoding: UTF-8 52 | string: soapenv:Server.generalExceptionfileId 54 | 1234 does not existcom.akamai.aws.util.AWSFaultext-tomapp1.extranet.akamai.com 56 | http_version: 57 | recorded_at: Thu, 22 May 2014 12:50:36 GMT 58 | recorded_with: VCR 2.9.0 59 | -------------------------------------------------------------------------------- /cassettes/akamai_api_eccu_destroy/invalid_credentials.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://control.akamai.com/webservices/services/PublishECCU 6 | body: 7 | encoding: UTF-8 8 | string: 1234 13 | headers: 14 | Soapaction: 15 | - '"delete"' 16 | Content-Type: 17 | - text/xml;charset=UTF-8 18 | Content-Length: 19 | - '497' 20 | Accept-Encoding: 21 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 22 | Accept: 23 | - "*/*" 24 | User-Agent: 25 | - Ruby 26 | Authorization: 27 | - Basic Zm9vOmJhcg== 28 | response: 29 | status: 30 | code: 401 31 | message: Unauthorized 32 | headers: 33 | Www-Authenticate: 34 | - Basic realm="Luna Control Center Web Services (use your Luna username and 35 | password)" 36 | Content-Length: 37 | - '401' 38 | Content-Type: 39 | - text/html; charset=iso-8859-1 40 | Expires: 41 | - Thu, 02 Mar 2017 05:44:32 GMT 42 | Cache-Control: 43 | - max-age=0, no-cache, no-store 44 | Pragma: 45 | - no-cache 46 | Date: 47 | - Thu, 02 Mar 2017 05:44:32 GMT 48 | Connection: 49 | - close 50 | Strict-Transport-Security: 51 | - max-age=15552000 52 | X-Frame-Options: 53 | - SAMEORIGIN 54 | body: 55 | encoding: UTF-8 56 | string: | 57 | 58 | 59 | 401 Authorization Required 60 | 61 |

Authorization Required

62 |

This server could not verify that you 63 | are authorized to access the document 64 | requested. Either you supplied the wrong 65 | credentials (e.g., bad password), or your 66 | browser doesn't understand how to supply 67 | the credentials required.

68 | 69 | http_version: 70 | recorded_at: Thu, 02 Mar 2017 05:44:32 GMT 71 | recorded_with: VCR 3.0.3 72 | -------------------------------------------------------------------------------- /cassettes/akamai_api_eccu_update_email/not_found_request.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://control.akamai.com/webservices/services/PublishECCU 6 | body: 7 | encoding: UTF-8 8 | string: 1234guest@mikamai.com 13 | headers: 14 | Soapaction: 15 | - '"setStatusChangeEmail"' 16 | Content-Type: 17 | - text/xml;charset=UTF-8 18 | Content-Length: 19 | - '603' 20 | Accept-Encoding: 21 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 22 | Accept: 23 | - '*/*' 24 | User-Agent: 25 | - Ruby 26 | Authorization: 27 | - Basic VVNFUk5BTUU6UEFTU1dPUkQ= 28 | response: 29 | status: 30 | code: 500 31 | message: Internal Server Error 32 | headers: 33 | Server: 34 | - Apache 35 | Content-Type: 36 | - text/xml;charset=utf-8 37 | Expires: 38 | - Thu, 22 May 2014 13:28:24 GMT 39 | Cache-Control: 40 | - max-age=0, no-cache, no-store 41 | Pragma: 42 | - no-cache 43 | Date: 44 | - Thu, 22 May 2014 13:28:24 GMT 45 | Connection: 46 | - close 47 | X-Frame-Options: 48 | - SAMEORIGIN 49 | body: 50 | encoding: UTF-8 51 | string: soapenv:Server.generalExceptionfileId 53 | 1234 does not existcom.akamai.aws.util.AWSFaultext-tomapp6.extranet.akamai.com 55 | http_version: 56 | recorded_at: Thu, 22 May 2014 13:28:23 GMT 57 | recorded_with: VCR 2.9.0 58 | -------------------------------------------------------------------------------- /cassettes/akamai_api_eccu_find/invalid_credentials.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://control.akamai.com/webservices/services/PublishECCU 6 | body: 7 | encoding: UTF-8 8 | string: 1234true 13 | headers: 14 | Soapaction: 15 | - '"getInfo"' 16 | Content-Type: 17 | - text/xml;charset=UTF-8 18 | Content-Length: 19 | - '563' 20 | Accept-Encoding: 21 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 22 | Accept: 23 | - "*/*" 24 | User-Agent: 25 | - Ruby 26 | Authorization: 27 | - Basic Zm9vOmJhcg== 28 | response: 29 | status: 30 | code: 401 31 | message: Unauthorized 32 | headers: 33 | Www-Authenticate: 34 | - Basic realm="Luna Control Center Web Services (use your Luna username and 35 | password)" 36 | Content-Length: 37 | - '401' 38 | Content-Type: 39 | - text/html; charset=iso-8859-1 40 | Expires: 41 | - Thu, 02 Mar 2017 05:48:42 GMT 42 | Cache-Control: 43 | - max-age=0, no-cache, no-store 44 | Pragma: 45 | - no-cache 46 | Date: 47 | - Thu, 02 Mar 2017 05:48:42 GMT 48 | Connection: 49 | - close 50 | Strict-Transport-Security: 51 | - max-age=15552000 52 | X-Frame-Options: 53 | - SAMEORIGIN 54 | body: 55 | encoding: UTF-8 56 | string: | 57 | 58 | 59 | 401 Authorization Required 60 | 61 |

Authorization Required

62 |

This server could not verify that you 63 | are authorized to access the document 64 | requested. Either you supplied the wrong 65 | credentials (e.g., bad password), or your 66 | browser doesn't understand how to supply 67 | the credentials required.

68 | 69 | http_version: 70 | recorded_at: Thu, 02 Mar 2017 05:48:42 GMT 71 | recorded_with: VCR 3.0.3 72 | -------------------------------------------------------------------------------- /cassettes/akamai_api_eccu_update_notes/invalid_credentials.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://control.akamai.com/webservices/services/PublishECCU 6 | body: 7 | encoding: UTF-8 8 | string: 1234request updated 13 | using AkamaiApi 14 | headers: 15 | Soapaction: 16 | - '"setNotes"' 17 | Content-Type: 18 | - text/xml;charset=UTF-8 19 | Content-Length: 20 | - '569' 21 | Accept-Encoding: 22 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 23 | Accept: 24 | - "*/*" 25 | User-Agent: 26 | - Ruby 27 | Authorization: 28 | - Basic Zm9vOmJhcg== 29 | response: 30 | status: 31 | code: 401 32 | message: Unauthorized 33 | headers: 34 | Www-Authenticate: 35 | - Basic realm="Luna Control Center Web Services (use your Luna username and 36 | password)" 37 | Content-Length: 38 | - '401' 39 | Content-Type: 40 | - text/html; charset=iso-8859-1 41 | Expires: 42 | - Thu, 02 Mar 2017 05:58:41 GMT 43 | Cache-Control: 44 | - max-age=0, no-cache, no-store 45 | Pragma: 46 | - no-cache 47 | Date: 48 | - Thu, 02 Mar 2017 05:58:41 GMT 49 | Connection: 50 | - close 51 | Strict-Transport-Security: 52 | - max-age=15552000 53 | X-Frame-Options: 54 | - SAMEORIGIN 55 | body: 56 | encoding: UTF-8 57 | string: | 58 | 59 | 60 | 401 Authorization Required 61 | 62 |

Authorization Required

63 |

This server could not verify that you 64 | are authorized to access the document 65 | requested. Either you supplied the wrong 66 | credentials (e.g., bad password), or your 67 | browser doesn't understand how to supply 68 | the credentials required.

69 | 70 | http_version: 71 | recorded_at: Thu, 02 Mar 2017 05:58:41 GMT 72 | recorded_with: VCR 3.0.3 73 | -------------------------------------------------------------------------------- /features/ccu_purge_status.feature: -------------------------------------------------------------------------------- 1 | Feature: akamai_api ccu purge status 2 | In order to get the status of an Akamai CCU request 3 | As a CLI user 4 | 5 | @vcr 6 | Scenario: invalid credentials 7 | When I run `akamai_api ccu status 12345678-1234-5678-1234-123456789012 -u foo -p bar` 8 | Then the output should contain: 9 | """ 10 | Your login credentials are invalid. 11 | """ 12 | 13 | @vcr 14 | Scenario: completed request 15 | When I run `akamai_api ccu status /ccu/v2/purges/12345678-1234-5678-1234-123456789012` 16 | Then the output should contain: 17 | """ 18 | Purge request has been successfully completed: 19 | """ 20 | And the output should contain: 21 | """ 22 | * Result: 200 - Done 23 | """ 24 | And the output should contain: 25 | """ 26 | * Purge ID: 12345678-1234-5678-1234-123456789012 | Support ID: 12345678901234567890-123456789 27 | """ 28 | And the output should contain: 29 | """ 30 | * Submitted by: test1 on 2014-05-20 08:19:21 UTC 31 | """ 32 | And the output should contain: 33 | """ 34 | * Completed on: 2014-05-20 08:22:20 UTC 35 | """ 36 | 37 | @vcr 38 | Scenario: enqueued request 39 | When I run `akamai_api ccu status ccu/v2/purges/12345678-1234-5678-1234-123456789012` 40 | Then the output should contain: 41 | """ 42 | Purge request is currently enqueued: 43 | """ 44 | And the output should contain: 45 | """ 46 | Result: 200 - In-Progress 47 | """ 48 | And the output should contain: 49 | """ 50 | * Purge ID: 12345678-1234-5678-1234-123456789012 | Support ID: 12345678901234567890-123456789 51 | """ 52 | And the output should contain: 53 | """ 54 | * Submitted by: test1 on 2014-05-20 08:19:21 UTC 55 | """ 56 | And the output should contain: 57 | """ 58 | * Time to wait before next check: 60 secs. 59 | """ 60 | And the output should not contain: 61 | """ 62 | * Completed on 63 | """ 64 | 65 | @vcr 66 | Scenario: not found request 67 | When I run `akamai_api ccu status foobarbaz` 68 | Then the output should contain: 69 | """ 70 | No purge request found 71 | """ 72 | And the output should contain: 73 | """ 74 | Result: 200 - Please note that it can take up to a minute for the status of a recently submitted request to become visible. 75 | """ 76 | And the output should contain: 77 | """ 78 | * Support ID: 12345678901234567890-123456789 79 | """ 80 | And the output should contain: 81 | """ 82 | * Time to wait before next check: 60 secs. 83 | """ -------------------------------------------------------------------------------- /cassettes/akamai_api_eccu_update_email/invalid_credentials.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://control.akamai.com/webservices/services/PublishECCU 6 | body: 7 | encoding: UTF-8 8 | string: 1234guest@mikamai.com 13 | headers: 14 | Soapaction: 15 | - '"setStatusChangeEmail"' 16 | Content-Type: 17 | - text/xml;charset=UTF-8 18 | Content-Length: 19 | - '603' 20 | Accept-Encoding: 21 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 22 | Accept: 23 | - "*/*" 24 | User-Agent: 25 | - Ruby 26 | Authorization: 27 | - Basic Zm9vOmJhcg== 28 | response: 29 | status: 30 | code: 401 31 | message: Unauthorized 32 | headers: 33 | Www-Authenticate: 34 | - Basic realm="Luna Control Center Web Services (use your Luna username and 35 | password)" 36 | Content-Length: 37 | - '401' 38 | Content-Type: 39 | - text/html; charset=iso-8859-1 40 | Expires: 41 | - Thu, 02 Mar 2017 05:54:58 GMT 42 | Cache-Control: 43 | - max-age=0, no-cache, no-store 44 | Pragma: 45 | - no-cache 46 | Date: 47 | - Thu, 02 Mar 2017 05:54:58 GMT 48 | Connection: 49 | - close 50 | Strict-Transport-Security: 51 | - max-age=15552000 52 | X-Frame-Options: 53 | - SAMEORIGIN 54 | body: 55 | encoding: UTF-8 56 | string: | 57 | 58 | 59 | 401 Authorization Required 60 | 61 |

Authorization Required

62 |

This server could not verify that you 63 | are authorized to access the document 64 | requested. Either you supplied the wrong 65 | credentials (e.g., bad password), or your 66 | browser doesn't understand how to supply 67 | the credentials required.

68 | 69 | http_version: 70 | recorded_at: Thu, 02 Mar 2017 05:54:58 GMT 71 | recorded_with: VCR 3.0.3 72 | -------------------------------------------------------------------------------- /lib/akamai_api/eccu_request.rb: -------------------------------------------------------------------------------- 1 | require "savon" 2 | require "active_support" 3 | require "active_support/core_ext/array" 4 | require "active_support/core_ext/object/blank" 5 | 6 | require "akamai_api/eccu/soap_body" 7 | require "akamai_api/eccu/update_attribute_request" 8 | require "akamai_api/eccu/destroy_request" 9 | require "akamai_api/eccu/find_request" 10 | require "akamai_api/eccu/publish_request" 11 | require "akamai_api/eccu/list_request" 12 | 13 | module AkamaiApi 14 | class ECCURequest 15 | attr_accessor :file, :status, :code, :notes, :property, :email, :upload_date, :uploaded_by, :version 16 | 17 | def initialize attributes = {} 18 | attributes.each do |key, value| 19 | send "#{key}=", value 20 | end 21 | end 22 | 23 | { 24 | notes: :notes, 25 | email: :status_change_email 26 | }.each do |name, attribute| 27 | define_method "update_#{name}!" do |value| 28 | successful = AkamaiApi::ECCU::UpdateAttributeRequest.new(code, attribute).execute(value) 29 | send "#{name}=", value if successful 30 | successful 31 | end 32 | end 33 | 34 | def destroy 35 | AkamaiApi::ECCU::DestroyRequest.new(code).execute 36 | end 37 | 38 | class << self 39 | def all_ids 40 | AkamaiApi::ECCU::ListRequest.new.execute 41 | end 42 | 43 | def all args = {} 44 | all_ids.map { |v| ECCURequest.find v, args } 45 | end 46 | 47 | def last args = {} 48 | find all_ids.last, args 49 | end 50 | 51 | def first args = {} 52 | find all_ids.first, args 53 | end 54 | 55 | def find code, args = {} 56 | response = AkamaiApi::ECCU::FindRequest.new(code).execute args.fetch(:verbose, true) 57 | new :file => response.file, 58 | :status => response.status, 59 | :code => response.code, 60 | :notes => response.notes, 61 | :property => response.property, 62 | :email => response.email, 63 | :upload_date => response.uploaded_at, 64 | :uploaded_by => response.uploaded_by, 65 | :version => response.version 66 | end 67 | 68 | def publish_file property, file_name, args = {} 69 | args[:file_name] = file_name 70 | publish property, File.read(file_name), args 71 | end 72 | 73 | def publish property, content, args = {} 74 | args = args.dup 75 | AkamaiApi::ECCU::PublishRequest.new(property, extract_property_arguments(args)).execute content, args 76 | end 77 | 78 | private 79 | 80 | def extract_property_arguments args 81 | { type: args.delete(:property_type), exact_match: args.delete(:property_exact_match) }.reject { |k, v| v.nil? } 82 | end 83 | end 84 | end 85 | end 86 | -------------------------------------------------------------------------------- /lib/akamai_api/cli/ccu/status_renderer.rb: -------------------------------------------------------------------------------- 1 | require "akamai_api/ccu/status/response" 2 | require "akamai_api/ccu/purge_status/response" 3 | 4 | module AkamaiApi::CLI::CCU 5 | class StatusRenderer 6 | attr_reader :response 7 | 8 | def initialize(response) 9 | @response = response 10 | end 11 | 12 | def render_error 13 | if response.is_a? AkamaiApi::CCU::PurgeStatus::NotFound 14 | render_not_found 15 | else 16 | render_generic_error 17 | end 18 | end 19 | 20 | def render 21 | res = response.is_a?(AkamaiApi::CCU::Status::Response) ? queue_status : purge_status 22 | [ 23 | '----------', 24 | res, 25 | '----------' 26 | ].join "\n" 27 | end 28 | 29 | def queue_status 30 | [ 31 | "Akamai CCU Queue Status", 32 | "\t* Result: #{response.code} - #{response.message}", 33 | "\t* Support ID: #{response.support_id}", 34 | "\t* Queue Length: #{response.queue_length}" 35 | ] 36 | end 37 | 38 | def purge_status 39 | output = [ 40 | purge_description, 41 | "\t* Result: #{response.code} - #{response.status}", 42 | "\t* Purge ID: #{response.purge_id} | Support ID: #{response.support_id}", 43 | "\t* Submitted by: #{response.submitted_by} on #{response.submitted_at}" 44 | ] 45 | output.concat response.completed_at ? successful_completed_purge : successful_pending_purge 46 | end 47 | 48 | def purge_description 49 | if response.completed_at 50 | "Purge request has been successfully completed:" 51 | else 52 | "Purge request is currently enqueued:" 53 | end 54 | end 55 | 56 | def render_not_found 57 | [ 58 | "----------", 59 | "No purge request found using #{response.progress_uri}:", 60 | "\t* Result: #{response.code} - #{response.message}", 61 | "\t* Support ID: #{response.support_id}", 62 | "\t* Time to wait before next check: #{response.time_to_wait} secs.", 63 | "----------" 64 | ].join "\n" 65 | end 66 | 67 | def render_generic_error 68 | [ 69 | "----------", 70 | "Error #{response.code}: '#{response.message}' (#{response.detail})", 71 | " Described by: #{response.described_by}", 72 | " Support ID: #{response.support_id}", 73 | "----------" 74 | ].join "\n" 75 | end 76 | 77 | def successful_completed_purge 78 | ["\t* Completed on: #{response.completed_at}"] 79 | end 80 | 81 | def successful_pending_purge 82 | [ 83 | "\t* Estimated time was: #{response.original_estimated_time} secs.", 84 | "\t* Queue length was: #{response.original_queue_length}", 85 | "\t* Time to wait before next check: #{response.time_to_wait} secs.", 86 | ] 87 | end 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /spec/lib/akamai_api/ccu/purge_status/response_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AkamaiApi::CCU::PurgeStatus::Response do 4 | let(:raw) do 5 | { 6 | 'originalEstimatedSeconds' => 480, 7 | 'progressUri' => '/CCU/v2/purges/12345678-1234-5678-1234-123456789012', 8 | 'originalQueueLength' => 6, 9 | 'purgeId' => '12345678-1234-5678-1234-123456789012', 10 | 'supportId' => '12345678901234567890-123456789', 11 | 'httpStatus' => 200, 12 | 'completionTime' => '2014-02-19T22:16:20Z', 13 | 'submittedBy' => 'test1', 14 | 'purgeStatus' => 'In-Progress', 15 | 'submissionTime' => '2014-02-19T21:16:20Z', 16 | 'pingAfterSeconds' => 60 17 | } 18 | end 19 | subject { AkamaiApi::CCU::PurgeStatus::Response.new raw } 20 | 21 | it '#original_estimated_time returns originalEstimatedSeconds attribute' do 22 | expect(subject.original_estimated_time).to eq 480 23 | end 24 | 25 | it '#progress_uri returns progressUri attribute' do 26 | expect(subject.progress_uri).to eq '/CCU/v2/purges/12345678-1234-5678-1234-123456789012' 27 | end 28 | 29 | it '#original_queue_length returns originalQueueLength attribute' do 30 | expect(subject.original_queue_length).to eq 6 31 | end 32 | 33 | it '#purge_id returns purgeId attribute' do 34 | expect(subject.purge_id).to eq '12345678-1234-5678-1234-123456789012' 35 | end 36 | 37 | it '#support_id returns supportId attribute' do 38 | expect(subject.support_id).to eq '12345678901234567890-123456789' 39 | end 40 | 41 | it '#code returns httpStatus attribute' do 42 | expect(subject.code).to eq 200 43 | end 44 | 45 | describe '#completed_at' do 46 | it 'returns a Time object' do 47 | expect(subject.completed_at).to be_a Time 48 | end 49 | 50 | it 'returns completionTime attribute' do 51 | expect(subject.completed_at.iso8601).to eq '2014-02-19T22:16:20Z' 52 | end 53 | 54 | it 'can return nil' do 55 | raw['completionTime'] = nil 56 | expect(subject.completed_at).to be_nil 57 | end 58 | end 59 | 60 | it '#submitted_by returns submittedBy attribute' do 61 | expect(subject.submitted_by).to eq 'test1' 62 | end 63 | 64 | it '#status returns purgeStatus attribute' do 65 | expect(subject.status).to eq 'In-Progress' 66 | end 67 | 68 | describe '#submitted_at' do 69 | it 'returns a Time object' do 70 | expect(subject.submitted_at).to be_a Time 71 | end 72 | 73 | it 'can return nil' do 74 | raw['submissionTime'] = nil 75 | expect(subject.submitted_at).to be_nil 76 | end 77 | 78 | it 'returns submissionTime attribute' do 79 | expect(subject.submitted_at.iso8601).to eq '2014-02-19T21:16:20Z' 80 | end 81 | end 82 | 83 | it '#time_to_wait returns pingAfterSeconds attribute' do 84 | expect(subject.time_to_wait).to eq 60 85 | end 86 | end 87 | -------------------------------------------------------------------------------- /lib/akamai_api/ccu/purge_status/request.rb: -------------------------------------------------------------------------------- 1 | require "httparty" 2 | 3 | require "akamai_api/unauthorized" 4 | require "akamai_api/ccu/error" 5 | require "akamai_api/ccu/purge_status/response" 6 | require "akamai_api/ccu/purge_status/not_found" 7 | 8 | module AkamaiApi::CCU::PurgeStatus 9 | # {Request} is used to check the status of a purge request using Akamai CCU. 10 | # 11 | # @example Check using {AkamaiApi::CCU::Purge::Response#purge_id} 12 | # purge_id # => "12345678-1234-5678-1234-123456789012" 13 | # AkamaiApi::CCU::PurgeStatus::Request.execute(purge_id) 14 | # @example Check using {AkamaiApi::CCU::Purge::Response#progress_uri} 15 | # progress_uri # => "/CCU/v2/purges/12345678-1234-5678-1234-123456789012" 16 | # AkamaiApi::CCU::PurgeStatus::Request.execute(progress_uri) 17 | class Request 18 | include HTTParty 19 | format :json 20 | base_uri 'https://api.ccu.akamai.com' 21 | 22 | # Checks the status of the requested associated with the given argument 23 | # @param [String] purge_id_or_progress_uri a purge request ID or URI 24 | # @return [Response] an object detailing the response 25 | # @raise [AkamaiApi::CCU::PurgeStatus::NotFound] when the request cannot be found 26 | # @raise [AkamaiApi::CCU::Error] when there is an error in the request 27 | # @raise [AkamaiApi::Unauthorized] when login credentials are invalid 28 | def self.execute purge_id_or_progress_uri 29 | new.execute purge_id_or_progress_uri 30 | end 31 | 32 | # Checks the status of the requested associated with the given argument 33 | # @return [Response] an object detailing the response 34 | # @raise [AkamaiApi::CCU::PurgeStatus::NotFound] when the request cannot be found 35 | # @raise [AkamaiApi::CCU::Error] when there is an error in the request 36 | # @raise [AkamaiApi::Unauthorized] when login credentials are invalid 37 | def execute purge_id_or_progress_uri 38 | purge_id_or_progress_uri = normalize_progress_uri purge_id_or_progress_uri 39 | response = self.class.get purge_id_or_progress_uri, basic_auth: AkamaiApi.auth 40 | parse_response response 41 | end 42 | 43 | private 44 | 45 | def parse_response response 46 | raise AkamaiApi::Unauthorized if response.code == 401 47 | parsed = response.parsed_response 48 | raise AkamaiApi::CCU::Error.new parsed unless successful_response? parsed 49 | raise AkamaiApi::CCU::PurgeStatus::NotFound.new parsed unless parsed['submissionTime'] 50 | AkamaiApi::CCU::PurgeStatus::Response.new(parsed) 51 | end 52 | 53 | def normalize_progress_uri progress_uri 54 | progress_uri = "/#{progress_uri}" unless progress_uri =~ /^\// 55 | if progress_uri =~ /\/ccu\/v2\/purges\// 56 | progress_uri 57 | else 58 | "/ccu/v2/purges#{progress_uri}" 59 | end 60 | end 61 | 62 | def successful_response? parsed_response 63 | (200...300).include? parsed_response['httpStatus'] 64 | end 65 | end 66 | end 67 | -------------------------------------------------------------------------------- /spec/lib/akamai_api/eccu/destroy_request_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AkamaiApi::ECCU::DestroyRequest do 4 | subject { AkamaiApi::ECCU::DestroyRequest.new '1234' } 5 | 6 | describe "#execute" do 7 | let(:fake_client) { double call: nil } 8 | 9 | before do 10 | allow(AkamaiApi::ECCU).to receive(:client) { fake_client } 11 | end 12 | 13 | it "calls 'delete' via savon with a message" do 14 | fake_response = double body: { delete_response: { success: true } } 15 | expect(subject).to receive(:request_body).and_return double(to_s: 'asd') 16 | expect(fake_client).to receive(:call).with(:delete, message: 'asd').and_return fake_response 17 | subject.execute 18 | end 19 | 20 | it "returns 'true' if response hash reports to be successful" do 21 | allow(subject).to receive(:request_body) { 'example' } 22 | allow(fake_client).to receive(:call) { double(body: { delete_response: { success: true } }) } 23 | expect(subject.execute).to be_truthy 24 | end 25 | 26 | it "returns 'false' if response hash reports to be unsuccessful" do 27 | allow(subject).to receive(:request_body) { 'example' } 28 | allow(fake_client).to receive(:call) { double(body: { delete_response: { success: false } }) } 29 | expect(subject.execute).to be_falsy 30 | end 31 | 32 | it "raises NotFound if request raises a Savon::SOAPFault with particular message" do 33 | expect(fake_client).to receive :call do 34 | exc = Savon::SOAPFault.new({}, {}) 35 | allow(exc).to receive(:to_hash) { { fault: { faultstring: 'asdasd fileId xsxx does not exist' } } } 36 | allow(exc).to receive(:to_s) { '' } 37 | raise exc 38 | end 39 | expect { subject.execute }.to raise_error AkamaiApi::ECCU::NotFound 40 | end 41 | 42 | it "raises unauthorized if request raises a Savon::HTTPError with code 401" do 43 | expect(fake_client).to receive :call do 44 | raise Savon::HTTPError, double(code: 401) 45 | end 46 | expect { subject.execute }.to raise_error AkamaiApi::Unauthorized 47 | end 48 | 49 | it "raises Savon:HTTPError if request raises this exception and its code differs from 401" do 50 | expect(fake_client).to receive :call do 51 | raise Savon::HTTPError, double(code: 402) 52 | end 53 | expect { subject.execute }.to raise_error Savon::HTTPError 54 | end 55 | end 56 | 57 | describe "#request_body" do 58 | def subject_request_body 59 | subject.send :request_body 60 | end 61 | 62 | it "returns a SoapBody object" do 63 | expect(subject_request_body).to be_a AkamaiApi::ECCU::SoapBody 64 | end 65 | 66 | it "sets an integer value named 'fileId' with the given code" do 67 | expect_any_instance_of(AkamaiApi::ECCU::SoapBody).to receive(:integer).with :fileId, 1234 68 | subject_request_body 69 | end 70 | 71 | it "sets only fileId" do 72 | expect(subject_request_body.to_s).to eq "1234" 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /spec/lib/akamai_api/eccu/find_request_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AkamaiApi::ECCU::FindRequest do 4 | subject { AkamaiApi::ECCU::FindRequest.new '1234' } 5 | 6 | describe "#execute" do 7 | let(:fake_client) { double call: nil } 8 | 9 | before do 10 | allow(AkamaiApi::ECCU).to receive(:client) { fake_client } 11 | end 12 | 13 | it "calls 'get_info' via savon with a message" do 14 | fake_response = double body: { get_info_response: { success: true } } 15 | expect(subject).to receive(:request_body).with(true).and_return double(to_s: 'asd') 16 | expect(fake_client).to receive(:call).with(:get_info, message: 'asd').and_return fake_response 17 | subject.execute true 18 | end 19 | 20 | it "returns a FindResponse" do 21 | allow(subject).to receive(:request_body) { 'example' } 22 | allow(fake_client).to receive(:call) { double(body: { get_info_response: { ECCU_info: {} } }) } 23 | expect(subject.execute 'foo').to be_a AkamaiApi::ECCU::FindResponse 24 | end 25 | 26 | it "raises NotFound if request raises a Savon::SOAPFault with particular message" do 27 | expect(fake_client).to receive :call do 28 | exc = Savon::SOAPFault.new({}, {}) 29 | allow(exc).to receive(:to_hash) { { fault: { faultstring: 'asdasd fileId xsxx does not exist' } } } 30 | allow(exc).to receive(:to_s) { '' } 31 | raise exc 32 | end 33 | expect { subject.execute true }.to raise_error AkamaiApi::ECCU::NotFound 34 | end 35 | 36 | it "raises unauthorized if request raises a Savon::HTTPError with code 401" do 37 | expect(fake_client).to receive :call do 38 | raise Savon::HTTPError, double(code: 401) 39 | end 40 | expect { subject.execute true }.to raise_error AkamaiApi::Unauthorized 41 | end 42 | 43 | it "raises Savon:HTTPError if request raises this exception and its code differs from 401" do 44 | expect(fake_client).to receive :call do 45 | raise Savon::HTTPError, double(code: 402) 46 | end 47 | expect { subject.execute true }.to raise_error Savon::HTTPError 48 | end 49 | end 50 | 51 | describe "#request_body" do 52 | def subject_request_body value 53 | subject.send :request_body, value 54 | end 55 | 56 | it "returns a SoapBody object" do 57 | expect(subject_request_body false).to be_a AkamaiApi::ECCU::SoapBody 58 | end 59 | 60 | it "sets an integer value named 'fileId' with the given code" do 61 | expect_any_instance_of(AkamaiApi::ECCU::SoapBody).to receive(:integer).with :fileId, 1234 62 | subject_request_body false 63 | end 64 | 65 | it "sets a boolean value named 'retrieveContents' with the given value" do 66 | expect_any_instance_of(AkamaiApi::ECCU::SoapBody).to receive(:boolean).with :retrieveContents, false 67 | subject_request_body '1' 68 | end 69 | 70 | it "sets only fileId" do 71 | expect(subject_request_body(false).to_s).to eq "1234false" 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /lib/akamai_api/eccu_parser.rb: -------------------------------------------------------------------------------- 1 | require 'akamai_api/eccu/tokenizer' 2 | 3 | module AkamaiApi 4 | # The {ECCUParser} class is used to create a XML request file starting from a url 5 | # 6 | # @example 7 | # AkamaiApi::ECCUParser.new(foo/bar/*.png).xml 8 | class ECCUParser 9 | 10 | PLACEHOLDER = "{YIELD}" 11 | NOT_ALLOWED_EXTENSIONS = %w[*] 12 | NOT_ALLOWED_DIRS = %w[. ..] 13 | 14 | attr_reader :tokenizer, :xml, :revalidate_on 15 | 16 | def initialize expression, revalidate_on = 'now' 17 | raise "Expression can't be empty" if expression.empty? 18 | revalidate_on = revalidate_on.to_i if revalidate_on != 'now' 19 | @tokenizer = ECCU::Tokenizer.new expression 20 | @revalidate_on = revalidate_on 21 | @xml = "\n#{PLACEHOLDER}" 22 | parse 23 | end 24 | 25 | private 26 | 27 | def parse 28 | while tokenizer.look_next_token 29 | tokenizer.next_token 30 | send "add_#{tokenizer.current_token.type.to_s}_tag", tokenizer.current_token.value 31 | end 32 | 33 | add_revalidate 34 | end 35 | 36 | def next_wildcard_extension? 37 | tokenizer.look_next_token.type == :wildcard and 38 | ! tokenizer.look_next_token(2).nil? and 39 | tokenizer.look_next_token(2).type == :extension 40 | end 41 | 42 | def next_filename? 43 | tokenizer.look_next_token.type == :filename 44 | end 45 | 46 | def add_revalidate 47 | xml.gsub! PLACEHOLDER, "#{revalidate_on}" 48 | end 49 | 50 | def add_dir_tag dir_name 51 | raise "Dir '#{dir_name}' not allowed" if NOT_ALLOWED_DIRS.include? dir_name 52 | 53 | xml.gsub! PLACEHOLDER, "#{PLACEHOLDER}" 54 | end 55 | 56 | def add_this_dir_tag 57 | xml.gsub! PLACEHOLDER, "#{PLACEHOLDER}" 58 | end 59 | 60 | 61 | def add_extension_tag extension 62 | raise "Extension '#{extension}' not allowed" if NOT_ALLOWED_EXTENSIONS.include? extension 63 | raise "Extension will be the last element" if tokenizer.look_next_token != nil 64 | 65 | xml.gsub! PLACEHOLDER, "#{PLACEHOLDER}" 66 | end 67 | 68 | def add_filename_tag filename 69 | xml.gsub! PLACEHOLDER, "#{PLACEHOLDER}" 70 | end 71 | 72 | def add_separator_tag separator 73 | if tokenizer.look_prev_token.type == :dir 74 | if tokenizer.look_next_token == nil 75 | add_this_dir_tag 76 | elsif next_wildcard_extension? or next_filename? 77 | add_this_dir_tag 78 | end 79 | end 80 | end 81 | 82 | def add_double_wildcard_tag token 83 | # Double wildcard do nothing 84 | end 85 | 86 | def add_wildcard_tag wildcard 87 | if tokenizer.look_next_token.nil? or 88 | tokenizer.look_next_token.type == :separator 89 | xml.gsub! PLACEHOLDER, "#{PLACEHOLDER}" 90 | end 91 | end 92 | 93 | end 94 | end 95 | -------------------------------------------------------------------------------- /spec/lib/akamai_api/eccu/tokenizer_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module AkamaiApi::ECCU 4 | describe Tokenizer do 5 | 6 | describe '.tokenize' do 7 | 8 | context 'with empty expression' do 9 | let(:tokenizer) { Tokenizer.new "" } 10 | it 'return 0 tokens' do 11 | expect( tokenizer.tokens.size ).to equal 0 12 | end 13 | 14 | it '.current_token return nil' do 15 | expect( tokenizer.current_token ).to be_nil 16 | end 17 | it '.look_next_token return nil' do 18 | expect( tokenizer.look_next_token ).to be_nil 19 | end 20 | it '.next_token return nil' do 21 | expect( tokenizer.next_token ).to be_nil 22 | end 23 | end 24 | 25 | context 'with correct expression' do 26 | let(:tokenizer) { Tokenizer.new "foo/bar/**/*.png" } 27 | it 'return 8 tokens' do 28 | expect(tokenizer.tokens.size).to equal 8 29 | end 30 | 31 | it 'and all tokens have the correct type' do 32 | expect( tokenizer.tokens[0].type ).to equal :dir 33 | expect( tokenizer.tokens[1].type ).to equal :separator 34 | expect( tokenizer.tokens[2].type ).to equal :dir 35 | expect( tokenizer.tokens[3].type ).to equal :separator 36 | expect( tokenizer.tokens[4].type ).to equal :double_wildcard 37 | expect( tokenizer.tokens[5].type ).to equal :separator 38 | expect( tokenizer.tokens[6].type ).to equal :wildcard 39 | expect( tokenizer.tokens[7].type ).to equal :extension 40 | end 41 | 42 | it '.current_token return nil initially' do 43 | expect( tokenizer.current_token ).to be_nil 44 | end 45 | it '.current_token return a Token object after call .next_token' do 46 | tokenizer.next_token 47 | expect( tokenizer.current_token.class.name ).to eq "AkamaiApi::ECCU::Token" 48 | end 49 | it '.next_token return a Token object' do 50 | expect( tokenizer.next_token.class.name ).to eq "AkamaiApi::ECCU::Token" 51 | end 52 | it '.look_next_token return a Token object' do 53 | expect( tokenizer.look_next_token.class.name ).to eq "AkamaiApi::ECCU::Token" 54 | end 55 | it '.look_next_token after all token cycles return nil' do 56 | tokenizer.tokens.size.times do 57 | tokenizer.next_token 58 | end 59 | expect( tokenizer.look_next_token ).to be_nil 60 | end 61 | 62 | context 'expression not tokenizable' do 63 | it { expect{ Tokenizer.new('foo/***') }.to raise_error } 64 | end 65 | end 66 | 67 | context 'last token is a :filename' do 68 | let(:tokenizer) { Tokenizer.new "foo/bar/**/test.png" } 69 | it { expect( tokenizer.tokens.last.type ).to equal :filename } 70 | end 71 | 72 | context 'single word is a :filename' do 73 | let(:tokenizer) { Tokenizer.new "foo" } 74 | it { expect( tokenizer.tokens.first.type ).to equal :filename } 75 | end 76 | 77 | context 'single word with end / is a :dir' do 78 | let(:tokenizer) { Tokenizer.new "foo/" } 79 | it { expect( tokenizer.tokens.first.type ).to equal :dir } 80 | end 81 | 82 | end 83 | 84 | end 85 | end 86 | -------------------------------------------------------------------------------- /cassettes/akamai_api_eccu_publish/invalid_domain.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://control.akamai.com/webservices/services/PublishECCU 6 | body: 7 | encoding: UTF-8 8 | string: |- 9 | ./publish.xmlPD94bWwgdmVyc2lvbj0iMS4wIj8+CjxlY2N1PgogIDxtYXRjaDpyZWN1cnNp 10 | dmUtZGlycyB2YWx1ZT0iZm9vIiA+CiAgICA8bWF0Y2g6cmVjdXJzaXZlLWRp 11 | cnMgdmFsdWU9ImJhciIgPgogICAgICA8bWF0Y2g6cmVjdXJzaXZlLWRpcnMg 12 | dmFsdWU9ImJhei5qcGciID4KICAgICAgICA8cmV2YWxpZGF0ZT5ub3c8L3Jl 13 | dmFsaWRhdGU+CiAgICAgIDwvbWF0Y2g6cmVjdXJzaXZlLWRpcnM+CiAgICA8 14 | L21hdGNoOnJlY3Vyc2l2ZS1kaXJzPgogIDwvbWF0Y2g6cmVjdXJzaXZlLWRp 15 | cnM+CjwvZWNjdT4= 16 | ECCU Request using AkamaiApi VERSIONfoobarbaz.comhostheadertrue 17 | headers: 18 | Soapaction: 19 | - '"upload"' 20 | Content-Type: 21 | - text/xml;charset=UTF-8 22 | Content-Length: 23 | - '1270' 24 | Accept-Encoding: 25 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 26 | Accept: 27 | - '*/*' 28 | User-Agent: 29 | - Ruby 30 | Authorization: 31 | - Basic VVNFUk5BTUU6UEFTU1dPUkQ= 32 | response: 33 | status: 34 | code: 500 35 | message: Internal Server Error 36 | headers: 37 | Server: 38 | - Apache 39 | Content-Type: 40 | - text/xml;charset=utf-8 41 | Expires: 42 | - Mon, 26 May 2014 08:05:51 GMT 43 | Cache-Control: 44 | - max-age=0, no-cache, no-store 45 | Pragma: 46 | - no-cache 47 | Date: 48 | - Mon, 26 May 2014 08:05:51 GMT 49 | Connection: 50 | - close 51 | X-Frame-Options: 52 | - SAMEORIGIN 53 | body: 54 | encoding: UTF-8 55 | string: 'soapenv:Server.generalExceptionECCU 57 | validation failed: You are not authorized to specify this digital propertycom.akamai.aws.util.AWSFaultp1-tomapp08.extranet.akamai.com' 60 | http_version: 61 | recorded_at: Mon, 26 May 2014 08:05:51 GMT 62 | recorded_with: VCR 2.9.0 63 | -------------------------------------------------------------------------------- /spec/lib/akamai_api/ccu/purge_status/request_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AkamaiApi::CCU::PurgeStatus::Request do 4 | it "includes httparty" do 5 | expect(subject.class.included_modules).to include HTTParty 6 | end 7 | 8 | it "sets a base_uri" do 9 | expect(subject.class.base_uri).to eq 'https://api.ccu.akamai.com' 10 | end 11 | 12 | describe "#execute" do 13 | let(:fake_response) { double code: 200, parsed_response: { 'httpStatus' => 200, 'submissionTime' => 1 } } 14 | 15 | it "executes a GET request on the given progress_uri" do 16 | expect(AkamaiApi::CCU::PurgeStatus::Request).to receive :get do |uri, args| 17 | expect(uri).to eq '/ccu/v2/purges/foo' 18 | fake_response 19 | end 20 | subject.execute '/ccu/v2/purges/foo' 21 | end 22 | 23 | it "sets the auth in the request" do 24 | allow(AkamaiApi).to receive(:auth) { 'foo' } 25 | expect(AkamaiApi::CCU::PurgeStatus::Request).to receive :get do |uri, args| 26 | expect(args).to eq basic_auth: 'foo' 27 | fake_response 28 | end 29 | subject.execute '/ccu/v2/purges/foo' 30 | end 31 | 32 | it "raises an exception when the response code is 401" do 33 | allow(fake_response).to receive(:code) { 401 } 34 | expect(AkamaiApi::CCU::PurgeStatus::Request).to receive(:get).and_return fake_response 35 | expect { subject.execute '/ccu/v2/purges/foo' }.to raise_error AkamaiApi::Unauthorized 36 | end 37 | 38 | it "returns a response built with the received json" do 39 | allow(fake_response).to receive(:parsed_response) { { 'httpStatus' => 201, 'submissionTime' => 1 } } 40 | expect(AkamaiApi::CCU::PurgeStatus::Request).to receive(:get).and_return fake_response 41 | expect(subject.execute '/ccu/v2/purges/foo' ).to be_a AkamaiApi::CCU::PurgeStatus::Response 42 | end 43 | 44 | it "raises an error if json code in response is not valid" do 45 | allow(fake_response).to receive(:parsed_response) { { 'httpStatus' => 400, 'submissionTime' => 1 } } 46 | expect(AkamaiApi::CCU::PurgeStatus::Request).to receive(:get).and_return fake_response 47 | expect { subject.execute '/ccu/v2/purges/foo' }.to raise_error AkamaiApi::CCU::Error 48 | end 49 | 50 | it "raises an error when json code in response has no submissionTime" do 51 | fake_response = double code: 201, parsed_response: { 'httpStatus' => 201 } 52 | expect(AkamaiApi::CCU::PurgeStatus::Request).to receive(:get).and_return fake_response 53 | expect { subject.execute '/ccu/v2/purges/foo' }.to raise_error AkamaiApi::CCU::PurgeStatus::NotFound 54 | end 55 | 56 | context "when the given progressUri is the purgeId" do 57 | it "the progressUri prefix is appended" do 58 | expect(AkamaiApi::CCU::PurgeStatus::Request).to receive :get do |uri, args| 59 | expect(uri).to eq '/ccu/v2/purges/foo' 60 | fake_response 61 | end 62 | subject.execute 'foo' 63 | end 64 | end 65 | 66 | context "when the given progressUri isn't prefixed by a slash" do 67 | it "a slash is prefixed" do 68 | expect(AkamaiApi::CCU::PurgeStatus::Request).to receive :get do |uri, args| 69 | expect(uri).to eq '/ccu/v2/purges/foo' 70 | fake_response 71 | end 72 | subject.execute 'ccu/v2/purges/foo' 73 | end 74 | end 75 | end 76 | end 77 | -------------------------------------------------------------------------------- /cassettes/akamai_api_eccu_publish/invalid_credentials.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://control.akamai.com/webservices/services/PublishECCU 6 | body: 7 | encoding: UTF-8 8 | string: |- 9 | ./publish.xmlPD94bWwgdmVyc2lvbj0iMS4wIj8+CjxlY2N1PgogIDxtYXRjaDpyZWN1cnNp 10 | dmUtZGlycyB2YWx1ZT0iZm9vIiA+CiAgICA8bWF0Y2g6cmVjdXJzaXZlLWRp 11 | cnMgdmFsdWU9ImJhciIgPgogICAgICA8bWF0Y2g6cmVjdXJzaXZlLWRpcnMg 12 | dmFsdWU9ImJhei5qcGciID4KICAgICAgICA8cmV2YWxpZGF0ZT5ub3c8L3Jl 13 | dmFsaWRhdGU+CiAgICAgIDwvbWF0Y2g6cmVjdXJzaXZlLWRpcnM+CiAgICA8 14 | L21hdGNoOnJlY3Vyc2l2ZS1kaXJzPgogIDwvbWF0Y2g6cmVjdXJzaXZlLWRp 15 | cnM+CjwvZWNjdT4= 16 | ECCU Request using AkamaiApi VERSIONfoo.comhostheadertrue 17 | headers: 18 | Soapaction: 19 | - '"upload"' 20 | Content-Type: 21 | - text/xml;charset=UTF-8 22 | Content-Length: 23 | - '1264' 24 | Accept-Encoding: 25 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 26 | Accept: 27 | - "*/*" 28 | User-Agent: 29 | - Ruby 30 | Authorization: 31 | - Basic Zm9vOmJhcg== 32 | response: 33 | status: 34 | code: 401 35 | message: Unauthorized 36 | headers: 37 | Www-Authenticate: 38 | - Basic realm="Luna Control Center Web Services (use your Luna username and 39 | password)" 40 | Content-Length: 41 | - '401' 42 | Content-Type: 43 | - text/html; charset=iso-8859-1 44 | Expires: 45 | - Thu, 02 Mar 2017 05:41:27 GMT 46 | Cache-Control: 47 | - max-age=0, no-cache, no-store 48 | Pragma: 49 | - no-cache 50 | Date: 51 | - Thu, 02 Mar 2017 05:41:27 GMT 52 | Connection: 53 | - close 54 | Strict-Transport-Security: 55 | - max-age=15552000 56 | X-Frame-Options: 57 | - SAMEORIGIN 58 | body: 59 | encoding: UTF-8 60 | string: | 61 | 62 | 63 | 401 Authorization Required 64 | 65 |

Authorization Required

66 |

This server could not verify that you 67 | are authorized to access the document 68 | requested. Either you supplied the wrong 69 | credentials (e.g., bad password), or your 70 | browser doesn't understand how to supply 71 | the credentials required.

72 | 73 | http_version: 74 | recorded_at: Thu, 02 Mar 2017 05:41:27 GMT 75 | recorded_with: VCR 3.0.3 76 | -------------------------------------------------------------------------------- /spec/features/ccu/purge_request_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'Given I request to purge an asset' do 4 | subject { AkamaiApi::CCU } 5 | 6 | let(:estimated_time) { 420 } 7 | 8 | shared_examples 'purge helper' do 9 | let(:method) { "#{action}_#{type}" } 10 | 11 | it 'responds with a PurgeResponse object' do 12 | VCR.use_cassette "akamai_api_ccu_#{type}_#{action}/single_item" do 13 | expect(subject.send method, items).to be_a AkamaiApi::CCU::Purge::Response 14 | end 15 | end 16 | 17 | it 'raises error when user is not authorized' do 18 | VCR.use_cassette "akamai_api_ccu_#{type}_#{action}/invalid_credentials" do 19 | expect { subject.send(method, items) }.to raise_error AkamaiApi::Unauthorized 20 | end 21 | end 22 | 23 | it 'raises an error when data request is invalid' do 24 | VCR.use_cassette "akamai_api_ccu_#{type}_#{action}/invalid_item" do 25 | expect { subject.send method, items }.to raise_error AkamaiApi::CCU::Error 26 | end 27 | end 28 | 29 | describe 'when data are correct' do 30 | it 'returns the expected response code' do 31 | VCR.use_cassette "akamai_api_ccu_#{type}_#{action}/single_item" do 32 | expect(subject.send(method, items).code).to eq 201 33 | end 34 | end 35 | 36 | it 'returns a successful message' do 37 | VCR.use_cassette "akamai_api_ccu_#{type}_#{action}/single_item" do 38 | expect(subject.send(method, items).message).to eq 'Request accepted.' 39 | end 40 | end 41 | 42 | it 'returns a unique purge id' do 43 | VCR.use_cassette "akamai_api_ccu_#{type}_#{action}/single_item" do 44 | expect(subject.send(method, items).purge_id).to eq '12345678-1234-1234-1234-123456789012' 45 | end 46 | end 47 | 48 | it 'returns a unique support id' do 49 | VCR.use_cassette "akamai_api_ccu_#{type}_#{action}/single_item" do 50 | expect(subject.send(method, items).support_id).to eq '12345678901234567890-123456789' 51 | end 52 | end 53 | 54 | it 'returns the estimated time in seconds' do 55 | VCR.use_cassette "akamai_api_ccu_#{type}_#{action}/single_item" do 56 | expect(subject.send(method, items).estimated_time).to eq estimated_time 57 | end 58 | end 59 | end 60 | end 61 | 62 | context 'when this asset is an ARL and I want to invalidate it' do 63 | let(:action) { 'invalidate' } 64 | let(:type) { 'arl' } 65 | let(:items) { ['http://www.foo.bar/t.txt'] } 66 | 67 | let(:estimated_time) { 5 } 68 | 69 | it_should_behave_like 'purge helper' 70 | end 71 | 72 | context 'when this asset is a CPCode and I want to invalidate it' do 73 | let(:action) { 'invalidate' } 74 | let(:type) { 'cpcode' } 75 | let(:items) { ['12345'] } 76 | 77 | it_should_behave_like 'purge helper' 78 | end 79 | 80 | context 'when this asset is an ARL and I want to remove it' do 81 | let(:action) { 'remove' } 82 | let(:type) { 'arl' } 83 | let(:items) { ['http://www.foo.bar/t.txt'] } 84 | 85 | it_should_behave_like 'purge helper' 86 | end 87 | 88 | context 'when this asset is a CPCode and I want to remove it' do 89 | let(:action) { 'remove' } 90 | let(:type) { 'cpcode' } 91 | let(:items) { ['12345'] } 92 | 93 | it_should_behave_like 'purge helper' 94 | end 95 | end 96 | -------------------------------------------------------------------------------- /lib/akamai_api/eccu/publish_request.rb: -------------------------------------------------------------------------------- 1 | require 'akamai_api/eccu/invalid_domain' 2 | require 'akamai_api/eccu/soap_body' 3 | require "akamai_api/eccu/base_request" 4 | 5 | module AkamaiApi::ECCU 6 | # {PublishRequest} is responsible of publishing a new ECCU request. 7 | # 8 | # @example 9 | # content = File.read './publish.xml' 10 | # begin 11 | # req = AkamaiApi::ECCU::PublishRequest.new 'http://foo.bar/t.txt' 12 | # code = req.execute content, file_name: 'publish.xml', emails: 'author@mikamai.com' 13 | # puts "Request enqueued with code #{code}" 14 | # rescue AkamaiApi::Unauthorized 15 | # puts "Invalid login credentials" 16 | # end 17 | class PublishRequest < BaseRequest 18 | # @return [String] Digital property name 19 | attr_reader :property_name 20 | # @return [String] Digital property type 21 | attr_reader :property_type 22 | # @return [true,false] Digital property match type (true if exact) 23 | attr_reader :property_exact_match 24 | 25 | # @param [String] property_name Digital property name 26 | # @param [Hash] args Additional arguments 27 | # @option args [String] :type ('hostheader') Digital property type 28 | # @option args [true,false] :exact_match (true) Digital property match type 29 | def initialize property_name, args = {} 30 | @property_name = property_name 31 | @property_type = args.fetch(:type, 'hostheader') 32 | @property_exact_match = args.fetch(:exact_match, true) == true 33 | end 34 | 35 | # Publishes a new ECCU request 36 | # @param [String] content content of the ECCU request 37 | # @param [Hash] args Additional arguments 38 | # @option args [String] :file_name ('') file name to set in the request 39 | # @option args [String] :notes ('ECCU Request using AkamaiApi ') notes of the ECCU request 40 | # @option args [String] :version ('') request version number 41 | # @option args [String,Array] :emails emails to notify when the request has been completed 42 | def execute content, args = {} 43 | with_soap_error_handling do 44 | response = client_call :upload, message_tag: 'upload', message: request_body(content, args).to_s 45 | response[:file_id].to_i 46 | end 47 | end 48 | 49 | protected 50 | 51 | # Creates the request body filling it with all necessary arguments 52 | # @return [SoapBody] 53 | def request_body content, args 54 | SoapBody.new.tap do |body| 55 | body.string :filename, args.fetch(:file_name, '') 56 | body.text :contents, content 57 | body.string :notes, args.fetch(:notes, "ECCU Request using AkamaiApi #{AkamaiApi::VERSION}") 58 | body.string :versionString, args.fetch(:version, '') 59 | if args[:emails] 60 | body.string :statusChangeEmail, Array.wrap(args[:emails]).join(',') 61 | end 62 | body.string :propertyName, property_name 63 | body.string :propertyType, property_type 64 | body.boolean :propertyNameExactMatch, property_exact_match 65 | end 66 | end 67 | 68 | def with_soap_error_handling &block 69 | super 70 | rescue Savon::SOAPFault => e 71 | e = AkamaiApi::ECCU::InvalidDomain if e.to_hash[:fault][:faultstring].include? 'You are not authorized to specify this digital property' 72 | raise e 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /wsdls/ccuapi.wsdl: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 52 | 53 | 54 | 55 | 56 | 57 | 59 | 60 | 61 | 62 | 66 | 67 | 68 | 72 | 73 | 74 | 75 | 76 | Provides programmatic purge access 77 | 78 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /lib/akamai_api/eccu/tokenizer.rb: -------------------------------------------------------------------------------- 1 | require 'akamai_api/eccu/token' 2 | 3 | module AkamaiApi::ECCU 4 | # Class used to tokenize path used for invalidate cache 5 | # 6 | # foo/bar/*.txt 7 | class Tokenizer 8 | 9 | SEPARATORS = ['/'] 10 | DIR_REGEXP = /^[^\/]+$/ 11 | WILDCARD_REGEXP = /^\**$/ 12 | 13 | attr_reader :tokens, :cursor 14 | 15 | def initialize expression 16 | @cursor = -1 17 | tokenize expression 18 | end 19 | 20 | def current_token 21 | return nil if cursor == -1 22 | tokens[cursor] 23 | end 24 | 25 | def next_token 26 | @cursor += 1 27 | current_token 28 | end 29 | 30 | def look_next_token i = 1 31 | tokens[cursor + i] 32 | end 33 | 34 | def look_prev_token i = 1 35 | tokens[cursor - 1] 36 | end 37 | 38 | def look_next_token_except exclude_type = nil 39 | look_next_token if exclude_type == nil 40 | 41 | i = 1 42 | while tokens[cursor + i].type == exclude_type 43 | i += 1 44 | end 45 | tokens[cursor + i] 46 | end 47 | 48 | def look_next_token_of_type token_type = nil 49 | look_next_token if token_type == nil 50 | 51 | i = cursor 52 | while tokens.size < i 53 | return tokens[i] if tokens[i].type == token_type 54 | i += 1 55 | end 56 | nil 57 | end 58 | 59 | private 60 | 61 | def tokenize expression 62 | @tokens = [] 63 | expression_to_parse = expression.strip 64 | while expression_to_parse.size > 0 65 | tokens << read_next_token(expression_to_parse) 66 | end 67 | end 68 | 69 | def read_next_token expression_to_parse 70 | expression_to_parse.strip! 71 | next_char = expression_to_parse.slice 0 72 | if SEPARATORS.include? next_char 73 | read_next_separator_token expression_to_parse 74 | elsif next_char =~ WILDCARD_REGEXP 75 | read_next_wildcard_token expression_to_parse 76 | elsif next_char =~ DIR_REGEXP 77 | read_next_dir_token expression_to_parse 78 | else 79 | raise "Unknown token starting with '#{next_char}'" 80 | end 81 | end 82 | 83 | def read_next_separator_token expression_to_parse 84 | Token.new :separator, expression_to_parse.slice!(0) 85 | end 86 | 87 | def read_next_wildcard_token expression_to_parse 88 | wildcard_value, next_char = loop_until_regexp expression_to_parse, WILDCARD_REGEXP 89 | 90 | if wildcard_value.size == 1 91 | Token.new :wildcard, wildcard_value 92 | elsif wildcard_value.size == 2 93 | Token.new :double_wildcard, wildcard_value 94 | else 95 | raise "Unknown wildcard '#{wildcard_value}'" 96 | end 97 | end 98 | 99 | def read_next_dir_token expression_to_parse 100 | dir_value, next_char = loop_until_regexp expression_to_parse, DIR_REGEXP 101 | 102 | if tokens.size > 0 && tokens.last.type == :wildcard 103 | Token.new :extension, dir_value.gsub('.','') 104 | elsif SEPARATORS.include? next_char 105 | Token.new :dir, dir_value 106 | else 107 | Token.new :filename, dir_value 108 | end 109 | end 110 | 111 | def loop_until_regexp expression_to_parse, regexp 112 | looped_value = '' 113 | next_char = '' 114 | begin 115 | looped_value << expression_to_parse.slice!(0) 116 | next_char = expression_to_parse.slice 0 117 | end while next_char && "#{looped_value}#{next_char}" =~ regexp 118 | 119 | return looped_value, next_char 120 | end 121 | 122 | end 123 | 124 | end 125 | -------------------------------------------------------------------------------- /cassettes/akamai_api_eccu_find/successful_without_content.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://control.akamai.com/webservices/services/PublishECCU 6 | body: 7 | encoding: UTF-8 8 | string: 1234false 13 | headers: 14 | Soapaction: 15 | - '"getInfo"' 16 | Content-Type: 17 | - text/xml;charset=UTF-8 18 | Content-Length: 19 | - '564' 20 | Accept-Encoding: 21 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 22 | Accept: 23 | - "*/*" 24 | User-Agent: 25 | - Ruby 26 | Authorization: 27 | - Basic VVNFUk5BTUU6UEFTU1dPUkQ= 28 | response: 29 | status: 30 | code: 200 31 | message: OK 32 | headers: 33 | Server: 34 | - Apache 35 | Content-Type: 36 | - text/xml;charset=utf-8 37 | Content-Length: 38 | - '1684' 39 | Expires: 40 | - Fri, 23 May 2014 09:10:03 GMT 41 | Cache-Control: 42 | - max-age=0, no-cache, no-store 43 | Pragma: 44 | - no-cache 45 | Date: 46 | - Fri, 23 May 2014 09:10:03 GMT 47 | Connection: 48 | - keep-alive 49 | X-Frame-Options: 50 | - SAMEORIGIN 51 | body: 52 | encoding: UTF-8 53 | string: File 58 | successfully deployed to Akamai network (Succeeded)12341278e456fe0bdeba72532f852e4daec184bECCU Request using EdgeControlfoo.bartruehostheaderguest@mikamai.com4000File 66 | successfully deployed to Akamai's network2014-05-21T09:07:11.279Z2014-05-21T08:41:55.279Ztest1 70 | http_version: 71 | recorded_at: Fri, 23 May 2014 09:10:03 GMT 72 | recorded_with: VCR 2.9.0 73 | -------------------------------------------------------------------------------- /spec/lib/akamai_api/eccu/update_attribute_request_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AkamaiApi::ECCU::UpdateAttributeRequest do 4 | subject { AkamaiApi::ECCU::UpdateAttributeRequest.new '1234', :status_change_email } 5 | 6 | describe '#attribute_for_soap' do 7 | it 'returns a camelized symbol with first letter in downcase' do 8 | expect(subject.send :attribute_for_soap).to eq :statusChangeEmail 9 | end 10 | end 11 | 12 | describe "#execute" do 13 | let(:fake_client) { double call: nil } 14 | 15 | before do 16 | allow(AkamaiApi::ECCU).to receive(:client) { fake_client } 17 | end 18 | 19 | it "calls the appropriate soap method via savon with a message" do 20 | fake_response = double body: { set_status_change_email_response: { success: true } } 21 | expect(subject).to receive(:request_body).with('foo').and_return double(to_s: 'asd') 22 | expect(fake_client).to receive(:call).with(:set_status_change_email, message: 'asd').and_return fake_response 23 | subject.execute 'foo' 24 | end 25 | 26 | it "returns 'true' if response hash reports to be successful" do 27 | allow(subject).to receive(:request_body) { 'example' } 28 | allow(fake_client).to receive(:call) { double(body: { set_status_change_email_response: { success: true } }) } 29 | expect(subject.execute 'foo').to be_truthy 30 | end 31 | 32 | it "returns 'false' if response hash reports to be unsuccessful" do 33 | allow(subject).to receive(:request_body) { 'example' } 34 | allow(fake_client).to receive(:call) { double(body: { set_status_change_email_response: { success: false } }) } 35 | expect(subject.execute 'foo').to be_falsy 36 | end 37 | 38 | it "raises NotFound if request raises a Savon::SOAPFault with particular message" do 39 | expect(fake_client).to receive :call do 40 | exc = Savon::SOAPFault.new({}, {}) 41 | allow(exc).to receive(:to_hash) { { fault: { faultstring: 'asdasd fileId xsxx does not exist' } } } 42 | allow(exc).to receive(:to_s) { '' } 43 | raise exc 44 | end 45 | expect { subject.execute 'foo' }.to raise_error AkamaiApi::ECCU::NotFound 46 | end 47 | 48 | it "raises unauthorized if request raises a Savon::HTTPError with code 401" do 49 | expect(fake_client).to receive :call do 50 | raise Savon::HTTPError, double(code: 401) 51 | end 52 | expect { subject.execute 'foo' }.to raise_error AkamaiApi::Unauthorized 53 | end 54 | 55 | it "raises Savon:HTTPError if request raises this exception and its code differs from 401" do 56 | expect(fake_client).to receive :call do 57 | raise Savon::HTTPError, double(code: 402) 58 | end 59 | expect { subject.execute 'foo' }.to raise_error Savon::HTTPError 60 | end 61 | end 62 | 63 | describe "#request_body" do 64 | def subject_request_body *args 65 | subject.send :request_body, *args 66 | end 67 | 68 | it "returns a SoapBody object" do 69 | expect(subject_request_body 'foo').to be_a AkamaiApi::ECCU::SoapBody 70 | end 71 | 72 | it "sets an integer value named 'fileId' with the given code" do 73 | expect_any_instance_of(AkamaiApi::ECCU::SoapBody).to receive(:integer).with :fileId, 1234 74 | subject_request_body 'foo' 75 | end 76 | 77 | it "sets a string value named 'statusChangeEmails' with the given email" do 78 | expect_any_instance_of(AkamaiApi::ECCU::SoapBody).to receive(:string).with :statusChangeEmail, 'foo' 79 | subject_request_body 'foo' 80 | end 81 | 82 | it "sets only fileId and email" do 83 | expect(subject_request_body('foo').to_s).to eq "1234foo" 84 | end 85 | end 86 | end 87 | -------------------------------------------------------------------------------- /cassettes/akamai_api_eccu_all_ids/successful.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://control.akamai.com/webservices/services/PublishECCU 6 | body: 7 | encoding: UTF-8 8 | string: 12 | headers: 13 | Soapaction: 14 | - '"getIds"' 15 | Content-Type: 16 | - text/xml;charset=UTF-8 17 | Content-Length: 18 | - '457' 19 | Accept-Encoding: 20 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 21 | Accept: 22 | - '*/*' 23 | User-Agent: 24 | - Ruby 25 | Authorization: 26 | - Basic VVNFUk5BTUU6UEFTU1dPUkQ= 27 | response: 28 | status: 29 | code: 200 30 | message: OK 31 | headers: 32 | Server: 33 | - Apache 34 | Content-Type: 35 | - text/xml;charset=utf-8 36 | Content-Length: 37 | - '2023' 38 | Expires: 39 | - Mon, 26 May 2014 10:48:27 GMT 40 | Cache-Control: 41 | - max-age=0, no-cache, no-store 42 | Pragma: 43 | - no-cache 44 | Date: 45 | - Mon, 26 May 2014 10:48:27 GMT 46 | Connection: 47 | - keep-alive 48 | X-Frame-Options: 49 | - SAMEORIGIN 50 | body: 51 | encoding: UTF-8 52 | string: 12341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371 72 | http_version: 73 | recorded_at: Mon, 26 May 2014 10:48:28 GMT 74 | recorded_with: VCR 2.9.0 75 | --------------------------------------------------------------------------------