feat(provider): Support worker filter on dynamic host catalogs
This commit is contained in:
1 parent
ad43c0bec0
commit
f9fd811205
6 files changed
+302
-161
No files matched your search
@@ -118,6 +118,11 @@ func resourceHostCatalogPlugin() *schema.Resource {
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
WorkerFilterKey: {
|
||||
Description: "HCP Only. A filter used to control which PKI workers can handle dynamic host catalog requests.",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
internalSecretsConfigHmacKey: {
|
||||
Description: "Internal only. HMAC of (serverSecretsHmac + config secrets). Used for proper secrets handling.",
|
||||
Type: schema.TypeString,
|
||||
@@ -294,6 +299,9 @@ func setFromHostCatalogPluginResponseMap(d *schema.ResourceData, raw map[string]
|
||||
if err := d.Set(ScopeIdKey, raw[ScopeIdKey]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(WorkerFilterKey, raw[WorkerFilterKey]); err != nil {
|
||||
return err
|
||||
}
|
||||
// Plugin stuff
|
||||
{
|
||||
if err := d.Set(PluginIdKey, raw[PluginIdKey]); err != nil {
|
||||
@@ -399,6 +407,12 @@ func resourceHostCatalogPluginCreate(ctx context.Context, d *schema.ResourceData
|
||||
opts = append(opts, hostcatalogs.WithDescription(descStr))
|
||||
}
|
||||
|
||||
workerFilterVal, ok := d.GetOk(WorkerFilterKey)
|
||||
if ok {
|
||||
workerFilterStr := workerFilterVal.(string)
|
||||
opts = append(opts, hostcatalogs.WithWorkerFilter(workerFilterStr))
|
||||
}
|
||||
|
||||
attrsVal, ok := d.GetOk(AttributesJsonKey)
|
||||
if ok {
|
||||
attrsStr, err := parseutil.ParsePath(attrsVal.(string))
|
||||
@@ -556,6 +570,15 @@ func resourceHostCatalogPluginUpdate(ctx context.Context, d *schema.ResourceData
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange(WorkerFilterKey) {
|
||||
opts = append(opts, hostcatalogs.DefaultWorkerFilter())
|
||||
workerFilterVal, ok := d.GetOk(WorkerFilterKey)
|
||||
if ok {
|
||||
workerFilterStr := workerFilterVal.(string)
|
||||
opts = append(opts, hostcatalogs.WithWorkerFilter(workerFilterStr))
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange(AttributesJsonKey) {
|
||||
attrsVal, ok := d.GetOk(AttributesJsonKey)
|
||||
if ok {
|
||||
|
||||
@@ -22,6 +22,9 @@ const (
|
||||
testPluginHostCatalogDescription = "bar"
|
||||
testPluginHostCatalogDescriptionUpdate = "bar foo"
|
||||
testPluginHostCatalogDescriptionUpdate2 = "bar foo foo"
|
||||
|
||||
testPluginHostCatalogWorkerFilterUpdate = "\"dev\" in \"/tags/type\""
|
||||
testPluginHostCatalogWorkerFilterUpdate2 = "\"pki\" in \"/tags/type\""
|
||||
)
|
||||
|
||||
// expectedAttributesState is used here and in plugin host sets to control how
|
||||
@@ -244,6 +247,212 @@ func TestAccPluginHostCatalog(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccPluginHostCatalogWithWorkerFilter(t *testing.T) {
|
||||
t.Skip("Skipping test until Boundary Terraform Provider can unit tests for Boundary Enterprise only features")
|
||||
|
||||
tc := controller.NewTestController(t, tcConfig...)
|
||||
defer tc.Shutdown()
|
||||
url := tc.ApiAddrs()[0]
|
||||
|
||||
resName := "boundary_host_catalog_plugin.foo"
|
||||
initialValuesStr := fmt.Sprintf(`
|
||||
description = "%s"
|
||||
attributes_json = jsonencode({
|
||||
foo = "bar"
|
||||
zip = "zap"
|
||||
})
|
||||
secrets_json = jsonencode({
|
||||
hush = "puppies"
|
||||
})
|
||||
`,
|
||||
testPluginHostCatalogDescription,
|
||||
)
|
||||
|
||||
// Changed description, secrets and added worker filter.
|
||||
valuesStrUpdate1 := fmt.Sprintf(`
|
||||
description = "%s"
|
||||
worker_filter = %q
|
||||
attributes_json = jsonencode({
|
||||
foo = "bar"
|
||||
zip = "zoop"
|
||||
})
|
||||
secrets_json = jsonencode({
|
||||
flush = "fluppies"
|
||||
})
|
||||
`,
|
||||
testPluginHostCatalogDescriptionUpdate,
|
||||
testPluginHostCatalogWorkerFilterUpdate,
|
||||
)
|
||||
|
||||
// Changed description, no secrets update, nullify worker filter.
|
||||
valuesStrUpdate2 := fmt.Sprintf(`
|
||||
description = "%s"
|
||||
worker_filter = null
|
||||
attributes_json = jsonencode({
|
||||
foo = "bar"
|
||||
zip = "zoop"
|
||||
})
|
||||
secrets_json = jsonencode({
|
||||
flush = "fluppies"
|
||||
})
|
||||
`,
|
||||
testPluginHostCatalogDescriptionUpdate2,
|
||||
)
|
||||
|
||||
// Same description and set a worker filter again, now empty secrets.
|
||||
valuesStrUpdate3 := fmt.Sprintf(`
|
||||
description = "%s"
|
||||
worker_filter = %q
|
||||
attributes_json = jsonencode({
|
||||
foo = "bar"
|
||||
zip = "zoop"
|
||||
})
|
||||
`,
|
||||
testPluginHostCatalogDescriptionUpdate2,
|
||||
testPluginHostCatalogWorkerFilterUpdate2,
|
||||
)
|
||||
|
||||
// Same description, now explicitly unset secrets and blankify attrs and
|
||||
// worker filter.
|
||||
valuesStrUpdate4 := fmt.Sprintf(`
|
||||
description = "%s"
|
||||
secrets_json = "null"
|
||||
`,
|
||||
testPluginHostCatalogDescriptionUpdate2,
|
||||
)
|
||||
|
||||
// Set values again
|
||||
valuesStrUpdate5 := fmt.Sprintf(`
|
||||
description = "%s"
|
||||
worker_filter = %q
|
||||
attributes_json = jsonencode({
|
||||
foo = "bar"
|
||||
zip = "zoop"
|
||||
})
|
||||
secrets_json = jsonencode({
|
||||
flush = "fluppies"
|
||||
})
|
||||
`,
|
||||
testPluginHostCatalogDescriptionUpdate2,
|
||||
testPluginHostCatalogWorkerFilterUpdate2,
|
||||
)
|
||||
|
||||
// Explicitly set both secrets and attributes to null
|
||||
valuesStrUpdate6 := fmt.Sprintf(`
|
||||
description = "%s"
|
||||
worker_filter = %q
|
||||
attributes_json = "null"
|
||||
secrets_json = "null"
|
||||
`,
|
||||
testPluginHostCatalogDescriptionUpdate2,
|
||||
testPluginHostCatalogWorkerFilterUpdate2,
|
||||
)
|
||||
|
||||
initialHcl := fmt.Sprintf(projPluginHostCatalogBase, initialValuesStr)
|
||||
update1Hcl := fmt.Sprintf(projPluginHostCatalogBase, valuesStrUpdate1)
|
||||
update2Hcl := fmt.Sprintf(projPluginHostCatalogBase, valuesStrUpdate2)
|
||||
update3Hcl := fmt.Sprintf(projPluginHostCatalogBase, valuesStrUpdate3)
|
||||
update4Hcl := fmt.Sprintf(projPluginHostCatalogBase, valuesStrUpdate4)
|
||||
update5Hcl := fmt.Sprintf(projPluginHostCatalogBase, valuesStrUpdate5)
|
||||
update6Hcl := fmt.Sprintf(projPluginHostCatalogBase, valuesStrUpdate6)
|
||||
|
||||
var provider *schema.Provider
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProviderFactories: providerFactories(&provider),
|
||||
CheckDestroy: testAccCheckHostCatalogResourceDestroy(t, provider, baseHostCatalogType),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
// test create
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, initialHcl),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckScopeResourceExists(provider, "boundary_scope.org1"),
|
||||
testAccCheckScopeResourceExists(provider, "boundary_scope.proj1"),
|
||||
testAccCheckPluginHostCatalogResourceExists(provider, resName, expectedAttributesStatePreviouslyEmptyNowSet),
|
||||
resource.TestCheckResourceAttr(resName, DescriptionKey, testPluginHostCatalogDescription),
|
||||
),
|
||||
ExpectNonEmptyPlan: true,
|
||||
},
|
||||
importStep(resName, SecretsJsonKey, internalHmacUsedForSecretsConfigHmacKey, internalForceUpdateKey, internalSecretsConfigHmacKey),
|
||||
{
|
||||
// test update
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, update1Hcl),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckPluginHostCatalogResourceExists(provider, resName, expectedAttributesStatePreviouslySetButChanged),
|
||||
resource.TestCheckResourceAttr(resName, DescriptionKey, testPluginHostCatalogDescriptionUpdate),
|
||||
resource.TestCheckResourceAttr(resName, WorkerFilterKey, testPluginHostCatalogWorkerFilterUpdate),
|
||||
),
|
||||
ExpectNonEmptyPlan: true,
|
||||
},
|
||||
importStep(resName, SecretsJsonKey, internalHmacUsedForSecretsConfigHmacKey, internalForceUpdateKey, internalSecretsConfigHmacKey),
|
||||
{
|
||||
// test update
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, update2Hcl),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckPluginHostCatalogResourceExists(provider, resName, expectedAttributesStatePreviouslySetNoChange),
|
||||
resource.TestCheckResourceAttr(resName, DescriptionKey, testPluginHostCatalogDescriptionUpdate2),
|
||||
),
|
||||
ExpectNonEmptyPlan: true,
|
||||
},
|
||||
importStep(resName, SecretsJsonKey, internalHmacUsedForSecretsConfigHmacKey, internalForceUpdateKey, internalSecretsConfigHmacKey),
|
||||
{
|
||||
// this runs the same HCL; mostly used in some manual checking
|
||||
// to ensure update is still called even when nothing has
|
||||
// changed (as we need for secrets)
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, update2Hcl),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckPluginHostCatalogResourceExists(provider, resName, expectedAttributesStatePreviouslySetNoChange),
|
||||
resource.TestCheckResourceAttr(resName, DescriptionKey, testPluginHostCatalogDescriptionUpdate2),
|
||||
),
|
||||
ExpectNonEmptyPlan: true,
|
||||
},
|
||||
importStep(resName, SecretsJsonKey, internalHmacUsedForSecretsConfigHmacKey, internalForceUpdateKey, internalSecretsConfigHmacKey),
|
||||
{
|
||||
// test update
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, update3Hcl),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckPluginHostCatalogResourceExists(provider, resName, expectedAttributesStatePreviouslySetNoChange),
|
||||
resource.TestCheckResourceAttr(resName, DescriptionKey, testPluginHostCatalogDescriptionUpdate2),
|
||||
resource.TestCheckResourceAttr(resName, WorkerFilterKey, testPluginHostCatalogWorkerFilterUpdate2),
|
||||
),
|
||||
ExpectNonEmptyPlan: true,
|
||||
},
|
||||
importStep(resName, SecretsJsonKey, internalHmacUsedForSecretsConfigHmacKey, internalForceUpdateKey, internalSecretsConfigHmacKey),
|
||||
{
|
||||
// test update
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, update4Hcl),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckPluginHostCatalogResourceExists(provider, resName, expectedAttributesStatePreviouslySetNowEmpty),
|
||||
resource.TestCheckResourceAttr(resName, DescriptionKey, testPluginHostCatalogDescriptionUpdate2),
|
||||
),
|
||||
ExpectNonEmptyPlan: true,
|
||||
},
|
||||
importStep(resName, SecretsJsonKey, internalHmacUsedForSecretsConfigHmacKey, internalForceUpdateKey, internalSecretsConfigHmacKey),
|
||||
{
|
||||
// test update
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, update5Hcl),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckPluginHostCatalogResourceExists(provider, resName, expectedAttributesStatePreviouslyEmptyNowSet),
|
||||
resource.TestCheckResourceAttr(resName, DescriptionKey, testPluginHostCatalogDescriptionUpdate2),
|
||||
resource.TestCheckResourceAttr(resName, WorkerFilterKey, testPluginHostCatalogWorkerFilterUpdate2),
|
||||
),
|
||||
ExpectNonEmptyPlan: true,
|
||||
},
|
||||
importStep(resName, SecretsJsonKey, internalHmacUsedForSecretsConfigHmacKey, internalForceUpdateKey, internalSecretsConfigHmacKey),
|
||||
{
|
||||
// test update
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, update6Hcl),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckPluginHostCatalogResourceExists(provider, resName, expectedAttributesStatePreviouslySetNowEmpty),
|
||||
resource.TestCheckResourceAttr(resName, DescriptionKey, testPluginHostCatalogDescriptionUpdate2),
|
||||
resource.TestCheckResourceAttr(resName, WorkerFilterKey, testPluginHostCatalogWorkerFilterUpdate2),
|
||||
),
|
||||
ExpectNonEmptyPlan: true,
|
||||
},
|
||||
importStep(resName, SecretsJsonKey, internalHmacUsedForSecretsConfigHmacKey, internalForceUpdateKey, internalSecretsConfigHmacKey),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckPluginHostCatalogResourceExists(testProvider *schema.Provider, name string, expAttrState expectedAttributesState) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[name]
|
||||
|
||||
Reference in new issue
Block a user