nex_client 0.1.0 → 0.2.0

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
  SHA1:
3
- metadata.gz: c4ae6ccb86acd03a0fbf4e551551c6ebbe38ebea
4
- data.tar.gz: 6eba8f471e9caefbf1d31907ffe084dcc69ebd4e
3
+ metadata.gz: eaf3b1116d1276f01639f77b71218bb6423c7be0
4
+ data.tar.gz: 3d5abdcc04437acd20d48c797909d3b5d30d7c04
5
5
  SHA512:
6
- metadata.gz: 4cc2d45e22cb810575f8aea00d767839ce67a605f1692692a943e12614cd8287495f5e5d9c25377d70db0455fb3373336df0fecfe5937fade08a76f82940d70e
7
- data.tar.gz: 80dbd8e444186e1ddb630e3e0a2fbf602c491baf6cfe1e43b3c7a858059d4e2bd09b498055c8adc87f7b29a18673dc37ff887f4a2c3ac53fa6170fc59ffe00a7
6
+ metadata.gz: 39cf5913237a6a192c3117737c3970f63d153bea86f7d474fe1f5cbbb429647b8c88ff377d27fa6f10c15114349a7da5c8ab94191921556a26102f5dbcc7dd5a
7
+ data.tar.gz: f16059882c2d143616ad268737a1ba2987a380b8c9e1d5683acbe5ed8f3fa098397509173a42e9e70a5f79fb8b38a75e3247574c0cd1f97e311618f5ff827935
@@ -3,5 +3,8 @@ module NexClient
3
3
  class Addon < BaseResource
4
4
  property :created_at, type: :time
5
5
  property :updated_at, type: :time
6
+
7
+ # GET <api_root>/apps/:id/logs
8
+ custom_endpoint :logs, on: :member, request_method: :get
6
9
  end
7
10
  end
@@ -20,5 +20,8 @@ module NexClient
20
20
 
21
21
  # PATCH <api_root>/apps/:id/unlink_scm
22
22
  custom_endpoint :unlink_scm, on: :member, request_method: :patch
23
+
24
+ # GET <api_root>/apps/:id/logs
25
+ custom_endpoint :logs, on: :member, request_method: :get
23
26
  end
24
27
  end
@@ -3,6 +3,7 @@ module NexClient
3
3
  class BaseResource < JsonApiClient::Resource
4
4
  API_HOST = {
5
5
  'development' => 'http://localhost:5000',
6
+ 'test' => 'http://nex-test.com',
6
7
  'uat' => 'https://api-nex-uat.maestrano.io',
7
8
  'production' => 'https://api-nex.maestrano.com',
8
9
  }
@@ -51,6 +51,18 @@ module NexClient
51
51
  end
52
52
  end
53
53
 
54
+ command :'addons:logs' do |c|
55
+ c.syntax = 'nex-cli addons:logs APP_NAME [options]'
56
+ c.summary = 'Gather addon logs'
57
+ c.description = 'Gather container logs for a given addon'
58
+ c.example 'gather logs for myaddon', 'nex-cli addons:logs myaddon'
59
+ c.example 'gather logs for myapp with a tail of 50', 'nex-cli addons:logs --tail 50 myaddon'
60
+ c.option '--tail NUMBER', String, 'number of lines to retrieve for each container'
61
+ c.action do |args, options|
62
+ NexClient::Commands::Addons.logs(args,options)
63
+ end
64
+ end
65
+
54
66
  command :apps do |c|
55
67
  c.syntax = 'nex-cli apps [options]'
56
68
  c.summary = 'Manage apps'
@@ -116,6 +128,18 @@ module NexClient
116
128
  end
117
129
  end
118
130
 
