jcf 0.0.11 → 0.0.12

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: 9479fc4468d9132f60c15f22782820798f35ae649d5bb09d575e7b051d77ddda
4
- data.tar.gz: 4090a17eb90884a706b11ea865805a4a99ada9b8bfbbfc1206fd6ddbf21e4af6
3
+ metadata.gz: 33389a4011279ad183dc738318b71355a50601dde4f602d867cb060b305e7a49
4
+ data.tar.gz: 42f129b8aa7ab515bd51fac1f2c8f78ee6785f8750debb5778c88fa2d062dca1
5
5
  SHA512:
6
- metadata.gz: 06fc37725e7ae5ad94b16e5e4a365ecd69760c45ca7e21922d81ca57e24e826cd43328d67d50e3b7bce5366a5421d09e99eb4fe03529d05562b9a6d4463ca546
7
- data.tar.gz: 2b508ca2c6441a640f13aa03fa05fb19438467f0bfa053e5cd23f37b8b861176f9648f22746cc2576a73c371e641e50684e02c0960da1e39401bfc89b676a1fc
6
+ metadata.gz: 35548f0ce298af159e532eb6b0517594d8e990857d8c5f77aab5e0b770920758e2a11f74ca063c113342adc1a46df120ed2d4577684ae69b60db90578a4a5d8d
7
+ data.tar.gz: 1fd422e325af12931d444728c4aca883eceaceab60bea50bc33e143bc62e70d783b1ed4103a2c181302fc6d5e7b44eeff70aa4ff53278cb12710e7b6ec806ee6
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [0.0.12] - 2023-10-19
2
+
3
+ - 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.
4
+ - Add a `jcf plugins` command to list available plugins (currently only ones in the `lib/jcf/plugins` directory)
5
+ - Refactored specs for output formatters
6
+
1
7
  ## [0.0.11] - 2023-10-12
2
8
 
3
9
  - Add a tree output for a new command `jcf services NAME` that will show all the offerings and instances for that broker. In a tree. Because trees are cool.
data/lib/jcf/cf/base.rb CHANGED
@@ -23,6 +23,14 @@ module JCF
23
23
  { name: name, guid: guid, relationships: relationships }
24
24
  end
25
25
 
26
+ def keys
27
+ attributes.keys
28
+ end
29
+
30
+ def values
31
+ attributes.values
32
+ end
33
+
26
34
  def initialize(name: nil, guid: nil, relationships: nil)
27
35
  @name = name
28
36
  @guid = guid
@@ -32,12 +40,14 @@ module JCF
32
40
  class << self
33
41
  attr_accessor :endpoint
34
42
 
43
+ def keys; new.keys; end
44
+
35
45
  def find_by(attrs)
36
46
  objects = all
37
47
  objects.find_all do |obj|
38
- # only find by attributes we have and our object has
39
48
  keys = obj.attributes.keys & attrs.keys
40
49
  keys.all? do |key|
50
+ return true if attrs[key].nil?
41
51
  obj.attributes[key].include? attrs[key]
42
52
  end
43
53
  end
@@ -51,6 +61,7 @@ module JCF
51
61
  new(guid: guid).populate!
52
62
  end
53
63
 
64
+ # TODO: make this less greedy
54
65
  def all(params = {})
55
66
  params.compact!
56
67
 
@@ -14,38 +14,51 @@ module JCF
14
14
  module Commands
15
15
  module CF
16
16
  class Metrics < Command
17
- argument :offering, required: true, values: %w[postgres mysql aws-s3-bucket],
18
- desc: "Choose a service instance offering to query"
17
+ argument :broker, required: true,
18
+ desc: "Choose a service instance offering to query. Get the broker name from the command: jcf sb"
19
+ argument :iaas_plugin, aliases: ["-m"], required: true, type: :string,
20
+ values: ::JCF::Plugins.plugins.keys.collect(&:to_s),
21
+ desc: "Select a IaaS plugin this broker is backed by"
19
22
 
