// Copyright 2020 Google LLC.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Code generated file. DO NOT EDIT.

// Package servicecontrol provides access to the Service Control API.
//
// For product documentation, see: https://cloud.google.com/service-control/
//
// Creating a client
//
// Usage example:
//
//   import "google.golang.org/api/servicecontrol/v2"
//   ...
//   ctx := context.Background()
//   servicecontrolService, err := servicecontrol.NewService(ctx)
//
// In this example, Google Application Default Credentials are used for authentication.
//
// For information on how to create and obtain Application Default Credentials, see https://developers.google.com/identity/protocols/application-default-credentials.
//
// Other authentication options
//
// By default, all available scopes (see "Constants") are used to authenticate. To restrict scopes, use option.WithScopes:
//
//   servicecontrolService, err := servicecontrol.NewService(ctx, option.WithScopes(servicecontrol.ServicecontrolScope))
//
// To use an API key for authentication (note: some APIs do not support API keys), use option.WithAPIKey:
//
//   servicecontrolService, err := servicecontrol.NewService(ctx, option.WithAPIKey("AIza..."))
//
// To use an OAuth token (e.g., a user token obtained via a three-legged OAuth flow), use option.WithTokenSource:
//
//   config := &oauth2.Config{...}
//   // ...
//   token, err := config.Exchange(ctx, ...)
//   servicecontrolService, err := servicecontrol.NewService(ctx, option.WithTokenSource(config.TokenSource(ctx, token)))
//
// See https://godoc.org/google.golang.org/api/option/ for details on options.
package servicecontrol // import "google.golang.org/api/servicecontrol/v2"

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	googleapi "google.golang.org/api/googleapi"
	gensupport "google.golang.org/api/internal/gensupport"
	option "google.golang.org/api/option"
	internaloption "google.golang.org/api/option/internaloption"
	htransport "google.golang.org/api/transport/http"
)

// Always reference these packages, just in case the auto-generated code
// below doesn't.
var _ = bytes.NewBuffer
var _ = strconv.Itoa
var _ = fmt.Sprintf
var _ = json.NewDecoder
var _ = io.Copy
var _ = url.Parse
var _ = gensupport.MarshalJSON
var _ = googleapi.Version
var _ = errors.New
var _ = strings.Replace
var _ = context.Canceled
var _ = internaloption.WithDefaultEndpoint

const apiId = "servicecontrol:v2"
const apiName = "servicecontrol"
const apiVersion = "v2"
const basePath = "https://servicecontrol.googleapis.com/"
const mtlsBasePath = "https://servicecontrol.mtls.googleapis.com/"

// OAuth2 scopes used by this API.
const (
	// View and manage your data across Google Cloud Platform services
	CloudPlatformScope = "https://www.googleapis.com/auth/cloud-platform"

	// Manage your Google Service Control data
	ServicecontrolScope = "https://www.googleapis.com/auth/servicecontrol"
)

// NewService creates a new Service.
func NewService(ctx context.Context, opts ...option.ClientOption) (*Service, error) {
	scopesOption := option.WithScopes(
		"https://www.googleapis.com/auth/cloud-platform",
		"https://www.googleapis.com/auth/servicecontrol",
	)
	// NOTE: prepend, so we don't override user-specified scopes.
	opts = append([]option.ClientOption{scopesOption}, opts...)
	opts = append(opts, internaloption.WithDefaultEndpoint(basePath))
	opts = append(opts, internaloption.WithDefaultMTLSEndpoint(mtlsBasePath))
	client, endpoint, err := htransport.NewClient(ctx, opts...)
	if err != nil {
		return nil, err
	}
	s, err := New(client)
	if err != nil {
		return nil, err
	}
	if endpoint != "" {
		s.BasePath = endpoint
	}
	return s, nil
}

// New creates a new Service. It uses the provided http.Client for requests.
//
// Deprecated: please use NewService instead.
// To provide a custom HTTP client, use option.WithHTTPClient.
// If you are using google.golang.org/api/googleapis/transport.APIKey, use option.WithAPIKey with NewService instead.
func New(client *http.Client) (*Service, error) {
	if client == nil {
		return nil, errors.New("client is nil")
	}
	s := &Service{client: client, BasePath: basePath}
	s.Services = NewServicesService(s)
	return s, nil
}

type Service struct {
	client    *http.Client
	BasePath  string // API endpoint base URL
	UserAgent string // optional additional User-Agent fragment

	Services *ServicesService
}

func (s *Service) userAgent() string {
	if s.UserAgent == "" {
		return googleapi.UserAgent
	}
	return googleapi.UserAgent + " " + s.UserAgent
}

func NewServicesService(s *Service) *ServicesService {
	rs := &ServicesService{s: s}
	return rs
}

type ServicesService struct {
	s *Service
}

