jcf 0.0.12 → 0.1.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: 33389a4011279ad183dc738318b71355a50601dde4f602d867cb060b305e7a49
4
- data.tar.gz: 42f129b8aa7ab515bd51fac1f2c8f78ee6785f8750debb5778c88fa2d062dca1
3
+ metadata.gz: 65808aa6761614f5fd189ae66ffe581709eaaebe1bbca0b9833ee00ead7957be
4
+ data.tar.gz: 223665d3d2608a6a2a12d870e718fd969753c43fb73db5edad10c4bc4dfa3166
5
5
  SHA512:
6
- metadata.gz: 35548f0ce298af159e532eb6b0517594d8e990857d8c5f77aab5e0b770920758e2a11f74ca063c113342adc1a46df120ed2d4577684ae69b60db90578a4a5d8d
7
- data.tar.gz: 1fd422e325af12931d444728c4aca883eceaceab60bea50bc33e143bc62e70d783b1ed4103a2c181302fc6d5e7b44eeff70aa4ff53278cb12710e7b6ec806ee6
6
+ metadata.gz: 179b7adbe213bbc2a317fbd06407abdd1f2d3ce27e3da8e2e42495db4b9fc748d5a798f4920017d00d0039c34fa168d2dfa1ef721313853abf1202be5b5de4d7
7
+ data.tar.gz: f2e8ec3f17848da098d049ae482e8529927f77e52337023fbda07ce6f4a438cb2ac441d69095552396e913a59d2c6e52099171c6bfc0bea62f05d8a1c0785270
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## [0.0.14] - 2023-10-19
2
+
3
+ - Fix all the output I broker in the last release...I need some more extensive tests
4
+
5
+ ## [0.0.13] - 2023-10-19
6
+
7
+ - Fix a bug where I'd left in some unnecessary code
8
+
1
9
  ## [0.0.12] - 2023-10-19
2
10
 
3
11
  - Refactored broker backend querying for metrics to use a plugin system that can be extended to support other brokers. Currently only the AWS and S3 broker is supported, but it should be easy to add others.
data/lib/jcf/cf/base.rb CHANGED
@@ -40,7 +40,7 @@ module JCF
40
40
  class << self
41
41
  attr_accessor :endpoint
42
42
 
43
- def keys; new.keys; end
43
+ def keys = new.keys
44
44
 
45
45
  def find_by(attrs)
46
46
  objects = all
@@ -48,6 +48,7 @@ module JCF
48
48
  keys = obj.attributes.keys & attrs.keys
49
49
  keys.all? do |key|
50
50
  return true if attrs[key].nil?
51
+
51
52
  obj.attributes[key].include? attrs[key]
52
53
  end
53
54
  end
@@ -72,6 +73,15 @@ module JCF
72
73
  endpoint || name.demodulize.tableize
73
74
  end
74
75
 
76
+ def format(data)
77
+ data.each_with_object({}) do |broker, h|
78
+ broker.attributes.each do |k, v|
79
+ h[k] ||= []
80
+ h[k] << v
81
+ end
82
+ end
83
+ end
84
+
75
85
  private
76
86
 
77
87
  def resources(params: {})
@@ -107,6 +107,7 @@ module JCF
107
107
  end
108
108
 
109
109
  # values = { guid: { name: "name", space: "space" }, guid2: { name: "name2", space: "space2" } }
110
+ # output = { header1: %w[name1 name2], header2: %w[space1 space2]}
110
111
  output = Hash.new { |hash, key| hash[key] = [] }
111
112
  values.each do |guid, metrics|
112
113
  metrics.each do |k, v|
@@ -13,12 +13,12 @@ module JCF
13
13
  argument :name, required: false, desc: "Organization name"
14
14
 
15
15
  def call(name: nil, **)
