Skip to content

Commit

Permalink
Sophisticate readme (#2)
Browse files Browse the repository at this point in the history
* [terraforming] add only iam_role and s3

* iam_policy_attachment
  • Loading branch information
nakamasato committed Nov 10, 2019
1 parent dc97d59 commit 93dbdc8
Show file tree
Hide file tree
Showing 30 changed files with 1,607 additions and 32 deletions.
14 changes: 13 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,25 @@ jobs:
build:
docker:
- image: circleci/ruby:2.4.2-jessie-node
environment:
BUNDLER_VERSION: 2.0.2
steps:
- checkout
- restore_cache:
keys:
- v1-dependencies-{{ checksum "Gemfile.lock" }}
- v1-dependencies-
- run: bundle install --path vendor/bundle
- run:
name: setup bundler
command: |
sudo gem update --system
sudo gem uninstall bundler
sudo rm /usr/local/bin/bundle
sudo rm /usr/local/bin/bundler
sudo gem install bundler
- run:
name: install
command: bundle install --path vendor/bundle
- save_cache:
paths:
- ./vendor/bundle
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@

# rspec failure tracking
.rspec_status
*.gem
17 changes: 17 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ Style/HashSyntax:
Exclude:
- 'Rakefile'

# TODO: check again
Style/IndentArray:
Enabled: false

# TODO: check again
Style/IndentHash:
Enabled: false

Style/LineEndConcatenation:
Enabled: false

Expand Down Expand Up @@ -74,3 +82,12 @@ Style/CollectionMethods:

Style/PerlBackrefs:
Enabled: false

Security/Open:
Enabled: false

Metrics/BlockLength:
Enabled: false

Naming/HeredocDelimiterNaming:
Enabled: false
50 changes: 47 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,14 +1,47 @@
PATH
remote: .
specs:
practice_terraforming (0.1.0)
practice_terraforming (0.1.1)
aws-sdk-iam (~> 1)
aws-sdk-s3 (~> 1)
multi_json (~> 1.12.1)
thor

GEM
remote: https://rubygems.org/
specs:
ast (2.4.0)
aws-eventstream (1.0.3)
aws-partitions (1.237.0)
aws-sdk-core (3.76.0)
aws-eventstream (~> 1.0, >= 1.0.2)
aws-partitions (~> 1, >= 1.228.0)
aws-sigv4 (~> 1.1)
jmespath (~> 1.0)
aws-sdk-iam (1.31.0)
aws-sdk-core (~> 3, >= 3.71.0)
aws-sigv4 (~> 1.1)
aws-sdk-kms (1.25.0)
aws-sdk-core (~> 3, >= 3.71.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.53.0)
aws-sdk-core (~> 3, >= 3.71.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.1)
aws-sigv4 (1.1.0)
aws-eventstream (~> 1.0, >= 1.0.2)
coveralls (0.8.21)
json (>= 1.8, < 3)
simplecov (~> 0.14.1)
term-ansicolor (~> 1.3)
thor (~> 0.19.4)
tins (~> 1.6)
diff-lcs (1.3)
docile (1.1.5)
jaro_winkler (1.5.4)
jmespath (1.4.0)
json (2.2.0)
multi_json (1.12.2)
parallel (1.18.0)
parser (2.6.5.0)
ast (~> 2.4.0)
Expand All @@ -35,17 +68,28 @@ GEM
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 1.7)
ruby-progressbar (1.10.1)
simplecov (0.14.1)
docile (~> 1.1.0)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.2)
term-ansicolor (1.7.1)
tins (~> 1.0)
thor (0.19.4)
tins (1.22.0)
unicode-display_width (1.6.0)

PLATFORMS
ruby

DEPENDENCIES
bundler (~> 1.16)
bundler (~> 2.0)
coveralls (~> 0.8.13)
practice_terraforming!
rake (~> 10.0)
rspec
rubocop
simplecov (~> 0.14.1)