// Api: This message defines attributes associated with API operations,
// such as a network API request. The terminology is based on the
// conventions used by Google APIs, Istio, and OpenAPI.
type Api struct {
	// Operation: The API operation name. For gRPC requests, it is the fully
	// qualified API method name, such as
	// "google.pubsub.v1.Publisher.Publish". For OpenAPI requests, it is the
	// `operationId`, such as "getPet".
	Operation string `json:"operation,omitempty"`

	// Protocol: The API protocol used for sending the request, such as
	// "http", "https", "grpc", or "internal".
	Protocol string `json:"protocol,omitempty"`

	// Service: The API service name. It is a logical identifier for a
	// networked API, such as "pubsub.googleapis.com". The naming syntax
	// depends on the API management system being used for handling the
	// request.
	Service string `json:"service,omitempty"`

	// Version: The API version associated with the API operation above,
	// such as "v1" or "v1alpha1".
	Version string `json:"version,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Operation") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Operation") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *Api) MarshalJSON() ([]byte, error) {
	type NoMethod Api
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// AttributeContext: This message defines the standard attribute
// vocabulary for Google APIs. An attribute is a piece of metadata that
// describes an activity on a network service. For example, the size of
// an HTTP request, or the status code of an HTTP response. Each
// attribute has a type and a name, which is logically defined as a
// proto message field in `AttributeContext`. The field type becomes the
// attribute type, and the field path becomes the attribute name. For
// example, the attribute `source.ip` maps to field
// `AttributeContext.source.ip`. This message definition is guaranteed
// not to have any wire breaking change. So you can use it directly for
// passing attributes across different systems. NOTE: Different system
// may generate different subset of attributes. Please verify the system
// specification before relying on an attribute generated a system.
type AttributeContext struct {
	// Api: Represents an API operation that is involved to a network
	// activity.
	Api *Api `json:"api,omitempty"`

	// Destination: The destination of a network activity, such as accepting
	// a TCP connection. In a multi hop network activity, the destination
	// represents the receiver of the last hop.
	Destination *Peer `json:"destination,omitempty"`

	// Extensions: Supports extensions for advanced use cases, such as logs
	// and metrics.
	Extensions []googleapi.RawMessage `json:"extensions,omitempty"`

	// Origin: The origin of a network activity. In a multi hop network
	// activity, the origin represents the sender of the first hop. For the
	// first hop, the `source` and the `origin` must have the same content.
	Origin *Peer `json:"origin,omitempty"`

	// Request: Represents a network request, such as an HTTP request.
	Request *Request `json:"request,omitempty"`

	// Resource: Represents a target resource that is involved with a
	// network activity. If multiple resources are involved with an
	// activity, this must be the primary one.
	Resource *Resource `json:"resource,omitempty"`

	// Response: Represents a network response, such as an HTTP response.
	Response *Response `json:"response,omitempty"`

	// Source: The source of a network activity, such as starting a TCP
	// connection. In a multi hop network activity, the source represents
	// the sender of the last hop.
	Source *Peer `json:"source,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Api") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Api") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *AttributeContext) MarshalJSON() ([]byte, error) {
	type NoMethod AttributeContext
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// AuditLog: Common audit log format for Google Cloud Platform API
// operations.
type AuditLog struct {
	// AuthenticationInfo: Authentication information.
	AuthenticationInfo *AuthenticationInfo `json:"authenticationInfo,omitempty"`

	// AuthorizationInfo: Authorization information. If there are multiple
	// resources or permissions involved, then there is one
	// AuthorizationInfo element for each {resource, permission} tuple.
	AuthorizationInfo []*AuthorizationInfo `json:"authorizationInfo,omitempty"`

	// Metadata: Other service-specific data about the request, response,
	// and other information associated with the current audited event.
	Metadata googleapi.RawMessage `json:"metadata,omitempty"`

	// MethodName: The name of the service method or operation. For API
	// calls, this should be the name of the API method. For example,
	// "google.cloud.bigquery.v2.TableService.InsertTable"
	// "google.logging.v2.ConfigServiceV2.CreateSink"
	MethodName string `json:"methodName,omitempty"`

	// NumResponseItems: The number of items returned from a List or Query
	// API method, if applicable.
	NumResponseItems int64 `json:"numResponseItems,omitempty,string"`

	// Request: The operation request. This may not include all request
	// parameters, such as those that are too large, privacy-sensitive, or
	// duplicated elsewhere in the log record. It should never include
	// user-generated data, such as file contents. When the JSON object
	// represented here has a proto equivalent, the proto name will be
	// indicated in the `@type` property.
	Request googleapi.RawMessage `json:"request,omitempty"`

	// RequestMetadata: Metadata about the operation.
	RequestMetadata *RequestMetadata `json:"requestMetadata,omitempty"`

	// ResourceLocation: The resource location information.
	ResourceLocation *ResourceLocation `json:"resourceLocation,omitempty"`

	// ResourceName: The resource or collection that is the target of the
	// operation. The name is a scheme-less URI, not including the API
	// service name. For example:
	// "projects/PROJECT_ID/zones/us-central1-a/instances"
	// "projects/PROJECT_ID/datasets/DATASET_ID"
	ResourceName string `json:"resourceName,omitempty"`

	// ResourceOriginalState: The resource's original state before mutation.
	// Present only for operations which have successfully modified the
	// targeted resource(s). In general, this field should contain all
	// changed fields, except those that are already been included in
	// `request`, `response`, `metadata` or `service_data` fields. When the
	// JSON object represented here has a proto equivalent, the proto name
	// will be indicated in the `@type` property.
	ResourceOriginalState googleapi.RawMessage `json:"resourceOriginalState,omitempty"`

	// Response: The operation response. This may not include all response
	// elements, such as those that are too large, privacy-sensitive, or
	// duplicated elsewhere in the log record. It should never include
	// user-generated data, such as file contents. When the JSON object
	// represented here has a proto equivalent, the proto name will be
	// indicated in the `@type` property.
	Response googleapi.RawMessage `json:"response,omitempty"`

	// ServiceData: Deprecated. Use the `metadata` field instead. Other
	// service-specific data about the request, response, and other
	// activities.
	ServiceData googleapi.RawMessage `json:"serviceData,omitempty"`

	// ServiceName: The name of the API service performing the operation.
	// For example, "compute.googleapis.com".
	ServiceName string `json:"serviceName,omitempty"`

	// Status: The status of the overall operation.
	Status *Status `json:"status,omitempty"`

	// ForceSendFields is a list of field names (e.g. "AuthenticationInfo")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "AuthenticationInfo") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *AuditLog) MarshalJSON() ([]byte, error) {
	type NoMethod AuditLog
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// Auth: This message defines request authentication attributes.
// Terminology is based on the JSON Web Token (JWT) standard, but the
// terms also correlate to concepts in other standards.
type Auth struct {
	// AccessLevels: A list of access level resource names that allow
	// resources to be accessed by authenticated requester. It is part of
	// Secure GCP processing for the incoming request. An access level
	// string has the format:
	// "//{api_service_name}/accessPolicies/{policy_id}/accessLevels/{short_n
	// ame}" Example:
	// "//accesscontextmanager.googleapis.com/accessPolicies/MY_POLICY_ID/acc
	// essLevels/MY_LEVEL"
	AccessLevels []string `json:"accessLevels,omitempty"`

	// Audiences: The intended audience(s) for this authentication
	// information. Reflects the audience (`aud`) claim within a JWT. The
	// audience value(s) depends on the `issuer`, but typically include one
	// or more of the following pieces of information: * The services
	// intended to receive the credential. For example,
	// ["https://pubsub.googleapis.com/",
	// "https://storage.googleapis.com/"]. * A set of service-based scopes.
	// For example, ["https://www.googleapis.com/auth/cloud-platform"]. *
	// The client id of an app, such as the Firebase project id for JWTs
	// from Firebase Auth. Consult the documentation for the credential
	// issuer to determine the information provided.
	Audiences []string `json:"audiences,omitempty"`

	// Claims: Structured claims presented with the credential. JWTs include
	// `{key: value}` pairs for standard and private claims. The following
	// is a subset of the standard required and optional claims that would
	// typically be presented for a Google-based JWT: {'iss':
	// 'accounts.google.com', 'sub': '113289723416554971153', 'aud':
	// ['123456789012', 'pubsub.googleapis.com'], 'azp':
	// '123456789012.apps.googleusercontent.com', 'email':
	// 'jsmith@example.com', 'iat': 1353601026, 'exp': 1353604926} SAML
	// assertions are similarly specified, but with an identity provider
	// dependent structure.
	Claims googleapi.RawMessage `json:"claims,omitempty"`

	// Presenter: The authorized presenter of the credential. Reflects the
	// optional Authorized Presenter (`azp`) claim within a JWT or the OAuth
	// client id. For example, a Google Cloud Platform client id looks as
	// follows: "123456789012.apps.googleusercontent.com".
	Presenter string `json:"presenter,omitempty"`

	// Principal: The authenticated principal. Reflects the issuer (`iss`)
	// and subject (`sub`) claims within a JWT. The issuer and subject
	// should be `/` delimited, with `/` percent-encoded within the subject
	// fragment. For Google accounts, the principal format is:
	// "https://accounts.google.com/{id}"
	Principal string `json:"principal,omitempty"`

	// ForceSendFields is a list of field names (e.g. "AccessLevels") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "AccessLevels") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *Auth) MarshalJSON() ([]byte, error) {
	type NoMethod Auth
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// AuthenticationInfo: Authentication information for the operation.
type AuthenticationInfo struct {
	// AuthoritySelector: The authority selector specified by the requestor,
	// if any. It is not guaranteed that the principal was allowed to use
	// this authority.
	AuthoritySelector string `json:"authoritySelector,omitempty"`

	// PrincipalEmail: The email address of the authenticated user (or
	// service account on behalf of third party principal) making the
	// request. For privacy reasons, the principal email address is redacted
	// for all read-only operations that fail with a "permission denied"
	// error.
	PrincipalEmail string `json:"principalEmail,omitempty"`

	// PrincipalSubject: String representation of identity of requesting
	// party. Populated for both first and third party identities.
	PrincipalSubject string `json:"principalSubject,omitempty"`

	// ServiceAccountDelegationInfo: Identity delegation history of an
	// authenticated service account that makes the request. It contains
	// information on the real authorities that try to access GCP resources
	// by delegating on a service account. When multiple authorities
	// present, they are guaranteed to be sorted based on the original
	// ordering of the identity delegation events.
	ServiceAccountDelegationInfo []*ServiceAccountDelegationInfo `json:"serviceAccountDelegationInfo,omitempty"`

	// ServiceAccountKeyName: The name of the service account key used to
	// create or exchange credentials for authenticating the service account
	// making the request. This is a scheme-less URI full resource name. For
	// example:
	// "//iam.googleapis.com/projects/{PROJECT_ID}/serviceAccounts/{ACCOUNT}/
	// keys/{key}"
	ServiceAccountKeyName string `json:"serviceAccountKeyName,omitempty"`

	// ThirdPartyPrincipal: The third party identification (if any) of the
	// authenticated user making the request. When the JSON object
	// represented here has a proto equivalent, the proto name will be
	// indicated in the `@type` property.
	ThirdPartyPrincipal googleapi.RawMessage `json:"thirdPartyPrincipal,omitempty"`

	// ForceSendFields is a list of field names (e.g. "AuthoritySelector")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "AuthoritySelector") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *AuthenticationInfo) MarshalJSON() ([]byte, error) {
	type NoMethod AuthenticationInfo
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// AuthorizationInfo: Authorization information for the operation.
type AuthorizationInfo struct {
	// Granted: Whether or not authorization for `resource` and `permission`
	// was granted.
	Granted bool `json:"granted,omitempty"`

	// Permission: The required IAM permission.
	Permission string `json:"permission,omitempty"`

	// Resource: The resource being accessed, as a REST-style string. For
	// example:
	// bigquery.googleapis.com/projects/PROJECTID/datasets/DATASETID
	Resource string `json:"resource,omitempty"`

	// ResourceAttributes: Resource attributes used in IAM condition
	// evaluation. This field contains resource attributes like resource
	// type and resource name. To get the whole view of the attributes used
	// in IAM condition evaluation, the user must also look into
	// `AuditLog.request_metadata.request_attributes`.
	ResourceAttributes *Resource `json:"resourceAttributes,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Granted") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Granted") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *AuthorizationInfo) MarshalJSON() ([]byte, error) {
	type NoMethod AuthorizationInfo
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// CheckRequest: Request message for the Check method.
type CheckRequest struct {
	// Attributes: Describes attributes about the operation being executed
	// by the service.
	Attributes *AttributeContext `json:"attributes,omitempty"`

	// Resources: Describes the resources and the policies applied to each
	// resource.
	Resources []*ResourceInfo `json:"resources,omitempty"`

	// ServiceConfigId: Specifies the version of the service configuration
	// that should be used to process the request. Must not be empty. Set
	// this field to 'latest' to specify using the latest configuration.
	ServiceConfigId string `json:"serviceConfigId,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Attributes") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Attributes") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *CheckRequest) MarshalJSON() ([]byte, error) {
	type NoMethod CheckRequest
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// CheckResponse: Response message for the Check method.
type CheckResponse struct {
	// Headers: Returns a set of request contexts generated from the
	// `CheckRequest`.
	Headers map[string]string `json:"headers,omitempty"`

	// Status: An 'OK' status allows the operation. Any other status
	// indicates a denial; [google.rpc.Status.details]() would contain
	// additional details about the denial.
	Status *Status `json:"status,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`

	// ForceSendFields is a list of field names (e.g. "Headers") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Headers") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *CheckResponse) MarshalJSON() ([]byte, error) {
	type NoMethod CheckResponse
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// FirstPartyPrincipal: First party identity principal.
type FirstPartyPrincipal struct {
	// PrincipalEmail: The email address of a Google account. .
	PrincipalEmail string `json:"principalEmail,omitempty"`

	// ServiceMetadata: Metadata about the service that uses the service
	// account. .
	ServiceMetadata googleapi.RawMessage `json:"serviceMetadata,omitempty"`

	// ForceSendFields is a list of field names (e.g. "PrincipalEmail") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "PrincipalEmail") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *FirstPartyPrincipal) MarshalJSON() ([]byte, error) {
	type NoMethod FirstPartyPrincipal
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// Peer: This message defines attributes for a node that handles a
// network request. The node can be either a service or an application
// that sends, forwards, or receives the request. Service peers should
// fill in `principal` and `labels` as appropriate.
type Peer struct {
	// Ip: The IP address of the peer.
	Ip string `json:"ip,omitempty"`

	// Labels: The labels associated with the peer.
	Labels map[string]string `json:"labels,omitempty"`

	// Port: The network port of the peer.
	Port int64 `json:"port,omitempty,string"`

	// Principal: The identity of this peer. Similar to
	// `Request.auth.principal`, but relative to the peer instead of the
	// request. For example, the idenity associated with a load balancer
	// that forwared the request.
	Principal string `json:"principal,omitempty"`

	// RegionCode: The CLDR country/region code associated with the above IP
	// address. If the IP address is private, the `region_code` should
	// reflect the physical location where this peer is running.
	RegionCode string `json:"regionCode,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Ip") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Ip") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *Peer) MarshalJSON() ([]byte, error) {
	type NoMethod Peer
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// ReportRequest: Request message for the Report method.
type ReportRequest struct {
	// Operations: Describes the list of operations to be reported. Each
	// operation is represented as an AttributeContext, and contains all
	// attributes around an API access.
	Operations []*AttributeContext `json:"operations,omitempty"`

	// ServiceConfigId: Specifies the version of the service configuration
	// that should be used to process the request. Must not be empty. Set
	// this field to 'latest' to specify using the latest configuration.
	ServiceConfigId string `json:"serviceConfigId,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Operations") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Operations") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *ReportRequest) MarshalJSON() ([]byte, error) {
	type NoMethod ReportRequest
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// ReportResponse: Response message for the Report method. If the
// request contains any invalid data, the server returns an RPC error.
type ReportResponse struct {
	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`
}

// Request: This message defines attributes for an HTTP request. If the
// actual request is not an HTTP request, the runtime system should try
// to map the actual request to an equivalent HTTP request.
type Request struct {
	// Auth: The request authentication. May be absent for unauthenticated
	// requests. Derived from the HTTP request `Authorization` header or
	// equivalent.
	Auth *Auth `json:"auth,omitempty"`

	// Headers: The HTTP request headers. If multiple headers share the same
	// key, they must be merged according to the HTTP spec. All header keys
	// must be lowercased, because HTTP header keys are case-insensitive.
	Headers map[string]string `json:"headers,omitempty"`

	// Host: The HTTP request `Host` header value.
	Host string `json:"host,omitempty"`

	// Id: The unique ID for a request, which can be propagated to
	// downstream systems. The ID should have low probability of collision
	// within a single day for a specific service.
	Id string `json:"id,omitempty"`

	// Method: The HTTP request method, such as `GET`, `POST`.
	Method string `json:"method,omitempty"`

	// Path: The HTTP URL path.
	Path string `json:"path,omitempty"`

	// Protocol: The network protocol used with the request, such as
	// "http/1.1", "spdy/3", "h2", "h2c", "webrtc", "tcp", "udp", "quic".
	// See
	// https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids for
	// details.
	Protocol string `json:"protocol,omitempty"`

	// Query: The HTTP URL query in the format of
	// `name1=value1&name2=value2`, as it appears in the first line of the
	// HTTP request. No decoding is performed.
	Query string `json:"query,omitempty"`

	// Reason: A special parameter for request reason. It is used by
	// security systems to associate auditing information with a request.
	Reason string `json:"reason,omitempty"`

	// Scheme: The HTTP URL scheme, such as `http` and `https`.
	Scheme string `json:"scheme,omitempty"`

	// Size: The HTTP request size in bytes. If unknown, it must be -1.
	Size int64 `json:"size,omitempty,string"`

	// Time: The timestamp when the `destination` service receives the first
	// byte of the request.
	Time string `json:"time,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Auth") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Auth") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *Request) MarshalJSON() ([]byte, error) {
	type NoMethod Request
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// RequestMetadata: Metadata about the request.
type RequestMetadata struct {
	// CallerIp: The IP address of the caller. For caller from internet,
	// this will be public IPv4 or IPv6 address. For caller from a Compute
	// Engine VM with external IP address, this will be the VM's external IP
	// address. For caller from a Compute Engine VM without external IP
	// address, if the VM is in the same organization (or project) as the
	// accessed resource, `caller_ip` will be the VM's internal IPv4
	// address, otherwise the `caller_ip` will be redacted to
	// "gce-internal-ip". See https://cloud.google.com/compute/docs/vpc/ for
	// more information.
	CallerIp string `json:"callerIp,omitempty"`

	// CallerNetwork: The network of the caller. Set only if the network
	// host project is part of the same GCP organization (or project) as the
	// accessed resource. See https://cloud.google.com/compute/docs/vpc/ for
	// more information. This is a scheme-less URI full resource name. For
	// example:
	// "//compute.googleapis.com/projects/PROJECT_ID/global/networks/NETWORK_
	// ID"
	CallerNetwork string `json:"callerNetwork,omitempty"`

	// CallerSuppliedUserAgent: The user agent of the caller. This
	// information is not authenticated and should be treated accordingly.
	// For example: + `google-api-python-client/1.4.0`: The request was made
	// by the Google API client for Python. + `Cloud SDK Command Line Tool
	// apitools-client/1.0 gcloud/0.9.62`: The request was made by the
	// Google Cloud SDK CLI (gcloud). + `AppEngine-Google;
	// (+http://code.google.com/appengine; appid: s~my-project`: The request
	// was made from the `my-project` App Engine app. NOLINT
	CallerSuppliedUserAgent string `json:"callerSuppliedUserAgent,omitempty"`

	// DestinationAttributes: The destination of a network activity, such as
	// accepting a TCP connection. In a multi hop network activity, the
	// destination represents the receiver of the last hop. Only two fields
	// are used in this message, Peer.port and Peer.ip. These fields are
	// optionally populated by those services utilizing the IAM condition
	// feature.
	DestinationAttributes *Peer `json:"destinationAttributes,omitempty"`

	// RequestAttributes: Request attributes used in IAM condition
	// evaluation. This field contains request attributes like request time
	// and access levels associated with the request. To get the whole view
	// of the attributes used in IAM condition evaluation, the user must
	// also look into `AuditLog.authentication_info.resource_attributes`.
	RequestAttributes *Request `json:"requestAttributes,omitempty"`

	// ForceSendFields is a list of field names (e.g. "CallerIp") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "CallerIp") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *RequestMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod RequestMetadata
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// Resource: This message defines core attributes for a resource. A
// resource is an addressable (named) entity provided by the destination
// service. For example, a file stored on a network storage service.
type Resource struct {
	// Labels: The labels or tags on the resource, such as AWS resource tags
	// and Kubernetes resource labels.
	Labels map[string]string `json:"labels,omitempty"`

	// Name: The stable identifier (name) of a resource on the `service`. A
	// resource can be logically identified as
	// "//{resource.service}/{resource.name}". The differences between a
	// resource name and a URI are: * Resource name is a logical identifier,
	// independent of network protocol and API version. For example,
	// `//pubsub.googleapis.com/projects/123/topics/news-feed`. * URI often
	// includes protocol and version information, so it can be used directly
	// by applications. For example,
	// `https://pubsub.googleapis.com/v1/projects/123/topics/news-feed`. See
	// https://cloud.google.com/apis/design/resource_names for details.
	Name string `json:"name,omitempty"`

	// Service: The name of the service that this resource belongs to, such
	// as `pubsub.googleapis.com`. The service may be different from the DNS
	// hostname that actually serves the request.
	Service string `json:"service,omitempty"`

	// Type: The type of the resource. The syntax is platform-specific
	// because different platforms define their resources differently. For
	// Google APIs, the type format must be "{service}/{kind}".
	Type string `json:"type,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Labels") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Labels") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *Resource) MarshalJSON() ([]byte, error) {
	type NoMethod Resource
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// ResourceInfo: Describes a resource referenced in the request.
type ResourceInfo struct {
	// Name: The name of the resource referenced in the request.
	Name string `json:"name,omitempty"`

	// Permission: The resource permission needed for this request. The
	// format must be "{service}/{plural}.{verb}".
	Permission string `json:"permission,omitempty"`

	// Type: The resource type in the format of "{service}/{kind}".
	Type string `json:"type,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Name") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Name") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *ResourceInfo) MarshalJSON() ([]byte, error) {
	type NoMethod ResourceInfo
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// ResourceLocation: Location information about a resource.
type ResourceLocation struct {
	// CurrentLocations: The locations of a resource after the execution of
	// the operation. Requests to create or delete a location based resource
	// must populate the 'current_locations' field and not the
	// 'original_locations' field. For example: "europe-west1-a" "us-east1"
	// "nam3"
	CurrentLocations []string `json:"currentLocations,omitempty"`

	// OriginalLocations: The locations of a resource prior to the execution
	// of the operation. Requests that mutate the resource's location must
	// populate both the 'original_locations' as well as the
	// 'current_locations' fields. For example: "europe-west1-a" "us-east1"
	// "nam3"
	OriginalLocations []string `json:"originalLocations,omitempty"`

	// ForceSendFields is a list of field names (e.g. "CurrentLocations") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "CurrentLocations") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *ResourceLocation) MarshalJSON() ([]byte, error) {
	type NoMethod ResourceLocation
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// Response: This message defines attributes for a typical network
// response. It generally models semantics of an HTTP response.
type Response struct {
	// Code: The HTTP response status code, such as `200` and `404`.
	Code int64 `json:"code,omitempty,string"`

	// Headers: The HTTP response headers. If multiple headers share the
	// same key, they must be merged according to HTTP spec. All header keys
	// must be lowercased, because HTTP header keys are case-insensitive.
	Headers map[string]string `json:"headers,omitempty"`

	// Size: The HTTP response size in bytes. If unknown, it must be -1.
	Size int64 `json:"size,omitempty,string"`

	// Time: The timestamp when the `destination` service generates the
	// first byte of the response.
	Time string `json:"time,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Code") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Code") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *Response) MarshalJSON() ([]byte, error) {
	type NoMethod Response
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// ServiceAccountDelegationInfo: Identity delegation history of an
// authenticated service account.
type ServiceAccountDelegationInfo struct {
	// FirstPartyPrincipal: First party (Google) identity as the real
	// authority.
	FirstPartyPrincipal *FirstPartyPrincipal `json:"firstPartyPrincipal,omitempty"`

	// ThirdPartyPrincipal: Third party identity as the real authority.
	ThirdPartyPrincipal *ThirdPartyPrincipal `json:"thirdPartyPrincipal,omitempty"`

	// ForceSendFields is a list of field names (e.g. "FirstPartyPrincipal")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "FirstPartyPrincipal") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *ServiceAccountDelegationInfo) MarshalJSON() ([]byte, error) {
	type NoMethod ServiceAccountDelegationInfo
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// SpanContext: The context of a span, attached to Exemplars in
// Distribution values during aggregation. It contains the name of a
// span with format:
// projects/[PROJECT_ID_OR_NUMBER]/traces/[TRACE_ID]/spans/[SPAN_ID]
type SpanContext struct {
	// SpanName: The resource name of the span. The format is:
	// projects/[PROJECT_ID_OR_NUMBER]/traces/[TRACE_ID]/spans/[SPAN_ID]
	// `[TRACE_ID]` is a unique identifier for a trace within a project; it
	// is a 32-character hexadecimal encoding of a 16-byte array.
	// `[SPAN_ID]` is a unique identifier for a span within a trace; it is a
	// 16-character hexadecimal encoding of an 8-byte array.
	SpanName string `json:"spanName,omitempty"`

	// ForceSendFields is a list of field names (e.g. "SpanName") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "SpanName") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *SpanContext) MarshalJSON() ([]byte, error) {
	type NoMethod SpanContext
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// Status: The `Status` type defines a logical error model that is
// suitable for different programming environments, including REST APIs
// and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each
// `Status` message contains three pieces of data: error code, error
// message, and error details. You can find out more about this error
// model and how to work with it in the [API Design
// Guide](https://cloud.google.com/apis/design/errors).
type Status struct {
	// Code: The status code, which should be an enum value of
	// google.rpc.Code.
	Code int64 `json:"code,omitempty"`

	// Details: A list of messages that carry the error details. There is a
	// common set of message types for APIs to use.
	Details []googleapi.RawMessage `json:"details,omitempty"`

	// Message: A developer-facing error message, which should be in
	// English. Any user-facing error message should be localized and sent
	// in the google.rpc.Status.details field, or localized by the client.
	Message string `json:"message,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Code") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Code") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *Status) MarshalJSON() ([]byte, error) {
	type NoMethod Status
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// ThirdPartyPrincipal: Third party identity principal.
type ThirdPartyPrincipal struct {
	// ThirdPartyClaims: Metadata about third party identity.
	ThirdPartyClaims googleapi.RawMessage `json:"thirdPartyClaims,omitempty"`

	// ForceSendFields is a list of field names (e.g. "ThirdPartyClaims") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "ThirdPartyClaims") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *ThirdPartyPrincipal) MarshalJSON() ([]byte, error) {
	type NoMethod ThirdPartyPrincipal
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// method id "servicecontrol.services.check":

type ServicesCheckCall struct {
	s            *Service
	serviceName  string
	checkrequest *CheckRequest
	urlParams_   gensupport.URLParams
	ctx_         context.Context
	header_      http.Header
}

// Check: Private Preview. This feature is only available for approved
// services. This method provides admission control for services that
// are integrated with [Service
// Infrastructure](/service-infrastructure). It checks whether an
// operation should be allowed based on the service configuration and
// relevant policies. It must be called before the operation is
// executed. For more information, see [Admission
// Control](/service-infrastructure/docs/admission-control). NOTE: The
// admission control has an expected policy propagation delay of 60s.
// The caller **must** not depend on the most recent policy changes.
// NOTE: The admission control has a hard limit of 1 referenced
// resources per call. If an operation refers to more than 1 resources,
// the caller must call the Check method multiple times. This method
// requires the `servicemanagement.services.check` permission on the
// specified service. For more information, see [Service Control API
// Access
// Control](https://cloud.google.com/service-infrastructure/docs/service-
// control/access-control).
func (r *ServicesService) Check(serviceName string, checkrequest *CheckRequest) *ServicesCheckCall {
	c := &ServicesCheckCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.serviceName = serviceName
	c.checkrequest = checkrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ServicesCheckCall) Fields(s ...googleapi.Field) *ServicesCheckCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ServicesCheckCall) Context(ctx context.Context) *ServicesCheckCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ServicesCheckCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ServicesCheckCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200819")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	body, err := googleapi.WithoutDataWrapper.JSONReader(c.checkrequest)
	if err != nil {
		return nil, err
	}
	reqHeaders.Set("Content-Type", "application/json")
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v2/services/{serviceName}:check")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"serviceName": c.serviceName,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "servicecontrol.services.check" call.
// Exactly one of *CheckResponse or error will be non-nil. Any non-2xx
// status code is an error. Response headers are in either
// *CheckResponse.ServerResponse.Header or (if a response was returned
// at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ServicesCheckCall) Do(opts ...googleapi.CallOption) (*CheckResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &CheckResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Private Preview. This feature is only available for approved services. This method provides admission control for services that are integrated with [Service Infrastructure](/service-infrastructure). It checks whether an operation should be allowed based on the service configuration and relevant policies. It must be called before the operation is executed. For more information, see [Admission Control](/service-infrastructure/docs/admission-control). NOTE: The admission control has an expected policy propagation delay of 60s. The caller **must** not depend on the most recent policy changes. NOTE: The admission control has a hard limit of 1 referenced resources per call. If an operation refers to more than 1 resources, the caller must call the Check method multiple times. This method requires the `servicemanagement.services.check` permission on the specified service. For more information, see [Service Control API Access Control](https://cloud.google.com/service-infrastructure/docs/service-control/access-control).",
	//   "flatPath": "v2/services/{serviceName}:check",
	//   "httpMethod": "POST",
	//   "id": "servicecontrol.services.check",
	//   "parameterOrder": [
	//     "serviceName"
	//   ],
	//   "parameters": {
	//     "serviceName": {
	//       "description": "The service name as specified in its service configuration. For example, `\"pubsub.googleapis.com\"`. See [google.api.Service](https://cloud.google.com/service-management/reference/rpc/google.api#google.api.Service) for the definition of a service name.",
	//       "location": "path",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v2/services/{serviceName}:check",
	//   "request": {
	//     "$ref": "CheckRequest"
	//   },
	//   "response": {
	//     "$ref": "CheckResponse"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform",
	//     "https://www.googleapis.com/auth/servicecontrol"
	//   ]
	// }

}

// method id "servicecontrol.services.report":

type ServicesReportCall struct {
	s             *Service
	serviceName   string
	reportrequest *ReportRequest
	urlParams_    gensupport.URLParams
	ctx_          context.Context
	header_       http.Header
}

// Report: Private Preview. This feature is only available for approved
// services. This method provides telemetry reporting for services that
// are integrated with [Service
// Infrastructure](/service-infrastructure). It reports a list of
// operations that have occurred on a service. It must be called after
// the operations have been executed. For more information, see
// [Telemetry
// Reporting](/service-infrastructure/docs/telemetry-reporting). NOTE:
// The telemetry reporting has a hard limit of 1000 operations and 1MB
// per Report call. It is recommended to have no more than 100
// operations per call. This method requires the
// `servicemanagement.services.report` permission on the specified
// service. For more information, see [Service Control API Access
// Control](https://cloud.google.com/service-infrastructure/docs/service-
// control/access-control).
func (r *ServicesService) Report(serviceName string, reportrequest *ReportRequest) *ServicesReportCall {
	c := &ServicesReportCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.serviceName = serviceName
	c.reportrequest = reportrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ServicesReportCall) Fields(s ...googleapi.Field) *ServicesReportCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ServicesReportCall) Context(ctx context.Context) *ServicesReportCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ServicesReportCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ServicesReportCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200819")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	body, err := googleapi.WithoutDataWrapper.JSONReader(c.reportrequest)
	if err != nil {
		return nil, err
	}
	reqHeaders.Set("Content-Type", "application/json")
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v2/services/{serviceName}:report")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"serviceName": c.serviceName,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "servicecontrol.services.report" call.
// Exactly one of *ReportResponse or error will be non-nil. Any non-2xx
// status code is an error. Response headers are in either
// *ReportResponse.ServerResponse.Header or (if a response was returned
// at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ServicesReportCall) Do(opts ...googleapi.CallOption) (*ReportResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &ReportResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Private Preview. This feature is only available for approved services. This method provides telemetry reporting for services that are integrated with [Service Infrastructure](/service-infrastructure). It reports a list of operations that have occurred on a service. It must be called after the operations have been executed. For more information, see [Telemetry Reporting](/service-infrastructure/docs/telemetry-reporting). NOTE: The telemetry reporting has a hard limit of 1000 operations and 1MB per Report call. It is recommended to have no more than 100 operations per call. This method requires the `servicemanagement.services.report` permission on the specified service. For more information, see [Service Control API Access Control](https://cloud.google.com/service-infrastructure/docs/service-control/access-control).",
	//   "flatPath": "v2/services/{serviceName}:report",
	//   "httpMethod": "POST",
	//   "id": "servicecontrol.services.report",
	//   "parameterOrder": [
	//     "serviceName"
	//   ],
	//   "parameters": {
	//     "serviceName": {
	//       "description": "The service name as specified in its service configuration. For example, `\"pubsub.googleapis.com\"`. See [google.api.Service](https://cloud.google.com/service-management/reference/rpc/google.api#google.api.Service) for the definition of a service name.",
	//       "location": "path",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v2/services/{serviceName}:report",
	//   "request": {
	//     "$ref": "ReportRequest"
	//   },
	//   "response": {
	//     "$ref": "ReportResponse"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform",
	//     "https://www.googleapis.com/auth/servicecontrol"
	//   ]
	// }

}