131
+ command :'apps:logs' do |c|
132
+ c.syntax = 'nex-cli apps:logs APP_NAME [options]'
133
+ c.summary = 'Gather app logs'
134
+ c.description = 'Gather container logs for a given app'
135
+ c.example 'gather logs for myapp', 'nex-cli apps:logs myapp'
136
+ c.example 'gather logs for myapp with a tail of 50', 'nex-cli apps:logs --tail 50 myapp'
137
+ c.option '--tail NUMBER', String, 'number of lines to retrieve for each container'
138
+ c.action do |args, options|
139
+ NexClient::Commands::Apps.logs(args,options)
140
+ end
141
+ end
142
+
119
143
  command :'apps:restart' do |c|
120
144
  c.syntax = 'nex-cli apps:restart APP_NAME'
121
145
  c.summary = 'Restart an app'
@@ -23,6 +23,21 @@ module NexClient
23
23
  self.display_addons(list)
24
24
  end
25
25
 
26
+ def self.logs(args,opts)
27
+ name = args.first
28
+ e = NexClient::Addon.find(name: name).first
29
+
30
+ # Display error
31
+ unless e
32
+ error("Error! Could not find addon: #{name}")
33
+ return false
34
+ end
35
+
36
+ # Retrieve logs and display them
37
+ logs = e.logs(tail: opts.tail).first
38
+ self.display_logs(logs.log_ret)
39
+ end
40
+
26
41
  def self.create(args,opts)
27
42
  svc_name,app_name = args
28
43
  app = NexClient::App.find(name: app_name).first
@@ -4,7 +4,7 @@ module NexClient
4
4
  module Commands
5
5
  module Apps
6
6
  extend Helpers
7
-
7
+
8
8
  SCALING_DIRECTIONS = [:up,:down]
9
9
  APPS_TITLE = "App Details".colorize(:green)
10
10
  APPS_HEADERS = ['id','name','status','image','ssl','storage','preferred region','nodes','owner'].map(&:upcase)
@@ -53,6 +53,21 @@ module NexClient
53
53
  Addons.display_addons(e.addons.select { |a| a.status == 'active'})
54
54
  end
55
55
 
56
+ def self.logs(args,opts)
57
+ name = args.first
58
+ e = NexClient::App.find(name: name).first
59
+
60
+ # Display error
61
+ unless e
62
+ error("Error! Could not find app: #{name}")
63
+ return false
64
+ end
65
+
66
+ # Retrieve logs and display them
67
+ logs = e.logs(tail: opts.tail).first
68
+ self.display_logs(logs.log_ret)
69
+ end
70
+
56
71
  def self.create(args,opts)
57
72
  image_info = args.first.split(':')
58
73
  attrs = { image: image_info[0], image_tag: image_info[1] }
@@ -3,6 +3,7 @@
3
3
  module NexClient
4
4
  module Commands
5
5
  module Helpers
6
+ LOG_COLORS = [:cyan,:green,:red,:yellow,:magenta]
6
7
 
7
8
  def display_record_errors(record)
8
9
  record.errors.messages.each do |k,v|
@@ -17,6 +18,18 @@ module NexClient
17
18
  def error(msg)
18
19
  puts msg.colorize(:red)
19
20
  end
21
+
22
+ def display_logs(logs)
23
+ color_index = 0
24
+ logs.each do |container_id,log_lines|
25
+ color_index = (color_index + 1) % LOG_COLORS.size
26
+ puts "\n"
27
+ puts "Node: #{container_id}".colorize(LOG_COLORS[color_index])
28
+ puts "-"*50
29
+ puts log_lines.join("\n")
30
+ end
31
+ puts "\n"
32
+ end
20
33
  end
21
34
  end
22
35
  end
