Skip to content

Commit

Permalink
Merge pull request #964 from Juniper/962-apstra_blueprint_device_rend…
Browse files Browse the repository at this point in the history
…ered_config-data-source-404-handling

Data source `apstra_blueprint_device_rendered_config` no error on incremental config 404
  • Loading branch information
chrismarget-j authored Nov 5, 2024
2 parents 8d9026d + 9c87de4 commit cef801c
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 55 deletions.
69 changes: 29 additions & 40 deletions apstra/data_source_blueprint_device_rendered_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import (
"github.com/Juniper/apstra-go-sdk/apstra"
"github.com/Juniper/apstra-go-sdk/apstra/enum"
"github.com/Juniper/terraform-provider-apstra/apstra/blueprint"
"github.com/Juniper/terraform-provider-apstra/apstra/utils"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
)

var (
Expand Down Expand Up @@ -46,77 +46,66 @@ func (o *dataSourceBlueprintNodeConfig) Read(ctx context.Context, req datasource
return
}

addNodeDiag := func(err error) {
var ace apstra.ClientErr
if errors.As(err, &ace) && ace.Type() == apstra.ErrNotfound {
resp.Diagnostics.AddError(
"Not Found",
fmt.Sprintf("Node %s in blueprint %s not found", config.NodeId, config.BlueprintId),
)
} else {
resp.Diagnostics.AddError("Failed to fetch config", err.Error())
}
}

addSysDiag := func(err error) {
var ace apstra.ClientErr
if errors.As(err, &ace) && ace.Type() == apstra.ErrNotfound {
resp.Diagnostics.AddError(
"Not Found",
fmt.Sprintf("System %s in blueprint %s not found", config.SystemId, config.BlueprintId),
)
} else {
resp.Diagnostics.AddError("Failed to fetch config", err.Error())
}
}

bpId := apstra.ObjectId(config.BlueprintId.ValueString())

var err error
var deployed, staged, incremental string
var ace apstra.ClientErr

switch {
case !config.NodeId.IsNull():
node := apstra.ObjectId(config.NodeId.ValueString())
deployed, err = o.client.GetNodeRenderedConfig(ctx, bpId, node, enum.RenderedConfigTypeDeployed)
if err != nil {
addNodeDiag(err)
return
if !errors.As(err, &ace) || ace.Type() != apstra.ErrNotfound {
resp.Diagnostics.AddError(fmt.Sprintf("failed to fetch deployed configuration for node %s", config.NodeId), err.Error())
return
}
}
staged, err = o.client.GetNodeRenderedConfig(ctx, bpId, node, enum.RenderedConfigTypeStaging)
if err != nil {
addNodeDiag(err)
return
if !errors.As(err, &ace) || ace.Type() != apstra.ErrNotfound {
resp.Diagnostics.AddError(fmt.Sprintf("failed to fetch staged configuration for node %s", config.NodeId), err.Error())
return
}
}
diff, err := o.client.GetNodeRenderedConfigDiff(ctx, bpId, node)
if err != nil {
addNodeDiag(err)
return
if !errors.As(err, &ace) || ace.Type() != apstra.ErrNotfound {
resp.Diagnostics.AddError(fmt.Sprintf("failed to fetch incremental configuration for node %s", config.NodeId), err.Error())
return
}
}
incremental = diff.Config
case !config.SystemId.IsNull():
system := apstra.ObjectId(config.SystemId.ValueString())
deployed, err = o.client.GetSystemRenderedConfig(ctx, bpId, system, enum.RenderedConfigTypeDeployed)
if err != nil {
addSysDiag(err)
return
if !errors.As(err, &ace) || ace.Type() != apstra.ErrNotfound {
resp.Diagnostics.AddError(fmt.Sprintf("failed to fetch deployed configuration for system %s", config.SystemId), err.Error())
return
}
}
staged, err = o.client.GetSystemRenderedConfig(ctx, bpId, system, enum.RenderedConfigTypeStaging)
if err != nil {
addSysDiag(err)
return
if !errors.As(err, &ace) || ace.Type() != apstra.ErrNotfound {
resp.Diagnostics.AddError(fmt.Sprintf("failed to fetch staged configuration for system %s", config.SystemId), err.Error())
return
}
}
diff, err := o.client.GetSystemRenderedConfigDiff(ctx, bpId, system)
if err != nil {
addSysDiag(err)
return
if !errors.As(err, &ace) || ace.Type() != apstra.ErrNotfound {
resp.Diagnostics.AddError(fmt.Sprintf("failed to fetch incremental configuration for system %s", config.SystemId), err.Error())
return
}
}
incremental = diff.Config
}

config.DeployedCfg = types.StringValue(deployed)
config.StagedCfg = types.StringValue(staged)
config.Incremental = types.StringValue(incremental)
config.DeployedCfg = utils.StringValueOrNull(ctx, deployed, &resp.Diagnostics)
config.StagedCfg = utils.StringValueOrNull(ctx, staged, &resp.Diagnostics)
config.Incremental = utils.StringValueOrNull(ctx, incremental, &resp.Diagnostics)

// set state
resp.Diagnostics.Append(resp.State.Set(ctx, &config)...)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"bufio"
"context"
"fmt"
"log"
"math"
"math/rand/v2"
"strconv"
Expand Down Expand Up @@ -147,7 +148,7 @@ func TestAccDatasourceBlueprintDeviceRenderedConfig(t *testing.T) {
resource.TestCheckNoResourceAttr("data."+datasourceType+".test", "system_id"),
resource.TestCheckResourceAttrSet("data."+datasourceType+".test", "deployed_config"),
resource.TestCheckResourceAttrSet("data."+datasourceType+".test", "staged_config"),
resource.TestCheckResourceAttr("data."+datasourceType+".test", "incremental_config", ""),
resource.TestCheckNoResourceAttr("data."+datasourceType+".test", "incremental_config"),
resource.TestCheckResourceAttrWith("data."+datasourceType+".test", "deployed_config", atLeast100Lines),
resource.TestCheckResourceAttrWith("data."+datasourceType+".test", "staged_config", atLeast100Lines),
},
Expand All @@ -160,7 +161,7 @@ func TestAccDatasourceBlueprintDeviceRenderedConfig(t *testing.T) {
resource.TestCheckResourceAttr("data."+datasourceType+".test", "system_id", sysIds[0].String()),
resource.TestCheckResourceAttrSet("data."+datasourceType+".test", "deployed_config"),
resource.TestCheckResourceAttrSet("data."+datasourceType+".test", "staged_config"),
resource.TestCheckResourceAttr("data."+datasourceType+".test", "incremental_config", ""),
resource.TestCheckNoResourceAttr("data."+datasourceType+".test", "incremental_config"),
resource.TestCheckResourceAttrWith("data."+datasourceType+".test", "deployed_config", atLeast100Lines),
resource.TestCheckResourceAttrWith("data."+datasourceType+".test", "staged_config", atLeast100Lines),
},
Expand Down Expand Up @@ -199,28 +200,32 @@ func TestAccDatasourceBlueprintDeviceRenderedConfig(t *testing.T) {
},
}

