package deploymentmanager

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
//
// Code generated by Microsoft (R) AutoRest Code Generator.
// Changes may cause incorrect behavior and will be lost if the code is regenerated.

import (
	"context"
	"encoding/json"
	"github.com/Azure/go-autorest/autorest"
	"github.com/Azure/go-autorest/autorest/azure"
	"github.com/Azure/go-autorest/autorest/date"
	"net/http"
)

// The package's fully qualified name.
const fqdn = "github.com/Azure/azure-sdk-for-go/services/preview/deploymentmanager/mgmt/2019-11-01-preview/deploymentmanager"

// APIKeyAuthentication apiKey authentication gives a name and a value that can be included in either the
// request header or query parameters.
type APIKeyAuthentication struct {
	// Name - The key name of the authentication key/value pair.
	Name *string `json:"name,omitempty"`
	// In - The location of the authentication key/value pair in the request. Possible values include: 'Query', 'Header'
	In RestAuthLocation `json:"in,omitempty"`
	// Value - The value of the authentication key/value pair.
	Value *string `json:"value,omitempty"`
	// Type - Possible values include: 'TypeRestRequestAuthentication', 'TypeRolloutIdentity', 'TypeAPIKey'
	Type TypeBasicRestRequestAuthentication `json:"type,omitempty"`
}

// MarshalJSON is the custom marshaler for APIKeyAuthentication.
func (aka APIKeyAuthentication) MarshalJSON() ([]byte, error) {
	aka.Type = TypeAPIKey
	objectMap := make(map[string]interface{})
	if aka.Name != nil {
		objectMap["name"] = aka.Name
	}
	if aka.In != "" {
		objectMap["in"] = aka.In
	}
	if aka.Value != nil {
		objectMap["value"] = aka.Value
	}
	if aka.Type != "" {
		objectMap["type"] = aka.Type
	}
	return json.Marshal(objectMap)
}

// AsRolloutIdentityAuthentication is the BasicRestRequestAuthentication implementation for APIKeyAuthentication.
func (aka APIKeyAuthentication) AsRolloutIdentityAuthentication() (*RolloutIdentityAuthentication, bool) {
	return nil, false
}

// AsAPIKeyAuthentication is the BasicRestRequestAuthentication implementation for APIKeyAuthentication.
func (aka APIKeyAuthentication) AsAPIKeyAuthentication() (*APIKeyAuthentication, bool) {
	return &aka, true
}

// AsRestRequestAuthentication is the BasicRestRequestAuthentication implementation for APIKeyAuthentication.
func (aka APIKeyAuthentication) AsRestRequestAuthentication() (*RestRequestAuthentication, bool) {
	return nil, false
}

// AsBasicRestRequestAuthentication is the BasicRestRequestAuthentication implementation for APIKeyAuthentication.
func (aka APIKeyAuthentication) AsBasicRestRequestAuthentication() (BasicRestRequestAuthentication, bool) {
	return &aka, true
}

// ArtifactSource the resource that defines the source location where the artifacts are located.
type ArtifactSource struct {
	autorest.Response `json:"-"`
	// ArtifactSourceProperties - The properties that define the artifact source.
	*ArtifactSourceProperties `json:"properties,omitempty"`
	// Tags - Resource tags.
	Tags map[string]*string `json:"tags"`
	// Location - The geo-location where the resource lives
	Location *string `json:"location,omitempty"`
	// ID - READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}
	ID *string `json:"id,omitempty"`
	// Name - READ-ONLY; The name of the resource
	Name *string `json:"name,omitempty"`
	// Type - READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts"
	Type *string `json:"type,omitempty"`
}

// MarshalJSON is the custom marshaler for ArtifactSource.
func (as ArtifactSource) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if as.ArtifactSourceProperties != nil {
		objectMap["properties"] = as.ArtifactSourceProperties
	}
	if as.Tags != nil {
		objectMap["tags"] = as.Tags
	}
	if as.Location != nil {
		objectMap["location"] = as.Location
	}
	return json.Marshal(objectMap)
}

// UnmarshalJSON is the custom unmarshaler for ArtifactSource struct.
func (as *ArtifactSource) UnmarshalJSON(body []byte) error {
	var m map[string]*json.RawMessage
	err := json.Unmarshal(body, &m)
	if err != nil {
		return err
	}
	for k, v := range m {
		switch k {
		case "properties":
			if v != nil {
				var artifactSourceProperties ArtifactSourceProperties
				err = json.Unmarshal(*v, &artifactSourceProperties)
				if err != nil {
					return err
				}
				as.ArtifactSourceProperties = &artifactSourceProperties
			}
		case "tags":
			if v != nil {
				var tags map[string]*string
				err = json.Unmarshal(*v, &tags)
				if err != nil {
					return err
				}
				as.Tags = tags
			}
		case "location":
			if v != nil {
				var location string
				err = json.Unmarshal(*v, &location)
				if err != nil {
					return err
				}
				as.Location = &location
			}
		case "id":
			if v != nil {
				var ID string
				err = json.Unmarshal(*v, &ID)
				if err != nil {
					return err
				}
				as.ID = &ID
			}
		case "name":
			if v != nil {
				var name string
				err = json.Unmarshal(*v, &name)
				if err != nil {
					return err
				}
				as.Name = &name
			}
		case "type":
			if v != nil {
				var typeVar string
				err = json.Unmarshal(*v, &typeVar)
				if err != nil {
					return err
				}
				as.Type = &typeVar
			}
		}
	}

	return nil
}

// ArtifactSourceProperties the properties that define the artifact source.
type ArtifactSourceProperties struct {
	// SourceType - The type of artifact source used.
	SourceType *string `json:"sourceType,omitempty"`
	// ArtifactRoot - The path from the location that the 'authentication' property [say, a SAS URI to the blob container] refers to, to the location of the artifacts. This can be used to differentiate different versions of the artifacts. Or, different types of artifacts like binaries or templates. The location referenced by the authentication property concatenated with this optional artifactRoot path forms the artifact source location where the artifacts are expected to be found.
	ArtifactRoot *string `json:"artifactRoot,omitempty"`
	// Authentication - The authentication method to use to access the artifact source.
	Authentication BasicAuthentication `json:"authentication,omitempty"`
}

// UnmarshalJSON is the custom unmarshaler for ArtifactSourceProperties struct.
func (as *ArtifactSourceProperties) UnmarshalJSON(body []byte) error {
	var m map[string]*json.RawMessage
	err := json.Unmarshal(body, &m)
	if err != nil {
		return err
	}
	for k, v := range m {
		switch k {
		case "sourceType":
			if v != nil {
				var sourceType string
				err = json.Unmarshal(*v, &sourceType)
				if err != nil {
					return err
				}
				as.SourceType = &sourceType
			}
		case "artifactRoot":
			if v != nil {
				var artifactRoot string
				err = json.Unmarshal(*v, &artifactRoot)
				if err != nil {
					return err
				}
				as.ArtifactRoot = &artifactRoot
			}
		case "authentication":
			if v != nil {
				authentication, err := unmarshalBasicAuthentication(*v)
				if err != nil {
					return err
				}
				as.Authentication = authentication
			}
		}
	}

	return nil
}

// ArtifactSourcePropertiesModel the properties that define the source location where the artifacts are
// located.
type ArtifactSourcePropertiesModel struct {
	// SourceType - The type of artifact source used.
	SourceType *string `json:"sourceType,omitempty"`
	// ArtifactRoot - The path from the location that the 'authentication' property [say, a SAS URI to the blob container] refers to, to the location of the artifacts. This can be used to differentiate different versions of the artifacts. Or, different types of artifacts like binaries or templates. The location referenced by the authentication property concatenated with this optional artifactRoot path forms the artifact source location where the artifacts are expected to be found.
	ArtifactRoot *string `json:"artifactRoot,omitempty"`
	// Authentication - The authentication method to use to access the artifact source.
	Authentication BasicAuthentication `json:"authentication,omitempty"`
}

// UnmarshalJSON is the custom unmarshaler for ArtifactSourcePropertiesModel struct.
func (aspm *ArtifactSourcePropertiesModel) UnmarshalJSON(body []byte) error {
	var m map[string]*json.RawMessage
	err := json.Unmarshal(body, &m)
	if err != nil {
		return err
	}
	for k, v := range m {
		switch k {
		case "sourceType":
			if v != nil {
				var sourceType string
				err = json.Unmarshal(*v, &sourceType)
				if err != nil {
					return err
				}
				aspm.SourceType = &sourceType
			}
		case "artifactRoot":
			if v != nil {
				var artifactRoot string
				err = json.Unmarshal(*v, &artifactRoot)
				if err != nil {
					return err
				}
				aspm.ArtifactRoot = &artifactRoot
			}
		case "authentication":
			if v != nil {
				authentication, err := unmarshalBasicAuthentication(*v)
				if err != nil {
					return err
				}
				aspm.Authentication = authentication
			}
		}
	}

	return nil
}

// BasicAuthentication defines the authentication method and properties to access the artifacts.
type BasicAuthentication interface {
	AsSasAuthentication() (*SasAuthentication, bool)
	AsAuthentication() (*Authentication, bool)
}

// Authentication defines the authentication method and properties to access the artifacts.
type Authentication struct {
	// Type - Possible values include: 'TypeAuthentication', 'TypeSas'
	Type Type `json:"type,omitempty"`
}