20
23
  option :template, aliases: ["-t"], required: true, type: :string,
21
- desc: "Template for backend service instance names e.g. \"rdsbroker-{guid}-{name}\""
24
+ desc: "Template for backend service instance names e.g. \"rdsbroker-{guid}-{name}\""
22
25
  option :values, aliases: ["-v"], required: false, type: :string, default: "",
23
- desc: "Values for the template. 'guid' is the service instance guid e.g. \"name=test\""
26
+ desc: "Values for the template. 'guid' is the service instance guid e.g. \"name=test\""
24
27
  option :org, aliases: ["-o"], required: true, type: :string,
25
- desc: "Choose an organization (can be multiple comma-separated)"
28
+ desc: "Choose an organization (can be multiple comma-separated)"
26
29
  option :name, aliases: ["-n"], type: :string, desc: "Choose a service instance name"
27
30
 
28
31
  def call(*_args, **options)
29
32
  validate_options(options)
33
+ JCF.plugin options[:iaas_plugin].to_sym
34
+ plugin = JCF::Plugins.plugins[options[:iaas_plugin].to_sym]
35
+
30
36
  orgs = options[:org].include?(",") ? options[:org].split(",") : [options[:org]]
31
37
 
38
+ brokers = service_brokers.select { |b| b.name == options[:broker] }
39
+ # find the offerings for those brokers
40
+ offerings = service_offerings.select do |o|
41
+ brokers.find { |b| b.guid == o.relationships.service_broker.guid }
42
+ end
43
+ if offerings && offerings.empty?
44
+ err.puts "No offerings found for broker #{options[:broker]}"
45
+ exit(1)
46
+ end
47
+ err.puts "Found #{offerings.count} offerings"
48
+
32
49
  orgs.each do |org|
33
50
  org_guid = organizations.find { |o| o.name == org }.guid
34
51
  err.puts "Found org guid: #{org_guid}"
35
52
 
36
- offering_guid = service_offerings.find { |s| s.name == options[:offering] }&.guid
37
- err.puts "Found offering guid: #{offering_guid}"
38
-
39
- unless offering_guid
40
- err.puts "No offerings found for type #{options[:offering]}"
41
- exit(1)
42
- end
43
-
44
- # find the plans for those gatherings
53
+ # find the plans for those offerings
45
54
  plan_guids = service_plans.find_all do |plan|
46
- plan.relationships.service_offering.guid == offering_guid
55
+ offerings.collect(&:guid).include? plan.relationships.service_offering.guid
47
56
  end.collect(&:guid)
48
57
  err.puts "Found plan guids: #{plan_guids.count}"
58
+ if plan_guids.empty?
59
+ err.puts "No plans found for offerings"
60
+ exit(1)
61
+ end
49
62
 
50
63
  # look up the instances that match the plans and org
51
64
  # "/v3/service_instances?organization_guids=${org_guids}&service_plan_guids=${plan_guids}"
@@ -56,11 +69,9 @@ module JCF
56
69
  instances.select! { |i| i.name.include? options[:name] } if options[:name]
57
70
  err.puts "Found instances: #{instances.count}"
58
71
 
59
- cw = JCF::AWS::CloudWatch.new
60
- values = []
72
+ values = {}
61
73
 
62
74
  Thread.abort_on_exception = true
63
- # use a the number of processors as the number of threads
64
75
  instances.each_slice(Concurrent.processor_count) do |slice|
65
76
  slice.collect do |instance|
66
77
  service_plan = instance.relationships.service_plan.populate!
@@ -68,42 +79,42 @@ module JCF
68
79
  service_broker = service_offering.relationships.service_broker.populate!
69
80
 
70
81
  Thread.new do