16
- values = if name
17
- Organization.find_by(name: name).collect(&:values)
18
- else
19
- Organization.all.collect(&:values)
20
- end
21
- out.puts formatter.format(headers: Organization.keys, values: values)
16
+ data = if name
17
+ Organization.find_by(name: name)
18
+ else
19
+ Organization.all
20
+ end
21
+ out.puts formatter.format(data: JCF::CF::Base.format(data))
22
22
  end
23
23
  end
24
24
  end
@@ -13,11 +13,12 @@ module JCF
13
13
  option :org, aliases: ["-o", "--org", "--organization"], type: :string, desc: "Filter to an organization"
14
14
 
15
15
  def call(name: nil, **options)
16
- if name
17
- out.puts formatter.format(JCF::CF::Quota.find_by(name: name))
18
- else
19
- out.puts formatter.format(JCF::CF::Quota.all(org: options[:org]))
20
- end
16
+ data = if name
17
+ JCF::CF::Quota.find_by(name: name)
18
+ else
19
+ JCF::CF::Quota.all(org: options[:org])
20
+ end
21
+ out.puts formatter.format(data: JCF::CF::Base.format(data))
21
22
  end
22
23
  end
23
24
  end
@@ -8,19 +8,25 @@ module JCF
8
8
  module Commands
9
9
  module CF
10
10
  class ServiceBrokers < Command
11
+ include JCF::CF
12
+
11
13
  argument :name, required: false, desc: "Service Broker name"
12
14
 
13
15
  option :space, aliases: ["-s", "--space"], type: :string, desc: "Filter to a space"
14
16
 
15
17
  def call(name: nil, **options)
16
18
  if name
17
- out.puts formatter.format(JCF::CF::ServiceBroker.find_by(name: name))
19
+ out.puts formatter.format(data: JCF::CF::ServiceBroker.find_by(name: name))
18
20
  else
19
- out.puts formatter.format(
20
- JCF::CF::ServiceBroker.all(
21
- space_guids: options[:space]
22
- )
23
- )
21
+ # [
22
+ # #<ServiceBroker @name="cdn-broker", @guid="aaaa", @relationships=[]>,
23
+ # #<ServiceBroker @name="rds-broker", @guid="bbbb", @relationships=[]>
24
+ # ]
25
+ # output = { name: %w[cdn-broker rds-broker], header2: %w[aaaa bbbb]}
26
+
27
+ data = ServiceBroker.all(space_guids: options[:space])
28
+
29
+ out.puts formatter.format(data: JCF::CF::Base.format(data))
24
30
  end
25
31
  end
26
32
  end
@@ -15,21 +15,19 @@ module JCF
15
15
  option :service_plan, aliases: ["-p", "--plan", "--service-plan"], type: :string,
16
16
  desc: "Filter to a service plan"
17
17
 
18
- # rubocop:disable Metrics/MethodLength
19
18
  def call(name: nil, **options)
20
- if name
21
- out.puts formatter.format(JCF::CF::ServiceInstance.find_by(name: name))
22
- else
23
- out.puts formatter.format(
24
- JCF::CF::ServiceInstance.all(
25
- organization_guids: options[:org],
26
- space_guids: options[:space],
27
- service_plan: options[:service_plan]
28
- )
29
- )
30
- end
19
+ data = if name
20
+ JCF::CF::ServiceInstance.find_by(name: name)
21
+ else
22
+ JCF::CF::ServiceInstance.all(
23
+ organization_guids: options[:org],
24
+ space_guids: options[:space],
25
+ service_plan: options[:service_plan]
26
+ )
27
+ end
28
+
29
+ out.puts formatter.format(data: JCF::CF::Base.format(data))
31
30
  end
32
- # rubocop:enable Metrics/MethodLength
33
31
  end
34
32
  end
35
33
  end
@@ -13,11 +13,13 @@ module JCF
13
13
  option :org, aliases: ["-o", "--org", "--organization"], type: :string, desc: "Filter to an organization guid"
14
14
 
15
15
  def call(name: nil, **options)
