furikake 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,123 @@
1
+ # Furikake [![Build Status](https://travis-ci.org/inokappa/furikake.svg?branch=master)](https://travis-ci.org/inokappa/furikake)
2
+ ![](https://raw.githubusercontent.com/inokappa/furikake/master/docs/images/furikake.png)
3
+
4
+ ## これなに
5
+
6
+ * 利用している AWS リソースを Backlog の Wiki ページ (Markdown フォーマットのみ) に良しなに纏めてドキュメント化してくれるコマンドラインツールです
7
+ * 簡単なコードを追加することで, 取得する AWS リソースを増やすことが出来るようにはしています
8
+ * Backlog Wiki 以外にも登録出来るようにはしています
9
+
10
+ ## Install
11
+
12
+ とりあえずは, `git clone` してきて `bundle install` する感じでお願い致します.
13
+
14
+ ```sh
15
+ $ git clone git@github.com:inokappa/furikake.git
16
+ $ bundle install --path vendor/bundle
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ### Create Wiki Page
22
+
23
+ * Backlog の wiki を作成し, wiki ID を控えておく (後の .furikake.yml で利用する)
24
+
25
+ ### Write .envrc
26
+
27
+ とりあえずは, direnv と組み合わせて利用することを想定しており, AWS のクレデンシャル情報は .envrc に記載して下さい.
28
+
29
+ ```sh
30
+ export AWS_PROFILE=your-profile
31
+ export AWS_REGION=ap-northeast-1
32
+ ```
33
+
34
+ ### Write .frikake.yml
35
+
36
+ カレントディレクトリに, 以下のような内容で .furikake.yml を作成して下さい.
37
+
38
+ ```yaml
39
+ backlog:
40
+ projects:
41
+ - space_id: 'your-backlog-space-id'
42
+ api_key: 'your-backlog-api-key'
43
+ top_level_domain: 'your-backlog-top-level-domain'
44
+ wiki_id: your-wiki-id
45
+ wiki_name: 'your-wiki-name'
46
+ header: >
47
+ # Test Header
48
+ footer: >
49
+ # Test Footer
50
+ ```
51
+
52
+ ### Run
53
+
54
+ ```sh
55
+ # ドキュメント化する情報を標準出力に出力する
56
+ bundle exec furikake show
57
+
58
+ # ドキュメント化する情報を wiki に登録する
59
+ bundle exec furikake publish
60
+ ```
61
+
62
+ ## Tips
63
+
64
+ ### リソース追加
65
+
66
+ `lib/furikake/resources/` 以下に任意のファイル名でコードを追加することで, ドキュメント化する対象のリソースを追加することが出来ます.
67
+
68
+ ```ruby
69
+ module Furikake
70
+ module Resources
71
+ module Ec2
72
+ def report(format = nil)
73
+ instance = get_resources
74
+ contents = {
75
+ title: 'EC2',
76
+ resources: [
77
+ {
78
+ subtitle: '',
79
+ header: ['Name', 'Instance ID', 'Instance Type',
80
+ 'Availability Zone', 'Private IP Address',
81
+ 'Public IP Address', 'State'],
82
+ resource: instance
83
+ }
84
+ ]
85
+ }
86
+ Furikake::Formatter.shaping(format, contents)
87
+ end
88
+
89
+ def get_resources
90
+ ec2 = Aws::EC2::Client.new
91
+ params = {}
92
+ instances = []
93
+ loop do
94
+ res = ec2.describe_instances(params)
95
+ ...
96
+ ```
97
+
98
+ report メソッドには, 一覧化する際のヘッダを `header` に配列で指定します. get_resources メソッドにドキュメント化したいリソースの一覧を取得する為の処理を追加します. 戻り値は, 以下のようなフォーマットになるように実装して下さい.
99
+
100
+ ```
101
+ [['ID', 'Name', 'Status'], ['ID', 'Name', 'Status'], ['ID', 'Name', 'Status']]
102
+ ```
103
+
104
+ ## Todo
105
+
106
+ * エラー処理
107
+ * デーモン化
108
+ * Backlog Wiki 以外の Wiki (例えば, Github Wiki や Gist 等)
109
+ * テスト追加
110
+
111
+ ## Development
112
+
113
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
114
+
115
+ 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 tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
116
+
117
+ ## Contributing
118
+
119
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/furikake.
120
+
121
+ ## License
122
+
123
+ 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,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "furikake"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
Binary file
data/exe/furikake ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'furikake'
4
+
5
+ Furikake::CLI.start
data/furikake.gemspec ADDED
@@ -0,0 +1,32 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "furikake/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "furikake"
8
+ spec.version = Furikake::VERSION
9
+ spec.authors = ["inokappa"]
10
+ spec.email = ["inokara@gmail.com"]
11
+
12
+ spec.summary = %q{It is a command line tool to register your resources in Wiki page (Markdown format).}
13
+ spec.description = %q{It is a command line tool to register your resources in Wiki page (Markdown format).}
14
+ spec.homepage = "https://github.com/inokappa/furikake"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
18
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.16"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rspec", "~> 3.0"
27
+
28
+ spec.add_dependency 'thor'
29
+ spec.add_dependency 'aws-sdk'
30
+ spec.add_dependency 'markdown-tables'
31
+ spec.add_dependency 'backlog_kit'
32
+ end
@@ -0,0 +1,22 @@
1
+ require 'furikake'
2
+
3
+ module Furikake
4
+ class CLI < Thor
5
+ desc 'version', 'version print.'
6
+ def version
7
+ puts Furikake::VERSION
8
+ end
9
+
10
+ desc 'show', 'resouces print.'
11
+ def show
12
+ report = Furikake::Report.new
13
+ report.show
14
+ end
15
+
16
+ desc 'publish', 'resouces publish to something.'
17
+ def publish
18
+ report = Furikake::Report.new
19
+ report.publish
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ require 'yaml'
2
+
3
+ module Furikake
4
+ module Config
5
+ def read_furikake_yaml
6
+ open('.furikake.yml', 'r') { |f| YAML.load(f) }
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'furikake/formatters/markdown'
2
+
3
+ module Furikake
4
+ class Formatter
5
+ def self.shaping(format, contents)
6
+ Furikake::Formatters::Markdown.write(contents) if format.nil?
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Furikake
2
+ module Formatters
3
+ class Csv
4
+ def self.wirte(c)
5
+ c
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,30 @@
1
+ require 'erb'
2
+ require 'markdown-tables'
3
+
4
+ module Furikake
5
+ module Formatters
6
+ class Markdown
7
+ def self.write(c)
8
+ contents = <<EOS
9
+ ### <%= c[:title] %>
10
+
11
+ <%- c[:resources].each do |r| -%>
12
+ <%- if r[:subtitle] != '' -%>
13
+ #### <%= r[:subtitle] %>
14
+
15
+ <%- end -%>
16
+ <%- if ! r[:resource].empty? -%>
17
+ <%= MarkdownTables.make_table(r[:header], r[:resource], is_rows: true, align: 'l') %>
18
+
19
+ <%- else -%>
20
+ <%= 'N/A' %>
21
+
22
+ <%- end -%>
23
+ <%- end -%>
24
+ EOS
25
+ erb = ERB.new(contents, nil, '-')
26
+ erb.result(binding).chomp
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,52 @@
1
+ require 'furikake/reporters/backlog'
2
+
3
+ module Furikake
4
+ class Report
5
+ include Furikake::Config
6
+
7
+ def initialize
8
+ @params = read_furikake_yaml
9
+ @resource = Furikake::Resource.generate
10
+ end
11
+
12
+ def show
13
+ @params['backlog']['projects'].each do |p|
14
+ header = insert_published_by(p['header'])
15
+ footer = p['footer']
16
+ puts generate(header, footer)
17
+ end
18
+ end
19
+
20
+ def publish
21
+ @params['backlog']['projects'].each do |p|
22
+ header = insert_published_by(p['header'])
23
+ footer = p['footer']
24
+ document = generate(header, footer)
25
+ p['wiki_contents'] = document
26
+ Furikake::Reporters::Backlog.new(p).publish
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def generate(header, footer)
33
+ documents = <<"EOS"
34
+ #{header}
35
+ #{@resource}
36
+ #{footer}
37
+ EOS
38
+ documents
39
+ end
40
+
41
+ def insert_published_by(header)
42
+ headers = header.split("\n")
43
+ headers.insert(1, published_by)
44
+ headers.insert(2, "\n")
45
+ headers.join("\n")
46
+ end
47
+
48
+ def published_by
49
+ "*Published #{Time.now} by [furikake](https://github.com/inokappa/furikake)*"
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,25 @@
1
+ require 'backlog_kit'
2
+
3
+ module Furikake
4
+ module Reporters
5
+ class Backlog
6
+ def initialize(params)
7
+ @client ||= BacklogKit::Client.new(
8
+ space_id: params['space_id'],
9
+ api_key: params['api_key'],
10
+ top_level_domain: params['top_level_domain']
11
+ )
12
+ @wiki_id = params['wiki_id']
13
+ @wiki_name = params['wiki_name']
14
+ @wiki_contents = params['wiki_contents']
15
+ end
16
+
17
+ def publish
18
+ params = {}
19
+ params['name'] = @wiki_name
20
+ params['content'] = @wiki_contents
21
+ @client.update_wiki(@wiki_id, params)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,21 @@
1
+ module Furikake
2
+ class Resource
3
+ def self.generate
4
+ documents = ''
5
+ load_type.each do |type|
6
+ require "furikake/resources/#{type}"
7
+ eval "documents.concat(Furikake::Resources::#{type.camelize}.report)"
8
+ documents.concat("\n")
9
+ end
10
+ documents
11
+ end
12
+
13
+ def self.load_type
14
+ type = []
15
+ Dir.glob(File.dirname(__FILE__) + '/resources/*').each do |r|
16
+ type << File.basename(r, '.rb') unless r.include?('stub')
17
+ end
18
+ type
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,71 @@
1
+ module Furikake
2
+ module Resources
3
+ module Alb
4
+ def report
5
+ albs, target_groups = get_resources
6
+ headers = ['LB Name', 'DNS Name', 'Type', 'Target Group']
7
+ if albs.empty?
8
+ albs_info = 'N/A'
9
+ else
10
+ albs_info = MarkdownTables.make_table(headers,
11
+ albs,
12
+ is_rows: true,
13
+ align: 'l')
14
+ end
15
+
16
+ headers = ['Target Group Name', 'Protocal', 'Port', 'Health Check Path', 'Health Chack Port', 'Health Check Protocol']
17
+ if target_groups.empty?
18
+ target_group_info = 'N/A'
19
+ else
20
+ target_group_info = MarkdownTables.make_table(headers,
21
+ target_groups,
22
+ is_rows: true,
23
+ align: 'l')
24
+ end
25
+
26
+ documents = <<"EOS"
27
+ ### ELB (ALB / NLB)
28
+
29
+ #### ALB / NLB
30
+
31
+ #{albs_info}
32
+
33
+ #### Target Groups
34
+
35
+ #{target_group_info}
36
+ EOS
37
+ documents
38
+ end
39
+
40
+ def get_resources
41
+ alb = Aws::ElasticLoadBalancingV2::Client.new
42
+
43
+ albs = []
44
+ target_groups = []
45
+ alb.describe_load_balancers.load_balancers.each do |lb|
46
+ alb_info = []
47
+ t = alb.describe_target_groups({
48
+ load_balancer_arn: lb.load_balancer_arn
49
+ }).target_groups.map(&:to_h)
50
+ alb_info << lb.load_balancer_name
51
+ alb_info << lb.dns_name
52
+ alb_info << lb.type
53
+ alb_info << (t.map {|a| a[:target_group_name]}).join(", ")
54
+ albs << alb_info
55
+ target_group = []
56
+ target_group << (t.map {|a| a[:target_group_name]}).join(", ")
57
+ target_group << (t.map {|a| a[:protocol]}).join(", ")
58
+ target_group << (t.map {|a| a[:port]}).join(", ")
59
+ target_group << (t.map {|a| a[:health_check_path].nil? ? " " : a[:health_check_path]}).join(", ")
60
+ target_group << (t.map {|a| a[:health_check_port]}).join(", ")
61
+ target_group << (t.map {|a| a[:health_check_protocol]}).join(", ")
62
+ target_groups << target_group
63
+ end
64
+
65
+ return albs, target_groups
66
+ end
67
+
68
+ module_function :report, :get_resources
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,37 @@
1
+ module Furikake
2
+ module Resources
3
+ module Clb
4
+ def report
5
+ resources = get_resources
6
+ headers = ['LB Name', 'DNS Name', 'Instances']
7
+ if resources.empty?
8
+ info = 'N/A'
9
+ else
10
+ info = MarkdownTables.make_table(headers, resources, is_rows: true, align: 'l')
11
+ end
12
+ documents = <<"EOS"
13
+ ### ELB (CLB)
14
+
15
+ #{info}
16
+ EOS
17
+
18
+ documents
19
+ end
20
+
21
+ def get_resources
22
+ elb = Aws::ElasticLoadBalancing::Client.new
23
+ elbs = []
24
+ elb.describe_load_balancers.load_balancer_descriptions.each do |lb|
25
+ elb = []
26
+ elb << lb.load_balancer_name
27
+ elb << lb.dns_name
28
+ elb << (lb.instances.map(&:to_h).map {|a| a[:instance_id] }).join(',')
29
+ elbs << elb
30
+ end
31
+ elbs
32
+ end
33
+
34
+ module_function :report, :get_resources
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,50 @@
1
+ module Furikake
2
+ module Resources
3
+ module DirectoryService
4
+ def report
5
+ resources = get_resources
6
+ headers = ['Directory ID', 'DNS Name', 'NetBIOS Name', 'Type', 'DNS Addresses', 'Size']
7
+ if resources.empty?
8
+ info = 'N/A'
9
+ else
10
+ info = MarkdownTables.make_table(headers, resources, is_rows: true, align: 'l')
11
+ end
12
+ documents = <<"EOS"
13
+ ### Directory Service (Simple AD)
14
+
15
+ #{info}
16
+ EOS
17
+
18
+ documents
19
+ end
20
+
21
+ def get_resources
22
+ ds = Aws::DirectoryService::Client.new
23
+
24
+ req = {}
25
+ resouces = []
26
+ loop do
27
+ res = ds.describe_directories(req)
28
+ resouces.push(*res.directory_descriptions.map(&:to_h))
29
+ break if res.next_token.nil?
30
+ req[:next_token] = res.next_token
31
+ end
32
+
33
+ directoryservice_infos = []
34
+ resouces.each do |r|
35
+ directory = []
36
+ directory << r[:directory_id]
37
+ directory << r[:name]
38
+ directory << r[:short_name]
39
+ directory << r[:type]
40
+ directory << r[:dns_ip_addrs].join(', ')
41
+ directory << r[:size]
42
+ directoryservice_infos << directory
43
+ end
44
+ directoryservice_infos
45
+ end
46
+
47
+ module_function :report, :get_resources
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,56 @@
1
+ module Furikake
2
+ module Resources
3
+ module Ec2
4
+ def report(format = nil)
5
+ instance = get_resources
6
+ contents = {
7
+ title: 'EC2',
8
+ resources: [
9
+ {
10
+ subtitle: '',
11
+ header: ['Name', 'Instance ID', 'Instance Type',
12
+ 'Availability Zone', 'Private IP Address',
13
+ 'Public IP Address', 'State'],
14
+ resource: instance
15
+ }
16
+ ]
17
+ }
18
+ Furikake::Formatter.shaping(format, contents)
19
+ end
20
+
21
+ def get_resources
22
+ ec2 = Aws::EC2::Client.new
23
+ params = {}
24
+ instances = []
25
+ loop do
26
+ res = ec2.describe_instances(params)
27
+ res.reservations.each do |r|
28
+ r.instances.each do |i|
29
+ instance = []
30
+ instance << 'N/A' if i.tags.map(&:to_h).all? { |h| h[:key] != 'Name' }
31
+ i.tags.each do |tag|
32
+ instance << tag.value if tag.key == 'Name'
33
+ end
34
+ instance << i.instance_id
35
+ instance << i.instance_type
36
+ instance << i.placement.availability_zone
37
+ instance << i.private_ip_address
38
+ if i.public_ip_address.nil?
39
+ instance << ' '
40
+ else
41
+ instance << i.public_ip_address
42
+ end
43
+ instance << i.state.name
44
+ instances << instance
45
+ end
46
+ end
47
+ break if res.next_token.nil?
48
+ params[:next_token] = res.next_token
49
+ end
50
+
51
+ instances
52
+ end
53
+ module_function :report, :get_resources
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,54 @@
1
+ module Furikake
2
+ module Resources
3
+ module ElasticsearchService
4
+ def report
5
+ resources = get_resources
6
+ headers = ['Domain Name', 'Endpoint', 'Instance Type', "Instance Count", "Elasticsearch Version", 'EBS Type', 'EBS Size']
7
+ if resources.empty?
8
+ info = 'N/A'
9
+ else
10
+ info = MarkdownTables.make_table(headers, resources, is_rows: true, align: 'l')
11
+ end
12
+ documents = <<"EOS"
13
+ ### Elasticsearch Service
14
+
15
+ #{info}
16
+ EOS
17
+
18
+ documents
19
+ end
20
+
21
+ def get_resources
22
+ ess = Aws::ElasticsearchService::Client.new
23
+
24
+ domains = []
25
+ loop do
26
+ res = ess.list_domain_names
27
+ domains.push(*res.domain_names.map(&:to_h))
28
+ break if res.domain_names.size == domains.size
29
+ end
30
+
31
+ domain_info = []
32
+ domains.each do |domain|
33
+ resource = []
34
+ res = ess.describe_elasticsearch_domains({
35
+ domain_names: [domain[:domain_name]],
36
+ })
37
+ res.domain_status_list.each do |r|
38
+ resource << r[:domain_name]
39
+ resource << r[:endpoints]['vpc']
40
+ resource << r[:elasticsearch_cluster_config][:instance_type]
41
+ resource << r[:elasticsearch_cluster_config][:instance_count]
42
+ resource << r[:elasticsearch_version]
43
+ resource << r[:ebs_options][:volume_type]
44
+ resource << r[:ebs_options][:volume_size]
45
+ end
46
+ domain_info << resource
47
+ end
48
+ domain_info
49
+ end
50
+
51
+ module_function :report, :get_resources
52
+ end
53
+ end
54
+ end