simnos 0.1.1.beta1 → 0.1.1.beta2

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
  SHA1:
3
- metadata.gz: f7852e8296f11712e300ceff4199a87244afa228
4
- data.tar.gz: 60783438422b07f0bbed97fa714c09fca1dc0c68
3
+ metadata.gz: 331d3fe90ec21685f9fa4a969c2e3d77436d88c3
4
+ data.tar.gz: e9053c2ad17c3d06fceef1097eed7066e8fc94ab
5
5
  SHA512:
6
- metadata.gz: 6c867759e0989739c9400ff6d9cf3fe255ffe05a43e1b84894c0c5ba78b46d442839faaf4d2b26a598bcc992f17bc77ac617fa888f8b7cc9c0f9d5207e65068a
7
- data.tar.gz: c3322803fb225d76b0753af9818698e579654147f9eda3b1f6386c93cc37de3e6446ff7122a41920a658d9d430f3c10d49f2ba7b961648b157310ed022eeb78c
6
+ metadata.gz: 61869e91186323165f8ea9cba28e1a79c503b25f10dec59167fea025abca8b9735bc14b5d843151e947f983abb2a20fa399e968fcf7fa01b63652c25bcaa34c5
7
+ data.tar.gz: a3aec65e414b5cab557b9d2ca491ee84e3188f1b8f93c913aa4ba49ef2681b12d7b524b2b970e49510126173c0c7be5d2eb7951eca0340f82d39f5791f36f2e0
data/README.md CHANGED
@@ -46,6 +46,10 @@ Usage: simnos [options]
46
46
  no color
47
47
  --with-subscriptions
48
48
  manage subscriptions
49
+ --recreate-subscriptions
50
+ recreate subscriptions
51
+ --secret-provider NAME
52
+ use secret value expansion
49
53
  -i, --include-names NAMES include SNS names
50
54
  -x, --exclude-names NAMES exclude SNS names by regex
51
55
  ```
@@ -114,6 +118,25 @@ sns "ap-northeast-1" do
114
118
  end
115
119
  ```
116
120
 
121
+ ## Secret provider
122
+
123
+ If you don't want to commit your Basic authentication password, you can use SecretProvider.
124
+ Use --secret-provider option to select provider.(e.g. --secret-provider=vault)
125
+ Expression inside `${...}` is passed to provider.
126
+
127
+ ```
128
+ subscriptions do
129
+ subscription protocol: "https", endpoint: "https://user:${password}your.awesome.site/"
130
+ end
131
+ ```
132
+
133
+ ## Subscriptions
134
+
135
+ There is no way to UPDATE subscription.
136
+ So if you want to recreate subscrptions, use --recreate-subscriptions option.
137
+ It is highly recommended to also path --include-names or exclude-names to select topics.
138
+ Because of Basic authentication password is not returned from API, recreation is needed to change password.
139
+
117
140
  ## Similar tools
118
141
 
