// 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 recommender provides access to the Recommender API.
//
// For product documentation, see: https://cloud.google.com/recommender/docs/
//
// Creating a client
//
// Usage example:
//
//   import "google.golang.org/api/recommender/v1beta1"
//   ...
//   ctx := context.Background()
//   recommenderService, err := recommender.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
//
// To use an API key for authentication (note: some APIs do not support API keys), use option.WithAPIKey:
//
//   recommenderService, err := recommender.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, ...)
//   recommenderService, err := recommender.NewService(ctx, option.WithTokenSource(config.TokenSource(ctx, token)))
//
// See https://godoc.org/google.golang.org/api/option/ for details on options.
package recommender // import "google.golang.org/api/recommender/v1beta1"

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 = "recommender:v1beta1"
const apiName = "recommender"
const apiVersion = "v1beta1"
const basePath = "https://recommender.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"
)

// 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",
	)
	// NOTE: prepend, so we don't override user-specified scopes.
	opts = append([]option.ClientOption{scopesOption}, opts...)
	opts = append(opts, internaloption.WithDefaultEndpoint(basePath))
	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.Projects = NewProjectsService(s)
	return s, nil
}

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

	Projects *ProjectsService
}

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

func NewProjectsService(s *Service) *ProjectsService {
	rs := &ProjectsService{s: s}
	rs.Locations = NewProjectsLocationsService(s)
	return rs
}

type ProjectsService struct {
	s *Service

	Locations *ProjectsLocationsService
}

func NewProjectsLocationsService(s *Service) *ProjectsLocationsService {
	rs := &ProjectsLocationsService{s: s}
	rs.Recommenders = NewProjectsLocationsRecommendersService(s)
	return rs
}

type ProjectsLocationsService struct {
	s *Service

	Recommenders *ProjectsLocationsRecommendersService
}

func NewProjectsLocationsRecommendersService(s *Service) *ProjectsLocationsRecommendersService {
	rs := &ProjectsLocationsRecommendersService{s: s}
	rs.Recommendations = NewProjectsLocationsRecommendersRecommendationsService(s)
	return rs
}

type ProjectsLocationsRecommendersService struct {
	s *Service

	Recommendations *ProjectsLocationsRecommendersRecommendationsService
}

func NewProjectsLocationsRecommendersRecommendationsService(s *Service) *ProjectsLocationsRecommendersRecommendationsService {
	rs := &ProjectsLocationsRecommendersRecommendationsService{s: s}
	return rs
}

type ProjectsLocationsRecommendersRecommendationsService struct {
	s *Service
}