func unmarshalBasicAuthentication(body []byte) (BasicAuthentication, error) {
	var m map[string]interface{}
	err := json.Unmarshal(body, &m)
	if err != nil {
		return nil, err
	}

	switch m["type"] {
	case string(TypeSas):
		var sa SasAuthentication
		err := json.Unmarshal(body, &sa)
		return sa, err
	default:
		var a Authentication
		err := json.Unmarshal(body, &a)
		return a, err
	}
}
func unmarshalBasicAuthenticationArray(body []byte) ([]BasicAuthentication, error) {
	var rawMessages []*json.RawMessage
	err := json.Unmarshal(body, &rawMessages)
	if err != nil {
		return nil, err
	}

	aArray := make([]BasicAuthentication, len(rawMessages))

	for index, rawMessage := range rawMessages {
		a, err := unmarshalBasicAuthentication(*rawMessage)
		if err != nil {
			return nil, err
		}
		aArray[index] = a
	}
	return aArray, nil
}

// MarshalJSON is the custom marshaler for Authentication.
func (a Authentication) MarshalJSON() ([]byte, error) {
	a.Type = TypeAuthentication
	objectMap := make(map[string]interface{})
	if a.Type != "" {
		objectMap["type"] = a.Type
	}
	return json.Marshal(objectMap)
}

// AsSasAuthentication is the BasicAuthentication implementation for Authentication.
func (a Authentication) AsSasAuthentication() (*SasAuthentication, bool) {
	return nil, false
}

// AsAuthentication is the BasicAuthentication implementation for Authentication.
func (a Authentication) AsAuthentication() (*Authentication, bool) {
	return &a, true
}

// AsBasicAuthentication is the BasicAuthentication implementation for Authentication.
func (a Authentication) AsBasicAuthentication() (BasicAuthentication, bool) {
	return &a, true
}

// AzureEntityResource the resource model definition for an Azure Resource Manager resource with an etag.
type AzureEntityResource struct {
	// Etag - READ-ONLY; Resource Etag.
	Etag *string `json:"etag,omitempty"`
	// ID - READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}
	ID *string `json:"id,omitempty"`
	// Name - READ-ONLY; The name of the resource
	Name *string `json:"name,omitempty"`
	// Type - READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts"
	Type *string `json:"type,omitempty"`
}

// MarshalJSON is the custom marshaler for AzureEntityResource.
func (aer AzureEntityResource) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	return json.Marshal(objectMap)
}

// CloudError the error information object.
type CloudError struct {
	// Error - The properties that define the error.
	Error *CloudErrorBody `json:"error,omitempty"`
}

// CloudErrorBody detailed error information of any failure.
type CloudErrorBody struct {
	// Code - READ-ONLY; Error code string.
	Code *string `json:"code,omitempty"`
	// Message - READ-ONLY; Descriptive error information.
	Message *string `json:"message,omitempty"`
	// Target - Error target
	Target *string `json:"target,omitempty"`
	// Details - More detailed error information.
	Details *[]CloudErrorBody `json:"details,omitempty"`
}

// MarshalJSON is the custom marshaler for CloudErrorBody.
func (ceb CloudErrorBody) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if ceb.Target != nil {
		objectMap["target"] = ceb.Target
	}
	if ceb.Details != nil {
		objectMap["details"] = ceb.Details
	}
	return json.Marshal(objectMap)
}

// BasicHealthCheckStepAttributes the attributes for the health check step.
type BasicHealthCheckStepAttributes interface {
	AsRestHealthCheckStepAttributes() (*RestHealthCheckStepAttributes, bool)
	AsHealthCheckStepAttributes() (*HealthCheckStepAttributes, bool)
}

// HealthCheckStepAttributes the attributes for the health check step.
type HealthCheckStepAttributes struct {
	// WaitDuration - The duration in ISO 8601 format for which health check waits idly without any checks.
	WaitDuration *string `json:"waitDuration,omitempty"`
	// MaxElasticDuration - The duration in ISO 8601 format for which the health check waits for the resource to become healthy. Health check fails if it doesn't. Health check starts to enforce healthyStateDuration once resource becomes healthy.
	MaxElasticDuration *string `json:"maxElasticDuration,omitempty"`
	// HealthyStateDuration - The duration in ISO 8601 format for which the resource is expected to be continuously healthy. If maxElasticDuration is specified, healthy state duration is enforced after the detection of first healthy signal.
	HealthyStateDuration *string `json:"healthyStateDuration,omitempty"`
	// Type - Possible values include: 'TypeHealthCheckStepAttributes', 'TypeREST'
	Type TypeBasicHealthCheckStepAttributes `json:"type,omitempty"`
}

func unmarshalBasicHealthCheckStepAttributes(body []byte) (BasicHealthCheckStepAttributes, error) {
	var m map[string]interface{}
	err := json.Unmarshal(body, &m)
	if err != nil {
		return nil, err
	}

	switch m["type"] {
	case string(TypeREST):
		var rhcsa RestHealthCheckStepAttributes
		err := json.Unmarshal(body, &rhcsa)
		return rhcsa, err
	default:
		var hcsa HealthCheckStepAttributes
		err := json.Unmarshal(body, &hcsa)
		return hcsa, err
	}
}
func unmarshalBasicHealthCheckStepAttributesArray(body []byte) ([]BasicHealthCheckStepAttributes, error) {
	var rawMessages []*json.RawMessage
	err := json.Unmarshal(body, &rawMessages)
	if err != nil {
		return nil, err
	}

	hcsaArray := make([]BasicHealthCheckStepAttributes, len(rawMessages))

	for index, rawMessage := range rawMessages {
		hcsa, err := unmarshalBasicHealthCheckStepAttributes(*rawMessage)
		if err != nil {
			return nil, err
		}
		hcsaArray[index] = hcsa
	}
	return hcsaArray, nil
}

// MarshalJSON is the custom marshaler for HealthCheckStepAttributes.
func (hcsa HealthCheckStepAttributes) MarshalJSON() ([]byte, error) {
	hcsa.Type = TypeHealthCheckStepAttributes
	objectMap := make(map[string]interface{})
	if hcsa.WaitDuration != nil {
		objectMap["waitDuration"] = hcsa.WaitDuration
	}
	if hcsa.MaxElasticDuration != nil {
		objectMap["maxElasticDuration"] = hcsa.MaxElasticDuration
	}
	if hcsa.HealthyStateDuration != nil {
		objectMap["healthyStateDuration"] = hcsa.HealthyStateDuration
	}
	if hcsa.Type != "" {
		objectMap["type"] = hcsa.Type
	}
	return json.Marshal(objectMap)
}

// AsRestHealthCheckStepAttributes is the BasicHealthCheckStepAttributes implementation for HealthCheckStepAttributes.
func (hcsa HealthCheckStepAttributes) AsRestHealthCheckStepAttributes() (*RestHealthCheckStepAttributes, bool) {
	return nil, false
}

// AsHealthCheckStepAttributes is the BasicHealthCheckStepAttributes implementation for HealthCheckStepAttributes.
func (hcsa HealthCheckStepAttributes) AsHealthCheckStepAttributes() (*HealthCheckStepAttributes, bool) {
	return &hcsa, true
}

// AsBasicHealthCheckStepAttributes is the BasicHealthCheckStepAttributes implementation for HealthCheckStepAttributes.
func (hcsa HealthCheckStepAttributes) AsBasicHealthCheckStepAttributes() (BasicHealthCheckStepAttributes, bool) {
	return &hcsa, true
}

// HealthCheckStepProperties defines the properties of a health check step.
type HealthCheckStepProperties struct {
	// Attributes - The health check step attributes
	Attributes BasicHealthCheckStepAttributes `json:"attributes,omitempty"`
	// StepType - Possible values include: 'StepTypeStepProperties', 'StepTypeHealthCheck', 'StepTypeWait'
	StepType StepType `json:"stepType,omitempty"`
}

// MarshalJSON is the custom marshaler for HealthCheckStepProperties.
func (hcsp HealthCheckStepProperties) MarshalJSON() ([]byte, error) {
	hcsp.StepType = StepTypeHealthCheck
	objectMap := make(map[string]interface{})
	objectMap["attributes"] = hcsp.Attributes
	if hcsp.StepType != "" {
		objectMap["stepType"] = hcsp.StepType
	}
	return json.Marshal(objectMap)
}

// AsHealthCheckStepProperties is the BasicStepProperties implementation for HealthCheckStepProperties.
func (hcsp HealthCheckStepProperties) AsHealthCheckStepProperties() (*HealthCheckStepProperties, bool) {
	return &hcsp, true
}

// AsWaitStepProperties is the BasicStepProperties implementation for HealthCheckStepProperties.
func (hcsp HealthCheckStepProperties) AsWaitStepProperties() (*WaitStepProperties, bool) {
	return nil, false
}

// AsStepProperties is the BasicStepProperties implementation for HealthCheckStepProperties.
func (hcsp HealthCheckStepProperties) AsStepProperties() (*StepProperties, bool) {
	return nil, false
}

// AsBasicStepProperties is the BasicStepProperties implementation for HealthCheckStepProperties.
func (hcsp HealthCheckStepProperties) AsBasicStepProperties() (BasicStepProperties, bool) {
	return &hcsp, true
}

// UnmarshalJSON is the custom unmarshaler for HealthCheckStepProperties struct.
func (hcsp *HealthCheckStepProperties) UnmarshalJSON(body []byte) error {
	var m map[string]*json.RawMessage
	err := json.Unmarshal(body, &m)
	if err != nil {
		return err
	}
	for k, v := range m {
		switch k {
		case "attributes":
			if v != nil {
				attributes, err := unmarshalBasicHealthCheckStepAttributes(*v)
				if err != nil {
					return err
				}
				hcsp.Attributes = attributes
			}
		case "stepType":
			if v != nil {
				var stepType StepType
				err = json.Unmarshal(*v, &stepType)
				if err != nil {
					return err
				}
				hcsp.StepType = stepType
			}
		}
	}

	return nil
}

