balancer 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 +4 -4
- data/.circleci/bin/commit_docs.sh +26 -0
- data/.circleci/config.yml +70 -0
- data/.rspec +1 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +20 -1
- data/README.md +45 -16
- data/balancer.gemspec +3 -0
- data/lib/balancer.rb +15 -1
- data/lib/balancer/aws_service.rb +14 -0
- data/lib/balancer/base.rb +37 -0
- data/lib/balancer/cli.rb +23 -9
- data/lib/balancer/core.rb +26 -0
- data/lib/balancer/create.rb +117 -0
- data/lib/balancer/destroy.rb +51 -0
- data/lib/balancer/help/create.md +5 -0
- data/lib/balancer/help/destroy.md +3 -0
- data/lib/balancer/help/init.md +4 -0
- data/lib/balancer/init.rb +49 -0
- data/lib/balancer/option_transformer.rb +39 -0
- data/lib/balancer/param.rb +43 -0
- data/lib/balancer/profile.rb +65 -0
- data/lib/balancer/security_group.rb +139 -0
- data/lib/balancer/setting.rb +47 -0
- data/lib/balancer/version.rb +1 -1
- data/lib/template/.balancer/profiles/default.yml.tt +21 -0
- data/spec/fixtures/project/.balancer/profiles/default.yml +16 -0
- data/spec/lib/cli_spec.rb +10 -19
- data/spec/lib/option_transformer_spec.rb +27 -0
- data/spec/spec_helper.rb +2 -0
- metadata +66 -5
- data/lib/balancer/help/hello.md +0 -5
- data/lib/balancer/help/sub/goodbye.md +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1432379a1ef4e87892a5a90a1fbc50428156124a52b12a64d259cd05c451b10b
|
4
|
+
data.tar.gz: 469af119bc5fb4093ce3a84b4cf008167dac9f58ec6041b0d11af5efe3d2fc6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94760e1fab90cc6762b8508bdc1e01a93a887c7dee4d5a4c8c7d141a802531465901a7da28ea17b6d40c5834f69acd6689e3fb550cd1babef54c08770738624e
|
7
|
+
data.tar.gz: 8b83a2318937d7ec0ee8110e6a17cd86048722008ef21500fd57a0499adcb1b5a030e1095969babb4e7d233836a5c364e16fd8812ac1f7284c4b9933419ded24
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/bin/bash -eux
|
2
|
+
|
3
|
+
# Even though specs also generate docs, lets run again to ensure clean slate
|
4
|
+
rake docs
|
5
|
+
|
6
|
+
out=$(git status docs)
|
7
|
+
if [[ "$out" = *"nothing to commit"* ]]; then
|
8
|
+
exit
|
9
|
+
fi
|
10
|
+
|
11
|
+
COMMIT_MESSAGE="docs updated by circleci"
|
12
|
+
|
13
|
+
# If the last commit already updated the docs, then exit.
|
14
|
+
# Preventable measure to avoid infinite loop.
|
15
|
+
if git log -1 --pretty=oneline | grep "$COMMIT_MESSAGE" ; then
|
16
|
+
exit
|
17
|
+
fi
|
18
|
+
|
19
|
+
# If reach here, we have some changes on docs that we should commit.
|
20
|
+
# Even though s
|
21
|
+
git add docs
|
22
|
+
git commit -m "$COMMIT_MESSAGE"
|
23
|
+
|
24
|
+
# https://makandracards.com/makandra/12107-git-show-current-branch-name-only
|
25
|
+
current_branch=$(git rev-parse --abbrev-ref HEAD)
|
26
|
+
git push origin "$current_branch"
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# Ruby CircleCI 2.0 configuration file
|
2
|
+
#
|
3
|
+
# Check https://circleci.com/docs/2.0/language-ruby/ for more details
|
4
|
+
#
|
5
|
+
version: 2
|
6
|
+
jobs:
|
7
|
+
build:
|
8
|
+
docker:
|
9
|
+
# specify the version you desire here
|
10
|
+
- image: circleci/ruby:2.5.1-node-browsers
|
11
|
+
|
12
|
+
# Specify service dependencies here if necessary
|
13
|
+
# CircleCI maintains a library of pre-built images
|
14
|
+
# documented at https://circleci.com/docs/2.0/circleci-images/
|
15
|
+
# - image: circleci/postgres:9.4
|
16
|
+
|
17
|
+
working_directory: ~/repo
|
18
|
+
|
19
|
+
steps:
|
20
|
+
- checkout
|
21
|
+
|
22
|
+
- run:
|
23
|
+
name: submodule sync
|
24
|
+
command: |
|
25
|
+
git submodule sync
|
26
|
+
git submodule update --init
|
27
|
+
|
28
|
+
# Download and cache dependencies
|
29
|
+
- restore_cache:
|
30
|
+
keys:
|
31
|
+
- v1-dependencies-{{ checksum "Gemfile" }}
|
32
|
+
# fallback to using the latest cache if no exact match is found
|
33
|
+
- v1-dependencies-
|
34
|
+
|
35
|
+
- run:
|
36
|
+
name: install dependencies
|
37
|
+
command: |
|
38
|
+
bundle install --jobs=4 --retry=3 --path vendor/bundle
|
39
|
+
|
40
|
+
- save_cache:
|
41
|
+
paths:
|
42
|
+
- ./vendor/bundle
|
43
|
+
key: v1-dependencies-{{ checksum "Gemfile" }}
|
44
|
+
|
45
|
+
# specs need git configured ad commit_docs.sh required it also
|
46
|
+
- run:
|
47
|
+
name: configure git
|
48
|
+
command: |
|
49
|
+
git config --global user.email "tongueroo@gmail.com"
|
50
|
+
git config --global user.name "Tung Nguyen"
|
51
|
+
|
52
|
+
# run tests!
|
53
|
+
- run:
|
54
|
+
name: run tests
|
55
|
+
command: |
|
56
|
+
mkdir /tmp/test-results
|
57
|
+
bundle exec rspec
|
58
|
+
|
59
|
+
# - run:
|
60
|
+
# name: commit cli reference docs
|
61
|
+
# command: |
|
62
|
+
# chmod a+x -R .circleci/bin
|
63
|
+
# .circleci/bin/commit_docs.sh
|
64
|
+
|
65
|
+
# collect reports
|
66
|
+
- store_test_results:
|
67
|
+
path: /tmp/test-results
|
68
|
+
- store_artifacts:
|
69
|
+
path: /tmp/test-results
|
70
|
+
destination: test-results
|
data/.rspec
CHANGED
data/CHANGELOG.md
CHANGED
@@ -3,5 +3,10 @@
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
This project *tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
|
5
5
|
|
6
|
+
## [0.2.0]
|
7
|
+
- balancer create command
|
8
|
+
- balancer destroy command
|
9
|
+
- auto create security group that opens up the listener port
|
10
|
+
|
6
11
|
## [0.1.0]
|
7
12
|
- Initial release.
|
data/Gemfile.lock
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
balancer (0.
|
4
|
+
balancer (0.2.0)
|
5
5
|
activesupport
|
6
|
+
aws-sdk-ec2
|
7
|
+
aws-sdk-elasticloadbalancingv2
|
6
8
|
colorize
|
9
|
+
memoist
|
7
10
|
thor
|
8
11
|
|
9
12
|
GEM
|
@@ -14,6 +17,20 @@ GEM
|
|
14
17
|
i18n (>= 0.7, < 2)
|
15
18
|
minitest (~> 5.1)
|
16
19
|
tzinfo (~> 1.1)
|
20
|
+
aws-eventstream (1.0.0)
|
21
|
+
aws-partitions (1.91.0)
|
22
|
+
aws-sdk-core (3.21.2)
|
23
|
+
aws-eventstream (~> 1.0)
|
24
|
+
aws-partitions (~> 1.0)
|
25
|
+
aws-sigv4 (~> 1.0)
|
26
|
+
jmespath (~> 1.0)
|
27
|
+
aws-sdk-ec2 (1.35.0)
|
28
|
+
aws-sdk-core (~> 3)
|
29
|
+
aws-sigv4 (~> 1.0)
|
30
|
+
aws-sdk-elasticloadbalancingv2 (1.10.0)
|
31
|
+
aws-sdk-core (~> 3)
|
32
|
+
aws-sigv4 (~> 1.0)
|
33
|
+
aws-sigv4 (1.0.2)
|
17
34
|
byebug (10.0.0)
|
18
35
|
cli_markdown (0.1.0)
|
19
36
|
codeclimate-test-reporter (1.0.8)
|
@@ -24,7 +41,9 @@ GEM
|
|
24
41
|
docile (1.1.5)
|
25
42
|
i18n (1.0.1)
|
26
43
|
concurrent-ruby (~> 1.0)
|
44
|
+
jmespath (1.4.0)
|
27
45
|
json (2.1.0)
|
46
|
+
memoist (0.16.0)
|
28
47
|
minitest (5.11.3)
|
29
48
|
rake (12.3.0)
|
30
49
|
rspec (3.7.0)
|
data/README.md
CHANGED
@@ -1,32 +1,61 @@
|
|
1
1
|
# Balancer
|
2
2
|
|
3
|
-
[](https://gemnasium.com/USER/REPO)
|
6
|
-
[](https://coveralls.io/r/USER/REPO)
|
7
|
-
[](https://gitter.im/USER/REPO?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
8
|
-
[](https://boltops.com?utm_source=badge&utm_medium=badge&utm_campaign=cli-template)
|
3
|
+
[](https://badge.fury.io/rb/balancer)
|
4
|
+
[](https://circleci.com/gh/tongueroo/balancer)[](https://boltops.com?utm_source=badge&utm_medium=badge&utm_campaign=balancer)
|
9
5
|
|
10
|
-
|
6
|
+
Tool to create ELB load balancers with a target group and listener. It's performs similar steps to this AWS Tutorial: [Create an Application Load Balancer Using the AWS CLI
|
7
|
+
](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/tutorial-application-load-balancer-cli.html)
|
11
8
|
|
12
9
|
## Usage
|
13
10
|
|
14
|
-
|
15
|
-
balancer sub:goodbye yourname
|
11
|
+
Quick start to creating and destroying a load balancer.
|
16
12
|
|
17
|
-
|
13
|
+
cd project
|
14
|
+
balancer init --vpc-id vpc-123 --subnets subnet-123 subnet-456 --security-groups sg-123
|
15
|
+
# edit .balancer/profiles/default.yml to fit your needs
|
16
|
+
balancer create my-elb
|
17
|
+
balancer destroy my-elb
|
18
18
|
|
19
|
-
|
19
|
+
### Profiles
|
20
|
+
|
21
|
+
Balancer has a concept of profiles. Profiles have preconfigured settings like subnets and vpc_id. The params in the profiles are passed to the ruby [aws-sdk](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/ElasticLoadBalancingV2/Client.html) api calls `create_load_balancer`, `create_target_group`, and `create_listener`:
|
22
|
+
|
23
|
+
```yaml
|
24
|
+
---
|
25
|
+
create_load_balancer:
|
26
|
+
subnets: # at least 2 subnets groups required
|
27
|
+
- subnet-123
|
28
|
+
- subnet-345
|
29
|
+
security_groups: # optional thanks to the automatically created security group by balancer
|
30
|
+
- sg-123 # additional security groups to use
|
31
|
+
create_target_group:
|
32
|
+
# vpc_id is required
|
33
|
+
vpc_id: vpc-123
|
34
|
+
# name: ... # automatically named, matches the load balancer name. override here
|
35
|
+
protocol: HTTP # required
|
36
|
+
port: 80 # required
|
37
|
+
create_listener:
|
38
|
+
protocol: HTTP # required
|
39
|
+
port: 80 # required, this is is the port that gets open on the security group
|
40
|
+
```
|
41
|
+
|
42
|
+
### Security Groups
|
20
43
|
|
21
|
-
|
44
|
+
Balancer automatically creates a security group with the same name as the elb and opens up the port configured on the listener. To disable this behavior, use the `--no-security-group` optional. If you use this option, you must specify you own security group in the profile file, since at least 1 security group is required. By default, the security group opens up `0.0.0.0/0`. If you want to override this use `--sg-cdir`, example:
|
22
45
|
|
23
|
-
|
46
|
+
balancer create my-elb --sg-cdir 10.0.0.0/16
|
24
47
|
|
25
|
-
|
48
|
+
When you destroy the ELB like so:
|
26
49
|
|
27
|
-
|
50
|
+
balancer destroy my-elb
|
28
51
|
|
29
|
-
|
52
|
+
Balancer also attempts to destroy the security group if:
|
53
|
+
|
54
|
+
* The security group is tagged with the `balancer=my-elb` tag. Balancer automatically adds this tag when creating the ELB.
|
55
|
+
* There are no dependencies on the security group. If there are dependencies the ELB is deleted but the security group is left behind for you to clean up.
|
56
|
+
|
57
|
+
|
58
|
+
## Installation
|
30
59
|
|
31
60
|
gem install balancer
|
32
61
|
|
data/balancer.gemspec
CHANGED
@@ -19,7 +19,10 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_dependency "activesupport"
|
22
|
+
spec.add_dependency "aws-sdk-ec2"
|
23
|
+
spec.add_dependency "aws-sdk-elasticloadbalancingv2"
|
22
24
|
spec.add_dependency "colorize"
|
25
|
+
spec.add_dependency "memoist"
|
23
26
|
spec.add_dependency "thor"
|
24
27
|
|
25
28
|
spec.add_development_dependency "bundler"
|
data/lib/balancer.rb
CHANGED
@@ -1,11 +1,25 @@
|
|
1
1
|
$:.unshift(File.expand_path("../", __FILE__))
|
2
2
|
require "balancer/version"
|
3
|
+
require "colorize"
|
4
|
+
require "memoist"
|
3
5
|
|
4
6
|
module Balancer
|
7
|
+
autoload :AwsService, "balancer/aws_service"
|
5
8
|
autoload :Help, "balancer/help"
|
9
|
+
autoload :Setting, "balancer/setting"
|
10
|
+
autoload :Base, "balancer/base"
|
11
|
+
autoload :Profile, "balancer/profile"
|
12
|
+
autoload :Init, "balancer/init"
|
13
|
+
autoload :Core, "balancer/core"
|
6
14
|
autoload :Command, "balancer/command"
|
7
15
|
autoload :CLI, "balancer/cli"
|
8
|
-
autoload :
|
16
|
+
autoload :Create, "balancer/create"
|
9
17
|
autoload :Completion, "balancer/completion"
|
10
18
|
autoload :Completer, "balancer/completer"
|
19
|
+
autoload :Destroy, "balancer/destroy"
|
20
|
+
autoload :Param, "balancer/param"
|
21
|
+
autoload :OptionTransformer, "balancer/option_transformer"
|
22
|
+
autoload :SecurityGroup, "balancer/security_group"
|
23
|
+
|
24
|
+
extend Core
|
11
25
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Balancer
|
2
|
+
class Base
|
3
|
+
def initialize(options={})
|
4
|
+
@options = options.clone
|
5
|
+
@name = randomize(@options[:name])
|
6
|
+
Balancer.validate_in_project!
|
7
|
+
end
|
8
|
+
|
9
|
+
# Appends a short random string at the end of the ec2 instance name.
|
10
|
+
# Later we will strip this same random string from the name.
|
11
|
+
# Very makes it convenient. We can just type:
|
12
|
+
#
|
13
|
+
# balancer create server --randomize
|
14
|
+
#
|
15
|
+
# instead of:
|
16
|
+
#
|
17
|
+
# balancer create server-123 --profile server
|
18
|
+
#
|
19
|
+
def randomize(name)
|
20
|
+
if @options[:randomize]
|
21
|
+
random = (0...3).map { (65 + rand(26)).chr }.join.downcase # Ex: jhx
|
22
|
+
[name, random].join('-')
|
23
|
+
else
|
24
|
+
name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Strip the random string at end of the ec2 instance name
|
29
|
+
def derandomize(name)
|
30
|
+
if @options[:randomize]
|
31
|
+
name.sub(/-(\w{3})$/,'') # strip the random part at the end
|
32
|
+
else
|
33
|
+
name
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/balancer/cli.rb
CHANGED
@@ -3,17 +3,31 @@ module Balancer
|
|
3
3
|
class_option :verbose, type: :boolean
|
4
4
|
class_option :noop, type: :boolean
|
5
5
|
|
6
|
-
desc "
|
7
|
-
long_desc Help.text(:
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
desc "create NAME", "Create Load Balancer."
|
7
|
+
long_desc Help.text(:create)
|
8
|
+
# create_load_balancer options
|
9
|
+
option :subnets, type: :array, desc: "Subnets"
|
10
|
+
option :security_groups, type: :array, desc: "Security groups"
|
11
|
+
# create_target_group options
|
12
|
+
option :vpc_id, type: :array, desc: "Vpc id"
|
13
|
+
option :target_group_name, desc: "Target group name"
|
14
|
+
# security_group options
|
15
|
+
option :sg_cidr, default: "0.0.0.0/0", desc: "Security group cidr range"
|
16
|
+
def create(name)
|
17
|
+
Create.new(options.merge(name: name)).run
|
12
18
|
end
|
13
19
|
|
14
|
-
desc "
|
15
|
-
long_desc Help.text(:
|
16
|
-
|
20
|
+
desc "destroy NAME", "Destroy Load Balancer and associated target group."
|
21
|
+
long_desc Help.text(:destroy)
|
22
|
+
def destroy(name)
|
23
|
+
Destroy.new(options.merge(name: name)).run
|
24
|
+
end
|
25
|
+
|
26
|
+
long_desc Help.text(:init)
|
27
|
+
Init.cli_options.each do |args|
|
28
|
+
option *args
|
29
|
+
end
|
30
|
+
register(Init, "init", "init", "Sets up balancer for project")
|
17
31
|
|
18
32
|
desc "completion *PARAMS", "Prints words for auto-completion."
|
19
33
|
long_desc Help.text("completion")
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Balancer
|
5
|
+
module Core
|
6
|
+
def root
|
7
|
+
path = ENV['BALANCER_ROOT'] || '.'
|
8
|
+
Pathname.new(path)
|
9
|
+
end
|
10
|
+
|
11
|
+
def profile
|
12
|
+
ENV['BALANCER_PROFILE'] || 'default'
|
13
|
+
end
|
14
|
+
|
15
|
+
def settings
|
16
|
+
Setting.new.data
|
17
|
+
end
|
18
|
+
|
19
|
+
def validate_in_project!
|
20
|
+
unless File.exist?("#{root}/.balancer")
|
21
|
+
puts "Could not find a .balancer folder in the current directory. It does not look like you are running this command within a balancer project. Please confirm that you are in a balancer project and try again.".colorize(:red)
|
22
|
+
exit
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Balancer
|
4
|
+
class Create
|
5
|
+
extend Memoist
|
6
|
+
include AwsService
|
7
|
+
include SecurityGroup
|
8
|
+
|
9
|
+
def initialize(options)
|
10
|
+
@options = options
|
11
|
+
@name = options[:name]
|
12
|
+
end
|
13
|
+
|
14
|
+
# https://docs.aws.amazon.com/elasticloadbalancing/latest/application/tutorial-application-load-balancer-cli.html
|
15
|
+
def run
|
16
|
+
if ENV['TEST'] # ghetto way to for sanity cli specs
|
17
|
+
puts "Creating load balancer"
|
18
|
+
return
|
19
|
+
end
|
20
|
+
|
21
|
+
if elb_exists?
|
22
|
+
puts "Load balancer #{@name} already exists"
|
23
|
+
return
|
24
|
+
end
|
25
|
+
|
26
|
+
@security_group_id = create_security_group
|
27
|
+
create_elb
|
28
|
+
create_target_group
|
29
|
+
create_listener
|
30
|
+
end
|
31
|
+
|
32
|
+
def elb_exists?
|
33
|
+
begin
|
34
|
+
resp = elb.describe_load_balancers(names: [@name])
|
35
|
+
true
|
36
|
+
rescue Aws::ElasticLoadBalancingV2::Errors::LoadBalancerNotFound
|
37
|
+
false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_elb
|
42
|
+
puts "Creating load balancer with params:"
|
43
|
+
params = param.create_load_balancer
|
44
|
+
params[:security_groups] ||= []
|
45
|
+
params[:security_groups] += [@security_group_id]
|
46
|
+
params[:security_groups] = params[:security_groups].uniq
|
47
|
+
pretty_display(params)
|
48
|
+
aws_cli_command("aws elbv2 create-load-balancer", params)
|
49
|
+
return if @options[:noop]
|
50
|
+
|
51
|
+
begin
|
52
|
+
resp = elb.create_load_balancer(params)
|
53
|
+
rescue Exception => e
|
54
|
+
puts "ERROR: #{e.class}: #{e.message}".colorize(:red)
|
55
|
+
exit 1
|
56
|
+
end
|
57
|
+
|
58
|
+
elb = resp.load_balancers.first
|
59
|
+
puts "Load balancer created: #{elb.load_balancer_arn}"
|
60
|
+
@load_balancer_arn = elb.load_balancer_arn # used later
|
61
|
+
puts
|
62
|
+
end
|
63
|
+
|
64
|
+
def create_target_group
|
65
|
+
puts "Creating target group with params:"
|
66
|
+
params = param.create_target_group
|
67
|
+
pretty_display(params)
|
68
|
+
aws_cli_command("aws elbv2 create-target-group", params)
|
69
|
+
|
70
|
+
begin
|
71
|
+
resp = elb.create_target_group(params)
|
72
|
+
rescue Exception => e
|
73
|
+
puts "ERROR: #{e.class}: #{e.message}".colorize(:red)
|
74
|
+
exit 1
|
75
|
+
end
|
76
|
+
target_group = resp.target_groups.first
|
77
|
+
puts "Target group created: #{target_group.target_group_arn}"
|
78
|
+
@target_group_arn = target_group.target_group_arn # used later
|
79
|
+
add_tags(@target_group_arn)
|
80
|
+
puts
|
81
|
+
end
|
82
|
+
|
83
|
+
def create_listener
|
84
|
+
puts "Creating listener with params:"
|
85
|
+
params = param.create_listener
|
86
|
+
params.merge!(
|
87
|
+
load_balancer_arn: @load_balancer_arn,
|
88
|
+
default_actions: [{type: "forward", target_group_arn: @target_group_arn}]
|
89
|
+
)
|
90
|
+
pretty_display(params)
|
91
|
+
aws_cli_command("aws elbv2 create-listener", params)
|
92
|
+
|
93
|
+
resp = run_with_error_handling do
|
94
|
+
elb.create_listener(params)
|
95
|
+
end
|
96
|
+
listener = resp.listeners.first
|
97
|
+
puts "Listener created: #{listener.listener_arn}"
|
98
|
+
puts
|
99
|
+
end
|
100
|
+
|
101
|
+
def run_with_error_handling
|
102
|
+
yield
|
103
|
+
rescue Exception => e
|
104
|
+
puts "ERROR: #{e.class}: #{e.message}".colorize(:red)
|
105
|
+
exit 1
|
106
|
+
end
|
107
|
+
|
108
|
+
def add_tags(arn)
|
109
|
+
params = {
|
110
|
+
resource_arns: [arn],
|
111
|
+
tags: [{ key: "balancer", value: @name }]
|
112
|
+
}
|
113
|
+
aws_cli_command("aws elbv2 add-tags", params)
|
114
|
+
elb.add_tags(params)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Balancer
|
2
|
+
class Destroy
|
3
|
+
extend Memoist
|
4
|
+
include AwsService
|
5
|
+
include SecurityGroup
|
6
|
+
|
7
|
+
def initialize(options)
|
8
|
+
@options = options
|
9
|
+
@name = options[:name]
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
puts "Destroying ELB and target groups associated with: #{@name}"
|
14
|
+
return if @options[:noop]
|
15
|
+
|
16
|
+
begin
|
17
|
+
resp = elb.describe_load_balancers(names: [@name])
|
18
|
+
rescue Aws::ElasticLoadBalancingV2::Errors::LoadBalancerNotFound
|
19
|
+
puts "Load balancer '#{@name}' not found. Exiting.".colorize(:red)
|
20
|
+
exit 1
|
21
|
+
end
|
22
|
+
|
23
|
+
load_balancer = resp.load_balancers.first
|
24
|
+
|
25
|
+
# Must load resources to be deleted into memory to delete them later since there
|
26
|
+
# are dependencies and they won't be available to query after deleting some of the
|
27
|
+
# resources.
|
28
|
+
resp = elb.describe_listeners(load_balancer_arn: load_balancer.load_balancer_arn)
|
29
|
+
listeners = resp.listeners
|
30
|
+
resp = elb.describe_target_groups(load_balancer_arn: load_balancer.load_balancer_arn)
|
31
|
+
groups = resp.target_groups
|
32
|
+
|
33
|
+
listeners.each do |listener|
|
34
|
+
elb.delete_listener(listener_arn: listener.listener_arn)
|
35
|
+
puts "Deleted listener: #{listener.listener_arn}"
|
36
|
+
end
|
37
|
+
|
38
|
+
groups.each do |group|
|
39
|
+
elb.delete_target_group(target_group_arn: group.target_group_arn)
|
40
|
+
puts "Deleted target group: #{group.target_group_arn}"
|
41
|
+
end
|
42
|
+
|
43
|
+
resp = elb.delete_load_balancer(
|
44
|
+
load_balancer_arn: load_balancer.load_balancer_arn,
|
45
|
+
)
|
46
|
+
puts "Deleted load balancer: #{load_balancer.load_balancer_arn}"
|
47
|
+
|
48
|
+
destroy_security_group
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'colorize'
|
3
|
+
require 'active_support/core_ext/string'
|
4
|
+
require 'thor'
|
5
|
+
require 'bundler'
|
6
|
+
|
7
|
+
module Balancer
|
8
|
+
class Init < Thor::Group
|
9
|
+
include Thor::Actions
|
10
|
+
|
11
|
+
# Ugly, but when the class_option is only defined in the Thor::Group class
|
12
|
+
# it doesnt show up with cli-template new help :(
|
13
|
+
# If anyone knows how to fix this let me know.
|
14
|
+
# Also options from the cli can be pass through to here
|
15
|
+
def self.cli_options
|
16
|
+
[
|
17
|
+
[:force, type: :boolean, desc: "Bypass overwrite are you sure prompt for existing files."],
|
18
|
+
[:git, type: :boolean, default: true, desc: "Git initialize the project"],
|
19
|
+
[:subnets, type: :array, default: ["REPLACE_ME"], desc: "Subnets"],
|
20
|
+
[:security_groups, type: :array, default: ["REPLACE_ME"], desc: "Security groups"],
|
21
|
+
[:vpc_id, default: "REPLACE_ME", desc: "Vpc id"],
|
22
|
+
]
|
23
|
+
end
|
24
|
+
|
25
|
+
cli_options.each do |args|
|
26
|
+
class_option *args
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.source_root
|
30
|
+
File.expand_path("../template", File.dirname(__FILE__))
|
31
|
+
end
|
32
|
+
|
33
|
+
def init_project
|
34
|
+
puts "Setting up balancer files."
|
35
|
+
directory ".", "."
|
36
|
+
end
|
37
|
+
|
38
|
+
def user_message
|
39
|
+
puts <<-EOL
|
40
|
+
#{"="*64}
|
41
|
+
Congrats 🎉 Balancer starter files succesfully created.
|
42
|
+
|
43
|
+
Check out .balancer/profiles/default.yml make make sure the settings like subnets and vpc_id are okay. Then run `balanace create` to to create an ELB, Target Group and listener. Example:
|
44
|
+
|
45
|
+
balancer create my-elb
|
46
|
+
EOL
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'active_support/core_ext/string'
|
2
|
+
require 'active_support/core_ext/hash'
|
3
|
+
|
4
|
+
module Balancer
|
5
|
+
class OptionTransformer
|
6
|
+
def to_cli(options)
|
7
|
+
params = []
|
8
|
+
options.each do |k,v|
|
9
|
+
case v
|
10
|
+
when Symbol, String, Integer
|
11
|
+
params << key_to_cli_option(k) + ' ' + v.to_s
|
12
|
+
when Array
|
13
|
+
values = []
|
14
|
+
v.each do |o|
|
15
|
+
if o.is_a?(Hash)
|
16
|
+
o.each do |x,y|
|
17
|
+
values << "#{x.to_s.camelize}=#{y}"
|
18
|
+
end
|
19
|
+
else # assume string
|
20
|
+
values << o
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
list = v.first.is_a?(Hash) ? values.join(',') : values.join(' ')
|
25
|
+
params << key_to_cli_option(k) + ' ' + list
|
26
|
+
else
|
27
|
+
puts "v.class: #{v.class.inspect}"
|
28
|
+
raise "the roof"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
params.join(' ')
|
32
|
+
end
|
33
|
+
|
34
|
+
# resource_arns => --resource-arns
|
35
|
+
def key_to_cli_option(key)
|
36
|
+
'--' + key.to_s.gsub('_','-')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'active_support/core_ext/hash'
|
2
|
+
|
3
|
+
module Balancer
|
4
|
+
class Param
|
5
|
+
extend Memoist
|
6
|
+
|
7
|
+
def initialize(options)
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def create_load_balancer
|
12
|
+
params = settings["create_load_balancer"].deep_symbolize_keys
|
13
|
+
params = merge_option(params, :name)
|
14
|
+
params = merge_option(params, :subnets)
|
15
|
+
params = merge_option(params, :security_groups)
|
16
|
+
params[:tags] = [{ key: "balancer", value: "balancer" }]
|
17
|
+
params
|
18
|
+
end
|
19
|
+
memoize :create_load_balancer
|
20
|
+
|
21
|
+
def create_target_group
|
22
|
+
params = settings["create_target_group"].deep_symbolize_keys
|
23
|
+
params[:name] ||= @options[:name] if @options[:name] # settings take precedence
|
24
|
+
params = merge_option(params, :vpc_id)
|
25
|
+
params
|
26
|
+
end
|
27
|
+
memoize :create_target_group
|
28
|
+
|
29
|
+
def create_listener
|
30
|
+
settings["create_listener"].deep_symbolize_keys
|
31
|
+
end
|
32
|
+
memoize :create_listener
|
33
|
+
|
34
|
+
def merge_option(params, option_key)
|
35
|
+
params[option_key] = @options[option_key] if @options[option_key]
|
36
|
+
params
|
37
|
+
end
|
38
|
+
|
39
|
+
def settings
|
40
|
+
@settings ||= Balancer.settings
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Balancer
|
2
|
+
class Profile < Base
|
3
|
+
include Balancer::Template
|
4
|
+
|
5
|
+
def load
|
6
|
+
return @profile_params if @profile_params
|
7
|
+
|
8
|
+
check!
|
9
|
+
|
10
|
+
file = profile_file(profile_name)
|
11
|
+
@profile_params = load_profile(file)
|
12
|
+
end
|
13
|
+
|
14
|
+
def check!
|
15
|
+
file = profile_file(profile_name)
|
16
|
+
return if File.exist?(file)
|
17
|
+
|
18
|
+
puts "Unable to find a #{file.colorize(:green)} profile file."
|
19
|
+
puts "Please double check that it exists or that you specified the right profile.".colorize(:red)
|
20
|
+
exit 1
|
21
|
+
end
|
22
|
+
|
23
|
+
def load_profile(file)
|
24
|
+
return {} unless File.exist?(file)
|
25
|
+
|
26
|
+
puts "Using profile: #{file}".colorize(:green)
|
27
|
+
text = RenderMePretty.result(file, context: context)
|
28
|
+
begin
|
29
|
+
data = YAML.load(text)
|
30
|
+
rescue Psych::SyntaxError => e
|
31
|
+
tmp_file = file.sub(".balancer", "tmp")
|
32
|
+
FileUtils.mkdir_p(File.dirname(tmp_file))
|
33
|
+
IO.write(tmp_file, text)
|
34
|
+
puts "There was an error evaluating in your yaml file #{file}".colorize(:red)
|
35
|
+
puts "The evaludated yaml file has been saved at #{tmp_file} for debugging."
|
36
|
+
puts "ERROR: #{e.message}"
|
37
|
+
exit 1
|
38
|
+
end
|
39
|
+
data ? data : {} # in case the file is empty
|
40
|
+
data.has_key?("create_load_balancer") ? data["create_load_balancer"] : data
|
41
|
+
end
|
42
|
+
|
43
|
+
# Determines a valid profile_name. Falls back to default
|
44
|
+
def profile_name
|
45
|
+
# allow user to specify the path also
|
46
|
+
if @options[:profile] && File.exist?(@options[:profile])
|
47
|
+
filename_profile = File.basename(@options[:profile], '.yml')
|
48
|
+
end
|
49
|
+
|
50
|
+
name = derandomize(@name)
|
51
|
+
if File.exist?(profile_file(name))
|
52
|
+
name_profile = name
|
53
|
+
end
|
54
|
+
|
55
|
+
filename_profile ||
|
56
|
+
@options[:profile] ||
|
57
|
+
name_profile || # conventional profile is the name of the elb
|
58
|
+
"default"
|
59
|
+
end
|
60
|
+
|
61
|
+
def profile_file(name)
|
62
|
+
"#{Balancer.root}/.balancer/#{name}.yml"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
module Balancer
|
2
|
+
module SecurityGroup
|
3
|
+
extend Memoist
|
4
|
+
|
5
|
+
def create_security_group
|
6
|
+
sg = find_security_group(@name)
|
7
|
+
group_id = sg.group_id if sg
|
8
|
+
|
9
|
+
unless group_id
|
10
|
+
puts "Creating security group #{@name} in vpc #{sg_vpc_id}"
|
11
|
+
params = {group_name: @name, description: @name, vpc_id: sg_vpc_id}
|
12
|
+
aws_cli_command("aws ec2 create-security-group", params)
|
13
|
+
begin
|
14
|
+
resp = ec2.create_security_group(params)
|
15
|
+
rescue Aws::EC2::Errors::InvalidVpcIDNotFound => e
|
16
|
+
puts "ERROR: #{e.class} #{e.message}".colorize(:red)
|
17
|
+
exit 1
|
18
|
+
end
|
19
|
+
group_id = resp.group_id
|
20
|
+
puts "Created security group: #{group_id}"
|
21
|
+
end
|
22
|
+
|
23
|
+
authorize_elb_port(group_id)
|
24
|
+
|
25
|
+
ec2.create_tags(resources: [group_id], tags: [{
|
26
|
+
key: "Name",
|
27
|
+
value: @name
|
28
|
+
},
|
29
|
+
key: "balancer",
|
30
|
+
value: @name
|
31
|
+
])
|
32
|
+
|
33
|
+
group_id
|
34
|
+
end
|
35
|
+
|
36
|
+
def authorize_elb_port(group_id)
|
37
|
+
resp = ec2.describe_security_groups(group_ids: [group_id])
|
38
|
+
sg = resp.security_groups.first
|
39
|
+
|
40
|
+
already_authorized = sg.ip_permissions.find do |perm|
|
41
|
+
perm.from_port == 80 &&
|
42
|
+
perm.to_port == 80
|
43
|
+
perm.ip_ranges.find { |ip_range| ip_range.cidr_ip == @options[:sg_cidr] }
|
44
|
+
end
|
45
|
+
if already_authorized
|
46
|
+
return
|
47
|
+
end
|
48
|
+
|
49
|
+
listener_port = param.create_listener[:port]
|
50
|
+
|
51
|
+
# authorize the matching port in the create_listener setting
|
52
|
+
params = {group_id: group_id, protocol: "tcp", port: listener_port, cidr: @options[:sg_cidr]}
|
53
|
+
puts "Authorizing listening port for security group"
|
54
|
+
aws_cli_command("aws ec2 authorize-security-group-ingress", params)
|
55
|
+
ec2.authorize_security_group_ingress(
|
56
|
+
group_id: params[:group_id],
|
57
|
+
ip_permissions: [
|
58
|
+
from_port: listener_port,
|
59
|
+
to_port: listener_port,
|
60
|
+
ip_protocol: "tcp",
|
61
|
+
ip_ranges: [
|
62
|
+
cidr_ip: @options[:sg_cidr],
|
63
|
+
description: "balancer #{@name}"
|
64
|
+
]
|
65
|
+
]
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
def destroy_security_group
|
70
|
+
sg = find_security_group(@name)
|
71
|
+
return unless sg
|
72
|
+
|
73
|
+
balancer_tag = sg.tags.find { |t| t.key == "balancer" && t.value == @name }
|
74
|
+
unless balancer_tag
|
75
|
+
puts "WARN: not destroying the #{@name} security group because it doesn't have a matching balancer tag".colorize(:yellow)
|
76
|
+
return
|
77
|
+
end
|
78
|
+
|
79
|
+
puts "Deleting security group #{@name} in vpc #{sg_vpc_id}"
|
80
|
+
params = {group_id: sg.group_id}
|
81
|
+
aws_cli_command("aws ec2 delete-security-group", params)
|
82
|
+
|
83
|
+
tries = 0
|
84
|
+
begin
|
85
|
+
ec2.delete_security_group(params)
|
86
|
+
puts "Deleted security group: #{sg.group_id}"
|
87
|
+
rescue Aws::EC2::Errors::DependencyViolation => e
|
88
|
+
sleep 2**tries
|
89
|
+
tries += 1
|
90
|
+
if tries <= 4
|
91
|
+
# retry because it takes some time for the load balancer to be deleted
|
92
|
+
# and that can cause a DependencyViolation exception
|
93
|
+
retry
|
94
|
+
else
|
95
|
+
puts "WARN: #{e.class} #{e.message}".colorize(:yellow)
|
96
|
+
puts "Unable to delete the security group because it's still in use by another resource. Leaving the security group."
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Use security group that is set in the profile under create_target_group
|
102
|
+
def sg_vpc_id
|
103
|
+
param.create_target_group[:vpc_id]
|
104
|
+
end
|
105
|
+
memoize :sg_vpc_id
|
106
|
+
|
107
|
+
def find_security_group(name)
|
108
|
+
resp = ec2.describe_security_groups(filters: [
|
109
|
+
{name: "group-name", values: ["my-elb"]},
|
110
|
+
{name: "vpc-id", values: [sg_vpc_id]},
|
111
|
+
])
|
112
|
+
resp.security_groups.first
|
113
|
+
end
|
114
|
+
memoize :find_security_group
|
115
|
+
|
116
|
+
# Few other common methods also included here
|
117
|
+
|
118
|
+
def param
|
119
|
+
Param.new(@options)
|
120
|
+
end
|
121
|
+
memoize :param
|
122
|
+
|
123
|
+
def pretty_display(data)
|
124
|
+
data = data.deep_stringify_keys
|
125
|
+
puts YAML.dump(data)
|
126
|
+
end
|
127
|
+
|
128
|
+
def option_transformer
|
129
|
+
Balancer::OptionTransformer.new
|
130
|
+
end
|
131
|
+
memoize :option_transformer
|
132
|
+
|
133
|
+
def aws_cli_command(aws_command, params)
|
134
|
+
# puts "Equivalent aws cli command:"
|
135
|
+
cli_options = option_transformer.to_cli(params)
|
136
|
+
puts " #{aws_command} #{cli_options}".colorize(:light_blue)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'active_support/core_ext/hash'
|
3
|
+
|
4
|
+
module Balancer
|
5
|
+
class Setting
|
6
|
+
extend Memoist
|
7
|
+
|
8
|
+
def data
|
9
|
+
settings_file = Balancer.profile || 'default'
|
10
|
+
settings_file += ".yml"
|
11
|
+
|
12
|
+
profile = yaml_file("#{Balancer.root}/.balancer/profiles/#{settings_file}")
|
13
|
+
user = yaml_file("#{home}/.balancer/#{settings_file}")
|
14
|
+
default_file = File.expand_path("../default/settings.yml", __FILE__)
|
15
|
+
default = yaml_file(default_file)
|
16
|
+
|
17
|
+
data = merge(default, user, profile)
|
18
|
+
|
19
|
+
if ENV['DEBUG_SETTINGS']
|
20
|
+
puts "settings data:"
|
21
|
+
pp data
|
22
|
+
end
|
23
|
+
data
|
24
|
+
end
|
25
|
+
memoize :data
|
26
|
+
|
27
|
+
def merge(*hashes)
|
28
|
+
hashes.inject({}) do |result, hash|
|
29
|
+
# note: important to compact for keys with nil value
|
30
|
+
result.deep_merge(hash.compact)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Any empty file will result in "false". Lets ensure that an empty file
|
35
|
+
# loads an empty hash instead.
|
36
|
+
def yaml_file(path)
|
37
|
+
# puts "yaml_file #{path}"
|
38
|
+
return {} unless File.exist?(path)
|
39
|
+
YAML.load_file(path) || {}
|
40
|
+
end
|
41
|
+
|
42
|
+
def home
|
43
|
+
# hack but fast
|
44
|
+
ENV['TEST'] ? "spec/fixtures/home" : ENV['HOME']
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/balancer/version.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
---
|
2
|
+
# https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/ElasticLoadBalancingV2/Client.html
|
3
|
+
# The keys correspond to methods called in the aws-sdk
|
4
|
+
create_load_balancer:
|
5
|
+
subnets: # at least 2 subnets required
|
6
|
+
<% options[:subnets].each do |subnet| -%>
|
7
|
+
- <%= subnet %>
|
8
|
+
<% end -%>
|
9
|
+
security_groups: # optional thanks to the automatically created security
|
10
|
+
<% options[:security_groups].each do |security_group| -%>
|
11
|
+
- <%= security_group %>
|
12
|
+
<% end -%>
|
13
|
+
create_target_group:
|
14
|
+
# vpc_id is required
|
15
|
+
vpc_id: <%= options[:vpc_id] %>
|
16
|
+
# name: ... # automatically named, matches the load balancer name. override here
|
17
|
+
protocol: HTTP # required
|
18
|
+
port: 80 # required
|
19
|
+
create_listener:
|
20
|
+
protocol: HTTP # required
|
21
|
+
port: 80 # required
|
@@ -0,0 +1,16 @@
|
|
1
|
+
---
|
2
|
+
create_load_balancer:
|
3
|
+
subnets: # required
|
4
|
+
- subnet-aaa
|
5
|
+
- subnet-bbb
|
6
|
+
security_groups: # required
|
7
|
+
- sg-123
|
8
|
+
create_target_group:
|
9
|
+
# vpc_id is required
|
10
|
+
vpc_id: vpc-123
|
11
|
+
# name: ... # automatically named, matches the load balancer name. override here
|
12
|
+
protocol: HTTP # required
|
13
|
+
port: 80 # required
|
14
|
+
create_listener:
|
15
|
+
protocol: HTTP # required
|
16
|
+
port: 80 # required
|
data/spec/lib/cli_spec.rb
CHANGED
@@ -1,32 +1,23 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
1
|
describe Balancer::CLI do
|
4
2
|
before(:all) do
|
5
|
-
@args = "--
|
3
|
+
@args = "--noop"
|
6
4
|
end
|
7
5
|
|
8
6
|
describe "balancer" do
|
9
|
-
it "
|
10
|
-
out = execute("exe/balancer
|
11
|
-
expect(out).to include("
|
7
|
+
it "create" do
|
8
|
+
out = execute("exe/balancer create my-elb #{@args}")
|
9
|
+
expect(out).to include("Creating load balancer")
|
12
10
|
end
|
13
11
|
|
14
|
-
it "
|
15
|
-
out = execute("exe/balancer
|
16
|
-
expect(out).to include("
|
12
|
+
it "destroy" do
|
13
|
+
out = execute("exe/balancer destroy my-elb #{@args}")
|
14
|
+
expect(out).to include("Destroying ELB")
|
17
15
|
end
|
18
16
|
|
19
17
|
commands = {
|
20
|
-
"
|
21
|
-
"
|
22
|
-
"
|
23
|
-
"hello name" => "--from",
|
24
|
-
"hello name --" => "--from",
|
25
|
-
"sub goodb" => "goodbye",
|
26
|
-
"sub goodbye" => "name",
|
27
|
-
"sub goodbye name" => "--from",
|
28
|
-
"sub goodbye name --" => "--from",
|
29
|
-
"sub goodbye name --from" => "--help",
|
18
|
+
"crea" => "create",
|
19
|
+
"create" => "name",
|
20
|
+
"dest" => "destroy",
|
30
21
|
}
|
31
22
|
commands.each do |command, expected_word|
|
32
23
|
it "completion #{command}" do
|
@@ -0,0 +1,27 @@
|
|
1
|
+
describe Balancer::OptionTransformer do
|
2
|
+
let(:create) { Balancer::OptionTransformer.new }
|
3
|
+
|
4
|
+
context '#to_cli' do
|
5
|
+
it "target group" do
|
6
|
+
options = {
|
7
|
+
port: 80,
|
8
|
+
protocol: "HTTP",
|
9
|
+
load_balancer_arn: "load_balancer_arn",
|
10
|
+
default_actions: [{type: "forward", target_group_arn: "target_group_arn"}],
|
11
|
+
}
|
12
|
+
text = create.to_cli(options)
|
13
|
+
# puts text
|
14
|
+
expect(text).to eq "--port 80 --protocol HTTP --load-balancer-arn load_balancer_arn --default-actions Type=forward,TargetGroupArn=target_group_arn"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "tags" do
|
18
|
+
options = {
|
19
|
+
resource_arns: %w[arn1 arn2],
|
20
|
+
tags: [{ key: "balancer", value: "test-elb" }]
|
21
|
+
}
|
22
|
+
text = create.to_cli(options)
|
23
|
+
# puts text
|
24
|
+
expect(text).to eq "--resource-arns arn1 arn2 --tags Key=balancer,Value=test-elb"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: balancer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tung Nguyen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-06-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -24,6 +24,34 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: aws-sdk-ec2
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: aws-sdk-elasticloadbalancingv2
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
27
55
|
- !ruby/object:Gem::Dependency
|
28
56
|
name: colorize
|
29
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,6 +66,20 @@ dependencies:
|
|
38
66
|
- - ">="
|
39
67
|
- !ruby/object:Gem::Version
|
40
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: memoist
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
41
83
|
- !ruby/object:Gem::Dependency
|
42
84
|
name: thor
|
43
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -130,6 +172,8 @@ executables:
|
|
130
172
|
extensions: []
|
131
173
|
extra_rdoc_files: []
|
132
174
|
files:
|
175
|
+
- ".circleci/bin/commit_docs.sh"
|
176
|
+
- ".circleci/config.yml"
|
133
177
|
- ".gitignore"
|
134
178
|
- ".rspec"
|
135
179
|
- CHANGELOG.md
|
@@ -142,19 +186,34 @@ files:
|
|
142
186
|
- balancer.gemspec
|
143
187
|
- exe/balancer
|
144
188
|
- lib/balancer.rb
|
189
|
+
- lib/balancer/aws_service.rb
|
190
|
+
- lib/balancer/base.rb
|
145
191
|
- lib/balancer/cli.rb
|
146
192
|
- lib/balancer/command.rb
|
147
193
|
- lib/balancer/completer.rb
|
148
194
|
- lib/balancer/completer/script.rb
|
149
195
|
- lib/balancer/completer/script.sh
|
196
|
+
- lib/balancer/core.rb
|
197
|
+
- lib/balancer/create.rb
|
198
|
+
- lib/balancer/destroy.rb
|
150
199
|
- lib/balancer/help.rb
|
151
200
|
- lib/balancer/help/completion.md
|
152
201
|
- lib/balancer/help/completion_script.md
|
153
|
-
- lib/balancer/help/
|
154
|
-
- lib/balancer/help/
|
202
|
+
- lib/balancer/help/create.md
|
203
|
+
- lib/balancer/help/destroy.md
|
204
|
+
- lib/balancer/help/init.md
|
205
|
+
- lib/balancer/init.rb
|
206
|
+
- lib/balancer/option_transformer.rb
|
207
|
+
- lib/balancer/param.rb
|
208
|
+
- lib/balancer/profile.rb
|
209
|
+
- lib/balancer/security_group.rb
|
210
|
+
- lib/balancer/setting.rb
|
155
211
|
- lib/balancer/sub.rb
|
156
212
|
- lib/balancer/version.rb
|
213
|
+
- lib/template/.balancer/profiles/default.yml.tt
|
214
|
+
- spec/fixtures/project/.balancer/profiles/default.yml
|
157
215
|
- spec/lib/cli_spec.rb
|
216
|
+
- spec/lib/option_transformer_spec.rb
|
158
217
|
- spec/spec_helper.rb
|
159
218
|
homepage: https://github.com/tongueroo/balancer
|
160
219
|
licenses:
|
@@ -176,10 +235,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
176
235
|
version: '0'
|
177
236
|
requirements: []
|
178
237
|
rubyforge_project:
|
179
|
-
rubygems_version: 2.7.
|
238
|
+
rubygems_version: 2.7.6
|
180
239
|
signing_key:
|
181
240
|
specification_version: 4
|
182
241
|
summary: Balancer tool
|
183
242
|
test_files:
|
243
|
+
- spec/fixtures/project/.balancer/profiles/default.yml
|
184
244
|
- spec/lib/cli_spec.rb
|
245
|
+
- spec/lib/option_transformer_spec.rb
|
185
246
|
- spec/spec_helper.rb
|
data/lib/balancer/help/hello.md
DELETED