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

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: 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