Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Major version upgrade tfp work #383

Merged
merged 2 commits into from
Aug 31, 2022
Merged
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
11 changes: 11 additions & 0 deletions docs/data-sources/vault_cluster.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ data "hcp_vault_cluster" "example" {
- `created_at` (String) The time that the Vault cluster was created.
- `hvn_id` (String) The ID of the HVN this HCP Vault cluster is associated to.
- `id` (String) The ID of this resource.
- `major_version_upgrade_config` (List of Object) (see [below for nested schema](#nestedatt--major_version_upgrade_config))
- `metrics_config` (Block List) The metrics configuration for export. (https://learn.hashicorp.com/tutorials/cloud/vault-metrics-guide#metrics-streaming-configuration) (see [below for nested schema](#nestedblock--metrics_config))
- `min_vault_version` (String) The minimum Vault version to use when creating the cluster. If not specified, it is defaulted to the version that is currently recommended by HCP.
- `namespace` (String) The name of the customer namespace this HCP Vault cluster is located in.
Expand Down Expand Up @@ -71,6 +72,16 @@ Read-Only:
- `splunk_hecendpoint` (String) Splunk endpoint for streaming audit logs


<a id="nestedatt--major_version_upgrade_config"></a>
### Nested Schema for `major_version_upgrade_config`

Read-Only:

- `maintenance_window_day` (String)
- `maintenance_window_time` (String)
- `upgrade_type` (String)


<a id="nestedblock--metrics_config"></a>
### Nested Schema for `metrics_config`

Expand Down
14 changes: 14 additions & 0 deletions docs/resources/vault_cluster.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ resource "hcp_vault_cluster" "example" {
### Optional

- `audit_log_config` (Block List, Max: 1) The audit logs configuration for export. (https://learn.hashicorp.com/tutorials/cloud/vault-metrics-guide#metrics-streaming-configuration) (see [below for nested schema](#nestedblock--audit_log_config))
- `major_version_upgrade_config` (Block List, Max: 1) The Major Version Upgrade configuration. (see [below for nested schema](#nestedblock--major_version_upgrade_config))
- `metrics_config` (Block List, Max: 1) The metrics configuration for export. (https://learn.hashicorp.com/tutorials/cloud/vault-metrics-guide#metrics-streaming-configuration) (see [below for nested schema](#nestedblock--metrics_config))
- `min_vault_version` (String) The minimum Vault version to use when creating the cluster. If not specified, it is defaulted to the version that is currently recommended by HCP.
- `paths_filter` (List of String) The performance replication [paths filter](https://learn.hashicorp.com/tutorials/vault/paths-filter). Applies to performance replication secondaries only and operates in "deny" mode only.
Expand Down Expand Up @@ -87,6 +88,19 @@ Optional:
- `splunk_token` (String, Sensitive) Splunk token for streaming audit logs


<a id="nestedblock--major_version_upgrade_config"></a>
### Nested Schema for `major_version_upgrade_config`

Required:

- `upgrade_type` (String) The major upgrade type for the cluster. Valid options for upgrade type - `AUTOMATIC`, `SCHEDULED`, `MANUAL`

Optional:

- `maintenance_window_day` (String) The maintenance day of the week for scheduled upgrades. Valid options for maintenance window day - `MONDAY`, `TUESDAY`, `WEDNESDAY`, `THURSDAY`, `FRIDAY`, `SATURDAY`, `SUNDAY`
- `maintenance_window_time` (String) The maintenance time frame for scheduled upgrades. Valid options for maintenance window time - `WINDOW_12AM_4AM`, `WINDOW_6AM_10AM`, `WINDOW_12PM_4PM`, `WINDOW_6PM_10PM`


<a id="nestedblock--metrics_config"></a>
### Nested Schema for `metrics_config`

Expand Down
32 changes: 32 additions & 0 deletions internal/clients/vault_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,38 @@ func UpdateVaultClusterPublicIps(ctx context.Context, client *Client, loc *share
return updateResp.Payload, nil
}

// UpdateVaultMajorVersionUpgradeConfig will make a call to the Vault service to update the major version upgrade config for the Vault cluster.
func UpdateVaultMajorVersionUpgradeConfig(ctx context.Context, client *Client, loc *sharedmodels.HashicorpCloudLocationLocation, clusterID string,
config *vaultmodels.HashicorpCloudVault20201125MajorVersionUpgradeConfig) (vaultmodels.HashicorpCloudVault20201125UpdateMajorVersionUpgradeConfigResponse, error) {

request := &vaultmodels.HashicorpCloudVault20201125UpdateMajorVersionUpgradeConfigRequest{
// ClusterID and Location are repeated because the values above are required to populate the URL,
// and the values below are required in the API request body
ClusterID: clusterID,
Location: loc,
UpgradeType: config.UpgradeType,
}
if config.MaintenanceWindow != nil {
request.MaintenanceWindow = &vaultmodels.HashicorpCloudVault20201125MajorVersionUpgradeConfigMaintenanceWindow{
DayOfWeek: config.MaintenanceWindow.DayOfWeek,
TimeWindowUtc: config.MaintenanceWindow.TimeWindowUtc,
}
}
updateParams := vault_service.NewUpdateMajorVersionUpgradeConfigParams()
updateParams.Context = ctx
updateParams.ClusterID = clusterID
updateParams.LocationProjectID = loc.ProjectID
updateParams.LocationOrganizationID = loc.OrganizationID
updateParams.Body = request

updateResp, err := client.Vault.UpdateMajorVersionUpgradeConfig(updateParams, nil)
if err != nil {
return nil, err
}

return updateResp.Payload, nil
}

// UpdateVaultCluster will make a call to the Vault service to update the Vault cluster configuration.
func UpdateVaultClusterConfig(ctx context.Context, client *Client, loc *sharedmodels.HashicorpCloudLocationLocation,
clusterID string, tier *string, metrics *vaultmodels.HashicorpCloudVault20201125ObservabilityConfig,
Expand Down
23 changes: 23 additions & 0 deletions internal/provider/data_source_vault_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,29 @@ func dataSourceVaultCluster() *schema.Resource {
},
},
},
"major_version_upgrade_config": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"upgrade_type": {
Description: "The major upgrade type for the cluster",
Type: schema.TypeString,
Computed: true,
},
"maintenance_window_day": {
Description: "The maintenance day of the week for scheduled updates",
Type: schema.TypeString,
Computed: true,
},
"maintenance_window_time": {
Description: "The maintenance time frame for scheduled updates",
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
}
}
Expand Down
159 changes: 157 additions & 2 deletions internal/provider/resource_vault_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,44 @@ func resourceVaultCluster() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"major_version_upgrade_config": {
Description: "The Major Version Upgrade configuration.",
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"upgrade_type": {
Description: "The major upgrade type for the cluster. Valid options for upgrade type - `AUTOMATIC`, `SCHEDULED`, `MANUAL`",
Type: schema.TypeString,
Required: true,
ValidateDiagFunc: validateVaultUpgradeType,
DiffSuppressFunc: func(_, old, new string, _ *schema.ResourceData) bool {
return strings.EqualFold(old, new)
},
},
"maintenance_window_day": {
Description: "The maintenance day of the week for scheduled upgrades. Valid options for maintenance window day - `MONDAY`, `TUESDAY`, `WEDNESDAY`, `THURSDAY`, `FRIDAY`, `SATURDAY`, `SUNDAY`",
Type: schema.TypeString,
Optional: true,
ValidateDiagFunc: validateVaultUpgradeWindowDay,
DiffSuppressFunc: func(_, old, new string, _ *schema.ResourceData) bool {
return strings.EqualFold(old, new)
},
},
"maintenance_window_time": {
Description: "The maintenance time frame for scheduled upgrades. Valid options for maintenance window time - `WINDOW_12AM_4AM`, `WINDOW_6AM_10AM`, `WINDOW_12PM_4PM`, `WINDOW_6PM_10PM`",
Type: schema.TypeString,
Optional: true,
ValidateDiagFunc: validateVaultUpgradeWindowTime,
DiffSuppressFunc: func(_, old, new string, _ *schema.ResourceData) bool {
return strings.EqualFold(old, new)
},
},
},
},
},
"vault_public_endpoint_url": {
Description: "The public URL for the Vault cluster. This will be empty if `public_endpoint` is `false`.",
Type: schema.TypeString,
Expand Down Expand Up @@ -268,7 +306,7 @@ func resourceVaultClusterCreate(ctx context.Context, d *schema.ResourceData, met
ProjectID: client.Config.ProjectID,
}

//get metrics and audit config first so we can validate and fail faster
//get metrics audit config and mvu config first so we can validate and fail faster
metricsConfig, diagErr := getObservabilityConfig("metrics_config", d)
if diagErr != nil {
return diagErr
Expand All @@ -277,6 +315,10 @@ func resourceVaultClusterCreate(ctx context.Context, d *schema.ResourceData, met
if diagErr != nil {
return diagErr
}
mvuConfig, error := getMajorVersionUpgradeConfig(d)
if diagErr != nil {
return error
}

// Use the hvn to get provider and region.
hvn, err := clients.GetHvnByID(ctx, client, loc, hvnID)
Expand Down Expand Up @@ -400,6 +442,21 @@ func resourceVaultClusterCreate(ctx context.Context, d *schema.ResourceData, met
return diag.Errorf("unable to retrieve Vault cluster (%s): %v", payload.ClusterID, err)
}

// If we pass the major version upgrade configuration we need to update it after the creation of the cluster,
// since the cluster is created by default to automatic upgrade
if mvuConfig != nil {
_, err := clients.UpdateVaultMajorVersionUpgradeConfig(ctx, client, cluster.Location, payload.ClusterID, mvuConfig)
if err != nil {
return diag.Errorf("error updating Vault cluster major version upgrade config (%s): %v", payload.ClusterID, err)
}

// refresh the created Vault cluster.
cluster, err = clients.GetVaultClusterByID(ctx, client, loc, payload.ClusterID)
if err != nil {
return diag.Errorf("unable to retrieve Vault cluster (%s): %v", payload.ClusterID, err)
}
}

if err := setVaultClusterResourceData(d, cluster); err != nil {
return diag.FromErr(err)
}
Expand Down Expand Up @@ -471,9 +528,16 @@ func resourceVaultClusterUpdate(ctx context.Context, d *schema.ResourceData, met
}

// Confirm at least one modifiable field has changed
if !d.HasChanges("tier", "public_endpoint", "paths_filter", "metrics_config", "audit_log_config") {
if !d.HasChanges("tier", "public_endpoint", "paths_filter", "metrics_config", "audit_log_config", "major_version_upgrade_config") {
return nil
}

// Get metrics audit config and mvu config first so we can validate and fail faster
mvuConfig, diagErr := getMajorVersionUpgradeConfig(d)
if diagErr != nil {
return diagErr
}

if d.HasChange("tier") || d.HasChange("metrics_config") || d.HasChange("audit_log_config") {
diagErr := updateVaultClusterConfig(ctx, client, d, cluster, clusterID)
if diagErr != nil {
Expand Down Expand Up @@ -529,6 +593,13 @@ func resourceVaultClusterUpdate(ctx context.Context, d *schema.ResourceData, met
}
}

if mvuConfig != nil {
_, err := clients.UpdateVaultMajorVersionUpgradeConfig(ctx, client, cluster.Location, clusterID, mvuConfig)
if err != nil {
return diag.Errorf("error updating Vault cluster major version upgrade config (%s): %v", clusterID, err)
}
}

// Get the updated Vault cluster.
cluster, err = clients.GetVaultClusterByID(ctx, client, loc, clusterID)

Expand Down Expand Up @@ -709,6 +780,10 @@ func setVaultClusterResourceData(d *schema.ResourceData, cluster *vaultmodels.Ha
return err
}

if err := d.Set("major_version_upgrade_config", flattenMajorVersionUpgradeConfig(cluster.Config.MajorVersionUpgradeConfig, d)); err != nil {
return err
}

if publicEndpoint {
// Port 8200 required to communicate with HCP Vault via HTTPS
if err := d.Set("vault_public_endpoint_url", fmt.Sprintf("https://%s:8200", cluster.DNSNames.Public)); err != nil {
Expand Down Expand Up @@ -885,6 +960,86 @@ func getValidObservabilityConfig(config map[string]interface{}) (*vaultmodels.Ha
return &observabilityConfig, nil
}

func getMajorVersionUpgradeConfig(d *schema.ResourceData) (*vaultmodels.HashicorpCloudVault20201125MajorVersionUpgradeConfig, diag.Diagnostics) {
if !d.HasChange("major_version_upgrade_config") {
return nil, nil
}
configParam, ok := d.GetOk("major_version_upgrade_config")
if !ok {
return nil, nil
}

configIfaceArr, ok := configParam.([]interface{})
if !ok || len(configIfaceArr) == 0 {
return nil, nil
}

config, ok := configIfaceArr[0].(map[string]interface{})
if !ok {
return nil, nil
}

tier := vaultmodels.HashicorpCloudVault20201125TierDEV
inputTier, ok := d.GetOk("tier")
if ok {
tier = vaultmodels.HashicorpCloudVault20201125Tier(strings.ToUpper(inputTier.(string)))
}

if !ok || len(configIfaceArr) == 0 {
return nil, nil
}

return getValidMajorVersionUpgradeConfig(config, tier)
}

func getValidMajorVersionUpgradeConfig(config map[string]interface{}, tier vaultmodels.HashicorpCloudVault20201125Tier) (*vaultmodels.HashicorpCloudVault20201125MajorVersionUpgradeConfig, diag.Diagnostics) {
if tier == vaultmodels.HashicorpCloudVault20201125TierDEV || tier == vaultmodels.HashicorpCloudVault20201125TierSTARTERSMALL {
return nil, diag.Errorf("major version configuration is only allowed for STANDARD or PLUS clusters")
}

mvuConfig := vaultmodels.HashicorpCloudVault20201125MajorVersionUpgradeConfig{}

upgradeType := config["upgrade_type"].(string)
mvuConfig.UpgradeType = vaultmodels.HashicorpCloudVault20201125MajorVersionUpgradeConfigUpgradeType(upgradeType)

maintenanceWindowDay := config["maintenance_window_day"].(string)
maintenanceWindowTime := config["maintenance_window_time"].(string)

if mvuConfig.UpgradeType == vaultmodels.HashicorpCloudVault20201125MajorVersionUpgradeConfigUpgradeTypeSCHEDULED {
if maintenanceWindowDay == "" || maintenanceWindowTime == "" {
return nil, diag.Errorf("major version upgrade configuration is invalid: maintenance window configuration information missing")
}
mvuConfig.MaintenanceWindow = &vaultmodels.HashicorpCloudVault20201125MajorVersionUpgradeConfigMaintenanceWindow{
DayOfWeek: vaultmodels.HashicorpCloudVault20201125MajorVersionUpgradeConfigMaintenanceWindowDayOfWeek(maintenanceWindowDay),
TimeWindowUtc: vaultmodels.HashicorpCloudVault20201125MajorVersionUpgradeConfigMaintenanceWindowTimeWindowUTC(maintenanceWindowTime),
}
} else {
if maintenanceWindowDay != "" || maintenanceWindowTime != "" {
return nil, diag.Errorf("major version upgrade configuration is invalid: maintenance window is only allowed to SCHEDULED upgrades")
}
mvuConfig.MaintenanceWindow = nil
}

return &mvuConfig, nil
}

func flattenMajorVersionUpgradeConfig(config *vaultmodels.HashicorpCloudVault20201125MajorVersionUpgradeConfig, d *schema.ResourceData) []interface{} {
if config == nil {
return []interface{}{}
}

configMap := map[string]interface{}{}
upgradeType := config.UpgradeType

configMap["upgrade_type"] = upgradeType
if upgradeType == vaultmodels.HashicorpCloudVault20201125MajorVersionUpgradeConfigUpgradeTypeSCHEDULED && config.MaintenanceWindow != nil {
configMap["maintenance_window_day"] = config.MaintenanceWindow.DayOfWeek
configMap["maintenance_window_time"] = config.MaintenanceWindow.TimeWindowUtc
}

return []interface{}{configMap}
}

func resourceVaultClusterImport(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
client := meta.(*clients.Client)

Expand Down
Loading