Skip to content

Commit ba59cce

Browse files
Add Beta support for allowedPorts field for Cloud Workstations configurations (#11299)
Co-authored-by: Cameron Thornton <[email protected]> [upstream:76e5a0ffe848b0d4385e5dbd386d61016241f625] Signed-off-by: Modular Magician <[email protected]>
1 parent 2cbcc78 commit ba59cce

5 files changed

+467
-0
lines changed

.changelog/11299.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
workstations: added field `allowedPorts` to `google_workstations_workstation_config`
3+
```

google-beta/services/workstations/resource_workstations_workstation_config.go

+129
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,26 @@ func ResourceWorkstationsWorkstationConfig() *schema.Resource {
7575
ForceNew: true,
7676
Description: `The ID to be assigned to the workstation cluster config.`,
7777
},
78+
"allowed_ports": {
79+
Type: schema.TypeList,
80+
Computed: true,
81+
Optional: true,
82+
Description: `A list of port ranges specifying single ports or ranges of ports that are externally accessible in the workstation. Allowed ports must be one of 22, 80, or within range 1024-65535. If not specified defaults to ports 22, 80, and ports 1024-65535.`,
83+
Elem: &schema.Resource{
84+
Schema: map[string]*schema.Schema{
85+
"first": {
86+
Type: schema.TypeInt,
87+
Optional: true,
88+
Description: `Starting port number for the current range of ports. Valid ports are 22, 80, and ports within the range 1024-65535.`,
89+
},
90+
"last": {
91+
Type: schema.TypeInt,
92+
Optional: true,
93+
Description: `Ending port number for the current range of ports. Valid ports are 22, 80, and ports within the range 1024-65535.`,
94+
},
95+
},
96+
},
97+
},
7898
"annotations": {
7999
Type: schema.TypeMap,
80100
Optional: true,
@@ -725,6 +745,12 @@ func resourceWorkstationsWorkstationConfigCreate(d *schema.ResourceData, meta in
725745
} else if v, ok := d.GetOkExists("disable_tcp_connections"); !tpgresource.IsEmptyValue(reflect.ValueOf(disableTcpConnectionsProp)) && (ok || !reflect.DeepEqual(v, disableTcpConnectionsProp)) {
726746
obj["disableTcpConnections"] = disableTcpConnectionsProp
727747
}
748+
allowedPortsProp, err := expandWorkstationsWorkstationConfigAllowedPorts(d.Get("allowed_ports"), d, config)
749+
if err != nil {
750+
return err
751+
} else if v, ok := d.GetOkExists("allowed_ports"); !tpgresource.IsEmptyValue(reflect.ValueOf(allowedPortsProp)) && (ok || !reflect.DeepEqual(v, allowedPortsProp)) {
752+
obj["allowedPorts"] = allowedPortsProp
753+
}
728754
labelsProp, err := expandWorkstationsWorkstationConfigEffectiveLabels(d.Get("effective_labels"), d, config)
729755
if err != nil {
730756
return err
@@ -890,6 +916,9 @@ func resourceWorkstationsWorkstationConfigRead(d *schema.ResourceData, meta inte
890916
if err := d.Set("disable_tcp_connections", flattenWorkstationsWorkstationConfigDisableTcpConnections(res["disableTcpConnections"], d, config)); err != nil {
891917
return fmt.Errorf("Error reading WorkstationConfig: %s", err)
892918
}
919+
if err := d.Set("allowed_ports", flattenWorkstationsWorkstationConfigAllowedPorts(res["allowedPorts"], d, config)); err != nil {
920+
return fmt.Errorf("Error reading WorkstationConfig: %s", err)
921+
}
893922
if err := d.Set("conditions", flattenWorkstationsWorkstationConfigConditions(res["conditions"], d, config)); err != nil {
894923
return fmt.Errorf("Error reading WorkstationConfig: %s", err)
895924
}
@@ -988,6 +1017,12 @@ func resourceWorkstationsWorkstationConfigUpdate(d *schema.ResourceData, meta in
9881017
} else if v, ok := d.GetOkExists("disable_tcp_connections"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, disableTcpConnectionsProp)) {
9891018
obj["disableTcpConnections"] = disableTcpConnectionsProp
9901019
}
1020+
allowedPortsProp, err := expandWorkstationsWorkstationConfigAllowedPorts(d.Get("allowed_ports"), d, config)
1021+
if err != nil {
1022+
return err
1023+
} else if v, ok := d.GetOkExists("allowed_ports"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, allowedPortsProp)) {
1024+
obj["allowedPorts"] = allowedPortsProp
1025+
}
9911026
labelsProp, err := expandWorkstationsWorkstationConfigEffectiveLabels(d.Get("effective_labels"), d, config)
9921027
if err != nil {
9931028
return err
@@ -1072,6 +1107,10 @@ func resourceWorkstationsWorkstationConfigUpdate(d *schema.ResourceData, meta in
10721107
updateMask = append(updateMask, "disableTcpConnections")
10731108
}
10741109

1110+
if d.HasChange("allowed_ports") {
1111+
updateMask = append(updateMask, "allowedPorts")
1112+
}
1113+
10751114
if d.HasChange("effective_labels") {
10761115
updateMask = append(updateMask, "labels")
10771116
}
@@ -1837,6 +1876,59 @@ func flattenWorkstationsWorkstationConfigDisableTcpConnections(v interface{}, d
18371876
return v
18381877
}
18391878

1879+
func flattenWorkstationsWorkstationConfigAllowedPorts(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1880+
if v == nil {
1881+
return v
1882+
}
1883+
l := v.([]interface{})
1884+
transformed := make([]interface{}, 0, len(l))
1885+
for _, raw := range l {
1886+
original := raw.(map[string]interface{})
1887+
if len(original) < 1 {
1888+
// Do not include empty json objects coming back from the api
1889+
continue
1890+
}
1891+
transformed = append(transformed, map[string]interface{}{
1892+
"first": flattenWorkstationsWorkstationConfigAllowedPortsFirst(original["first"], d, config),
1893+
"last": flattenWorkstationsWorkstationConfigAllowedPortsLast(original["last"], d, config),
1894+
})
1895+
}
1896+
return transformed
1897+
}
1898+
func flattenWorkstationsWorkstationConfigAllowedPortsFirst(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1899+
// Handles the string fixed64 format
1900+
if strVal, ok := v.(string); ok {
1901+
if intVal, err := tpgresource.StringToFixed64(strVal); err == nil {
1902+
return intVal
1903+
}
1904+
}
1905+
1906+
// number values are represented as float64
1907+
if floatVal, ok := v.(float64); ok {
1908+
intVal := int(floatVal)
1909+
return intVal
1910+
}
1911+
1912+
return v // let terraform core handle it otherwise
1913+
}
1914+
1915+
func flattenWorkstationsWorkstationConfigAllowedPortsLast(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1916+
// Handles the string fixed64 format
1917+
if strVal, ok := v.(string); ok {
1918+
if intVal, err := tpgresource.StringToFixed64(strVal); err == nil {
1919+
return intVal
1920+
}
1921+
}
1922+
1923+
// number values are represented as float64
1924+
if floatVal, ok := v.(float64); ok {
1925+
intVal := int(floatVal)
1926+
return intVal
1927+
}
1928+
1929+
return v // let terraform core handle it otherwise
1930+
}
1931+
18401932
func flattenWorkstationsWorkstationConfigConditions(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
18411933
if v == nil {
18421934
return v
@@ -2673,6 +2765,43 @@ func expandWorkstationsWorkstationConfigDisableTcpConnections(v interface{}, d t
26732765
return v, nil
26742766
}
26752767

2768+
func expandWorkstationsWorkstationConfigAllowedPorts(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
2769+
l := v.([]interface{})
2770+
req := make([]interface{}, 0, len(l))
2771+
for _, raw := range l {
2772+
if raw == nil {
2773+
continue
2774+
}
2775+
original := raw.(map[string]interface{})
2776+
transformed := make(map[string]interface{})
2777+
2778+
transformedFirst, err := expandWorkstationsWorkstationConfigAllowedPortsFirst(original["first"], d, config)
2779+
if err != nil {
2780+
return nil, err
2781+
} else if val := reflect.ValueOf(transformedFirst); val.IsValid() && !tpgresource.IsEmptyValue(val) {
2782+
transformed["first"] = transformedFirst
2783+
}
2784+
2785+
transformedLast, err := expandWorkstationsWorkstationConfigAllowedPortsLast(original["last"], d, config)
2786+
if err != nil {
2787+
return nil, err
2788+
} else if val := reflect.ValueOf(transformedLast); val.IsValid() && !tpgresource.IsEmptyValue(val) {
2789+
transformed["last"] = transformedLast
2790+
}
2791+
2792+
req = append(req, transformed)
2793+
}
2794+
return req, nil
2795+
}
2796+
2797+
func expandWorkstationsWorkstationConfigAllowedPortsFirst(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
2798+
return v, nil
2799+
}
2800+
2801+
func expandWorkstationsWorkstationConfigAllowedPortsLast(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
2802+
return v, nil
2803+
}
2804+
26762805
func expandWorkstationsWorkstationConfigEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) {
26772806
if v == nil {
26782807
return map[string]string{}, nil

google-beta/services/workstations/resource_workstations_workstation_config_generated_test.go

+92
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,98 @@ resource "google_workstations_workstation_config" "default" {
742742
`, context)
743743
}
744744

