Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 4 additions & 0 deletions docs/resources/container.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ The following arguments are supported:

- `args` - (Optional) Arguments passed to the command specified in the "command" field. These override the default arguments from the container image, and behave like command-line parameters.

- `private_network_id` (Optional) The ID of the Private Network the container is connected to.

~> **Important** This feature is currently in beta and requires a namespace with VPC integration activated by setting the `activate_vpc_integration` attribute to `true`.

Note that if you want to use your own configuration, you must consult our configuration [restrictions](https://www.scaleway.com/en/docs/serverless-containers/reference-content/containers-limitations/#configuration-restrictions) section.

## Attributes Reference
Expand Down
4 changes: 4 additions & 0 deletions docs/resources/container_namespace.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ The following arguments are supported:

- `secret_environment_variables` - (Optional) The secret environment variables of the namespace.

- `activate_vpc_integration` - (Optional) Activates VPC integration for the namespace. Containers of a namespace with VPC integration activated will be able to connect to a Private Network.

~> **Important** Updates to `activate_vpc_integration` will recreate the namespace.

## Attributes Reference

The `scaleway_container_namespace` resource exports certain attributes once the Containers namespace has been created. These attributes can be referenced in other parts of your Terraform configuration.
Expand Down
1 change: 1 addition & 0 deletions internal/acctest/validate_cassettes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ func exceptionsCassettesCases() map[string]struct{} {
"../services/secret/testdata/secret-version-type.cassette.yaml": {},
"../services/file/testdata/file-system-invalid-size-granularity-fails.cassette.yaml": {},
"../services/file/testdata/file-system-size-too-small-fails.cassette.yaml": {},
"../services/container/testdata/namespace-vpc-integration.cassette.yaml": {},
}
}

Expand Down
12 changes: 12 additions & 0 deletions internal/services/container/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func ResourceContainer() *schema.Resource {
"namespace_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "The container namespace associated",
},
"tags": {
Expand Down Expand Up @@ -263,6 +264,11 @@ func ResourceContainer() *schema.Resource {
Optional: true,
Description: "Arguments passed to the command from the command \"field\". Overrides the arguments from the container image.",
},
"private_network_id": {
Type: schema.TypeString,
Optional: true,
Description: "ID of the Private Network the container is connected to",
},
// computed
"status": {
Type: schema.TypeString,
Expand Down Expand Up @@ -385,6 +391,12 @@ func ResourceContainerRead(ctx context.Context, d *schema.ResourceData, m any) d
_ = d.Set("command", types.FlattenSliceString(co.Command))
_ = d.Set("args", types.FlattenSliceString(co.Args))

if co.PrivateNetworkID != nil {
_ = d.Set("private_network_id", regional.NewID(region, types.FlattenStringPtr(co.PrivateNetworkID).(string)).String())
} else {
_ = d.Set("private_network_id", nil)
}

return nil
}

Expand Down
132 changes: 132 additions & 0 deletions internal/services/container/container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/container"
containerchecks "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/container/testfuncs"
vpcchecks "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/vpc/testfuncs"
)

func TestAccContainer_Basic(t *testing.T) {
Expand Down Expand Up @@ -645,6 +646,137 @@ func TestAccContainer_CommandAndArgs(t *testing.T) {
})
}