16
- if name
17
- out.puts formatter.format(JCF::CF::ServiceOffering.find_by(name: name))
18
- else
19
- out.puts formatter.format(JCF::CF::ServiceOffering.all(organization_guids: options[:org]))
20
- end
16
+ data = if name
17
+ JCF::CF::ServiceOffering.find_by(name: name)
18
+ else
19
+ JCF::CF::ServiceOffering.all(organization_guids: options[:org])
20
+ end
21
+
22
+ out.puts formatter.format(data: JCF::CF::Base.format(data))
21
23
  end
22
24
  end
23
25
  end
@@ -13,15 +13,13 @@ module JCF
13
13
  option :org, aliases: ["-o", "--org", "--organization"], type: :string, desc: "Filter to an organization"
14
14
 
15
15
  def call(name: nil, **options)
16
- if name
17
- out.puts formatter.format(JCF::CF::ServicePlan.find_by(name: name))
18
- else
19
- out.puts formatter.format(
20
- JCF::CF::ServicePlan.all(
21
- organization_guids: options[:org]
22
- )
23
- )
24
- end
16
+ data = if name
17
+ JCF::CF::ServicePlan.find_by(name: name)
18
+ else
19
+ JCF::CF::ServicePlan.all(organization_guids: options[:org])
20
+ end
21
+
22
+ out.puts formatter.format(data: JCF::CF::Base.format(data))
25
23
  end
26
24
  end
27
25
  end
@@ -9,16 +9,11 @@ module JCF
9
9
  module Commands
10
10
  module CF
11
11
  class Services < Command
12
- argument :broker, required: false, desc: "Broker name"
12
+ argument :broker, required: true, desc: "Broker name"
13
13
 
14
- def call(broker: nil, **)
14
+ def call(broker:, **)
15
15
  # gather all service offerings and plans for a single broker
16
- if broker
17
- out.puts formatter.format(JCF::CF::Services.first(name: broker), tree: true)
18
- else
19
- # TODO: this is a stub, it should be a list of all brokers
20
- # out.puts formatter.format(JCF::CF::Organization.all)
21
- end
16
+ out.puts formatter.format(data: JCF::CF::Services.first(name: broker), tree: true)
22
17
  end
23
18
  end
24
19
  end
@@ -13,11 +13,13 @@ module JCF
13
13
  option :org, aliases: ["-o", "--org", "--organization"], type: :string, desc: "Filter to an organization"
14
14
 
15
15
  def call(name: nil, **options)
16
- if name
17
- out.puts formatter.format(JCF::CF::Space.find_by(name: name))
18
- else
19
- out.puts formatter.format(JCF::CF::Space.all(organization_guids: options[:org]))
20
- end
16
+ data = if name
17
+ JCF::CF::Space.find_by(name: name)
18
+ else
19
+ JCF::CF::Space.all(organization_guids: options[:org])
20
+ end
21
+
22
+ out.puts formatter.format(data: JCF::CF::Base.format(data))
21
23
  end
22
24
  end
23
25
  end
@@ -11,11 +11,13 @@ module JCF
11
11
  argument :name, required: false, desc: "Partial username"
12
12
 
13
13
  def call(name: nil, **_options)
14
- if name
15
- out.puts formatter.format(JCF::CF::User.all(partial_usernames: name))
16
- else
17
- out.puts formatter.format(JCF::CF::User.all)
18
- end
14
+ data = if name
15
+ JCF::CF::User.all(partial_usernames: name)
16
+ else
17
+ JCF::CF::User.all
18
+ end
19
+
20
+ out.puts formatter.format(data: JCF::CF::Base.format(data))
19
21
  end
20
22
  end
21
23
  end
@@ -10,10 +10,20 @@ module JCF
10
10
  out.puts "JCF Plugins:"
11
11
  plugin_dir = File.join(JCF.root, "jcf", "plugins", "*.rb")
12
12
  pp "plugin dir: #{plugin_dir}" if ENV["DEBUG"]
