Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GNUmakefile text eol=lf
*.sh text eol=lf
13 changes: 9 additions & 4 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ TEST?=$$(go list ./... |grep -v 'vendor')
GOFMT_FILES?=$$(find . -name '*.go' |grep -v vendor)
WEBSITE_REPO=github.com/hashicorp/terraform-website
PKG_NAME=mysql
TERRAFORM_VERSION=0.14.7
TERRAFORM_VERSION=1.11.3
TERRAFORM_OS=$(shell uname -s | tr A-Z a-z)
TEST_USER=root
TEST_PASSWORD=my-secret-pw
Expand All @@ -20,15 +20,19 @@ bin/terraform:
(cd $(CURDIR)/bin/ ; unzip terraform.zip)

testacc: fmtcheck bin/terraform
PATH="$(CURDIR)/bin:${PATH}" TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout=120s
PATH="$(CURDIR)/bin:${PATH}" TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout=600s

acceptance: testversion5.6 testversion5.7 testversion8.0 testpercona5.7 testpercona8.0 testmariadb10.3 testmariadb10.8 testmariadb10.10 testtidb6.1.0 testtidb7.5.2
acceptance: testversion5.6 testversion5.7 testversion8.0 testversion8.4.5 testpercona5.7 testpercona8.0 testmariadb10.3 testmariadb10.8 testmariadb10.10 testtidb6.1.0 testtidb7.5.2

testversion%:
$(MAKE) MYSQL_VERSION=$* MYSQL_PORT=33$(shell echo "$*" | tr -d '.') testversion

testversion:
-docker run --rm --name test-mysql$(MYSQL_VERSION) -e MYSQL_ROOT_PASSWORD="$(TEST_PASSWORD)" -d -p $(MYSQL_PORT):3306 mysql:$(MYSQL_VERSION)
@MYSQLD_ARGS=""; \
if [ "$$(echo $(MYSQL_VERSION) | awk -F. '{ if ($$1 > 8 || ($$1 == 8 && $$2 >= 4)) print 1; else print 0 }')" -eq 1 ]; then \
MYSQLD_ARGS="mysqld --mysql-native-password=ON"; \
fi; \
docker run --rm --name test-mysql$(MYSQL_VERSION) -e MYSQL_ROOT_PASSWORD="$(TEST_PASSWORD)" -d -p $(MYSQL_PORT):3306 mysql:$(MYSQL_VERSION) $$MYSQLD_ARGS
@echo 'Waiting for MySQL...'
@while ! mysql -h 127.0.0.1 -P $(MYSQL_PORT) -u "$(TEST_USER)" -p"$(TEST_PASSWORD)" -e 'SELECT 1' >/dev/null 2>&1; do printf '.'; sleep 1; done ; echo ; echo "Connected!"
-mysql -h 127.0.0.1 -P $(MYSQL_PORT) -u "$(TEST_USER)" -p"$(TEST_PASSWORD)" -e "INSTALL PLUGIN mysql_no_login SONAME 'mysql_no_login.so';"
Expand Down Expand Up @@ -76,6 +80,7 @@ testmariadb:
MYSQL_USERNAME="$(TEST_USER)" MYSQL_PASSWORD="$(TEST_PASSWORD)" MYSQL_ENDPOINT=127.0.0.1:$(MYSQL_PORT) $(MAKE) testacc
-docker rm -f test-mariadb$(MYSQL_VERSION)


