capistrano-data_plane_api 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +5 -0
  3. data/.ruby-version +1 -0
  4. data/CHANGELOG.md +5 -0
  5. data/Gemfile +15 -0
  6. data/Gemfile.lock +128 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +197 -0
  9. data/Rakefile +16 -0
  10. data/capistrano-data_plane_api.gemspec +41 -0
  11. data/exe/cap_data_plane_api +37 -0
  12. data/lib/capistrano/data_plane_api/configuration/backend.rb +18 -0
  13. data/lib/capistrano/data_plane_api/configuration/server.rb +22 -0
  14. data/lib/capistrano/data_plane_api/configuration/symbol.rb +16 -0
  15. data/lib/capistrano/data_plane_api/configuration.rb +33 -0
  16. data/lib/capistrano/data_plane_api/deploy/args.rb +241 -0
  17. data/lib/capistrano/data_plane_api/deploy/deployment_stats.rb +117 -0
  18. data/lib/capistrano/data_plane_api/deploy/group.rb +100 -0
  19. data/lib/capistrano/data_plane_api/deploy/helper.rb +51 -0
  20. data/lib/capistrano/data_plane_api/deploy/server_stats.rb +110 -0
  21. data/lib/capistrano/data_plane_api/deploy.rb +27 -0
  22. data/lib/capistrano/data_plane_api/diggable.rb +31 -0
  23. data/lib/capistrano/data_plane_api/equatable.rb +32 -0
  24. data/lib/capistrano/data_plane_api/helper.rb +56 -0
  25. data/lib/capistrano/data_plane_api/hooks.rb +7 -0
  26. data/lib/capistrano/data_plane_api/show_state.rb +86 -0
  27. data/lib/capistrano/data_plane_api/tasks.rb +30 -0
  28. data/lib/capistrano/data_plane_api/terminal_print_loop.rb +43 -0
  29. data/lib/capistrano/data_plane_api/type.rb +29 -0
  30. data/lib/capistrano/data_plane_api/version.rb +8 -0
  31. data/lib/capistrano/data_plane_api.rb +296 -0
  32. data/readme/failed_deployment_summary.png +0 -0
  33. data/readme/haproxy_state.png +0 -0
  34. data/sig/capistrano/data_plane_api.rbs +6 -0
  35. data/templates/bin/deploy +5 -0
  36. data/templates/bin/deploy.rb +6 -0
  37. data/templates/config/data_plane_api.rb +6 -0
  38. data/templates/config/data_plane_api.yml +51 -0
  39. metadata +177 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f09bc2341ac4e11146025f5ec2fb4dac89fe856ccfa94943487af17dcc63b5f5
