Skip to content

Commit a3f43d8

Browse files
ps-dbutlerccannon424
authored andcommitted
cbs_array_azure release
1 parent 0f44d04 commit a3f43d8

21 files changed

+1837
-154
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 0.2.0 (March 9, 2021)
2+
3+
* Release of CBS on Azure support through the cbs_array_azure resource
4+
* Various docs updates and typo fixes
5+
16
## 0.1.0 (February 9, 2021)
27

38
* Initial Release. Support for AWS CBS instances only.

README.md

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,52 @@ go mod download
1818
```shell
1919
make
2020
```
21-
Note: The provider has only been tested on Linux and may not work on other platforms
21+
Note: The provider has only been tested on Linux and might not work on other platforms.
2222

2323
### AWS Credentials
2424

2525
The provider is built using AWS SDK for Go, and will require the AWS credentials configured
2626
in the sytem. for more information about setting up the SDK, refer to this page:
2727
https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html
2828

29+
### Azure Credentials
30+
31+
The provider can be authenticated to Azure using either the Azure CLI or an Azure Service Principal. For Azure CLI,
32+
Terraform only supports authenticating using the `az` CLI (and this must be available on your PATH). Authenticating
33+
using the older `azure` CLI or PowerShell Cmdlets are not supported.
34+
Login to the Azure CLI:
35+
```shell
36+
az login
37+
```
38+
39+
And list the Subscriptions associated with the account:
40+
```shell
41+
az account list
42+
```
43+
44+
You can specify the Subscription to be default if you have more than one Subscription:
45+
```shell
46+
az account set --subscription="SUBSCRIPTION_ID"
47+
```
48+
49+
Terraform can be authenticated with a Service Principal in the provider configuration:
50+
```hcl
51+
provider "cbs" {
52+
azure {
53+
client_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
54+
client_secret = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
55+
subscription_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
56+
tenant_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
57+
}
58+
}
59+
```
60+
Alternatively, those values can also be supplied to the provider through the following environment variables:
61+
```shell
62+
export ARM_CLIENT_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
63+
export ARM_CLIENT_SECRET="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
64+
export ARM_SUBSCRIPTION_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
65+
export ARM_TENANT_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
66+
```
2967
## Using the Provider
3068