71
- m = JCF::CF::Metric.new
72
- m.name = (instance.name || "")
73
- err.puts "Getting metrics for #{m.name}"
74
- m.region = ENV["AWS_REGION"]
75
- m.deploy_env = options[:env]
76
- m.organization = org
77
- m.organization_guid = org_guid
82
+ metrics = {}
83
+ metrics[:name] = (instance.name || "")
84
+ metrics[:instance_guid] = instance.guid
85
+ err.puts "Getting metrics for #{instance.name}"
86
+ metrics[:region] = ENV["AWS_REGION"]
87
+ metrics[:organization] = org
88
+ metrics[:organization_guid] = org_guid
78
89
  space = spaces.find { |s| s.guid == instance.relationships.space.guid }
79
- m.space = space.name
80
- m.space_guid = space.guid
81
- m.service_broker_name = service_broker.name
82
- m.service_broker_guid = service_broker.guid
83
- m.service_offering = service_offering.name
84
- m.service_plan = service_plan.name
90
+ metrics[:space] = space.name
91
+ metrics[:space_guid] = space.guid
92
+ metrics[:service_broker_name] = service_broker.name
93
+ metrics[:service_broker_guid] = service_broker.guid
94
+ metrics[:service_offering] = service_offering.name
95
+ metrics[:service_plan] = service_plan.name
85
96
 
86
97
  template = options[:template]
87
98
  t_values = parse_values(options[:values], instance.guid)
88
99
 
89
- if service_offering.name == "postgres"
90
- m.storage_used = to_gb(cw.rds_storage_used(name: JCF::CLI.template_parser(template, t_values)) || "")
91
- m.storage_allocated = to_gb(cw.storage_allocated(name: JCF::CLI.template_parser(template, t_values)) || "")
92
- m.storage_free = to_gb(cw.storage_free(name: JCF::CLI.template_parser(template, t_values)) || "")
93
- m.iops = (cw.iops(name: JCF::CLI.template_parser(template, t_values)).to_fs(:rounded, precision: 0) || "")
94
- m.cpu = (cw.cpu(name: JCF::CLI.template_parser(template, t_values)).to_fs(:rounded, precision: 0) || "")
95
- end
96
-
97
- if service_offering.name == "aws-s3-bucket"
98
- m.storage_used = to_gb(cw.s3_storage_used(name: JCF::CLI.template_parser(template, t_values)) || "")
100
+ t = JCF::CLI.template_parser(template, t_values)
101
+ plugin.new(name: t).metrics.each do |k, v|
102
+ metrics[k] = v
99
103
  end
100
- values << m
104
+ values[instance.guid] = metrics
101
105
  end
102
- end.map(&:value)
106
+ end.each(&:join)
103
107
  end
104
108
 
105
- values << JCF::CF::Metric.new if values.empty?
106
- out.puts formatter.format(values)
109
+ # values = { guid: { name: "name", space: "space" }, guid2: { name: "name2", space: "space2" } }
110
+ output = Hash.new { |hash, key| hash[key] = [] }
111
+ values.each do |guid, metrics|
112
+ metrics.each do |k, v|
113
+ output[k] << v
114
+ end
115
+ end
116
+
117
+ out.puts formatter.format(data: output)
107
118
  err.puts "Done."
108
119
  end
109
120
  end
@@ -141,13 +152,7 @@ module JCF
141
152
  end
142
153
 
143
154
  def service_brokers
144
- JCF::CF::ServiceBroker.all
145
- end
146
-
147
- def to_gb(bytes)
148
- Filesize.from("#{bytes} b").to("GB").to_fs(:rounded, precision: 2)
149
- rescue ArgumentError
150
- 0
155
+ @service_brokers ||= JCF::CF::ServiceBroker.all
151
156
  end
152
157
  end
153
158
  end
@@ -8,14 +8,17 @@ module JCF
8
8
  module Commands
9
9
  module CF
10
10
  class Organizations < Command
11
+ include JCF::CF
12
+
11
13
  argument :name, required: false, desc: "Organization name"
12
14
 
13
15
  def call(name: nil, **)
14
- if name
15
- out.puts formatter.format(JCF::CF::Organization.find_by(name: name))
16
+ values = if name
17
+ Organization.find_by(name: name).collect(&:values)
16
18
  else
