diff --git a/lib/apiservers/service/restapi/handlers/vch_create.go b/lib/apiservers/service/restapi/handlers/vch_create.go index 5eaf2a10c6..362f1973dc 100644 --- a/lib/apiservers/service/restapi/handlers/vch_create.go +++ b/lib/apiservers/service/restapi/handlers/vch_create.go @@ -233,7 +233,7 @@ func buildCreate(op trace.Operation, d *data.Data, finder *find.Finder, vch *mod } c.ClientNetworkName = path c.ClientNetworkGateway = fromGateway(vch.Network.Client.Gateway) - c.ClientNetworkIP = fromNetworkAddress(vch.Network.Client.Static) + c.ClientNetworkIP = fromCIDR(&vch.Network.Client.Static) if err := c.ProcessNetwork(&c.Data.ClientNetwork, "client", c.ClientNetworkName, c.ClientNetworkIP, c.ClientNetworkGateway); err != nil { return nil, util.WrapError(http.StatusBadRequest, err) @@ -250,7 +250,7 @@ func buildCreate(op trace.Operation, d *data.Data, finder *find.Finder, vch *mod } c.ManagementNetworkName = path c.ManagementNetworkGateway = fromGateway(vch.Network.Management.Gateway) - c.ManagementNetworkIP = fromNetworkAddress(vch.Network.Management.Static) + c.ManagementNetworkIP = fromCIDR(&vch.Network.Management.Static) if err := c.ProcessNetwork(&c.Data.ManagementNetwork, "management", c.ManagementNetworkName, c.ManagementNetworkIP, c.ManagementNetworkGateway); err != nil { return nil, util.WrapError(http.StatusBadRequest, err) @@ -267,7 +267,7 @@ func buildCreate(op trace.Operation, d *data.Data, finder *find.Finder, vch *mod } c.PublicNetworkName = path c.PublicNetworkGateway = fromGateway(vch.Network.Public.Gateway) - c.PublicNetworkIP = fromNetworkAddress(vch.Network.Public.Static) + c.PublicNetworkIP = fromCIDR(&vch.Network.Public.Static) if err := c.ProcessNetwork(&c.Data.PublicNetwork, "public", c.PublicNetworkName, c.PublicNetworkIP, c.PublicNetworkGateway); err != nil { return nil, util.WrapError(http.StatusBadRequest, err) @@ -295,6 +295,9 @@ func buildCreate(op trace.Operation, d *data.Data, finder *find.Finder, vch *mod containerNetworks.MappedNetworks[alias] = path address := net.ParseIP(string(cnetwork.Gateway.Address)) + if cnetwork.Gateway.RoutingDestinations == nil || len(cnetwork.Gateway.RoutingDestinations) != 1 { + return nil, util.NewError(http.StatusBadRequest, fmt.Sprintf("Error parsing network mask for container network %s: exactly one subnet must be specified", alias)) + } _, mask, err := net.ParseCIDR(string(cnetwork.Gateway.RoutingDestinations[0].CIDR)) if err != nil { return nil, util.NewError(http.StatusBadRequest, fmt.Sprintf("Error parsing network mask for container network %s: %s", alias, err)) @@ -477,18 +480,6 @@ func fromIPRanges(m *[]models.IPRange) *[]string { return &s } -func fromNetworkAddress(m *models.NetworkAddress) string { - if m == nil { - return "" - } - - if m.IP != "" { - return string(m.IP) - } - - return string(m.Hostname) -} - func fromManagedObject(op trace.Operation, finder *find.Finder, t string, m *models.ManagedObject) (string, error) { if m == nil { return "", nil @@ -521,7 +512,13 @@ func fromGateway(m *models.Gateway) string { return "" } - return fmt.Sprintf("%s:%s", // TODO (#6715): what if RoutingDestinations is empty? + if m.RoutingDestinations == nil { + return fmt.Sprintf("%s", + m.Address, + ) + } + + return fmt.Sprintf("%s:%s", strings.Join(*fromIPRanges(&m.RoutingDestinations), ","), m.Address, ) diff --git a/lib/apiservers/service/swagger.json b/lib/apiservers/service/swagger.json index 600754c0f0..aafce5e98d 100644 --- a/lib/apiservers/service/swagger.json +++ b/lib/apiservers/service/swagger.json @@ -552,19 +552,6 @@ "description": "TODO: see if this can just be a string with a format that captures IPv4 and IPv6?", "format": "ipv4" }, - "Network_Address": { - "type": "object", - "description": "TODO: see if this can just be a string with a format that captures IPv4, IPv6, and FQDNs?", - "minProperties": 1, - "maxProperties": 1, - "properties": { - "ip": { "$ref": "#/definitions/IP_Address" }, - "hostname": { - "type": "string", - "format": "hostname" - } - } - }, "Gateway": { "type": "object", "properties": { @@ -584,7 +571,7 @@ "type": "array", "items": { "$ref": "#/definitions/IP_Address" } }, - "static": { "$ref": "#/definitions/Network_Address" } + "static": { "$ref": "#/definitions/CIDR" } } }, "Container_Network" : { diff --git a/tests/test-cases/Group23-VIC-Machine-Service/23-03-VCH-Create.robot b/tests/test-cases/Group23-VIC-Machine-Service/23-03-VCH-Create.robot index 6f2a5293c0..31aeb487b3 100644 --- a/tests/test-cases/Group23-VIC-Machine-Service/23-03-VCH-Create.robot +++ b/tests/test-cases/Group23-VIC-Machine-Service/23-03-VCH-Create.robot @@ -240,3 +240,12 @@ Fail to create VCH without network Verify Status Bad Request Output Should Contain network + + +Fail to create VCH with gateway without static address + Create VCH '{"name":"%{VCH-NAME}-api-bad-gateway","compute":{"resource":{"name":"%{TEST_RESOURCE}"}},"storage":{"image_stores":["ds://%{TEST_DATASTORE}"]},"network":{"bridge":{"ip_range":"172.16.0.0/12","port_group":{"name":"%{BRIDGE_NETWORK}"}},"public":{"port_group":{"name":"${PUBLIC_NETWORK}"},"gateway":{"address":"127.0.0.1","routing_destinations":[]}}},"auth":{"server":{"generate":{"cname":"vch.example.com","organization":["VMware, Inc."],"size":{"value":2048,"units":"bits"}}},"client":{"no_tls_verify": true}}}' + + Verify Return Code + Verify Status Bad Request + + Output Should Contain static