cloudflare_cli 0.0.3.pre.alpha.3 → 0.0.3.pre.alpha.4

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: e9040ea27f4419504e8ca1685366b138182c761cf049434495aa26125dc516b7
4
- data.tar.gz: 68f45141a508ef11ad4eb325f615574de01854ab669a66861653866b03e04b04
3
+ metadata.gz: 674fa0021f915da803db1c1b029d1414a071e840db062510e7666dcc1335bb5c
4
+ data.tar.gz: e0cbcb0b80cb82b9a67393373473bffd7a4ba776efe33dd05f141ce7b6745bf4
5
5
  SHA512:
6
- metadata.gz: 11ec37db18fdcdbdafa403e7e792ffa9f2cf25599f365462ac6ea71dd68d64c253f2cc3880214c44f86e3e8c1be0e564c5e54d4ab96ccd863ddd81c672d52f62
7
- data.tar.gz: 59819e1622c1914a6ffb6f634e34eea8878abfe72f1a7eafe23233f13bb7262379d9ed5bb1acdb838d7a86db0e564b907c599840ef1c0b70dfcbb1b8eef7e9cb
6
+ metadata.gz: b55ee5dc35a872462aa51f5f955a5227d6b78c07253c8caa916e57b6bb0f42f02b8c475dba1da6ac998ad74a223f14996e266d00bc41805f2dfb17315b86a8b1
7
+ data.tar.gz: bc4aa6e6e8ab983fc02aa4f55d557caa500ce277d3cd6966ea57d8eefcf15a50f703182f23898c0b7bfc109b9d2d95d6be13c21d02041ccd30c967e174bbf0db
data/README.md CHANGED
@@ -1,18 +1,109 @@
1
- = cloudflare_cli
1
+ ## cloudflare_cli - Interface with the Cloudflare API!
2
2
 
3
- A Command Line Interface for interacting with CloudFlare's API without having to
4
- mess with scripting a script yourself.
3
+ cloudflare_cli is an interface into the Cloudflare API,
4
+ usage is rate-limited by Cloudflare itself, not the gem.
5
5
 
6
+ See https://api.cloudflare.com/#getting-started-requests for information
7
+ on the API and the linked anchor for rate-limiting specifically.
6
8
 
7
- == Installation
9
+ v0.0.3-alpha.3
8
10
 
9
- gem install cloudflare_cli
11
+ ### Global Options
10
12
 
11
- == About
13
+ ### --api-key APIKEY
12
14
 