// Identity identity for the resource.
type Identity struct {
	// Type - The identity type.
	Type *string `json:"type,omitempty"`
	// IdentityIds - The list of identities.
	IdentityIds *[]string `json:"identityIds,omitempty"`
}

// ListArtifactSource ...
type ListArtifactSource struct {
	autorest.Response `json:"-"`
	Value             *[]ArtifactSource `json:"value,omitempty"`
}

// ListRollout ...
type ListRollout struct {
	autorest.Response `json:"-"`
	Value             *[]Rollout `json:"value,omitempty"`
}

// ListServiceResource ...
type ListServiceResource struct {
	autorest.Response `json:"-"`
	Value             *[]ServiceResource `json:"value,omitempty"`
}

// ListServiceTopologyResource ...
type ListServiceTopologyResource struct {
	autorest.Response `json:"-"`
	Value             *[]ServiceTopologyResource `json:"value,omitempty"`
}

// ListServiceUnitResource ...
type ListServiceUnitResource struct {
	autorest.Response `json:"-"`
	Value             *[]ServiceUnitResource `json:"value,omitempty"`
}

// ListStepResource ...
type ListStepResource struct {
	autorest.Response `json:"-"`
	Value             *[]StepResource `json:"value,omitempty"`
}

// Message supplementary contextual messages during a rollout.
type Message struct {
	// TimeStamp - READ-ONLY; Time in UTC this message was provided.
	TimeStamp *date.Time `json:"timeStamp,omitempty"`
	// Message - READ-ONLY; The actual message text.
	Message *string `json:"message,omitempty"`
}

// MarshalJSON is the custom marshaler for Message.
func (mVar Message) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	return json.Marshal(objectMap)
}

// Operation represents an operation that can be performed on the service.
type Operation struct {
	// Name - The name of the operation.
	Name *string `json:"name,omitempty"`
	// Display - The display name of the operation.
	Display *OperationDetail `json:"display,omitempty"`
	// Origin - The origin of the operation.
	Origin *string `json:"origin,omitempty"`
	// Properties - The properties of the operation.
	Properties interface{} `json:"properties,omitempty"`
}

// OperationDetail the detail about an operation.
type OperationDetail struct {
	// Provider - The name of the provider that supports the operation.
	Provider *string `json:"provider,omitempty"`
	// Resource - The resource type on which this operation can be performed.
	Resource *string `json:"resource,omitempty"`
	// Operation - The name of the operation.
	Operation *string `json:"operation,omitempty"`
	// Description - The description of the operation.
	Description *string `json:"description,omitempty"`
}

// OperationsList the operations response.
type OperationsList struct {
	autorest.Response `json:"-"`
	// Value - The list of supported operations
	Value *Operation `json:"value,omitempty"`
}

// PrePostStep the properties that define a step.
type PrePostStep struct {
	// StepID - The resource Id of the step to be run.
	StepID *string `json:"stepId,omitempty"`
}

// ProxyResource the resource model definition for a Azure Resource Manager proxy resource. It will not
// have tags and a location
type ProxyResource struct {
	// ID - READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}
	ID *string `json:"id,omitempty"`
	// Name - READ-ONLY; The name of the resource
	Name *string `json:"name,omitempty"`
	// Type - READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts"
	Type *string `json:"type,omitempty"`
}

// MarshalJSON is the custom marshaler for ProxyResource.
func (pr ProxyResource) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	return json.Marshal(objectMap)
}

// Resource common fields that are returned in the response for all Azure Resource Manager resources
type Resource struct {
	// ID - READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}
	ID *string `json:"id,omitempty"`
	// Name - READ-ONLY; The name of the resource
	Name *string `json:"name,omitempty"`
	// Type - READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts"
	Type *string `json:"type,omitempty"`
}

// MarshalJSON is the custom marshaler for Resource.
func (r Resource) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	return json.Marshal(objectMap)
}

// ResourceOperation individual resource operation information.
type ResourceOperation struct {
	// ResourceName - Name of the resource as specified in the artifacts. For ARM resources, this is the name of the resource specified in the template.
	ResourceName *string `json:"resourceName,omitempty"`
	// OperationID - READ-ONLY; Unique identifier of the operation. For ARM resources, this is the operationId obtained from ARM service.
	OperationID *string `json:"operationId,omitempty"`
	// ResourceType - Type of the resource as specified in the artifacts. For ARM resources, this is the type of the resource specified in the template.
	ResourceType *string `json:"resourceType,omitempty"`
	// ProvisioningState - READ-ONLY; State of the resource deployment. For ARM resources, this is the current provisioning state of the resource.
	ProvisioningState *string `json:"provisioningState,omitempty"`
	// StatusMessage - READ-ONLY; Descriptive information of the resource operation.
	StatusMessage *string `json:"statusMessage,omitempty"`
	// StatusCode - READ-ONLY; Http status code of the operation.
	StatusCode *string `json:"statusCode,omitempty"`
}

// MarshalJSON is the custom marshaler for ResourceOperation.
func (ro ResourceOperation) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if ro.ResourceName != nil {
		objectMap["resourceName"] = ro.ResourceName
	}
	if ro.ResourceType != nil {
		objectMap["resourceType"] = ro.ResourceType
	}
	return json.Marshal(objectMap)
}

// RestHealthCheck a REST based health check
type RestHealthCheck struct {
	// Name - A unique name for this check.
	Name *string `json:"name,omitempty"`
	// Request - The request to the health provider.
	Request *RestRequest `json:"request,omitempty"`
	// Response - The expected response from the health provider. If no expected response is provided, the default is to expect the received response to have an HTTP status code of 200 OK.
	Response *RestResponse `json:"response,omitempty"`
}

// RestHealthCheckStepAttributes defines the REST health check step properties.
type RestHealthCheckStepAttributes struct {
	// RestParameters - The REST health check parameters.
	*RestParameters `json:"properties,omitempty"`
	// WaitDuration - The duration in ISO 8601 format for which health check waits idly without any checks.
	WaitDuration *string `json:"waitDuration,omitempty"`
	// MaxElasticDuration - The duration in ISO 8601 format for which the health check waits for the resource to become healthy. Health check fails if it doesn't. Health check starts to enforce healthyStateDuration once resource becomes healthy.
	MaxElasticDuration *string `json:"maxElasticDuration,omitempty"`
	// HealthyStateDuration - The duration in ISO 8601 format for which the resource is expected to be continuously healthy. If maxElasticDuration is specified, healthy state duration is enforced after the detection of first healthy signal.
	HealthyStateDuration *string `json:"healthyStateDuration,omitempty"`
	// Type - Possible values include: 'TypeHealthCheckStepAttributes', 'TypeREST'
	Type TypeBasicHealthCheckStepAttributes `json:"type,omitempty"`
}

// MarshalJSON is the custom marshaler for RestHealthCheckStepAttributes.
func (rhcsa RestHealthCheckStepAttributes) MarshalJSON() ([]byte, error) {
	rhcsa.Type = TypeREST
	objectMap := make(map[string]interface{})
	if rhcsa.RestParameters != nil {
		objectMap["properties"] = rhcsa.RestParameters
	}
	if rhcsa.WaitDuration != nil {
		objectMap["waitDuration"] = rhcsa.WaitDuration
	}
	if rhcsa.MaxElasticDuration != nil {
		objectMap["maxElasticDuration"] = rhcsa.MaxElasticDuration
	}
	if rhcsa.HealthyStateDuration != nil {
		objectMap["healthyStateDuration"] = rhcsa.HealthyStateDuration
	}
	if rhcsa.Type != "" {
		objectMap["type"] = rhcsa.Type
	}
	return json.Marshal(objectMap)
}

// AsRestHealthCheckStepAttributes is the BasicHealthCheckStepAttributes implementation for RestHealthCheckStepAttributes.
func (rhcsa RestHealthCheckStepAttributes) AsRestHealthCheckStepAttributes() (*RestHealthCheckStepAttributes, bool) {
	return &rhcsa, true
}

// AsHealthCheckStepAttributes is the BasicHealthCheckStepAttributes implementation for RestHealthCheckStepAttributes.
func (rhcsa RestHealthCheckStepAttributes) AsHealthCheckStepAttributes() (*HealthCheckStepAttributes, bool) {
	return nil, false
}

// AsBasicHealthCheckStepAttributes is the BasicHealthCheckStepAttributes implementation for RestHealthCheckStepAttributes.
func (rhcsa RestHealthCheckStepAttributes) AsBasicHealthCheckStepAttributes() (BasicHealthCheckStepAttributes, bool) {
	return &rhcsa, true
}

// UnmarshalJSON is the custom unmarshaler for RestHealthCheckStepAttributes struct.
func (rhcsa *RestHealthCheckStepAttributes) UnmarshalJSON(body []byte) error {
	var m map[string]*json.RawMessage
	err := json.Unmarshal(body, &m)
	if err != nil {
		return err
	}
	for k, v := range m {
		switch k {
		case "properties":
			if v != nil {
				var restParameters RestParameters
				err = json.Unmarshal(*v, &restParameters)
				if err != nil {
					return err
				}
				rhcsa.RestParameters = &restParameters
			}
		case "waitDuration":
			if v != nil {
				var waitDuration string
				err = json.Unmarshal(*v, &waitDuration)
				if err != nil {
					return err
				}
				rhcsa.WaitDuration = &waitDuration
			}
		case "maxElasticDuration":
			if v != nil {
				var maxElasticDuration string
				err = json.Unmarshal(*v, &maxElasticDuration)
				if err != nil {
					return err
				}
				rhcsa.MaxElasticDuration = &maxElasticDuration
			}
		case "healthyStateDuration":
			if v != nil {
				var healthyStateDuration string
				err = json.Unmarshal(*v, &healthyStateDuration)
				if err != nil {
					return err
				}
				rhcsa.HealthyStateDuration = &healthyStateDuration
			}
		case "type":
			if v != nil {
				var typeVar TypeBasicHealthCheckStepAttributes
				err = json.Unmarshal(*v, &typeVar)
				if err != nil {
					return err
				}
				rhcsa.Type = typeVar
			}
		}
	}

	return nil
}