// GoogleCloudRecommenderV1beta1CostProjection: Contains metadata about
// how much money a recommendation can save or incur.
type GoogleCloudRecommenderV1beta1CostProjection struct {
	// Cost: An approximate projection on amount saved or amount incurred.
	// Negative cost
	// units indicate cost savings and positive cost units indicate
	// increase.
	// See google.type.Money documentation for positive/negative units.
	Cost *GoogleTypeMoney `json:"cost,omitempty"`

	// Duration: Duration for which this cost applies.
	Duration string `json:"duration,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Cost") 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. "Cost") 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 *GoogleCloudRecommenderV1beta1CostProjection) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommenderV1beta1CostProjection
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommenderV1beta1Impact: Contains the impact a
// recommendation can have for a given category.
type GoogleCloudRecommenderV1beta1Impact struct {
	// Category: Category that is being targeted.
	//
	// Possible values:
	//   "CATEGORY_UNSPECIFIED" - Default unspecified category. Don't use
	// directly.
	//   "COST" - Indicates a potential increase or decrease in cost.
	//   "SECURITY" - Indicates a potential increase or decrease in
	// security.
	//   "PERFORMANCE" - Indicates a potential increase or decrease in
	// performance.
	//   "MANAGEABILITY" - Indicates a potential increase or decrease in
	// manageability.
	Category string `json:"category,omitempty"`

	// CostProjection: Use with CategoryType.COST
	CostProjection *GoogleCloudRecommenderV1beta1CostProjection `json:"costProjection,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Category") 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. "Category") 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 *GoogleCloudRecommenderV1beta1Impact) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommenderV1beta1Impact
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommenderV1beta1ListRecommendationsResponse: Response to
// the `ListRecommendations` method.
type GoogleCloudRecommenderV1beta1ListRecommendationsResponse struct {
	// NextPageToken: A token that can be used to request the next page of
	// results. This field is
	// empty if there are no additional results.
	NextPageToken string `json:"nextPageToken,omitempty"`

	// Recommendations: The set of recommendations for the `parent`
	// resource.
	Recommendations []*GoogleCloudRecommenderV1beta1Recommendation `json:"recommendations,omitempty"`

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

	// ForceSendFields is a list of field names (e.g. "NextPageToken") 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. "NextPageToken") 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 *GoogleCloudRecommenderV1beta1ListRecommendationsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommenderV1beta1ListRecommendationsResponse
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommenderV1beta1MarkRecommendationClaimedRequest:
// Request for the `MarkRecommendationClaimed` Method.
type GoogleCloudRecommenderV1beta1MarkRecommendationClaimedRequest struct {
	// Etag: Required. Fingerprint of the Recommendation. Provides
	// optimistic locking.
	Etag string `json:"etag,omitempty"`

	// StateMetadata: State properties to include with this state.
	// Overwrites any existing
	// `state_metadata`.
	// Keys must match the regex /^a-z0-9{0,62}$/.
	// Values must match the regex /^[a-zA-Z0-9_./-]{0,255}$/.
	StateMetadata map[string]string `json:"stateMetadata,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Etag") 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. "Etag") 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 *GoogleCloudRecommenderV1beta1MarkRecommendationClaimedRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommenderV1beta1MarkRecommendationClaimedRequest
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommenderV1beta1MarkRecommendationFailedRequest: Request
// for the `MarkRecommendationFailed` Method.
type GoogleCloudRecommenderV1beta1MarkRecommendationFailedRequest struct {
	// Etag: Fingerprint of the Recommendation. Provides optimistic locking.
	Etag string `json:"etag,omitempty"`

	// StateMetadata: State properties to include with this state.
	// Overwrites any existing
	// `state_metadata`.
	// Keys must match the regex /^a-z0-9{0,62}$/.
	// Values must match the regex /^[a-zA-Z0-9_./-]{0,255}$/.
	StateMetadata map[string]string `json:"stateMetadata,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Etag") 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. "Etag") 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 *GoogleCloudRecommenderV1beta1MarkRecommendationFailedRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommenderV1beta1MarkRecommendationFailedRequest
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommenderV1beta1MarkRecommendationSucceededRequest:
// Request for the `MarkRecommendationSucceeded` Method.
type GoogleCloudRecommenderV1beta1MarkRecommendationSucceededRequest struct {
	// Etag: Required. Fingerprint of the Recommendation. Provides
	// optimistic locking.
	Etag string `json:"etag,omitempty"`

	// StateMetadata: State properties to include with this state.
	// Overwrites any existing
	// `state_metadata`.
	// Keys must match the regex /^a-z0-9{0,62}$/.
	// Values must match the regex /^[a-zA-Z0-9_./-]{0,255}$/.
	StateMetadata map[string]string `json:"stateMetadata,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Etag") 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. "Etag") 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 *GoogleCloudRecommenderV1beta1MarkRecommendationSucceededRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommenderV1beta1MarkRecommendationSucceededRequest
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommenderV1beta1Operation: Contains an operation for a
// resource loosely based on the JSON-PATCH format
// with support for:
//
// * Custom filters for describing partial array patch.
// * Extended path values for describing nested arrays.
// * Custom fields for describing the resource for which the operation
// is being
//   described.
// * Allows extension to custom operations not natively supported by
// RFC6902.
// See https://tools.ietf.org/html/rfc6902 for details on the original
// RFC.
type GoogleCloudRecommenderV1beta1Operation struct {
	// Action: Type of this operation. Contains one of 'and', 'remove',
	// 'replace', 'move',
	// 'copy', 'test' and 'custom' operations. This field is
	// case-insensitive and
	// always populated.
	Action string `json:"action,omitempty"`

	// Path: Path to the target field being operated on. If the operation is
	// at the
	// resource level, then path should be "/". This field is always
	// populated.
	Path string `json:"path,omitempty"`

	// PathFilters: Set of filters to apply if `path` refers to array
	// elements or nested array
	// elements in order to narrow down to a single unique element that is
	// being
	// tested/modified.
	// This is intended to be an exact match per filter. To perform
	// advanced
	// matching, use path_value_matchers.
	//
	// * Example: {
	//   "/versions/*/name" : "it-123"
	//   "/versions/*/targetSize/percent": 20
	//   }
	// * Example: {
	//   "/bindings/*/role": "roles/admin"
	//   "/bindings/*/condition" : null
	//   }
	// * Example: {
	//   "/bindings/*/role": "roles/admin"
	//   "/bindings/*/members/*" : ["x@google.com", "y@google.com"]
	//   }
	// When both path_filters and path_value_matchers are set, an implicit
	// AND
	// must be performed.
	PathFilters googleapi.RawMessage `json:"pathFilters,omitempty"`

	// PathValueMatchers: Similar to path_filters, this contains set of
	// filters to apply if `path`
	// field referes to array elements. This is meant to support value
	// matching
	// beyond exact match. To perform exact match, use path_filters.
	// When both path_filters and path_value_matchers are set, an implicit
	// AND
	// must be performed.
	PathValueMatchers map[string]GoogleCloudRecommenderV1beta1ValueMatcher `json:"pathValueMatchers,omitempty"`

	// Resource: Contains the fully qualified resource name. This field is
	// always populated.
	// ex: //cloudresourcemanager.googleapis.com/projects/foo.
	Resource string `json:"resource,omitempty"`

	// ResourceType: Type of GCP resource being modified/tested. This field
	// is always populated.
	// Example:
	// cloudresourcemanager.googleapis.com/Project,
	// compute.googleapis.com/In
	// stance
	ResourceType string `json:"resourceType,omitempty"`

	// SourcePath: Can be set with action 'copy' or 'move' to indicate the
	// source field within
	// resource or source_resource, ignored if provided for other operation
	// types.
	SourcePath string `json:"sourcePath,omitempty"`

	// SourceResource: Can be set with action 'copy' to copy resource
	// configuration across
	// different resources of the same type. Example: A resource clone can
	// be
	// done via action = 'copy', path = "/", from = "/",
	// source_resource = <source> and resource_name = <target>.
	// This field is empty for all other values of `action`.
	SourceResource string `json:"sourceResource,omitempty"`

	// Value: Value for the `path` field. Will be set for
	// actions:'add'/'replace'.
	// Maybe set for action: 'test'. Either this or `value_matcher` will be
	// set
	// for 'test' operation. An exact match must be performed.
	Value interface{} `json:"value,omitempty"`

	// ValueMatcher: Can be set for action 'test' for advanced matching for
	// the value of
	// 'path' field. Either this or `value` will be set for 'test'
	// operation.
	ValueMatcher *GoogleCloudRecommenderV1beta1ValueMatcher `json:"valueMatcher,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Action") 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. "Action") 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 *GoogleCloudRecommenderV1beta1Operation) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommenderV1beta1Operation
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommenderV1beta1OperationGroup: Group of operations that
// need to be performed atomically.
type GoogleCloudRecommenderV1beta1OperationGroup struct {
	// Operations: List of operations across one or more resources that
	// belong to this group.
	// Loosely based on RFC6902 and should be performed in the order they
	// appear.
	Operations []*GoogleCloudRecommenderV1beta1Operation `json:"operations,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 *GoogleCloudRecommenderV1beta1OperationGroup) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommenderV1beta1OperationGroup
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommenderV1beta1Recommendation: A recommendation along
// with a suggested action. E.g., a rightsizing
// recommendation for an underutilized VM, IAM role recommendations, etc
type GoogleCloudRecommenderV1beta1Recommendation struct {
	// AdditionalImpact: Optional set of additional impact that this
	// recommendation may have when
	// trying to optimize for the primary category. These may be positive
	// or negative.
	AdditionalImpact []*GoogleCloudRecommenderV1beta1Impact `json:"additionalImpact,omitempty"`

	// Content: Content of the recommendation describing recommended changes
	// to resources.
	Content *GoogleCloudRecommenderV1beta1RecommendationContent `json:"content,omitempty"`

	// Description: Free-form human readable summary in English. The maximum
	// length is 500
	// characters.
	Description string `json:"description,omitempty"`

	// Etag: Fingerprint of the Recommendation. Provides optimistic locking
	// when
	// updating states.
	Etag string `json:"etag,omitempty"`

	// LastRefreshTime: Last time this recommendation was refreshed by the
	// system that created it
	// in the first place.
	LastRefreshTime string `json:"lastRefreshTime,omitempty"`

	// Name: Name of recommendation.
	Name string `json:"name,omitempty"`

	// PrimaryImpact: The primary impact that this recommendation can have
	// while trying to
	// optimize for one category.
	PrimaryImpact *GoogleCloudRecommenderV1beta1Impact `json:"primaryImpact,omitempty"`

	// RecommenderSubtype: Contains an identifier for a subtype of
	// recommendations produced for the
	// same recommender. Subtype is a function of content and impact,
	// meaning a
	// new subtype might be added when significant changes to `content`
	// or
	// `primary_impact.category` are introduced. See the Recommenders
	// section
	// to see a list of subtypes for a given Recommender.
	//
	// Examples:
	//   For recommender = "google.iam.policy.Recommender",
	//   recommender_subtype can be one of "REMOVE_ROLE"/"REPLACE_ROLE"
	RecommenderSubtype string `json:"recommenderSubtype,omitempty"`

	// StateInfo: Information for state. Contains state and metadata.
	StateInfo *GoogleCloudRecommenderV1beta1RecommendationStateInfo `json:"stateInfo,omitempty"`

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

	// ForceSendFields is a list of field names (e.g. "AdditionalImpact") 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. "AdditionalImpact") 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 *GoogleCloudRecommenderV1beta1Recommendation) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommenderV1beta1Recommendation
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommenderV1beta1RecommendationContent: Contains what
// resources are changing and how they are changing.
type GoogleCloudRecommenderV1beta1RecommendationContent struct {
	// OperationGroups: Operations to one or more Google Cloud resources
	// grouped in such a way
	// that, all operations within one group are expected to be
	// performed
	// atomically and in an order.
	OperationGroups []*GoogleCloudRecommenderV1beta1OperationGroup `json:"operationGroups,omitempty"`

	// ForceSendFields is a list of field names (e.g. "OperationGroups") 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. "OperationGroups") 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 *GoogleCloudRecommenderV1beta1RecommendationContent) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommenderV1beta1RecommendationContent
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommenderV1beta1RecommendationStateInfo: Information for
// state. Contains state and metadata.
type GoogleCloudRecommenderV1beta1RecommendationStateInfo struct {
	// State: The state of the recommendation, Eg ACTIVE, SUCCEEDED, FAILED.
	//
	// Possible values:
	//   "STATE_UNSPECIFIED" - Default state. Don't use directly.
	//   "ACTIVE" - Recommendation is active and can be applied.
	// Recommendations content can
	// be updated by Google.
	//
	// ACTIVE recommendations can be marked as CLAIMED, SUCCEEDED, or
	// FAILED.
	//   "CLAIMED" - Recommendation is in claimed state. Recommendations
	// content is
	// immutable and cannot be updated by Google.
	//
	// CLAIMED recommendations can be marked as CLAIMED, SUCCEEDED, or
	// FAILED.
	//   "SUCCEEDED" - Recommendation is in succeeded state. Recommendations
	// content is
	// immutable and cannot be updated by Google.
	//
	// SUCCEEDED recommendations can be marked as SUCCEEDED, or FAILED.
	//   "FAILED" - Recommendation is in failed state. Recommendations
	// content is immutable
	// and cannot be updated by Google.
	//
	// FAILED recommendations can be marked as SUCCEEDED, or FAILED.
	//   "DISMISSED" - Recommendation is in dismissed state. Recommendation
	// content can be
	// updated by Google.
	//
	// DISMISSED recommendations can be marked as ACTIVE.
	State string `json:"state,omitempty"`

	// StateMetadata: A map of metadata for the state, provided by user or
	// automations systems.
	StateMetadata map[string]string `json:"stateMetadata,omitempty"`

	// ForceSendFields is a list of field names (e.g. "State") 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. "State") 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 *GoogleCloudRecommenderV1beta1RecommendationStateInfo) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommenderV1beta1RecommendationStateInfo
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommenderV1beta1ValueMatcher: Contains various matching
// options for values for a GCP resource field.
type GoogleCloudRecommenderV1beta1ValueMatcher struct {
	// MatchesPattern: To be used for full regex matching. The regular
	// expression is using the
	// Google RE2 syntax (https://github.com/google/re2/wiki/Syntax), so to
	// be
	// used with RE2::FullMatch
	MatchesPattern string `json:"matchesPattern,omitempty"`

	// ForceSendFields is a list of field names (e.g. "MatchesPattern") 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. "MatchesPattern") 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 *GoogleCloudRecommenderV1beta1ValueMatcher) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommenderV1beta1ValueMatcher
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleTypeMoney: Represents an amount of money with its currency
// type.
type GoogleTypeMoney struct {
	// CurrencyCode: The 3-letter currency code defined in ISO 4217.
	CurrencyCode string `json:"currencyCode,omitempty"`

	// Nanos: Number of nano (10^-9) units of the amount.
	// The value must be between -999,999,999 and +999,999,999 inclusive.
	// If `units` is positive, `nanos` must be positive or zero.
	// If `units` is zero, `nanos` can be positive, zero, or negative.
	// If `units` is negative, `nanos` must be negative or zero.
	// For example $-1.75 is represented as `units`=-1 and
	// `nanos`=-750,000,000.
	Nanos int64 `json:"nanos,omitempty"`

	// Units: The whole units of the amount.
	// For example if `currencyCode` is "USD", then 1 unit is one US
	// dollar.
	Units int64 `json:"units,omitempty,string"`

	// ForceSendFields is a list of field names (e.g. "CurrencyCode") 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. "CurrencyCode") 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 *GoogleTypeMoney) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleTypeMoney
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// method id "recommender.projects.locations.recommenders.recommendations.get":

type ProjectsLocationsRecommendersRecommendationsGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Gets the requested recommendation. Requires the
// recommender.*.get
// IAM permission for the specified recommender.
func (r *ProjectsLocationsRecommendersRecommendationsService) Get(name string) *ProjectsLocationsRecommendersRecommendationsGetCall {
	c := &ProjectsLocationsRecommendersRecommendationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	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 *ProjectsLocationsRecommendersRecommendationsGetCall) Fields(s ...googleapi.Field) *ProjectsLocationsRecommendersRecommendationsGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets the optional parameter which makes the operation
// fail if the object's ETag matches the given value. This is useful for
// getting updates only after the object has changed since the last
// request. Use googleapi.IsNotModified to check whether the response
// error from Do is the result of In-None-Match.
func (c *ProjectsLocationsRecommendersRecommendationsGetCall) IfNoneMatch(entityTag string) *ProjectsLocationsRecommendersRecommendationsGetCall {
	c.ifNoneMatch_ = entityTag
	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 *ProjectsLocationsRecommendersRecommendationsGetCall) Context(ctx context.Context) *ProjectsLocationsRecommendersRecommendationsGetCall {
	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 *ProjectsLocationsRecommendersRecommendationsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsRecommendersRecommendationsGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200302")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommender.projects.locations.recommenders.recommendations.get" call.
// Exactly one of *GoogleCloudRecommenderV1beta1Recommendation or error
// will be non-nil. Any non-2xx status code is an error. Response
// headers are in either
// *GoogleCloudRecommenderV1beta1Recommendation.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 *ProjectsLocationsRecommendersRecommendationsGetCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecommenderV1beta1Recommendation, 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 := &GoogleCloudRecommenderV1beta1Recommendation{
		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": "Gets the requested recommendation. Requires the recommender.*.get\nIAM permission for the specified recommender.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/recommenders/{recommendersId}/recommendations/{recommendationsId}",
	//   "httpMethod": "GET",
	//   "id": "recommender.projects.locations.recommenders.recommendations.get",
	//   "parameterOrder": [
	//     "name"
	//   ],
	//   "parameters": {
	//     "name": {
	//       "description": "Required. Name of the recommendation.",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/recommenders/[^/]+/recommendations/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+name}",
	//   "response": {
	//     "$ref": "GoogleCloudRecommenderV1beta1Recommendation"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "recommender.projects.locations.recommenders.recommendations.list":

type ProjectsLocationsRecommendersRecommendationsListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists recommendations for a Cloud project. Requires the
// recommender.*.list
// IAM permission for the specified recommender.
func (r *ProjectsLocationsRecommendersRecommendationsService) List(parent string) *ProjectsLocationsRecommendersRecommendationsListCall {
	c := &ProjectsLocationsRecommendersRecommendationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// Filter sets the optional parameter "filter": Filter expression to
// restrict the recommendations returned. Supported
// filter fields: state_info.state
// Eg: `state_info.state:"DISMISSED" or state_info.state:"FAILED"
func (c *ProjectsLocationsRecommendersRecommendationsListCall) Filter(filter string) *ProjectsLocationsRecommendersRecommendationsListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

// PageSize sets the optional parameter "pageSize": The maximum number
// of results to return from this request.  Non-positive
// values are ignored. If not specified, the server will determine the
// number
// of results to return.
func (c *ProjectsLocationsRecommendersRecommendationsListCall) PageSize(pageSize int64) *ProjectsLocationsRecommendersRecommendationsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": If present,
// retrieves the next batch of results from the preceding call to
// this method. `page_token` must be the value of `next_page_token` from
// the
// previous response. The values of other method parameters must be
// identical
// to those in the previous call.
func (c *ProjectsLocationsRecommendersRecommendationsListCall) PageToken(pageToken string) *ProjectsLocationsRecommendersRecommendationsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	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 *ProjectsLocationsRecommendersRecommendationsListCall) Fields(s ...googleapi.Field) *ProjectsLocationsRecommendersRecommendationsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets the optional parameter which makes the operation
// fail if the object's ETag matches the given value. This is useful for
// getting updates only after the object has changed since the last
// request. Use googleapi.IsNotModified to check whether the response
// error from Do is the result of In-None-Match.
func (c *ProjectsLocationsRecommendersRecommendationsListCall) IfNoneMatch(entityTag string) *ProjectsLocationsRecommendersRecommendationsListCall {
	c.ifNoneMatch_ = entityTag
	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 *ProjectsLocationsRecommendersRecommendationsListCall) Context(ctx context.Context) *ProjectsLocationsRecommendersRecommendationsListCall {
	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 *ProjectsLocationsRecommendersRecommendationsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsRecommendersRecommendationsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200302")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+parent}/recommendations")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommender.projects.locations.recommenders.recommendations.list" call.