13
- This is not a library or require'able gem, this is an executable only.
14
- If you wish to use CloudFlare's API in more advanced ways, then you would need
15
- to install a gem that is requirable like [RubyFlare](https://github.com/trev/rubyflare)
16
- which this gem uses behind the scenes.
15
+ Cloudflare API Key
16
+
17
+ Default Value
18
+ : none
19
+
20
+
21
+ ### --email EMAIL
22
+
23
+ Cloudflare E-Mail
24
+
25
+ Default Value
26
+ : none
27
+
28
+
29
+ ### --help
30
+ Show this message
31
+
32
+
33
+ ### --version
34
+ Display the program version
35
+
36
+
37
+ ### Commands
38
+
39
+ #### Command: `dns-record `
40
+
41
+ DNS Record Management
42
+
43
+ ##### Commands
44
+
45
+ ###### Command: `add `
46
+
47
+ add a record
48
+
49
+ ###### Command: `rem|del|delete `
50
+
51
+ remove a record
52
+
53
+ ###### Command: `show `
54
+
55
+ get a record
56
+
57
+ ###### Command: `update|modify `
58
+
59
+ update a record
60
+
61
+ #### Command: `help command`
62
+
63
+ Shows a list of commands or help for one command
64
+
65
+ Gets help for the application or its commands. Can also list the commands in a
66
+ way helpful to creating a bash-style completion function
67
+
68
+ ##### Options
69
+
70
+ ##### -c
71
+ List commands one per line, to assist with shell completion
72
+
73
+
74
+ #### Command: `initconfig `
75
+ Initialize the config file using current global options
76
+
77
+ Initializes a configuration file where you can set default options for command
78
+ line flags, both globally and on a per-command basis. These defaults override
79
+ the built-in defaults and allow you to omit commonly-used command line flags
80
+ when invoking this program
81
+
82
+ ##### Options
83
+
84
+ ##### --[no-]force
85
+ force overwrite of existing config file
86
+
87
+
88
+ #### Command: `ips `
89
+ Return Cloudflare IPs
90
+
91
+ ##### Commands
92
+
93
+ ###### Command: `list `
94
+ list out cloudflare's IPs
95
+
96
+ Default Command
97
+ : list
98
+
99
+ #### Command: `zones `
100
+ Use all the non-dns '/zones/*' endpoints
101
+
102
+ ##### Commands
103
+
104
+ ###### Command: `all|list `
105
+ list all zones or filter them
106
+
107
+ Default Command
108
+ : all
17
109
 
18
- gem install rubyflare
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ ##########
3
+ # File: cloudflare_cli/bin/cfcli
4
+ # Project: cloudflare_cli
5
+ # Author: Ken Spencer <me@iotaspencer.me>
6
+ # Copyright (c) 2018 Ken Spencer
7
+ # License: MIT
8
+ # --------
9
+
10
+ require 'cloudflare_cli'
11
+
12
+ CloudflareCli::App.run(ARGV)
@@ -1,4 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
+ ##########
3
+ # File: cloudflare_cli/bin/cloudflare_cli
4
+ # Project: cloudflare_cli
5
+ # Author: Ken Spencer <me@iotaspencer.me>
6
+ # Copyright (c) 2018 Ken Spencer
7
+ # License: MIT
8
+ # --------
9
+
2
10
  require 'cloudflare_cli'
3
11
 
4
12
  CloudflareCli::App.run(ARGV)
@@ -1,13 +1,13 @@
1
1
  == cloudflare_cli - Interface with the Cloudflare API!
2
2
 
3
3
 
4
- cloudflare_cli is an interface into the Cloudflare API,
5
- usage is rate-limited by Cloudflare itself, not the gem.
4
+ cloudflare_cli is an interface into the Cloudflare API,
5
+ usage is rate-limited by Cloudflare itself, not the gem.
6
6
 
7
- See https://api.cloudflare.com/#getting-started-requests for information
8
- on the API and the linked anchor for rate-limiting specifically.
7
+ See https://api.cloudflare.com/#getting-started-requests for information
8
+ on the API and the linked anchor for rate-limiting specifically.
9
9
 
10
- v0.0.3
10
+ v0.0.3-alpha.3
11
11
 
12
12
  === Global Options
13
13
  === --api-key APIKEY
@@ -91,8 +91,8 @@ Use all the non-dns '/zones/*' endpoints
91
91
 
92
92
 
93
93
  ===== Commands
94
- ====== Command: <tt>all|list-zones </tt>
94
+ ====== Command: <tt>all|list </tt>
95
95
  list all zones or filter them
96
96
 
97
97
 
98
- [Default Command] false
98
+ [Default Command] all
@@ -1,32 +1,32 @@
1
- require "gli"
2
- require "json"
3
- require "cloudflare_cli/tree"
1
+ require 'gli'
2
+ require 'json'
3
+ require 'cloudflare_cli/tree'
4
4
 
5
5
  module CloudflareCli
6
+ # Have a class for the GLI space
6
7
  class App
7
8
  extend GLI::App
8
- program_desc "Interface with the Cloudflare API!"
9
+ program_desc 'Interface with the Cloudflare API!'
9
10
 
10
- program_long_desc <<~HEREDOC
11
+ program_long_desc <<-HEREDOC
11
12
 
12
- #{exe_name} is an interface into the Cloudflare API,
13
+ #{exe_name} is an interface into the Cloudflare API,
13
14
  usage is rate-limited by Cloudflare itself, not the gem.
14
15
 
15
16
  See https://api.cloudflare.com/#getting-started-requests for information
16
17
  on the API and the linked anchor for rate-limiting specifically.
17
- HEREDOC
18
+ HEREDOC
18
19
 
19
20
  version CloudflareCli::VERSION
20
21
 
21
- config_file ".cfcli/config"
22
+ config_file '.cfcli/config'
22
23
  subcommand_option_handling :normal
23
24
  arguments :strict
24
25
  wrap_help_text :verbatim
25
26
 
26
-
27
27
  commands_from 'cloudflare_cli/commands'
28
- flag [:email], desc: "Cloudflare E-Mail", default_value: "", arg_name: "EMAIL", mask: true
29
- flag ["api-key"], desc: "Cloudflare API Key", default_value: "", arg_name: "APIKEY", mask: true
28
+ flag [:email], desc: 'Cloudflare E-Mail', default_value: '', arg_name: 'EMAIL', mask: true
29
+ flag ['api-key'], desc: 'Cloudflare API Key', default_value: '', arg_name: 'APIKEY', mask: true
30
30
 
31
31
  around do |global_options, command, options, arguments, code|
32
32
  CloudflareCli::State.initiate(global_options)
@@ -1,19 +1,24 @@
1
+ require 'gli'
1
2
  module CloudflareCli
3
+ # Cloudflare CLI App class
2
4
  class App
3
5
  extend GLI::App
4
6
 
5
- desc "DNS Record Management"
6
- command "dns-record" do |c|
7
- c.desc "add a record"
7
+ desc 'DNS Record Management'
8
+ command 'dns-record' do |c|
9
+ c.desc 'add a record'
10
+
8
11
  c.command :add do |dnsadd|
9
- dnsadd.action do |global_options, options, args|
12
+ dnsadd.flag :type, default_value: 'A', must_match: %w[A AAAA CNAME SOA PTR NS MX LOC SRV SPF TXT CAA CERT DNSKEY DS NAPTR SSHFP TLSA URI SMIMEA], desc: 'Record Type'
10
13
 
14
+ dnsadd.flag :zone, desc: 'DNS Zone ID or Zone Name'
15
+ dnsadd.action do |global_options, options, args|
11
16
  # Your command logic here
12
17
 
13
18
  # If you have any errors, just raise them
14
19
  # raise "that command made no sense"
15
20
 
16
- puts "dns-record add command ran"
21
+ puts "dns-record add command ran with #{options}"
17
22
  end
18
23
  end
19
24
 
@@ -1,20 +1,56 @@
1
+ require 'gli'
2
+ require 'cloudflare_cli/methods/term_table'
3
+ require 'cloudflare_cli/methods/output_class'
4
+ require 'recursive_open_struct'
5
+ require 'cloudflare_cli/send_nested'
6
+
1
7
  module CloudflareCli
2
8
  class App
3
9
  extend GLI::App
4
10
 
5
11
  desc "Use all the non-dns '/zones/*' endpoints"
6
12
  command :zones do |c|
7
- c.desc "list all zones or filter them"
8
- c.command [:all, "list-zones"] do |lz|
9
- lz.example "#{exe_name} zones [list-zones|all]", desc: "List all zones without filtering them"
10
- lz.flag [:name], desc: "Zone name to search for"
13
+ c.desc 'list all zones or filter them'
14
+ c.command [:all, :list] do |lz|
15
+ lz.example "#{exe_name} zones [list-zones|all]", desc: 'List all zones without filtering them'
16
+ lz.example "#{exe_name} zones [list-zones|all] --name example.com", desc: 'List by filter'
17
+ lz.example "#{exe_name} zones [list-zones|all] --status active", desc: 'List active zones'
18
+ lz.example "#{exe_name} zones [list-zones|all] --order name --direction desc", desc: 'List zones and sort by name in descending order'
19
+ lz.example "#{exe_name} zones [list-zones|all] --name example.com --output success --output result[0].id", desc: 'list zones and output some fields, for use with scripts'
20
+ lz.flag [:name], desc: 'Zone name to search for, max length is 253 characters', arg_name: 'NAME'
21
+ lz.flag [:status], desc: 'Status of the zone', must_match: %w[active pending initializing moved deleted deactivated], required: false, arg_name: 'STATUS', default_value: 'active'
22
+ lz.flag :page, desc: 'Page number of paginated results', type: Integer, arg_name: 'PAGE#', default_value: 1
23
+ lz.flag :per_page, desc: 'Number of zones per page', default_value: 20, must_match: 5..50, arg_name: '##'
24
+ lz.flag :order, desc: 'Field to order zones by', must_match: %w[name status email], arg_name: 'ORDER', default_value: 'name'
25
+ lz.flag %i[direction dir], desc: 'Direction to order zones', must_match: %w[asc desc], arg_name: 'DIR', default_value: 'asc'
26
+ lz.flag :match, desc: 'Whether to match all search requirements or at least one (any)', must_match: %w[any all], default_value: 'all', arg_name: 'MATCH'
27
+ lz.flag :'output-sep', desc: 'choose character to separate output fields', must_match: [:newline, :crlf, :space], required: false, default_value: ' '
28
+ lz.flag :output, desc: 'output fields, use multiple times to output multiple fields', multiple: true
29
+ lz.switch :table, desc: 'Put some of the output into a table', default_value: true
30
+ lz.switch :json, desc: 'output the full raw json', negatable: true
11
31
  lz.action do |global_options, options, args|
12
- puts CloudflareCli::Endpoints::Zones.all(options)
32
+ cf_options = options.reject{ |k,v| %w[output output-sep table].include? k }.reject{ |k,v| %i[output output-sep table].include? k }
33
+ js = CloudflareCli::Nodes::Zone::Zones.all(cf_options).body
34
+ if options[:json]
35
+ puts js.to_json
36
+ end
37
+ if options[:table]
38
+ table = CloudflareCli::Methods::Zones::TermTable.new('Zones', js)
39
+ table.make_rows
40
+ end
41
+ if options[:output]
42
+ want = CloudflareCli::Methods::Zones::Output.new(options[:output], options, js)
43
+ want.put
44
+ end
13
45
  end
14
46
  end
15
- c.action do |global_options, options, args|
47
+ c.desc 'Create a zone'
48
+ c.command [:new, :create] do |cz|
49
+ cz.switch :'jump-start', desc: 'Automatically attempt to fetch existing DNS records', negatable: true, default_value: false
50
+ cz.flag :name, desc: 'The domain name', must_match: /^([a-zA-Z0-9][\-a-zA-Z0-9]*\.)+[\-a-zA-Z0-9]{2,20}$/
51
+ cz.flag :'account-name', desc: "The account's name, this is shown through Home->Account Home->Configurations->Preferences->Account Name"
16
52
  end
17
- c.default_command false
53
+ c.default_command :all
18
54
  end
19
55
  end
20
56
  end
@@ -0,0 +1,33 @@
1
+ require 'recursive_open_struct'
2
+ module CloudflareCli
3
+ module Methods
4
+ module Zones
5
+ class Output
6
+ def initialize(fields, options, hsh)
7
+ @fields = fields
8
+ @options = options
9
+ @hsh = hsh
10
+ @struct = RecursiveOpenStruct.new(hsh, recurse_over_arrays: true)
11
+ end
12
+ def get_fields(fields = @fields)
13
+ fields.each do |path|
14
+ print @struct.send_nested(path)
15
+ case @options[:'output-sep']
16
+ when :newline
17
+ print "\n"
18
+ when :space
19
+ print ' '
20
+ when :crlf
21
+ print "\r\n"
22
+
23
+ end
24
+ end
25
+
26
+ end
27
+ def put
28
+ self.get_fields
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,39 @@
1
+ require 'terminal-table'
2
+ require 'recursive_open_struct'
3
+ require 'table_print'
4
+ module CloudflareCli
5
+ module Methods
6
+ module Zones
7
+ class TermTable
8
+ # @param [String] title Table title
9
+ # @param [Hash] hsh Initialize a TermTable instance
10
+ def initialize(title, hsh)
11
+ @table_title = title
12
+ @table = Terminal::Table.new
13
+ @hash = hsh
14
+ @struct = RecursiveOpenStruct.new(hsh, recurse_over_arrays: true)
15
+ @table.title = @table_title
16
+ #@table.style = {:width => 80}
17
+ end
18
+
19
+ # @return [NilClass]
20
+ def add_separator
21
+ @table.add_separator
22
+ end
23
+
24
+ def table
25
+ @table
26
+ end
27
+
28
+ def make_rows
29
+ tp.set :capitalize_headers, false
30
+ @struct.result.each do |res|
31
+ puts res
32
+ end
33
+ tp @struct, {'result.id' => {width: 40, display_name: 'ID'}}, {'result.name' => {display_name: 'Zone Name'}}
34
+
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,92 @@
1
+ class String
2
+ alias_method :starts_with?, :start_with?
3
+ alias_method :ends_with?, :end_with?
4
+ end
5
+ class Object
6
+ # Retrieve the value of a deeply nested attribute
7
+ #
8
+ # Example usage
9
+ #
10
+ # attribute = "data.foo['bar'].id"
11
+ # value = obj.send_nested(attribute)
12
+ #
13
+ # Under the hood this will do something akin to
14
+ # obj.send(data).send(foo)['bar'].send(id)
15
+ #
16
+ # This also works with symbols in the attribute string
17
+ #
18
+ # attribute = "data.foo[:bar].id"
19
+ # value = obj.send_nested(attribute)
20
+ #
21
+ # Under the hood this will do something akin to
22
+ # obj.send(data).send(foo)['bar'].send(id)
23
+ #
24
+ #
25
+ # Parameters
26
+ # attribute: The (nested) attribute to query for
27
+ # with_indifferent_access: If this is true, then this will convert any
28
+ # hashes to HashWithIndifferentAccess. As such,
29
+ # anything that was a symbol before will become a
30
+ # string.
31
+ # Returns whatever the attribute evaluates to with the major caveat is that
32
+ # if `with_indifferent_access` is used, any resulting hashes will have string
33
+ # keys even if they were symbols to begin with as this is how the ruby method
34
+ # hash.with_indifferent_access works
35
+ def send_nested(attribute, with_indifferent_access: false)
36
+ # Split in to the attribute and the deeper nested things
37
+ # E.g. this will split "data.foo['bar'].id" in to
38
+ # data
39
+ # .foo['bar'].id
40
+
41
+ matches = /([^\.\[\]]+)(.*)/.match(attribute)
42
+ attr = matches.captures[0]
43
+ obj = send(attr)
44
+ until matches.captures[1].empty?
45
+ next_part = matches.captures[1]
46
+ kind = next_part.slice!(0)
47
+
48
+ # This means to use a nested send
49
+ if kind == '.'
50
+ matches = /([^\.\[\]]+)(.*)/.match(next_part)
51
+ attr = matches.captures[0]
52
+ obj = obj.send(attr)
53
+
54
+ # This means we want to access something by a key or index
55
+ elsif kind == '['
56
+ matches = /(['|"|:]*[^\]]+['|"]*)\](.*)/.match(next_part)
57
+ attr = matches.captures[0]
58
+
59
+ # Figure out if the attribute is a string, symbol, or an integer index
60
+ # and do the right thing to convert it to the attribute we care about
61
+ if attr.starts_with?(':')
62
+ attr.slice!(0)
63
+ attr = attr.to_sym
64
+ elsif attr.starts_with?("'")
65
+ unless attr.ends_with?("'")
66
+ raise ArgumentError, "Hash key starts with a ' but does not end with one: #{attr}"
67
+ end
68
+ attr.slice!(0)
69
+ attr.chop!
70
+ elsif attr.starts_with?('"')
71
+ unless attr.ends_with?('"')
72
+ raise ArgumentError, "Hash key starts with a \" but does not end with one: #{attr}"
73
+ end
74
+ attr.slice!(0)
75
+ attr.chop!
76
+ elsif attr.to_i.to_s == attr
77
+ attr = attr.to_i
78
+ end
79
+
80
+ if with_indifferent_access && obj.is_a?(Hash)
81
+ obj = obj.with_indifferent_access
82
+ end
83
+
84
+ obj = obj[attr]
85
+
86
+ else
87
+ raise ArgumentError, "Could not parse attribute #{attribute}"
88
+ end
89
+ end
90
+ obj
91
+ end
92
+ end
@@ -1,14 +1,15 @@
1
1
  require "rubyflare"
2
2
 
3
3
  module CloudflareCli
4
- module Endpoints
4
+ module Nodes
5
5
  class IPs
6
6
  def self.list
7
7
 
8
8
  ctx = CloudflareCli::State.ctx
9
9
  ctx.get('ips')
10
10
  rescue Rubyflare::ConnectionError => e
11
- # puts e.response.body
11
+ puts e.response.body
12
+
12
13
  end
13
14
  end
14
15
  end
@@ -1,19 +1,17 @@
1
1
  require "rubyflare"
2
2
 
3
3
  module CloudflareCli
4
- module Endpoints
5
- class Zones
6
-
4
+ module Nodes
5
+ module Zone
6
+ class Zones
7
7
  # Return Cloudflare Account Zones
8
- def self.all(options)
9
- puts options
10
- #begin
11
- # ctx = CloudflareCli::State.ctx
12
- # ctx.get('zones')
13
- #rescue Rubyflare::ConnectionError => e
14
- # puts e.response.body
15
- #end
8
+ def self.all(options)
9
+ ctx = CloudflareCli::State.ctx
10
+ ctx.get('zones', options)
11
+ rescue Rubyflare::ConnectionError => e
12
+ puts e.response.body
13
+ end
16
14
  end
17
15
  end
18
16
  end
19
- end
17
+ end
@@ -1,3 +1,3 @@
1
1
  module CloudflareCli
2
- VERSION = '0.0.3-alpha.3'
2
+ VERSION = '0.0.3-alpha.4'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudflare_cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3.pre.alpha.3
4
+ version: 0.0.3.pre.alpha.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ken Spencer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-29 00:00:00.000000000 Z
11
+ date: 2018-12-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -80,6 +80,48 @@ dependencies:
80
80
  - - '='
81
81
  - !ruby/object:Gem::Version
82
82
  version: 0.16.2
83
+ - !ruby/object:Gem::Dependency
84
+ name: table_print
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: terminal-table
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: recursive-open-struct
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
83
125
  description:
84
126
  email: me+cloudflare_cli@iotaspencer.me
85
127
  executables:
@@ -89,6 +131,7 @@ extra_rdoc_files: []
89
131
  files:
90
132
  - ChangeLog.md
91
133
  - README.md
134
+ - bin/cfcli
92
135
  - bin/cloudflare_cli
93
136
  - cloudflare_cli.rdoc
94
137
  - lib/cloudflare_cli.rb
@@ -96,6 +139,9 @@ files:
96
139
  - lib/cloudflare_cli/commands/001_dns_records.rb
97
140
  - lib/cloudflare_cli/commands/002_cloudflare_ips.rb
98
141
  - lib/cloudflare_cli/commands/003_zones.rb
142
+ - lib/cloudflare_cli/methods/output_class.rb
143
+ - lib/cloudflare_cli/methods/term_table.rb
144
+ - lib/cloudflare_cli/send_nested.rb
99
145
  - lib/cloudflare_cli/tree.rb
100
146
  - lib/cloudflare_cli/tree/ips.rb
101
147
  - lib/cloudflare_cli/tree/zones.rb