// RestParameters the parameters for the REST health check.
type RestParameters struct {
	// HealthChecks - The list of checks that form the health check step.
	HealthChecks *[]RestHealthCheck `json:"healthChecks,omitempty"`
}

// RestRequest the properties that make up a REST request
type RestRequest struct {
	// Method - The HTTP method to use for the request. Possible values include: 'GET', 'POST'
	Method RestRequestMethod `json:"method,omitempty"`
	// URI - The HTTP URI to use for the request.
	URI *string `json:"uri,omitempty"`
	// Authentication - The authentication information required in the request to the health provider.
	Authentication BasicRestRequestAuthentication `json:"authentication,omitempty"`
}

// UnmarshalJSON is the custom unmarshaler for RestRequest struct.
func (rr *RestRequest) UnmarshalJSON(body []byte) error {
	var m map[string]*json.RawMessage
	err := json.Unmarshal(body, &m)
	if err != nil {
		return err
	}
	for k, v := range m {
		switch k {
		case "method":
			if v != nil {
				var method RestRequestMethod
				err = json.Unmarshal(*v, &method)
				if err != nil {
					return err
				}
				rr.Method = method
			}
		case "uri":
			if v != nil {
				var URI string
				err = json.Unmarshal(*v, &URI)
				if err != nil {
					return err
				}
				rr.URI = &URI
			}
		case "authentication":
			if v != nil {
				authentication, err := unmarshalBasicRestRequestAuthentication(*v)
				if err != nil {
					return err
				}
				rr.Authentication = authentication
			}
		}
	}

	return nil
}

// BasicRestRequestAuthentication the authentication information required in the REST health check request to the
// health provider.
type BasicRestRequestAuthentication interface {
	AsRolloutIdentityAuthentication() (*RolloutIdentityAuthentication, bool)
	AsAPIKeyAuthentication() (*APIKeyAuthentication, bool)
	AsRestRequestAuthentication() (*RestRequestAuthentication, bool)
}

// RestRequestAuthentication the authentication information required in the REST health check request to the
// health provider.
type RestRequestAuthentication struct {
	// Type - Possible values include: 'TypeRestRequestAuthentication', 'TypeRolloutIdentity', 'TypeAPIKey'
	Type TypeBasicRestRequestAuthentication `json:"type,omitempty"`
}

func unmarshalBasicRestRequestAuthentication(body []byte) (BasicRestRequestAuthentication, error) {
	var m map[string]interface{}
	err := json.Unmarshal(body, &m)
	if err != nil {
		return nil, err
	}

	switch m["type"] {
	case string(TypeRolloutIdentity):
		var ria RolloutIdentityAuthentication
		err := json.Unmarshal(body, &ria)
		return ria, err
	case string(TypeAPIKey):
		var aka APIKeyAuthentication
		err := json.Unmarshal(body, &aka)
		return aka, err
	default:
		var rra RestRequestAuthentication
		err := json.Unmarshal(body, &rra)
		return rra, err
	}
}
func unmarshalBasicRestRequestAuthenticationArray(body []byte) ([]BasicRestRequestAuthentication, error) {
	var rawMessages []*json.RawMessage
	err := json.Unmarshal(body, &rawMessages)
	if err != nil {
		return nil, err
	}

	rraArray := make([]BasicRestRequestAuthentication, len(rawMessages))

	for index, rawMessage := range rawMessages {
		rra, err := unmarshalBasicRestRequestAuthentication(*rawMessage)
		if err != nil {
			return nil, err
		}
		rraArray[index] = rra
	}
	return rraArray, nil
}

// MarshalJSON is the custom marshaler for RestRequestAuthentication.
func (rra RestRequestAuthentication) MarshalJSON() ([]byte, error) {
	rra.Type = TypeRestRequestAuthentication
	objectMap := make(map[string]interface{})
	if rra.Type != "" {
		objectMap["type"] = rra.Type
	}
	return json.Marshal(objectMap)
}

// AsRolloutIdentityAuthentication is the BasicRestRequestAuthentication implementation for RestRequestAuthentication.
func (rra RestRequestAuthentication) AsRolloutIdentityAuthentication() (*RolloutIdentityAuthentication, bool) {
	return nil, false
}

// AsAPIKeyAuthentication is the BasicRestRequestAuthentication implementation for RestRequestAuthentication.
func (rra RestRequestAuthentication) AsAPIKeyAuthentication() (*APIKeyAuthentication, bool) {
	return nil, false
}

// AsRestRequestAuthentication is the BasicRestRequestAuthentication implementation for RestRequestAuthentication.
func (rra RestRequestAuthentication) AsRestRequestAuthentication() (*RestRequestAuthentication, bool) {
	return &rra, true
}

// AsBasicRestRequestAuthentication is the BasicRestRequestAuthentication implementation for RestRequestAuthentication.
func (rra RestRequestAuthentication) AsBasicRestRequestAuthentication() (BasicRestRequestAuthentication, bool) {
	return &rra, true
}

// RestResponse the properties that make up the expected REST response
type RestResponse struct {
	// SuccessStatusCodes - The HTTP status codes expected in a successful health check response. The response is expected to match one of the given status codes. If no expected status codes are provided, default expected status code is 200 OK.
	SuccessStatusCodes *[]string `json:"successStatusCodes,omitempty"`
	// Regex - The regular expressions to match the response content with.
	Regex *RestResponseRegex `json:"regex,omitempty"`
}

// RestResponseRegex the regular expressions to match the response content with.
type RestResponseRegex struct {
	// Matches - The list of regular expressions.
	Matches *[]string `json:"matches,omitempty"`
	// MatchQuantifier - Indicates whether any or all of the expressions should match with the response content. Possible values include: 'All', 'Any'
	MatchQuantifier RestMatchQuantifier `json:"matchQuantifier,omitempty"`
}

// Rollout defines the rollout.
type Rollout struct {
	autorest.Response `json:"-"`
	// Identity - Identity for the resource.
	Identity *Identity `json:"identity,omitempty"`
	// RolloutProperties - The properties that define a rollout.
	*RolloutProperties `json:"properties,omitempty"`
	// Tags - Resource tags.
	Tags map[string]*string `json:"tags"`
	// Location - The geo-location where the resource lives
	Location *string `json:"location,omitempty"`
	// ID - READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}
	ID *string `json:"id,omitempty"`
	// Name - READ-ONLY; The name of the resource
	Name *string `json:"name,omitempty"`
	// Type - READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts"
	Type *string `json:"type,omitempty"`
}

// MarshalJSON is the custom marshaler for Rollout.
func (r Rollout) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if r.Identity != nil {
		objectMap["identity"] = r.Identity
	}
	if r.RolloutProperties != nil {
		objectMap["properties"] = r.RolloutProperties
	}
	if r.Tags != nil {
		objectMap["tags"] = r.Tags
	}
	if r.Location != nil {
		objectMap["location"] = r.Location
	}
	return json.Marshal(objectMap)
}

// UnmarshalJSON is the custom unmarshaler for Rollout struct.
func (r *Rollout) UnmarshalJSON(body []byte) error {
	var m map[string]*json.RawMessage
	err := json.Unmarshal(body, &m)
	if err != nil {
		return err
	}
	for k, v := range m {
		switch k {
		case "identity":
			if v != nil {
				var identity Identity
				err = json.Unmarshal(*v, &identity)
				if err != nil {
					return err
				}
				r.Identity = &identity
			}
		case "properties":
			if v != nil {
				var rolloutProperties RolloutProperties
				err = json.Unmarshal(*v, &rolloutProperties)
				if err != nil {
					return err
				}
				r.RolloutProperties = &rolloutProperties
			}
		case "tags":
			if v != nil {
				var tags map[string]*string
				err = json.Unmarshal(*v, &tags)
				if err != nil {
					return err
				}
				r.Tags = tags
			}
		case "location":
			if v != nil {
				var location string
				err = json.Unmarshal(*v, &location)
				if err != nil {
					return err
				}
				r.Location = &location
			}
		case "id":
			if v != nil {
				var ID string
				err = json.Unmarshal(*v, &ID)
				if err != nil {
					return err
				}
				r.ID = &ID
			}
		case "name":
			if v != nil {
				var name string
				err = json.Unmarshal(*v, &name)
				if err != nil {
					return err
				}
				r.Name = &name
			}
		case "type":
			if v != nil {
				var typeVar string
				err = json.Unmarshal(*v, &typeVar)
				if err != nil {
					return err
				}
				r.Type = &typeVar
			}
		}
	}

	return nil
}

// RolloutIdentityAuthentication rolloutIdentity uses the user-assigned managed identity authentication
// context specified in the Identity property during rollout creation.
type RolloutIdentityAuthentication struct {
	// Type - Possible values include: 'TypeRestRequestAuthentication', 'TypeRolloutIdentity', 'TypeAPIKey'
	Type TypeBasicRestRequestAuthentication `json:"type,omitempty"`
}

// MarshalJSON is the custom marshaler for RolloutIdentityAuthentication.
func (ria RolloutIdentityAuthentication) MarshalJSON() ([]byte, error) {
	ria.Type = TypeRolloutIdentity
	objectMap := make(map[string]interface{})
	if ria.Type != "" {
		objectMap["type"] = ria.Type
	}
	return json.Marshal(objectMap)
}