13
+ load_plugins(plugin_dir)
14
+ list_plugins
15
+ end
16
+
17
+ private
18
+
19
+ def load_plugins(plugin_dir)
13
20
  Dir[plugin_dir].each do |plugin|
14
21
  out.puts " file: #{File.basename(plugin, ".rb")}" if ENV["DEBUG"]
15
22
  JCF::Plugins.load_plugin(File.basename(plugin, ".rb").to_sym)
16
23
  end
24
+ end
25
+
26
+ def list_plugins
17
27
  JCF::Plugins.plugins.each do |plugin|
18
28
  out.puts " #{plugin}"
19
29
  end
@@ -5,6 +5,7 @@ module JCF
5
5
  module Commands
6
6
  end
7
7
 
8
+ # rubocop:disable Metrics/MethodLength
8
9
  def self.register_commands!
9
10
  register "version", Commands::Version, aliases: ["v", "-v", "--version"]
10
11
  register "plugins", Commands::Plugins
@@ -19,5 +20,6 @@ module JCF
19
20
  register "service_instances", Commands::CF::ServiceInstances, aliases: %w[si service_instance]
20
21
  register "service_plans", Commands::CF::ServicePlans, aliases: %w[sp service_plan]
21
22
  end
23
+ # rubocop:enable Metrics/MethodLength
22
24
  end
23
25
  end
@@ -5,13 +5,9 @@ module JCF
5
5
  class Error < StandardError
6
6
  end
7
7
 
8
- class NotImplementedError < Error
9
- end
10
-
11
- class NotLoggedInError < StandardError
12
- end
13
-
14
- class InvalidOptionError < StandardError
15
- end
8
+ class NotImplementedError < Error; end
9
+ class NotLoggedInError < StandardError; end
10
+ class InvalidOptionError < StandardError; end
11
+ class EmptyResultError < StandardError; end
16
12
  end
17
13
  end
@@ -7,6 +7,19 @@ module JCF
7
7
  module OutputFormatters
8
8
  class Text
9
9
  class << self
10
+ # @param data [Hash] the data to be formatted
11
+ # @param tree [Boolean] whether to format as a tree or a table
12
+ # @return [String] the formatted data
13
+ # @example
14
+ #
15
+ # data: { header1: %w[name1 name2], header2: %w[space1 space2]}
16
+ # output:
17
+ # ┌────────┬────────┐
18
+ # │header1 │header2 │
19
+ # ├────────┼────────┤
20
+ # │name1 │space1 │
21
+ # │name2 │space2 │
22
+ # └────────┴────────┘
10
23
  def format(data:, tree: false)
11
24
  return "" if data.nil? || data.empty?
12
25
 
@@ -19,9 +32,15 @@ module JCF
19
32
 
20
33
  private
21
34
 
35
+ # @param data [Hash] the data to be formatted
36
+ # @return [String] the formatted data
37
+ # @example
38
+ #
39
+ # data: { header1: %w[name1 name2], header2: %w[space1 space2]}
40
+ # values: [["name1", "space1"], ["name2", "space2"]]
22
41
  def render_data(data)
23
- keys = collect_keys(data)
24
- values = collect_values(data)
42
+ keys = data.keys.collect(&:to_s)
43
+ values = data.values.transpose
25
44
 
26
45
  table = TTY::Table.new(keys, values)
27
46
  table.render(:unicode, resize: true)
@@ -30,33 +49,6 @@ module JCF
30
49
  def render_tree(data)
31
50
  TTY::Tree.new(data).render
32
51
  end