@@ -1,3 +1,3 @@
1
1
  module NexClient
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe NexClient::App do
4
+ subject { described_class.new(id: 1) }
5
+ let(:api_key) { ENV['NEX_API_KEY'] }
6
+
7
+ describe 'restart' do
8
+ let!(:stub) { stub_request(:patch, "#{api_key}:@nex-test.com/api/v1/apps/#{subject.id}/restart") }
9
+ before { subject.restart }
10
+ it { expect(stub).to have_been_requested }
11
+ end
12
+
13
+ describe 'scale_up' do
14
+ describe 'without arguments' do
15
+ let!(:stub) { stub_request(:patch, "#{api_key}:@nex-test.com/api/v1/apps/#{subject.id}/scale_up") }
16
+ before { subject.scale_up }
17
+ it { expect(stub).to have_been_requested }
18
+ end
19
+ end
20
+
21
+ describe 'scale_down' do
22
+ let!(:stub) { stub_request(:patch, "#{api_key}:@nex-test.com/api/v1/apps/#{subject.id}/scale_down") }
23
+ before { subject.scale_down }
24
+ it { expect(stub).to have_been_requested }
25
+ end
26
+
27
+ describe 'link_scm' do
28
+ let!(:stub) { stub_request(:patch, "#{api_key}:@nex-test.com/api/v1/apps/#{subject.id}/link_scm") }
29
+ before { subject.link_scm }
30
+ it { expect(stub).to have_been_requested }
31
+ end
32
+
33
+ describe 'unlink_scm' do
34
+ let!(:stub) { stub_request(:patch, "#{api_key}:@nex-test.com/api/v1/apps/#{subject.id}/unlink_scm") }
35
+ before { subject.unlink_scm }
36
+ it { expect(stub).to have_been_requested }
37
+ end
38
+
39
+ describe 'logs' do
40
+ let!(:stub) { stub_request(:get, "#{api_key}:@nex-test.com/api/v1/apps/#{subject.id}/logs") }
41
+ before { subject.logs }
42
+ it { expect(stub).to have_been_requested }
43
+ end
44
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe NexClient::CubeInstance do
4
+ subject { described_class.new(id: 1) }
5
+ let(:api_key) { ENV['NEX_API_KEY'] }
6
+
7
+ describe 'restart' do
8
+ let!(:stub) { stub_request(:patch, "#{api_key}:@nex-test.com/api/v1/cube_instances/#{subject.id}/restart") }
9
+ before { subject.restart }
10
+ it { expect(stub).to have_been_requested }
11
+ end
12
+
13
+ describe 'start' do
14
+ let!(:stub) { stub_request(:patch, "#{api_key}:@nex-test.com/api/v1/cube_instances/#{subject.id}/start") }
15
+ before { subject.start }
16
+ it { expect(stub).to have_been_requested }
17
+ end
18
+
19
+ describe 'stop' do
20
+ let!(:stub) { stub_request(:patch, "#{api_key}:@nex-test.com/api/v1/cube_instances/#{subject.id}/stop") }
21
+ before { subject.stop }
22
+ it { expect(stub).to have_been_requested }
23
+ end
24
+
25
+ end
@@ -0,0 +1,93 @@
1
+ ENV['NEX_API_KEY'] = 'somekey'
2
+ ENV['NEX_ENV'] = 'test'
3
+
4
+ $:.unshift File.expand_path("../../lib", __FILE__)
5
+
6
+ require 'nex_client'
7
+ require 'webmock/rspec'
8
+
9
+ RSpec.configure do |config|
10
+ # rspec-expectations config goes here. You can use an alternate
11
+ # assertion/expectation library such as wrong or the stdlib/minitest
12
+ # assertions if you prefer.
13
+ config.expect_with :rspec do |expectations|
14
+ # This option will default to `true` in RSpec 4. It makes the `description`
15
+ # and `failure_message` of custom matchers include text for helper methods
16
+ # defined using `chain`, e.g.:
17
+ # be_bigger_than(2).and_smaller_than(4).description
18
+ # # => "be bigger than 2 and smaller than 4"
19
+ # ...rather than:
20
+ # # => "be bigger than 2"
21
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
22
+ end
23
+
24
+ # rspec-mocks config goes here. You can use an alternate test double
25
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
26
+ config.mock_with :rspec do |mocks|
27
+ # Prevents you from mocking or stubbing a method that does not exist on
28
+ # a real object. This is generally recommended, and will default to
29
+ # `true` in RSpec 4.
30
+ mocks.verify_partial_doubles = true
31
+ end
32
+
33
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
34
+ # have no way to turn it off -- the option exists only for backwards
35
+ # compatibility in RSpec 3). It causes shared context metadata to be
36
+ # inherited by the metadata hash of host groups and examples, rather than
37
+ # triggering implicit auto-inclusion in groups with matching metadata.
38
+ config.shared_context_metadata_behavior = :apply_to_host_groups
39
+
40
+ # The settings below are suggested to provide a good initial experience
41
+ # with RSpec, but feel free to customize to your heart's content.
42
+ =begin
43
+ # This allows you to limit a spec run to individual examples or groups
44
+ # you care about by tagging them with `:focus` metadata. When nothing
45
+ # is tagged with `:focus`, all examples get run. RSpec also provides
46
+ # aliases for `it`, `describe`, and `context` that include `:focus`
47
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
48
+ config.filter_run_when_matching :focus
49
+
50
+ # Allows RSpec to persist some state between runs in order to support
51
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
52
+ # you configure your source control system to ignore this file.
53
+ config.example_status_persistence_file_path = "spec/examples.txt"
54
+
55
+ # Limits the available syntax to the non-monkey patched syntax that is
56
+ # recommended. For more details, see:
57
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
58
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
59
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
60
+ config.disable_monkey_patching!
61
+
62
+ # This setting enables warnings. It's recommended, but in some cases may
63
+ # be too noisy due to issues in dependencies.
64
+ config.warnings = true
65
+
66
+ # Many RSpec users commonly either run the entire suite or an individual
67
+ # file, and it's useful to allow more verbose output when running an
68
+ # individual spec file.
69
+ if config.files_to_run.one?
70
+ # Use the documentation formatter for detailed output,
71
+ # unless a formatter has already been configured
72
+ # (e.g. via a command-line flag).
73
+ config.default_formatter = 'doc'
74
+ end
75
+
76
+ # Print the 10 slowest examples and example groups at the
77
+ # end of the spec run, to help surface which specs are running
78
+ # particularly slow.
79
+ config.profile_examples = 10
80
+
81
+ # Run specs in random order to surface order dependencies. If you find an
82
+ # order dependency and want to debug it, you can fix the order by providing
83
+ # the seed, which is printed after each run.
84
+ # --seed 1234
85
+ config.order = :random
86
+
87
+ # Seed global randomization in this process using the `--seed` CLI option.
88
+ # Setting this allows you to use `--seed` to deterministically reproduce
89
+ # test failures related to randomization by passing the same `--seed` value
90
+ # as the one that triggered the failure.
91
+ Kernel.srand config.seed
92
+ =end
93
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nex_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arnaud Lachaume
@@ -80,6 +80,34 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.5'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.5'
97
+ - !ruby/object:Gem::Dependency
98
+ name: webmock
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
83
111
  description: Client library for Maestrano Nex!™ PaaS
84
112
  email:
85
113
  - developers@maestrano.com
@@ -119,6 +147,9 @@ files:
119
147
  - lib/nex_client/storage_rack.rb
120
148
  - lib/nex_client/user.rb
121
149
  - lib/nex_client/version.rb
150
+ - spec/nex_client/app_spec.rb
151
+ - spec/nex_client/cube_instance_spec.rb
152
+ - spec/spec_helper.rb
122
153
  homepage: https://maestrano.com
123
154
  licenses:
124
155
  - Apache-2.0
@@ -143,4 +174,7 @@ rubygems_version: 2.5.1
143
174
  signing_key:
144
175
  specification_version: 4
145
176
  summary: Maestrano Nex!™ Client
146
- test_files: []
177
+ test_files:
178
+ - spec/nex_client/app_spec.rb
179
+ - spec/nex_client/cube_instance_spec.rb
180
+ - spec/spec_helper.rb