Skip to content

Commit

Permalink
feat: introduce storage_directives map instead storage set
Browse files Browse the repository at this point in the history
  • Loading branch information
anvial committed Jul 1, 2024
1 parent 76b8490 commit 04cfe44
Show file tree
Hide file tree
Showing 5 changed files with 296 additions and 183 deletions.
14 changes: 6 additions & 8 deletions docs/resources/application.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ resource "juju_application" "placement_example" {
latest revision.
* If the charm revision or channel are not updated, then no changes will take
place (juju does not have an "un-attach" command for resources).
- `storage` (Attributes Set) Configure storage constraints for the juju application. (see [below for nested schema](#nestedatt--storage))
- `storage` (Attributes Set) Storage used by the application. (see [below for nested schema](#nestedatt--storage))
- `storage_directives` (Map of String) Storage directives (constraints) for the juju application. The map key is the label of the storage defined by the charm, the map value is the storage directive in the form <pool>,<count>,<size>.
- `trust` (Boolean) Set the trust for the application.
- `units` (Number) The number of application units to deploy for the charm.

Expand Down Expand Up @@ -127,15 +128,12 @@ Optional:
<a id="nestedatt--storage"></a>
### Nested Schema for `storage`

Required:

- `label` (String) The specific storage option defined in the charm.

Optional:
Read-Only:

- `count` (Number) The number of volumes.
- `pool` (String) Name of the storage pool to use. E.g. ebs on aws.
- `size` (String) The size of each volume. E.g. 100G.
- `label` (String) The specific storage option defined in the charm.
- `pool` (String) Name of the storage pool to use.
- `size` (String) The size of each volume.

## Import

Expand Down
84 changes: 84 additions & 0 deletions internal/provider/modifer_storagedirectiveset.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright 2024 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package provider

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
jujustorage "github.com/juju/juju/storage"
)

// storageDirectivesMapRequiresReplace is a plan modifier function that
// determines if the storage directive map requires the application to be
// replaced. It compares the storage directive map in the plan with the
// storage directive map in state.
// Return false if new items were added and old items were not changed.
// Return true if old items were changed or removed.
func storageDirectivesMapRequiresReplace(ctx context.Context, req planmodifier.MapRequest, resp *mapplanmodifier.RequiresReplaceIfFuncResponse) {
planSet := make(map[string]jujustorage.Constraints)
if !req.PlanValue.IsUnknown() {
var planStorageDirectives map[string]string
resp.Diagnostics.Append(req.PlanValue.ElementsAs(ctx, &planStorageDirectives, false)...)
if resp.Diagnostics.HasError() {
return
}
if len(planStorageDirectives) > 0 {
for label, storage := range planStorageDirectives {
cons, err := jujustorage.ParseConstraints(storage)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to parse storage directives, got error: %s", err))
continue
}
planSet[label] = cons
}
}
}
if resp.Diagnostics.HasError() {
return
}
stateSet := make(map[string]jujustorage.Constraints)
if !req.StateValue.IsUnknown() {
var stateStorageDirectives map[string]string
resp.Diagnostics.Append(req.StateValue.ElementsAs(ctx, &stateStorageDirectives, false)...)
if resp.Diagnostics.HasError() {
return
}
if len(stateStorageDirectives) > 0 {
for label, storage := range stateStorageDirectives {
cons, err := jujustorage.ParseConstraints(storage)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to parse storage directives, got error: %s", err))
continue
}
stateSet[label] = cons
}
}
}

// Return false if new items were added and old items were not changed
for key, value := range planSet {
stateValue, ok := stateSet[key]
if !ok {
resp.RequiresReplace = false
return
}
if (value.Size != stateValue.Size) || (value.Pool != stateValue.Pool) || (value.Count != stateValue.Count) {
resp.RequiresReplace = true
return
}
}

// Return true if old items were removed
for key := range stateSet {
if _, ok := planSet[key]; !ok {
resp.RequiresReplace = true
return
}
}

resp.RequiresReplace = false
}
Loading

0 comments on commit 04cfe44

Please sign in to comment.