func TestAccContainer_PrivateNetwork(t *testing.T) {
tt := acctest.NewTestTools(t)
defer tt.Cleanup()
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ProviderFactories: tt.ProviderFactories,
CheckDestroy: resource.ComposeTestCheckFunc(
isNamespaceDestroyed(tt),
isContainerDestroyed(tt),
vpcchecks.CheckPrivateNetworkDestroy(tt),
),
Steps: []resource.TestStep{
{
Config: `
resource scaleway_vpc_private_network pn00 {
name = "test-acc-container-pn-pn00"
}
resource scaleway_vpc_private_network pn01 {
name = "test-acc-container-pn-pn01"
}

resource scaleway_container_namespace main {
activate_vpc_integration = true
}

resource scaleway_container c00 {
name = "test-acc-container-pn-c00"
namespace_id = scaleway_container_namespace.main.id
private_network_id = scaleway_vpc_private_network.pn00.id
sandbox = "v1"
}
`,
Check: resource.ComposeTestCheckFunc(
isContainerPresent(tt, "scaleway_container.c00"),
resource.TestCheckResourceAttr("scaleway_container_namespace.main", "activate_vpc_integration", "true"),
resource.TestCheckResourceAttr("scaleway_container.c00", "sandbox", "v1"),
resource.TestCheckResourceAttrPair("scaleway_container.c00", "private_network_id", "scaleway_vpc_private_network.pn00", "id"),
),
},
{
Config: `
resource scaleway_vpc_private_network pn00 {
name = "test-acc-container-pn-pn00"
}
resource scaleway_vpc_private_network pn01 {
name = "test-acc-container-pn-pn01"
}

resource scaleway_container_namespace main {
activate_vpc_integration = true
}

resource scaleway_container c00 {
name = "test-acc-container-pn-c00"
namespace_id = scaleway_container_namespace.main.id
private_network_id = scaleway_vpc_private_network.pn00.id
sandbox = "v1"
}

resource scaleway_container c01 {
name = "test-acc-container-pn-c01"
namespace_id = scaleway_container_namespace.main.id
private_network_id = scaleway_vpc_private_network.pn00.id
sandbox = "v1"
}

resource scaleway_container c02 {
name = "test-acc-container-pn-c02"
namespace_id = scaleway_container_namespace.main.id
private_network_id = scaleway_vpc_private_network.pn00.id
sandbox = "v1"
}
`,
Check: resource.ComposeTestCheckFunc(
isContainerPresent(tt, "scaleway_container.c00"),
isContainerPresent(tt, "scaleway_container.c01"),
isContainerPresent(tt, "scaleway_container.c02"),
resource.TestCheckResourceAttr("scaleway_container.c00", "sandbox", "v1"),
resource.TestCheckResourceAttr("scaleway_container.c01", "sandbox", "v1"),
resource.TestCheckResourceAttr("scaleway_container.c02", "sandbox", "v1"),
resource.TestCheckResourceAttrPair("scaleway_container.c00", "private_network_id", "scaleway_vpc_private_network.pn00", "id"),
resource.TestCheckResourceAttrPair("scaleway_container.c01", "private_network_id", "scaleway_vpc_private_network.pn00", "id"),
resource.TestCheckResourceAttrPair("scaleway_container.c02", "private_network_id", "scaleway_vpc_private_network.pn00", "id"),
),
},
{
Config: `
resource scaleway_vpc_private_network pn00 {
name = "test-acc-container-pn-pn00"
}
resource scaleway_vpc_private_network pn01 {
name = "test-acc-container-pn-pn01"
}

resource scaleway_container_namespace main {
activate_vpc_integration = true
}

resource scaleway_container c00 {
name = "test-acc-container-pn-c00"
namespace_id = scaleway_container_namespace.main.id
sandbox = "v1"
}

resource scaleway_container c01 {
name = "test-acc-container-pn-c01"
namespace_id = scaleway_container_namespace.main.id
private_network_id = scaleway_vpc_private_network.pn01.id
sandbox = "v1"
}

resource scaleway_container c02 {
name = "test-acc-container-pn-c02"
namespace_id = scaleway_container_namespace.main.id
private_network_id = scaleway_vpc_private_network.pn00.id
sandbox = "v1"
}
`,
Check: resource.ComposeTestCheckFunc(
isContainerPresent(tt, "scaleway_container.c00"),
isContainerPresent(tt, "scaleway_container.c01"),
isContainerPresent(tt, "scaleway_container.c02"),
resource.TestCheckResourceAttr("scaleway_container.c00", "private_network_id", ""),
resource.TestCheckResourceAttrPair("scaleway_container.c01", "private_network_id", "scaleway_vpc_private_network.pn01", "id"),
resource.TestCheckResourceAttrPair("scaleway_container.c02", "private_network_id", "scaleway_vpc_private_network.pn00", "id"),
),
},
},
})
}

func isContainerPresent(tt *acctest.TestTools, n string) resource.TestCheckFunc {
return func(state *terraform.State) error {
rs, ok := state.RootModule().Resources[n]
Expand Down
8 changes: 8 additions & 0 deletions internal/services/container/helpers_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ func setCreateContainerRequest(d *schema.ResourceData, region scw.Region) (*cont
req.Args = types.ExpandStrings(args)
}

if pnID, ok := d.GetOk("private_network_id"); ok {
req.PrivateNetworkID = types.ExpandStringPtr(locality.ExpandID(pnID.(string)))
}

return req, nil
}

Expand Down Expand Up @@ -270,6 +274,10 @@ func setUpdateContainerRequest(d *schema.ResourceData, region scw.Region, contai
req.Args = types.ExpandUpdatedStringsPtr(d.Get("args"))
}

if d.HasChanges("private_network_id") {
req.PrivateNetworkID = types.ExpandUpdatedStringPtr(locality.ExpandID(d.Get("private_network_id")))
}

return req, nil
}