33
-
34
- def collect_keys(data)
35
- return ["Empty result"] if !data || data.empty?
36
-
37
- if data.is_a?(Array)
38
- data.first.keys.collect(&:to_s)
39
- elsif data.is_a?(Hash)
40
- data.keys.collect(&:to_s) || ["Empty result"]
41
- else
42
- data.keys.collect(&:to_s)
43
- end
44
- end
45
-
46
- # Hash:
47
- # values: [["name1", "name2"], ["space1", "space2"]]
48
- # output: [["name1", "space1"], ["name2", "space2"]]
49
- def collect_values(data)
50
- return [["Empty result"]] if !data || data.empty?
51
-
52
- if data.is_a?(Array)
53
- data.map { |d| d.attributes.values.collect(&:to_s) }
54
- elsif data.is_a?(Hash)
55
- data.values.transpose
56
- else
57
- [data.attributes.values.collect(&:to_s)]
58
- end
59
- end
60
52
  end
61
53
  end
62
54
  end
data/lib/jcf/cli.rb CHANGED
@@ -25,7 +25,7 @@ module JCF
25
25
  puts "Validating plugin (#{plugin}) implementation conforms to interface" if ENV["DEBUG"]
26
26
 
27
27
  %i[metrics names values].each do |method|
28
- raise "Plugin does not conform to interface (missing method \"#{method.to_s}\")" \
28
+ raise "Plugin does not conform to interface (missing method \"#{method}\")" \
29
29
  unless plugin.new(name: nil).respond_to?(method)
30
30
  end
31
31
  rescue JCF::CLI::NotLoggedInError => e
@@ -46,6 +46,7 @@ module JCF
46
46
  puts "Loading plugin #{name}" if ENV["DEBUG"]
47
47
  require "jcf/plugins/#{name}"
48
48
  raise "Plugin didn't correctly register itself" unless @plugins[name]
49
+
49
50
  @plugins[name]
50
51
  end
51
52
 
@@ -98,8 +99,6 @@ module JCF
98
99
  require_relative "cli/output_formatters"
99
100
  require_relative "cli/commands"
100
101
  require_relative "cli/errors"
101
- # require_relative "cf.rb"
102
- require_relative "aws/cloudwatch"
103
102
 
104
103
  extend Dry::CLI::Registry
105
104
 
@@ -33,7 +33,7 @@ module JCF
33
33
  end
34
34
 
35
35
  def to_s
36
- metrics.to_s
36
+ metrics.to_s
37
37
  end
38
38
 
39
39
  private
@@ -59,8 +59,8 @@ module JCF
59
59
  def storage_allocated(name:)
60
60
  rds = Aws::RDS::Client.new
61
61
  size = rds
62
- .describe_db_instances(db_instance_identifier: name)
63
- .db_instances.first.allocated_storage
62
+ .describe_db_instances(db_instance_identifier: name)
63
+ .db_instances.first.allocated_storage
64
64
  Filesize.from("#{size} GB").to_i
65
65
  end
66
66
 
@@ -78,18 +78,18 @@ module JCF
78
78
  cloudwatch(name: name, metric: :cpu)
79
79
  end
80
80
 
81
- # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
81
+ # rubocop:disable Metrics/MethodLength
82
82
  def cloudwatch(name:, metric:)
83
83
  cloudwatch = Aws::CloudWatch::Client.new
84
84
  res = cloudwatch.get_metric_statistics({
85
- namespace: "AWS/RDS",
86
- metric_name: metric,
87
- dimensions: [{ name: "DBInstanceIdentifier", value: name }],
88
- start_time: 1.day.ago,
89
- end_time: Time.now,
90
- period: 86_400,
91
- statistics: ["Average"]
92
- })
85
+ namespace: "AWS/RDS",
86
+ metric_name: metric,
87
+ dimensions: [{ name: "DBInstanceIdentifier", value: name }],
88
+ start_time: 1.day.ago,
89
+ end_time: Time.now,
90
+ period: 86_400,
91
+ statistics: ["Average"]
92
+ })
93
93
 
94
94
  pp res if ENV["DEBUG"]
95
95
 
@@ -97,7 +97,7 @@ module JCF
97
97
  rescue Aws::Errors::MissingCredentialsError
98
98
  puts "You are not logged in to an AWS shell. 'gds aws <ACCOUNT> -s'"
