terraspace_plugin_azurerm 0.0.0 → 0.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5558017d6143d6bfda510f1aab5508130506d1a9de81bc75582b145ee2867d3b
4
- data.tar.gz: ec7ece5847e2cb02ba991d00ceb7d91e60b4d1886a2c1d7c23333e3fd4369a2d
3
+ metadata.gz: 96bcbc4372bc972b9aac47dea9ae90c9b666934a3d7b8a0384d96a793bd0c85e
4
+ data.tar.gz: d6f539c1ada933e1227e53e9e4a133ddc21425800e59c6eda3c59f88d0b1a76e
5
5
  SHA512:
6
- metadata.gz: 33461605e1ff3b16b2eb0d7b4b0230805dc34542181aa51a48a2d6e41a8b1940951673452cc1d9e06a642b47e6b427403edd9265edebffa3a26f190eba081ee3
7
- data.tar.gz: '004158f2120660455a6450b581ceda03ce91bacd45b32b836149672fa0b5f800e79b58563c754c65d69d90556a56c900039e4a71caccf3687f138bc5b34f50c1'
6
+ metadata.gz: 4d6f485d4b65dc2dbf12ca58215422390593ee78a78c1d41dc69e06322fb959722246a77d3845457bdaaee3c6093e0d2a3fdd6c1726591bfe1b15b46adfdf896
7
+ data.tar.gz: a37fb5daa3b964c2c2c743ec3636302412e6207c5d3cb4563ad482f13f869477362aa1403357c61096a0fac925b5305c16c56456de471ff64fe6420c5e576adb
@@ -1,8 +1,7 @@
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
8
-
6
+ ## [0.1.0]
7
+ - 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
+ }
@@ -5,6 +5,6 @@ terraform {
5
5
  resource_group_name = "<%= backend_expand('azurerm', 'terraform-resources-:LOCATION') %>"
6
6
  storage_account_name = "<%= backend_expand('azurerm', 'ts:SUBSCRIPTION_HASH:LOCATION:ENV') %>"
7
7
  container_name = "terraform-state"
8
- key = "<%= backend_expand('azurerm', ':LOCATION/:ENV/:BUILD_DIR') %>"
8
+ key = "<%= backend_expand('azurerm', ':LOCATION/:ENV/:BUILD_DIR.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
+ }
@@ -4,5 +4,5 @@ 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.tfstate",
8
8
  )
@@ -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
@@ -27,10 +27,6 @@ module TerraspacePluginAzurerm::Interfaces
27
27
  def subscription_hash
28
28
  Digest::SHA1.hexdigest(subscription)[0..3]
29
29
  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
30
+ alias_method :namespace_hash, :subscription_hash
35
31
  end
36
32
  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)
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.1.0"
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.1.0
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-07-23 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
@@ -123,6 +151,7 @@ files:
123
151
  - lib/terraspace_plugin_azurerm/interfaces/config.rb
124
152
  - lib/terraspace_plugin_azurerm/interfaces/expander.rb
125
153
  - lib/terraspace_plugin_azurerm/interfaces/layer.rb
154
+ - lib/terraspace_plugin_azurerm/interfaces/summary.rb
126
155
  - lib/terraspace_plugin_azurerm/version.rb
127
156
  - terraspace_plugin_azurerm.gemspec
128
157
  homepage: https://github.com/boltops-tools/terraspace_plugin_azurerm