terraspace_plugin_azurerm 0.0.0 → 0.2.2

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
  SHA256:
3
- metadata.gz: 5558017d6143d6bfda510f1aab5508130506d1a9de81bc75582b145ee2867d3b
4
- data.tar.gz: ec7ece5847e2cb02ba991d00ceb7d91e60b4d1886a2c1d7c23333e3fd4369a2d
3
+ metadata.gz: b3ff4bc13ad8e73d40b985420c107ef791d652bde858092271a239715ec6b824
4
+ data.tar.gz: cdbc5ddac31c0c4fad5676ea802810fd9982f02a59f3347bf72d4e407f7abec7
5
5
  SHA512:
6
- metadata.gz: 33461605e1ff3b16b2eb0d7b4b0230805dc34542181aa51a48a2d6e41a8b1940951673452cc1d9e06a642b47e6b427403edd9265edebffa3a26f190eba081ee3
7
- data.tar.gz: '004158f2120660455a6450b581ceda03ce91bacd45b32b836149672fa0b5f800e79b58563c754c65d69d90556a56c900039e4a71caccf3687f138bc5b34f50c1'
6
+ metadata.gz: 878dc0469567622cd0bf3ef0c378ae5ba9962035511110fdb057892873d0d4e67cf0e00c2173cc52904ea9d2a58d7c2062b1bac8673a8dd45c03bb946e220149
7
+ data.tar.gz: f9f776fc7ad11500b9f29c57a141012b883295f59e25c67d7393d07a6dde2aadaf71f7e2322848bdf67ba5feaebce3553c49a4004632e83f9fc5026b965278bf
@@ -1,8 +1,19 @@
1
- # Change Log
1
+ # Changelog
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
  This project *loosely tries* to adhere to [Semantic Versioning](http://semver.org/).
5
5
 
6
- ## [0.0.0]
7
- - item 1
6
+ ## [0.2.2]
7
+ - #3 fix test template
8
8
 
9
+ ## [0.2.1]
10
+ - set prefix to @folder for performance improvement
11
+
12
+ ## [0.2.0]
13
+ - #1 include layer interface, update template to use expansion method, add region method
14
+
15
+ ## [0.1.1]
16
+ - update generator init terraform state path
17
+
18
+ ## [0.1.0]
19
+ - Initial release
data/Gemfile CHANGED
@@ -7,6 +7,5 @@ gem "rake", "~> 12.0"
7
7
  gem "rspec", "~> 3.0"
8
8
 
9
9
  group :development, :test do
10
- base = ENV['TS_EDGE_ROOT'] || "#{ENV['HOME']}/environment/terraspace-edge"
11
- gem "terraspace", path: "#{base}/terraspace"
10
+ gem "terraspace"
12
11
  end
@@ -1,7 +1,8 @@
1
1
  resource "azurerm_storage_account" "this" {
2
- name = var.name
3
- resource_group_name = var.resource_group_name
4
- location = var.location
5
- account_tier = "Standard"
6
- account_replication_type = "GRS"
2
+ name = var.name
3
+ resource_group_name = var.resource_group_name
4
+ location = var.location
5
+ account_tier = "Standard"
6
+ account_replication_type = "GRS"
7
+ enable_https_traffic_only = var.enable_https_traffic_only
7
8
  }
@@ -12,3 +12,9 @@ variable "location" {
12
12
  description = "The name of the storage location"
13
13
  type = string
14
14
  }
15
+
16
+ variable "enable_https_traffic_only" {
17
+ description = "forces HTTPS if enabled"
18
+ type = string
19
+ default = true
20
+ }
@@ -1,10 +1,10 @@
1
1
  # SUBSCRIPTION_HASH is a short 4-char consistent hash of the longer subscription id.
2
- # This is useful because azure storage accounts not allowed special characters and can only be 24 chars long.
2
+ # This is useful because azure storage account names are not allowed special characters and are limited to 24 chars.
3
3
  terraform {
4
4
  backend "azurerm" {
5
- resource_group_name = "<%= backend_expand('azurerm', 'terraform-resources-:LOCATION') %>"
6
- storage_account_name = "<%= backend_expand('azurerm', 'ts:SUBSCRIPTION_HASH:LOCATION:ENV') %>"
5
+ resource_group_name = "<%= expansion('terraform-resources-:LOCATION') %>"
6
+ storage_account_name = "<%= expansion('ts:SUBSCRIPTION_HASH:LOCATION:ENV') %>"
7
7
  container_name = "terraform-state"
8
- key = "<%= backend_expand('azurerm', ':LOCATION/:ENV/:BUILD_DIR') %>"
8
+ key = "<%= expansion(':LOCATION/:ENV/:BUILD_DIR/terraform.tfstate') %>"
9
9
  }
10
10
  }
@@ -1,5 +1,6 @@
1
1
  resource "random_pet" "this" {
2
- length = 1 # using 1, since default separator is '-', also account name can only be 24 characters, and lowercase letters
2
+ length = 2 # using 2, since default separator is '-', also account name can only be 24 characters, and lowercase letters
3
+ separator = ""# a blank string separator because azure storage accounts dont support - characters
3
4
  }
4
5
 
5
6
  resource "azurerm_resource_group" "this" {
@@ -8,8 +9,9 @@ resource "azurerm_resource_group" "this" {
8
9
  }
9
10
 
10
11
  module "storage_account" {
11
- source = "../../modules/example"
12
- name = "sa${random_pet.this.id}"
13
- resource_group_name = azurerm_resource_group.this.name
14
- location = azurerm_resource_group.this.location
12
+ source = "../../modules/example"
13
+ name = "sa${random_pet.this.id}"
14
+ resource_group_name = azurerm_resource_group.this.name
15
+ location = azurerm_resource_group.this.location
16
+ enable_https_traffic_only = var.enable_https_traffic_only
15
17
  }
@@ -1 +1,5 @@
1
- # This is where you put an example
1
+ variable "enable_https_traffic_only" {
2
+ description = "forces HTTPS if enabled"
3
+ type = string
4
+ default = true
5
+ }
@@ -1,8 +1,8 @@
1
1
  # SUBSCRIPTION_HASH is a short 4-char consistent hash of the longer subscription id.
2
- # This is useful because azure storage accounts not allowed special characters and can only be 24 chars long.
2
+ # This is useful because azure storage account names are not allowed special characters and are limited to 24 chars.
3
3
  backend("azurerm",
4
4
  resource_group_name: "terraform-resources-:LOCATION",
5
5
  storage_account_name: "ts:SUBSCRIPTION_HASH:LOCATION:ENV",
6
6
  container_name: "terraform-state",
7
- key: ":LOCATION/:ENV/:BUILD_DIR",
7
+ key: ":LOCATION/:ENV/:BUILD_DIR/terraform.tfstate",
8
8
  )
@@ -0,0 +1,4 @@
1
+ Terraspace.configure do |config|
2
+ config.logger.level = :info
3
+ config.test_framework = "rspec"
4
+ end
@@ -8,6 +8,7 @@ describe "main" do
8
8
  stacks: "app/stacks", # include all stacks in this folder
9
9
  # override demo stack tfvars for testing
10
10
  # copied over to test harness' app/stacks/demo/tfvars/test.tfvars
11
+ # need for azure
11
12
  tfvars: {demo: "spec/fixtures/tfvars/demo.tfvars"},
12
13
  config: "spec/fixtures/config",
13
14
  )
@@ -18,9 +19,6 @@ describe "main" do
18
19
  end
19
20
 
20
21
  it "successful deploy" do
21
- # Replace with your actual test
22
- expect(true).to be true
23
- # Example
24
22
  storage_account_id = terraspace.output("demo", "storage_account_id")
25
23
  expect(storage_account_id).to include("sa") # starts with sa
26
24
  end
@@ -18,6 +18,11 @@ module TerraspacePluginAzurerm
18
18
  def configure(&block)
19
19
  Interfaces::Config.instance.configure(&block)
20
20
  end
21
+
22
+ def config
23
+ Interfaces::Config.instance.config
24
+ end
25
+
21
26
  extend self
22
27
  end
23
28
 
@@ -17,5 +17,9 @@ class TerraspacePluginAzurerm::Interfaces::Backend
17
17
  AzureInfo
18
18
  end
19
19
  memoize :azure_info
20
+
21
+ def logger
22
+ Terraspace.logger
23
+ end
20
24
  end
21
25
  end
@@ -5,7 +5,7 @@ class TerraspacePluginAzurerm::Interfaces::Backend
5
5
 
6
6
  def create
7
7
  if exist?
8
- puts "Resource Group #{@resource_group_name} already exists" if ENV['TS_LOUD']
8
+ logger.debug "Resource Group #{@resource_group_name} already exists"
9
9
  else
10
10
  create_resource_group
11
11
  end
@@ -16,7 +16,7 @@ class TerraspacePluginAzurerm::Interfaces::Backend
16
16
  end
17
17
 
18
18
  def create_resource_group
19
- puts "Creating Resource Group #{@resource_group_name}..."
19
+ logger.info "Creating Resource Group #{@resource_group_name}..."
20
20
  resource_group = ResourceGroup.new
21
21
  resource_group.name = @resource_group_name
22
22
  resource_group.location = config.location || AzureInfo.location
@@ -5,7 +5,7 @@ class TerraspacePluginAzurerm::Interfaces::Backend
5
5
 
6
6
  def create
7
7
  if exist?
8
- puts "Storage Account #{@storage_account_name} already exists" if ENV['TS_LOUD']
8
+ logger.debug "Storage Account #{@storage_account_name} already exists"
9
9
  else
10
10
  create_storage_account
11
11
  end
@@ -24,8 +24,8 @@ class TerraspacePluginAzurerm::Interfaces::Backend
24
24
 
25
25
  case result.reason
26
26
  when "AccountNameInvalid"
27
- puts "ERROR: Failed to create storage account, reason: #{result.reason}".color(:red)
28
- puts "Provided storage_account_name: #{@storage_account_name}"
27
+ logger.error "ERROR: Failed to create storage account, reason: #{result.reason}".color(:red)
28
+ logger.error "Provided storage_account_name: #{@storage_account_name}"
29
29
  exit 1
30
30
  else
31
31
  false
@@ -33,7 +33,7 @@ class TerraspacePluginAzurerm::Interfaces::Backend
33
33
  end
34
34
 
35
35
  def create_storage_account
36
- puts "Creating Storage Account #{@storage_account_name}..."
36
+ logger.info "Creating Storage Account #{@storage_account_name}..."
37
37
  storage_accounts.create(@resource_group_name, @storage_account_name, storage_account_params)
38
38
  end
39
39
 
@@ -5,7 +5,7 @@ class TerraspacePluginAzurerm::Interfaces::Backend
5
5
 
6
6
  def create
7
7
  if exist?
8
- puts "Storage Container #{@container_name} already exists" if ENV['TS_LOUD']
8
+ logger.debug "Storage Container #{@container_name} already exists"
9
9
  else
10
10
  create_storage_container
11
11
  end
@@ -21,7 +21,7 @@ class TerraspacePluginAzurerm::Interfaces::Backend
21
21
  end
22
22
 
23
23
  def create_storage_container
24
- puts "Creating Storage Container #{@container_name}..."
24
+ logger.info "Creating Storage Container #{@container_name}..."
25
25
  blob_container = BlobContainer.new
26
26
  blob_container.name = @container_name
27
27
  blob_containers.create(@resource_group_name, @storage_account_name, @container_name, blob_container)
@@ -3,6 +3,8 @@ module TerraspacePluginAzurerm::Interfaces
3
3
  include Terraspace::Plugin::Config::Interface
4
4
  include Singleton # Config class must be a Singleton with the class .instance method
5
5
 
6
+ # interface method
7
+ # load_project_config: config/plugins/azurerm.rb
6
8
  def provider
7
9
  "azurerm"
8
10
  end
@@ -16,21 +16,18 @@ module TerraspacePluginAzurerm::Interfaces
16
16
 
17
17
  delegate :subscription_id, :subscription, :tenant_id, :tenant_id, :group, :location, to: :azure_info
18
18
  alias_method :namespace, :subscription
19
+ alias_method :region, :location
19
20
 
20
21
  def azure_info
21
22
  AzureInfo
22
23
  end
23
24
 
24
25
  # subscription_hash is a short 4-char consistent hash of the longer subscription id.
25
- # This is useful because azure storage accounts not allowed special characters and can only be 24 chars long.
26
+ # This is useful because azure storage account names are not allowed special characters and are limited to 24 chars.
26
27
  # NOTE: be careful to not change this! or else state path will change
27
28
  def subscription_hash
28
29
  Digest::SHA1.hexdigest(subscription)[0..3]
29
30
  end
30
-
31
- # NOTE: be careful to not change this! or else state path will change
32
- def namespace_hash
33
- Digest::SHA1.hexdigest(subscription)[0..3]
34
- end
31
+ alias_method :namespace_hash, :subscription_hash
35
32
  end
36
33
  end
@@ -1,6 +1,7 @@
1
1
  module TerraspacePluginAzurerm::Interfaces
2
2
  class Layer
3
3
  extend Memoist
4
+ include Terraspace::Plugin::Layer::Interface
4
5
 
5
6
  # interface method
6
7
  def namespace
@@ -11,10 +12,5 @@ module TerraspacePluginAzurerm::Interfaces
11
12
  def region
12
13
  AzureInfo.location
13
14
  end
14
-
15
- # interface method
16
- def provider
17
- "azurerm"
18
- end
19
15
  end
20
16
  end
@@ -0,0 +1,122 @@
1
+ require 'azure/storage/blob'
2
+
3
+ module TerraspacePluginAzurerm::Interfaces
4
+ class Summary
5
+ include Terraspace::Plugin::Summary::Interface
6
+ include TerraspacePluginAzurerm::Clients::Storage # for mgmt storage_accounts to get keys only, the azure/storage/blob gem is used to get the objects
7
+ extend Memoist
8
+
9
+ # interface method
10
+ def bucket_field
11
+ 'storage_account_name'
12
+ end
13
+
14
+ # interface method
15
+ def download
16
+ marker = nil
17
+ loop do
18
+ blobs = list_blobs(container_name, marker: marker)
19
+ blobs.each do |blob|
20
+ blob, content = blob_client.get_blob(container_name, blob.name)
21
+ local_path = "#{@dest}/#{blob.name}"
22
+ FileUtils.mkdir_p(File.dirname(local_path))
23
+ File.open(local_path, 'wb') {|f| f.write(content)}
24
+ end
25
+ marker = blobs.continuation_token
26
+ break unless marker && !marker.empty?
27
+ end
28
+ end
29
+
30
+ # interface method
31
+ def delete_empty_statefile(key)
32
+ delete_blob(key)
33
+ end
34
+
35
+ def delete_blob(key)
36
+ blob_client.delete_blob(container_name, key)
37
+ rescue Azure::Core::Http::HTTPError => e
38
+ case e.message
39
+ when /BlobNotFound/
40
+ logger.info "WARN: #{e.class}: #{e.message}"
41
+ logger.info "Blob item does not exist: #{key}"
42
+ when /ContainerNotFound/
43
+ logger.info "WARN: #{e.class}: #{e.message}"
44
+ logger.info "Container not found: #{container_name}"
45
+ else
46
+ raise
47
+ end
48
+ end
49
+
50
+ def container_name
51
+ @info['container_name']
52
+ end
53
+
54
+ # Friendly error handling for user
55
+ def list_blobs(container_name, marker:)
56
+ blob_client.list_blobs(container_name, marker: marker, prefix: @folder)
57
+ rescue Azure::Core::Http::HTTPError => e
58
+ if e.message.include?("AuthenticationFailed")
59
+ logger.error "e.class #{e.class}: #{e.message}"
60
+ logger.error "Unable to authenticate to download the statefiles from the storage account.".color(:red)
61
+ if ENV['AZURE_STORAGE_ACCESS_KEY']
62
+ logger.error <<~EOL
63
+ It looks like you have the AZURE_STORAGE_ACCESS_KEY environment variable set.
64
+ It may be the incorrect key for the storage account: #{@info['storage_account_name']}
65
+ Try unsetting it:
66
+
67
+ unset AZURE_STORAGE_ACCESS_KEY
68
+
69
+ When the environment variable is not set, this library will try to fetch the key for you.
70
+ Or you can try setting the correct key.
71
+ EOL
72
+ else
73
+ logger.error <<~EOL
74
+ The fetched storage access key did not seem to authenticate successfully.
75
+ Try setting the AZURE_STORAGE_ACCESS_KEY environment variable with access to the storage account: #{@info['storage_account_name']}
76
+ EOL
77
+ end
78
+ # Common message
79
+ logger.error <<~EOL
80
+ One way to get the key is with:
81
+
82
+ az storage account keys list --account-name #{@info['storage_account_name']} --resource-group #{@info['resource_group_name']}
83
+
84
+ Then you can set it:
85
+
86
+ export AZURE_STORAGE_ACCESS_KEY=[replace-with-value]
87
+ EOL
88
+ exit 1
89
+ else
90
+ raise
91
+ end
92
+ end
93
+
94
+ private
95
+ def blob_client
96
+ # Note per docs: https://github.com/azure/azure-storage-ruby/tree/master/blob#via-environment-variables
97
+ #
98
+ # export AZURE_STORAGE_ACCOUNT = <your azure storage account name>
99
+ # export AZURE_STORAGE_ACCESS_KEY = <your azure storage access key>
100
+ #
101
+ # Works if zero args are passed to the create method. But set the storage_account_name arg, so we must also set
102
+ # the storage_access_key explicitly. We'll follow the same env variable convention.
103
+ #
104
+ Azure::Storage::Blob::BlobService.create(
105
+ storage_account_name: @info['storage_account_name'],
106
+ storage_access_key: storage_access_key
107
+ )
108
+ end
109
+ memoize :blob_client
110
+
111
+ def storage_access_key
112
+ ENV['AZURE_STORAGE_ACCESS_KEY'] || fetch_storage_access_key
113
+ end
114
+
115
+ def fetch_storage_access_key
116
+ # result is a StorageAccountListKeysResult with a keys reader method
117
+ # then .value contains the key
118
+ result = storage_accounts.list_keys(@info['resource_group_name'], @info['storage_account_name'])
119
+ result.keys.first.value
120
+ end
121
+ end
122
+ end
@@ -1,3 +1,3 @@
1
1
  module TerraspacePluginAzurerm
2
- VERSION = "0.0.0"
2
+ VERSION = "0.2.2"
3
3
  end
@@ -22,7 +22,8 @@ Gem::Specification.new do |spec|
22
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
23
  spec.require_paths = ["lib"]
24
24
 
25
- # spec.add_dependency "azure_info"
25
+ spec.add_dependency "azure-storage-blob"
26
+ spec.add_dependency "azure_info"
26
27
  spec.add_dependency "azure_mgmt_resources"
27
28
  spec.add_dependency "azure_mgmt_storage"
28
29
  spec.add_dependency "memoist"
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: terraspace_plugin_azurerm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-06-02 00:00:00.000000000 Z
11
+ date: 2020-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: azure-storage-blob
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: azure_info
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'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: azure_mgmt_resources
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -106,6 +134,7 @@ files:
106
134
  - lib/templates/test/rspec/module/test/spec/fixtures/stack/variables.tf
107
135
  - lib/templates/test/rspec/module/test/spec/main_spec.rb.tt
108
136
  - lib/templates/test/rspec/module/test/spec/spec_helper.rb
137
+ - lib/templates/test/rspec/project/spec/fixtures/config/app.rb
109
138
  - lib/templates/test/rspec/project/spec/fixtures/config/terraform/provider.tf
110
139
  - lib/templates/test/rspec/project/spec/fixtures/tfvars/demo.tfvars
111
140
  - lib/templates/test/rspec/project/spec/spec_helper.rb
@@ -123,6 +152,7 @@ files:
123
152
  - lib/terraspace_plugin_azurerm/interfaces/config.rb
124
153
  - lib/terraspace_plugin_azurerm/interfaces/expander.rb
125
154
  - lib/terraspace_plugin_azurerm/interfaces/layer.rb
155
+ - lib/terraspace_plugin_azurerm/interfaces/summary.rb
126
156
  - lib/terraspace_plugin_azurerm/version.rb
127
157
  - terraspace_plugin_azurerm.gemspec
128
158
  homepage: https://github.com/boltops-tools/terraspace_plugin_azurerm