Skip to content

Commit 5233397

Browse files
feat: Updates (#1)
* fix * update * update versions * badgen * badgen * updates * updates * updates * update * update * update README * update descriptor formats * updates * updates * updates * fix * updates * updates * fix * docs: enable contrib badges and refresh .envrc Co-authored-by: Piotr Mossakowski <[email protected]>
1 parent 5e31dc9 commit 5233397

23 files changed

+314
-110
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@ override.tf.json
3333
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
3434
# example: *tfplan*
3535
*tfplan*
36+
.idea

README.md

+51-51
Large diffs are not rendered by default.

examples/complete/.env.dist

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
SNOWFLAKE_USER=
2+
SNOWFLAKE_PASSWORD=
3+
SNOWFLAKE_ROLE=
4+
SNOWFLAKE_ACCOUNT=

examples/complete/.envrc

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
#Override defaults
2-
command -v dotenv && test -f .env && dotenv
1+
dotenv_if_exists

examples/complete/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.env

examples/complete/README.md

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
# Complete Example
22

33
```terraform
4-
module "terraform_module_template" {
4+
module "terraform_snowflake_user" {
55
source = "../../"
66
context = module.this.context
7-
8-
example_var = "This is a example value."
7+
name = "snowflake-user"
98
}
109
```
1110

examples/complete/fixtures.tfvars

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
descriptor_formats = {
2-
2+
snowflake-user = {
3+
labels = ["name"]
4+
format = "%v"
5+
}
36
}
47

58
tags = {

examples/complete/main.tf

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
module "terraform_module_template" {
2-
source = "../../"
3-
context = module.this.context
4-
5-
example_var = "This is a example value."
1+
module "terraform_snowflake_user" {
2+
source = "../../"
3+
context = module.this.context
4+
name = "snowflake-user"
5+
generate_rsa_key = true
6+
generate_password = true
67
}

examples/complete/outputs.tf

+11-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
output "example_output" {
2-
description = "Example output of the module"
3-
value = module.terraform_module_template
1+
output "display_name" {
2+
description = "Specifies the namespace (database only or database and schema) that is active by default for the user's session upon login"
3+
value = module.terraform_snowflake_user.display_name
4+
}
5+
output "login_name" {
6+
description = "The name users use to log in"
7+
value = module.terraform_snowflake_user.login_name
8+
}
9+
output "default_role" {
10+
description = "Specifies the role that is active by default for the user's session upon login"
11+
value = module.terraform_snowflake_user.default_role
412
}

examples/complete/versions.tf

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
terraform {
2-
required_version = ">= 0.15.0"
2+
required_version = ">= 1.3.0"
33

44
required_providers {
55
null = {

examples/simple/.env.dist

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
SNOWFLAKE_USER=
2+
SNOWFLAKE_PASSWORD=
3+
SNOWFLAKE_ROLE=
4+
SNOWFLAKE_ACCOUNT=

examples/simple/.envrc

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
#Override defaults
2-
command -v dotenv && test -f .env && dotenv
1+
dotenv_if_exists

examples/simple/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.env

examples/simple/README.md

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
# Simple Example
22

33
```terraform
4-
module "terraform_module_template" {
4+
module "terraform_snowflake_user" {
55
source = "../../"
6-
7-
example_var = "This is a example value."
6+
name = "snowflake-user"
87
}
98
```
109

examples/simple/main.tf

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
module "terraform_module_template" {
1+
module "terraform_snowflake_user" {
22
source = "../../"
3-
4-
example_var = "This is a example value."
3+
name = "snowflake-user"
54
}

examples/simple/outputs.tf

+11-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
output "example_output" {
2-
description = "Example output of the module"
3-
value = module.terraform_module_template
1+
output "display_name" {
2+
description = "Specifies the namespace (database only or database and schema) that is active by default for the user's session upon login"
3+
value = module.terraform_snowflake_user.display_name
4+
}
5+
output "login_name" {
6+
description = "The name users use to log in"
7+
value = module.terraform_snowflake_user.login_name
8+
}
9+
output "default_role" {
10+
description = "Specifies the role that is active by default for the user's session upon login"
11+
value = module.terraform_snowflake_user.default_role
412
}

examples/simple/providers.tf

-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
provider "null" {
2-
# Configuration options
32
}

examples/simple/versions.tf

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
terraform {
2-
required_version = ">= 0.15.0"
2+
required_version = ">= 1.3.0"
33

44
required_providers {
55
null = {

locals.tf

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
locals {
2-
# Get a name from the descriptor. If not available, use default naming convention.
3-
# Trim and replace function are used to avoid bare delimiters on both ends of the name and situation of adjacent delimiters.
4-
name_from_descriptor = trim(replace(
5-
lookup(module.this.descriptors, "module-resource-name", module.this.id), "/${module.this.delimiter}${module.this.delimiter}+/", module.this.delimiter
6-
), module.this.delimiter)
2+
name_from_descriptor = module.user_label.enabled ? trim(replace(
3+
lookup(module.user_label.descriptors, var.descriptor_name, module.user_label.id), "/${module.user_label.delimiter}${module.user_label.delimiter}+/", module.user_label.delimiter
4+
), module.user_label.delimiter) : null
75

8-
enabled = module.this.enabled
6+
rsa_public_key = var.generate_rsa_key ? join("", split("\n", trim(one(resource.tls_private_key.this[*].public_key_pem), "- \n BEGIN END PUBLIC KEY"))) : var.rsa_public_key
7+
generate_password = module.this.enabled && var.generate_password
8+
generate_rsa_key = module.this.enabled && var.generate_rsa_key
99
}

main.tf

+51-11
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,55 @@
1-
# Example resource that outputs the input value and
2-
# echoes it's base64 encoded version locally
1+
/*
2+
* # Snowflake User
3+
*
4+
* Terraform module can:
5+
* * Create and manage Snowflake Users
6+
* * Automatically generate RSA private and public keys for the user
7+
*/
8+
module "user_label" {
9+
source = "cloudposse/label/null"
10+
version = "0.25.0"
11+
context = module.this.context
312

4-
resource "null_resource" "output_input" {
5-
count = local.enabled ? 1 : 0
13+
delimiter = coalesce(module.this.context.delimiter, "_")
14+
regex_replace_chars = coalesce(module.this.context.regex_replace_chars, "/[^_a-zA-Z0-9]/")
15+
label_value_case = coalesce(module.this.context.label_value_case, "upper")
16+
name = "snowflake-user"
617

7-
triggers = {
8-
name = local.name_from_descriptor
9-
input = var.example_var
10-
}
18+
}
19+
20+
resource "tls_private_key" "this" {
21+
count = local.generate_rsa_key ? 1 : 0
22+
23+
algorithm = "RSA"
24+
rsa_bits = 4096
25+
}
26+
resource "random_password" "this" {
27+
count = local.generate_password ? 1 : 0
28+
length = 16
29+
special = true
30+
override_special = "!#$%&*()-_=+[]{}<>:?"
31+
}
32+
33+
resource "snowflake_user" "this" {
34+
count = module.this.enabled ? 1 : 0
35+
36+
name = local.name_from_descriptor
37+
login_name = var.login_name
38+
display_name = var.display_name
39+
comment = var.comment
40+
41+
password = one(random_password.this[*].result)
42+
must_change_password = true # When password set here - always change password on login
43+
44+
email = var.email
45+
first_name = var.first_name
46+
last_name = var.last_name
47+
48+
default_namespace = var.default_namespace
49+
default_warehouse = var.default_warehouse
50+
default_role = var.default_role
51+
default_secondary_roles = var.default_secondary_roles
1152

12-
provisioner "local-exec" {
13-
command = "echo ${var.example_var} | base64"
14-
}
53+
rsa_public_key = local.rsa_public_key
54+
rsa_public_key_2 = var.rsa_public_key_2
1555
}

outputs.tf

+47-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,49 @@
1-
# Example output from the module
1+
output "default_namespace" {
2+
description = "Specifies the namespace (database only or database and schema) that is active by default for the user's session upon login"
3+
value = one(snowflake_user.this[*].default_namespace)
4+
}
5+
6+
output "default_role" {
7+
description = "Specifies the role that is active by default for the user's session upon login"
8+
value = one(snowflake_user.this[*].default_role)
9+
}
10+
11+
output "default_warehouse" {
12+
description = "Specifies the virtual warehouse that is active by default for the user's session upon login"
13+
value = one(snowflake_user.this[*].default_warehouse)
14+
}
15+
16+
output "disabled" {
17+
description = "Whether user account is disabled"
18+
value = one(snowflake_user.this[*].disabled)
19+
}
20+
21+
output "login_name" {
22+
description = "The name users use to log in"
23+
value = one(snowflake_user.this[*].login_name)
24+
}
25+
26+
output "name" {
27+
description = "Name of the user"
28+
value = one(snowflake_user.this[*].name)
29+
}
30+
31+
output "display_name" {
32+
description = "Name displayed for the user in the Snowflake web interface"
33+
value = one(snowflake_user.this[*].display_name)
34+
}
35+
36+
output "first_name" {
37+
description = "First name of the user"
38+
value = one(snowflake_user.this[*].first_name)
39+
}
40+
41+
output "last_name" {
42+
description = "Last name of the user"
43+
value = one(snowflake_user.this[*].last_name)
44+
}
245

3-
output "example_output" {
4-
description = "Example output of the module"
5-
value = one(null_resource.output_input[*].id)
46+
output "email" {
47+
description = "Email address for the user"
48+
value = one(snowflake_user.this[*].email)
649
}

variables.tf

+94-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,97 @@
1-
# Example, compulsory input variable
1+
variable "login_name" {
2+
description = "The name users use to log in. If not supplied, snowflake will use name instead."
3+
type = string
4+
default = null
5+
}
6+
7+
variable "display_name" {
8+
description = "Name displayed for the user in the Snowflake web interface."
9+
type = string
10+
default = null
11+
}
212

3-
variable "example_var" {
4-
description = "Example varible passed into the module"
13+
variable "comment" {
14+
description = "Comment / description of Snowflake user"
515
type = string
16+
default = null
17+
}
18+
19+
variable "email" {
20+
description = "Email address for the user"
21+
type = string
22+
default = null
23+
}
24+
25+
variable "first_name" {
26+
description = "First name of the user"
27+
type = string
28+
default = null
29+
}
30+
31+
variable "last_name" {
32+
description = "Last name of the user"
33+
type = string
34+
default = null
35+
}
36+
37+
variable "default_namespace" {
38+
description = "Specifies the namespace (database only or database and schema) that is active by default for the user's session upon login."
39+
type = string
40+
default = null
41+
}
42+
43+
variable "default_warehouse" {
44+
description = "Specifies the virtual warehouse that is active by default for the user's session upon login."
45+
type = string
46+
default = null
47+
}
48+
49+
variable "default_role" {
50+
description = "Specifies the role that is active by default for the user's session upon login."
51+
type = string
52+
default = null
53+
}
54+
55+
variable "default_secondary_roles" {
56+
description = "Specifies the set of secondary roles that are active for the user's session upon login."
57+
type = list(string)
58+
default = []
59+
}
60+
61+
variable "rsa_public_key" {
62+
description = "Specifies the user's RSA public key; used for key-pair authentication. Must be on 1 line without header and trailer."
63+
type = string
64+
default = null
65+
}
66+
67+
variable "rsa_public_key_2" {
68+
description = <<EOT
69+
Specifies the user's second RSA public key; used to rotate the public and private keys
70+
for key-pair authentication based on an expiration schedule set by your organization.
71+
Must be on 1 line without header and trailer."
72+
EOT
73+
type = string
74+
default = null
75+
}
76+
77+
variable "generate_rsa_key" {
78+
description = <<EOT
79+
Whether automatically generate an RSA key - IMPORTANT
80+
The private key generated by this resource will be stored
81+
unencrypted in your Terraform state file.
82+
Use of this resource for production deployments is not recommended.
83+
EOT
84+
type = bool
85+
default = false
86+
}
87+
88+
variable "descriptor_name" {
89+
description = "Name of the descriptor used to form a Snowflake User name"
90+
type = string
91+
default = "snowflake-user"
92+
}
93+
variable "generate_password" {
94+
description = "Generate a random password using Terraform"
95+
type = bool
96+
default = false
697
}

versions.tf

+12-7
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
# Example configuration of terraform providers
2-
31
terraform {
4-
required_version = ">= 0.15.0"
5-
2+
required_version = ">= 1.3.0"
63
required_providers {
7-
null = {
8-
source = "hashicorp/null"
9-
version = "3.1.1"
4+
snowflake = {
5+
source = "Snowflake-Labs/snowflake"
6+
version = "~> 0.54"
7+
}
8+
tls = {
9+
source = "hashicorp/tls"
10+
version = "~> 4.0"
11+
}
12+
random = {
13+
source = "hashicorp/random"
14+
version = ">= 3.0.0"
1015
}
1116
}
1217
}

0 commit comments

Comments
 (0)