vet:
@echo "go vet ."
@go vet $$(go list ./... | grep -v vendor/) ; if [ $$? -eq 1 ]; then \
Expand Down
132 changes: 129 additions & 3 deletions mysql/resource_grant_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1033,7 +1033,7 @@ resource "mysql_grant" "test_procedure" {
host = "%s"
privileges = ["EXECUTE"]
database = "PROCEDURE %s"
table = "%s"
table = "%s"
}
`, dbName, dbName, dbName, dbName, hostName, dbName, procedureName)
}
Expand Down Expand Up @@ -1150,7 +1150,7 @@ func TestAllowDuplicateUsersDifferentTables(t *testing.T) {
user = "${mysql_user.test.user}"
host = "${mysql_user.test.host}"
database = "${mysql_database.test.name}"
table = "table1"
table = "table1"
privileges = ["UPDATE", "SELECT"]
}

Expand Down Expand Up @@ -1215,7 +1215,7 @@ func TestDisallowDuplicateUsersSameTable(t *testing.T) {
user = "${mysql_user.test.user}"
host = "${mysql_user.test.host}"
database = "${mysql_database.test.name}"
table = "table1"
table = "table1"
privileges = ["UPDATE", "SELECT"]
}

Expand Down Expand Up @@ -1246,3 +1246,129 @@ func TestDisallowDuplicateUsersSameTable(t *testing.T) {
},
})
}

// TestModifyPrivileges explicitly verifies the correct and incorrect ways of modifying privileges.
// It tests adding privileges by augmenting the existing grant (correct way).
// It also tests that dynamic privileges configured on the global (`*`) database can coexist with grants on specific databases.
func TestModifyPrivileges(t *testing.T) {
dbName := fmt.Sprintf("tf-test-modify-%d", rand.Intn(100))
roleName := fmt.Sprintf("TFRole-modify-%d", rand.Intn(100))
userName := fmt.Sprintf("jdoe-modify-%s", dbName)

onePrivilegeConfig := getGrantsSampleWithPrivileges(roleName, dbName, userName, `"SELECT"`)
twoPrivilegesConfig := getGrantsSampleWithPrivileges(roleName, dbName, userName, `"SELECT", "UPDATE"`)
additionalStaticPrivilegeConfig := twoPrivilegesConfig + getAdditionalGrantSample(dbName, `"INSERT"`)
threePrivilegesConfig := getGrantsSampleWithPrivileges(roleName, dbName, userName, `"SELECT", "UPDATE", "INSERT"`)
// Configuring dynamic privilege on global (`*`) database alongside specific database grants
additionalDynamicPrivilegeConfigFlushTables := threePrivilegesConfig + getAdditionalGrantSample("*", `"FLUSH_TABLES"`)
additionalDynamicPrivilegeConfigShowRoutine := threePrivilegesConfig + getAdditionalGrantSample("*", `"SHOW_ROUTINE"`)
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
testAccPreCheckSkipRds(t)
testAccPreCheckSkipMariaDB(t)
testAccPreCheckSkipNotMySQLVersionMin(t, "8.0.0")
testAccPreCheckSkipTiDB(t)
},
ProviderFactories: testAccProviderFactories,
CheckDestroy: testAccGrantCheckDestroy,
Steps: []resource.TestStep{
{
Config: testAccGrantConfigNoGrant(dbName),
},
{
Config: onePrivilegeConfig,
Check: resource.ComposeTestCheckFunc(
testAccPrivilege("mysql_grant.grant", "SELECT", true, false),
testAccPrivilege("mysql_grant.grant", "UPDATE", false, false),
testAccPrivilege("mysql_grant.grant", "INSERT", false, false),
),
},
{
// Correct way: augment existing grant with additional privileges
Config: twoPrivilegesConfig,
Check: resource.ComposeTestCheckFunc(
testAccPrivilege("mysql_grant.grant", "SELECT", true, false),
testAccPrivilege("mysql_grant.grant", "UPDATE", true, false),
testAccPrivilege("mysql_grant.grant", "INSERT", false, false),
),
},
{
// Incorrect way: create a new conflicting grant (expected to fail)
Config: additionalStaticPrivilegeConfig,
ExpectError: regexp.MustCompile("already has"),
},
{
// Correct way: augment existing grant with additional privileges
Config: threePrivilegesConfig,
Check: resource.ComposeTestCheckFunc(
testAccPrivilege("mysql_grant.grant", "SELECT", true, false),
testAccPrivilege("mysql_grant.grant", "UPDATE", true, false),
testAccPrivilege("mysql_grant.grant", "INSERT", true, false),
),
},

// Testing coexistence of dynamic privilege on global (`*`) database with specific database grants

{
Config: additionalDynamicPrivilegeConfigFlushTables,
Check: resource.ComposeTestCheckFunc(
testAccPrivilege("mysql_grant.grant", "SELECT", true, false),
testAccPrivilege("mysql_grant.grant", "UPDATE", true, false),
testAccPrivilege("mysql_grant.grant", "INSERT", true, false),
testAccPrivilege("mysql_grant.additional_grant", "FLUSH_TABLES", true, false),
testAccPrivilege("mysql_grant.additional_grant", "SHOW_ROUTINE", false, false),
),
},
{
Config: additionalDynamicPrivilegeConfigShowRoutine,
Check: resource.ComposeTestCheckFunc(
testAccPrivilege("mysql_grant.grant", "SELECT", true, false),
testAccPrivilege("mysql_grant.grant", "UPDATE", true, false),
testAccPrivilege("mysql_grant.grant", "INSERT", true, false),
testAccPrivilege("mysql_grant.additional_grant", "FLUSH_TABLES", false, false),
testAccPrivilege("mysql_grant.additional_grant", "SHOW_ROUTINE", true, false),
),
},
},
})
}

func getGrantsSampleWithPrivileges(roleName string, dbName string, userName string, privileges string) string {
return fmt.Sprintf(`

resource "mysql_role" "role" {
name = "%s"
}

resource "mysql_grant" "grant" {
role = "${mysql_role.role.name}"
database = "%s"
privileges = [%s]
}

resource "mysql_user" "user" {
user = "%s"
host = "%%"
}

resource "mysql_grant" "user_grant" {
user = "${mysql_user.user.user}"
host = "${mysql_user.user.host}"
database = "%s"
roles = ["${mysql_role.role.name}"]
}

`, roleName, dbName, privileges, userName, dbName)
}

func getAdditionalGrantSample(dbName string, privileges string) string {
return fmt.Sprintf(`