// AsRolloutIdentityAuthentication is the BasicRestRequestAuthentication implementation for RolloutIdentityAuthentication.
func (ria RolloutIdentityAuthentication) AsRolloutIdentityAuthentication() (*RolloutIdentityAuthentication, bool) {
	return &ria, true
}

// AsAPIKeyAuthentication is the BasicRestRequestAuthentication implementation for RolloutIdentityAuthentication.
func (ria RolloutIdentityAuthentication) AsAPIKeyAuthentication() (*APIKeyAuthentication, bool) {
	return nil, false
}

// AsRestRequestAuthentication is the BasicRestRequestAuthentication implementation for RolloutIdentityAuthentication.
func (ria RolloutIdentityAuthentication) AsRestRequestAuthentication() (*RestRequestAuthentication, bool) {
	return nil, false
}

// AsBasicRestRequestAuthentication is the BasicRestRequestAuthentication implementation for RolloutIdentityAuthentication.
func (ria RolloutIdentityAuthentication) AsBasicRestRequestAuthentication() (BasicRestRequestAuthentication, bool) {
	return &ria, true
}

// RolloutOperationInfo detailed runtime information of the rollout.
type RolloutOperationInfo struct {
	// RetryAttempt - READ-ONLY; The ordinal count of the number of retry attempts on a rollout. 0 if no retries of the rollout have been performed. If the rollout is updated with a PUT, this count is reset to 0.
	RetryAttempt *int32 `json:"retryAttempt,omitempty"`
	// SkipSucceededOnRetry - READ-ONLY; True, if all steps that succeeded on the previous run/attempt were chosen to be skipped in this retry attempt. False, otherwise.
	SkipSucceededOnRetry *bool `json:"skipSucceededOnRetry,omitempty"`
	// StartTime - READ-ONLY; The start time of the rollout in UTC.
	StartTime *date.Time `json:"startTime,omitempty"`
	// EndTime - READ-ONLY; The start time of the rollout in UTC. This property will not be set if the rollout has not completed yet.
	EndTime *date.Time `json:"endTime,omitempty"`
	// Error - READ-ONLY; The detailed error information for any failure.
	Error *CloudErrorBody `json:"error,omitempty"`
}

// MarshalJSON is the custom marshaler for RolloutOperationInfo.
func (roi RolloutOperationInfo) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	return json.Marshal(objectMap)
}

// RolloutProperties the properties that define a rollout.
type RolloutProperties struct {
	// BuildVersion - The version of the build being deployed.
	BuildVersion *string `json:"buildVersion,omitempty"`
	// ArtifactSourceID - The reference to the artifact source resource Id where the payload is located.
	ArtifactSourceID *string `json:"artifactSourceId,omitempty"`
	// TargetServiceTopologyID - The resource Id of the service topology from which service units are being referenced in step groups to be deployed.
	TargetServiceTopologyID *string `json:"targetServiceTopologyId,omitempty"`
	// StepGroups - The list of step groups that define the orchestration.
	StepGroups *[]StepGroup `json:"stepGroups,omitempty"`
	// Status - READ-ONLY; The current status of the rollout.
	Status *string `json:"status,omitempty"`
	// TotalRetryAttempts - READ-ONLY; The cardinal count of total number of retries performed on the rollout at a given time.
	TotalRetryAttempts *int32 `json:"totalRetryAttempts,omitempty"`
	// OperationInfo - READ-ONLY; Operational information of the rollout.
	OperationInfo *RolloutOperationInfo `json:"operationInfo,omitempty"`
	// Services - READ-ONLY; The detailed information on the services being deployed.
	Services *[]Service `json:"services,omitempty"`
}

// MarshalJSON is the custom marshaler for RolloutProperties.
func (r RolloutProperties) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if r.BuildVersion != nil {
		objectMap["buildVersion"] = r.BuildVersion
	}
	if r.ArtifactSourceID != nil {
		objectMap["artifactSourceId"] = r.ArtifactSourceID
	}
	if r.TargetServiceTopologyID != nil {
		objectMap["targetServiceTopologyId"] = r.TargetServiceTopologyID
	}
	if r.StepGroups != nil {
		objectMap["stepGroups"] = r.StepGroups
	}
	return json.Marshal(objectMap)
}

// RolloutPropertiesModel defines the properties of a rollout.
type RolloutPropertiesModel struct {
	// Status - READ-ONLY; The current status of the rollout.
	Status *string `json:"status,omitempty"`
	// TotalRetryAttempts - READ-ONLY; The cardinal count of total number of retries performed on the rollout at a given time.
	TotalRetryAttempts *int32 `json:"totalRetryAttempts,omitempty"`
	// OperationInfo - READ-ONLY; Operational information of the rollout.
	OperationInfo *RolloutOperationInfo `json:"operationInfo,omitempty"`
	// Services - READ-ONLY; The detailed information on the services being deployed.
	Services *[]Service `json:"services,omitempty"`
}

// MarshalJSON is the custom marshaler for RolloutPropertiesModel.
func (rpm RolloutPropertiesModel) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	return json.Marshal(objectMap)
}

// RolloutRequest defines the PUT rollout request body.
type RolloutRequest struct {
	autorest.Response `json:"-"`
	// Identity - Identity for the resource.
	Identity *Identity `json:"identity,omitempty"`
	// RolloutRequestProperties - Defines the properties that make up a rollout request.
	*RolloutRequestProperties `json:"properties,omitempty"`
	// Tags - Resource tags.
	Tags map[string]*string `json:"tags"`
	// Location - The geo-location where the resource lives
	Location *string `json:"location,omitempty"`
	// ID - READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}
	ID *string `json:"id,omitempty"`
	// Name - READ-ONLY; The name of the resource
	Name *string `json:"name,omitempty"`
	// Type - READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts"
	Type *string `json:"type,omitempty"`
}

// MarshalJSON is the custom marshaler for RolloutRequest.
func (rr RolloutRequest) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if rr.Identity != nil {
		objectMap["identity"] = rr.Identity
	}
	if rr.RolloutRequestProperties != nil {
		objectMap["properties"] = rr.RolloutRequestProperties
	}
	if rr.Tags != nil {
		objectMap["tags"] = rr.Tags
	}
	if rr.Location != nil {
		objectMap["location"] = rr.Location
	}
	return json.Marshal(objectMap)
}

// UnmarshalJSON is the custom unmarshaler for RolloutRequest struct.
func (rr *RolloutRequest) UnmarshalJSON(body []byte) error {
	var m map[string]*json.RawMessage
	err := json.Unmarshal(body, &m)
	if err != nil {
		return err
	}
	for k, v := range m {
		switch k {
		case "identity":
			if v != nil {
				var identity Identity
				err = json.Unmarshal(*v, &identity)
				if err != nil {
					return err
				}
				rr.Identity = &identity
			}
		case "properties":
			if v != nil {
				var rolloutRequestProperties RolloutRequestProperties
				err = json.Unmarshal(*v, &rolloutRequestProperties)
				if err != nil {
					return err
				}
				rr.RolloutRequestProperties = &rolloutRequestProperties
			}
		case "tags":
			if v != nil {
				var tags map[string]*string
				err = json.Unmarshal(*v, &tags)
				if err != nil {
					return err
				}
				rr.Tags = tags
			}
		case "location":
			if v != nil {
				var location string
				err = json.Unmarshal(*v, &location)
				if err != nil {
					return err
				}
				rr.Location = &location
			}
		case "id":
			if v != nil {
				var ID string
				err = json.Unmarshal(*v, &ID)
				if err != nil {
					return err
				}
				rr.ID = &ID
			}
		case "name":
			if v != nil {
				var name string
				err = json.Unmarshal(*v, &name)
				if err != nil {
					return err
				}
				rr.Name = &name
			}
		case "type":
			if v != nil {
				var typeVar string
				err = json.Unmarshal(*v, &typeVar)
				if err != nil {
					return err
				}
				rr.Type = &typeVar
			}
		}
	}

	return nil
}

// RolloutRequestProperties the properties for defining a rollout.
type RolloutRequestProperties struct {
	// BuildVersion - The version of the build being deployed.
	BuildVersion *string `json:"buildVersion,omitempty"`
	// ArtifactSourceID - The reference to the artifact source resource Id where the payload is located.
	ArtifactSourceID *string `json:"artifactSourceId,omitempty"`
	// TargetServiceTopologyID - The resource Id of the service topology from which service units are being referenced in step groups to be deployed.
	TargetServiceTopologyID *string `json:"targetServiceTopologyId,omitempty"`
	// StepGroups - The list of step groups that define the orchestration.
	StepGroups *[]StepGroup `json:"stepGroups,omitempty"`
}

// RolloutsCreateOrUpdateFuture an abstraction for monitoring and retrieving the results of a long-running
// operation.
type RolloutsCreateOrUpdateFuture struct {
	azure.FutureAPI
	// Result returns the result of the asynchronous operation.
	// If the operation has not completed it will return an error.
	Result func(RolloutsClient) (RolloutRequest, error)
}

// UnmarshalJSON is the custom unmarshaller for CreateFuture.
func (future *RolloutsCreateOrUpdateFuture) UnmarshalJSON(body []byte) error {
	var azFuture azure.Future
	if err := json.Unmarshal(body, &azFuture); err != nil {
		return err
	}
	future.FutureAPI = &azFuture
	future.Result = future.result
	return nil
}