// bpModificationWg delays modifications to the blueprint until pre-modification tests are complete
// bpModificationWg delays modifications to the blueprint until pre-modification tests are
// complete. Test cases which do not include pre-work contribute to (and delete from) this
// WG. Test cases which include pre-work must wait
bpModificationWg := new(sync.WaitGroup)

// testCaseStartWg ensures that no test case starts begins before all have had a chance
// to pile onto bpModificationWg
testCaseStartWg := new(sync.WaitGroup)
testCaseStartWg.Add(len(testCases))
for tName, tCase := range testCases {
if tCase.preFunc == nil {
log.Println(tName, "adding to bpModificationWg")
bpModificationWg.Add(1)
}
}

for tName, tCase := range testCases {
t.Run(tName, func(t *testing.T) {
t.Parallel()

if tCase.config.nodeId == "" && tCase.config.systemId == "" {
testCaseStartWg.Done()
if tCase.preFunc == nil {
log.Println(tName, "done-ing to bpModificationWg")
bpModificationWg.Done()
}
t.Skipf("skipping because node has no system assigned")
return
}
t.Parallel()

if tCase.preFunc == nil {
bpModificationWg.Add(1)
testCaseStartWg.Done()
} else {
testCaseStartWg.Done()
if tCase.preFunc != nil {
log.Printf("%s waiting for bpModificationWg", tName)
bpModificationWg.Wait()
tCase.preFunc(t, ctx, bp)
}
Expand All @@ -239,6 +244,7 @@ func TestAccDatasourceBlueprintDeviceRenderedConfig(t *testing.T) {
})

if tCase.preFunc == nil {
log.Println(tName, "done-ing to bpModificationWg")
bpModificationWg.Done() // release test cases which will make changes
}
})
Expand Down

0 comments on commit cef801c

Please sign in to comment.