BUNDLED WITH
1.16.6
2.0.2
216 changes: 216 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,219 @@ The gem is available as open source under the terms of the [MIT License](https:/
## Code of Conduct

Everyone interacting in the PracticeTerraforming project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/practice_terraforming/blob/master/CODE_OF_CONDUCT.md).

# How I created this

## Prepare Gem

```
bundle gem practice_terraforming
```

## Entrypoint of practice_terraforming

`bin/practice_terraforming`

CLI command (extended Thor)

## lib/practice_terraforming.rb

`lib/practice_terraforming.rb` just requires all the dependencies

## cli definition

`lib/practice_terraforming/cli.rb`

Basically, just copied from `terraforming/lib/terraforming/cli.rb`. Deleted resources but `iam_role` and `s3`

## AWS Resources (Main logic to generate tfstate/tf)

```
lib/practice_terraforming/resource/iam_role.rb
lib/practice_terraforming/resource/s3.rb
```

Resource file is generated by `script/generate` but need to update `tfstate` method

## Util

`lib/practice_terraforming/util.rb`

Just copied from `terraforming/lib/terraforming/util.rb`

## Gemspec

`practice_terraforming.gemspec`

Wrote dependencies with `spec.add_dependency` and `spec.add_development_dependency`

## Templates

- resource.erb.erb -> tf file
- resource.rb.erb -> resource class to write logic to generate tf file
- resource_spec.rb.erb -> spec file

## Spec

|spec file|memo|
|---|---|
|spec/fixtures/terraform.tfstate|copied from terraforming|
|spec/lib/practice_terraforming/cli_spec.rb|copied from terraforming|
|spec/lib/practice_terraforming/resource/<resource>.rb|generated by `script/generate` but need to write by yourself|


## Create Resource

0. generate templates with `script/generate`

```
script/generate iam_policy_attachment
==> Generate iam_policy_attachment.rb
==> Generate iam_policy_attachment_spec.rb
==> Generate iam_policy_attachment.erb
Add below code by hand.
lib/practice_terraforming.rb:
require "practice_terraforming/resource/iam_policy_attachment"
lib/practice_terraforming/cli.rb:
module PracticeTerraforming
class CLI < Thor
# Subcommand name should be acronym.
desc "iam_policy_attachment", "Iam Policy Attachment"
def iam_policy_attachment
execute(PracticeTerraforming::Resource::IamPolicyAttachment, options)
end
spec/lib/practice_terraforming/cli_spec.rb:
module PracticeTerraforming
describe CLI do
context "resources" do
describe "iam_policy_attachment" do
let(:klass) { PracticeTerraforming::Resource::IamPolicyAttachment }
let(:command) { :iam_policy_attachment }
it_behaves_like "CLI examples"
end
```

1. As the message says, add those codes.
2. `lib/practice_terraforming/resource/iam_policy_attachment.rb`: Change Aws client and write logic in `tfstate` method

Use aws-sdk-<resource> to get the input data and write the logic to generate tf/tfstate file.
1. tf -> only need to update the template file, which appears in the next step
2. tfstate -> get resource list using private method, format them into resources and return them
3. As for private methods:
- module_name_of(<resource>) -> used for module name of terraform to be imported
- <api method name, e.g. entities_for_policy> -> get the resource info with aws-sdk
- other -> make a list of resources to be used in `tfstate` method

3. `lib/practice_terraforming/template/tf/iam_policy_attachment.erb`: Update the erb based on the corresponding terraform resource.

```
<% iam_policy_attachments.each do |policy_attachment| -%>
resource "aws_iam_policy_attachment" "<%= module_name_of(policy_attachment) %>" {
name = "<%= policy_attachment[:name] %>"
policy_arn = "<%= policy_attachment[:arn] %>"
groups = <%= policy_attachment[:entities].policy_groups.map(&:group_name).inspect %>
users = <%= policy_attachment[:entities].policy_users.map(&:user_name).inspect %>
roles = <%= policy_attachment[:entities].policy_roles.map(&:role_name).inspect %>
}
<% end -%>
```

