github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/backend/remote-state/oss/backend_test.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package oss 5 6 import ( 7 "fmt" 8 "math/rand" 9 "os" 10 "testing" 11 "time" 12 13 "strings" 14 15 "github.com/aliyun/aliyun-oss-go-sdk/oss" 16 "github.com/aliyun/aliyun-tablestore-go-sdk/tablestore" 17 "github.com/terramate-io/tf/backend" 18 "github.com/terramate-io/tf/configs/hcl2shim" 19 ) 20 21 // verify that we are doing ACC tests or the OSS tests specifically 22 func testACC(t *testing.T) { 23 skip := os.Getenv("TF_ACC") == "" && os.Getenv("TF_OSS_TEST") == "" 24 if skip { 25 t.Log("oss backend tests require setting TF_ACC or TF_OSS_TEST") 26 t.Skip() 27 } 28 if skip { 29 t.Fatal("oss backend tests require setting ALICLOUD_ACCESS_KEY or ALICLOUD_ACCESS_KEY_ID") 30 } 31 if os.Getenv("ALICLOUD_REGION") == "" { 32 os.Setenv("ALICLOUD_REGION", "cn-beijing") 33 } 34 } 35 36 func TestBackend_impl(t *testing.T) { 37 var _ backend.Backend = new(Backend) 38 } 39 40 func TestBackendConfig(t *testing.T) { 41 testACC(t) 42 config := map[string]interface{}{ 43 "region": "cn-beijing", 44 "bucket": "terraform-backend-oss-test", 45 "prefix": "mystate", 46 "key": "first.tfstate", 47 "tablestore_endpoint": "https://terraformstate.cn-beijing.ots.aliyuncs.com", 48 "tablestore_table": "TableStore", 49 } 50 51 b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(config)).(*Backend) 52 53 if !strings.HasPrefix(b.ossClient.Config.Endpoint, "https://oss-cn-beijing") { 54 t.Fatalf("Incorrect region was provided") 55 } 56 if b.bucketName != "terraform-backend-oss-test" { 57 t.Fatalf("Incorrect bucketName was provided") 58 } 59 if b.statePrefix != "mystate" { 60 t.Fatalf("Incorrect state file path was provided") 61 } 62 if b.stateKey != "first.tfstate" { 63 t.Fatalf("Incorrect keyName was provided") 64 } 65 66 if b.ossClient.Config.AccessKeyID == "" { 67 t.Fatalf("No Access Key Id was provided") 68 } 69 if b.ossClient.Config.AccessKeySecret == "" { 70 t.Fatalf("No Secret Access Key was provided") 71 } 72 } 73 74 func TestBackendConfigWorkSpace(t *testing.T) { 75 testACC(t) 76 bucketName := fmt.Sprintf("terraform-backend-oss-test-%d", rand.Intn(1000)) 77 config := map[string]interface{}{ 78 "region": "cn-beijing", 79 "bucket": bucketName, 80 "prefix": "mystate", 81 "key": "first.tfstate", 82 "tablestore_endpoint": "https://terraformstate.cn-beijing.ots.aliyuncs.com", 83 "tablestore_table": "TableStore", 84 } 85 86 b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(config)).(*Backend) 87 createOSSBucket(t, b.ossClient, bucketName) 88 defer deleteOSSBucket(t, b.ossClient, bucketName) 89 if _, err := b.Workspaces(); err != nil { 90 t.Fatal(err.Error()) 91 } 92 if !strings.HasPrefix(b.ossClient.Config.Endpoint, "https://oss-cn-beijing") { 93 t.Fatalf("Incorrect region was provided") 94 } 95 if b.bucketName != bucketName { 96 t.Fatalf("Incorrect bucketName was provided") 97 } 98 if b.statePrefix != "mystate" { 99 t.Fatalf("Incorrect state file path was provided") 100 } 101 if b.stateKey != "first.tfstate" { 102 t.Fatalf("Incorrect keyName was provided") 103 } 104 105 if b.ossClient.Config.AccessKeyID == "" { 106 t.Fatalf("No Access Key Id was provided") 107 } 108 if b.ossClient.Config.AccessKeySecret == "" { 109 t.Fatalf("No Secret Access Key was provided") 110 } 111 } 112 113 func TestBackendConfigProfile(t *testing.T) { 114 testACC(t) 115 config := map[string]interface{}{ 116 "region": "cn-beijing", 117 "bucket": "terraform-backend-oss-test", 118 "prefix": "mystate", 119 "key": "first.tfstate", 120 "tablestore_endpoint": "https://terraformstate.cn-beijing.ots.aliyuncs.com", 121 "tablestore_table": "TableStore", 122 "profile": "default", 123 } 124 125 b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(config)).(*Backend) 126 127 if !strings.HasPrefix(b.ossClient.Config.Endpoint, "https://oss-cn-beijing") { 128 t.Fatalf("Incorrect region was provided") 129 } 130 if b.bucketName != "terraform-backend-oss-test" { 131 t.Fatalf("Incorrect bucketName was provided") 132 } 133 if b.statePrefix != "mystate" { 134 t.Fatalf("Incorrect state file path was provided") 135 } 136 if b.stateKey != "first.tfstate" { 137 t.Fatalf("Incorrect keyName was provided") 138 } 139 140 if b.ossClient.Config.AccessKeyID == "" { 141 t.Fatalf("No Access Key Id was provided") 142 } 143 if b.ossClient.Config.AccessKeySecret == "" { 144 t.Fatalf("No Secret Access Key was provided") 145 } 146 } 147 148 func TestBackendConfig_invalidKey(t *testing.T) { 149 testACC(t) 150 cfg := hcl2shim.HCL2ValueFromConfigValue(map[string]interface{}{ 151 "region": "cn-beijing", 152 "bucket": "terraform-backend-oss-test", 153 "prefix": "/leading-slash", 154 "name": "/test.tfstate", 155 "tablestore_endpoint": "https://terraformstate.cn-beijing.ots.aliyuncs.com", 156 "tablestore_table": "TableStore", 157 }) 158 159 _, results := New().PrepareConfig(cfg) 160 if !results.HasErrors() { 161 t.Fatal("expected config validation error") 162 } 163 } 164 165 func TestBackend(t *testing.T) { 166 testACC(t) 167 168 bucketName := fmt.Sprintf("terraform-remote-oss-test-%x", time.Now().Unix()) 169 statePrefix := "multi/level/path/" 170 171 b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{ 172 "bucket": bucketName, 173 "prefix": statePrefix, 174 })).(*Backend) 175 176 b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{ 177 "bucket": bucketName, 178 "prefix": statePrefix, 179 })).(*Backend) 180 181 createOSSBucket(t, b1.ossClient, bucketName) 182 defer deleteOSSBucket(t, b1.ossClient, bucketName) 183 184 backend.TestBackendStates(t, b1) 185 backend.TestBackendStateLocks(t, b1, b2) 186 backend.TestBackendStateForceUnlock(t, b1, b2) 187 } 188 189 func createOSSBucket(t *testing.T, ossClient *oss.Client, bucketName string) { 190 // Be clear about what we're doing in case the user needs to clean this up later. 191 if err := ossClient.CreateBucket(bucketName); err != nil { 192 t.Fatal("failed to create test OSS bucket:", err) 193 } 194 } 195 196 func deleteOSSBucket(t *testing.T, ossClient *oss.Client, bucketName string) { 197 warning := "WARNING: Failed to delete the test OSS bucket. It may have been left in your Alibaba Cloud account and may incur storage charges. (error was %s)" 198 199 // first we have to get rid of the env objects, or we can't delete the bucket 200 bucket, err := ossClient.Bucket(bucketName) 201 if err != nil { 202 t.Fatal("Error getting bucket:", err) 203 return 204 } 205 objects, err := bucket.ListObjects() 206 if err != nil { 207 t.Logf(warning, err) 208 return 209 } 210 for _, obj := range objects.Objects { 211 if err := bucket.DeleteObject(obj.Key); err != nil { 212 // this will need cleanup no matter what, so just warn and exit 213 t.Logf(warning, err) 214 return 215 } 216 } 217 218 if err := ossClient.DeleteBucket(bucketName); err != nil { 219 t.Logf(warning, err) 220 } 221 } 222 223 // create the tablestore table, and wait until we can query it. 224 func createTablestoreTable(t *testing.T, otsClient *tablestore.TableStoreClient, tableName string) { 225 tableMeta := new(tablestore.TableMeta) 226 tableMeta.TableName = tableName 227 tableMeta.AddPrimaryKeyColumn(pkName, tablestore.PrimaryKeyType_STRING) 228 229 tableOption := new(tablestore.TableOption) 230 tableOption.TimeToAlive = -1 231 tableOption.MaxVersion = 1 232 233 reservedThroughput := new(tablestore.ReservedThroughput) 234 235 _, err := otsClient.CreateTable(&tablestore.CreateTableRequest{ 236 TableMeta: tableMeta, 237 TableOption: tableOption, 238 ReservedThroughput: reservedThroughput, 239 }) 240 if err != nil { 241 t.Fatal(err) 242 } 243 } 244 245 func deleteTablestoreTable(t *testing.T, otsClient *tablestore.TableStoreClient, tableName string) { 246 params := &tablestore.DeleteTableRequest{ 247 TableName: tableName, 248 } 249 _, err := otsClient.DeleteTable(params) 250 if err != nil { 251 t.Logf("WARNING: Failed to delete the test TableStore table %q. It has been left in your Alibaba Cloud account and may incur charges. (error was %s)", tableName, err) 252 } 253 }