// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package google.cloud.networkconnectivity.v1;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/cloud/networkconnectivity/v1/common.proto";
import "google/longrunning/operations.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";

option csharp_namespace = "Google.Cloud.NetworkConnectivity.V1";
option go_package = "cloud.google.com/go/networkconnectivity/apiv1/networkconnectivitypb;networkconnectivitypb";
option java_multiple_files = true;
option java_outer_classname = "InternalRangeProto";
option java_package = "com.google.cloud.networkconnectivity.v1";
option php_namespace = "Google\\Cloud\\NetworkConnectivity\\V1";
option ruby_package = "Google::Cloud::NetworkConnectivity::V1";

// The CLH-based service for internal range resources used to perform IPAM
// operations within a VPC network.
service InternalRangeService {
  option (google.api.default_host) = "networkconnectivity.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/cloud-platform";

  // Lists internal ranges in a given project and location.
  rpc ListInternalRanges(ListInternalRangesRequest)
      returns (ListInternalRangesResponse) {
    option (google.api.http) = {
      get: "/v1/{parent=projects/*/locations/*}/internalRanges"
    };
    option (google.api.method_signature) = "parent";
  }

  // Gets details of a single internal range.
  rpc GetInternalRange(GetInternalRangeRequest) returns (InternalRange) {
    option (google.api.http) = {
      get: "/v1/{name=projects/*/locations/*/internalRanges/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Creates a new internal range in a given project and location.
  rpc CreateInternalRange(CreateInternalRangeRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1/{parent=projects/*/locations/*}/internalRanges"
      body: "internal_range"
    };
    option (google.api.method_signature) =
        "parent,internal_range,internal_range_id";
    option (google.longrunning.operation_info) = {
      response_type: "InternalRange"
      metadata_type: "OperationMetadata"
    };
  }

  // Updates the parameters of a single internal range.
  rpc UpdateInternalRange(UpdateInternalRangeRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      patch: "/v1/{internal_range.name=projects/*/locations/*/internalRanges/*}"
      body: "internal_range"
    };
    option (google.api.method_signature) = "internal_range,update_mask";
    option (google.longrunning.operation_info) = {
      response_type: "InternalRange"
      metadata_type: "OperationMetadata"
    };
  }

  // Deletes a single internal range.
  rpc DeleteInternalRange(DeleteInternalRangeRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      delete: "/v1/{name=projects/*/locations/*/internalRanges/*}"
    };
    option (google.api.method_signature) = "name";
    option (google.longrunning.operation_info) = {
      response_type: "google.protobuf.Empty"
      metadata_type: "OperationMetadata"
    };
  }
}

// The internal range resource for IPAM operations within a VPC network.
// Used to represent a private address range along with behavioral
// characteristics of that range (its usage and peering behavior).
// Networking resources can link to this range if they are created
// as belonging to it.
message InternalRange {
  option (google.api.resource) = {
    type: "networkconnectivity.googleapis.com/InternalRange"
    pattern: "projects/{project}/locations/{location}/internalRanges/{internal_range}"
  };

  // Specification for migration with source and target resource names.
  message Migration {
    // Immutable. Resource path as an URI of the source resource, for example a
    // subnet. The project for the source resource should match the project for
    // the InternalRange. An example:
    //   /projects/{project}/regions/{region}/subnetworks/{subnet}
    string source = 1 [(google.api.field_behavior) = IMMUTABLE];

    // Immutable. Resource path of the target resource. The target project can
    // be different, as in the cases when migrating to peer networks. For
    // example:
    //   /projects/{project}/regions/{region}/subnetworks/{subnet}
    string target = 2 [(google.api.field_behavior) = IMMUTABLE];
  }

  // Range auto-allocation options, to be optionally used when CIDR block is not
  // explicitly set.
  message AllocationOptions {
    // Optional. Allocation strategy Not setting this field when the allocation
    // is requested means an implementation defined strategy is used.
    AllocationStrategy allocation_strategy = 1
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. This field must be set only when allocation_strategy is set to
    // RANDOM_FIRST_N_AVAILABLE.
    // The value should be the maximum expected parallelism of range creation
    // requests issued to the same space of peered netwroks.
    int32 first_available_ranges_lookup_size = 2
        [(google.api.field_behavior) = OPTIONAL];
  }

  // Possible usage of an internal range.
  enum Usage {
    // Unspecified usage is allowed in calls which identify the resource by
    // other fields and do not need Usage set to complete. These are, i.e.:
    // GetInternalRange and DeleteInternalRange.
    // Usage needs to be specified explicitly in CreateInternalRange
    // or UpdateInternalRange calls.
    USAGE_UNSPECIFIED = 0;

    // A VPC resource can use the reserved CIDR block by associating it with the
    // internal range resource if usage is set to FOR_VPC.
    FOR_VPC = 1;

    // Ranges created with EXTERNAL_TO_VPC cannot be associated with VPC
    // resources and are meant to block out address ranges for various use
    // cases, like for example, usage on-prem, with dynamic route announcements
    // via interconnect.
    EXTERNAL_TO_VPC = 2;

    // Ranges created FOR_MIGRATION can be used to lock a CIDR range between a
    // source and target subnet. If usage is set to FOR_MIGRATION, the peering
    // value has to be set to FOR_SELF or default to FOR_SELF when unset.
    FOR_MIGRATION = 3;
  }

  // Peering type.
  enum Peering {
    // If Peering is left unspecified in CreateInternalRange or
    // UpdateInternalRange, it will be defaulted to FOR_SELF.
    PEERING_UNSPECIFIED = 0;

    // This is the default behavior and represents the case that this
    // internal range is intended to be used in the VPC in which it is created
    // and is accessible from its peers. This implies that peers or
    // peers-of-peers cannot use this range.
    FOR_SELF = 1;

    // This behavior can be set when the internal range is being reserved for
    // usage by peers. This means that no resource within the VPC in which
    // it is being created can use this to associate with a VPC resource, but
    // one of the peers can. This represents donating a range for peers to
    // use.
    FOR_PEER = 2;

    // This behavior can be set when the internal range is being reserved for
    // usage by the VPC in which it is created, but not shared with peers.
    // In a sense, it is local to the VPC. This can be used to create internal
    // ranges for various purposes like HTTP_INTERNAL_LOAD_BALANCER or for
    // Interconnect routes that are not shared with peers. This also implies
    // that peers cannot use this range in a way that is visible to this VPC,
    // but can re-use this range as long as it is NOT_SHARED from the peer VPC,
    // too.
    NOT_SHARED = 3;
  }

  // Overlap specifications.
  enum Overlap {
    // No overlap overrides.
    OVERLAP_UNSPECIFIED = 0;

    // Allow creation of static routes more specific that the current
    // internal range.
    OVERLAP_ROUTE_RANGE = 1;

    // Allow creation of internal ranges that overlap with existing subnets.
    OVERLAP_EXISTING_SUBNET_RANGE = 2;
  }

  // Enumeration of range auto-allocation strategies
  enum AllocationStrategy {
    // Unspecified is the only valid option when the range is specified
    // explicitly by ip_cidr_range field. Otherwise unspefified means using the
    // default strategy.
    ALLOCATION_STRATEGY_UNSPECIFIED = 0;

    // Random strategy, the legacy algorithm, used for backwards compatibility.
    // This allocation strategy remains efficient in the case of concurrent
    // allocation requests in the same peered network space and doesn't require
    // providing the level of concurrency in an explicit parameter, but it is
    // prone to fragmenting available address space.
    RANDOM = 1;

    // Pick the first available address range. This strategy is deterministic
    // and the result is easy to predict.
    FIRST_AVAILABLE = 2;

    // Pick an arbitrary range out of the first N available ones. The N will be
    // set in the first_available_ranges_lookup_size field. This strategy should
    // be used when concurrent allocation requests are made in the same space of
    // peered networks while the fragmentation of the addrress space is reduced.
    RANDOM_FIRST_N_AVAILABLE = 3;

    // Pick the smallest but fitting available range. This deterministic
    // strategy minimizes fragmentation of the address space.
    FIRST_SMALLEST_FITTING = 4;
  }

  // Identifier. The name of an internal range.
  // Format:
  // projects/{project}/locations/{location}/internalRanges/{internal_range}
  // See: https://google.aip.dev/122#fields-representing-resource-names
  string name = 1 [(google.api.field_behavior) = IDENTIFIER];

  // Time when the internal range was created.
  google.protobuf.Timestamp create_time = 2;

  // Time when the internal range was updated.
  google.protobuf.Timestamp update_time = 3;

  // User-defined labels.
  map<string, string> labels = 4;

  // Optional. A description of this resource.
  string description = 5 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The IP range that this internal range defines.
  // NOTE: IPv6 ranges are limited to usage=EXTERNAL_TO_VPC and
  // peering=FOR_SELF.
  // NOTE: For IPv6 Ranges this field is compulsory, i.e. the address range must
  // be specified explicitly.
  string ip_cidr_range = 6 [(google.api.field_behavior) = OPTIONAL];

  // Immutable. The URL or resource ID of the network in which to reserve the
  // internal range. The network cannot be deleted if there are any reserved
  // internal ranges referring to it. Legacy networks are not supported. For
  // example:
  //   https://www.googleapis.com/compute/v1/projects/{project}/locations/global/networks/{network}
  //   projects/{project}/locations/global/networks/{network}
  //   {network}
  string network = 7 [(google.api.field_behavior) = IMMUTABLE];

  // Optional. The type of usage set for this InternalRange.
  Usage usage = 8 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The type of peering set for this internal range.
  Peering peering = 9 [(google.api.field_behavior) = OPTIONAL];

  // Optional. An alternate to ip_cidr_range. Can be set when trying to create
  // an IPv4 reservation that automatically finds a free range of the given
  // size. If both ip_cidr_range and prefix_length are set, there is an error if
  // the range sizes do not match. Can also be used during updates to change the
  // range size.
  // NOTE: For IPv6 this field only works if ip_cidr_range is set as well, and
  // both fields must match. In other words, with IPv6 this field only works as
  // a redundant parameter.
  int32 prefix_length = 10 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Can be set to narrow down or pick a different address space while
  // searching for a free range. If not set, defaults to the "10.0.0.0/8"
  // address space. This can be used to search in other rfc-1918 address
  // spaces like "172.16.0.0/12" and "192.168.0.0/16" or non-rfc-1918
  // address spaces used in the VPC.
  repeated string target_cidr_range = 11
      [(google.api.field_behavior) = OPTIONAL];

  // Output only. The list of resources that refer to this internal range.
  // Resources that use the internal range for their range allocation
  // are referred to as users of the range. Other resources mark themselves
  // as users while doing so by creating a reference to this internal range.
  // Having a user, based on this reference, prevents deletion of the
  // internal range referred to. Can be empty.
  repeated string users = 12 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Optional. Types of resources that are allowed to overlap with the current
  // internal range.
  repeated Overlap overlaps = 13 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Must be present if usage is set to FOR_MIGRATION.
  Migration migration = 14 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Immutable ranges cannot have their fields modified, except for
  // labels and description.
  bool immutable = 15 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Range auto-allocation options, may be set only when
  // auto-allocation is selected by not setting ip_cidr_range (and setting
  // prefix_length).
  AllocationOptions allocation_options = 16
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. ExcludeCidrRanges flag. Specifies a set of CIDR blocks that
  // allows exclusion of particular CIDR ranges from the auto-allocation
  // process, without having to reserve these blocks
  repeated string exclude_cidr_ranges = 17
      [(google.api.field_behavior) = OPTIONAL];
}

// Request for InternalRangeService.ListInternalRanges
message ListInternalRangesRequest {
  // Required. The parent resource's name.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "locations.googleapis.com/Location"
    }
  ];

  // The maximum number of results per page that should be returned.
  int32 page_size = 2;

  // The page token.
  string page_token = 3;

  // A filter expression that filters the results listed in the response.
  string filter = 4;

  // Sort the results by a certain order.
  string order_by = 5;
}

// Response for InternalRange.ListInternalRanges
message ListInternalRangesResponse {
  // Internal ranges to be returned.
  repeated InternalRange internal_ranges = 1;

  // The next pagination token in the List response. It should be used as
  // page_token for the following request. An empty value means no more result.
  string next_page_token = 2;

  // Locations that could not be reached.
  repeated string unreachable = 3;
}

// Request for InternalRangeService.GetInternalRange
message GetInternalRangeRequest {
  // Required. Name of the InternalRange to get.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "networkconnectivity.googleapis.com/InternalRange"
    }
  ];
}

// Request for InternalRangeService.CreateInternalRange
message CreateInternalRangeRequest {
  // Required. The parent resource's name of the internal range.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "networkconnectivity.googleapis.com/InternalRange"
    }
  ];

  // Optional. Resource ID
  // (i.e. 'foo' in '[...]/projects/p/locations/l/internalRanges/foo')
  // See https://google.aip.dev/122#resource-id-segments
  // Unique per location.
  string internal_range_id = 2 [(google.api.field_behavior) = OPTIONAL];

  // Required. Initial values for a new internal range
  InternalRange internal_range = 3 [(google.api.field_behavior) = REQUIRED];

  // Optional. An optional request ID to identify requests. Specify a unique
  // request ID so that if you must retry your request, the server will know to
  // ignore the request if it has already been completed. The server will
  // guarantee that for at least 60 minutes since the first request.
  //
  // For example, consider a situation where you make an initial request and
  // the request times out. If you make the request again with the same request
  // ID, the server can check if original operation with the same request ID
  // was received, and if so, will ignore the second request. This prevents
  // clients from accidentally creating duplicate commitments.
  //
  // The request ID must be a valid UUID with the exception that zero UUID is
  // not supported (00000000-0000-0000-0000-000000000000).
  string request_id = 4 [(google.api.field_behavior) = OPTIONAL];
}

// Request for InternalRangeService.UpdateInternalRange
message UpdateInternalRangeRequest {
  // Optional. Field mask is used to specify the fields to be overwritten in the
  // InternalRange resource by the update.
  // The fields specified in the update_mask are relative to the resource, not
  // the full request. A field will be overwritten if it is in the mask. If the
  // user does not provide a mask then all fields will be overwritten.
  google.protobuf.FieldMask update_mask = 1
      [(google.api.field_behavior) = OPTIONAL];

  // Required. New values to be patched into the resource.
  InternalRange internal_range = 2 [(google.api.field_behavior) = REQUIRED];

  // Optional. An optional request ID to identify requests. Specify a unique
  // request ID so that if you must retry your request, the server will know to
  // ignore the request if it has already been completed. The server will
  // guarantee that for at least 60 minutes since the first request.
  //
  // For example, consider a situation where you make an initial request and
  // the request times out. If you make the request again with the same request
  // ID, the server can check if original operation with the same request ID
  // was received, and if so, will ignore the second request. This prevents
  // clients from accidentally creating duplicate commitments.
  //
  // The request ID must be a valid UUID with the exception that zero UUID is
  // not supported (00000000-0000-0000-0000-000000000000).
  string request_id = 3 [(google.api.field_behavior) = OPTIONAL];
}

// Request for InternalRangeService.DeleteInternalRange
message DeleteInternalRangeRequest {
  // Required. The name of the internal range to delete.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "networkconnectivity.googleapis.com/InternalRange"
    }
  ];

  // Optional. An optional request ID to identify requests. Specify a unique
  // request ID so that if you must retry your request, the server will know to
  // ignore the request if it has already been completed. The server will
  // guarantee that for at least 60 minutes after the first request.
  //
  // For example, consider a situation where you make an initial request and
  // the request times out. If you make the request again with the same request
  // ID, the server can check if original operation with the same request ID
  // was received, and if so, will ignore the second request. This prevents
  // clients from accidentally creating duplicate commitments.
  //
  // The request ID must be a valid UUID with the exception that zero UUID is
  // not supported (00000000-0000-0000-0000-000000000000).
  string request_id = 2 [(google.api.field_behavior) = OPTIONAL];
}
