cloudflare 3.2.1 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8e27cb2bec2e08d2652f1095ea2a59b81ab2e1bdf7859ceec4e7cd6b8f8789e1
4
- data.tar.gz: bfeada1f9e3c1d828b99e5e6767b441453d9455d5a8a044ef67105576397418f
3
+ metadata.gz: 0bdda4cf1d75b71db4667d63da7382958e2cbebedb052e51adce192bf5db2a81
4
+ data.tar.gz: ea73942a2251da8f3de0e9a4b46af6a0f877cb1d52b39567ea5aee0c5514aff3
5
5
  SHA512:
6
- metadata.gz: d225c93aeead46e57d21a62d06854907ded827fb255e7c6773df1462d85268df67421796eac4883a9184fa9e7f2de8876bf311a00e2931742ef53cb6c78db299
7
- data.tar.gz: d2a2d558755b653ff5679507fc06e2c049e64fbdc7849f1c398199239408292002b722813431c1697a4d6bd577740ad293957eb362cc470fe48c9205e2b79ce0
6
+ metadata.gz: cbe1fe27c1dcbdf5bcf1480c21058e8b2f82d3c43829c606355e864e56390b9f0e128e80af3d6274ce09c45a40548e0a5ce29d1dd70d9ca9bfa707a86982a477
7
+ data.tar.gz: d1c18b4b98110472759b0e3400f3e22717d91cb1022292a997b21920eca74ceabefa78b830c22231f9338efda14d99ff99e0310b1f33ffbd2f637b0a092b5d21
data/.travis.yml CHANGED
@@ -1,24 +1,22 @@
1
1
  language: ruby
2
- sudo: false
3
- dist: trusty
2
+ dist: xenial
4
3
  cache: bundler
5
4
 
6
- before_script:
7
- - gem update --system
8
- - gem install bundler
9
-
10
- rvm:
11
- - 2.2
12
- - 2.3
13
- - 2.4
14
- - 2.5
15
- - 2.6
16
- - jruby-head
17
- - ruby-head
18
5
  matrix:
6
+ include:
7
+ - rvm: 2.3
8
+ - rvm: 2.4
9
+ - rvm: 2.5
10
+ - rvm: 2.6
11
+ - rvm: jruby-head
12
+ env: JRUBY_OPTS="--debug -X+O"
13
+ - rvm: truffleruby
14
+ - rvm: ruby-head
19
15
  allow_failures:
20
- - rvm: ruby-head
21
- - rvm: jruby-head
16
+ - rvm: ruby-head
17
+ - rvm: jruby-head
18
+ - rvm: truffleruby
19
+
22
20
  env:
23
21
  global:
24
22
  secure: c5yG7N1r9nYuw47Y90jGeoHNvkL59AAC55dtPAhKP+gjXWW8hKbntj3oj+lVkxEqzRpzEQgYZzUElrP+6mJnb20ldclZg03L56243tMtVEcpGOx/MFhnIBkx3kKu1H6ydKKMxieHxjsLQ3vnpcIZ3p0skTQjYbjdu607tjbyg7s=
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  It is a Ruby wrapper for the Cloudflare V4 API. It provides a light weight wrapper using `RestClient::Resource`. The wrapper functionality is limited to zones and DNS records at this time, *PRs welcome*.
4
4
 
