diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d205540..655ccba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go-version: [1.15,1.16] + go-version: [1.16,1.17] steps: - name: Set up Go ${{ matrix.go-version }} uses: actions/setup-go@v1 diff --git a/client.go b/client.go index 2082f1b..a106632 100644 --- a/client.go +++ b/client.go @@ -53,6 +53,9 @@ type Client struct { Snapshot SnapshotClient AvailabilityZone AvailabilityZoneClient VMRecoveryPoint VMRecoveryPointClient + VPC VpcClient + FlotatingIP FloatingIPClient + RoutingPolicy RoutingPolicyClient } // Credentials needed username and password @@ -145,6 +148,9 @@ func NewClient(options ...ClientOption) *Client { client.Snapshot = SnapshotClient{client: client} client.AvailabilityZone = AvailabilityZoneClient{client: client} client.VMRecoveryPoint = VMRecoveryPointClient{client: client} + client.VPC = VpcClient{client: client} + client.FlotatingIP = FloatingIPClient{client: client} + client.RoutingPolicy = RoutingPolicyClient{client: client} return client } diff --git a/floating_ip.go b/floating_ip.go new file mode 100644 index 0000000..aaad983 --- /dev/null +++ b/floating_ip.go @@ -0,0 +1,82 @@ +package nutanix + +import ( + "context" + "fmt" + "net/http" + + "github.com/tecbiz-ch/nutanix-go-sdk/pkg/utils" + "github.com/tecbiz-ch/nutanix-go-sdk/schema" +) + +const ( + floatingIPBasePath = "/floating_ips" + floatingIPListPath = floatingIPBasePath + "/list" + floatingIPSinglePath = floatingIPBasePath + "/%s" +) + +// FloatingIPClient is a client for the vpc API. +type FloatingIPClient struct { + client *Client +} + +// Get retrieves an FlotatingIp by its UUID if the input can be parsed as an uuid, otherwise it +// retrieves a FlotatingIp by its name +func (c *FloatingIPClient) Get(ctx context.Context, idOrName string) (*schema.FloatingIPIntent, error) { + if utils.IsValidUUID(idOrName) { + return c.GetByUUID(ctx, idOrName) + } + return c.GetByName(ctx, idOrName) +} + +// GetByUUID retrieves an FlotatingIp by its UUID +func (c *FloatingIPClient) GetByUUID(ctx context.Context, uuid string) (*schema.FloatingIPIntent, error) { + response := new(schema.FloatingIPIntent) + err := c.client.requestHelper(ctx, fmt.Sprintf(floatingIPSinglePath, uuid), http.MethodGet, nil, response) + return response, err +} + +// GetByName retrieves an FlotatingIp by its name +func (c *FloatingIPClient) GetByName(ctx context.Context, name string) (*schema.FloatingIPIntent, error) { + list, err := c.List(ctx, &schema.DSMetadata{Filter: fmt.Sprintf("floating_ip==%s", name)}) + if err != nil { + return nil, err + } + if len(list.Entities) == 0 { + return nil, fmt.Errorf("floating_ip not found: %s", name) + } + return list.Entities[0], err +} + +// List returns a list of FlotatingIp's +func (c *FloatingIPClient) List(ctx context.Context, opts *schema.DSMetadata) (*schema.FloatingIPListIntent, error) { + response := new(schema.FloatingIPListIntent) + err := c.client.requestHelper(ctx, floatingIPListPath, http.MethodPost, opts, response) + return response, err + +} + +// All returns all FlotatingIp's +func (c *FloatingIPClient) All(ctx context.Context) (*schema.FloatingIPListIntent, error) { + return c.List(ctx, &schema.DSMetadata{Length: utils.Int64Ptr(itemsPerPage), Offset: utils.Int64Ptr(0)}) +} + +// Create creates a FlotatingIp +func (c *FloatingIPClient) Create(ctx context.Context, createRequest *schema.FloatingIPIntent) (*schema.FloatingIPIntent, error) { + response := new(schema.FloatingIPIntent) + err := c.client.requestHelper(ctx, floatingIPBasePath, http.MethodPost, createRequest, response) + return response, err +} + +// Update a FlotatingIp +func (c *FloatingIPClient) Update(ctx context.Context, fip *schema.FloatingIPIntent) (*schema.FloatingIPIntent, error) { + fip.Status = nil + response := new(schema.FloatingIPIntent) + err := c.client.requestHelper(ctx, fmt.Sprintf(floatingIPSinglePath, fip.Metadata.UUID), http.MethodPut, fip, response) + return response, err +} + +// Delete deletes a FlotatingIp +func (c *FloatingIPClient) Delete(ctx context.Context, uuid string) error { + return c.client.requestHelper(ctx, fmt.Sprintf(floatingIPSinglePath, uuid), http.MethodDelete, nil, nil) +} diff --git a/routing_policy.go b/routing_policy.go new file mode 100644 index 0000000..fdd936a --- /dev/null +++ b/routing_policy.go @@ -0,0 +1,61 @@ +package nutanix + +import ( + "context" + "fmt" + "net/http" + + "github.com/tecbiz-ch/nutanix-go-sdk/pkg/utils" + "github.com/tecbiz-ch/nutanix-go-sdk/schema" +) + +const ( + routingPolicyBasePath = "/routing_policies" + routingPolicyListPath = routingPolicyBasePath + "/list" + routingPolicySinglePath = routingPolicyBasePath + "/%s" +) + +// RoutingPolicyClient is a client for the vpc API. +type RoutingPolicyClient struct { + client *Client +} + +// GetByUUID retrieves an FlotatingIp by its UUID +func (c *RoutingPolicyClient) GetByUUID(ctx context.Context, uuid string) (*schema.RoutingPolicyIntent, error) { + response := new(schema.RoutingPolicyIntent) + err := c.client.requestHelper(ctx, fmt.Sprintf(routingPolicySinglePath, uuid), http.MethodGet, nil, response) + return response, err +} + +// List returns a list of FlotatingIp's +func (c *RoutingPolicyClient) List(ctx context.Context, opts *schema.DSMetadata) (*schema.RoutingPolicyListIntent, error) { + response := new(schema.RoutingPolicyListIntent) + err := c.client.requestHelper(ctx, routingPolicyListPath, http.MethodPost, opts, response) + return response, err + +} + +// All returns all FlotatingIp's +func (c *RoutingPolicyClient) All(ctx context.Context) (*schema.RoutingPolicyListIntent, error) { + return c.List(ctx, &schema.DSMetadata{Length: utils.Int64Ptr(itemsPerPage), Offset: utils.Int64Ptr(0)}) +} + +// Create creates a FlotatingIp +func (c *RoutingPolicyClient) Create(ctx context.Context, createRequest *schema.RoutingPolicyIntent) (*schema.RoutingPolicyIntent, error) { + response := new(schema.RoutingPolicyIntent) + err := c.client.requestHelper(ctx, routingPolicyBasePath, http.MethodPost, createRequest, response) + return response, err +} + +// Update a FlotatingIp +func (c *RoutingPolicyClient) Update(ctx context.Context, r *schema.RoutingPolicyIntent) (*schema.RoutingPolicyIntent, error) { + r.Status = nil + response := new(schema.RoutingPolicyIntent) + err := c.client.requestHelper(ctx, fmt.Sprintf(routingPolicySinglePath, r.Metadata.UUID), http.MethodPut, r, response) + return response, err +} + +// Delete deletes a FlotatingIp +func (c *RoutingPolicyClient) Delete(ctx context.Context, uuid string) error { + return c.client.requestHelper(ctx, fmt.Sprintf(routingPolicySinglePath, uuid), http.MethodDelete, nil, nil) +} diff --git a/schema/floating_ip.go b/schema/floating_ip.go new file mode 100644 index 0000000..c465a69 --- /dev/null +++ b/schema/floating_ip.go @@ -0,0 +1,110 @@ +package schema + +type FloatingIP struct { + + // availability zone reference + AvailabilityZoneReference *Reference `json:"availability_zone_reference,omitempty"` + + // A description for floating_ip. + // Max Length: 1000 + Description string `json:"description,omitempty"` + + // floating_ip Name. + // Max Length: 256 + Name string `json:"name,omitempty"` + + // resources + // Required: true + Resources *FloatingIPResources `json:"resources"` +} + +// FloatingIPResourcesDefStatus Floating IP allocation status +// +// Floating IP allocation status. +// +// swagger:model floating_ip_resources_def_status +type FloatingIPResources struct { + + // External subnet from which floating IP is selected. + ExternalSubnetReference *Reference `json:"external_subnet_reference,omitempty"` + + // The Floating IP associated with the vnic. + // Pattern: ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ + FloatingIP string `json:"floating_ip,omitempty"` + + // Private IP with which the floating IP is associated. + // Pattern: ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ + PrivateIP string `json:"private_ip,omitempty"` + + // NIC with which the floating IP is associated. + VMNicReference *Reference `json:"vm_nic_reference,omitempty"` + + // VPC in which the private IP exists. + VpcReference *Reference `json:"vpc_reference,omitempty"` +} + +type FloatingIPIntent struct { + + // api version + APIVersion string `json:"api_version,omitempty"` + + // metadata + // Required: true + Metadata *Metadata `json:"metadata"` + + // spec + Spec *FloatingIP `json:"spec,omitempty"` + + // status + Status *FloatingIPDefStatus `json:"status,omitempty"` +} + +// FloatingIPDefStatus floating_ip Intent Status with placement specified +// +// An intentful representation of a floating_ip status +// +// swagger:model floating_ip_def_status +type FloatingIPDefStatus struct { + + // availability zone reference + AvailabilityZoneReference *Reference `json:"availability_zone_reference,omitempty"` + + // cluster reference + ClusterReference *Reference `json:"cluster_reference,omitempty"` + + // A description for floating_ip. + Description string `json:"description,omitempty"` + + // Any error messages for the floating_ip, if in an error state. + MessageList []*MessageResource `json:"message_list"` + + // floating_ip Name. + // Required: true + Name *string `json:"name"` + + // resources + // Required: true + Resources *FloatingIPResources `json:"resources"` + + // The state of the floating_ip. + State string `json:"state,omitempty"` +} + +// FloatingIPListIntentResponse Entity Intent List Response +// +// Response object for intentful operation of floating_ips +// +// swagger:model floating_ip_list_intent_response +type FloatingIPListIntent struct { + + // api version + // Required: true + APIVersion string `json:"api_version,omitempty"` + + // entities + Entities []*FloatingIPIntent `json:"entities"` + + // metadata + // Required: true + Metadata *ListMetadata `json:"metadata"` +} diff --git a/schema/routing_policy.go b/schema/routing_policy.go new file mode 100644 index 0000000..848c51c --- /dev/null +++ b/schema/routing_policy.go @@ -0,0 +1,322 @@ +package schema + +type RoutingPolicy struct { + + // availability zone reference + AvailabilityZoneReference *Reference `json:"availability_zone_reference,omitempty"` + + // A description for routing_policy. + // Max Length: 1000 + Description string `json:"description,omitempty"` + + // routing_policy Name. + // Required: true + // Max Length: 256 + Name string `json:"name"` + + // resources + // Required: true + Resources *RoutingPolicyResources `json:"resources"` +} + +// Routing Policy creation/modification spec. The routing policy matches incoming traffic on the router based on the following fields: 'source', 'destination', 'protocol_type', 'protocol_parameters'. Once traffic matches the parameters defined in the policy 'action' field defines the action that needs to be performed on the traffic. 'action' could be permit/deny/reroute. +// +// swagger:model routing_policy_resources +type RoutingPolicyResources struct { + + // The IP protocol type of traffic that is entering the router. + // + // Required: true + Action *RoutingPolicyAction `json:"action"` + + // Destination of traffic that is entering the router. + // + // Required: true + Destination *NetworkAddress `json:"destination"` + + // Whether to configure/install policy in reverse direction too (i.e matching traffic from destination to source) + // + IsBidirectional bool `json:"is_bidirectional,omitempty"` + + // priority + // Required: true + // Maximum: 1000 + // Minimum: 1 + Priority int16 `json:"priority"` + + // The IP protocol type of traffic that is entering the router. + // + ProtocolParameters *ProtocolParameters `json:"protocol_parameters,omitempty"` + + // protocol type + // Required: true + ProtocolType string `json:"protocol_type"` + + // Source of traffic that is entering the router. + // + // Required: true + Source *NetworkAddress `json:"source"` + + // The virtual network this routing policy belongs to. This reference is deprecated, use vpc_reference instead. + // + VirtualNetworkReference *Reference `json:"virtual_network_reference,omitempty"` + + // The VPC this routing policy belongs to. + // + VpcReference *Reference `json:"vpc_reference,omitempty"` +} + +// NetworkAddress Network address +// +// Address (source/destination) of an IP packet. > This could be either an ip prefix or a special category like "INTERNET". +// +// swagger:model network_address +type NetworkAddress struct { + + // address type + AddressType string `json:"address_type,omitempty"` + + // ip subnet + IPSubnet *IPSubnet `json:"ip_subnet,omitempty"` +} + +// RoutingPolicyAction Action +// +// Routing policy action +// +// swagger:model routing_policy_action +type RoutingPolicyAction struct { + + // action + // Required: true + Action string `json:"action"` + + // IP addresses of network services in the chain.> This field is valid only when action is REROUTE. + ServiceIPList []string `json:"service_ip_list,omitempty"` +} + +// ProtocolParameters IP protocol +// +// Routing policy IP protocol parameters +// +// swagger:model protocol_parameters +type ProtocolParameters struct { + + // ICMP parameters to be matched + Icmp *Icmp `json:"icmp,omitempty"` + + // protocol number + // Maximum: 255 + // Minimum: 0 + ProtocolNumber *uint8 `json:"protocol_number,omitempty"` + + // TCP parameters to be matched + TCP *TCP `json:"tcp,omitempty"` + + // UDP parameters to be matched + UDP *UDP `json:"udp,omitempty"` +} + +// Icmp ICMP parameters +// +// ICMP parameters to be matched in routing policy. +// +// swagger:model icmp +type Icmp struct { + + // icmp code + // Maximum: 255 + // Minimum: 0 + IcmpCode *uint8 `json:"icmp_code,omitempty"` + + // icmp type + // Maximum: 255 + // Minimum: 0 + IcmpType *uint8 `json:"icmp_type,omitempty"` +} + +// UDP UDP parameters +// +// UDP parameters to be matched in routing policy +// +// swagger:model udp +type UDP struct { + + // Range of UDP destination ports. This field is deprecated, use destination_port_range_list instead. + // + DestinationPortRange *PortRange `json:"destination_port_range,omitempty"` + + // List of ranges of UDP destination ports. + DestinationPortRangeList []*PortRange `json:"destination_port_range_list"` + + // Range of UDP source ports. This field is deprecated, use source_port_range_list instead. + // + SourcePortRange *PortRange `json:"source_port_range,omitempty"` + + // List of ranges of UDP source ports. + SourcePortRangeList []*PortRange `json:"source_port_range_list"` +} + +// TCP TCP parameters +// +// TCP parameters to be matched in routing policy. +// +// swagger:model tcp +type TCP struct { + + // Range of TCP destination ports. This field is deprecated, use destination_port_range_list instead. + // + DestinationPortRange *PortRange `json:"destination_port_range,omitempty"` + + // List of ranges of TCP destination ports. + DestinationPortRangeList []*PortRange `json:"destination_port_range_list"` + + // Range of TCP source ports. This field is deprecated, use source_port_range_list instead. + // + SourcePortRange *PortRange `json:"source_port_range,omitempty"` + + // List of ranges of TCP source ports. + SourcePortRangeList []*PortRange `json:"source_port_range_list"` +} + +type RoutingPolicyIntent struct { + + // api version + // Required: true + APIVersion string `json:"api_version"` + + Metadata *Metadata `json:"metadata,omitempty"` + + // spec + Spec *RoutingPolicy `json:"spec,omitempty"` + + // status + Status *RoutingPolicyDefStatus `json:"status,omitempty"` +} + +type RoutingPolicyDefStatus struct { + + // availability zone reference + AvailabilityZoneReference *Reference `json:"availability_zone_reference,omitempty"` + + // cluster reference + ClusterReference *Reference `json:"cluster_reference,omitempty"` + + // A description for routing_policy. + Description string `json:"description,omitempty"` + + // Any error messages for the routing_policy, if in an error state. + MessageList []*MessageResource `json:"message_list"` + + // routing_policy Name. + // Required: true + Name *string `json:"name"` + + // resources + // Required: true + Resources *RoutingPolicyResourcesDefStatus `json:"resources"` + + // The state of the routing_policy. + State string `json:"state,omitempty"` +} + +type RoutingPolicyResourcesDefStatus struct { + + // The action to be taken on traffic entering the router. + // + Action *RoutingPolicyAction `json:"action,omitempty"` + + // The destination IP address of traffic that is entering the router. + // + Destination *NetworkAddress `json:"destination,omitempty"` + + // Error message describing why the routing policy is inactive. + // + ErrorMessage string `json:"error_message,omitempty"` + + // Whether to configure/install policy in reverse direction too (i.e matching traffic from destination to source) + // + IsBidirectional bool `json:"is_bidirectional,omitempty"` + + // priority + Priority int16 `json:"priority,omitempty"` + + // IP protocol parameters of traffic entering the router. + // + ProtocolParameters *ProtocolParameters `json:"protocol_parameters,omitempty"` + + // The IP protocol type of traffic that is entering the router. + // + ProtocolType string `json:"protocol_type,omitempty"` + + // Number of packets matching the routing policy. + RoutingPolicyCounters *RoutingPolicyCounters `json:"routing_policy_counters,omitempty"` + + // Number of packets matching the reverse direction routing policy. Applicable only if is_bidirectional is true. + // + RoutingPolicyCountersReverseDirection *RoutingPolicyCounters `json:"routing_policy_counters_reverse_direction,omitempty"` + + // Policy counters for each service IP. + ServiceIPCounters []*ServiceIPCounters `json:"service_ip_counters"` + + // Policy counters for each service IP for reverse direction reroute routing policy. Applicable only if is_bidirectional is true. + // + ServiceIPCountersReverseDirection []*ServiceIPCounters `json:"service_ip_counters_reverse_direction"` + + // The source IP address of traffic that is entering the router. + // + Source *NetworkAddress `json:"source,omitempty"` + // The virtual network this routing policy belongs to. This reference is deprecated, use vpc_reference instead. + // + VirtualNetworkReference *Reference `json:"virtual_network_reference,omitempty"` + + // The VPC this routing policy belongs to. + // + VpcReference *Reference `json:"vpc_reference,omitempty"` +} + +// RoutingPolicyCounters Policy counters +// +// Number of packets and bytes hitting the rule. +// +// swagger:model routing_policy_counters +type RoutingPolicyCounters struct { + + // byte count + ByteCount uint64 `json:"byte_count,omitempty"` + + // packet count + PacketCount uint64 `json:"packet_count,omitempty"` +} + +// ServiceIPCounters Service IP counters +// +// Number of packets and bytes hitting the service IP. +// +// swagger:model service_ip_counters +type ServiceIPCounters struct { + + // received + Received *RoutingPolicyCounters `json:"received,omitempty"` + + // sent + Sent *RoutingPolicyCounters `json:"sent,omitempty"` + + // service ip + // Pattern: ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ + ServiceIP string `json:"service_ip,omitempty"` +} + +type RoutingPolicyListIntent struct { + + // api version + // Required: true + APIVersion string `json:"api_version"` + + // entities + Entities []*RoutingPolicyIntent `json:"entities"` + + // metadata + // Required: true + Metadata *ListMetadata `json:"metadata"` +} diff --git a/schema/structs.go b/schema/structs.go index c2935ba..b318d4b 100644 --- a/schema/structs.go +++ b/schema/structs.go @@ -558,18 +558,18 @@ type VMIntentResource struct { // PortRange represents Range of TCP/UDP ports. type PortRange struct { - EndPort *int64 `json:"end_port,omitempty"` + EndPort int64 `json:"end_port,omitempty"` - StartPort *int64 `json:"start_port,omitempty"` + StartPort int64 `json:"start_port,omitempty"` } // IPSubnet IP subnet provided as an address and prefix length. type IPSubnet struct { // IPV4 address. - IP *string `json:"ip,omitempty"` + IP string `json:"ip,omitempty"` - PrefixLength *int64 `json:"prefix_length,omitempty"` + PrefixLength int64 `json:"prefix_length,omitempty"` } // NetworkRuleIcmpTypeCodeList .. diff --git a/schema/subnet.go b/schema/subnet.go index db22e4b..79f0fcb 100644 --- a/schema/subnet.go +++ b/schema/subnet.go @@ -8,6 +8,8 @@ type SubnetResources struct { SubnetType string `json:"subnet_type,omitempty"` + VPCReference *Reference `json:"vpc_reference,omitempty"` + VlanID *int64 `json:"vlan_id,omitempty"` VswitchName string `json:"vswitch_name,omitempty"` diff --git a/schema/vpc.go b/schema/vpc.go new file mode 100644 index 0000000..efbcfd4 --- /dev/null +++ b/schema/vpc.go @@ -0,0 +1,141 @@ +package schema + +type Vpc struct { + + // description + // Max Length: 1000 + Description string `json:"description,omitempty"` + + // name + // Required: true + // Max Length: 64 + Name string `json:"name"` + + // resources + Resources *VpcResources `json:"resources,omitempty"` +} + +type VpcResources struct { + + // List of availability zones in Xi from which resources are derived (Only supported on Xi) + // + AvailabilityZoneReferenceList []*Reference `json:"availability_zone_reference_list,omitempty"` + + // List of domain name server IPs. + CommonDomainNameServerIPList []*Address `json:"common_domain_name_server_ip_list,omitempty"` + + // List of external subnets attached to this VPC. + ExternalSubnetList []*ExternalSubnet `json:"external_subnet_list,omitempty"` + + // CIDR blocks from the VPC which can talk externally without performing NAT. These blocks should be between /16 netmask and /28 netmask and cannot overlap across VPCs. They are effective when the VPC connects to a NAT-less external subnet. + // + ExternallyRoutablePrefixList []*IPSubnet `json:"externally_routable_prefix_list,omitempty"` +} + +type Node struct { + + // host reference + // Required: true + HostReference *Reference `json:"host_reference"` + + // Node IP Address + // Pattern: ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ + IPAddress string `json:"ip_address,omitempty"` +} + +// ExternalSubnetDefStatus External subnet status. +// +// External subnet status. +// +// swagger:model external_subnet_def_status +type ExternalSubnet struct { + + // Active gateway node for the external connectivity. + ActiveGatewayNode *Node `json:"active_gateway_node,omitempty"` + + // List of IP addresses for the VPC router port connecting to the external network. + // + ExternalIPList []string `json:"external_ip_list,omitempty"` + + // External subnet reference. + ExternalSubnetReference *Reference `json:"external_subnet_reference,omitempty"` + + // List of gateway nodes for the external connectivity. + GatewayNodeUUIDList []string `json:"gateway_node_uuid_list,omitempty"` +} + +// swagger:model vpc_list_intent_response +type VpcListIntent struct { + + // api version + // Required: true + APIVersion string `json:"api_version,omitempty"` + + // entities + Entities []*VpcIntent `json:"entities"` + + // metadata + // Required: true + Metadata *ListMetadata `json:"metadata"` +} + +// swagger:model vpc_intent_resource +type VpcIntent struct { + + // api version + APIVersion string `json:"api_version,omitempty"` + + // metadata + // Required: true + Metadata *Metadata `json:"metadata,omitempty"` + + // spec + Spec *Vpc `json:"spec,omitempty"` + + // status + Status *VpcDefStatus `json:"status,omitempty"` +} + +type VpcDefStatus struct { + + // description + Description string `json:"description,omitempty"` + + // Any error messages for the VPC, if in an error state. + // + MessageList []*MessageResource `json:"message_list"` + + // name + Name string `json:"name,omitempty"` + + // resources + Resources *VpcResourcesDefStatus `json:"resources,omitempty"` + + // The state of the VPC. + State string `json:"state,omitempty"` +} + +// VpcResourcesDefStatus VPC resources status +// +// VPC resources status +// +// swagger:model vpc_resources_def_status +type VpcResourcesDefStatus struct { + + // List of availability zones in Xi from which resources are derived (Only supported on Xi) + // + AvailabilityZoneReferenceList []*Reference `json:"availability_zone_reference_list"` + + // List of domain name server IPs. + CommonDomainNameServerIPList []*Address `json:"common_domain_name_server_ip_list"` + + // List of external subnets attached to this VPC. + ExternalSubnetList []*ExternalSubnet `json:"external_subnet_list"` + + // CIDR blocks from the VPC which can talk externally without performing NAT. These blocks should be between /16 netmask and /28 netmask and cannot overlap across VPCs. They are effective when the VPC connects to a NAT-less external subnet. + // + ExternallyRoutablePrefixList []*IPSubnet `json:"externally_routable_prefix_list"` + + // List of IP addresses used for SNAT. + NatIPList []string `json:"nat_ip_list"` +} diff --git a/vpc.go b/vpc.go new file mode 100644 index 0000000..8071907 --- /dev/null +++ b/vpc.go @@ -0,0 +1,82 @@ +package nutanix + +import ( + "context" + "fmt" + "net/http" + + "github.com/tecbiz-ch/nutanix-go-sdk/pkg/utils" + "github.com/tecbiz-ch/nutanix-go-sdk/schema" +) + +const ( + vpcBasePath = "/vpcs" + vpcListPath = vpcBasePath + "/list" + vpcSinglePath = vpcBasePath + "/%s" +) + +// VpcClient is a client for the vpc API. +type VpcClient struct { + client *Client +} + +// Get retrieves an vpc by its UUID if the input can be parsed as an uuid, otherwise it +// retrieves a vpc by its name +func (c *VpcClient) Get(ctx context.Context, idOrName string) (*schema.VpcIntent, error) { + if utils.IsValidUUID(idOrName) { + return c.GetByUUID(ctx, idOrName) + } + return c.GetByName(ctx, idOrName) +} + +// GetByUUID retrieves an vpc by its UUID +func (c *VpcClient) GetByUUID(ctx context.Context, uuid string) (*schema.VpcIntent, error) { + response := new(schema.VpcIntent) + err := c.client.requestHelper(ctx, fmt.Sprintf(vpcSinglePath, uuid), http.MethodGet, nil, response) + return response, err +} + +// GetByName retrieves an vpc by its name +func (c *VpcClient) GetByName(ctx context.Context, name string) (*schema.VpcIntent, error) { + list, err := c.List(ctx, &schema.DSMetadata{Filter: fmt.Sprintf("name==%s", name)}) + if err != nil { + return nil, err + } + if len(list.Entities) == 0 { + return nil, fmt.Errorf("vpc not found: %s", name) + } + return list.Entities[0], err +} + +// List returns a list of vpc's +func (c *VpcClient) List(ctx context.Context, opts *schema.DSMetadata) (*schema.VpcListIntent, error) { + response := new(schema.VpcListIntent) + err := c.client.requestHelper(ctx, vpcListPath, http.MethodPost, opts, response) + return response, err + +} + +// All returns all vpc's +func (c *VpcClient) All(ctx context.Context) (*schema.VpcListIntent, error) { + return c.List(ctx, &schema.DSMetadata{Length: utils.Int64Ptr(itemsPerPage), Offset: utils.Int64Ptr(0)}) +} + +// Create creates a vpc +func (c *VpcClient) Create(ctx context.Context, createRequest *schema.VpcIntent) (*schema.VpcIntent, error) { + response := new(schema.VpcIntent) + err := c.client.requestHelper(ctx, vpcBasePath, http.MethodPost, createRequest, response) + return response, err +} + +// Update a vpc +func (c *VpcClient) Update(ctx context.Context, vpc *schema.VpcIntent) (*schema.VpcIntent, error) { + vpc.Status = nil + response := new(schema.VpcIntent) + err := c.client.requestHelper(ctx, fmt.Sprintf(vpcSinglePath, vpc.Metadata.UUID), http.MethodPut, vpc, response) + return response, err +} + +// Delete deletes a vpc +func (c *VpcClient) Delete(ctx context.Context, uuid string) error { + return c.client.requestHelper(ctx, fmt.Sprintf(vpcSinglePath, uuid), http.MethodDelete, nil, nil) +}