Skip to content

Commit

Permalink
v0.10.0 release
Browse files Browse the repository at this point in the history
Added support for tagging by resource type, refer to the documentation
Added support for specifying version plan tag when deploying array
(e.g. `6.6.4` or `6.6.x`)
  • Loading branch information
tsimacek committed Jul 9, 2024
1 parent 06d54a3 commit 3f4cef2
Show file tree
Hide file tree
Showing 35 changed files with 851 additions and 1,455 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.10.0 (July 9, 2024)

* Added support for tagging by resource type, refer to the [documentation](docs/resources/array_azure.md#nested-schema-for-resource_tags)
* Added support for specifying version plan tag when deploying array (e.g. `6.6.4` or `6.6.x`)

## 0.9.0 (July 3, 2023)

* Added support for PremiumV2 SSD with V20MP2R2 SKU, refer to the [documentation](docs/resources/array_azure.md)
Expand Down Expand Up @@ -46,4 +51,4 @@
## 0.1.0 (February 9, 2021)

* Initial Release. Support for AWS CBS instances only.
* Create/Destroy, no updates yet.
* Create/Destroy, no updates yet.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,4 @@ tidy:
@go fix ./cbs
@go clean ./cbs
@go clean --tags mock ./cbs

4 changes: 0 additions & 4 deletions cbs/acceptance/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ const (
// parameters file in json format
EnvTfAccAzureParamsPath = "TEST_ACC_AZURE_PARAMS_PATH"

// Enviromment variable with path to the Fusion Storage Endpoint
// Collection Azure acceptance tests parameters file in json format
EnvTfAccFusionSECAzureParamsPath = "TEST_ACC_FUSION_SEC_AZURE_PARAMS_PATH"

// Environment variable with path to the AWS acceptance tests
// parameters file in json format
EnvTfAccAwsParamsPath = "TEST_ACC_AWS_PARAMS_PATH"
Expand Down
2 changes: 1 addition & 1 deletion cbs/acceptance/test_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ type AccTestCbsAzureParams struct {
VirtualNetworkId string `json:"virtual_network_id"`
JitGroup string `json:"jit_group"`
JitGroupID string `json:"jit_group_id"`
FusionSECIdentity string `json:"fusion_sec_identity"`
UserAssignedIdentity string `json:"user_assigned_identity"`
ResourceTags string `json:"resource_tags"`
}

type AccTestCbsFusionSECAzureParams struct {
Expand Down
13 changes: 13 additions & 0 deletions cbs/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,19 @@ func validateAzureManagedApplicationName(v interface{}, k string) (warnings []st
return warnings, errors
}

func validateVersionPrefixTag(v interface{}, k string) (warnings []string, errors []error) {
value := v.(string)

pattern := `^\d+\.\d+(?:\.\d+|\.x)?$`
regexpPattern := regexp.MustCompile(pattern)

if !regexpPattern.MatchString(value) {
errors = append(errors, fmt.Errorf("version prefix tag format not correct"))
}

return warnings, errors
}

func validateAzureResourceGroupName(v interface{}, k string) (warnings []string, errors []error) {
value := v.(string)

Expand Down
95 changes: 86 additions & 9 deletions cbs/data_azure_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import (
"strings"
"time"

"github.com/PureStorage-OpenConnect/terraform-provider-cbs/cbs/internal/appcatalog"
"github.com/hashicorp/go-version"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
Expand Down Expand Up @@ -67,6 +66,39 @@ func dataSourceAzurePlans() *schema.Resource {
}
}

func dataSourceCbsPlanAzure() *schema.Resource {
return &schema.Resource{
ReadContext: dataSourceCbsPlanAzureRead,
Schema: map[string]*schema.Schema{
"plan_version": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validateVersionPrefixTag,
},
"name": {
Type: schema.TypeString,
Computed: true,
Elem: schema.TypeString,
},
"version": {
Type: schema.TypeString,
Computed: true,
Elem: schema.TypeString,
},
"publisher": {
Type: schema.TypeString,
Computed: true,
Elem: schema.TypeString,
},
"product": {
Type: schema.TypeString,
Computed: true,
Elem: schema.TypeString,
},
},
}
}

type Plan struct {
Name string
Product string
Expand Down Expand Up @@ -96,7 +128,7 @@ func (a PlanByVersion) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
var plan_name_regexp = regexp.MustCompile(`^[\w]+_([\d]+)_([\d]+)_([\d]+)$`)

// Retrieve a plan information from Azure DefaultTemplate artifact
func getPlanFromTemplateJson(data []byte) (*Plan, error) {
func GetPlanFromTemplateJson(data []byte) (*Plan, error) {
// Parse the default template
var unmarshalled_data JSONDefaultTemplate
err := json.Unmarshal(data, &unmarshalled_data)
Expand Down Expand Up @@ -131,16 +163,14 @@ func versionPlans(plans []Plan) ([]VersionedPlan, error) {
return versioned_plans, nil
}

func queryMarketplaceForPlans(ctx context.Context) ([]VersionedPlan, error) {

search_client := appcatalog.NewSearchClient()
response, err := search_client.Get(ctx, "en", "US", "terraform-cbs-provider", []appcatalog.SearchV2FieldName{"All"}, []string{"purestoragemarketplaceadmin"})
func QueryMarketplaceForPlans(ctx context.Context) ([]VersionedPlan, error) {
productSummary, err := GetProductSummary(ctx)
if err != nil {
return nil, err
}

var template_plans []Plan
for _, response_result := range response.Results {
for _, response_result := range productSummary.Results {
for _, response_plan := range response_result.Plans {
if !strings.HasPrefix(*response_plan.PlanID, "cbs_azure") {
// Exclude any plans which aren't the Pure Cloud Block Store on Azure offering.
Expand All @@ -158,7 +188,7 @@ func queryMarketplaceForPlans(ctx context.Context) ([]VersionedPlan, error) {
continue
}

template_plan, err := getPlanFromTemplateJson(template_data)
template_plan, err := GetPlanFromTemplateJson(template_data)
if err != nil {
continue
}
Expand All @@ -174,7 +204,7 @@ func queryMarketplaceForPlans(ctx context.Context) ([]VersionedPlan, error) {
func dataSourceAzurePlansRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
var diags diag.Diagnostics

versioned_plans, err := queryMarketplaceForPlans(ctx)
versioned_plans, err := QueryMarketplaceForPlans(ctx)
if err != nil {
return diag.FromErr(err)
}
Expand All @@ -201,3 +231,50 @@ func dataSourceAzurePlansRead(ctx context.Context, d *schema.ResourceData, m int

return diags
}

func dataSourceCbsPlanAzureRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
var diags diag.Diagnostics

versioned_plans, err := QueryMarketplaceForPlans(ctx)
if err != nil {
return diag.FromErr(err)
}

version_prefix_tag := d.Get("plan_version").(string)
if version_prefix_tag[len(version_prefix_tag)-1] == 'x' {
version_prefix_tag = version_prefix_tag[0 : len(version_prefix_tag)-1]
}

set := false
for _, versioned_plan := range versioned_plans {
match := plan_name_regexp.FindStringSubmatch(versioned_plan.Plan.Name)
version_tag := fmt.Sprintf("%s.%s.%s", match[1], match[2], match[3])
if strings.HasPrefix(version_tag, version_prefix_tag) {
d.SetId(strconv.FormatInt(time.Now().Unix(), 10))
err = d.Set("name", versioned_plan.Plan.Name)
if err != nil {
return diag.FromErr(err)
}
err = d.Set("product", versioned_plan.Plan.Product)
if err != nil {
return diag.FromErr(err)
}
err = d.Set("publisher", versioned_plan.Plan.Publisher)
if err != nil {
return diag.FromErr(err)
}
err = d.Set("version", versioned_plan.Plan.Version)
if err != nil {
return diag.FromErr(err)
}
set = true
break
}
}

if !set {
return diag.FromErr(errors.New("Specific plan for provided version tag not found"))
}

return diags
}
59 changes: 59 additions & 0 deletions cbs/data_azure_plans_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package cbs
import (
"fmt"
"os"
"regexp"
"strconv"
"testing"

Expand Down Expand Up @@ -49,10 +50,35 @@ func TestAccDataAzurePlans(t *testing.T) {
})
}

func TestAccDataCbsPlanAzure(t *testing.T) {

if os.Getenv(acceptance.EnvTfAccAzureSkipMarketplace) != "" {
t.Skipf("Skipping acc test due to env variable '%s'", acceptance.EnvTfAccAzureSkipMarketplace)
}

resource.ParallelTest(t, resource.TestCase{
ProviderFactories: testAccProvidersFactory,
Steps: []resource.TestStep{
{
Config: testAccAzureDataCbsPlanAzure(),
Check: resource.ComposeTestCheckFunc(
testAccDataCbsPlanAzure(),
),
},
},
})
}

func testAccAzureDataPlansConfig() string {
return `data "cbs_azure_plans" "azure_plans" {}`
}

func testAccAzureDataCbsPlanAzure() string {
return `data "cbs_plan_azure" "version_plan" {
plan_version = "6.6.x"
}`
}

func testAccDataAzurePlans() resource.TestCheckFunc {
return func(s *terraform.State) error {
data_resource := s.RootModule().Resources["data.cbs_azure_plans.azure_plans"]
Expand All @@ -62,9 +88,11 @@ func testAccDataAzurePlans() resource.TestCheckFunc {
if err != nil {
return err
}

if plans_size < 2 {
return fmt.Errorf("Unexpected plans size: %d", plans_size)
}

for i := 0; i < plans_size; i++ {
// Check product version derivation from plan name makes sense.
plan_name := data_resource.Primary.Attributes["plans."+strconv.Itoa(i)+".name"]
Expand Down Expand Up @@ -101,3 +129,34 @@ func testAccDataAzurePlans() resource.TestCheckFunc {
return nil
}
}

func testAccDataCbsPlanAzure() resource.TestCheckFunc {
return func(s *terraform.State) error {
pattern := `^\d+\.\d+\.\d+$`
re := regexp.MustCompile(pattern)
data_resource := s.RootModule().Resources["data.cbs_plan_azure.version_plan"]

plan_name := data_resource.Primary.Attributes["name"]
match := plan_name_regexp.FindStringSubmatch(plan_name)
version_tag := fmt.Sprintf("%s.%s.%s", match[1], match[2], match[3])
if len(match) != 4 || !re.MatchString(version_tag) {
return fmt.Errorf("Incorrect plan name: %s", plan_name)
}

plan_product := data_resource.Primary.Attributes["product"]
if plan_product != "pure_storage_cloud_block_store_deployment" {
return fmt.Errorf("Incorrect plan product : %s", plan_product)
}

plan_publisher := data_resource.Primary.Attributes["publisher"]
if plan_publisher != "purestoragemarketplaceadmin" {
return fmt.Errorf("Incorrect plan publisher : %s", plan_publisher)
}

plan_version := data_resource.Primary.Attributes["version"]
if !re.MatchString(plan_version) {
return fmt.Errorf("Incorrect plan version : %s", plan_version)
}
return nil
}
}
83 changes: 0 additions & 83 deletions cbs/internal/array/faclient/faclient_test.go

This file was deleted.

3 changes: 3 additions & 0 deletions cbs/internal/cloud/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"context"

"github.com/Azure/azure-sdk-for-go/profiles/latest/resources/mgmt/managedapplications"
"github.com/Azure/azure-sdk-for-go/profiles/latest/resources/mgmt/resources"
"github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac"
vaultSecret "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault"
"github.com/PureStorage-OpenConnect/terraform-provider-cbs/cbs/internal/array"
Expand Down Expand Up @@ -61,6 +62,8 @@ type AzureClientAPI interface {
GroupsListComplete(ctx context.Context, filter string) (*[]graphrbac.ADGroup, error)
AppsCreateOrUpdate(ctx context.Context, resourceGroupName string, applicationName string, parameters managedapplications.Application) error
AppsGet(ctx context.Context, resourceGroupName string, applicationName string) (managedapplications.Application, error)
ResourcesGetByType(ctx context.Context, resourceType string, managedResourceGroup string) ([]resources.GenericResourceExpanded, error)
ResourceGet(ctx context.Context, resourceID string) (resources.GenericResource, error)
AppsDelete(ctx context.Context, resourceGroupName string, applicationName string) error
SecretSet(ctx context.Context, vaultId string, secretName string, parameters vaultSecret.SecretSetParameters) (vaultSecret.SecretBundle, error)
SecretGet(ctx context.Context, vaultId string, secretName string, version string) (vaultSecret.SecretBundle, error)
Expand Down
Loading

0 comments on commit 3f4cef2

Please sign in to comment.