99
99
  end
100
- # rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
100
+ # rubocop:enable Metrics/MethodLength
101
101
 
102
102
  def to_gb(bytes)
103
103
  Filesize.from("#{bytes} b").to("GB").to_fs(:rounded, precision: 2)
data/lib/jcf/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JCF
4
- VERSION = "0.0.12"
4
+ VERSION = "0.1.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jcf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.12
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jamie van Dyke
@@ -275,7 +275,6 @@ files:
275
275
  - lib/.DS_Store
276
276
  - lib/jcf.rb
277
277
  - lib/jcf/.DS_Store
278
- - lib/jcf/aws/cloudwatch.rb
279
278
  - lib/jcf/cf.rb
280
279
  - lib/jcf/cf/.DS_Store
281
280
  - lib/jcf/cf/base.rb
@@ -1,90 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "aws-sdk-cloudwatch"
4
- require "aws-sdk-rds"
5
- require "aws-sdk-s3"
6
- require "active_support/core_ext/integer/time"
7
- require "active_support/isolated_execution_state"
8
- require "filesize"
9
-
10
- module JCF
11
- module AWS
12
- class CloudWatch
13
- NAMESPACES = {
14
- rds: "AWS/RDS",
15
- s3: "AWS/S3"
16
- }.freeze
17
- METRICS = {
18
- free_storage: "FreeStorageSpace",
19
- allocated_storage: "AllocatedStorage",
20
- iops: "WriteIOPS",
21
- cpu: "CPUUtilization"
22
- }.freeze
23
-
24
- def storage_free(name:)
25
- storage_free = rds(name: name, metric: :free_storage)
26
- storage_free.to_i
27
- end
28
-
29
- def storage_allocated(name:)
30
- rds = Aws::RDS::Client.new
31
- size = rds
32
- .describe_db_instances(db_instance_identifier: name)
33
- .db_instances.first.allocated_storage
34
- Filesize.from("#{size} GB").to_i
35
- end
36
-
37
- def rds_storage_used(name:)
38
- free = storage_free(name: name)
39
- allocated = storage_allocated(name: name)
40
- allocated - free
41
- end
42
-
43
- def s3_storage_used(name:)
44
- s3 = Aws::S3::Client.new
45
- total_size = 0
46
- response = s3.list_objects_v2(bucket: name)
47
- response.contents.each do |object|
48
- total_size += object.size
49
- end
50
- total_size
51
- end
52
-
53
- def iops(name:)
54
- rds(name: name, metric: :iops)
55
- end
56
-
57
- def cpu(name:)
58
- rds(name: name, metric: :cpu)
59
- end
60
-
61
- private
62
-
63
- def rds(name:, metric:)
64
- dimensions = { name: "DBInstanceIdentifier", value: name }
65
- aws(namespace: NAMESPACES[:rds], metric: METRICS[metric], dimensions: dimensions)
66
- end
67
-
68
- # rubocop:disable Metrics/ParameterLists, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
69
- def aws(namespace:, metric:, dimensions:, start_time: nil, end_time: nil, period: nil, statistic: nil)
70
- cloudwatch = Aws::CloudWatch::Client.new
71
- res = cloudwatch.get_metric_statistics({
72
- namespace: namespace,
73
- metric_name: metric,
74
- dimensions: [dimensions],
75
- start_time: (start_time || 1.day.ago),
76
- end_time: (end_time || Time.now),
77
- period: (period || 86_400),
78
- statistics: [(statistic || "Average")]
79
- })
80
-
81
- pp res if ENV["DEBUG"]
82
-
83
- res.datapoints.first&.average || 0
84
- rescue Aws::Errors::MissingCredentialsError
85
- puts "You are not logged in to an AWS shell. 'gds aws <ACCOUNT> -s'"
86
- end
87
- # rubocop:enable Metrics/ParameterLists, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
88
- end
89
- end
90
- end