furikake 0.0.1

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.
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