4
+ data.tar.gz: 20cf62b4bbce05fbc1fc9fe8fef6a85fb23ebcd121d5caa8783620a590eb336d
5
+ SHA512:
6
+ metadata.gz: ba8c47106b3f124602eb6d6214cabc918c4aadc4cba6bd29b799453416d904b4dfb82f835fdd8eee64fabac28c55900f3dfe1c6987bdb53406801d7b8b6ff6b5
7
+ data.tar.gz: df2302167edfec625fbe2edc5221187025255a24263e1c481f19d130713d20767fd11ec6979b06f9cd5a4f39fb92f56eb715ff4e14d12f960f6ef09ecd77e5c4
data/.rubocop.yml ADDED
@@ -0,0 +1,5 @@
1
+ inherit_gem:
2
+ rubocop-espago: rubocop.yml
3
+
4
+ AllCops:
5
+ TargetRubyVersion: 2.7
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.2.0
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2022-12-28
4
+
5
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in capistrano-data_plane_api.gemspec
6
+ gemspec
7
+
8
+ gem 'minitest', '~> 5.0' # Test framework
9
+ gem 'rake', '~> 13.0' # Ruby automation tasks
10
+ gem 'rubocop', '~> 1.21' # Ruby linter
11
+ gem 'rubocop-espago', '~> 1.0' # Custom Ruby linter config
12
+ gem 'solargraph' # Ruby language server
13
+ gem 'shoulda-context', '~> 2.0' # Testing utilities
14
+ gem 'vcr' # Save HTTP interactions to files during tests
15
+ gem 'webmock' # Mock network interactions
data/Gemfile.lock ADDED
@@ -0,0 +1,128 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ capistrano-data_plane_api (0.1.0)
5
+ data_plane_api (~> 0.1)
6
+ pastel (< 1)
7
+ shale (< 1)
8
+ thor (> 1, < 2)
9
+ tty-box (< 1)
10
+ tty-cursor (< 1)
11
+
12
+ GEM
13
+ remote: https://rubygems.org/
14
+ specs:
15
+ addressable (2.8.1)
16
+ public_suffix (>= 2.0.2, < 6.0)
17
+ ast (2.4.2)
18
+ backport (1.2.0)
19
+ benchmark (0.2.1)
20
+ crack (0.4.5)
21
+ rexml
22
+ data_plane_api (0.1.2)
23
+ faraday (> 1, < 3)
24
+ diff-lcs (1.5.0)
25
+ e2mmap (0.1.0)
26
+ faraday (2.7.2)
27
+ faraday-net_http (>= 2.0, < 3.1)
28
+ ruby2_keywords (>= 0.0.4)
29
+ faraday-net_http (3.0.2)
30
+ hashdiff (1.0.1)
31
+ jaro_winkler (1.5.4)
32
+ json (2.6.3)
33
+ kramdown (2.4.0)
34
+ rexml
35
+ kramdown-parser-gfm (1.1.0)
36
+ kramdown (~> 2.0)
37
+ mini_portile2 (2.8.1)
38
+ minitest (5.16.3)
39
+ nokogiri (1.13.10)
40
+ mini_portile2 (~> 2.8.0)
41
+ racc (~> 1.4)
42
+ parallel (1.22.1)
43
+ parser (3.1.3.0)
44
+ ast (~> 2.4.1)
45
+ pastel (0.8.0)
46
+ tty-color (~> 0.5)
47
+ public_suffix (5.0.1)
48
+ racc (1.6.2)
49
+ rainbow (3.1.1)
50
+ rake (13.0.6)
51
+ regexp_parser (2.6.1)
52
+ reverse_markdown (2.1.1)
53
+ nokogiri
54
+ rexml (3.2.5)
55
+ rubocop (1.41.1)
56
+ json (~> 2.3)
57
+ parallel (~> 1.10)
58
+ parser (>= 3.1.2.1)
59
+ rainbow (>= 2.2.2, < 4.0)
60
+ regexp_parser (>= 1.8, < 3.0)
61
+ rexml (>= 3.2.5, < 4.0)
62
+ rubocop-ast (>= 1.23.0, < 2.0)
63
+ ruby-progressbar (~> 1.7)
64
+ unicode-display_width (>= 1.4.0, < 3.0)
65
+ rubocop-ast (1.24.0)
66
+ parser (>= 3.1.1.0)
67
+ rubocop-espago (1.0.2)
68
+ rubocop
69
+ ruby-progressbar (1.11.0)
70
+ ruby2_keywords (0.0.5)
71
+ shale (0.9.0)
72
+ shoulda-context (2.0.0)
73
+ solargraph (0.48.0)
74
+ backport (~> 1.2)
75
+ benchmark
76
+ bundler (>= 1.17.2)
77
+ diff-lcs (~> 1.4)
78
+ e2mmap
79
+ jaro_winkler (~> 1.5)
80
+ kramdown (~> 2.3)
81
+ kramdown-parser-gfm (~> 1.1)
82
+ parser (~> 3.0)
83
+ reverse_markdown (>= 1.0.5, < 3)
84
+ rubocop (>= 0.52)
85
+ thor (~> 1.0)
86
+ tilt (~> 2.0)
87
+ yard (~> 0.9, >= 0.9.24)
88
+ strings (0.2.1)
89
+ strings-ansi (~> 0.2)
90
+ unicode-display_width (>= 1.5, < 3.0)
91
+ unicode_utils (~> 1.4)
92
+ strings-ansi (0.2.0)
93
+ thor (1.2.1)
94
+ tilt (2.0.11)
95
+ tty-box (0.7.0)
96
+ pastel (~> 0.8)
97
+ strings (~> 0.2.0)
98
+ tty-cursor (~> 0.7)
99
+ tty-color (0.6.0)
100
+ tty-cursor (0.7.1)
101
+ unicode-display_width (2.3.0)
102
+ unicode_utils (1.4.0)
103
+ vcr (6.1.0)
104
+ webmock (3.18.1)
105
+ addressable (>= 2.8.0)
106
+ crack (>= 0.3.2)
107
+ hashdiff (>= 0.4.0, < 2.0.0)
108
+ webrick (1.7.0)
109
+ yard (0.9.28)
110
+ webrick (~> 1.7.0)
111
+
112
+ PLATFORMS
113
+ arm64-darwin-20
114
+ x86_64-linux
115
+
116
+ DEPENDENCIES
117
+ capistrano-data_plane_api!
118
+ minitest (~> 5.0)
119
+ rake (~> 13.0)
120
+ rubocop (~> 1.21)
121
+ rubocop-espago (~> 1.0)
122
+ shoulda-context (~> 2.0)
123
+ solargraph
124
+ vcr
125
+ webmock
126
+
127
+ BUNDLED WITH
128
+ 2.4.1
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Espago
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,197 @@
1
+ # Capistrano::DataPlaneApi
2
+
3
+ Capistrano plugin which helps you automatically change the admin state of your HAProxy servers.
4
+
5
+ ## Installation
6
+
7
+ ### Gemfile
8
+
9
+ Install the gem and add to the application's Gemfile by executing:
10
+
11
+ ```sh
12
+ $ bundle add capistrano-data_plane_api
13
+ ```
14
+
15
+ Or add it to `Gemfile` manually:
16
+
17
+ ```rb
18
+ gem "capistrano-data_plane_api"
19
+ ```
20
+
21
+ ### Installer
22
+
23
+ Afterwards, you can use the installer to set up your app.
24
+
25
+ We highly recommend it.
26
+
27
+ ```sh
28
+ $ bundle exec cap_data_plane_api install
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ This gem hooks into capistrano to add new tasks which
34
+ enable you to change the admin state of your HAProxy
35
+ servers during the deployment process.
36
+
37
+ We recommend creating separate Capistrano stages
38
+ for every HAProxy server.
39
+
40
+ ## Deployment script
41
+
42
+ The installer generates a handy deployment script which
43
+ let's you deploy your app to all servers in a particular HAProxy
44
+ backend with one command.
45
+
46
+ All admin state switching is handled automatically for you.
47
+ You can go make yourself a coffee without having to worry.
48
+
49
+ It prints a beautiful summary after the deployment.
50
+
51
+ ![Failed Deployment Summary](readme/failed_deployment_summary.png)
52
+
53
+
54
+ It can be invoked like that
55
+
56
+ ```sh
57
+ $ bin/deploy -h
58
+ ```
59
+
60
+ That particular command prints a help message, which is a good
61
+ reference for how to use this script.
62
+
63
+ ```
64
+ Usage: bin/deploy [options]
65
+
66
+ This script can be used to deploy this app to remote servers.
67
+
68
+ -c, --current Deploy from the currently checked out branch
69
+ -t, --test Show the commands that would be executed but do not carry out the deployment
70
+ -g, --group=GROUP Deploy the code to every server in the passed HAProxy backend/group
71
+ --no-haproxy Do not modify the state of any server in HAProxy
72
+ --force-haproxy Ignore the current state of servers in HAProxy
73
+ -o, --only=ONLY Deploy the code only to the passed servers in the same order
74
+ -H, --haproxy-config Show the current HAProxy configuration
75
+ -S, --haproxy-state Show the current HAProxy state
76
+ -T, --tasks Print a list of all available deployment Rake tasks
77
+ -r, --rake=RAKE Carry out a particular Rake task on the server
78
+ -h, --help Prints this help
79
+ -b, --branch=BRANCH Deploy the code from the passed Git branch
80
+ --no-migrations Do not carry out migrations
81
+ ```
82
+
83
+ ### Example of commands
84
+
85
+ #### Show the state of all HAProxy servers and live reload every 2 seconds
86
+
87
+ ```sh
88
+ $ bin/deploy -S
89
+ ```
90
+
91
+ ![HAProxy State](readme/haproxy_state.png)
92
+
93
+ #### Show the current config of this gem
94
+
95
+ ```sh
96
+ $ bin/deploy -H
97
+ ```
98
+
99
+ #### Deploy to all servers in the `staging` backend
100
+
101
+ ```sh
102
+ $ bin/deploy -g staging
103
+ ```
104
+
105
+ #### Deploy to all servers in the `staging` backend using the currently checked out git branch
106
+
107
+ ```sh
108
+ $ bin/deploy -g staging -c
109
+ ```
110
+
111
+ #### Deploy to `staging_serv3` and `staging_serv1` in the `staging` backend (in this order)
112
+
113
+ ```sh
114
+ $ bin/deploy -g staging -o staging_serv3,staging_serv1
115
+ ```
116
+
117
+ #### Deploy to all servers in the `edge` backend using the `development` git branch
118
+
119
+ ```sh
120
+ $ bin/deploy -g edge -b development
121
+ ```
122
+
123
+ #### Deploy to the `staging_serv3` server
124
+
125
+ Same as `cap staging_serv3 deploy`
126
+
127
+ ```sh
128
+ $ bin/deploy staging_serv3
129
+ ```
130
+
131
+ #### Carry out the `deploy:restart` Rake task on all servers in the `production` backend
132
+
133
+ ```sh
134
+ $ bin/deploy -g production -r deploy:restart
135
+ ```
136
+
137
+ ## New Rake tasks
138
+
139
+ There are three new Rake tasks:
140
+
141
+ - `data_plane_api:server:set_drain` -- sets the admin state of the currently deployed server to `DRAIN`
142
+ - `data_plane_api:server:set_maint` -- sets the admin state of the currently deployed server to `MAINT`
143
+ - `data_plane_api:server:set_ready` -- sets the admin state of the currently deployed server to `READY`
144
+
145
+ To load them and and invoke them manually you should
146
+ add this line to your `Capfile`
147
+
148
+ ```rb
149
+ require 'capistrano/data_plane_api'
150
+ ```
151
+
152
+ ## Hooks
153
+
154
+ If you used the installer, your app is already
155
+ set up with hooks.
156
+
157
+ In order to use our recommended configuration of these
158
+ new tasks, you should add the following line to your
159
+ `Capfile`
160
+
161
+ ```rb
162
+ require 'capistrano/data_plane_api/hooks'
163
+ ```
164
+
165
+ Our config works as follows:
166
+
167
+ ```
168
+ deploy
169
+ deploy:starting
170
+ deploy:started
171
+ [after]
172
+ data_plane_api:server:set_drain
173
+ deploy:updating
174
+ deploy:updated
175
+ deploy:publishing
176
+ [before]
177
+ data_plane_api:server:set_maint
178
+ deploy:published
179
+ deploy:finishing
180
+ deploy:finished
181
+ [after]
182
+ data_plane_api:server:set_ready
183
+ ```
184
+
185
+ ## Development
186
+
187
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
188
+
189
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
190
+
191
+ ## Contributing
192
+
193
+ Bug reports and pull requests are welcome on GitHub at https://github.com/espago/capistrano-data_plane_api.
194
+
195
+ ## License
196
+
197
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
5
+
6
+ ::Rake::TestTask.new(:test) do |t|
7
+ t.libs << 'test'
8
+ t.libs << 'lib'
9
+ t.test_files = ::FileList['test/**/*_test.rb']
10
+ end
11
+
12
+ require 'rubocop/rake_task'
13
+
14
+ ::RuboCop::RakeTask.new
15
+
16
+ task default: %i[test rubocop]
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/capistrano/data_plane_api/version'
4
+
5
+ ::Gem::Specification.new do |spec|
6
+ spec.name = 'capistrano-data_plane_api'
7
+ spec.version = ::Capistrano::DataPlaneApi::VERSION
8
+ spec.authors = ['Mateusz Drewniak', 'Espago']
9
+ spec.email = ['m.drewniak@espago.com']
10
+
11
+ spec.summary = 'Capistrano plugin which helps you automatically change the admin state of your HAProxy servers'
12
+ spec.description = 'Capistrano plugin which helps you automatically change the admin state of your HAProxy servers'
13
+ spec.homepage = 'https://github.com/espago/capistrano-data_plane_api'
14
+ spec.license = 'MIT'
15
+ spec.required_ruby_version = '>= 2.7.0'
16
+
17
+ spec.metadata['homepage_uri'] = spec.homepage
18
+ spec.metadata['source_code_uri'] = 'https://github.com/espago/capistrano-data_plane_api'
19
+ # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = ::Dir.chdir(__dir__) do
24
+ `git ls-files -z`.split("\x0").reject do |f|
25
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|circleci)|appveyor)})
26
+ end
27
+ end
28
+ spec.bindir = 'exe'
29
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| ::File.basename(f) }
30
+ spec.require_paths = ['lib']
31
+
32
+ # Uncomment to register a new dependency of your gem
33
+ spec.add_dependency 'data_plane_api', '~> 0.1'
34
+ spec.add_dependency 'pastel', '< 1'
35
+ spec.add_dependency 'shale', '< 1'
36
+ spec.add_dependency 'thor', '> 1', '< 2'
37
+ spec.add_dependency 'tty-box', '< 1'
38
+ spec.add_dependency 'tty-cursor', '< 1'
39
+
40
+ spec.metadata['rubygems_mfa_required'] = 'true'
41
+ end
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'thor'
5
+
6
+ class ::CapistranoDataPlaneApiCommand < ::Thor
7
+ include ::Thor::Actions
8
+
9
+ class << self
10
+ # Define the generator's root folder
11
+ #
12
+ # @return [String]
13
+ def source_root
14
+ ::File.expand_path('..', __dir__)
15
+ end
16
+ end
17
+
18
+ desc 'install', 'Install the `capistrano-data_plane_api` gem in your application'
19
+
20
+ # @return [void]
21
+ def install
22
+ copy_file 'templates/bin/deploy', 'bin/deploy'
23
+ chmod 'bin/deploy', 'a+x'
24
+ copy_file 'templates/bin/deploy.rb', 'bin/deploy.rb'
25
+
26
+ copy_file 'templates/config/data_plane_api.yml', 'config/data_plane_api.yml'
27
+ copy_file 'templates/config/data_plane_api.rb', 'config/data_plane_api.rb'
28
+
29
+ inject_into_file 'Capfile', <<~RUBY, after: %r{require ("|')capistrano/deploy("|')\n}
30
+ require_relative "config/data_plane_api" # load your `capistrano-data_plane_api` config file
31
+ require "capistrano/data_plane_api/hooks"
32
+ RUBY
33
+
34
+ end
35
+ end
36
+
37
+ ::CapistranoDataPlaneApiCommand.start
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'symbol'
4
+ require_relative 'server'
5
+
6
+ module Capistrano
7
+ module DataPlaneApi
8
+ class Configuration < Type
9
+ class Backend < Type
10
+ attribute :name, ::Shale::Type::String
11
+ attribute :styles, Symbol, collection: true
12
+ attribute :basic_user, ::Shale::Type::String
13
+ attribute :basic_password, ::Shale::Type::String
14
+ attribute :servers, Server, collection: true
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Capistrano
4
+ module DataPlaneApi
5
+ class Configuration < Type
6
+ class Server < Type
7
+ attribute :name, ::Shale::Type::String
8
+ attribute :stage, ::Shale::Type::String
9
+
10
+ # @return [String, nil]
11
+ def stage
12
+ @stage || @name
13
+ end
14
+
15
+ # @return [String, nil]
16
+ def name
17
+ @name || @stage
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Capistrano
4
+ module DataPlaneApi
5
+ class Configuration < Type
6
+ class Symbol < ::Shale::Type::String
7
+ class << self
8
+ def cast(value)
9
+ value&.to_sym
10
+ end
11
+ end
12
+
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+ require 'erb'
5
+ require 'logger'
6
+
7
+ require 'shale'
8
+
9
+ require_relative 'type'
10
+
11
+ ::Dir[::File.expand_path('configuration/*.rb', __dir__)].sort.each { require _1 }
12
+
13
+ module Capistrano
14
+ module DataPlaneApi
15
+ # Configuration object of the `capistrano-data_plane_api` gem.
16
+ class Configuration < Type
17
+ attribute :api_url, ::Shale::Type::String
18
+ attribute :logger_level, ::Shale::Type::Integer, default: -> { ::Logger::DEBUG }
19
+ attribute :backends, Backend, collection: true
20
+ attribute :file_path, ::Shale::Type::String
21
+ attribute :basic_user, ::Shale::Type::String
22
+ attribute :basic_password, ::Shale::Type::String
23
+
24
+ class << self
25
+ # @param path [String]
26
+ # @return [self]
27
+ def from_file(path)
28
+ from_yaml ::ERB.new(::File.read(path)).result
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end