17
- out.puts formatter.format(JCF::CF::Organization.all)
19
+ Organization.all.collect(&:values)
18
20
  end
21
+ out.puts formatter.format(headers: Organization.keys, values: values)
19
22
  end
20
23
  end
21
24
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JCF
4
+ module CLI
5
+ module Commands
6
+ class Plugins < Command
7
+ desc "Show JCF plugins"
8
+
9
+ def call(*)
10
+ out.puts "JCF Plugins:"
11
+ plugin_dir = File.join(JCF.root, "jcf", "plugins", "*.rb")
12
+ pp "plugin dir: #{plugin_dir}" if ENV["DEBUG"]
13
+ Dir[plugin_dir].each do |plugin|
14
+ out.puts " file: #{File.basename(plugin, ".rb")}" if ENV["DEBUG"]
15
+ JCF::Plugins.load_plugin(File.basename(plugin, ".rb").to_sym)
16
+ end
17
+ JCF::Plugins.plugins.each do |plugin|
18
+ out.puts " #{plugin}"
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -7,6 +7,7 @@ module JCF
7
7
 
8
8
  def self.register_commands!
9
9
  register "version", Commands::Version, aliases: ["v", "-v", "--version"]
10
+ register "plugins", Commands::Plugins
10
11
  register "metrics", Commands::CF::Metrics, aliases: ["m"]
11
12
 
12
13
  register "organizations", Commands::CF::Organizations, aliases: %w[o orgs organization]
@@ -7,24 +7,12 @@ module JCF
7
7
  module OutputFormatters
8
8
  class CSV
9
9
  class << self
10
- def format(data)
11
- case data
12
- in Array
13
- array = data.collect(&:serializable_hash)
14
- generate_csv(headers: array.first&.keys, values: array)
15
- in Hash
16
- generate_csv(headers: data.keys.sort, values: [data.serializable_hash])
17
- else
18
- generate_csv(headers: [], values: [])
19
- end
20
- end
21
-
22
- private
10
+ def format(data:)
11
+ return "" if data.nil? || data.empty?
23
12
 
24
- def generate_csv(headers:, values:)
25
- ::CSV.generate(headers: headers, write_headers: true) do |csv|
26
- values.each do |hash|
27
- csv << hash.values
13
+ ::CSV.generate(headers: data.keys, write_headers: true) do |csv|
14
+ data.values.transpose.each do |value|
15
+ csv << value
28
16
  end
29
17
  end
30
18
  end
@@ -6,12 +6,10 @@ module JCF
6
6
  module CLI
7
7
  module OutputFormatters
8
8
  class JSON
9
- def self.format(data)
10
- if data.is_a?(Enumerable)
11
- ::JSON.generate data.collect(&:serializable_hash)
12
- else
13
- ::JSON.generate data.serializable_hash
14
- end
9
+ def self.format(data:)
10
+ return "{}" if data.nil? || data.empty?
11
+
12
+ data.to_json
15
13
  end
16
14
  end
17
15
  end
@@ -7,8 +7,8 @@ module JCF
7
7
  module OutputFormatters
8
8
  class Text
9
9
  class << self
10
- def format(data, tree: false)
11
- return "" if data.nil?
10
+ def format(data:, tree: false)
11
+ return "" if data.nil? || data.empty?
12
12
 
13
13
  if tree
14
14
  render_tree(data)
@@ -17,6 +17,8 @@ module JCF
17
17
  end
18
18
  end
19
19
 
20
+ private
21
+
20
22
  def render_data(data)
21
23
  keys = collect_keys(data)
22
24
  values = collect_values(data)
@@ -29,19 +31,30 @@ module JCF
29
31
  TTY::Tree.new(data).render
30
32
  end
31
33
 
32
- def collect_values(data)
34
+ def collect_keys(data)
35
+ return ["Empty result"] if !data || data.empty?
36
+
33
37
  if data.is_a?(Array)
34
- data.map { |d| d.attributes.values.collect(&:to_s) }
38
+ data.first.keys.collect(&:to_s)
39
+ elsif data.is_a?(Hash)
40
+ data.keys.collect(&:to_s) || ["Empty result"]
35
41
  else