// result is the default implementation for RolloutsCreateOrUpdateFuture.Result.
func (future *RolloutsCreateOrUpdateFuture) result(client RolloutsClient) (rr RolloutRequest, err error) {
	var done bool
	done, err = future.DoneWithContext(context.Background(), client)
	if err != nil {
		err = autorest.NewErrorWithError(err, "deploymentmanager.RolloutsCreateOrUpdateFuture", "Result", future.Response(), "Polling failure")
		return
	}
	if !done {
		rr.Response.Response = future.Response()
		err = azure.NewAsyncOpIncompleteError("deploymentmanager.RolloutsCreateOrUpdateFuture")
		return
	}
	sender := autorest.DecorateSender(client, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
	if rr.Response.Response, err = future.GetResult(sender); err == nil && rr.Response.Response.StatusCode != http.StatusNoContent {
		rr, err = client.CreateOrUpdateResponder(rr.Response.Response)
		if err != nil {
			err = autorest.NewErrorWithError(err, "deploymentmanager.RolloutsCreateOrUpdateFuture", "Result", rr.Response.Response, "Failure responding to request")
		}
	}
	return
}

// RolloutStep defines a specific step on a target service unit.
type RolloutStep struct {
	// Name - Name of the step.
	Name *string `json:"name,omitempty"`
	// Status - READ-ONLY; Current state of the step.
	Status *string `json:"status,omitempty"`
	// StepGroup - The step group the current step is part of.
	StepGroup *string `json:"stepGroup,omitempty"`
	// OperationInfo - READ-ONLY; Detailed information of specific action execution.
	OperationInfo *StepOperationInfo `json:"operationInfo,omitempty"`
	// ResourceOperations - READ-ONLY; Set of resource operations that were performed, if any, on an Azure resource.
	ResourceOperations *[]ResourceOperation `json:"resourceOperations,omitempty"`
	// Messages - READ-ONLY; Supplementary informative messages during rollout.
	Messages *[]Message `json:"messages,omitempty"`
}

// MarshalJSON is the custom marshaler for RolloutStep.
func (rs RolloutStep) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if rs.Name != nil {
		objectMap["name"] = rs.Name
	}
	if rs.StepGroup != nil {
		objectMap["stepGroup"] = rs.StepGroup
	}
	return json.Marshal(objectMap)
}

// SasAuthentication defines the properties to access the artifacts using an Azure Storage SAS URI.
type SasAuthentication struct {
	// SasProperties - The SAS properties
	*SasProperties `json:"properties,omitempty"`
	// Type - Possible values include: 'TypeAuthentication', 'TypeSas'
	Type Type `json:"type,omitempty"`
}

// MarshalJSON is the custom marshaler for SasAuthentication.
func (sa SasAuthentication) MarshalJSON() ([]byte, error) {
	sa.Type = TypeSas
	objectMap := make(map[string]interface{})
	if sa.SasProperties != nil {
		objectMap["properties"] = sa.SasProperties
	}
	if sa.Type != "" {
		objectMap["type"] = sa.Type
	}
	return json.Marshal(objectMap)
}

// AsSasAuthentication is the BasicAuthentication implementation for SasAuthentication.
func (sa SasAuthentication) AsSasAuthentication() (*SasAuthentication, bool) {
	return &sa, true
}

// AsAuthentication is the BasicAuthentication implementation for SasAuthentication.
func (sa SasAuthentication) AsAuthentication() (*Authentication, bool) {
	return nil, false
}

// AsBasicAuthentication is the BasicAuthentication implementation for SasAuthentication.
func (sa SasAuthentication) AsBasicAuthentication() (BasicAuthentication, bool) {
	return &sa, true
}

// UnmarshalJSON is the custom unmarshaler for SasAuthentication struct.
func (sa *SasAuthentication) UnmarshalJSON(body []byte) error {
	var m map[string]*json.RawMessage
	err := json.Unmarshal(body, &m)
	if err != nil {
		return err
	}
	for k, v := range m {
		switch k {
		case "properties":
			if v != nil {
				var sasProperties SasProperties
				err = json.Unmarshal(*v, &sasProperties)
				if err != nil {
					return err
				}
				sa.SasProperties = &sasProperties
			}
		case "type":
			if v != nil {
				var typeVar Type
				err = json.Unmarshal(*v, &typeVar)
				if err != nil {
					return err
				}
				sa.Type = typeVar
			}
		}
	}

	return nil
}

// SasProperties the properties that define SAS authentication.
type SasProperties struct {
	// SasURI - The SAS URI to the Azure Storage blob container. Any offset from the root of the container to where the artifacts are located can be defined in the artifactRoot.
	SasURI *string `json:"sasUri,omitempty"`
}

// Service defines a service.
type Service struct {
	// Name - Name of the service.
	Name *string `json:"name,omitempty"`
	// ServiceUnits - The detailed information about the units that make up the service.
	ServiceUnits *[]ServiceUnit `json:"serviceUnits,omitempty"`
	// TargetLocation - The Azure location to which the resources in the service belong to or should be deployed to.
	TargetLocation *string `json:"targetLocation,omitempty"`
	// TargetSubscriptionID - The subscription to which the resources in the service belong to or should be deployed to.
	TargetSubscriptionID *string `json:"targetSubscriptionId,omitempty"`
}

// ServiceProperties the properties of a service.
type ServiceProperties struct {
	// TargetLocation - The Azure location to which the resources in the service belong to or should be deployed to.
	TargetLocation *string `json:"targetLocation,omitempty"`
	// TargetSubscriptionID - The subscription to which the resources in the service belong to or should be deployed to.
	TargetSubscriptionID *string `json:"targetSubscriptionId,omitempty"`
}

// ServiceResource the resource representation of a service in a service topology.
type ServiceResource struct {
	autorest.Response `json:"-"`
	// ServiceResourceProperties - The properties that define a service in a service topology.
	*ServiceResourceProperties `json:"properties,omitempty"`
	// Tags - Resource tags.
	Tags map[string]*string `json:"tags"`
	// Location - The geo-location where the resource lives
	Location *string `json:"location,omitempty"`
	// ID - READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}
	ID *string `json:"id,omitempty"`
	// Name - READ-ONLY; The name of the resource
	Name *string `json:"name,omitempty"`
	// Type - READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts"
	Type *string `json:"type,omitempty"`
}

// MarshalJSON is the custom marshaler for ServiceResource.
func (sr ServiceResource) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if sr.ServiceResourceProperties != nil {
		objectMap["properties"] = sr.ServiceResourceProperties
	}
	if sr.Tags != nil {
		objectMap["tags"] = sr.Tags
	}
	if sr.Location != nil {
		objectMap["location"] = sr.Location
	}
	return json.Marshal(objectMap)
}

// UnmarshalJSON is the custom unmarshaler for ServiceResource struct.
func (sr *ServiceResource) UnmarshalJSON(body []byte) error {
	var m map[string]*json.RawMessage
	err := json.Unmarshal(body, &m)
	if err != nil {
		return err
	}
	for k, v := range m {
		switch k {
		case "properties":
			if v != nil {
				var serviceResourceProperties ServiceResourceProperties
				err = json.Unmarshal(*v, &serviceResourceProperties)
				if err != nil {
					return err
				}
				sr.ServiceResourceProperties = &serviceResourceProperties
			}
		case "tags":
			if v != nil {
				var tags map[string]*string
				err = json.Unmarshal(*v, &tags)
				if err != nil {
					return err
				}
				sr.Tags = tags
			}
		case "location":
			if v != nil {
				var location string
				err = json.Unmarshal(*v, &location)
				if err != nil {
					return err
				}
				sr.Location = &location
			}
		case "id":
			if v != nil {
				var ID string
				err = json.Unmarshal(*v, &ID)
				if err != nil {
					return err
				}
				sr.ID = &ID
			}
		case "name":
			if v != nil {
				var name string
				err = json.Unmarshal(*v, &name)
				if err != nil {
					return err
				}
				sr.Name = &name
			}
		case "type":
			if v != nil {
				var typeVar string
				err = json.Unmarshal(*v, &typeVar)
				if err != nil {
					return err
				}
				sr.Type = &typeVar
			}
		}
	}

	return nil
}

// ServiceResourceProperties the properties that define a service in a service topology.
type ServiceResourceProperties struct {
	// TargetLocation - The Azure location to which the resources in the service belong to or should be deployed to.
	TargetLocation *string `json:"targetLocation,omitempty"`
	// TargetSubscriptionID - The subscription to which the resources in the service belong to or should be deployed to.
	TargetSubscriptionID *string `json:"targetSubscriptionId,omitempty"`
}

// ServiceTopologyProperties the properties of a service topology.
type ServiceTopologyProperties struct {
	// ArtifactSourceID - The resource Id of the artifact source that contains the artifacts that can be referenced in the service units.
	ArtifactSourceID *string `json:"artifactSourceId,omitempty"`
}

// ServiceTopologyResource the resource representation of a service topology.
type ServiceTopologyResource struct {
	autorest.Response `json:"-"`
	// ServiceTopologyResourceProperties - The properties that define the service topology.
	*ServiceTopologyResourceProperties `json:"properties,omitempty"`
	// Tags - Resource tags.
	Tags map[string]*string `json:"tags"`
	// Location - The geo-location where the resource lives
	Location *string `json:"location,omitempty"`
	// ID - READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}
	ID *string `json:"id,omitempty"`
	// Name - READ-ONLY; The name of the resource
	Name *string `json:"name,omitempty"`
	// Type - READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts"
	Type *string `json:"type,omitempty"`
}

// MarshalJSON is the custom marshaler for ServiceTopologyResource.
func (str ServiceTopologyResource) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if str.ServiceTopologyResourceProperties != nil {
		objectMap["properties"] = str.ServiceTopologyResourceProperties
	}
	if str.Tags != nil {
		objectMap["tags"] = str.Tags
	}
	if str.Location != nil {
		objectMap["location"] = str.Location
	}
	return json.Marshal(objectMap)
}