3169
[Provider Documentation](https://registry.terraform.io/providers/PureStorage-OpenConnect/cbs/latest/docs)
@@ -35,12 +73,15 @@ Example terraform configuration templates can be found in the examples/ subdirec
3573
## Testing
3674

3775
To run acceptance tests, a JSON config file must be specified to supply the input parameters to
38-
the test CBS instances. An example config file can be found at `testing/example_aws_config`.
76+
the test CBS instances. An example config file for AWS can be found at `testing/example_aws_config`.
3977
The config file is passed to the test using the `TEST_ACC_AWS_PARAMS_PATH` environment variable.
78+
An example config file for Azure can be found at `testing/example_azure_config`.
79+
The config file is passed to the test using the `TEST_ACC_AZURE_PARAMS_PATH` environment variable.
4080

4181
Acceptance tests can be run with `make testacc`:
4282
```shell
4383
export TEST_ACC_AWS_PARAMS_PATH=<path to config file>
84+
export TEST_ACC_AZURE_PARAMS_PATH=<path to config file>
4485
make testacc
4586
```
4687

cbs/cbs_service.go

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
3+
Copyright 2021, Pure Storage Inc.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
17+
*/
18+
19+
package cbs
20+
21+
import (
22+
"fmt"
23+
24+
"github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac"
25+
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/managedapplications"
26+
"github.com/Azure/go-autorest/autorest"
27+
28+
"github.com/aws/aws-sdk-go/aws"
29+
"github.com/aws/aws-sdk-go/aws/session"
30+
"github.com/aws/aws-sdk-go/service/cloudformation"
31+
32+
"github.com/hashicorp/go-azure-helpers/authentication"
33+
"github.com/hashicorp/go-azure-helpers/sender"
34+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
35+
)
36+
37+
type CbsService struct {
38+
CloudFormation *cloudformation.CloudFormation
39+
AzureClient *AzureClient
40+
}
41+
42+
type AzureClient struct {
43+
ApplicationsClient *managedapplications.ApplicationsClient
44+
GroupsClient *graphrbac.GroupsClient
45+
}
46+
47+
func (m *CbsService) CloudFormationService() (*cloudformation.CloudFormation, diag.Diagnostics) {
48+
if m.CloudFormation == nil {
49+
cftSvc, diags := buildSession(awsRegionStr)
50+
if diags.HasError() {
51+
return nil, diags
52+
}
53+
m.CloudFormation = cftSvc
54+
}
55+
56+
return m.CloudFormation, nil
57+
}
58+
59+
func (m *CbsService) AzureClientService() (*AzureClient, diag.Diagnostics) {
60+
if m.AzureClient == nil {
61+
azureClient, diags := buildAzureClient(azureBuilder)
62+
if diags.HasError() {
63+
return nil, diags
64+
}
65+
m.AzureClient = azureClient
66+
}
67+
68+
return m.AzureClient, nil
69+
}
70+
71+
func buildSession(region string) (*cloudformation.CloudFormation, diag.Diagnostics) {
72+
var diags diag.Diagnostics
73+
if region == "" {
74+
diags = append(diags, diag.Diagnostic{
75+
Severity: diag.Error,
76+
Summary: fmt.Sprintf("No AWS region specified. The AWS region must be provided either in "+
77+
"the provider configuration block or with the %s environment variable.", awsRegionVar),
78+
})
79+
return nil, diags
80+
}
81+
sess, err := session.NewSession(&aws.Config{
82+
Region: aws.String(region)},
83+
)
84+
if err != nil {
85+
return nil, diag.FromErr(err)
86+
}
87+
88+
cftSvc := cloudformation.New(sess)
89+
return cftSvc, nil
90+
}
91+
92+
func buildAzureClient(builder *authentication.Builder) (*AzureClient, diag.Diagnostics) {
93+
var azureClient AzureClient
94+
config, err := builder.Build()
95+
if err != nil {
96+
return nil, diag.FromErr(err)
97+
}
98+
99+
env, err := authentication.DetermineEnvironment(config.Environment)
100+
if err != nil {
101+
return nil, diag.FromErr(err)
102+
}
103+
104+
// This indicates that a 429 response should not be included as a retry attempt
105+
// so that we continue to retry until it succeeds. Set this behavior to keep
106+
// consistent with azurerm provider.
107+
autorest.Count429AsRetry = false
108+
109+
oauthConfig, err := config.BuildOAuthConfig(env.ActiveDirectoryEndpoint)
110+
if err != nil {
111+
return nil, diag.FromErr(err)
112+
}
113+
sender := sender.BuildSender("cbs")
114+
auth, err := config.GetAuthorizationToken(sender, oauthConfig, env.TokenAudience)
115+
if err != nil {
116+
return nil, diag.FromErr(err)
117+
}
118+
graphAuth, err := config.GetAuthorizationToken(sender, oauthConfig, env.GraphEndpoint)
119+
if err != nil {
120+
return nil, diag.FromErr(err)
121+
}
122+
123+
// Create applications client
124+
client := managedapplications.NewApplicationsClient(config.SubscriptionID)
125+
client.SubscriptionID = config.SubscriptionID
126+
client.Client.Authorizer = auth
127+
// Create groups client
128+
groupClient := graphrbac.NewGroupsClient(config.TenantID)
129+
groupClient.Client.Authorizer = graphAuth
130+
131+
azureClient.ApplicationsClient = &client
132+
azureClient.GroupsClient = &groupClient
133+
return &azureClient, nil
134+
}

cbs/common.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
3+
Copyright 2021, Pure Storage Inc.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
17+
*/
18+
19+
package cbs
20+
21+
import (
22+
"regexp"
23+
"strings"
24+
25+
"github.com/iancoleman/strcase"
26+
)
27+
28+
func toSnake(s string) string {
29+
snakeStr := strcase.ToSnake(s)
30+
// Post process the string to correct some edge cases
31+
if strings.Contains(snakeStr, "i_scsi") {
32+
snakeStr = strings.ReplaceAll(snakeStr, "i_scsi", "iscsi")
33+
}
34+
exp := regexp.MustCompile("ct_([0,1])")
35+
if exp.MatchString(snakeStr) {
36+
snakeStr = exp.ReplaceAllString(snakeStr, "ct${1}")
37+
}
38+
return snakeStr
39+
}
40+
41+
// returns the corresponding terraform schema parameter name given a template
42+
// parameter name and renamed string map.
43+
func templateToTFParam(cftParam string, renamedMap map[string]string) string {
44+
var tfParam string
45+
if renamedParam, ok := renamedMap[cftParam]; ok {
46+
tfParam = renamedParam
47+
} else {
48+
tfParam = toSnake(cftParam)
49+
}
50+
return tfParam
51+
}
52+
53+
func convertToStringSlice(vals []interface{}) []string {
54+
strs := make([]string, len(vals))
55+
for i := range vals {
56+
strs[i] = vals[i].(string)
57+
}
58+
return strs
59+
}

cbs/common_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
3+
Copyright 2021, Pure Storage Inc.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
17+
*/
18+
19+
package cbs
20+
21+
import (
22+
"testing"
23+
)
24+
25+
func TestCbs_toSnake(t *testing.T) {
26+
27+
m := map[string]string{
28+
"ArrayName": "array_name",
29+
"ISCSISubnet": "iscsi_subnet",
30+
"ReplicationEndpointCT0": "replication_endpoint_ct0",
31+
"iSCSIEndpointCT1": "iscsi_endpoint_ct1",
32+
}
33+
34+
for camel, snakeExp := range m {
35+
snakeStr := toSnake(camel)
36+
if snakeStr != snakeExp {
37+
t.Errorf("error converting camel case to snake case, expected: %s, actual: %s", snakeExp, snakeStr)
38+
}
39+
}
40+
}

0 commit comments

Comments
 (0)