36
- [data.attributes.values.collect(&:to_s)]
42
+ data.keys.collect(&:to_s)
37
43
  end
38
44
  end
39
45
 
40
- def collect_keys(data)
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
+
41
52
  if data.is_a?(Array)
42
- data.first&.attributes&.keys || ["Empty result"]
53
+ data.map { |d| d.attributes.values.collect(&:to_s) }
54
+ elsif data.is_a?(Hash)
55
+ data.values.transpose
43
56
  else
44
- data.attributes.keys
57
+ [data.attributes.values.collect(&:to_s)]
45
58
  end
46
59
  end
47
60
  end
data/lib/jcf/cli.rb CHANGED
@@ -14,6 +14,50 @@ module JCF
14
14
  @cache ||= MiniCache::Store.new
15
15
  end
16
16
 
17
+ def self.plugin(plugin)
18
+ plugin = JCF::Plugins.load_plugin(plugin) if plugin.is_a?(Symbol)
19
+ validate_plugin!(plugin)
20
+ plugin.load_dependencies(self, *args, &block) if plugin.respond_to?(:load_dependencies)
21
+ plugin.configure(self, *args, &block) if plugin.respond_to?(:configure)
22
+ end
23
+
24
+ def self.validate_plugin!(plugin)
25
+ puts "Validating plugin (#{plugin}) implementation conforms to interface" if ENV["DEBUG"]
26
+
27
+ %i[metrics names values].each do |method|
28
+ raise "Plugin does not conform to interface (missing method \"#{method.to_s}\")" \
29
+ unless plugin.new(name: nil).respond_to?(method)
30
+ end
31
+ rescue JCF::CLI::NotLoggedInError => e
32
+ puts e.message
33
+ exit 1
34
+ end
35
+
36
+ module Plugins
37
+ @plugins = {}
38
+
39
+ def self.plugins
40
+ @plugins
41
+ end
42
+
43
+ def self.load_plugin(name)
44
+ return @plugins[name] if @plugins[name]
45
+
46
+ puts "Loading plugin #{name}" if ENV["DEBUG"]
47
+ require "jcf/plugins/#{name}"
48
+ raise "Plugin didn't correctly register itself" unless @plugins[name]
49
+ @plugins[name]
50
+ end
51
+
52
+ # Plugins need to call this method to register themselves:
53
+ #
54
+ # JCF::Plugins.register_plugin :render, Render
55
+ def self.register_plugin(name, mod)
56
+ puts "Registering plugin #{name}" if ENV["DEBUG"]
57
+ @plugins[name] = mod
58
+ end
59
+ end
60
+
17
61
  module CLI
18
62
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
19
63
  def self.loader
@@ -59,7 +103,9 @@ module JCF
59
103
 
60
104
  extend Dry::CLI::Registry
61
105
 
106
+ puts "Loading formatters..." if ENV["DEBUG"]
62
107
  register_formatters!
108
+ puts "Loading commands..." if ENV["DEBUG"]
63
109
  register_commands!
64
110
  end
65
111
  end