// UnmarshalJSON is the custom unmarshaler for ServiceTopologyResource struct.
func (str *ServiceTopologyResource) UnmarshalJSON(body []byte) error {
	var m map[string]*json.RawMessage
	err := json.Unmarshal(body, &m)
	if err != nil {
		return err
	}
	for k, v := range m {
		switch k {
		case "properties":
			if v != nil {
				var serviceTopologyResourceProperties ServiceTopologyResourceProperties
				err = json.Unmarshal(*v, &serviceTopologyResourceProperties)
				if err != nil {
					return err
				}
				str.ServiceTopologyResourceProperties = &serviceTopologyResourceProperties
			}
		case "tags":
			if v != nil {
				var tags map[string]*string
				err = json.Unmarshal(*v, &tags)
				if err != nil {
					return err
				}
				str.Tags = tags
			}
		case "location":
			if v != nil {
				var location string
				err = json.Unmarshal(*v, &location)
				if err != nil {
					return err
				}
				str.Location = &location
			}
		case "id":
			if v != nil {
				var ID string
				err = json.Unmarshal(*v, &ID)
				if err != nil {
					return err
				}
				str.ID = &ID
			}
		case "name":
			if v != nil {
				var name string
				err = json.Unmarshal(*v, &name)
				if err != nil {
					return err
				}
				str.Name = &name
			}
		case "type":
			if v != nil {
				var typeVar string
				err = json.Unmarshal(*v, &typeVar)
				if err != nil {
					return err
				}
				str.Type = &typeVar
			}
		}
	}

	return nil
}

// ServiceTopologyResourceProperties the properties that define the service topology.
type ServiceTopologyResourceProperties struct {
	// ArtifactSourceID - The resource Id of the artifact source that contains the artifacts that can be referenced in the service units.
	ArtifactSourceID *string `json:"artifactSourceId,omitempty"`
}

// ServiceUnit defines a service unit.
type ServiceUnit struct {
	// Name - Name of the service unit.
	Name *string `json:"name,omitempty"`
	// Steps - Detailed step information, if present.
	Steps *[]RolloutStep `json:"steps,omitempty"`
	// TargetResourceGroup - The Azure Resource Group to which the resources in the service unit belong to or should be deployed to.
	TargetResourceGroup *string `json:"targetResourceGroup,omitempty"`
	// DeploymentMode - Describes the type of ARM deployment to be performed on the resource. Possible values include: 'Incremental', 'Complete'
	DeploymentMode DeploymentMode `json:"deploymentMode,omitempty"`
	// Artifacts - The artifacts for the service unit.
	Artifacts *ServiceUnitArtifacts `json:"artifacts,omitempty"`
}

// ServiceUnitArtifacts defines the artifacts of a service unit.
type ServiceUnitArtifacts struct {
	// TemplateURI - The full URI of the ARM template file with the SAS token.
	TemplateURI *string `json:"templateUri,omitempty"`
	// ParametersURI - The full URI of the ARM parameters file with the SAS token.
	ParametersURI *string `json:"parametersUri,omitempty"`
	// TemplateArtifactSourceRelativePath - The path to the ARM template file relative to the artifact source.
	TemplateArtifactSourceRelativePath *string `json:"templateArtifactSourceRelativePath,omitempty"`
	// ParametersArtifactSourceRelativePath - The path to the ARM parameters file relative to the artifact source.
	ParametersArtifactSourceRelativePath *string `json:"parametersArtifactSourceRelativePath,omitempty"`
}

// ServiceUnitProperties defines the properties of a service unit.
type ServiceUnitProperties struct {
	// TargetResourceGroup - The Azure Resource Group to which the resources in the service unit belong to or should be deployed to.
	TargetResourceGroup *string `json:"targetResourceGroup,omitempty"`
	// DeploymentMode - Describes the type of ARM deployment to be performed on the resource. Possible values include: 'Incremental', 'Complete'
	DeploymentMode DeploymentMode `json:"deploymentMode,omitempty"`
	// Artifacts - The artifacts for the service unit.
	Artifacts *ServiceUnitArtifacts `json:"artifacts,omitempty"`
}

// ServiceUnitResource represents the response of a service unit resource.
type ServiceUnitResource struct {
	autorest.Response `json:"-"`
	// ServiceUnitResourceProperties - The properties that define the service unit.
	*ServiceUnitResourceProperties `json:"properties,omitempty"`
	// Tags - Resource tags.
	Tags map[string]*string `json:"tags"`
	// Location - The geo-location where the resource lives
	Location *string `json:"location,omitempty"`
	// ID - READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}
	ID *string `json:"id,omitempty"`
	// Name - READ-ONLY; The name of the resource
	Name *string `json:"name,omitempty"`
	// Type - READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts"
	Type *string `json:"type,omitempty"`
}

// MarshalJSON is the custom marshaler for ServiceUnitResource.
func (sur ServiceUnitResource) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if sur.ServiceUnitResourceProperties != nil {
		objectMap["properties"] = sur.ServiceUnitResourceProperties
	}
	if sur.Tags != nil {
		objectMap["tags"] = sur.Tags
	}
	if sur.Location != nil {
		objectMap["location"] = sur.Location
	}
	return json.Marshal(objectMap)
}

// UnmarshalJSON is the custom unmarshaler for ServiceUnitResource struct.
func (sur *ServiceUnitResource) UnmarshalJSON(body []byte) error {
	var m map[string]*json.RawMessage
	err := json.Unmarshal(body, &m)
	if err != nil {
		return err
	}
	for k, v := range m {
		switch k {
		case "properties":
			if v != nil {
				var serviceUnitResourceProperties ServiceUnitResourceProperties
				err = json.Unmarshal(*v, &serviceUnitResourceProperties)
				if err != nil {
					return err
				}
				sur.ServiceUnitResourceProperties = &serviceUnitResourceProperties
			}
		case "tags":
			if v != nil {
				var tags map[string]*string
				err = json.Unmarshal(*v, &tags)
				if err != nil {
					return err
				}
				sur.Tags = tags
			}
		case "location":
			if v != nil {
				var location string
				err = json.Unmarshal(*v, &location)
				if err != nil {
					return err
				}
				sur.Location = &location
			}
		case "id":
			if v != nil {
				var ID string
				err = json.Unmarshal(*v, &ID)
				if err != nil {
					return err
				}
				sur.ID = &ID
			}
		case "name":
			if v != nil {
				var name string
				err = json.Unmarshal(*v, &name)
				if err != nil {
					return err
				}
				sur.Name = &name
			}
		case "type":
			if v != nil {
				var typeVar string
				err = json.Unmarshal(*v, &typeVar)
				if err != nil {
					return err
				}
				sur.Type = &typeVar
			}
		}
	}

	return nil
}

// ServiceUnitResourceProperties the properties that define the service unit.
type ServiceUnitResourceProperties struct {
	// TargetResourceGroup - The Azure Resource Group to which the resources in the service unit belong to or should be deployed to.
	TargetResourceGroup *string `json:"targetResourceGroup,omitempty"`
	// DeploymentMode - Describes the type of ARM deployment to be performed on the resource. Possible values include: 'Incremental', 'Complete'
	DeploymentMode DeploymentMode `json:"deploymentMode,omitempty"`
	// Artifacts - The artifacts for the service unit.
	Artifacts *ServiceUnitArtifacts `json:"artifacts,omitempty"`
}

// ServiceUnitsCreateOrUpdateFuture an abstraction for monitoring and retrieving the results of a
// long-running operation.
type ServiceUnitsCreateOrUpdateFuture struct {
	azure.FutureAPI
	// Result returns the result of the asynchronous operation.
	// If the operation has not completed it will return an error.
	Result func(ServiceUnitsClient) (ServiceUnitResource, error)
}

// UnmarshalJSON is the custom unmarshaller for CreateFuture.
func (future *ServiceUnitsCreateOrUpdateFuture) UnmarshalJSON(body []byte) error {
	var azFuture azure.Future
	if err := json.Unmarshal(body, &azFuture); err != nil {
		return err
	}
	future.FutureAPI = &azFuture
	future.Result = future.result
	return nil
}