resource "mysql_grant" "additional_grant" {
role = "${mysql_role.role.name}"
database = "%s"
privileges = [%s]
}
`, dbName, privileges)
}
2 changes: 1 addition & 1 deletion scripts/changelog-links.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash

# This script rewrites [GH-nnnn]-style references in the CHANGELOG.md file to
# be Markdown links to the given github issues.
Expand Down
2 changes: 1 addition & 1 deletion scripts/gogetcookie.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash

touch ~/.gitcookies
chmod 0600 ~/.gitcookies
Expand Down
15 changes: 15 additions & 0 deletions test/run-tests-cygwin.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

set PATH=C:\cygwin64\bin;%PATH%
cd test1
if errorlevel 1 goto exit
C:\cygwin64\bin\bash.exe ../test.sh
if errorlevel 1 goto exit
cd ..
if errorlevel 1 goto exit
cd test2
if errorlevel 1 goto exit
C:\cygwin64\bin\bash.exe ../test.sh
:exit



8 changes: 8 additions & 0 deletions test/run-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env bash

cd test1 || exit 1
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For other changes, I understand them - but how would these scripts and directory test help?

Generally, tests inside *_test.go are much better idea - terraform testing harness catches more issues than executing something manually.

../test.sh
cd .. || exit 1

cd test2 || exit 1
../test.sh
33 changes: 33 additions & 0 deletions test/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env bash

export TF_VAR_MYSQL_ROOT_USER="root"
export TF_VAR_MYSQL_ROOT_PASSWORD="$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 20 | head -n 1)"
container1=$(docker run --rm --name test-mysql8.4.5-1 -e MYSQL_ROOT_PASSWORD=$TF_VAR_MYSQL_ROOT_PASSWORD -d -p 3307:3306 mysql:8.4.5 mysqld --mysql-native-password=ON)
if ! echo "$container1" | grep -Eq '^[0-9a-f]+$'; then
exit 1
fi
container2=$(docker run --rm --name test-mysql8.4.5-2 -e MYSQL_ROOT_PASSWORD=$TF_VAR_MYSQL_ROOT_PASSWORD -d -p 3308:3306 mysql:8.4.5 mysqld --mysql-native-password=ON)
if ! echo "$container2" | grep -Eq '^[0-9a-f]+$'; then
exit 1
fi


echo "Waiting for MySQL to become available..."
until docker exec "$container1" mysqladmin ping -h"localhost" -P3306 --silent; do
sleep 1
done
until docker exec "$container2" mysqladmin ping -h"localhost" -P3306 --silent; do
sleep 1
done


terraform init
terraform_code=$?
if [ $terraform_code -eq 0 ]; then
terraform apply -auto-approve
terraform_code=$?
fi

docker container stop $container1
docker container stop $container2
exit $terraform_code
121 changes: 121 additions & 0 deletions test/test1/test.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
terraform {
required_providers {
mysql = {
source = "petoju/mysql"
version = ">= 3.0.37"
}
}
required_version = ">= 1.11.4"
}

variable "MYSQL_ROOT_USER" {
sensitive = true
type = string
}

variable "MYSQL_ROOT_PASSWORD" {
sensitive = true
type = string
}

# First provider

provider "mysql" {
alias = "local1"
endpoint = "localhost:3307"
username = var.MYSQL_ROOT_USER
password = var.MYSQL_ROOT_PASSWORD
}

resource "mysql_database" "test1" {
provider = mysql.local1
name = "test-db"
}


resource "mysql_role" "analyst1" {
provider = mysql.local1
name = "analyst"
}

resource "mysql_grant" "grant_to_role_select1" {
provider = mysql.local1
role = mysql_role.analyst1.name
database = mysql_database.test1.name
table = "*"
privileges = ["SELECT"]
}

resource "mysql_grant" "grant_to_role_showroutine1" {
provider = mysql.local1
role = mysql_role.analyst1.name
database = "*"
table = "*"
privileges = ["SHOW_ROUTINE"]
}

resource "mysql_grant" "grant_to_user1" {
provider = mysql.local1
user = mysql_user.user1.user
host = "%"
database = mysql_database.test1.name
roles = [mysql_role.analyst1.name]
}


resource "mysql_user" "user1" {
provider = mysql.local1
user = "test-user"
host = "%"
}

# Second provider

provider "mysql" {
alias = "local2"
endpoint = "localhost:3308"
username = var.MYSQL_ROOT_USER
password = var.MYSQL_ROOT_PASSWORD
}

resource "mysql_database" "test2" {
provider = mysql.local2
name = "test-db"
}


resource "mysql_role" "analyst2" {
provider = mysql.local2
name = "analyst"
}

resource "mysql_grant" "grant_to_role_select2" {
provider = mysql.local2
role = mysql_role.analyst2.name
database = mysql_database.test2.name
table = "*"
privileges = ["SELECT"]
}

resource "mysql_grant" "grant_to_role_showroutine2" {
provider = mysql.local2
role = mysql_role.analyst2.name
database = "*"
table = "*"
privileges = ["SHOW_ROUTINE"]
}

resource "mysql_grant" "grant_to_user2" {
provider = mysql.local2
user = mysql_user.user2.user
host = "%"
database = mysql_database.test2.name
roles = [mysql_role.analyst2.name]
}


resource "mysql_user" "user2" {
provider = mysql.local2
user = "test-user"
host = "%"
}
Loading
Loading