data/lib/jcf/metric.rb ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module JCF
6
+ class Metric
7
+ attr_accessor :name, :value
8
+
9
+ def to_s
10
+ "#{name}: #{value}"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "aws-sdk-cloudwatch"
4
+ require "aws-sdk-rds"
5
+ require "active_support/core_ext/integer/time"
6
+ require "active_support/isolated_execution_state"
7
+ require "filesize"
8
+
9
+ module JCF
10
+ module Plugins
11
+ class AwsRds
12
+ def initialize(name:)
13
+ @name = name
14
+ @metrics = {}
15
+ check_token!
16
+ end
17
+
18
+ def names
19
+ %w[storage_used storage_allocated storage_free iops cpu]
20
+ end
21
+
22
+ def values
23
+ names.map { |name| send(name.to_sym) }
24
+ end
25
+
26
+ def metrics
27
+ @metrics[:storage_used] = to_gb(storage_used(name: @name || ""))
28
+ @metrics[:storage_allocated] = to_gb(storage_allocated(name: @name) || "")
29
+ @metrics[:storage_free] = to_gb(storage_free(name: @name) || "")
30
+ @metrics[:iops] = (iops(name: @name).to_fs(:rounded, precision: 0) || "")
31
+ @metrics[:cpu] = (cpu(name: @name).to_fs(:rounded, precision: 0) || "")
32
+ @metrics
33
+ end
34
+
35
+ def to_s
36
+ metrics.to_s
37
+ end
38
+
39
+ private
40
+
41
+ def check_token!
42
+ Aws::STS::Client.new.get_caller_identity({})
43
+ rescue Aws::Errors::MissingCredentialsError
44
+ raise JCF::CLI::NotLoggedInError, "Your AWS token has expired. Please log in again."
45
+ end
46
+
47
+ METRICS = {
48
+ free_storage: "FreeStorageSpace",
49
+ allocated_storage: "AllocatedStorage",
50
+ iops: "WriteIOPS",
51
+ cpu: "CPUUtilization"
52
+ }.freeze
53
+
54
+ def storage_free(name:)
55
+ storage_free = cloudwatch(name: name, metric: "FreeStorageSpace")
56
+ storage_free.to_i
57
+ end
58
+
59
+ def storage_allocated(name:)
60
+ rds = Aws::RDS::Client.new
61
+ size = rds
62
+ .describe_db_instances(db_instance_identifier: name)
63
+ .db_instances.first.allocated_storage
64
+ Filesize.from("#{size} GB").to_i
65
+ end
66
+
67
+ def storage_used(name:)
68
+ free = storage_free(name: name)
69
+ allocated = storage_allocated(name: name)
70
+ allocated - free
71
+ end
72
+
73
+ def iops(name:)
74
+ cloudwatch(name: name, metric: :iops)
75
+ end
76
+
77
+ def cpu(name:)
78
+ cloudwatch(name: name, metric: :cpu)
79
+ end
80
+
81
+ # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
82
+ def cloudwatch(name:, metric:)
83
+ cloudwatch = Aws::CloudWatch::Client.new
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
+ })
93
+
94
+ pp res if ENV["DEBUG"]
95
+
96
+ res.datapoints.first&.average || 0
97
+ rescue Aws::Errors::MissingCredentialsError
98
+ puts "You are not logged in to an AWS shell. 'gds aws <ACCOUNT> -s'"
99
+ end
100
+ # rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
101
+
102
+ def to_gb(bytes)
103
+ Filesize.from("#{bytes} b").to("GB").to_fs(:rounded, precision: 2)
104
+ rescue ArgumentError
105
+ 0
106
+ end
107
+ end
108
+
109
+ register_plugin :aws_rds, AwsRds
110
+ end
111
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "aws-sdk-s3"
4
+ require "active_support/core_ext/integer/time"
5
+ require "active_support/isolated_execution_state"
6
+ require "filesize"
7
+
8
+ module JCF
9
+ module Plugins
10
+ class AwsS3
11
+ def initialize(name:)
12
+ @name = name
13
+ @metrics = {}
14
+ check_token!
15
+ end
16
+
17
+ def names
18
+ %w[storage_used]
19
+ end
20
+
21
+ def values
22
+ names.map { |name| send(name.to_sym) }
23
+ end
24
+
25
+ def metrics
26
+ @metrics[:storage_used] = to_gb(s3_storage_used(name: @name || ""))
27
+ @metrics
28
+ end
29
+
30
+ def to_s
31
+ metrics.to_s
32
+ end
33
+
34
+ private
35
+
36
+ def s3_storage_used(name:)
37
+ s3 = Aws::S3::Client.new
38
+ total_size = 0
39
+ response = s3.list_objects_v2(bucket: name)
40
+ response.contents.each do |object|
41
+ total_size += object.size
42
+ end
43
+ total_size
44
+ end
45
+
46
+ def check_token!
47
+ Aws::STS::Client.new.get_caller_identity({})
48
+ rescue Aws::Errors::MissingCredentialsError
49
+ raise JCF::CLI::NotLoggedInError, "Your AWS token has expired. Please log in again."
50
+ end
51
+
52
+ def to_gb(bytes)
53
+ Filesize.from("#{bytes} b").to("GB").to_fs(:rounded, precision: 2)
54
+ rescue ArgumentError
55
+ 0
56
+ end
57
+ end
58
+
59
+ register_plugin :aws_s3, AwsS3
60
+ end
61
+ end
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.11"
4
+ VERSION = "0.0.12"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jcf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.11
4
+ version: 0.0.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jamie van Dyke
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-12 00:00:00.000000000 Z
11
+ date: 2023-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -279,7 +279,6 @@ files:
279
279
  - lib/jcf/cf.rb