5
- [![Build Status](https://secure.travis-ci.org/ioquatix/cloudflare.svg)](http://travis-ci.org/ioquatix/cloudflare)
5
+ [![Build Status](https://secure.travis-ci.org/socketry/cloudflare.svg)](http://travis-ci.org/socketry/cloudflare)
6
6
 
7
7
  ## Installation
8
8
 
@@ -42,7 +42,7 @@ connection = Cloudflare.connect(key: key, email: email)
42
42
  Get all available zones:
43
43
 
44
44
  ```ruby
45
- zones = connection.zones.all
45
+ zones = connection.zones
46
46
  ```
47
47
 
48
48
  Get a specific zone:
@@ -55,7 +55,7 @@ zone = connection.zones.find_by_name("example.com")
55
55
  Get DNS records for a given zone:
56
56
 
57
57
  ```ruby
58
- dns_records = zones.first.dns_records.all
58
+ dns_records = zones.first.dns_records
59
59
  ```
60
60
 
61
61
  Show some details of the DNS record:
@@ -69,14 +69,14 @@ puts records
69
69
  Get firewall rules:
70
70
 
71
71
  ```ruby
72
- all_rules = zones.first.firewall_rules.all
73
- block_rules = zones.first.firewall_rules.all("block") # or "whitelist" or "challenge"
72
+ all_rules = zones.first.firewall_rules
73
+ block_rules = zones.first.firewall_rules("block") # or "whitelist" or "challenge"
74
74
  ```
75
75
 
76
76
  Get blocked ips:
77
77
 
78
78
  ```ruby
79
- block_rules = zones.first.firewall_rules.all("block")
79
+ block_rules = zones.first.firewall_rules("block")
80
80
  blocked_ips = zones.first.firewall_rules.firewalled_ips(block_rules)
81
81
  ```
82
82
 
@@ -89,7 +89,7 @@ data = {"mode":"block","configuration":{"target":"ip","value":"#{ip}"},"notes":"
89
89
  response = zones.first.firewall_rules.post(data.to_json, content_type: 'application/json')
90
90
  ```
91
91
 
92
- Add a DNS record dynamically. Here we add an A record for `batman.example.com`:
92
+ Add a DNS record dynamically. Here we add an A record for `batman.example.com`:
93
93
 
94
94
  ```ruby
95
95
  client = Cloudflare.connect(key: CF_KEY, email: CF_EMAIL)
@@ -114,9 +114,9 @@ zone.dns_records.post({"type":"A","name":"batman","content":"127.0.0.1","proxied
114
114
 
115
115
  Released under the MIT license.
116
116
 
117
- Copyright, 2012, 2014, by [Marcin Prokop](https://github.com/b4k3r).
118
- Copyright, 2017, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
117
+ Copyright, 2018, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
119
118
  Copyright, 2017, by [David Rosenbloom](http://artifactory.com).
119
+ Copyright, 2012, 2014, by [Marcin Prokop](https://github.com/b4k3r).
120
120
 
121
121
  Permission is hereby granted, free of charge, to any person obtaining a copy
122
122
  of this software and associated documentation files (the "Software"), to deal
data/Rakefile CHANGED
@@ -8,17 +8,19 @@ RSpec::Core::RakeTask.new(:test)
8
8
  task default: :test
9
9
 
10
10
  task :coverage do
11
- ENV['COVERAGE'] = 'y'
11
+ ENV['COVERAGE'] = 'y'
12
12
  end
13
13
 
14
14
  task :console do
15
- require 'cloudflare'
16
- require 'pry'
15
+ require_relative 'lib/cloudflare'
16
+ require 'pry'
17
17
 
18
- email = ENV['CLOUDFLARE_EMAIL']
19
- key = ENV['CLOUDFLARE_KEY']
18
+ email = ENV.fetch('CLOUDFLARE_EMAIL')
19
+ key = ENV.fetch('CLOUDFLARE_KEY')
20
20
 
21
- connection = Cloudflare::Connection.new(key: key, email: email)
22
-
23
- binding.pry
21
+ Async.run do
22
+ connection = Cloudflare.connect(key: key, email: email)
23
+
24
+ binding.pry
25
+ end
24
26
  end
data/cloudflare.gemspec CHANGED
@@ -4,26 +4,28 @@
4
4
  require_relative 'lib/cloudflare/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = 'cloudflare'
8
- spec.version = Cloudflare::VERSION
9
- spec.platform = Gem::Platform::RUBY
7
+ spec.name = 'cloudflare'
8
+ spec.version = Cloudflare::VERSION
9
+ spec.platform = Gem::Platform::RUBY
10
10
 
11
- spec.summary = 'A Ruby wrapper for the Cloudflare API.'
12
- spec.authors = ['Marcin Prokop', 'Samuel Williams']
13
- spec.email = ['marcin@prokop.co', 'samuel.williams@oriontransfer.co.nz']
14
- spec.homepage = 'https://github.com/b4k3r/cloudflare'
15
- spec.licenses = ['MIT']
11
+ spec.summary = 'A Ruby wrapper for the Cloudflare API.'
12
+ spec.authors = ['Marcin Prokop', 'Samuel Williams']
13
+ spec.email = ['marcin@prokop.co', 'samuel.williams@oriontransfer.co.nz']
14
+ spec.homepage = 'https://github.com/b4k3r/cloudflare'
15
+ spec.licenses = ['MIT']
16
16
 
17
- spec.files = `git ls-files`.split("\n")
18
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
- spec.require_paths = ['lib']
17
+ spec.files = `git ls-files`.split("\n")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ['lib']
21
21
 
22
- spec.required_ruby_version = '>= 2.0.0'
22
+ spec.required_ruby_version = '>= 2.0.0'
23
23
 
24
- spec.add_dependency 'rest-client', '~> 2.0.2'
24
+ spec.add_dependency 'async-rest'
25
25
 
26
- spec.add_development_dependency 'bundler', '~> 1.3'
27
- spec.add_development_dependency 'rake'
28
- spec.add_development_dependency 'rspec', '~> 3.6'
26
+ spec.add_development_dependency 'async-rspec'
27
+
28
+ spec.add_development_dependency 'bundler'
29
+ spec.add_development_dependency 'rake'
30
+ spec.add_development_dependency 'rspec', '~> 3.6'
29
31
  end
data/lib/cloudflare.rb CHANGED
@@ -21,12 +21,27 @@
21
21
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
22
  # THE SOFTWARE.
23
23
 
24
+ require 'async'
24
25
  require_relative 'cloudflare/connection'
25
- require_relative 'cloudflare/zone'
26
- require_relative 'cloudflare/user'
27
26
 
28
27
  module Cloudflare
29
- def self.connect(**options)
30
- Connection.new(**options)
31
- end
28
+ DEFAULT_URL = 'https://api.cloudflare.com/client/v4'
29
+
30
+ def self.connect(key: nil, email: nil)
31
+ representation = Connection.for(DEFAULT_URL)
32
+
33
+ if key
34
+ representation = representation.authenticated(key, email)
35
+ end
36
+
37
+ return representation unless block_given?
38
+
39
+ Async do
40
+ begin
41
+ yield representation
42
+ ensure
43
+ representation.close
44
+ end
45
+ end
46
+ end
32
47
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  # Copyright, 2012, by Marcin Prokop.
4
4
  # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
5
+ # Copyright, 2017, by David Rosenbloom. <http://artifactory.com>
5
6
  #
6
7
  # Permission is hereby granted, free of charge, to any person obtaining a copy
7
8
  # of this software and associated documentation files (the "Software"), to deal
@@ -21,53 +22,30 @@
21
22
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
23
  # THE SOFTWARE.
23
24
 
24
- require 'json'
25
+ require_relative 'representation'
26
+ require_relative 'paginate'
25
27
 
26
28
  module Cloudflare
27
- class RequestError < StandardError
28
- def initialize(what, response)
29
- super("#{what}: #{response.errors.join(', ')}")
30
-
31
- @response = response
32
- end
33
-
34
- attr_reader :response
35
- end
36
-
37
- class Response
38
- def initialize(what, content)
39
- @what = what
40
-
41
- @body = JSON.parse(content, symbolize_names: true)
42
- end
43
-
44
- attr_reader :body
45
-
46
- def result
47
- raise RequestError.new(@what, self) unless successful?
48
-
49
- body[:result]
50
- end
51
-
52
- # Treat result as an array (often it is).
53
- def results
54
- Array(result)
55
- end
56
-
57
- def empty?
58
- result.empty?
59
- end
60
-
61
- def successful?
62
- body[:success]
63
- end
64
-
65
- def errors
66
- body[:errors]
67
- end
68
-
69
- def messages
70
- body[:messages]
71
- end
72
- end
29
+ class Account < Representation
30
+ end
31
+
32
+ class Accounts < Representation
33
+ include Paginate
34
+
35
+ def represent(metadata, attributes)
36
+ resource = @resource.with(path: attributes[:id])
37
+
38
+ return Account.new(resource, metadata: metadata, value: attributes)
39
+ end
40
+
41
+ def create(name)
42
+ response = self.post(name: name)
43
+
44
+ return represent(response.headers, response.read)
45
+ end
46
+
47
+ def find_by_id(id)
48
+ Zone.new(@resource.with(path: id))
49
+ end
50
+ end
73
51
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright, 2012, by Marcin Prokop.
4
- # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
3
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
5
4
  #
6
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
7
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -21,57 +20,37 @@
21
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
21
  # THE SOFTWARE.
23
22
 
24
- require 'net/http'
25
- require 'json'
23
+ require_relative 'representation'
26
24
 
27
- require 'rest-client'
28
- require 'uri'
29
-
30
- require_relative 'response'
25
+ require_relative 'zones'
26
+ require_relative 'accounts'
27
+ require_relative 'user'
31
28
 
32
29
  module Cloudflare
33
- DEFAULT_URL = 'https://api.cloudflare.com/client/v4/'
34
- TIMEOUT = 10 # Default is 5 seconds
35
- DEFAULT_HEADERS = { 'Content-Type' => 'application/json' }.freeze
36
-
37
- class Resource < RestClient::Resource
38
- include Enumerable
39
-
40
- # @param api_key [String] `X-Auth-Key` or `X-Auth-User-Service-Key` if no email provided.
41
- # @param email [String] `X-Auth-Email`, your email address for the account.
42
- def initialize(url = DEFAULT_URL, key: nil, email: nil, **options)
43
- headers = options[:headers] || DEFAULT_HEADERS.dup
44
-
45
- if email.nil?
46
- headers['X-Auth-User-Service-Key'] = key
47
- else
48
- headers['X-Auth-Key'] = key
49
- headers['X-Auth-Email'] = email
50
- end
51
-
52
- # Convert HTTP API responses to our own internal response class:
53
- super(url, headers: headers, accept: 'application/json', **options) do |response|
54
- Response.new(response.request.url, response.body)
55
- end
56
- end
57
-
58
- def paginate(obj, url, url_args = '')
59
- page = 1
60
- page_size = 50
61
- results = []
62
-
63
- # fetch and aggregate all pages
64
- loop do
65
- query = URI.encode_www_form scope_type: :organization, per_page: page_size, page: page
66
- rules = obj.new(concat_urls(url, "?#{query}#{url_args}"), self, **options)
67
- results += rules.get.results
68
- break if results.empty? || results.size % page_size != 0
69
- page += 1
70
- end
71
- results
72
- end
73
- end
74
-
75
- class Connection < Resource
76
- end
30
+ class Connection < Representation
31
+ def authenticated(key, email = nil)
32
+ headers = {}
33
+
34
+ if email.nil?
35
+ headers['X-Auth-User-Service-Key'] = key
36
+ else
37
+ headers['X-Auth-Key'] = key
38
+ headers['X-Auth-Email'] = email
39
+ end
40
+
41
+ self.class.new(@resource.with(headers: headers))
42
+ end
43
+
44
+ def zones
45
+ Zones.new(@resource.with(path: 'zones'))
46
+ end
47
+
48
+ def accounts
49
+ Accounts.new(@resource.with(path: 'accounts'))
50
+ end
51
+
52
+ def user
53
+ User.new(@resource.with(path: 'user'))
54
+ end
55
+ end
77
56
  end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright, 2012, by Marcin Prokop.
4
+ # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
5
+ # Copyright, 2017, by David Rosenbloom. <http://artifactory.com>
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in
15
+ # all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ # THE SOFTWARE.
24
+
25
+ require_relative 'representation'
26
+ require_relative 'paginate'
27
+
28
+ module Cloudflare
29
+ module DNS
30
+ class Record < Representation
31
+ def initialize(url, record = nil, **options)
32
+ super(url, **options)
33
+
34
+ @record = record || get.result
35
+ end
36
+
37
+ def update_content(content)
38
+ response = put(
39
+ type: @record[:type],
40
+ name: @record[:name],
41
+ content: content
42
+ )
43
+
44
+ @value = response.result
45
+ end
46
+
47
+ def type
48
+ value[:type]
49
+ end
50
+
51
+ def name
52
+ value[:name]
53
+ end
54
+
55
+ def content
56
+ value[:content]
57
+ end
58
+
59
+ def to_s
60
+ "#{@record[:name]} #{@record[:type]} #{@record[:content]}"
61
+ end
62
+ end
63
+
64
+ class Records < Representation
65
+ include Paginate
66
+
67
+ def representation
68
+ Record
69
+ end
70
+
71
+ TTL_AUTO = 1
72
+
73
+ def create(type, name, content, **options)
74
+ message = self.post(type: type, name: name, content: content, **options)
75
+
76
+ id = message.result[:id]
77
+ resource = @resource.with(path: id)
78
+
79
+ return representation.new(resource, metadata: message.headers, value: message.result)
80
+ end
81
+
82
+ def find_by_name(name)
83
+ each(name: name).first
84
+ end
85
+
86
+ def find_by_id(id)
87
+ Record.new(@resource.with(path: id))
88
+ end
89
+ end
90
+ end
91
+ end