// Exactly one of
// *GoogleCloudRecommenderV1beta1ListRecommendationsResponse or error
// will be non-nil. Any non-2xx status code is an error. Response
// headers are in either
// *GoogleCloudRecommenderV1beta1ListRecommendationsResponse.ServerRespon
// se.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 *ProjectsLocationsRecommendersRecommendationsListCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecommenderV1beta1ListRecommendationsResponse, 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 := &GoogleCloudRecommenderV1beta1ListRecommendationsResponse{
		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": "Lists recommendations for a Cloud project. Requires the recommender.*.list\nIAM permission for the specified recommender.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/recommenders/{recommendersId}/recommendations",
	//   "httpMethod": "GET",
	//   "id": "recommender.projects.locations.recommenders.recommendations.list",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "filter": {
	//       "description": "Filter expression to restrict the recommendations returned. Supported\nfilter fields: state_info.state\nEg: `state_info.state:\"DISMISSED\" or state_info.state:\"FAILED\"",
	//       "location": "query",
	//       "type": "string"
	//     },
	//     "pageSize": {
	//       "description": "Optional. The maximum number of results to return from this request.  Non-positive\nvalues are ignored. If not specified, the server will determine the number\nof results to return.",
	//       "format": "int32",
	//       "location": "query",
	//       "type": "integer"
	//     },
	//     "pageToken": {
	//       "description": "Optional. If present, retrieves the next batch of results from the preceding call to\nthis method. `page_token` must be the value of `next_page_token` from the\nprevious response. The values of other method parameters must be identical\nto those in the previous call.",
	//       "location": "query",
	//       "type": "string"
	//     },
	//     "parent": {
	//       "description": "Required. The container resource on which to execute the request.\nAcceptable formats:\n\n1.\n\"projects/[PROJECT_NUMBER]/locations/[LOCATION]/recommenders/[RECOMMENDER_ID]\",\n\nLOCATION here refers to GCP Locations:\nhttps://cloud.google.com/about/locations/",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/recommenders/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+parent}/recommendations",
	//   "response": {
	//     "$ref": "GoogleCloudRecommenderV1beta1ListRecommendationsResponse"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsLocationsRecommendersRecommendationsListCall) Pages(ctx context.Context, f func(*GoogleCloudRecommenderV1beta1ListRecommendationsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