280
280
  - lib/jcf/cf/.DS_Store
281
281
  - lib/jcf/cf/base.rb
282
- - lib/jcf/cf/metric.rb
283
282
  - lib/jcf/cf/organization.rb
284
283
  - lib/jcf/cf/quota.rb
285
284
  - lib/jcf/cf/relationships.rb
@@ -304,12 +303,16 @@ files:
304
303
  - lib/jcf/cli/commands/cf/services.rb
305
304
  - lib/jcf/cli/commands/cf/spaces.rb
306
305
  - lib/jcf/cli/commands/cf/users.rb
306
+ - lib/jcf/cli/commands/plugins.rb
307
307
  - lib/jcf/cli/commands/version.rb
308
308
  - lib/jcf/cli/errors.rb
309
309
  - lib/jcf/cli/output_formatters.rb
310
310
  - lib/jcf/cli/output_formatters/csv.rb
311
311
  - lib/jcf/cli/output_formatters/json.rb
312
312
  - lib/jcf/cli/output_formatters/text.rb
313
+ - lib/jcf/metric.rb
314
+ - lib/jcf/plugins/aws_rds.rb
315
+ - lib/jcf/plugins/aws_s3.rb
313
316
  - lib/jcf/version.rb
314
317
  - sig/jcf.rbs
315
318
  homepage: https://github.com/fearoffish/paas-org-metric-gathering-gem
@@ -336,7 +339,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
336
339
  - !ruby/object:Gem::Version
337
340
  version: '0'
338
341
  requirements: []
339
- rubygems_version: 3.4.19
342
+ rubygems_version: 3.4.20
340
343
  signing_key:
341
344
  specification_version: 4
342
345
  summary: Gather metrics from AWS for CloudFoundry installations
data/lib/jcf/cf/metric.rb DELETED
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "base"
4
-
5
- module JCF
6
- module CF
7
- class Metric < Base
8
- attr_accessor :name, :region, :deploy_env, :organization, :organization_guid, :space, :space_guid,
9
- :service_broker_name, :service_broker_guid, :service_offering, :service_plan,
10
- :storage_allocated, :storage_used, :storage_free, :iops, :cpu
11
-
12
- # rubocop:disable Metrics/MethodLength
13
- def attributes
14
- {
15
- name: name,
16
- region: region,
17
- organization: organization,
18
- organization_guid: organization_guid,
19
- space: space,
20
- space_guid: space_guid,
21
- service_broker_name: service_broker_name,
22
- service_broker_guid: service_broker_guid,
23
- service_offering: service_offering,
24
- service_plan: service_plan,
25
- storage_used: storage_used,
26
- storage_allocated: storage_allocated,
27
- storage_free: storage_free,
28
- iops: iops,
29
- cpu: cpu
30
- }
31
- end
32
- # rubocop:enable Metrics/MethodLength
33
-
34
- def to_s
35
- "#{name}: used(#{storage_used}) allocated(#{storage_allocated}) free(#{storage_free}) iops(#{iops}) cpu(#{cpu})"
36
- end
37
- end
38
- end
39
- end