Expand Down
12 changes: 12 additions & 0 deletions internal/services/container/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ func ResourceNamespace() *schema.Resource {
Description: "Destroy registry on deletion",
Deprecated: "Registry namespace is automatically destroyed with namespace",
},
"activate_vpc_integration": {
Type: schema.TypeBool,
ForceNew: true,
Optional: true,
Default: false,
Description: "Activate VPC integration for the namespace",
},
"region": regional.Schema(),
"organization_id": account.OrganizationIDSchema(),
"project_id": account.ProjectIDSchema(),
Expand Down Expand Up @@ -122,6 +129,10 @@ func ResourceContainerNamespaceCreate(ctx context.Context, d *schema.ResourceDat
createReq.Tags = types.ExpandStrings(rawTag)
}

if activateVPC, ok := d.GetOk("activate_vpc_integration"); ok {
createReq.ActivateVpcIntegration = activateVPC.(bool)
}

ns, err := api.CreateNamespace(createReq, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
Expand Down Expand Up @@ -164,6 +175,7 @@ func ResourceContainerNamespaceRead(ctx context.Context, d *schema.ResourceData,
_ = d.Set("registry_endpoint", ns.RegistryEndpoint)
_ = d.Set("registry_namespace_id", ns.RegistryNamespaceID)
_ = d.Set("secret_environment_variables", flattenContainerSecrets(ns.SecretEnvironmentVariables))
_ = d.Set("activate_vpc_integration", types.FlattenBoolPtr(ns.VpcIntegrationActivated))

return nil
}
Expand Down
74 changes: 74 additions & 0 deletions internal/services/container/namespace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package container_test

import (
"fmt"
"regexp"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
Expand All @@ -12,6 +13,7 @@ import (
"github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/container"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/registry"
vpcchecks "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/vpc/testfuncs"
)

const containerNamespaceResource = "scaleway_container_namespace"
Expand Down Expand Up @@ -265,6 +267,78 @@ func TestAccNamespace_DestroyRegistry(t *testing.T) {
})
}

func TestAccNamespace_VPCIntegration(t *testing.T) {
tt := acctest.NewTestTools(t)
defer tt.Cleanup()

namespaceID := ""

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ProviderFactories: tt.ProviderFactories,
CheckDestroy: resource.ComposeTestCheckFunc(
isNamespaceDestroyed(tt),
isContainerDestroyed(tt),
vpcchecks.CheckPrivateNetworkDestroy(tt),
),
Steps: []resource.TestStep{
{
Config: `
resource scaleway_vpc_private_network main {}
resource scaleway_container_namespace main {}
resource scaleway_container main {
namespace_id = scaleway_container_namespace.main.id
sandbox = "v1"
}
`,
Check: resource.ComposeTestCheckFunc(
isNamespacePresent(tt, "scaleway_container_namespace.main"),
resource.TestCheckResourceAttr("scaleway_container_namespace.main", "activate_vpc_integration", "false"),
acctest.CheckResourceIDPersisted("scaleway_container_namespace.main", &namespaceID),
),
},
{
Config: `
resource scaleway_vpc_private_network main {}
resource scaleway_container_namespace main {}
resource scaleway_container main {
namespace_id = scaleway_container_namespace.main.id
private_network_id = scaleway_vpc_private_network.main.id
sandbox = "v1"
}
`,
ExpectError: regexp.MustCompile("Application can't be attached to private network, vpc integration must be activated on its parent namespace"),
},
{
Config: `
resource scaleway_vpc_private_network main {}
resource scaleway_container_namespace main {
activate_vpc_integration = true
}
resource scaleway_container main {
namespace_id = scaleway_container_namespace.main.id
private_network_id = scaleway_vpc_private_network.main.id
sandbox = "v1"
}
`,
Check: resource.ComposeTestCheckFunc(
isNamespacePresent(tt, "scaleway_container_namespace.main"),
isContainerPresent(tt, "scaleway_container.main"),
resource.TestCheckResourceAttr("scaleway_container_namespace.main", "activate_vpc_integration", "true"),
resource.TestCheckResourceAttrPair("scaleway_container.main", "private_network_id", "scaleway_vpc_private_network.main", "id"),
acctest.CheckResourceIDChanged("scaleway_container_namespace.main", &namespaceID),
),
},
},
})
}

func isNamespacePresent(tt *acctest.TestTools, n string) resource.TestCheckFunc {
return func(state *terraform.State) error {
rs, ok := state.RootModule().Resources[n]
Expand Down
Loading
Loading