// result is the default implementation for ServiceUnitsCreateOrUpdateFuture.Result.
func (future *ServiceUnitsCreateOrUpdateFuture) result(client ServiceUnitsClient) (sur ServiceUnitResource, err error) {
	var done bool
	done, err = future.DoneWithContext(context.Background(), client)
	if err != nil {
		err = autorest.NewErrorWithError(err, "deploymentmanager.ServiceUnitsCreateOrUpdateFuture", "Result", future.Response(), "Polling failure")
		return
	}
	if !done {
		sur.Response.Response = future.Response()
		err = azure.NewAsyncOpIncompleteError("deploymentmanager.ServiceUnitsCreateOrUpdateFuture")
		return
	}
	sender := autorest.DecorateSender(client, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
	if sur.Response.Response, err = future.GetResult(sender); err == nil && sur.Response.Response.StatusCode != http.StatusNoContent {
		sur, err = client.CreateOrUpdateResponder(sur.Response.Response)
		if err != nil {
			err = autorest.NewErrorWithError(err, "deploymentmanager.ServiceUnitsCreateOrUpdateFuture", "Result", sur.Response.Response, "Failure responding to request")
		}
	}
	return
}

// StepGroup the properties that define a Step group in a rollout.
type StepGroup struct {
	// Name - The name of the step group.
	Name *string `json:"name,omitempty"`
	// DependsOnStepGroups - The list of step group names on which this step group depends on.
	DependsOnStepGroups *[]string `json:"dependsOnStepGroups,omitempty"`
	// PreDeploymentSteps - The list of steps to be run before deploying the target.
	PreDeploymentSteps *[]PrePostStep `json:"preDeploymentSteps,omitempty"`
	// DeploymentTargetID - The resource Id of service unit to be deployed. The service unit should be from the service topology referenced in targetServiceTopologyId
	DeploymentTargetID *string `json:"deploymentTargetId,omitempty"`
	// PostDeploymentSteps - The list of steps to be run after deploying the target.
	PostDeploymentSteps *[]PrePostStep `json:"postDeploymentSteps,omitempty"`
}

// StepOperationInfo detailed information of a specific step run.
type StepOperationInfo struct {
	// DeploymentName - READ-ONLY; The name of the ARM deployment initiated as part of the step.
	DeploymentName *string `json:"deploymentName,omitempty"`
	// CorrelationID - READ-ONLY; Unique identifier to track the request for ARM-based resources.
	CorrelationID *string `json:"correlationId,omitempty"`
	// StartTime - READ-ONLY; Start time of the action in UTC.
	StartTime *date.Time `json:"startTime,omitempty"`
	// EndTime - READ-ONLY; End time of the action in UTC.
	EndTime *date.Time `json:"endTime,omitempty"`
	// LastUpdatedTime - READ-ONLY; Last time in UTC this operation was updated.
	LastUpdatedTime *date.Time `json:"lastUpdatedTime,omitempty"`
	// Error - The errors, if any, for the action.
	Error *CloudErrorBody `json:"error,omitempty"`
}

// MarshalJSON is the custom marshaler for StepOperationInfo.
func (soi StepOperationInfo) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if soi.Error != nil {
		objectMap["error"] = soi.Error
	}
	return json.Marshal(objectMap)
}

// BasicStepProperties the properties of a step resource.
type BasicStepProperties interface {
	AsHealthCheckStepProperties() (*HealthCheckStepProperties, bool)
	AsWaitStepProperties() (*WaitStepProperties, bool)
	AsStepProperties() (*StepProperties, bool)
}

// StepProperties the properties of a step resource.
type StepProperties struct {
	// StepType - Possible values include: 'StepTypeStepProperties', 'StepTypeHealthCheck', 'StepTypeWait'
	StepType StepType `json:"stepType,omitempty"`
}

func unmarshalBasicStepProperties(body []byte) (BasicStepProperties, error) {
	var m map[string]interface{}
	err := json.Unmarshal(body, &m)
	if err != nil {
		return nil, err
	}

	switch m["stepType"] {
	case string(StepTypeHealthCheck):
		var hcsp HealthCheckStepProperties
		err := json.Unmarshal(body, &hcsp)
		return hcsp, err
	case string(StepTypeWait):
		var wsp WaitStepProperties
		err := json.Unmarshal(body, &wsp)
		return wsp, err
	default:
		var sp StepProperties
		err := json.Unmarshal(body, &sp)
		return sp, err
	}
}
func unmarshalBasicStepPropertiesArray(body []byte) ([]BasicStepProperties, error) {
	var rawMessages []*json.RawMessage
	err := json.Unmarshal(body, &rawMessages)
	if err != nil {
		return nil, err
	}

	spArray := make([]BasicStepProperties, len(rawMessages))

	for index, rawMessage := range rawMessages {
		sp, err := unmarshalBasicStepProperties(*rawMessage)
		if err != nil {
			return nil, err
		}
		spArray[index] = sp
	}
	return spArray, nil
}

// MarshalJSON is the custom marshaler for StepProperties.
func (sp StepProperties) MarshalJSON() ([]byte, error) {
	sp.StepType = StepTypeStepProperties
	objectMap := make(map[string]interface{})
	if sp.StepType != "" {
		objectMap["stepType"] = sp.StepType
	}
	return json.Marshal(objectMap)
}

// AsHealthCheckStepProperties is the BasicStepProperties implementation for StepProperties.
func (sp StepProperties) AsHealthCheckStepProperties() (*HealthCheckStepProperties, bool) {
	return nil, false
}

// AsWaitStepProperties is the BasicStepProperties implementation for StepProperties.
func (sp StepProperties) AsWaitStepProperties() (*WaitStepProperties, bool) {
	return nil, false
}

// AsStepProperties is the BasicStepProperties implementation for StepProperties.
func (sp StepProperties) AsStepProperties() (*StepProperties, bool) {
	return &sp, true
}

// AsBasicStepProperties is the BasicStepProperties implementation for StepProperties.
func (sp StepProperties) AsBasicStepProperties() (BasicStepProperties, bool) {
	return &sp, true
}

// StepResource the resource representation of a rollout step.
type StepResource struct {
	autorest.Response `json:"-"`
	// Properties - The properties that define the step.
	Properties BasicStepProperties `json:"properties,omitempty"`
	// Tags - Resource tags.
	Tags map[string]*string `json:"tags"`
	// Location - The geo-location where the resource lives
	Location *string `json:"location,omitempty"`
	// ID - READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}
	ID *string `json:"id,omitempty"`
	// Name - READ-ONLY; The name of the resource
	Name *string `json:"name,omitempty"`
	// Type - READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts"
	Type *string `json:"type,omitempty"`
}

// MarshalJSON is the custom marshaler for StepResource.
func (sr StepResource) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	objectMap["properties"] = sr.Properties
	if sr.Tags != nil {
		objectMap["tags"] = sr.Tags
	}
	if sr.Location != nil {
		objectMap["location"] = sr.Location
	}
	return json.Marshal(objectMap)
}

// UnmarshalJSON is the custom unmarshaler for StepResource struct.
func (sr *StepResource) UnmarshalJSON(body []byte) error {
	var m map[string]*json.RawMessage
	err := json.Unmarshal(body, &m)
	if err != nil {
		return err
	}
	for k, v := range m {
		switch k {
		case "properties":
			if v != nil {
				properties, err := unmarshalBasicStepProperties(*v)
				if err != nil {
					return err
				}
				sr.Properties = properties
			}
		case "tags":
			if v != nil {
				var tags map[string]*string
				err = json.Unmarshal(*v, &tags)
				if err != nil {
					return err
				}
				sr.Tags = tags
			}
		case "location":
			if v != nil {
				var location string
				err = json.Unmarshal(*v, &location)
				if err != nil {
					return err
				}
				sr.Location = &location
			}
		case "id":
			if v != nil {
				var ID string
				err = json.Unmarshal(*v, &ID)
				if err != nil {
					return err
				}
				sr.ID = &ID
			}
		case "name":
			if v != nil {
				var name string
				err = json.Unmarshal(*v, &name)
				if err != nil {
					return err
				}
				sr.Name = &name
			}
		case "type":
			if v != nil {
				var typeVar string
				err = json.Unmarshal(*v, &typeVar)
				if err != nil {
					return err
				}
				sr.Type = &typeVar
			}
		}
	}

	return nil
}

// TrackedResource the resource model definition for an Azure Resource Manager tracked top level resource
// which has 'tags' and a 'location'
type TrackedResource struct {
	// Tags - Resource tags.
	Tags map[string]*string `json:"tags"`
	// Location - The geo-location where the resource lives
	Location *string `json:"location,omitempty"`
	// ID - READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}
	ID *string `json:"id,omitempty"`
	// Name - READ-ONLY; The name of the resource
	Name *string `json:"name,omitempty"`
	// Type - READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts"
	Type *string `json:"type,omitempty"`
}

// MarshalJSON is the custom marshaler for TrackedResource.
func (tr TrackedResource) MarshalJSON() ([]byte, error) {
	objectMap := make(map[string]interface{})
	if tr.Tags != nil {
		objectMap["tags"] = tr.Tags
	}
	if tr.Location != nil {
		objectMap["location"] = tr.Location
	}
	return json.Marshal(objectMap)
}

// WaitStepAttributes the parameters for the wait step.
type WaitStepAttributes struct {
	// Duration - The duration in ISO 8601 format of how long the wait should be.
	Duration *string `json:"duration,omitempty"`
}

// WaitStepProperties defines the properties of a Wait step.
type WaitStepProperties struct {
	// Attributes - The Wait attributes
	Attributes *WaitStepAttributes `json:"attributes,omitempty"`
	// StepType - Possible values include: 'StepTypeStepProperties', 'StepTypeHealthCheck', 'StepTypeWait'
	StepType StepType `json:"stepType,omitempty"`
}

// MarshalJSON is the custom marshaler for WaitStepProperties.
func (wsp WaitStepProperties) MarshalJSON() ([]byte, error) {
	wsp.StepType = StepTypeWait
	objectMap := make(map[string]interface{})
	if wsp.Attributes != nil {
		objectMap["attributes"] = wsp.Attributes
	}
	if wsp.StepType != "" {
		objectMap["stepType"] = wsp.StepType
	}
	return json.Marshal(objectMap)
}

// AsHealthCheckStepProperties is the BasicStepProperties implementation for WaitStepProperties.
func (wsp WaitStepProperties) AsHealthCheckStepProperties() (*HealthCheckStepProperties, bool) {
	return nil, false
}

// AsWaitStepProperties is the BasicStepProperties implementation for WaitStepProperties.
func (wsp WaitStepProperties) AsWaitStepProperties() (*WaitStepProperties, bool) {
	return &wsp, true
}

// AsStepProperties is the BasicStepProperties implementation for WaitStepProperties.
func (wsp WaitStepProperties) AsStepProperties() (*StepProperties, bool) {
	return nil, false
}

// AsBasicStepProperties is the BasicStepProperties implementation for WaitStepProperties.
func (wsp WaitStepProperties) AsBasicStepProperties() (BasicStepProperties, bool) {
	return &wsp, true
}