4. `spec/lib/practice_terraforming/resource/iam_policy_attachment_spec.rb`: Change Aws client and write test for tf and tfstate

Test Perspective:
1. Create aws sdk result using stub.
2. Use the module to generate tf/tfstate.
3. Compare expected one and generated one.
```
irb(main):007:0> client.list_policies.policies[0]
=> #<struct Aws::IAM::Types::Policy policy_name="test-policy", policy_id="ABCDEFG", arn="arn:aws:iam::123456789:policy/test-policy", path="/", default_version_id="v1", attachment_count=1, permissions_boundary_usage_count=0, is_attachable=true, description=nil, create_date=2019-01-01 00:00:00 UTC, update_date=2019-01-02 00:00:00 UTC>
client.list_entities_for_policy(policy_arn: "arn:aws:iam::351540792571:policy/ai-suggest-batch-user-policy")
irb(main):008:0> client.list_entities_for_policy(policy_arn: "arn:aws:iam::123456789:policy/test-policy")
=> #<struct Aws::IAM::Types::ListEntitiesForPolicyResponse policy_groups=[#<struct Aws::IAM::Types::PolicyGroup group_name="test-group", group_id="ABCDEFG">], policy_users=[], policy_roles=[], is_truncated=false, marker=nil>
```

```
let(:policies) do
[
{
policy_name: "test-policy",
policy_id: "ABCDEFG",
arn: "arn:aws:iam::123456789:policy/test-policy",
path: "/",
default_version_id: "v1",
attachment_count: 1,
is_attachable: true,
create_date: Time.parse("2019-01-01 00:00:00 UTC"),
update_date: Time.parse("2019-01-02 00:00:00 UTC"),
description: nil,
}
]
end
let(:entities_for_policy) do
{
policy_groups: [
{ group_name: "test-group", group_id: "ABCDEFG" },
],
policy_users: [],
policy_roles: [],
}
end
before do
client.stub_responses(:list_policies, policies: policies)
client.stub_responses(:list_entities_for_policy, [entities_for_policy])
end
```

## Install on local

### Build

```
gem build practice_terraforming.gemspec
```

the above command will generate the `practice_terraforming-X.X.X.gem`

### Install

0.1.0 as an example

```
gem install practice_terraforming-0.1.0.gem
Successfully installed practice_terraforming-0.1.0
Parsing documentation for practice_terraforming-0.1.0
Installing ri documentation for practice_terraforming-0.1.0
Done installing documentation for practice_terraforming after 0 seconds
1 gem installed
```

### Check

```
practice_terraforming
Commands:
practice_terraforming help [COMMAND] # Describe available commands or one specific command
practice_terraforming iamr # Iam Role
practice_terraforming s3 # S3
Options:
[--merge=MERGE] # tfstate file to merge
[--overwrite], [--no-overwrite] # Overwrite existing tfstate
[--tfstate], [--no-tfstate] # Generate tfstate
[--profile=PROFILE] # AWS credentials profile
[--region=REGION] # AWS region
[--assume=ASSUME] # Role ARN to assume
[--use-bundled-cert], [--no-use-bundled-cert] # Use the bundled CA certificate from AWS SDK
```
6 changes: 6 additions & 0 deletions bin/practice_terraforming
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

require "practice_terraforming"

PracticeTerraforming::CLI.start(ARGV)
14 changes: 11 additions & 3 deletions lib/practice_terraforming.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
# frozen_string_literal: true

require "aws-sdk-iam"
require "aws-sdk-s3"
require "multi_json"
require "thor"
require "erb"

require "practice_terraforming/util"
require 'practice_terraforming/version'

module PracticeTerraforming
# Your code goes here...
end
require "practice_terraforming/cli"
require "practice_terraforming/resource/iam_role"
require "practice_terraforming/resource/iam_policy_attachment"
require "practice_terraforming/resource/s3"

0 comments on commit 93dbdc8

Please sign in to comment.