cloudflare 3.2.1 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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