119
142
  * [Codenize.tools](http://codenize.tools/)
@@ -44,6 +44,8 @@ module Simnos
44
44
  opts.on('-s', '--split', 'split export DSL file to 1 per topic') { @options[:split] = true }
45
45
  opts.on('', '--no-color', 'no color') { @options[:color] = false }
46
46
  opts.on('', '--with-subscriptions', 'manage subscriptions') { @options[:with_subscriptions] = true }
47
+ opts.on('', '--recreate-subscriptions', 'recreate subscriptions') { @options[:recreate_subscriptions] = true }
48
+ opts.on('', '--secret-provider NAME', 'use secret value expansion') { |v| @options[:secret_provider] = v }
47
49
  opts.on('-i', '--include-names NAMES', 'include SNS names', Array) { |v| @options[:includes] = v }
48
50
  opts.on('-x', '--exclude-names NAMES', 'exclude SNS names by regex', Array) do |v|
49
51
  @options[:excludes] = v.map! do |name|
@@ -3,6 +3,7 @@ require 'simnos/client_wrapper'
3
3
  require 'simnos/converter'
4
4
  require 'simnos/dsl'
5
5
  require 'simnos/filterable'
6
+ require 'simnos/secret_expander'
6
7
 
7
8
  module Simnos
8
9
  class Client
@@ -15,6 +16,7 @@ module Simnos
15
16
  def initialize(filepath, options = {})
16
17
  @filepath = filepath
17
18
  @options = options
19
+ @options[:secret_expander] = SecretExpander.new(@options[:secret_provider]) if @options[:secret_provider]
18
20
  end
19
21
 
20
22
  def apply
@@ -70,29 +72,41 @@ module Simnos
70
72
 
71
73
  private
72
74
 
75
+ def delete_subscriptions(aws_topic, aws_sub_by_key)
76
+ aws_sub_by_key.each do |key, aws_sub|
77
+ Simnos.logger.info("Delete Topic(#{aws_topic[:topic].topic_arn.split(':').last}) Subscription. protocol: #{key[0].inspect}, endpoint: #{key[1].inspect}.#{@options[:dry_run] ? ' [dry-run]' : ''}")
78
+ if aws_sub.subscription_arn.split(':').length < 6
79
+ Simnos.logger.warn("Can not delete Subscription `#{aws_sub.subscription_arn}`")
80
+ next
81
+ end
82
+ next if @options[:dry_run]
83
+
84
+ client.unsubscribe(subscription_arn: aws_sub.subscription_arn)
85
+ end
86
+ end
87
+
73
88
  def traverse_subscriptions(aws_topic, dsl_subscriptions, aws_subscriptions)
74
- dsl_sub_by_key = dsl_subscriptions.each_with_object({}) { |dsl_sub, h| h[[dsl_sub.protocol, dsl_sub.endpoint]] = dsl_sub }
89
+ dsl_sub_by_key = dsl_subscriptions.each_with_object({}) { |dsl_sub, h| h[[dsl_sub.protocol, dsl_sub.masked_endpoint]] = dsl_sub }
75
90
  aws_sub_by_key = aws_subscriptions.each_with_object({}) { |aws_sub, h| h[[aws_sub.protocol, aws_sub.endpoint]] = aws_sub }
91
+
92
+ if @options[:recreate_subscriptions]
93
+ Simnos.logger.info("Subscription recreation flag is on.#{@options[:dry_run] ? ' [dry-run]' : ''}")
94
+ delete_subscriptions(aws_topic, aws_sub_by_key)
95
+ aws_sub_by_key = {}
96
+ end
97
+
76
98
  # create
77
99
  dsl_sub_by_key.reject { |key, _| aws_sub_by_key[key] }.each do |key, dsl_sub|
78
100
  dsl_sub.aws_topic(aws_topic).create
79
101
  end
80
102
 
103
+ # there is no way to update subscriptions
81
104
  dsl_sub_by_key.each do |key, dsl_sub|
82
105
  aws_sub_by_key.delete(key)
83
106
  end
84
107
 
85
108
  # delete
86
- aws_sub_by_key.each do |key, aws_sub|
87
- Simnos.logger.info("Delete Topic(#{aws_topic[:topic].topic_arn.split(':').last}) Subscription. protocol: #{key[0].inspect}, endpoint: #{key[1].inspect}.#{@options[:dry_run] ? ' [dry-run]' : ''}")
88
- if aws_sub.subscription_arn.split(':').length < 6
89
- Simnos.logger.warn("Can not delete Subscription `#{aws_sub.subscription_arn}`")
90
- next
91
- end
92
- next if @options[:dry_run]
93
-
94
- client.unsubscribe(subscription_arn: aws_sub.subscription_arn)
95
- end
109
+ delete_subscriptions(aws_topic, aws_sub_by_key)
96
110
  end
97
111
 
98
112
  def traverse_topics(dsl_topics_all, aws_topics_by_name)
@@ -6,7 +6,7 @@ module Simnos
6
6
  include Simnos::TemplateHelper
7
7
 
8
8
  def create
9
- Simnos.logger.info("Create Topic(#{@aws_topic[:topic].topic_arn.split(':').last}) Subscription. protocol: #{protocol.inspect}, endpoint: #{endpoint.inspect}#{@options[:dry_run] ? ' [dry-run]' : ''}")
9
+ Simnos.logger.info("Create Topic(#{@aws_topic[:topic].topic_arn.split(':').last}) Subscription. protocol: #{protocol.inspect}, endpoint: #{masked_endpoint.inspect}#{@options[:dry_run] ? ' [dry-run]' : ''}")
10
10
  return if @options[:dry_run]
11
11
 
12
12
  client.subscribe(
@@ -29,7 +29,28 @@ module Simnos
29
29
  @endpoint = endpoint
30
30
  end
31
31
 
32
- attr_reader :topic, :protocol, :endpoint
32
+ attr_reader :topic, :protocol
33
+
34
+ # We have to mask endpoint because SNS returns masked endpoint from API
35
+ def masked_endpoint
36
+ if URI.extract(@endpoint, ['http', 'https']).empty?
37
+ return endpoint
38
+ end
39
+ uri = URI.parse(endpoint)
40
+ if md = uri.userinfo&.match(/(.*):(.*)/)
41
+ uri.userinfo = "#{md[1]}:****"
42
+ end
43
+ uri.to_s
44
+ end
45
+
46
+ def endpoint
47
+ secret_expander = @options[:secret_expander]
48
+ if secret_expander
49
+ secret_expander.expand(@endpoint)
50
+ else
51
+ @endpoint
52
+ end
53
+ end
33
54
 
34
55
  private
35
56
 
@@ -0,0 +1,75 @@
1
+ require 'strscan'
2
+
3
+ module Simnos
4
+ class ExpansionError < StandardError
5
+ end
6
+
7
+ class SecretExpander
8
+ Literal = Struct.new(:literal)
9
+ Variable = Struct.new(:name)
10
+
11
+ def initialize(provider_name)
12
+ @provider = load_provider(provider_name)
13
+ @asked_variables = {}
14
+ end
15
+
16
+ def expand(str)
17
+ tokens = parse(str)
18
+ variables = Set.new
19
+ tokens.each do |token|
20
+ if token.is_a?(Variable)
21
+ unless @asked_variables.include?(token.name)
22
+ variables << token.name
23
+ end
24
+ end
25
+ end
26
+
27
+ unless variables.empty?
28
+ @provider.ask(variables).each do |k, v|
29
+ @asked_variables[k] = v
30
+ end
31
+ end
32
+
33
+ tokens.map do |token|
34
+ case token
35
+ when Literal
36
+ token.literal
37
+ when Variable
38
+ @asked_variables.fetch(token.name)
39
+ else
40
+ raise ExpansionError.new("Unknown token type: #{token.class}")
41
+ end
42
+ end.join
43
+ end
44
+
45
+ private
46
+
47
+ def parse(value)
48
+ s = StringScanner.new(value)
49
+ tokens = []
50
+ pos = 0
51
+ while s.scan_until(/\$\{(.*?)\}/)
52
+ pre = s.string.byteslice(pos...(s.pos - s.matched.size))
53
+ var = s[1]
54
+ unless pre.empty?
55
+ tokens << Literal.new(pre)
56
+ end
57
+ if var.empty?
58
+ raise ExpansionError.new('Empty interpolation is not allowed')
59
+ else
60
+ tokens << Variable.new(var)
61
+ end
62
+ pos = s.pos
63
+ end
64
+ unless s.rest.empty?
65
+ tokens << Literal.new(s.rest)
66
+ end
67
+ tokens
68
+ end
69
+
70
+ def load_provider(name)
71
+ require "simnos/secret_providers/#{name}"
72
+ Simnos::SecretProviders.const_get(name.split('_').map(&:capitalize).join('')).new
73
+ end
74
+ end
75
+ end
@@ -1,3 +1,3 @@
1
1
  module Simnos
2
- VERSION = "0.1.1.beta1"
2
+ VERSION = "0.1.1.beta2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simnos
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1.beta1
4
+ version: 0.1.1.beta2
5
5
  platform: ruby
6
6
  authors:
7
7
  - wata
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-10-03 00:00:00.000000000 Z
11
+ date: 2017-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk
@@ -166,6 +166,7 @@ files:
166
166
  - lib/simnos/dsl/topic.rb
167
167
  - lib/simnos/filterable.rb
168
168
  - lib/simnos/output_topic.erb
169
+ - lib/simnos/secret_expander.rb
169
170
  - lib/simnos/template_helper.rb
170
171
  - lib/simnos/utils.rb
171
172
  - lib/simnos/version.rb