745+
func TestAccWorkstationsWorkstationConfig_workstationConfigAllowedPortsExample(t *testing.T) {
746+
t.Parallel()
747+
748+
context := map[string]interface{}{
749+
"random_suffix": acctest.RandString(t, 10),
750+
}
751+
752+
acctest.VcrTest(t, resource.TestCase{
753+
PreCheck: func() { acctest.AccTestPreCheck(t) },
754+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t),
755+
CheckDestroy: testAccCheckWorkstationsWorkstationConfigDestroyProducer(t),
756+
Steps: []resource.TestStep{
757+
{
758+
Config: testAccWorkstationsWorkstationConfig_workstationConfigAllowedPortsExample(context),
759+
},
760+
{
761+
ResourceName: "google_workstations_workstation_config.default",
762+
ImportState: true,
763+
ImportStateVerify: true,
764+
ImportStateVerifyIgnore: []string{"annotations", "enable_audit_agent", "labels", "location", "terraform_labels", "workstation_cluster_id", "workstation_config_id"},
765+
},
766+
},
767+
})
768+
}
769+
770+
func testAccWorkstationsWorkstationConfig_workstationConfigAllowedPortsExample(context map[string]interface{}) string {
771+
return acctest.Nprintf(`
772+
resource "google_compute_network" "default" {
773+
provider = google-beta
774+
name = "tf-test-workstation-cluster%{random_suffix}"
775+
auto_create_subnetworks = false
776+
}
777+
778+
resource "google_compute_subnetwork" "default" {
779+
provider = google-beta
780+
name = "tf-test-workstation-cluster%{random_suffix}"
781+
ip_cidr_range = "10.0.0.0/24"
782+
region = "us-central1"
783+
network = google_compute_network.default.name
784+
}
785+
786+
resource "google_workstations_workstation_cluster" "default" {
787+
provider = google-beta
788+
workstation_cluster_id = "tf-test-workstation-cluster%{random_suffix}"
789+
network = google_compute_network.default.id
790+
subnetwork = google_compute_subnetwork.default.id
791+
location = "us-central1"
792+
793+
labels = {
794+
"label" = "key"
795+
}
796+
797+
annotations = {
798+
label-one = "value-one"
799+
}
800+
}
801+
802+
resource "google_workstations_workstation_config" "default" {
803+
provider = google-beta
804+
workstation_config_id = "tf-test-workstation-config%{random_suffix}"
805+
workstation_cluster_id = google_workstations_workstation_cluster.default.workstation_cluster_id
806+
location = "us-central1"
807+
808+
host {
809+
gce_instance {
810+
machine_type = "e2-standard-4"
811+
boot_disk_size_gb = 35
812+
disable_public_ip_addresses = true
813+
}
814+
}
815+
816+
# Allow only port 80 (HTTP)
817+
allowed_ports {
818+
first = 80
819+
last = 80
820+
}
821+
822+
# Allow only port 22 (SSH)
823+
allowed_ports {
824+
first = 22
825+
last = 22
826+
}
827+
828+
# Allow port range 1024-65535
829+
allowed_ports {
830+
first = 1024
831+
last = 65535
832+
}
833+
}
834+
`, context)
835+
}
836+
745837
func testAccCheckWorkstationsWorkstationConfigDestroyProducer(t *testing.T) func(s *terraform.State) error {
746838
return func(s *terraform.State) error {
747839
for name, rs := range s.RootModule().Resources {

0 commit comments

Comments
 (0)