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 +4 -4
- data/CHANGELOG.md +14 -3
- data/Gemfile +1 -2
- data/lib/templates/hcl/module/main.tf +6 -5
- data/lib/templates/hcl/module/variables.tf +6 -0
- data/lib/templates/hcl/project/config/terraform/backend.tf +4 -4
- data/lib/templates/hcl/stack/main.tf +7 -5
- data/lib/templates/hcl/stack/variables.tf +5 -1
- data/lib/templates/ruby/project/config/terraform/backend.rb +2 -2
- data/lib/templates/test/rspec/project/spec/fixtures/config/app.rb +4 -0
- data/lib/templates/test/rspec/project/spec/stacks/demo/main_spec.rb +1 -3
- data/lib/terraspace_plugin_azurerm.rb +5 -0
- data/lib/terraspace_plugin_azurerm/interfaces/backend/base.rb +4 -0
- data/lib/terraspace_plugin_azurerm/interfaces/backend/resource_group_creator.rb +2 -2
- data/lib/terraspace_plugin_azurerm/interfaces/backend/storage_account.rb +4 -4
- data/lib/terraspace_plugin_azurerm/interfaces/backend/storage_container.rb +2 -2
- data/lib/terraspace_plugin_azurerm/interfaces/config.rb +2 -0
- data/lib/terraspace_plugin_azurerm/interfaces/expander.rb +3 -6
- data/lib/terraspace_plugin_azurerm/interfaces/layer.rb +1 -5
- data/lib/terraspace_plugin_azurerm/interfaces/summary.rb +122 -0
- data/lib/terraspace_plugin_azurerm/version.rb +1 -1
- data/terraspace_plugin_azurerm.gemspec +2 -1
- metadata +32 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b3ff4bc13ad8e73d40b985420c107ef791d652bde858092271a239715ec6b824
|
4
|
+
data.tar.gz: cdbc5ddac31c0c4fad5676ea802810fd9982f02a59f3347bf72d4e407f7abec7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 878dc0469567622cd0bf3ef0c378ae5ba9962035511110fdb057892873d0d4e67cf0e00c2173cc52904ea9d2a58d7c2062b1bac8673a8dd45c03bb946e220149
|
7
|
+
data.tar.gz: f9f776fc7ad11500b9f29c57a141012b883295f59e25c67d7393d07a6dde2aadaf71f7e2322848bdf67ba5feaebce3553c49a4004632e83f9fc5026b965278bf
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,19 @@
|
|
1
|
-
#
|
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.
|
7
|
-
-
|
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
@@ -1,7 +1,8 @@
|
|
1
1
|
resource "azurerm_storage_account" "this" {
|
2
|
-
name
|
3
|
-
resource_group_name
|
4
|
-
location
|
5
|
-
account_tier
|
6
|
-
account_replication_type
|
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
|
}
|
@@ -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
|
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 = "<%=
|
6
|
-
storage_account_name = "<%=
|
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 = "<%=
|
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 =
|
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
|
12
|
-
name
|
13
|
-
resource_group_name
|
14
|
-
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,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
|
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
|
)
|
@@ -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
|
@@ -5,7 +5,7 @@ class TerraspacePluginAzurerm::Interfaces::Backend
|
|
5
5
|
|
6
6
|
def create
|
7
7
|
if exist?
|
8
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
28
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
@@ -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
|
-
|
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.
|
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-
|
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
|