// method id "recommender.projects.locations.recommenders.recommendations.markClaimed":

type ProjectsLocationsRecommendersRecommendationsMarkClaimedCall struct {
	s                                                             *Service
	name                                                          string
	googlecloudrecommenderv1beta1markrecommendationclaimedrequest *GoogleCloudRecommenderV1beta1MarkRecommendationClaimedRequest
	urlParams_                                                    gensupport.URLParams
	ctx_                                                          context.Context
	header_                                                       http.Header
}

// MarkClaimed: Marks the Recommendation State as Claimed. Users can use
// this method to
// indicate to the Recommender API that they are starting to apply
// the
// recommendation themselves. This stops the recommendation content from
// being
// updated. Associated insights are frozen and placed in the ACCEPTED
// state.
//
// MarkRecommendationClaimed can be applied to recommendations in
// CLAIMED or
// ACTIVE state.
//
// Requires the recommender.*.update IAM permission for the
// specified
// recommender.
func (r *ProjectsLocationsRecommendersRecommendationsService) MarkClaimed(name string, googlecloudrecommenderv1beta1markrecommendationclaimedrequest *GoogleCloudRecommenderV1beta1MarkRecommendationClaimedRequest) *ProjectsLocationsRecommendersRecommendationsMarkClaimedCall {
	c := &ProjectsLocationsRecommendersRecommendationsMarkClaimedCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.googlecloudrecommenderv1beta1markrecommendationclaimedrequest = googlecloudrecommenderv1beta1markrecommendationclaimedrequest
	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 *ProjectsLocationsRecommendersRecommendationsMarkClaimedCall) Fields(s ...googleapi.Field) *ProjectsLocationsRecommendersRecommendationsMarkClaimedCall {
	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 *ProjectsLocationsRecommendersRecommendationsMarkClaimedCall) Context(ctx context.Context) *ProjectsLocationsRecommendersRecommendationsMarkClaimedCall {
	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 *ProjectsLocationsRecommendersRecommendationsMarkClaimedCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsRecommendersRecommendationsMarkClaimedCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200302")
	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.googlecloudrecommenderv1beta1markrecommendationclaimedrequest)
	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, "v1beta1/{+name}:markClaimed")
	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{
		"name": c.name,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommender.projects.locations.recommenders.recommendations.markClaimed" call.
// Exactly one of *GoogleCloudRecommenderV1beta1Recommendation or error
// will be non-nil. Any non-2xx status code is an error. Response
// headers are in either
// *GoogleCloudRecommenderV1beta1Recommendation.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 *ProjectsLocationsRecommendersRecommendationsMarkClaimedCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecommenderV1beta1Recommendation, 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 := &GoogleCloudRecommenderV1beta1Recommendation{
		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": "Marks the Recommendation State as Claimed. Users can use this method to\nindicate to the Recommender API that they are starting to apply the\nrecommendation themselves. This stops the recommendation content from being\nupdated. Associated insights are frozen and placed in the ACCEPTED state.\n\nMarkRecommendationClaimed can be applied to recommendations in CLAIMED or\nACTIVE state.\n\nRequires the recommender.*.update IAM permission for the specified\nrecommender.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/recommenders/{recommendersId}/recommendations/{recommendationsId}:markClaimed",
	//   "httpMethod": "POST",
	//   "id": "recommender.projects.locations.recommenders.recommendations.markClaimed",
	//   "parameterOrder": [
	//     "name"
	//   ],
	//   "parameters": {
	//     "name": {
	//       "description": "Required. Name of the recommendation.",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/recommenders/[^/]+/recommendations/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+name}:markClaimed",
	//   "request": {
	//     "$ref": "GoogleCloudRecommenderV1beta1MarkRecommendationClaimedRequest"
	//   },
	//   "response": {
	//     "$ref": "GoogleCloudRecommenderV1beta1Recommendation"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "recommender.projects.locations.recommenders.recommendations.markFailed":

type ProjectsLocationsRecommendersRecommendationsMarkFailedCall struct {
	s                                                            *Service
	name                                                         string
	googlecloudrecommenderv1beta1markrecommendationfailedrequest *GoogleCloudRecommenderV1beta1MarkRecommendationFailedRequest
	urlParams_                                                   gensupport.URLParams
	ctx_                                                         context.Context
	header_                                                      http.Header
}

// MarkFailed: Marks the Recommendation State as Failed. Users can use
// this method to
// indicate to the Recommender API that they have applied the
// recommendation
// themselves, and the operation failed. This stops the recommendation
// content
// from being updated. Associated insights are frozen and placed in
// the
// ACCEPTED state.
//
// MarkRecommendationFailed can be applied to recommendations in
// ACTIVE,
// CLAIMED, SUCCEEDED, or FAILED state.
//
// Requires the recommender.*.update IAM permission for the
// specified
// recommender.
func (r *ProjectsLocationsRecommendersRecommendationsService) MarkFailed(name string, googlecloudrecommenderv1beta1markrecommendationfailedrequest *GoogleCloudRecommenderV1beta1MarkRecommendationFailedRequest) *ProjectsLocationsRecommendersRecommendationsMarkFailedCall {
	c := &ProjectsLocationsRecommendersRecommendationsMarkFailedCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.googlecloudrecommenderv1beta1markrecommendationfailedrequest = googlecloudrecommenderv1beta1markrecommendationfailedrequest
	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 *ProjectsLocationsRecommendersRecommendationsMarkFailedCall) Fields(s ...googleapi.Field) *ProjectsLocationsRecommendersRecommendationsMarkFailedCall {
	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 *ProjectsLocationsRecommendersRecommendationsMarkFailedCall) Context(ctx context.Context) *ProjectsLocationsRecommendersRecommendationsMarkFailedCall {
	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 *ProjectsLocationsRecommendersRecommendationsMarkFailedCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsRecommendersRecommendationsMarkFailedCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200302")
	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.googlecloudrecommenderv1beta1markrecommendationfailedrequest)
	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, "v1beta1/{+name}:markFailed")
	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{
		"name": c.name,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommender.projects.locations.recommenders.recommendations.markFailed" call.
// Exactly one of *GoogleCloudRecommenderV1beta1Recommendation or error
// will be non-nil. Any non-2xx status code is an error. Response
// headers are in either
// *GoogleCloudRecommenderV1beta1Recommendation.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 *ProjectsLocationsRecommendersRecommendationsMarkFailedCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecommenderV1beta1Recommendation, 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 := &GoogleCloudRecommenderV1beta1Recommendation{
		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": "Marks the Recommendation State as Failed. Users can use this method to\nindicate to the Recommender API that they have applied the recommendation\nthemselves, and the operation failed. This stops the recommendation content\nfrom being updated. Associated insights are frozen and placed in the\nACCEPTED state.\n\nMarkRecommendationFailed can be applied to recommendations in ACTIVE,\nCLAIMED, SUCCEEDED, or FAILED state.\n\nRequires the recommender.*.update IAM permission for the specified\nrecommender.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/recommenders/{recommendersId}/recommendations/{recommendationsId}:markFailed",
	//   "httpMethod": "POST",
	//   "id": "recommender.projects.locations.recommenders.recommendations.markFailed",
	//   "parameterOrder": [
	//     "name"
	//   ],
	//   "parameters": {
	//     "name": {
	//       "description": "Required. Name of the recommendation.",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/recommenders/[^/]+/recommendations/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+name}:markFailed",
	//   "request": {
	//     "$ref": "GoogleCloudRecommenderV1beta1MarkRecommendationFailedRequest"
	//   },
	//   "response": {
	//     "$ref": "GoogleCloudRecommenderV1beta1Recommendation"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "recommender.projects.locations.recommenders.recommendations.markSucceeded":

type ProjectsLocationsRecommendersRecommendationsMarkSucceededCall struct {
	s                                                               *Service
	name                                                            string
	googlecloudrecommenderv1beta1markrecommendationsucceededrequest *GoogleCloudRecommenderV1beta1MarkRecommendationSucceededRequest
	urlParams_                                                      gensupport.URLParams
	ctx_                                                            context.Context
	header_                                                         http.Header
}

// MarkSucceeded: Marks the Recommendation State as Succeeded. Users can
// use this method to
// indicate to the Recommender API that they have applied the
// recommendation
// themselves, and the operation was successful. This stops the
// recommendation
// content from being updated. Associated insights are frozen and placed
// in
// the ACCEPTED state.
//
// MarkRecommendationSucceeded can be applied to recommendations in
// ACTIVE,
// CLAIMED, SUCCEEDED, or FAILED state.
//
// Requires the recommender.*.update IAM permission for the
// specified
// recommender.
func (r *ProjectsLocationsRecommendersRecommendationsService) MarkSucceeded(name string, googlecloudrecommenderv1beta1markrecommendationsucceededrequest *GoogleCloudRecommenderV1beta1MarkRecommendationSucceededRequest) *ProjectsLocationsRecommendersRecommendationsMarkSucceededCall {
	c := &ProjectsLocationsRecommendersRecommendationsMarkSucceededCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.googlecloudrecommenderv1beta1markrecommendationsucceededrequest = googlecloudrecommenderv1beta1markrecommendationsucceededrequest
	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 *ProjectsLocationsRecommendersRecommendationsMarkSucceededCall) Fields(s ...googleapi.Field) *ProjectsLocationsRecommendersRecommendationsMarkSucceededCall {
	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 *ProjectsLocationsRecommendersRecommendationsMarkSucceededCall) Context(ctx context.Context) *ProjectsLocationsRecommendersRecommendationsMarkSucceededCall {
	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 *ProjectsLocationsRecommendersRecommendationsMarkSucceededCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsRecommendersRecommendationsMarkSucceededCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200302")
	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.googlecloudrecommenderv1beta1markrecommendationsucceededrequest)
	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, "v1beta1/{+name}:markSucceeded")
	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{
		"name": c.name,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommender.projects.locations.recommenders.recommendations.markSucceeded" call.
// Exactly one of *GoogleCloudRecommenderV1beta1Recommendation or error
// will be non-nil. Any non-2xx status code is an error. Response
// headers are in either
// *GoogleCloudRecommenderV1beta1Recommendation.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 *ProjectsLocationsRecommendersRecommendationsMarkSucceededCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecommenderV1beta1Recommendation, 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 := &GoogleCloudRecommenderV1beta1Recommendation{
		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": "Marks the Recommendation State as Succeeded. Users can use this method to\nindicate to the Recommender API that they have applied the recommendation\nthemselves, and the operation was successful. This stops the recommendation\ncontent from being updated. Associated insights are frozen and placed in\nthe ACCEPTED state.\n\nMarkRecommendationSucceeded can be applied to recommendations in ACTIVE,\nCLAIMED, SUCCEEDED, or FAILED state.\n\nRequires the recommender.*.update IAM permission for the specified\nrecommender.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/recommenders/{recommendersId}/recommendations/{recommendationsId}:markSucceeded",
	//   "httpMethod": "POST",
	//   "id": "recommender.projects.locations.recommenders.recommendations.markSucceeded",
	//   "parameterOrder": [
	//     "name"
	//   ],
	//   "parameters": {
	//     "name": {
	//       "description": "Required. Name of the recommendation.",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/recommenders/[^/]+/recommendations/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+name}:markSucceeded",
	//   "request": {
	//     "$ref": "GoogleCloudRecommenderV1beta1MarkRecommendationSucceededRequest"
	//   },
	//   "response": {
	//     "$ref": "GoogleCloudRecommenderV1beta1Recommendation"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}
