Create a provider to use Azure Batch (#133)
* Started work on provider * WIP Adding batch provider * Working basic call into pool client. Need to parameterize the baseurl * Fixed job creation by manipulating the content-type * WIP Kicking off containers. Dirty * [wip] More meat around scheduling simple containers. * Working on basic task wrapper to co-schedule pods * WIP on task wrapper * WIP * Working pod minimal wrapper for batch * Integrate pod template code into provider * Cleaning up * Move to docker without gpu * WIP batch integration * partially working * Working logs * Tidy code * WIP: Testing and readme * Added readme and terraform deployment for GPU Azure Batch pool. * Update to enable low priority nodes for gpu * Fix log formatting bug. Return node logs when container not yet started * Moved to golang v1.10 * Fix cri test * Fix up minor docs Issue. Add provider to readme. Add var for vk image.
This commit is contained in:
committed by
Robbie Zhang
parent
1ad6fb434e
commit
d6e8b3daf7
@@ -3,7 +3,7 @@ jobs:
|
||||
build:
|
||||
docker:
|
||||
# specify the version
|
||||
- image: circleci/golang:1.9
|
||||
- image: circleci/golang:1.10
|
||||
|
||||
working_directory: /go/src/github.com/virtual-kubelet/virtual-kubelet
|
||||
steps:
|
||||
|
||||
4
.dockerignore
Normal file
4
.dockerignore
Normal file
@@ -0,0 +1,4 @@
|
||||
.vscode
|
||||
private.env
|
||||
*.private.*
|
||||
providers/azurebatch/deployment/
|
||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -24,4 +24,10 @@ bin/
|
||||
credentials.json
|
||||
|
||||
# VS Code files
|
||||
.vscode/
|
||||
.vscode/
|
||||
|
||||
# Terraform ignores
|
||||
**/.terraform/**
|
||||
**/terraform-provider-kubernetes
|
||||
**/*.tfstate*
|
||||
debug
|
||||
|
||||
29
Gopkg.lock
generated
29
Gopkg.lock
generated
@@ -1,6 +1,15 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/Azure/azure-sdk-for-go"
|
||||
packages = [
|
||||
"services/batch/2017-09-01.6.0/batch",
|
||||
"version"
|
||||
]
|
||||
revision = "51228ee60b238eaa5a9d53adc82ebd8b321bca4f"
|
||||
version = "v15.1.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/Azure/go-ansiterm"
|
||||
@@ -13,8 +22,12 @@
|
||||
[[projects]]
|
||||
name = "github.com/Azure/go-autorest"
|
||||
packages = [
|
||||
"autorest",
|
||||
"autorest/adal",
|
||||
"autorest/date"
|
||||
"autorest/azure",
|
||||
"autorest/date",
|
||||
"autorest/to",
|
||||
"autorest/validation"
|
||||
]
|
||||
revision = "eaa7994b2278094c904d31993d26f56324db3052"
|
||||
version = "v10.8.1"
|
||||
@@ -502,6 +515,12 @@
|
||||
packages = ["."]
|
||||
revision = "7cafcd837844e784b526369c9bce262804aebc60"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/lawrencegripper/pod2docker"
|
||||
packages = ["."]
|
||||
revision = "9a9182c0c682798fe214fa11df7bfca83048d433"
|
||||
version = "v0.5.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/magiconair/properties"
|
||||
packages = ["."]
|
||||
@@ -576,6 +595,12 @@
|
||||
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/satori/go.uuid"
|
||||
packages = ["."]
|
||||
revision = "f58768cc1a7a7e77a3bd49e98cdd21419399b6a3"
|
||||
version = "v1.2.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/spf13/afero"
|
||||
packages = [
|
||||
@@ -1049,6 +1074,6 @@
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "6125e24314e26b6b5fb9a7cd98e4f23fa2e551d882485d1ff5f481abdfd792aa"
|
||||
inputs-digest = "8f3ca80656c580339bc7105912693cf126c4952c476e7052cbd9de4ef73d9e75"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
||||
@@ -55,6 +55,14 @@
|
||||
name = "github.com/hyperhq/hypercli"
|
||||
revision = "29217d318cab52815518a1126d57ca010de83e4d"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/Azure/azure-sdk-for-go"
|
||||
version = "15.1.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/lawrencegripper/pod2docker"
|
||||
version = "0.5.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/aws/aws-sdk-go"
|
||||
version = "1.13.38"
|
||||
|
||||
@@ -20,6 +20,7 @@ The best description is "Kubernetes API on top, programmable back."
|
||||
* [Usage](#usage)
|
||||
* [Providers](#providers)
|
||||
+ [Azure Container Instances Provider](#azure-container-instances-provider)
|
||||
+ [Azure Batch GPU Provider](./providers/azurebatch/README.md)
|
||||
+ [AWS Fargate Provider](#aws-fargate-provider)
|
||||
+ [Hyper.sh Provider](#hypersh-provider)
|
||||
+ [Adding a New Provider via the Provider Interface](#adding-a-new-provider-via-the-provider-interface)
|
||||
|
||||
26
examples/busyecho.yaml
Normal file
26
examples/busyecho.yaml
Normal file
@@ -0,0 +1,26 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: busyecho
|
||||
spec:
|
||||
containers:
|
||||
- image: busybox
|
||||
command:
|
||||
- echo "Hello from container"
|
||||
imagePullPolicy: Always
|
||||
name: nginx
|
||||
resources:
|
||||
requests:
|
||||
memory: 1G
|
||||
cpu: 1
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
protocol: TCP
|
||||
- containerPort: 443
|
||||
name: https
|
||||
dnsPolicy: ClusterFirst
|
||||
nodeName: virtual-kubelet
|
||||
tolerations:
|
||||
- key: azure.com/aci
|
||||
effect: NoSchedule
|
||||
24
examples/pause.yaml
Normal file
24
examples/pause.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: pauseexample1
|
||||
spec:
|
||||
containers:
|
||||
- name: pauseexample1
|
||||
imagePullPolicy: Always
|
||||
image: gcr.io/google_containers/pause:1.0
|
||||
resources:
|
||||
requests:
|
||||
memory: 1G
|
||||
cpu: 1
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
protocol: TCP
|
||||
- containerPort: 443
|
||||
name: https
|
||||
dnsPolicy: ClusterFirst
|
||||
nodeName: virtual-kubelet
|
||||
tolerations:
|
||||
- key: azure.com/aci
|
||||
effect: NoSchedule
|
||||
79
providers/azurebatch/README.md
Normal file
79
providers/azurebatch/README.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# Kubernetes Virtual Kubelet with Azure Batch
|
||||
|
||||
[Azure Batch](https://docs.microsoft.com/en-us/azure/batch/) provides a HPC Computing environment in Azure for distributed tasks. Azure Batch handles scheduling decrete jobs and tasks accross pools of VM's. It is commonly used for batch processing tasks such as rendering.
|
||||
|
||||
The Virtual kubelet integration allows you to take advantage of this from within Kubernetes. The primary usecase for the provider is to make it easy to use GPU based workload from normal Kubernetes clusters. For example, creating Kubernetes Jobs which train or execute ML models using Nvidia GPU's or using FFMPEG.
|
||||
|
||||
Azure Batch allows for [low priority nodes](https://docs.microsoft.com/en-us/azure/batch/batch-low-pri-vms) which can also help to reduce cost for non-time sensitive workloads.
|
||||
|
||||
__The [ACI provider](../azure/README.MD) is the best option unless you're looking to utilise some specific features of Azure Batch__.
|
||||
|
||||
## Status: Experimental
|
||||
|
||||
This provider is currently in the exterimental stages. Contributions welcome!
|
||||
|
||||
## Quick Start
|
||||
|
||||
The following Terraform template deploys an AKS cluster with the Virtual Kubelet, Azure Batch Account and GPU enabled Azure Batch pool. The Batch pool contains 1 Dedicated NC6 Node and 2 Low Priority NC6 Nodes.
|
||||
|
||||
1. Setup Terraform for Azure following [this guide here](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/terraform-install-configure)
|
||||
2. From the commandline move to the deployment folder `cd ./providers/azurebatch/deployment` then edit `vars.example.tfvars` adding in your Service Principal details
|
||||
3. Download the latest version of the Community Kubernetes Provider for Terraform. Get the correct link [from here](https://github.com/sl1pm4t/terraform-provider-kubernetes/releases) and use it as follows: (Current official Terraform K8s provider doesn't support `Deployments`)
|
||||
|
||||
```shell
|
||||
curl -L -o - PUT_RELASE_BINARY_LINK_YOU_FOUND_HERE | gunzip > terraform-provider-kubernetes
|
||||
chmod +x ./terraform-provider-kubernetes
|
||||
```
|
||||
|
||||
4. Use `terraform init` to initialize the template
|
||||
5. Use `terraform plan -var-file=./vars.example.tfvars` and `terraform apply -var-file=./vars.example.tfvars` to deploy the template
|
||||
6. Run `kubectl describe deployment/vkdeployment` to check the virtual kubelet is running correctly.
|
||||
7. Run `kubectl create -f examplegpupod.yaml`
|
||||
8. Run `pods=$(kubectl get pods --selector=app=examplegpupod --show-all --output=jsonpath={.items..metadata.name})` then `kubectl logs $pods` to view the logs. Should see:
|
||||
|
||||
```text
|
||||
[Vector addition of 50000 elements]
|
||||
Copy input data from the host memory to the CUDA device
|
||||
CUDA kernel launch with 196 blocks of 256 threads
|
||||
Copy output data from the CUDA device to the host memory
|
||||
Test PASSED
|
||||
Done
|
||||
```
|
||||
|
||||
### Tweaking the Quickstart
|
||||
|
||||
You can update [main.tf](./main.tf) to increase the number of nodes allocated to the Azure Batch pool or update [./aks/main.tf](./aks/main.tf) to increase the number of agent nodes allocated to your AKS cluster.
|
||||
|
||||
## Advanced Setup
|
||||
|
||||
## Prerequistes
|
||||
|
||||
1. An Azure Batch Account configurated
|
||||
2. An Azure Batch Pool created with necessary VM spec. VM's in the pool must have:
|
||||
- `docker` installed and correctly configured
|
||||
- `nvidia-docker` and `cuda` drivers installed
|
||||
3. K8s cluster
|
||||
4. Azure Service Principal with access to the Azure Batch Account
|
||||
|
||||
## Setup
|
||||
|
||||
The provider expects the following environment variables to be configured:
|
||||
|
||||
```
|
||||
ClientID: AZURE_CLIENT_ID
|
||||
ClientSecret: AZURE_CLIENT_SECRET
|
||||
ResourceGroup: AZURE_RESOURCE_GROUP
|
||||
SubscriptionID: AZURE_SUBSCRIPTION_ID
|
||||
TenantID: AZURE_TENANT_ID
|
||||
PoolID: AZURE_BATCH_POOLID
|
||||
JobID (optional):AZURE_BATCH_JOBID
|
||||
AccountLocation: AZURE_BATCH_ACCOUNT_LOCATION
|
||||
AccountName: AZURE_BATCH_ACCOUNT_NAME
|
||||
```
|
||||
|
||||
## Running
|
||||
|
||||
The provider will assign pods to machines in the Azure Batch Pool. Each machine can, by default, process only one pod at a time
|
||||
running more than 1 pod per machine isn't currently supported and will result in errors.
|
||||
|
||||
Azure Batch queues tasks when no machines are available so pods will sit in `podPending` state while waiting for a VM to become available.
|
||||
409
providers/azurebatch/batch.go
Normal file
409
providers/azurebatch/batch.go
Normal file
@@ -0,0 +1,409 @@
|
||||
package azurebatch
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch"
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
"github.com/lawrencegripper/pod2docker"
|
||||
"github.com/virtual-kubelet/virtual-kubelet/manager"
|
||||
azureCreds "github.com/virtual-kubelet/virtual-kubelet/providers/azure"
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
podJSONKey string = "virtualkubelet_pod"
|
||||
)
|
||||
|
||||
// Provider the base struct for the Azure Batch provider
|
||||
type Provider struct {
|
||||
batchConfig *Config
|
||||
ctx context.Context
|
||||
cancelCtx context.CancelFunc
|
||||
fileClient *batch.FileClient
|
||||
resourceManager *manager.ResourceManager
|
||||
listTasks func() (*[]batch.CloudTask, error)
|
||||
addTask func(batch.TaskAddParameter) (autorest.Response, error)
|
||||
getTask func(taskID string) (batch.CloudTask, error)
|
||||
deleteTask func(taskID string) (autorest.Response, error)
|
||||
getFileFromTask func(taskID, path string) (result batch.ReadCloser, err error)
|
||||
nodeName string
|
||||
operatingSystem string
|
||||
cpu string
|
||||
memory string
|
||||
pods string
|
||||
internalIP string
|
||||
daemonEndpointPort int32
|
||||
}
|
||||
|
||||
// Config - Basic azure config used to interact with ARM resources.
|
||||
type Config struct {
|
||||
ClientID string
|
||||
ClientSecret string
|
||||
SubscriptionID string
|
||||
TenantID string
|
||||
ResourceGroup string
|
||||
PoolID string
|
||||
JobID string
|
||||
AccountName string
|
||||
AccountLocation string
|
||||
}
|
||||
|
||||
// NewBatchProvider Creates a batch provider
|
||||
func NewBatchProvider(configString string, rm *manager.ResourceManager, nodeName, operatingSystem string, internalIP string, daemonEndpointPort int32) (*Provider, error) {
|
||||
fmt.Println("Starting create provider")
|
||||
|
||||
config := &Config{}
|
||||
if azureCredsFilepath := os.Getenv("AZURE_CREDENTIALS_LOCATION"); azureCredsFilepath != "" {
|
||||
creds, err := azureCreds.NewAcsCredential(azureCredsFilepath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.ClientID = creds.ClientID
|
||||
config.ClientSecret = creds.ClientSecret
|
||||
config.SubscriptionID = creds.SubscriptionID
|
||||
config.TenantID = creds.TenantID
|
||||
}
|
||||
|
||||
err := getAzureConfigFromEnv(config)
|
||||
if err != nil {
|
||||
log.Println("Failed to get auth information")
|
||||
}
|
||||
|
||||
return NewBatchProviderFromConfig(config, rm, nodeName, operatingSystem, internalIP, daemonEndpointPort)
|
||||
}
|
||||
|
||||
// NewBatchProviderFromConfig Creates a batch provider
|
||||
func NewBatchProviderFromConfig(config *Config, rm *manager.ResourceManager, nodeName, operatingSystem string, internalIP string, daemonEndpointPort int32) (*Provider, error) {
|
||||
p := Provider{}
|
||||
p.batchConfig = config
|
||||
// Set sane defaults for Capacity in case config is not supplied
|
||||
p.cpu = "20"
|
||||
p.memory = "100Gi"
|
||||
p.pods = "20"
|
||||
p.resourceManager = rm
|
||||
p.operatingSystem = operatingSystem
|
||||
p.nodeName = nodeName
|
||||
p.internalIP = internalIP
|
||||
p.daemonEndpointPort = daemonEndpointPort
|
||||
p.ctx, p.cancelCtx = context.WithCancel(context.Background())
|
||||
|
||||
auth := getAzureADAuthorizer(config, azure.PublicCloud.BatchManagementEndpoint)
|
||||
|
||||
batchBaseURL := getBatchBaseURL(config.AccountName, config.AccountLocation)
|
||||
_, err := getPool(p.ctx, batchBaseURL, config.PoolID, auth)
|
||||
if err != nil {
|
||||
log.Panicf("Error retreiving Azure Batch pool: %v", err)
|
||||
}
|
||||
_, err = createOrGetJob(p.ctx, batchBaseURL, config.JobID, config.PoolID, auth)
|
||||
if err != nil {
|
||||
log.Panicf("Error retreiving/creating Azure Batch job: %v", err)
|
||||
}
|
||||
taskClient := batch.NewTaskClientWithBaseURI(batchBaseURL)
|
||||
taskClient.Authorizer = auth
|
||||
p.listTasks = func() (*[]batch.CloudTask, error) {
|
||||
res, err := taskClient.List(p.ctx, config.JobID, "", "", "", nil, nil, nil, nil, nil)
|
||||
if err != nil {
|
||||
return &[]batch.CloudTask{}, err
|
||||
}
|
||||
currentTasks := res.Values()
|
||||
for res.NotDone() {
|
||||
err = res.Next()
|
||||
if err != nil {
|
||||
return &[]batch.CloudTask{}, err
|
||||
}
|
||||
pageTasks := res.Values()
|
||||
if pageTasks != nil || len(pageTasks) != 0 {
|
||||
currentTasks = append(currentTasks, pageTasks...)
|
||||
}
|
||||
}
|
||||
|
||||
return ¤tTasks, nil
|
||||
}
|
||||
p.addTask = func(task batch.TaskAddParameter) (autorest.Response, error) {
|
||||
return taskClient.Add(p.ctx, config.JobID, task, nil, nil, nil, nil)
|
||||
}
|
||||
p.getTask = func(taskID string) (batch.CloudTask, error) {
|
||||
return taskClient.Get(p.ctx, config.JobID, taskID, "", "", nil, nil, nil, nil, "", "", nil, nil)
|
||||
}
|
||||
p.deleteTask = func(taskID string) (autorest.Response, error) {
|
||||
return taskClient.Delete(p.ctx, config.JobID, taskID, nil, nil, nil, nil, "", "", nil, nil)
|
||||
}
|
||||
p.getFileFromTask = func(taskID, path string) (batch.ReadCloser, error) {
|
||||
return p.fileClient.GetFromTask(p.ctx, config.JobID, taskID, path, nil, nil, nil, nil, "", nil, nil)
|
||||
}
|
||||
|
||||
fileClient := batch.NewFileClientWithBaseURI(batchBaseURL)
|
||||
fileClient.Authorizer = auth
|
||||
p.fileClient = &fileClient
|
||||
|
||||
return &p, nil
|
||||
}
|
||||
|
||||
// CreatePod accepts a Pod definition
|
||||
func (p *Provider) CreatePod(pod *v1.Pod) error {
|
||||
log.Println("Creating pod...")
|
||||
podCommand, err := pod2docker.GetBashCommand(pod2docker.PodComponents{
|
||||
InitContainers: pod.Spec.InitContainers,
|
||||
Containers: pod.Spec.Containers,
|
||||
PodName: pod.Name,
|
||||
Volumes: pod.Spec.Volumes,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bytes, err := json.Marshal(pod)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
task := batch.TaskAddParameter{
|
||||
DisplayName: to.StringPtr(string(pod.UID)),
|
||||
ID: to.StringPtr(getTaskIDForPod(pod.Namespace, pod.Name)),
|
||||
CommandLine: to.StringPtr(fmt.Sprintf(`/bin/bash -c "%s"`, podCommand)),
|
||||
UserIdentity: &batch.UserIdentity{
|
||||
AutoUser: &batch.AutoUserSpecification{
|
||||
ElevationLevel: batch.Admin,
|
||||
Scope: batch.Pool,
|
||||
},
|
||||
},
|
||||
EnvironmentSettings: &[]batch.EnvironmentSetting{
|
||||
{
|
||||
Name: to.StringPtr(podJSONKey),
|
||||
Value: to.StringPtr(string(bytes)),
|
||||
},
|
||||
},
|
||||
}
|
||||
_, err = p.addTask(task)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPodStatus retrieves the status of a given pod by name.
|
||||
func (p *Provider) GetPodStatus(namespace, name string) (*v1.PodStatus, error) {
|
||||
log.Println("Getting pod status ....")
|
||||
pod, err := p.GetPod(namespace, name)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if pod == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return &pod.Status, nil
|
||||
}
|
||||
|
||||
// UpdatePod accepts a Pod definition
|
||||
func (p *Provider) UpdatePod(pod *v1.Pod) error {
|
||||
log.Println("Pod Update called: No-op as not implemented")
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeletePod accepts a Pod definition
|
||||
func (p *Provider) DeletePod(pod *v1.Pod) error {
|
||||
taskID := getTaskIDForPod(pod.Namespace, pod.Name)
|
||||
task, err := p.deleteTask(taskID)
|
||||
if err != nil {
|
||||
log.Println(task)
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf(fmt.Sprintf("Deleting task: %v", taskID))
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPod returns a pod by name
|
||||
func (p *Provider) GetPod(namespace, name string) (*v1.Pod, error) {
|
||||
log.Println("Getting Pod ...")
|
||||
task, err := p.getTask(getTaskIDForPod(namespace, name))
|
||||
if err != nil {
|
||||
if task.Response.StatusCode == http.StatusNotFound {
|
||||
return nil, nil
|
||||
}
|
||||
log.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pod, err := getPodFromTask(&task)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
status, _ := convertTaskToPodStatus(&task)
|
||||
pod.Status = *status
|
||||
|
||||
return pod, nil
|
||||
}
|
||||
|
||||
// GetContainerLogs returns the logs of a container running in a pod by name.
|
||||
func (p *Provider) GetContainerLogs(namespace, podName, containerName string, tail int) (string, error) {
|
||||
log.Println("Getting pod logs ....")
|
||||
|
||||
taskID := getTaskIDForPod(namespace, podName)
|
||||
logFileLocation := fmt.Sprintf("wd/%s.log", containerName)
|
||||
containerLogReader, err := p.getFileFromTask(taskID, logFileLocation)
|
||||
|
||||
if containerLogReader.Response.Response != nil && containerLogReader.StatusCode == http.StatusNotFound {
|
||||
stdoutReader, err := p.getFileFromTask(taskID, "stdout.txt")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
stderrReader, err := p.getFileFromTask(taskID, "stderr.txt")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var builder strings.Builder
|
||||
builderPtr := &builder
|
||||
mustWriteString(builderPtr, "Container still starting....\n")
|
||||
mustWriteString(builderPtr, "Showing startup logs from Azure Batch node instead:\n")
|
||||
mustWriteString(builderPtr, "----- STDOUT -----\n")
|
||||
stdoutBytes, _ := ioutil.ReadAll(*stdoutReader.Value)
|
||||
mustWrite(builderPtr, stdoutBytes)
|
||||
mustWriteString(builderPtr, "\n")
|
||||
|
||||
mustWriteString(builderPtr, "----- STDERR -----\n")
|
||||
stderrBytes, _ := ioutil.ReadAll(*stderrReader.Value)
|
||||
mustWrite(builderPtr, stderrBytes)
|
||||
mustWriteString(builderPtr, "\n")
|
||||
|
||||
return builder.String(), nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
result, err := formatLogJSON(containerLogReader)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Container log formating failed err: %v", err)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetPods retrieves a list of all pods scheduled to run.
|
||||
func (p *Provider) GetPods() ([]*v1.Pod, error) {
|
||||
log.Println("Getting pods...")
|
||||
tasksPtr, err := p.listTasks()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if tasksPtr == nil {
|
||||
return []*v1.Pod{}, nil
|
||||
}
|
||||
|
||||
tasks := *tasksPtr
|
||||
|
||||
pods := make([]*v1.Pod, len(tasks), len(tasks))
|
||||
for i, t := range tasks {
|
||||
pod, err := getPodFromTask(&t)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
pods[i] = pod
|
||||
}
|
||||
return pods, nil
|
||||
}
|
||||
|
||||
// Capacity returns a resource list containing the capacity limits
|
||||
func (p *Provider) Capacity() v1.ResourceList {
|
||||
return v1.ResourceList{
|
||||
"cpu": resource.MustParse(p.cpu),
|
||||
"memory": resource.MustParse(p.memory),
|
||||
"pods": resource.MustParse(p.pods),
|
||||
"nvidia.com/gpu": resource.MustParse("1"),
|
||||
}
|
||||
}
|
||||
|
||||
// NodeConditions returns a list of conditions (Ready, OutOfDisk, etc), for updates to the node status
|
||||
// within Kubernetes.
|
||||
func (p *Provider) NodeConditions() []v1.NodeCondition {
|
||||
return []v1.NodeCondition{
|
||||
{
|
||||
Type: "Ready",
|
||||
Status: v1.ConditionTrue,
|
||||
LastHeartbeatTime: metav1.Now(),
|
||||
LastTransitionTime: metav1.Now(),
|
||||
Reason: "KubeletReady",
|
||||
Message: "kubelet is ready.",
|
||||
},
|
||||
{
|
||||
Type: "OutOfDisk",
|
||||
Status: v1.ConditionFalse,
|
||||
LastHeartbeatTime: metav1.Now(),
|
||||
LastTransitionTime: metav1.Now(),
|
||||
Reason: "KubeletHasSufficientDisk",
|
||||
Message: "kubelet has sufficient disk space available",
|
||||
},
|
||||
{
|
||||
Type: "MemoryPressure",
|
||||
Status: v1.ConditionFalse,
|
||||
LastHeartbeatTime: metav1.Now(),
|
||||
LastTransitionTime: metav1.Now(),
|
||||
Reason: "KubeletHasSufficientMemory",
|
||||
Message: "kubelet has sufficient memory available",
|
||||
},
|
||||
{
|
||||
Type: "DiskPressure",
|
||||
Status: v1.ConditionFalse,
|
||||
LastHeartbeatTime: metav1.Now(),
|
||||
LastTransitionTime: metav1.Now(),
|
||||
Reason: "KubeletHasNoDiskPressure",
|
||||
Message: "kubelet has no disk pressure",
|
||||
},
|
||||
{
|
||||
Type: "NetworkUnavailable",
|
||||
Status: v1.ConditionFalse,
|
||||
LastHeartbeatTime: metav1.Now(),
|
||||
LastTransitionTime: metav1.Now(),
|
||||
Reason: "RouteCreated",
|
||||
Message: "RouteController created a route",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// NodeAddresses returns a list of addresses for the node status
|
||||
// within Kubernetes.
|
||||
func (p *Provider) NodeAddresses() []v1.NodeAddress {
|
||||
// TODO: Make these dynamic and augment with custom ACI specific conditions of interest
|
||||
return []v1.NodeAddress{
|
||||
{
|
||||
Type: "InternalIP",
|
||||
Address: p.internalIP,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// NodeDaemonEndpoints returns NodeDaemonEndpoints for the node status
|
||||
// within Kubernetes.
|
||||
func (p *Provider) NodeDaemonEndpoints() *v1.NodeDaemonEndpoints {
|
||||
return &v1.NodeDaemonEndpoints{
|
||||
KubeletEndpoint: v1.DaemonEndpoint{
|
||||
Port: p.daemonEndpointPort,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// OperatingSystem returns the operating system for this provider.
|
||||
func (p *Provider) OperatingSystem() string {
|
||||
return p.operatingSystem
|
||||
}
|
||||
216
providers/azurebatch/batch_helpers.go
Normal file
216
providers/azurebatch/batch_helpers.go
Normal file
@@ -0,0 +1,216 @@
|
||||
package azurebatch
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/Azure/go-autorest/autorest/adal"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
)
|
||||
|
||||
func mustWriteString(builder *strings.Builder, s string) {
|
||||
_, err := builder.WriteString(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func mustWrite(builder *strings.Builder, b []byte) {
|
||||
_, err := builder.Write(b)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// NewServicePrincipalTokenFromCredentials creates a new ServicePrincipalToken using values of the
|
||||
// passed credentials map.
|
||||
func newServicePrincipalTokenFromCredentials(c *Config, scope string) (*adal.ServicePrincipalToken, error) {
|
||||
oauthConfig, err := adal.NewOAuthConfig(azure.PublicCloud.ActiveDirectoryEndpoint, c.TenantID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return adal.NewServicePrincipalToken(*oauthConfig, c.ClientID, c.ClientSecret, scope)
|
||||
}
|
||||
|
||||
// GetAzureADAuthorizer return an authorizor for Azure SP
|
||||
func getAzureADAuthorizer(c *Config, azureEndpoint string) autorest.Authorizer {
|
||||
spt, err := newServicePrincipalTokenFromCredentials(c, azureEndpoint)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to create authorizer: %v", err))
|
||||
}
|
||||
auth := autorest.NewBearerAuthorizer(spt)
|
||||
return auth
|
||||
}
|
||||
|
||||
func getPool(ctx context.Context, batchBaseURL, poolID string, auth autorest.Authorizer) (*batch.PoolClient, error) {
|
||||
poolClient := batch.NewPoolClientWithBaseURI(batchBaseURL)
|
||||
poolClient.Authorizer = auth
|
||||
poolClient.RetryAttempts = 0
|
||||
|
||||
pool, err := poolClient.Get(ctx, poolID, "*", "", nil, nil, nil, nil, "", "", nil, nil)
|
||||
|
||||
// If we observe an error which isn't related to the pool not existing panic.
|
||||
// 404 is expected if this is first run.
|
||||
if err != nil && pool.Response.Response == nil {
|
||||
log.Printf("Failed to get pool. nil response %v", poolID)
|
||||
return nil, err
|
||||
} else if err != nil && pool.StatusCode == 404 {
|
||||
log.Printf("Pool doesn't exist 404 received Error: %v PoolID: %v", err, poolID)
|
||||
return nil, err
|
||||
} else if err != nil {
|
||||
log.Printf("Failed to get pool. Response:%v", pool.Response)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if pool.State == batch.PoolStateActive {
|
||||
log.Println("Pool active and running...")
|
||||
return &poolClient, nil
|
||||
}
|
||||
return nil, fmt.Errorf("Pool not in active state: %v", pool.State)
|
||||
}
|
||||
|
||||
func createOrGetJob(ctx context.Context, batchBaseURL, jobID, poolID string, auth autorest.Authorizer) (*batch.JobClient, error) {
|
||||
jobClient := batch.NewJobClientWithBaseURI(batchBaseURL)
|
||||
jobClient.Authorizer = auth
|
||||
// check if job exists already
|
||||
currentJob, err := jobClient.Get(ctx, jobID, "", "", nil, nil, nil, nil, "", "", nil, nil)
|
||||
|
||||
if err == nil && currentJob.State == batch.JobStateActive {
|
||||
log.Println("Wrapper job already exists...")
|
||||
return &jobClient, nil
|
||||
} else if currentJob.Response.StatusCode == 404 {
|
||||
|
||||
log.Println("Wrapper job missing... creating...")
|
||||
wrapperJob := batch.JobAddParameter{
|
||||
ID: &jobID,
|
||||
PoolInfo: &batch.PoolInformation{
|
||||
PoolID: &poolID,
|
||||
},
|
||||
}
|
||||
|
||||
_, err := jobClient.Add(ctx, wrapperJob, nil, nil, nil, nil)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &jobClient, nil
|
||||
|
||||
} else if currentJob.State == batch.JobStateDeleting {
|
||||
log.Printf("Job is being deleted... Waiting then will retry")
|
||||
time.Sleep(time.Minute)
|
||||
return createOrGetJob(ctx, batchBaseURL, jobID, poolID, auth)
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func getBatchBaseURL(batchAccountName, batchAccountLocation string) string {
|
||||
return fmt.Sprintf("https://%s.%s.batch.azure.com", batchAccountName, batchAccountLocation)
|
||||
}
|
||||
|
||||
func envHasValue(env string) bool {
|
||||
val := os.Getenv(env)
|
||||
if val == "" {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// GetConfigFromEnv - Retreives the azure configuration from environment variables.
|
||||
func getAzureConfigFromEnv(config *Config) error {
|
||||
if envHasValue("AZURE_CLIENT_ID") {
|
||||
config.ClientID = os.Getenv("AZURE_CLIENT_ID")
|
||||
}
|
||||
if envHasValue("AZURE_CLIENT_SECRET") {
|
||||
config.ClientSecret = os.Getenv("AZURE_CLIENT_SECRET")
|
||||
}
|
||||
if envHasValue("AZURE_RESOURCE_GROUP") {
|
||||
config.ResourceGroup = os.Getenv("AZURE_RESOURCE_GROUP")
|
||||
}
|
||||
if envHasValue("AZURE_SUBSCRIPTION_ID") {
|
||||
config.SubscriptionID = os.Getenv("AZURE_SUBSCRIPTION_ID")
|
||||
}
|
||||
if envHasValue("AZURE_TENANT_ID") {
|
||||
config.TenantID = os.Getenv("AZURE_TENANT_ID")
|
||||
}
|
||||
if envHasValue("AZURE_BATCH_POOLID") {
|
||||
config.PoolID = os.Getenv("AZURE_BATCH_POOLID")
|
||||
}
|
||||
if envHasValue("AZURE_BATCH_JOBID") {
|
||||
config.JobID = os.Getenv("AZURE_BATCH_JOBID")
|
||||
}
|
||||
if envHasValue("AZURE_BATCH_ACCOUNT_LOCATION") {
|
||||
config.AccountLocation = os.Getenv("AZURE_BATCH_ACCOUNT_LOCATION")
|
||||
}
|
||||
if envHasValue("AZURE_BATCH_ACCOUNT_NAME") {
|
||||
config.AccountName = os.Getenv("AZURE_BATCH_ACCOUNT_NAME")
|
||||
}
|
||||
|
||||
if config.JobID == "" {
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
config.JobID = hostname
|
||||
}
|
||||
|
||||
if config.ClientID == "" ||
|
||||
config.ClientSecret == "" ||
|
||||
config.ResourceGroup == "" ||
|
||||
config.SubscriptionID == "" ||
|
||||
config.PoolID == "" ||
|
||||
config.TenantID == "" {
|
||||
return &ConfigError{CurrentConfig: config, ErrorDetails: "Missing configuration"}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getTaskIDForPod(namespace, name string) string {
|
||||
ID := []byte(fmt.Sprintf("%s-%s", namespace, name))
|
||||
return string(fmt.Sprintf("%x", md5.Sum(ID)))
|
||||
}
|
||||
|
||||
type jsonLog struct {
|
||||
Log string `json:"log"`
|
||||
}
|
||||
|
||||
func formatLogJSON(readCloser batch.ReadCloser) (string, error) {
|
||||
//Read line by line as file isn't valid json. Each line is a single valid json object.
|
||||
scanner := bufio.NewScanner(*readCloser.Value)
|
||||
var b strings.Builder
|
||||
for scanner.Scan() {
|
||||
result := jsonLog{}
|
||||
err := json.Unmarshal(scanner.Bytes(), &result)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
mustWriteString(&b, result.Log)
|
||||
}
|
||||
|
||||
return b.String(), nil
|
||||
}
|
||||
|
||||
// ConfigError - Error when reading configuration values.
|
||||
type ConfigError struct {
|
||||
CurrentConfig *Config
|
||||
ErrorDetails string
|
||||
}
|
||||
|
||||
func (e *ConfigError) Error() string {
|
||||
configJSON, err := json.Marshal(e.CurrentConfig)
|
||||
if err != nil {
|
||||
return e.ErrorDetails
|
||||
}
|
||||
|
||||
return e.ErrorDetails + ": " + string(configJSON)
|
||||
}
|
||||
141
providers/azurebatch/batch_status.go
Normal file
141
providers/azurebatch/batch_status.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package azurebatch
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch"
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func getPodFromTask(task *batch.CloudTask) (pod *apiv1.Pod, err error) {
|
||||
if task == nil || task.EnvironmentSettings == nil {
|
||||
return nil, fmt.Errorf("invalid input task: %v", task)
|
||||
}
|
||||
|
||||
ok := false
|
||||
jsonData := ""
|
||||
settings := *task.EnvironmentSettings
|
||||
for _, s := range settings {
|
||||
if *s.Name == podJSONKey && s.Value != nil {
|
||||
ok = true
|
||||
jsonData = *s.Value
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("task doesn't have pod json stored in it: %v", task.EnvironmentSettings)
|
||||
}
|
||||
|
||||
pod = &apiv1.Pod{}
|
||||
err = json.Unmarshal([]byte(jsonData), pod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func convertTaskToPodStatus(task *batch.CloudTask) (status *apiv1.PodStatus, err error) {
|
||||
|
||||
pod, err := getPodFromTask(task)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Todo: Review indivudal container status response
|
||||
status = &apiv1.PodStatus{
|
||||
Phase: convertTaskStatusToPodPhase(task),
|
||||
Conditions: []apiv1.PodCondition{},
|
||||
Message: "",
|
||||
Reason: "",
|
||||
HostIP: "",
|
||||
PodIP: "127.0.0.1",
|
||||
StartTime: &pod.CreationTimestamp,
|
||||
}
|
||||
|
||||
for _, container := range pod.Spec.Containers {
|
||||
containerStatus := apiv1.ContainerStatus{
|
||||
Name: container.Name,
|
||||
State: convertTaskStatusToContainerState(task),
|
||||
Ready: true,
|
||||
RestartCount: 0,
|
||||
Image: container.Image,
|
||||
ImageID: "",
|
||||
ContainerID: "",
|
||||
}
|
||||
status.ContainerStatuses = append(status.ContainerStatuses, containerStatus)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func convertTaskStatusToPodPhase(t *batch.CloudTask) (podPhase apiv1.PodPhase) {
|
||||
switch t.State {
|
||||
case batch.TaskStatePreparing:
|
||||
podPhase = apiv1.PodPending
|
||||
case batch.TaskStateActive:
|
||||
podPhase = apiv1.PodPending
|
||||
case batch.TaskStateRunning:
|
||||
podPhase = apiv1.PodRunning
|
||||
case batch.TaskStateCompleted:
|
||||
podPhase = apiv1.PodFailed
|
||||
|
||||
if t.ExecutionInfo != nil && t.ExecutionInfo.ExitCode != nil && *t.ExecutionInfo.ExitCode == 0 {
|
||||
podPhase = apiv1.PodSucceeded
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func convertTaskStatusToContainerState(t *batch.CloudTask) (containerState apiv1.ContainerState) {
|
||||
|
||||
startTime := metav1.Time{}
|
||||
if t.ExecutionInfo != nil {
|
||||
if t.ExecutionInfo.StartTime != nil {
|
||||
startTime.Time = t.ExecutionInfo.StartTime.Time
|
||||
}
|
||||
}
|
||||
|
||||
switch t.State {
|
||||
case batch.TaskStatePreparing:
|
||||
containerState = apiv1.ContainerState{
|
||||
Waiting: &apiv1.ContainerStateWaiting{
|
||||
Message: "Waiting for machine in AzureBatch",
|
||||
Reason: "Preparing",
|
||||
},
|
||||
}
|
||||
case batch.TaskStateActive:
|
||||
containerState = apiv1.ContainerState{
|
||||
Waiting: &apiv1.ContainerStateWaiting{
|
||||
Message: "Waiting for machine in AzureBatch",
|
||||
Reason: "Queued",
|
||||
},
|
||||
}
|
||||
case batch.TaskStateRunning:
|
||||
containerState = apiv1.ContainerState{
|
||||
Running: &apiv1.ContainerStateRunning{
|
||||
StartedAt: startTime,
|
||||
},
|
||||
}
|
||||
case batch.TaskStateCompleted:
|
||||
termStatus := apiv1.ContainerState{
|
||||
Terminated: &apiv1.ContainerStateTerminated{
|
||||
FinishedAt: metav1.Time{
|
||||
Time: t.StateTransitionTime.Time,
|
||||
},
|
||||
StartedAt: startTime,
|
||||
},
|
||||
}
|
||||
|
||||
if t.ExecutionInfo != nil && t.ExecutionInfo.ExitCode != nil {
|
||||
exitCode := *t.ExecutionInfo.ExitCode
|
||||
termStatus.Terminated.ExitCode = exitCode
|
||||
if exitCode != 0 {
|
||||
termStatus.Terminated.Message = *t.ExecutionInfo.FailureInfo.Message
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
166
providers/azurebatch/batch_status_test.go
Normal file
166
providers/azurebatch/batch_status_test.go
Normal file
@@ -0,0 +1,166 @@
|
||||
package azurebatch
|
||||
|
||||
import (
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch"
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
func Test_getPodFromTask(t *testing.T) {
|
||||
type args struct {
|
||||
task *batch.CloudTask
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
task batch.CloudTask
|
||||
wantPod *apiv1.Pod
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "SimplePod",
|
||||
task: batch.CloudTask{
|
||||
EnvironmentSettings: &[]batch.EnvironmentSetting{
|
||||
{
|
||||
Name: to.StringPtr(podJSONKey),
|
||||
Value: to.StringPtr(`{"metadata":{"creationTimestamp":null},"spec":{"containers":[{"name":"web","image":"nginx:1.12","ports":[{"name":"http","containerPort":80,"protocol":"TCP"}],"resources":{}}]},"status":{}}`),
|
||||
},
|
||||
},
|
||||
},
|
||||
wantPod: &apiv1.Pod{
|
||||
Spec: apiv1.PodSpec{
|
||||
Containers: []apiv1.Container{
|
||||
{
|
||||
Name: "web",
|
||||
Image: "nginx:1.12",
|
||||
Ports: []apiv1.ContainerPort{
|
||||
{
|
||||
Name: "http",
|
||||
Protocol: apiv1.ProtocolTCP,
|
||||
ContainerPort: 80,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "InvalidJson",
|
||||
task: batch.CloudTask{
|
||||
EnvironmentSettings: &[]batch.EnvironmentSetting{
|
||||
{
|
||||
Name: to.StringPtr(podJSONKey),
|
||||
Value: to.StringPtr("---notjson--"),
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "NilEnvironment",
|
||||
task: batch.CloudTask{
|
||||
EnvironmentSettings: nil,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "NilString",
|
||||
task: batch.CloudTask{
|
||||
EnvironmentSettings: &[]batch.EnvironmentSetting{
|
||||
{
|
||||
Name: to.StringPtr(podJSONKey),
|
||||
Value: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotPod, err := getPodFromTask(&tt.task)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("getPodFromTask() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(gotPod, tt.wantPod) {
|
||||
|
||||
t.Errorf("getPodFromTask() = %v, want %v", gotPod, tt.wantPod)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_convertTaskStatusToPodPhase(t *testing.T) {
|
||||
type args struct {
|
||||
t *batch.CloudTask
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
task batch.CloudTask
|
||||
wantPodPhase apiv1.PodPhase
|
||||
}{
|
||||
{
|
||||
name: "PreparingTask",
|
||||
task: batch.CloudTask{
|
||||
State: batch.TaskStatePreparing,
|
||||
},
|
||||
wantPodPhase: apiv1.PodPending,
|
||||
},
|
||||
{
|
||||
//Active tasks are sitting in a queue waiting for a node
|
||||
// so maps best to pending state
|
||||
name: "ActiveTask",
|
||||
task: batch.CloudTask{
|
||||
State: batch.TaskStateActive,
|
||||
},
|
||||
wantPodPhase: apiv1.PodPending,
|
||||
},
|
||||
{
|
||||
name: "RunningTask",
|
||||
task: batch.CloudTask{
|
||||
State: batch.TaskStateRunning,
|
||||
},
|
||||
wantPodPhase: apiv1.PodRunning,
|
||||
},
|
||||
{
|
||||
name: "CompletedTask_ExitCode0",
|
||||
task: batch.CloudTask{
|
||||
State: batch.TaskStateCompleted,
|
||||
ExecutionInfo: &batch.TaskExecutionInformation{
|
||||
ExitCode: to.Int32Ptr(0),
|
||||
},
|
||||
},
|
||||
wantPodPhase: apiv1.PodSucceeded,
|
||||
},
|
||||
{
|
||||
name: "CompletedTask_ExitCode127",
|
||||
task: batch.CloudTask{
|
||||
State: batch.TaskStateCompleted,
|
||||
ExecutionInfo: &batch.TaskExecutionInformation{
|
||||
ExitCode: to.Int32Ptr(127),
|
||||
},
|
||||
},
|
||||
wantPodPhase: apiv1.PodFailed,
|
||||
},
|
||||
{
|
||||
name: "CompletedTask_nilExecInfo",
|
||||
task: batch.CloudTask{
|
||||
State: batch.TaskStateCompleted,
|
||||
ExecutionInfo: nil,
|
||||
},
|
||||
wantPodPhase: apiv1.PodFailed,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if gotPodPhase := convertTaskStatusToPodPhase(&tt.task); !reflect.DeepEqual(gotPodPhase, tt.wantPodPhase) {
|
||||
t.Errorf("convertTaskStatusToPodPhase() = %v, want %v", gotPodPhase, tt.wantPodPhase)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
165
providers/azurebatch/batch_test.go
Normal file
165
providers/azurebatch/batch_test.go
Normal file
@@ -0,0 +1,165 @@
|
||||
package azurebatch
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
func Test_deletePod(t *testing.T) {
|
||||
podNamespace := "bob"
|
||||
podName := "marley"
|
||||
concatName := []byte(fmt.Sprintf("%s-%s", podNamespace, podName))
|
||||
expectedDeleteTaskID := fmt.Sprintf("%x", md5.Sum(concatName))
|
||||
|
||||
provider := Provider{}
|
||||
provider.deleteTask = func(taskID string) (autorest.Response, error) {
|
||||
if taskID != expectedDeleteTaskID {
|
||||
t.Errorf("Deleted wrong task! Expected delete: %v Actual: %v", taskID, expectedDeleteTaskID)
|
||||
}
|
||||
return autorest.Response{}, nil
|
||||
}
|
||||
|
||||
pod := &apiv1.Pod{}
|
||||
pod.Name = podName
|
||||
pod.Namespace = podNamespace
|
||||
|
||||
err := provider.DeletePod(pod)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_deletePod_doesntExist(t *testing.T) {
|
||||
pod := &apiv1.Pod{}
|
||||
pod.Namespace = "bob"
|
||||
pod.Name = "marley"
|
||||
|
||||
provider := Provider{}
|
||||
provider.deleteTask = func(taskID string) (autorest.Response, error) {
|
||||
return autorest.Response{}, fmt.Errorf("Task doesn't exist")
|
||||
}
|
||||
|
||||
err := provider.DeletePod(pod)
|
||||
if err == nil {
|
||||
t.Error("Expected error but none seen")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_createPod(t *testing.T) {
|
||||
pod := &apiv1.Pod{}
|
||||
pod.Namespace = "bob"
|
||||
pod.Name = "marley"
|
||||
|
||||
provider := Provider{}
|
||||
provider.addTask = func(task batch.TaskAddParameter) (autorest.Response, error) {
|
||||
if task.CommandLine == nil || *task.CommandLine == "" {
|
||||
t.Error("Missing commandline args")
|
||||
}
|
||||
|
||||
derefVars := *task.EnvironmentSettings
|
||||
if len(derefVars) != 1 || *derefVars[0].Name != podJSONKey {
|
||||
t.Error("Missing pod json")
|
||||
}
|
||||
return autorest.Response{}, nil
|
||||
}
|
||||
|
||||
err := provider.CreatePod(pod)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error creating pod %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_createPod_errorResponse(t *testing.T) {
|
||||
pod := &apiv1.Pod{}
|
||||
pod.Namespace = "bob"
|
||||
pod.Name = "marley"
|
||||
|
||||
provider := Provider{}
|
||||
provider.addTask = func(task batch.TaskAddParameter) (autorest.Response, error) {
|
||||
return autorest.Response{}, fmt.Errorf("Failed creating task")
|
||||
}
|
||||
|
||||
err := provider.CreatePod(pod)
|
||||
if err == nil {
|
||||
t.Error("Expected error but none seen")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_readLogs_404Response_expectReturnStartupLogs(t *testing.T) {
|
||||
pod := &apiv1.Pod{}
|
||||
pod.Namespace = "bob"
|
||||
pod.Name = "marley"
|
||||
containerName := "sam"
|
||||
|
||||
provider := Provider{}
|
||||
provider.getFileFromTask = func(taskID, path string) (batch.ReadCloser, error) {
|
||||
if path == "wd/sam.log" {
|
||||
// Autorest - Seriously? Can't find a better way to make a 404 :(
|
||||
return batch.ReadCloser{Response: autorest.Response{Response: &http.Response{StatusCode: 404}}}, nil
|
||||
} else if path == "stderr.txt" {
|
||||
response := ioutil.NopCloser(strings.NewReader("stderrResponse"))
|
||||
return batch.ReadCloser{Value: &response}, nil
|
||||
} else if path == "stdout.txt" {
|
||||
response := ioutil.NopCloser(strings.NewReader("stdoutResponse"))
|
||||
return batch.ReadCloser{Value: &response}, nil
|
||||
} else {
|
||||
t.Errorf("Unexpected Filepath: %v", path)
|
||||
}
|
||||
|
||||
return batch.ReadCloser{}, fmt.Errorf("Failed in test mock of getFileFromTask")
|
||||
}
|
||||
|
||||
result, err := provider.GetContainerLogs(pod.Namespace, pod.Name, containerName, 0)
|
||||
if err != nil {
|
||||
t.Errorf("GetContainerLogs return error: %v", err)
|
||||
}
|
||||
|
||||
fmt.Print(result)
|
||||
|
||||
if !strings.Contains(result, "stderrResponse") || !strings.Contains(result, "stdoutResponse") {
|
||||
t.Errorf("Result didn't contain expected content have: %v", result)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Test_readLogs_JsonResponse_expectFormattedLogs(t *testing.T) {
|
||||
pod := &apiv1.Pod{}
|
||||
pod.Namespace = "bob"
|
||||
pod.Name = "marley"
|
||||
containerName := "sam"
|
||||
|
||||
provider := Provider{}
|
||||
provider.getFileFromTask = func(taskID, path string) (batch.ReadCloser, error) {
|
||||
if path == "wd/sam.log" {
|
||||
fileReader, err := os.Open("./testdata/logresponse.json")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
readCloser := ioutil.NopCloser(fileReader)
|
||||
return batch.ReadCloser{Value: &readCloser, Response: autorest.Response{Response: &http.Response{StatusCode: 200}}}, nil
|
||||
}
|
||||
|
||||
t.Errorf("Unexpected Filepath: %v", path)
|
||||
return batch.ReadCloser{}, fmt.Errorf("Failed in test mock of getFileFromTask")
|
||||
}
|
||||
|
||||
result, err := provider.GetContainerLogs(pod.Namespace, pod.Name, containerName, 0)
|
||||
if err != nil {
|
||||
t.Errorf("GetContainerLogs return error: %v", err)
|
||||
}
|
||||
|
||||
fmt.Print(result)
|
||||
if !strings.Contains(result, "Copy output data from the CUDA device to the host memory") || strings.Contains(result, "{") {
|
||||
t.Errorf("Result didn't contain expected content have or had json: %v", result)
|
||||
}
|
||||
|
||||
}
|
||||
59
providers/azurebatch/deployment/aks/main.tf
Normal file
59
providers/azurebatch/deployment/aks/main.tf
Normal file
@@ -0,0 +1,59 @@
|
||||
resource "random_id" "workspace" {
|
||||
keepers = {
|
||||
# Generate a new id each time we switch to a new resource group
|
||||
group_name = "${var.resource_group_name}"
|
||||
}
|
||||
|
||||
byte_length = 8
|
||||
}
|
||||
|
||||
#an attempt to keep the AKS name (and dns label) somewhat unique
|
||||
resource "random_integer" "random_int" {
|
||||
min = 100
|
||||
max = 999
|
||||
}
|
||||
|
||||
resource "azurerm_kubernetes_cluster" "aks" {
|
||||
name = "aks-${random_integer.random_int.result}"
|
||||
location = "${var.resource_group_location}"
|
||||
dns_prefix = "aks-${random_integer.random_int.result}"
|
||||
|
||||
resource_group_name = "${var.resource_group_name}"
|
||||
kubernetes_version = "1.9.2"
|
||||
|
||||
linux_profile {
|
||||
admin_username = "${var.linux_admin_username}"
|
||||
|
||||
ssh_key {
|
||||
key_data = "${var.linux_admin_ssh_publickey}"
|
||||
}
|
||||
}
|
||||
|
||||
agent_pool_profile {
|
||||
name = "agentpool"
|
||||
count = "2"
|
||||
vm_size = "Standard_DS2_v2"
|
||||
os_type = "Linux"
|
||||
}
|
||||
|
||||
service_principal {
|
||||
client_id = "${var.client_id}"
|
||||
client_secret = "${var.client_secret}"
|
||||
}
|
||||
}
|
||||
|
||||
output "cluster_client_certificate" {
|
||||
value = "${base64decode(azurerm_kubernetes_cluster.aks.kube_config.0.client_certificate)}"
|
||||
}
|
||||
|
||||
output "cluster_client_key" {
|
||||
value = "${base64decode(azurerm_kubernetes_cluster.aks.kube_config.0.client_key)}"
|
||||
}
|
||||
|
||||
output "cluster_ca" {
|
||||
value = "${base64decode(azurerm_kubernetes_cluster.aks.kube_config.0.cluster_ca_certificate)}"
|
||||
}
|
||||
|
||||
output "host" {
|
||||
value = "${azurerm_kubernetes_cluster.aks.kube_config.0.host}"
|
||||
}
|
||||
31
providers/azurebatch/deployment/aks/variables.tf
Normal file
31
providers/azurebatch/deployment/aks/variables.tf
Normal file
@@ -0,0 +1,31 @@
|
||||
variable "client_id" {
|
||||
type = "string"
|
||||
description = "Client ID"
|
||||
}
|
||||
|
||||
variable "client_secret" {
|
||||
type = "string"
|
||||
description = "Client secret."
|
||||
}
|
||||
|
||||
variable "resource_group_name" {
|
||||
type = "string"
|
||||
description = "Name of the azure resource group."
|
||||
default = "akc-rg"
|
||||
}
|
||||
|
||||
variable "resource_group_location" {
|
||||
type = "string"
|
||||
description = "Location of the azure resource group."
|
||||
default = "eastus"
|
||||
}
|
||||
|
||||
variable "linux_admin_username" {
|
||||
type = "string"
|
||||
description = "User name for authentication to the Kubernetes linux agent virtual machines in the cluster."
|
||||
}
|
||||
|
||||
variable "linux_admin_ssh_publickey" {
|
||||
type = "string"
|
||||
description = "Configure all the linux virtual machines in the cluster with the SSH RSA public key string. The key should include three parts, for example 'ssh-rsa AAAAB...snip...UcyupgH azureuser@linuxvm'"
|
||||
}
|
||||
146
providers/azurebatch/deployment/azurebatch/main.tf
Normal file
146
providers/azurebatch/deployment/azurebatch/main.tf
Normal file
@@ -0,0 +1,146 @@
|
||||
resource "random_string" "batchname" {
|
||||
keepers = {
|
||||
# Generate a new id each time we switch to a new resource group
|
||||
group_name = "${var.resource_group_name}"
|
||||
}
|
||||
|
||||
length = 8
|
||||
upper = false
|
||||
special = false
|
||||
number = false
|
||||
}
|
||||
|
||||
resource "azurerm_template_deployment" "test" {
|
||||
name = "tfdeployment"
|
||||
resource_group_name = "${var.resource_group_name}"
|
||||
|
||||
# these key-value pairs are passed into the ARM Template's `parameters` block
|
||||
parameters {
|
||||
"batchAccountName" = "${random_string.batchname.result}"
|
||||
"storageAccountID" = "${var.storage_account_id}"
|
||||
"poolBoostrapScriptUrl" = "${var.pool_bootstrap_script_url}"
|
||||
"location" = "${var.resource_group_location}"
|
||||
"poolID" = "${var.pool_id}"
|
||||
"vmSku" = "${var.vm_sku}"
|
||||
"lowPriorityNodeCount" = "${var.low_priority_node_count}"
|
||||
"dedicatedNodeCount" = "${var.dedicated_node_count}"
|
||||
}
|
||||
|
||||
deployment_mode = "Incremental"
|
||||
|
||||
template_body = <<DEPLOY
|
||||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"batchAccountName": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "Batch Account Name"
|
||||
}
|
||||
},
|
||||
"poolID": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "GPU Pool ID"
|
||||
}
|
||||
},
|
||||
"dedicatedNodeCount": {
|
||||
"type": "string"
|
||||
},
|
||||
"lowPriorityNodeCount": {
|
||||
"type": "string"
|
||||
},
|
||||
"vmSku": {
|
||||
"type": "string"
|
||||
},
|
||||
"storageAccountID": {
|
||||
"type": "string"
|
||||
},
|
||||
"poolBoostrapScriptUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
"location": {
|
||||
"type": "string",
|
||||
"defaultValue": "[resourceGroup().location]",
|
||||
"metadata": {
|
||||
"description": "Location for all resources."
|
||||
}
|
||||
}
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"type": "Microsoft.Batch/batchAccounts",
|
||||
"name": "[parameters('batchAccountName')]",
|
||||
"apiVersion": "2015-12-01",
|
||||
"location": "[parameters('location')]",
|
||||
"tags": {
|
||||
"ObjectName": "[parameters('batchAccountName')]"
|
||||
},
|
||||
"properties": {
|
||||
"autoStorage": {
|
||||
"storageAccountId": "[parameters('storageAccountID')]"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Batch/batchAccounts/pools",
|
||||
"name": "[concat(parameters('batchAccountName'), '/', parameters('poolID'))]",
|
||||
"apiVersion": "2017-09-01",
|
||||
"scale": null,
|
||||
"properties": {
|
||||
"vmSize": "STANDARD_NC6",
|
||||
"interNodeCommunication": "Disabled",
|
||||
"maxTasksPerNode": 1,
|
||||
"taskSchedulingPolicy": {
|
||||
"nodeFillType": "Spread"
|
||||
},
|
||||
"startTask": {
|
||||
"commandLine": "/bin/bash -c ./init.sh",
|
||||
"resourceFiles": [
|
||||
{
|
||||
"blobSource": "[parameters('poolBoostrapScriptUrl')]",
|
||||
"fileMode": "777",
|
||||
"filePath": "./init.sh"
|
||||
}
|
||||
],
|
||||
"userIdentity": {
|
||||
"autoUser": {
|
||||
"elevationLevel": "Admin",
|
||||
"scope": "Pool"
|
||||
}
|
||||
},
|
||||
"waitForSuccess": true,
|
||||
"maxTaskRetryCount": 0
|
||||
},
|
||||
"deploymentConfiguration": {
|
||||
"virtualMachineConfiguration": {
|
||||
"imageReference": {
|
||||
"publisher": "Canonical",
|
||||
"offer": "UbuntuServer",
|
||||
"sku": "16.04-LTS",
|
||||
"version": "latest"
|
||||
},
|
||||
"nodeAgentSkuId": "batch.node.ubuntu 16.04"
|
||||
}
|
||||
},
|
||||
"scaleSettings": {
|
||||
"fixedScale": {
|
||||
"targetDedicatedNodes": "[parameters('dedicatedNodeCount')]",
|
||||
"targetLowPriorityNodes": "[parameters('lowPriorityNodeCount')]",
|
||||
"resizeTimeout": "PT15M"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Batch/batchAccounts', parameters('batchAccountName'))]"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
DEPLOY
|
||||
}
|
||||
|
||||
output "name" {
|
||||
value = "${random_string.batchname.result}"
|
||||
}
|
||||
43
providers/azurebatch/deployment/azurebatch/variables.tf
Normal file
43
providers/azurebatch/deployment/azurebatch/variables.tf
Normal file
@@ -0,0 +1,43 @@
|
||||
variable "pool_id" {
|
||||
type = "string"
|
||||
description = "Name of the Azure Batch pool to create."
|
||||
default = "pool1"
|
||||
}
|
||||
|
||||
variable "vm_sku" {
|
||||
type = "string"
|
||||
description = "VM SKU to use - Default to NC6 GPU SKU."
|
||||
default = "STANDARD_NC6"
|
||||
}
|
||||
|
||||
variable "pool_bootstrap_script_url" {
|
||||
type = "string"
|
||||
description = "Publicly accessible url used for boostrapping nodes in the pool. Installing GPU drivers, for example."
|
||||
}
|
||||
|
||||
variable "storage_account_id" {
|
||||
type = "string"
|
||||
description = "Name of the storage account to be used by Azure Batch"
|
||||
}
|
||||
|
||||
variable "resource_group_name" {
|
||||
type = "string"
|
||||
description = "Name of the azure resource group."
|
||||
default = "akc-rg"
|
||||
}
|
||||
|
||||
variable "resource_group_location" {
|
||||
type = "string"
|
||||
description = "Location of the azure resource group."
|
||||
default = "eastus"
|
||||
}
|
||||
|
||||
variable "low_priority_node_count" {
|
||||
type = "string"
|
||||
description = "The number of low priority nodes to allocate to the pool"
|
||||
}
|
||||
|
||||
variable "dedicated_node_count" {
|
||||
type = "string"
|
||||
description = "The number dedicated nodes to allocate to the pool"
|
||||
}
|
||||
19
providers/azurebatch/deployment/examplegpupod.yaml
Normal file
19
providers/azurebatch/deployment/examplegpupod.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: cuda-vector-add
|
||||
labels:
|
||||
app: examplegpupod
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: cuda-vector-add
|
||||
# https://github.com/kubernetes/kubernetes/blob/v1.7.11/test/images/nvidia-cuda/Dockerfile
|
||||
image: "k8s.gcr.io/cuda-vector-add:v0.1"
|
||||
resources:
|
||||
limits:
|
||||
nvidia.com/gpu: 1 # requesting 1 GPU
|
||||
nodeName: virtual-kubelet
|
||||
tolerations:
|
||||
- key: azure.com/batch
|
||||
effect: NoSchedule
|
||||
20
providers/azurebatch/deployment/examplenvidiasmi.yaml
Normal file
20
providers/azurebatch/deployment/examplenvidiasmi.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: exampegpujob
|
||||
spec:
|
||||
containers:
|
||||
- image: nvidia/cuda
|
||||
command: ["nvidia-smi"]
|
||||
imagePullPolicy: Always
|
||||
name: nvidia
|
||||
resources:
|
||||
requests:
|
||||
memory: 1G
|
||||
cpu: 1
|
||||
limits:
|
||||
nvidia.com/gpu: 1 # requesting 1 GPU
|
||||
nodeName: virtual-kubelet
|
||||
tolerations:
|
||||
- key: azure.com/batch
|
||||
effect: NoSchedule
|
||||
53
providers/azurebatch/deployment/main.tf
Normal file
53
providers/azurebatch/deployment/main.tf
Normal file
@@ -0,0 +1,53 @@
|
||||
resource "azurerm_resource_group" "batchrg" {
|
||||
name = "${var.resource_group_name}"
|
||||
location = "${var.resource_group_location}"
|
||||
}
|
||||
|
||||
module "aks" {
|
||||
source = "aks"
|
||||
|
||||
//Defaults to using current ssh key: recomend changing as needed
|
||||
linux_admin_username = "aks"
|
||||
linux_admin_ssh_publickey = "${file("~/.ssh/id_rsa.pub")}"
|
||||
|
||||
client_id = "${var.client_id}"
|
||||
client_secret = "${var.client_secret}"
|
||||
|
||||
resource_group_name = "${azurerm_resource_group.batchrg.name}"
|
||||
resource_group_location = "${azurerm_resource_group.batchrg.location}"
|
||||
}
|
||||
|
||||
module "storage" {
|
||||
source = "storage"
|
||||
pool_bootstrap_script_path = "./scripts/poolstartup.sh"
|
||||
|
||||
resource_group_name = "${azurerm_resource_group.batchrg.name}"
|
||||
resource_group_location = "${azurerm_resource_group.batchrg.location}"
|
||||
}
|
||||
|
||||
module "azurebatch" {
|
||||
source = "azurebatch"
|
||||
|
||||
storage_account_id = "${module.storage.id}"
|
||||
pool_bootstrap_script_url = "${module.storage.pool_boostrap_script_url}"
|
||||
|
||||
resource_group_name = "${azurerm_resource_group.batchrg.name}"
|
||||
resource_group_location = "${azurerm_resource_group.batchrg.location}"
|
||||
|
||||
dedicated_node_count = 1
|
||||
low_priority_node_count = 2
|
||||
}
|
||||
|
||||
module "virtualkubelet" {
|
||||
source = "virtualkubelet"
|
||||
virtualkubelet_docker_image = "${var.virtualkubelet_docker_image}"
|
||||
|
||||
cluster_client_key = "${module.aks.cluster_client_key}"
|
||||
cluster_client_certificate = "${module.aks.cluster_client_certificate}"
|
||||
cluster_ca = "${module.aks.cluster_ca}"
|
||||
cluster_host = "${module.aks.host}"
|
||||
|
||||
azure_batch_account_name = "${module.azurebatch.name}"
|
||||
|
||||
resource_group_location = "${azurerm_resource_group.batchrg.location}"
|
||||
}
|
||||
49
providers/azurebatch/deployment/scripts/poolstartup.sh
Normal file
49
providers/azurebatch/deployment/scripts/poolstartup.sh
Normal file
@@ -0,0 +1,49 @@
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
export TEMP_DISK=/mnt
|
||||
|
||||
apt-get install -y -q --no-install-recommends \
|
||||
build-essential
|
||||
|
||||
|
||||
# Add dockerce repo
|
||||
apt-get update -y -q --no-install-recommends
|
||||
apt-get install -y -q -o Dpkg::Options::="--force-confnew" --no-install-recommends \
|
||||
apt-transport-https ca-certificates curl software-properties-common cgroup-lite
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
|
||||
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
|
||||
apt-get update
|
||||
|
||||
|
||||
#Install latest cuda driver..
|
||||
CUDA_REPO_PKG=cuda-repo-ubuntu1604_9.1.85-1_amd64.deb
|
||||
wget -O /tmp/${CUDA_REPO_PKG} http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/${CUDA_REPO_PKG}
|
||||
sudo dpkg -i /tmp/${CUDA_REPO_PKG}
|
||||
sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub
|
||||
rm -f /tmp/${CUDA_REPO_PKG}
|
||||
sudo apt-get update -y -q --no-install-recommends
|
||||
sudo apt-get install cuda-drivers -y -q --no-install-recommends
|
||||
|
||||
# install nvidia-docker
|
||||
curl -fSsL https://nvidia.github.io/nvidia-docker/gpgkey | apt-key add -
|
||||
curl -fSsL https://nvidia.github.io/nvidia-docker/ubuntu16.04/amd64/nvidia-docker.list | \
|
||||
tee /etc/apt/sources.list.d/nvidia-docker.list
|
||||
apt-get update -y -q --no-install-recommends
|
||||
apt-get install -y -q --no-install-recommends -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" nvidia-docker2
|
||||
systemctl restart docker.service
|
||||
nvidia-docker version
|
||||
|
||||
# prep docker
|
||||
systemctl stop docker.service
|
||||
rm -rf /var/lib/docker
|
||||
mkdir -p /etc/docker
|
||||
mkdir -p $TEMPDISK/docker
|
||||
chmod 777 $TEMPDISK/docker
|
||||
echo "{ \"data-root\": \"$TEMP_DISK/docker\", \"hosts\": [ \"unix:///var/run/docker.sock\", \"tcp://127.0.0.1:2375\" ] }" > /etc/docker/daemon.json.merge
|
||||
python -c "import json;a=json.load(open('/etc/docker/daemon.json.merge'));b=json.load(open('/etc/docker/daemon.json'));a.update(b);f=open('/etc/docker/daemon.json','w');json.dump(a,f);f.close();"
|
||||
rm -f /etc/docker/daemon.json.merge
|
||||
sed -i 's|^ExecStart=/usr/bin/dockerd.*|ExecStart=/usr/bin/dockerd|' /lib/systemd/system/docker.service
|
||||
systemctl daemon-reload
|
||||
systemctl start docker.service
|
||||
|
||||
|
||||
|
||||
77
providers/azurebatch/deployment/storage/main.tf
Normal file
77
providers/azurebatch/deployment/storage/main.tf
Normal file
@@ -0,0 +1,77 @@
|
||||
resource "random_string" "storage" {
|
||||
keepers = {
|
||||
# Generate a new id each time we switch to a new resource group
|
||||
group_name = "${var.resource_group_name}"
|
||||
}
|
||||
|
||||
length = 8
|
||||
upper = false
|
||||
special = false
|
||||
number = false
|
||||
}
|
||||
|
||||
resource "azurerm_storage_account" "batchstorage" {
|
||||
name = "${lower(random_string.storage.result)}"
|
||||
resource_group_name = "${var.resource_group_name}"
|
||||
location = "${var.resource_group_location}"
|
||||
account_tier = "Standard"
|
||||
account_replication_type = "LRS"
|
||||
}
|
||||
|
||||
resource "azurerm_storage_container" "boostrapscript" {
|
||||
name = "scripts"
|
||||
resource_group_name = "${var.resource_group_name}"
|
||||
storage_account_name = "${azurerm_storage_account.batchstorage.name}"
|
||||
container_access_type = "private"
|
||||
}
|
||||
|
||||
resource "azurerm_storage_blob" "initscript" {
|
||||
name = "init.sh"
|
||||
|
||||
resource_group_name = "${var.resource_group_name}"
|
||||
storage_account_name = "${azurerm_storage_account.batchstorage.name}"
|
||||
storage_container_name = "${azurerm_storage_container.boostrapscript.name}"
|
||||
|
||||
type = "block"
|
||||
source = "${var.pool_bootstrap_script_path}"
|
||||
}
|
||||
|
||||
data "azurerm_storage_account_sas" "scriptaccess" {
|
||||
connection_string = "${azurerm_storage_account.batchstorage.primary_connection_string}"
|
||||
https_only = true
|
||||
|
||||
resource_types {
|
||||
service = false
|
||||
container = false
|
||||
object = true
|
||||
}
|
||||
|
||||
services {
|
||||
blob = true
|
||||
queue = false
|
||||
table = false
|
||||
file = false
|
||||
}
|
||||
|
||||
start = "${timestamp()}"
|
||||
expiry = "${timeadd(timestamp(), "8776h")}"
|
||||
|
||||
permissions {
|
||||
read = true
|
||||
write = false
|
||||
delete = false
|
||||
list = false
|
||||
add = false
|
||||
create = false
|
||||
update = false
|
||||
process = false
|
||||
}
|
||||
}
|
||||
|
||||
output "pool_boostrap_script_url" {
|
||||
value = "${azurerm_storage_blob.initscript.url}${data.azurerm_storage_account_sas.scriptaccess.sas}"
|
||||
}
|
||||
|
||||
output "id" {
|
||||
value = "${azurerm_storage_account.batchstorage.id}"
|
||||
}
|
||||
14
providers/azurebatch/deployment/storage/variables.tf
Normal file
14
providers/azurebatch/deployment/storage/variables.tf
Normal file
@@ -0,0 +1,14 @@
|
||||
variable "resource_group_name" {
|
||||
description = "Resource group name"
|
||||
type = "string"
|
||||
}
|
||||
|
||||
variable "resource_group_location" {
|
||||
description = "Resource group location"
|
||||
type = "string"
|
||||
}
|
||||
|
||||
variable "pool_bootstrap_script_path" {
|
||||
description = "The filepath of the pool boostrapping script"
|
||||
type = "string"
|
||||
}
|
||||
23
providers/azurebatch/deployment/variables.tf
Normal file
23
providers/azurebatch/deployment/variables.tf
Normal file
@@ -0,0 +1,23 @@
|
||||
variable "client_id" {
|
||||
type = "string"
|
||||
description = "Client ID"
|
||||
}
|
||||
|
||||
variable "client_secret" {
|
||||
type = "string"
|
||||
description = "Client secret."
|
||||
}
|
||||
|
||||
variable "resource_group_name" {
|
||||
description = "Resource group name"
|
||||
type = "string"
|
||||
}
|
||||
|
||||
variable "resource_group_location" {
|
||||
description = "Resource group location"
|
||||
type = "string"
|
||||
}
|
||||
|
||||
variable "virtualkubelet_docker_image" {
|
||||
type = "string"
|
||||
}
|
||||
14
providers/azurebatch/deployment/vars.example.tfvars
Normal file
14
providers/azurebatch/deployment/vars.example.tfvars
Normal file
@@ -0,0 +1,14 @@
|
||||
// Provide the Client ID of a service principal for use by AKS
|
||||
client_id = "00000000-0000-0000-0000-000000000000"
|
||||
|
||||
// Provide the Client Secret of a service principal for use by AKS
|
||||
client_secret = "00000000-0000-0000-0000-000000000000"
|
||||
|
||||
// The resource group you would like to deploy too
|
||||
resource_group_name = "vkgpu"
|
||||
|
||||
// The location of all resources
|
||||
resource_group_location = "westeurope"
|
||||
|
||||
// Virtual Kubelet docker image
|
||||
virtualkubelet_docker_image = "microsoft/virtual-kubelet"
|
||||
126
providers/azurebatch/deployment/virtualkubelet/main.tf
Normal file
126
providers/azurebatch/deployment/virtualkubelet/main.tf
Normal file
@@ -0,0 +1,126 @@
|
||||
provider "kubernetes" {
|
||||
host = "${var.cluster_host}"
|
||||
|
||||
client_certificate = "${var.cluster_client_certificate}"
|
||||
client_key = "${var.cluster_client_key}"
|
||||
cluster_ca_certificate = "${var.cluster_ca}"
|
||||
}
|
||||
|
||||
resource "kubernetes_secret" "vkcredentials" {
|
||||
metadata {
|
||||
name = "vkcredentials"
|
||||
}
|
||||
|
||||
data {
|
||||
cert.pem = "${var.cluster_client_certificate}"
|
||||
key.pem = "${var.cluster_client_key}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_deployment" "vkdeployment" {
|
||||
metadata {
|
||||
name = "vkdeployment"
|
||||
}
|
||||
|
||||
spec {
|
||||
selector {
|
||||
app = "virtualkubelet"
|
||||
}
|
||||
|
||||
template {
|
||||
metadata {
|
||||
labels {
|
||||
app = "virtualkubelet"
|
||||
}
|
||||
}
|
||||
|
||||
spec {
|
||||
container {
|
||||
name = "vk"
|
||||
image = "${var.virtualkubelet_docker_image}"
|
||||
|
||||
args = [
|
||||
"--provider",
|
||||
"azurebatch",
|
||||
"--taint",
|
||||
"azure.com/batch",
|
||||
"--namespace",
|
||||
"default",
|
||||
]
|
||||
|
||||
port {
|
||||
container_port = 10250
|
||||
protocol = "TCP"
|
||||
name = "kubeletport"
|
||||
}
|
||||
|
||||
volume_mount {
|
||||
name = "azure-credentials"
|
||||
mount_path = "/etc/aks/azure.json"
|
||||
}
|
||||
|
||||
volume_mount {
|
||||
name = "credentials"
|
||||
mount_path = "/etc/virtual-kubelet"
|
||||
}
|
||||
|
||||
env = [
|
||||
{
|
||||
name = "AZURE_BATCH_ACCOUNT_LOCATION"
|
||||
value = "${var.resource_group_location}"
|
||||
},
|
||||
{
|
||||
name = "AZURE_BATCH_ACCOUNT_NAME"
|
||||
value = "${var.azure_batch_account_name}"
|
||||
},
|
||||
{
|
||||
name = "AZURE_BATCH_POOLID"
|
||||
value = "${var.azure_batch_pool_id}"
|
||||
},
|
||||
{
|
||||
name = "KUBELET_PORT"
|
||||
value = "10250"
|
||||
},
|
||||
{
|
||||
name = "AZURE_CREDENTIALS_LOCATION"
|
||||
value = "/etc/aks/azure.json"
|
||||
},
|
||||
{
|
||||
name = "APISERVER_CERT_LOCATION"
|
||||
value = "/etc/virtual-kubelet/cert.pem"
|
||||
},
|
||||
{
|
||||
name = "APISERVER_KEY_LOCATION"
|
||||
value = "/etc/virtual-kubelet/key.pem"
|
||||
},
|
||||
{
|
||||
name = "VKUBELET_POD_IP"
|
||||
|
||||
value_from {
|
||||
field_ref {
|
||||
field_path = "status.podIP"
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
volume {
|
||||
name = "azure-credentials"
|
||||
|
||||
host_path {
|
||||
path = "/etc/kubernetes/azure.json"
|
||||
}
|
||||
}
|
||||
|
||||
volume {
|
||||
name = "credentials"
|
||||
|
||||
secret {
|
||||
secret_name = "vkcredentials"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
41
providers/azurebatch/deployment/virtualkubelet/variables.tf
Normal file
41
providers/azurebatch/deployment/virtualkubelet/variables.tf
Normal file
@@ -0,0 +1,41 @@
|
||||
variable "cluster_client_certificate" {
|
||||
type = "string"
|
||||
description = "Cluster client Certificate"
|
||||
default = "eastus"
|
||||
}
|
||||
|
||||
variable "cluster_client_key" {
|
||||
type = "string"
|
||||
description = "Cluster client Certificate Key"
|
||||
}
|
||||
|
||||
variable "cluster_ca" {
|
||||
type = "string"
|
||||
description = "Cluster Certificate Authority"
|
||||
}
|
||||
|
||||
variable "cluster_host" {
|
||||
type = "string"
|
||||
description = "Cluster Admin API host"
|
||||
}
|
||||
|
||||
variable "virtualkubelet_docker_image" {
|
||||
type = "string"
|
||||
description = "The docker image to use for deploying the virtual kubelet"
|
||||
}
|
||||
|
||||
variable "azure_batch_account_name" {
|
||||
type = "string"
|
||||
description = "The name of the Azure Batch account to use"
|
||||
}
|
||||
|
||||
variable "azure_batch_pool_id" {
|
||||
type = "string"
|
||||
description = "The PoolID to use in Azure batch"
|
||||
default = "pool1"
|
||||
}
|
||||
|
||||
variable "resource_group_location" {
|
||||
description = "Resource group location"
|
||||
type = "string"
|
||||
}
|
||||
6
providers/azurebatch/testdata/logresponse.json
vendored
Normal file
6
providers/azurebatch/testdata/logresponse.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{"log":"[Vector addition of 50000 elements]\n","stream":"stdout","time":"2018-05-30T17:02:49.967357287Z"}
|
||||
{"log":"Copy input data from the host memory to the CUDA device\n","stream":"stdout","time":"2018-05-30T17:02:49.967417086Z"}
|
||||
{"log":"CUDA kernel launch with 196 blocks of 256 threads\n","stream":"stdout","time":"2018-05-30T17:02:49.967423286Z"}
|
||||
{"log":"Copy output data from the CUDA device to the host memory\n","stream":"stdout","time":"2018-05-30T17:02:49.967427386Z"}
|
||||
{"log":"Test PASSED\n","stream":"stdout","time":"2018-05-30T17:02:49.967431286Z"}
|
||||
{"log":"Done\n","stream":"stdout","time":"2018-05-30T17:02:49.967435286Z"}
|
||||
@@ -616,7 +616,7 @@ func readLogFile(filename string, tail int) (string, error) {
|
||||
lines = append(lines, scanner.Text())
|
||||
}
|
||||
if tail > 0 && tail < len(lines) {
|
||||
lines = lines[len(lines)-tail : len(lines)]
|
||||
lines = lines[len(lines)-tail:]
|
||||
}
|
||||
return strings.Join(lines, ""), nil
|
||||
}
|
||||
@@ -636,7 +636,7 @@ func (p *CRIProvider) GetContainerLogs(namespace, podName, containerName string,
|
||||
}
|
||||
container := pod.containers[containerName]
|
||||
if container == nil {
|
||||
return "", fmt.Errorf("Cannot find container %s in pod %s namespace %s", containerName, pod, namespace)
|
||||
return "", fmt.Errorf("Cannot find container %s in pod %s namespace %s", containerName, podName, namespace)
|
||||
}
|
||||
|
||||
return readLogFile(container.LogPath, tail)
|
||||
|
||||
202
vendor/github.com/Azure/azure-sdk-for-go/LICENSE
generated
vendored
Normal file
202
vendor/github.com/Azure/azure-sdk-for-go/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2016 Microsoft Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
5
vendor/github.com/Azure/azure-sdk-for-go/NOTICE
generated
vendored
Normal file
5
vendor/github.com/Azure/azure-sdk-for-go/NOTICE
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
Microsoft Azure-SDK-for-Go
|
||||
Copyright 2014-2017 Microsoft
|
||||
|
||||
This product includes software developed at
|
||||
the Microsoft Corporation (https://www.microsoft.com).
|
||||
175
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/account.go
generated
vendored
Normal file
175
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/account.go
generated
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
package batch
|
||||
|
||||
// Copyright (c) Microsoft and contributors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/Azure/go-autorest/autorest/date"
|
||||
"github.com/Azure/go-autorest/autorest/validation"
|
||||
"github.com/satori/go.uuid"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// AccountClient is the a client for issuing REST requests to the Azure Batch service.
|
||||
type AccountClient struct {
|
||||
BaseClient
|
||||
}
|
||||
|
||||
// NewAccountClient creates an instance of the AccountClient client.
|
||||
func NewAccountClient() AccountClient {
|
||||
return NewAccountClientWithBaseURI(DefaultBaseURI)
|
||||
}
|
||||
|
||||
// NewAccountClientWithBaseURI creates an instance of the AccountClient client.
|
||||
func NewAccountClientWithBaseURI(baseURI string) AccountClient {
|
||||
return AccountClient{NewWithBaseURI(baseURI)}
|
||||
}
|
||||
|
||||
// ListNodeAgentSkus sends the list node agent skus request.
|
||||
//
|
||||
// filter is an OData $filter clause. For more information on constructing this filter, see
|
||||
// https://docs.microsoft.com/en-us/rest/api/batchservice/odata-filters-in-batch#list-node-agent-skus. maxResults
|
||||
// is the maximum number of items to return in the response. A maximum of 1000 results will be returned. timeout is
|
||||
// the maximum time that the server can spend processing the request, in seconds. The default is 30 seconds.
|
||||
// clientRequestID is the caller-generated request identity, in the form of a GUID with no decoration such as curly
|
||||
// braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0. returnClientRequestID is whether the server should return the
|
||||
// client-request-id in the response. ocpDate is the time the request was issued. Client libraries typically set
|
||||
// this to the current system clock time; set it explicitly if you are calling the REST API directly.
|
||||
func (client AccountClient) ListNodeAgentSkus(ctx context.Context, filter string, maxResults *int32, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (result AccountListNodeAgentSkusResultPage, err error) {
|
||||
if err := validation.Validate([]validation.Validation{
|
||||
{TargetValue: maxResults,
|
||||
Constraints: []validation.Constraint{{Target: "maxResults", Name: validation.Null, Rule: false,
|
||||
Chain: []validation.Constraint{{Target: "maxResults", Name: validation.InclusiveMaximum, Rule: 1000, Chain: nil},
|
||||
{Target: "maxResults", Name: validation.InclusiveMinimum, Rule: 1, Chain: nil},
|
||||
}}}}}); err != nil {
|
||||
return result, validation.NewError("batch.AccountClient", "ListNodeAgentSkus", err.Error())
|
||||
}
|
||||
|
||||
result.fn = client.listNodeAgentSkusNextResults
|
||||
req, err := client.ListNodeAgentSkusPreparer(ctx, filter, maxResults, timeout, clientRequestID, returnClientRequestID, ocpDate)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.AccountClient", "ListNodeAgentSkus", nil, "Failure preparing request")
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.ListNodeAgentSkusSender(req)
|
||||
if err != nil {
|
||||
result.alnasr.Response = autorest.Response{Response: resp}
|
||||
err = autorest.NewErrorWithError(err, "batch.AccountClient", "ListNodeAgentSkus", resp, "Failure sending request")
|
||||
return
|
||||
}
|
||||
|
||||
result.alnasr, err = client.ListNodeAgentSkusResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.AccountClient", "ListNodeAgentSkus", resp, "Failure responding to request")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ListNodeAgentSkusPreparer prepares the ListNodeAgentSkus request.
|
||||
func (client AccountClient) ListNodeAgentSkusPreparer(ctx context.Context, filter string, maxResults *int32, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (*http.Request, error) {
|
||||
const APIVersion = "2017-09-01.6.0"
|
||||
queryParameters := map[string]interface{}{
|
||||
"api-version": APIVersion,
|
||||
}
|
||||
if len(filter) > 0 {
|
||||
queryParameters["$filter"] = autorest.Encode("query", filter)
|
||||
}
|
||||
if maxResults != nil {
|
||||
queryParameters["maxresults"] = autorest.Encode("query", *maxResults)
|
||||
} else {
|
||||
queryParameters["maxresults"] = autorest.Encode("query", 1000)
|
||||
}
|
||||
if timeout != nil {
|
||||
queryParameters["timeout"] = autorest.Encode("query", *timeout)
|
||||
} else {
|
||||
queryParameters["timeout"] = autorest.Encode("query", 30)
|
||||
}
|
||||
|
||||
preparer := autorest.CreatePreparer(
|
||||
autorest.AsGet(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
autorest.WithPath("/nodeagentskus"),
|
||||
autorest.WithQueryParameters(queryParameters))
|
||||
if clientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("client-request-id", autorest.String(clientRequestID)))
|
||||
}
|
||||
if returnClientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(returnClientRequestID)))
|
||||
} else {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(false)))
|
||||
}
|
||||
if ocpDate != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("ocp-date", autorest.String(ocpDate)))
|
||||
}
|
||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||
}
|
||||
|
||||
// ListNodeAgentSkusSender sends the ListNodeAgentSkus request. The method will close the
|
||||
// http.Response Body if it receives an error.
|
||||
func (client AccountClient) ListNodeAgentSkusSender(req *http.Request) (*http.Response, error) {
|
||||
return autorest.SendWithSender(client, req,
|
||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
|
||||
}
|
||||
|
||||
// ListNodeAgentSkusResponder handles the response to the ListNodeAgentSkus request. The method always
|
||||
// closes the http.Response Body.
|
||||
func (client AccountClient) ListNodeAgentSkusResponder(resp *http.Response) (result AccountListNodeAgentSkusResult, err error) {
|
||||
err = autorest.Respond(
|
||||
resp,
|
||||
client.ByInspecting(),
|
||||
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||
autorest.ByUnmarshallingJSON(&result),
|
||||
autorest.ByClosing())
|
||||
result.Response = autorest.Response{Response: resp}
|
||||
return
|
||||
}
|
||||
|
||||
// listNodeAgentSkusNextResults retrieves the next set of results, if any.
|
||||
func (client AccountClient) listNodeAgentSkusNextResults(lastResults AccountListNodeAgentSkusResult) (result AccountListNodeAgentSkusResult, err error) {
|
||||
req, err := lastResults.accountListNodeAgentSkusResultPreparer()
|
||||
if err != nil {
|
||||
return result, autorest.NewErrorWithError(err, "batch.AccountClient", "listNodeAgentSkusNextResults", nil, "Failure preparing next results request")
|
||||
}
|
||||
if req == nil {
|
||||
return
|
||||
}
|
||||
resp, err := client.ListNodeAgentSkusSender(req)
|
||||
if err != nil {
|
||||
result.Response = autorest.Response{Response: resp}
|
||||
return result, autorest.NewErrorWithError(err, "batch.AccountClient", "listNodeAgentSkusNextResults", resp, "Failure sending next results request")
|
||||
}
|
||||
result, err = client.ListNodeAgentSkusResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.AccountClient", "listNodeAgentSkusNextResults", resp, "Failure responding to next results request")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ListNodeAgentSkusComplete enumerates all values, automatically crossing page boundaries as required.
|
||||
func (client AccountClient) ListNodeAgentSkusComplete(ctx context.Context, filter string, maxResults *int32, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (result AccountListNodeAgentSkusResultIterator, err error) {
|
||||
result.page, err = client.ListNodeAgentSkus(ctx, filter, maxResults, timeout, clientRequestID, returnClientRequestID, ocpDate)
|
||||
return
|
||||
}
|
||||
264
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/application.go
generated
vendored
Normal file
264
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/application.go
generated
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
package batch
|
||||
|
||||
// Copyright (c) Microsoft and contributors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/Azure/go-autorest/autorest/date"
|
||||
"github.com/Azure/go-autorest/autorest/validation"
|
||||
"github.com/satori/go.uuid"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// ApplicationClient is the a client for issuing REST requests to the Azure Batch service.
|
||||
type ApplicationClient struct {
|
||||
BaseClient
|
||||
}
|
||||
|
||||
// NewApplicationClient creates an instance of the ApplicationClient client.
|
||||
func NewApplicationClient() ApplicationClient {
|
||||
return NewApplicationClientWithBaseURI(DefaultBaseURI)
|
||||
}
|
||||
|
||||
// NewApplicationClientWithBaseURI creates an instance of the ApplicationClient client.
|
||||
func NewApplicationClientWithBaseURI(baseURI string) ApplicationClient {
|
||||
return ApplicationClient{NewWithBaseURI(baseURI)}
|
||||
}
|
||||
|
||||
// Get this operation returns only applications and versions that are available for use on compute nodes; that is, that
|
||||
// can be used in an application package reference. For administrator information about applications and versions that
|
||||
// are not yet available to compute nodes, use the Azure portal or the Azure Resource Manager API.
|
||||
//
|
||||
// applicationID is the ID of the application. timeout is the maximum time that the server can spend processing the
|
||||
// request, in seconds. The default is 30 seconds. clientRequestID is the caller-generated request identity, in the
|
||||
// form of a GUID with no decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.
|
||||
// returnClientRequestID is whether the server should return the client-request-id in the response. ocpDate is the
|
||||
// time the request was issued. Client libraries typically set this to the current system clock time; set it
|
||||
// explicitly if you are calling the REST API directly.
|
||||
func (client ApplicationClient) Get(ctx context.Context, applicationID string, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (result ApplicationSummary, err error) {
|
||||
req, err := client.GetPreparer(ctx, applicationID, timeout, clientRequestID, returnClientRequestID, ocpDate)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.ApplicationClient", "Get", nil, "Failure preparing request")
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.GetSender(req)
|
||||
if err != nil {
|
||||
result.Response = autorest.Response{Response: resp}
|
||||
err = autorest.NewErrorWithError(err, "batch.ApplicationClient", "Get", resp, "Failure sending request")
|
||||
return
|
||||
}
|
||||
|
||||
result, err = client.GetResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.ApplicationClient", "Get", resp, "Failure responding to request")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetPreparer prepares the Get request.
|
||||
func (client ApplicationClient) GetPreparer(ctx context.Context, applicationID string, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (*http.Request, error) {
|
||||
pathParameters := map[string]interface{}{
|
||||
"applicationId": autorest.Encode("path", applicationID),
|
||||
}
|
||||
|
||||
const APIVersion = "2017-09-01.6.0"
|
||||
queryParameters := map[string]interface{}{
|
||||
"api-version": APIVersion,
|
||||
}
|
||||
if timeout != nil {
|
||||
queryParameters["timeout"] = autorest.Encode("query", *timeout)
|
||||
} else {
|
||||
queryParameters["timeout"] = autorest.Encode("query", 30)
|
||||
}
|
||||
|
||||
preparer := autorest.CreatePreparer(
|
||||
autorest.AsGet(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
autorest.WithPathParameters("/applications/{applicationId}", pathParameters),
|
||||
autorest.WithQueryParameters(queryParameters))
|
||||
if clientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("client-request-id", autorest.String(clientRequestID)))
|
||||
}
|
||||
if returnClientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(returnClientRequestID)))
|
||||
} else {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(false)))
|
||||
}
|
||||
if ocpDate != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("ocp-date", autorest.String(ocpDate)))
|
||||
}
|
||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||
}
|
||||
|
||||
// GetSender sends the Get request. The method will close the
|
||||
// http.Response Body if it receives an error.
|
||||
func (client ApplicationClient) GetSender(req *http.Request) (*http.Response, error) {
|
||||
return autorest.SendWithSender(client, req,
|
||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
|
||||
}
|
||||
|
||||
// GetResponder handles the response to the Get request. The method always
|
||||
// closes the http.Response Body.
|
||||
func (client ApplicationClient) GetResponder(resp *http.Response) (result ApplicationSummary, err error) {
|
||||
err = autorest.Respond(
|
||||
resp,
|
||||
client.ByInspecting(),
|
||||
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||
autorest.ByUnmarshallingJSON(&result),
|
||||
autorest.ByClosing())
|
||||
result.Response = autorest.Response{Response: resp}
|
||||
return
|
||||
}
|
||||
|
||||
// List this operation returns only applications and versions that are available for use on compute nodes; that is,
|
||||
// that can be used in an application package reference. For administrator information about applications and versions
|
||||
// that are not yet available to compute nodes, use the Azure portal or the Azure Resource Manager API.
|
||||
//
|
||||
// maxResults is the maximum number of items to return in the response. A maximum of 1000 applications can be
|
||||
// returned. timeout is the maximum time that the server can spend processing the request, in seconds. The default
|
||||
// is 30 seconds. clientRequestID is the caller-generated request identity, in the form of a GUID with no
|
||||
// decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0. returnClientRequestID is whether the
|
||||
// server should return the client-request-id in the response. ocpDate is the time the request was issued. Client
|
||||
// libraries typically set this to the current system clock time; set it explicitly if you are calling the REST API
|
||||
// directly.
|
||||
func (client ApplicationClient) List(ctx context.Context, maxResults *int32, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (result ApplicationListResultPage, err error) {
|
||||
if err := validation.Validate([]validation.Validation{
|
||||
{TargetValue: maxResults,
|
||||
Constraints: []validation.Constraint{{Target: "maxResults", Name: validation.Null, Rule: false,
|
||||
Chain: []validation.Constraint{{Target: "maxResults", Name: validation.InclusiveMaximum, Rule: 1000, Chain: nil},
|
||||
{Target: "maxResults", Name: validation.InclusiveMinimum, Rule: 1, Chain: nil},
|
||||
}}}}}); err != nil {
|
||||
return result, validation.NewError("batch.ApplicationClient", "List", err.Error())
|
||||
}
|
||||
|
||||
result.fn = client.listNextResults
|
||||
req, err := client.ListPreparer(ctx, maxResults, timeout, clientRequestID, returnClientRequestID, ocpDate)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.ApplicationClient", "List", nil, "Failure preparing request")
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.ListSender(req)
|
||||
if err != nil {
|
||||
result.alr.Response = autorest.Response{Response: resp}
|
||||
err = autorest.NewErrorWithError(err, "batch.ApplicationClient", "List", resp, "Failure sending request")
|
||||
return
|
||||
}
|
||||
|
||||
result.alr, err = client.ListResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.ApplicationClient", "List", resp, "Failure responding to request")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ListPreparer prepares the List request.
|
||||
func (client ApplicationClient) ListPreparer(ctx context.Context, maxResults *int32, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (*http.Request, error) {
|
||||
const APIVersion = "2017-09-01.6.0"
|
||||
queryParameters := map[string]interface{}{
|
||||
"api-version": APIVersion,
|
||||
}
|
||||
if maxResults != nil {
|
||||
queryParameters["maxresults"] = autorest.Encode("query", *maxResults)
|
||||
} else {
|
||||
queryParameters["maxresults"] = autorest.Encode("query", 1000)
|
||||
}
|
||||
if timeout != nil {
|
||||
queryParameters["timeout"] = autorest.Encode("query", *timeout)
|
||||
} else {
|
||||
queryParameters["timeout"] = autorest.Encode("query", 30)
|
||||
}
|
||||
|
||||
preparer := autorest.CreatePreparer(
|
||||
autorest.AsGet(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
autorest.WithPath("/applications"),
|
||||
autorest.WithQueryParameters(queryParameters))
|
||||
if clientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("client-request-id", autorest.String(clientRequestID)))
|
||||
}
|
||||
if returnClientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(returnClientRequestID)))
|
||||
} else {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(false)))
|
||||
}
|
||||
if ocpDate != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("ocp-date", autorest.String(ocpDate)))
|
||||
}
|
||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||
}
|
||||
|
||||
// ListSender sends the List request. The method will close the
|
||||
// http.Response Body if it receives an error.
|
||||
func (client ApplicationClient) ListSender(req *http.Request) (*http.Response, error) {
|
||||
return autorest.SendWithSender(client, req,
|
||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
|
||||
}
|
||||
|
||||
// ListResponder handles the response to the List request. The method always
|
||||
// closes the http.Response Body.
|
||||
func (client ApplicationClient) ListResponder(resp *http.Response) (result ApplicationListResult, err error) {
|
||||
err = autorest.Respond(
|
||||
resp,
|
||||
client.ByInspecting(),
|
||||
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||
autorest.ByUnmarshallingJSON(&result),
|
||||
autorest.ByClosing())
|
||||
result.Response = autorest.Response{Response: resp}
|
||||
return
|
||||
}
|
||||
|
||||
// listNextResults retrieves the next set of results, if any.
|
||||
func (client ApplicationClient) listNextResults(lastResults ApplicationListResult) (result ApplicationListResult, err error) {
|
||||
req, err := lastResults.applicationListResultPreparer()
|
||||
if err != nil {
|
||||
return result, autorest.NewErrorWithError(err, "batch.ApplicationClient", "listNextResults", nil, "Failure preparing next results request")
|
||||
}
|
||||
if req == nil {
|
||||
return
|
||||
}
|
||||
resp, err := client.ListSender(req)
|
||||
if err != nil {
|
||||
result.Response = autorest.Response{Response: resp}
|
||||
return result, autorest.NewErrorWithError(err, "batch.ApplicationClient", "listNextResults", resp, "Failure sending next results request")
|
||||
}
|
||||
result, err = client.ListResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.ApplicationClient", "listNextResults", resp, "Failure responding to next results request")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ListComplete enumerates all values, automatically crossing page boundaries as required.
|
||||
func (client ApplicationClient) ListComplete(ctx context.Context, maxResults *int32, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (result ApplicationListResultIterator, err error) {
|
||||
result.page, err = client.List(ctx, maxResults, timeout, clientRequestID, returnClientRequestID, ocpDate)
|
||||
return
|
||||
}
|
||||
557
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/certificate.go
generated
vendored
Normal file
557
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/certificate.go
generated
vendored
Normal file
@@ -0,0 +1,557 @@
|
||||
package batch
|
||||
|
||||
// Copyright (c) Microsoft and contributors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/Azure/go-autorest/autorest/date"
|
||||
"github.com/Azure/go-autorest/autorest/validation"
|
||||
"github.com/satori/go.uuid"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// CertificateClient is the a client for issuing REST requests to the Azure Batch service.
|
||||
type CertificateClient struct {
|
||||
BaseClient
|
||||
}
|
||||
|
||||
// NewCertificateClient creates an instance of the CertificateClient client.
|
||||
func NewCertificateClient() CertificateClient {
|
||||
return NewCertificateClientWithBaseURI(DefaultBaseURI)
|
||||
}
|
||||
|
||||
// NewCertificateClientWithBaseURI creates an instance of the CertificateClient client.
|
||||
func NewCertificateClientWithBaseURI(baseURI string) CertificateClient {
|
||||
return CertificateClient{NewWithBaseURI(baseURI)}
|
||||
}
|
||||
|
||||
// Add sends the add request.
|
||||
//
|
||||
// certificate is the certificate to be added. timeout is the maximum time that the server can spend processing the
|
||||
// request, in seconds. The default is 30 seconds. clientRequestID is the caller-generated request identity, in the
|
||||
// form of a GUID with no decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.
|
||||
// returnClientRequestID is whether the server should return the client-request-id in the response. ocpDate is the
|
||||
// time the request was issued. Client libraries typically set this to the current system clock time; set it
|
||||
// explicitly if you are calling the REST API directly.
|
||||
func (client CertificateClient) Add(ctx context.Context, certificate CertificateAddParameter, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (result autorest.Response, err error) {
|
||||
if err := validation.Validate([]validation.Validation{
|
||||
{TargetValue: certificate,
|
||||
Constraints: []validation.Constraint{{Target: "certificate.Thumbprint", Name: validation.Null, Rule: true, Chain: nil},
|
||||
{Target: "certificate.ThumbprintAlgorithm", Name: validation.Null, Rule: true, Chain: nil},
|
||||
{Target: "certificate.Data", Name: validation.Null, Rule: true, Chain: nil}}}}); err != nil {
|
||||
return result, validation.NewError("batch.CertificateClient", "Add", err.Error())
|
||||
}
|
||||
|
||||
req, err := client.AddPreparer(ctx, certificate, timeout, clientRequestID, returnClientRequestID, ocpDate)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.CertificateClient", "Add", nil, "Failure preparing request")
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.AddSender(req)
|
||||
if err != nil {
|
||||
result.Response = resp
|
||||
err = autorest.NewErrorWithError(err, "batch.CertificateClient", "Add", resp, "Failure sending request")
|
||||
return
|
||||
}
|
||||
|
||||
result, err = client.AddResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.CertificateClient", "Add", resp, "Failure responding to request")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// AddPreparer prepares the Add request.
|
||||
func (client CertificateClient) AddPreparer(ctx context.Context, certificate CertificateAddParameter, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (*http.Request, error) {
|
||||
const APIVersion = "2017-09-01.6.0"
|
||||
queryParameters := map[string]interface{}{
|
||||
"api-version": APIVersion,
|
||||
}
|
||||
if timeout != nil {
|
||||
queryParameters["timeout"] = autorest.Encode("query", *timeout)
|
||||
} else {
|
||||
queryParameters["timeout"] = autorest.Encode("query", 30)
|
||||
}
|
||||
|
||||
preparer := autorest.CreatePreparer(
|
||||
autorest.AsContentType("application/json; odata=minimalmetadata; charset=utf-8"),
|
||||
autorest.AsPost(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
autorest.WithPath("/certificates"),
|
||||
autorest.WithJSON(certificate),
|
||||
autorest.WithQueryParameters(queryParameters))
|
||||
if clientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("client-request-id", autorest.String(clientRequestID)))
|
||||
}
|
||||
if returnClientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(returnClientRequestID)))
|
||||
} else {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(false)))
|
||||
}
|
||||
if ocpDate != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("ocp-date", autorest.String(ocpDate)))
|
||||
}
|
||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||
}
|
||||
|
||||
// AddSender sends the Add request. The method will close the
|
||||
// http.Response Body if it receives an error.
|
||||
func (client CertificateClient) AddSender(req *http.Request) (*http.Response, error) {
|
||||
return autorest.SendWithSender(client, req,
|
||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
|
||||
}
|
||||
|
||||
// AddResponder handles the response to the Add request. The method always
|
||||
// closes the http.Response Body.
|
||||
func (client CertificateClient) AddResponder(resp *http.Response) (result autorest.Response, err error) {
|
||||
err = autorest.Respond(
|
||||
resp,
|
||||
client.ByInspecting(),
|
||||
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusCreated),
|
||||
autorest.ByClosing())
|
||||
result.Response = resp
|
||||
return
|
||||
}
|
||||
|
||||
// CancelDeletion if you try to delete a certificate that is being used by a pool or compute node, the status of the
|
||||
// certificate changes to deleteFailed. If you decide that you want to continue using the certificate, you can use this
|
||||
// operation to set the status of the certificate back to active. If you intend to delete the certificate, you do not
|
||||
// need to run this operation after the deletion failed. You must make sure that the certificate is not being used by
|
||||
// any resources, and then you can try again to delete the certificate.
|
||||
//
|
||||
// thumbprintAlgorithm is the algorithm used to derive the thumbprint parameter. This must be sha1. thumbprint is
|
||||
// the thumbprint of the certificate being deleted. timeout is the maximum time that the server can spend
|
||||
// processing the request, in seconds. The default is 30 seconds. clientRequestID is the caller-generated request
|
||||
// identity, in the form of a GUID with no decoration such as curly braces, e.g.
|
||||
// 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0. returnClientRequestID is whether the server should return the
|
||||
// client-request-id in the response. ocpDate is the time the request was issued. Client libraries typically set
|
||||
// this to the current system clock time; set it explicitly if you are calling the REST API directly.
|
||||
func (client CertificateClient) CancelDeletion(ctx context.Context, thumbprintAlgorithm string, thumbprint string, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (result autorest.Response, err error) {
|
||||
req, err := client.CancelDeletionPreparer(ctx, thumbprintAlgorithm, thumbprint, timeout, clientRequestID, returnClientRequestID, ocpDate)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.CertificateClient", "CancelDeletion", nil, "Failure preparing request")
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.CancelDeletionSender(req)
|
||||
if err != nil {
|
||||
result.Response = resp
|
||||
err = autorest.NewErrorWithError(err, "batch.CertificateClient", "CancelDeletion", resp, "Failure sending request")
|
||||
return
|
||||
}
|
||||
|
||||
result, err = client.CancelDeletionResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.CertificateClient", "CancelDeletion", resp, "Failure responding to request")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// CancelDeletionPreparer prepares the CancelDeletion request.
|
||||
func (client CertificateClient) CancelDeletionPreparer(ctx context.Context, thumbprintAlgorithm string, thumbprint string, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (*http.Request, error) {
|
||||
pathParameters := map[string]interface{}{
|
||||
"thumbprint": autorest.Encode("path", thumbprint),
|
||||
"thumbprintAlgorithm": autorest.Encode("path", thumbprintAlgorithm),
|
||||
}
|
||||
|
||||
const APIVersion = "2017-09-01.6.0"
|
||||
queryParameters := map[string]interface{}{
|
||||
"api-version": APIVersion,
|
||||
}
|
||||
if timeout != nil {
|
||||
queryParameters["timeout"] = autorest.Encode("query", *timeout)
|
||||
} else {
|
||||
queryParameters["timeout"] = autorest.Encode("query", 30)
|
||||
}
|
||||
|
||||
preparer := autorest.CreatePreparer(
|
||||
autorest.AsPost(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
autorest.WithPathParameters("/certificates(thumbprintAlgorithm={thumbprintAlgorithm},thumbprint={thumbprint})/canceldelete", pathParameters),
|
||||
autorest.WithQueryParameters(queryParameters))
|
||||
if clientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("client-request-id", autorest.String(clientRequestID)))
|
||||
}
|
||||
if returnClientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(returnClientRequestID)))
|
||||
} else {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(false)))
|
||||
}
|
||||
if ocpDate != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("ocp-date", autorest.String(ocpDate)))
|
||||
}
|
||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||
}
|
||||
|
||||
// CancelDeletionSender sends the CancelDeletion request. The method will close the
|
||||
// http.Response Body if it receives an error.
|
||||
func (client CertificateClient) CancelDeletionSender(req *http.Request) (*http.Response, error) {
|
||||
return autorest.SendWithSender(client, req,
|
||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
|
||||
}
|
||||
|
||||
// CancelDeletionResponder handles the response to the CancelDeletion request. The method always
|
||||
// closes the http.Response Body.
|
||||
func (client CertificateClient) CancelDeletionResponder(resp *http.Response) (result autorest.Response, err error) {
|
||||
err = autorest.Respond(
|
||||
resp,
|
||||
client.ByInspecting(),
|
||||
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusNoContent),
|
||||
autorest.ByClosing())
|
||||
result.Response = resp
|
||||
return
|
||||
}
|
||||
|
||||
// Delete you cannot delete a certificate if a resource (pool or compute node) is using it. Before you can delete a
|
||||
// certificate, you must therefore make sure that the certificate is not associated with any existing pools, the
|
||||
// certificate is not installed on any compute nodes (even if you remove a certificate from a pool, it is not removed
|
||||
// from existing compute nodes in that pool until they restart), and no running tasks depend on the certificate. If you
|
||||
// try to delete a certificate that is in use, the deletion fails. The certificate status changes to deleteFailed. You
|
||||
// can use Cancel Delete Certificate to set the status back to active if you decide that you want to continue using the
|
||||
// certificate.
|
||||
//
|
||||
// thumbprintAlgorithm is the algorithm used to derive the thumbprint parameter. This must be sha1. thumbprint is
|
||||
// the thumbprint of the certificate to be deleted. timeout is the maximum time that the server can spend
|
||||
// processing the request, in seconds. The default is 30 seconds. clientRequestID is the caller-generated request
|
||||
// identity, in the form of a GUID with no decoration such as curly braces, e.g.
|
||||
// 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0. returnClientRequestID is whether the server should return the
|
||||
// client-request-id in the response. ocpDate is the time the request was issued. Client libraries typically set
|
||||
// this to the current system clock time; set it explicitly if you are calling the REST API directly.
|
||||
func (client CertificateClient) Delete(ctx context.Context, thumbprintAlgorithm string, thumbprint string, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (result autorest.Response, err error) {
|
||||
req, err := client.DeletePreparer(ctx, thumbprintAlgorithm, thumbprint, timeout, clientRequestID, returnClientRequestID, ocpDate)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.CertificateClient", "Delete", nil, "Failure preparing request")
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.DeleteSender(req)
|
||||
if err != nil {
|
||||
result.Response = resp
|
||||
err = autorest.NewErrorWithError(err, "batch.CertificateClient", "Delete", resp, "Failure sending request")
|
||||
return
|
||||
}
|
||||
|
||||
result, err = client.DeleteResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.CertificateClient", "Delete", resp, "Failure responding to request")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DeletePreparer prepares the Delete request.
|
||||
func (client CertificateClient) DeletePreparer(ctx context.Context, thumbprintAlgorithm string, thumbprint string, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (*http.Request, error) {
|
||||
pathParameters := map[string]interface{}{
|
||||
"thumbprint": autorest.Encode("path", thumbprint),
|
||||
"thumbprintAlgorithm": autorest.Encode("path", thumbprintAlgorithm),
|
||||
}
|
||||
|
||||
const APIVersion = "2017-09-01.6.0"
|
||||
queryParameters := map[string]interface{}{
|
||||
"api-version": APIVersion,
|
||||
}
|
||||
if timeout != nil {
|
||||
queryParameters["timeout"] = autorest.Encode("query", *timeout)
|
||||
} else {
|
||||
queryParameters["timeout"] = autorest.Encode("query", 30)
|
||||
}
|
||||
|
||||
preparer := autorest.CreatePreparer(
|
||||
autorest.AsDelete(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
autorest.WithPathParameters("/certificates(thumbprintAlgorithm={thumbprintAlgorithm},thumbprint={thumbprint})", pathParameters),
|
||||
autorest.WithQueryParameters(queryParameters))
|
||||
if clientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("client-request-id", autorest.String(clientRequestID)))
|
||||
}
|
||||
if returnClientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(returnClientRequestID)))
|
||||
} else {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(false)))
|
||||
}
|
||||
if ocpDate != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("ocp-date", autorest.String(ocpDate)))
|
||||
}
|
||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||
}
|
||||
|
||||
// DeleteSender sends the Delete request. The method will close the
|
||||
// http.Response Body if it receives an error.
|
||||
func (client CertificateClient) DeleteSender(req *http.Request) (*http.Response, error) {
|
||||
return autorest.SendWithSender(client, req,
|
||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
|
||||
}
|
||||
|
||||
// DeleteResponder handles the response to the Delete request. The method always
|
||||
// closes the http.Response Body.
|
||||
func (client CertificateClient) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
|
||||
err = autorest.Respond(
|
||||
resp,
|
||||
client.ByInspecting(),
|
||||
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusAccepted),
|
||||
autorest.ByClosing())
|
||||
result.Response = resp
|
||||
return
|
||||
}
|
||||
|
||||
// Get gets information about the specified certificate.
|
||||
//
|
||||
// thumbprintAlgorithm is the algorithm used to derive the thumbprint parameter. This must be sha1. thumbprint is
|
||||
// the thumbprint of the certificate to get. selectParameter is an OData $select clause. timeout is the maximum
|
||||
// time that the server can spend processing the request, in seconds. The default is 30 seconds. clientRequestID is
|
||||
// the caller-generated request identity, in the form of a GUID with no decoration such as curly braces, e.g.
|
||||
// 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0. returnClientRequestID is whether the server should return the
|
||||
// client-request-id in the response. ocpDate is the time the request was issued. Client libraries typically set
|
||||
// this to the current system clock time; set it explicitly if you are calling the REST API directly.
|
||||
func (client CertificateClient) Get(ctx context.Context, thumbprintAlgorithm string, thumbprint string, selectParameter string, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (result Certificate, err error) {
|
||||
req, err := client.GetPreparer(ctx, thumbprintAlgorithm, thumbprint, selectParameter, timeout, clientRequestID, returnClientRequestID, ocpDate)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.CertificateClient", "Get", nil, "Failure preparing request")
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.GetSender(req)
|
||||
if err != nil {
|
||||
result.Response = autorest.Response{Response: resp}
|
||||
err = autorest.NewErrorWithError(err, "batch.CertificateClient", "Get", resp, "Failure sending request")
|
||||
return
|
||||
}
|
||||
|
||||
result, err = client.GetResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.CertificateClient", "Get", resp, "Failure responding to request")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetPreparer prepares the Get request.
|
||||
func (client CertificateClient) GetPreparer(ctx context.Context, thumbprintAlgorithm string, thumbprint string, selectParameter string, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (*http.Request, error) {
|
||||
pathParameters := map[string]interface{}{
|
||||
"thumbprint": autorest.Encode("path", thumbprint),
|
||||
"thumbprintAlgorithm": autorest.Encode("path", thumbprintAlgorithm),
|
||||
}
|
||||
|
||||
const APIVersion = "2017-09-01.6.0"
|
||||
queryParameters := map[string]interface{}{
|
||||
"api-version": APIVersion,
|
||||
}
|
||||
if len(selectParameter) > 0 {
|
||||
queryParameters["$select"] = autorest.Encode("query", selectParameter)
|
||||
}
|
||||
if timeout != nil {
|
||||
queryParameters["timeout"] = autorest.Encode("query", *timeout)
|
||||
} else {
|
||||
queryParameters["timeout"] = autorest.Encode("query", 30)
|
||||
}
|
||||
|
||||
preparer := autorest.CreatePreparer(
|
||||
autorest.AsGet(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
autorest.WithPathParameters("/certificates(thumbprintAlgorithm={thumbprintAlgorithm},thumbprint={thumbprint})", pathParameters),
|
||||
autorest.WithQueryParameters(queryParameters))
|
||||
if clientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("client-request-id", autorest.String(clientRequestID)))
|
||||
}
|
||||
if returnClientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(returnClientRequestID)))
|
||||
} else {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(false)))
|
||||
}
|
||||
if ocpDate != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("ocp-date", autorest.String(ocpDate)))
|
||||
}
|
||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||
}
|
||||
|
||||
// GetSender sends the Get request. The method will close the
|
||||
// http.Response Body if it receives an error.
|
||||
func (client CertificateClient) GetSender(req *http.Request) (*http.Response, error) {
|
||||
return autorest.SendWithSender(client, req,
|
||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
|
||||
}
|
||||
|
||||
// GetResponder handles the response to the Get request. The method always
|
||||
// closes the http.Response Body.
|
||||
func (client CertificateClient) GetResponder(resp *http.Response) (result Certificate, err error) {
|
||||
err = autorest.Respond(
|
||||
resp,
|
||||
client.ByInspecting(),
|
||||
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||
autorest.ByUnmarshallingJSON(&result),
|
||||
autorest.ByClosing())
|
||||
result.Response = autorest.Response{Response: resp}
|
||||
return
|
||||
}
|
||||
|
||||
// List sends the list request.
|
||||
//
|
||||
// filter is an OData $filter clause. For more information on constructing this filter, see
|
||||
// https://docs.microsoft.com/en-us/rest/api/batchservice/odata-filters-in-batch#list-certificates. selectParameter
|
||||
// is an OData $select clause. maxResults is the maximum number of items to return in the response. A maximum of
|
||||
// 1000 certificates can be returned. timeout is the maximum time that the server can spend processing the request,
|
||||
// in seconds. The default is 30 seconds. clientRequestID is the caller-generated request identity, in the form of
|
||||
// a GUID with no decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0. returnClientRequestID
|
||||
// is whether the server should return the client-request-id in the response. ocpDate is the time the request was
|
||||
// issued. Client libraries typically set this to the current system clock time; set it explicitly if you are
|
||||
// calling the REST API directly.
|
||||
func (client CertificateClient) List(ctx context.Context, filter string, selectParameter string, maxResults *int32, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (result CertificateListResultPage, err error) {
|
||||
if err := validation.Validate([]validation.Validation{
|
||||
{TargetValue: maxResults,
|
||||
Constraints: []validation.Constraint{{Target: "maxResults", Name: validation.Null, Rule: false,
|
||||
Chain: []validation.Constraint{{Target: "maxResults", Name: validation.InclusiveMaximum, Rule: 1000, Chain: nil},
|
||||
{Target: "maxResults", Name: validation.InclusiveMinimum, Rule: 1, Chain: nil},
|
||||
}}}}}); err != nil {
|
||||
return result, validation.NewError("batch.CertificateClient", "List", err.Error())
|
||||
}
|
||||
|
||||
result.fn = client.listNextResults
|
||||
req, err := client.ListPreparer(ctx, filter, selectParameter, maxResults, timeout, clientRequestID, returnClientRequestID, ocpDate)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.CertificateClient", "List", nil, "Failure preparing request")
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.ListSender(req)
|
||||
if err != nil {
|
||||
result.clr.Response = autorest.Response{Response: resp}
|
||||
err = autorest.NewErrorWithError(err, "batch.CertificateClient", "List", resp, "Failure sending request")
|
||||
return
|
||||
}
|
||||
|
||||
result.clr, err = client.ListResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.CertificateClient", "List", resp, "Failure responding to request")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ListPreparer prepares the List request.
|
||||
func (client CertificateClient) ListPreparer(ctx context.Context, filter string, selectParameter string, maxResults *int32, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (*http.Request, error) {
|
||||
const APIVersion = "2017-09-01.6.0"
|
||||
queryParameters := map[string]interface{}{
|
||||
"api-version": APIVersion,
|
||||
}
|
||||
if len(filter) > 0 {
|
||||
queryParameters["$filter"] = autorest.Encode("query", filter)
|
||||
}
|
||||
if len(selectParameter) > 0 {
|
||||
queryParameters["$select"] = autorest.Encode("query", selectParameter)
|
||||
}
|
||||
if maxResults != nil {
|
||||
queryParameters["maxresults"] = autorest.Encode("query", *maxResults)
|
||||
} else {
|
||||
queryParameters["maxresults"] = autorest.Encode("query", 1000)
|
||||
}
|
||||
if timeout != nil {
|
||||
queryParameters["timeout"] = autorest.Encode("query", *timeout)
|
||||
} else {
|
||||
queryParameters["timeout"] = autorest.Encode("query", 30)
|
||||
}
|
||||
|
||||
preparer := autorest.CreatePreparer(
|
||||
autorest.AsGet(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
autorest.WithPath("/certificates"),
|
||||
autorest.WithQueryParameters(queryParameters))
|
||||
if clientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("client-request-id", autorest.String(clientRequestID)))
|
||||
}
|
||||
if returnClientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(returnClientRequestID)))
|
||||
} else {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(false)))
|
||||
}
|
||||
if ocpDate != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("ocp-date", autorest.String(ocpDate)))
|
||||
}
|
||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||
}
|
||||
|
||||
// ListSender sends the List request. The method will close the
|
||||
// http.Response Body if it receives an error.
|
||||
func (client CertificateClient) ListSender(req *http.Request) (*http.Response, error) {
|
||||
return autorest.SendWithSender(client, req,
|
||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
|
||||
}
|
||||
|
||||
// ListResponder handles the response to the List request. The method always
|
||||
// closes the http.Response Body.
|
||||
func (client CertificateClient) ListResponder(resp *http.Response) (result CertificateListResult, err error) {
|
||||
err = autorest.Respond(
|
||||
resp,
|
||||
client.ByInspecting(),
|
||||
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||
autorest.ByUnmarshallingJSON(&result),
|
||||
autorest.ByClosing())
|
||||
result.Response = autorest.Response{Response: resp}
|
||||
return
|
||||
}
|
||||
|
||||
// listNextResults retrieves the next set of results, if any.
|
||||
func (client CertificateClient) listNextResults(lastResults CertificateListResult) (result CertificateListResult, err error) {
|
||||
req, err := lastResults.certificateListResultPreparer()
|
||||
if err != nil {
|
||||
return result, autorest.NewErrorWithError(err, "batch.CertificateClient", "listNextResults", nil, "Failure preparing next results request")
|
||||
}
|
||||
if req == nil {
|
||||
return
|
||||
}
|
||||
resp, err := client.ListSender(req)
|
||||
if err != nil {
|
||||
result.Response = autorest.Response{Response: resp}
|
||||
return result, autorest.NewErrorWithError(err, "batch.CertificateClient", "listNextResults", resp, "Failure sending next results request")
|
||||
}
|
||||
result, err = client.ListResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.CertificateClient", "listNextResults", resp, "Failure responding to next results request")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ListComplete enumerates all values, automatically crossing page boundaries as required.
|
||||
func (client CertificateClient) ListComplete(ctx context.Context, filter string, selectParameter string, maxResults *int32, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (result CertificateListResultIterator, err error) {
|
||||
result.page, err = client.List(ctx, filter, selectParameter, maxResults, timeout, clientRequestID, returnClientRequestID, ocpDate)
|
||||
return
|
||||
}
|
||||
49
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/client.go
generated
vendored
Normal file
49
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/client.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
// Package batch implements the Azure ARM Batch service API version 2017-09-01.6.0.
|
||||
//
|
||||
// A client for issuing REST requests to the Azure Batch service.
|
||||
package batch
|
||||
|
||||
// Copyright (c) Microsoft and contributors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
|
||||
|
||||
import (
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultBaseURI is the default URI used for the service Batch
|
||||
DefaultBaseURI = "https://batch.core.windows.net"
|
||||
)
|
||||
|
||||
// BaseClient is the base client for Batch.
|
||||
type BaseClient struct {
|
||||
autorest.Client
|
||||
BaseURI string
|
||||
}
|
||||
|
||||
// New creates an instance of the BaseClient client.
|
||||
func New() BaseClient {
|
||||
return NewWithBaseURI(DefaultBaseURI)
|
||||
}
|
||||
|
||||
// NewWithBaseURI creates an instance of the BaseClient client.
|
||||
func NewWithBaseURI(baseURI string) BaseClient {
|
||||
return BaseClient{
|
||||
Client: autorest.NewClientWithUserAgent(UserAgent()),
|
||||
BaseURI: baseURI,
|
||||
}
|
||||
}
|
||||
1124
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/computenode.go
generated
vendored
Normal file
1124
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/computenode.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
946
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/file.go
generated
vendored
Normal file
946
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/file.go
generated
vendored
Normal file
@@ -0,0 +1,946 @@
|
||||
package batch
|
||||
|
||||
// Copyright (c) Microsoft and contributors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/Azure/go-autorest/autorest/date"
|
||||
"github.com/Azure/go-autorest/autorest/validation"
|
||||
"github.com/satori/go.uuid"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// FileClient is the a client for issuing REST requests to the Azure Batch service.
|
||||
type FileClient struct {
|
||||
BaseClient
|
||||
}
|
||||
|
||||
// NewFileClient creates an instance of the FileClient client.
|
||||
func NewFileClient() FileClient {
|
||||
return NewFileClientWithBaseURI(DefaultBaseURI)
|
||||
}
|
||||
|
||||
// NewFileClientWithBaseURI creates an instance of the FileClient client.
|
||||
func NewFileClientWithBaseURI(baseURI string) FileClient {
|
||||
return FileClient{NewWithBaseURI(baseURI)}
|
||||
}
|
||||
|
||||
// DeleteFromComputeNode sends the delete from compute node request.
|
||||
//
|
||||
// poolID is the ID of the pool that contains the compute node. nodeID is the ID of the compute node from which you
|
||||
// want to delete the file. filePath is the path to the file or directory that you want to delete. recursive is
|
||||
// whether to delete children of a directory. If the filePath parameter represents a directory instead of a file,
|
||||
// you can set recursive to true to delete the directory and all of the files and subdirectories in it. If
|
||||
// recursive is false then the directory must be empty or deletion will fail. timeout is the maximum time that the
|
||||
// server can spend processing the request, in seconds. The default is 30 seconds. clientRequestID is the
|
||||
// caller-generated request identity, in the form of a GUID with no decoration such as curly braces, e.g.
|
||||
// 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0. returnClientRequestID is whether the server should return the
|
||||
// client-request-id in the response. ocpDate is the time the request was issued. Client libraries typically set
|
||||
// this to the current system clock time; set it explicitly if you are calling the REST API directly.
|
||||
func (client FileClient) DeleteFromComputeNode(ctx context.Context, poolID string, nodeID string, filePath string, recursive *bool, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (result autorest.Response, err error) {
|
||||
req, err := client.DeleteFromComputeNodePreparer(ctx, poolID, nodeID, filePath, recursive, timeout, clientRequestID, returnClientRequestID, ocpDate)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "DeleteFromComputeNode", nil, "Failure preparing request")
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.DeleteFromComputeNodeSender(req)
|
||||
if err != nil {
|
||||
result.Response = resp
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "DeleteFromComputeNode", resp, "Failure sending request")
|
||||
return
|
||||
}
|
||||
|
||||
result, err = client.DeleteFromComputeNodeResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "DeleteFromComputeNode", resp, "Failure responding to request")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteFromComputeNodePreparer prepares the DeleteFromComputeNode request.
|
||||
func (client FileClient) DeleteFromComputeNodePreparer(ctx context.Context, poolID string, nodeID string, filePath string, recursive *bool, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (*http.Request, error) {
|
||||
pathParameters := map[string]interface{}{
|
||||
"filePath": autorest.Encode("path", filePath),
|
||||
"nodeId": autorest.Encode("path", nodeID),
|
||||
"poolId": autorest.Encode("path", poolID),
|
||||
}
|
||||
|
||||
const APIVersion = "2017-09-01.6.0"
|
||||
queryParameters := map[string]interface{}{
|
||||
"api-version": APIVersion,
|
||||
}
|
||||
if recursive != nil {
|
||||
queryParameters["recursive"] = autorest.Encode("query", *recursive)
|
||||
}
|
||||
if timeout != nil {
|
||||
queryParameters["timeout"] = autorest.Encode("query", *timeout)
|
||||
} else {
|
||||
queryParameters["timeout"] = autorest.Encode("query", 30)
|
||||
}
|
||||
|
||||
preparer := autorest.CreatePreparer(
|
||||
autorest.AsDelete(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
autorest.WithPathParameters("/pools/{poolId}/nodes/{nodeId}/files/{filePath}", pathParameters),
|
||||
autorest.WithQueryParameters(queryParameters))
|
||||
if clientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("client-request-id", autorest.String(clientRequestID)))
|
||||
}
|
||||
if returnClientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(returnClientRequestID)))
|
||||
} else {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(false)))
|
||||
}
|
||||
if ocpDate != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("ocp-date", autorest.String(ocpDate)))
|
||||
}
|
||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||
}
|
||||
|
||||
// DeleteFromComputeNodeSender sends the DeleteFromComputeNode request. The method will close the
|
||||
// http.Response Body if it receives an error.
|
||||
func (client FileClient) DeleteFromComputeNodeSender(req *http.Request) (*http.Response, error) {
|
||||
return autorest.SendWithSender(client, req,
|
||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
|
||||
}
|
||||
|
||||
// DeleteFromComputeNodeResponder handles the response to the DeleteFromComputeNode request. The method always
|
||||
// closes the http.Response Body.
|
||||
func (client FileClient) DeleteFromComputeNodeResponder(resp *http.Response) (result autorest.Response, err error) {
|
||||
err = autorest.Respond(
|
||||
resp,
|
||||
client.ByInspecting(),
|
||||
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||
autorest.ByClosing())
|
||||
result.Response = resp
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteFromTask sends the delete from task request.
|
||||
//
|
||||
// jobID is the ID of the job that contains the task. taskID is the ID of the task whose file you want to delete.
|
||||
// filePath is the path to the task file or directory that you want to delete. recursive is whether to delete
|
||||
// children of a directory. If the filePath parameter represents a directory instead of a file, you can set
|
||||
// recursive to true to delete the directory and all of the files and subdirectories in it. If recursive is false
|
||||
// then the directory must be empty or deletion will fail. timeout is the maximum time that the server can spend
|
||||
// processing the request, in seconds. The default is 30 seconds. clientRequestID is the caller-generated request
|
||||
// identity, in the form of a GUID with no decoration such as curly braces, e.g.
|
||||
// 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0. returnClientRequestID is whether the server should return the
|
||||
// client-request-id in the response. ocpDate is the time the request was issued. Client libraries typically set
|
||||
// this to the current system clock time; set it explicitly if you are calling the REST API directly.
|
||||
func (client FileClient) DeleteFromTask(ctx context.Context, jobID string, taskID string, filePath string, recursive *bool, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (result autorest.Response, err error) {
|
||||
req, err := client.DeleteFromTaskPreparer(ctx, jobID, taskID, filePath, recursive, timeout, clientRequestID, returnClientRequestID, ocpDate)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "DeleteFromTask", nil, "Failure preparing request")
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.DeleteFromTaskSender(req)
|
||||
if err != nil {
|
||||
result.Response = resp
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "DeleteFromTask", resp, "Failure sending request")
|
||||
return
|
||||
}
|
||||
|
||||
result, err = client.DeleteFromTaskResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "DeleteFromTask", resp, "Failure responding to request")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteFromTaskPreparer prepares the DeleteFromTask request.
|
||||
func (client FileClient) DeleteFromTaskPreparer(ctx context.Context, jobID string, taskID string, filePath string, recursive *bool, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (*http.Request, error) {
|
||||
pathParameters := map[string]interface{}{
|
||||
"filePath": autorest.Encode("path", filePath),
|
||||
"jobId": autorest.Encode("path", jobID),
|
||||
"taskId": autorest.Encode("path", taskID),
|
||||
}
|
||||
|
||||
const APIVersion = "2017-09-01.6.0"
|
||||
queryParameters := map[string]interface{}{
|
||||
"api-version": APIVersion,
|
||||
}
|
||||
if recursive != nil {
|
||||
queryParameters["recursive"] = autorest.Encode("query", *recursive)
|
||||
}
|
||||
if timeout != nil {
|
||||
queryParameters["timeout"] = autorest.Encode("query", *timeout)
|
||||
} else {
|
||||
queryParameters["timeout"] = autorest.Encode("query", 30)
|
||||
}
|
||||
|
||||
preparer := autorest.CreatePreparer(
|
||||
autorest.AsDelete(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
autorest.WithPathParameters("/jobs/{jobId}/tasks/{taskId}/files/{filePath}", pathParameters),
|
||||
autorest.WithQueryParameters(queryParameters))
|
||||
if clientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("client-request-id", autorest.String(clientRequestID)))
|
||||
}
|
||||
if returnClientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(returnClientRequestID)))
|
||||
} else {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(false)))
|
||||
}
|
||||
if ocpDate != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("ocp-date", autorest.String(ocpDate)))
|
||||
}
|
||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||
}
|
||||
|
||||
// DeleteFromTaskSender sends the DeleteFromTask request. The method will close the
|
||||
// http.Response Body if it receives an error.
|
||||
func (client FileClient) DeleteFromTaskSender(req *http.Request) (*http.Response, error) {
|
||||
return autorest.SendWithSender(client, req,
|
||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
|
||||
}
|
||||
|
||||
// DeleteFromTaskResponder handles the response to the DeleteFromTask request. The method always
|
||||
// closes the http.Response Body.
|
||||
func (client FileClient) DeleteFromTaskResponder(resp *http.Response) (result autorest.Response, err error) {
|
||||
err = autorest.Respond(
|
||||
resp,
|
||||
client.ByInspecting(),
|
||||
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||
autorest.ByClosing())
|
||||
result.Response = resp
|
||||
return
|
||||
}
|
||||
|
||||
// GetFromComputeNode returns the content of the specified compute node file.
|
||||
//
|
||||
// poolID is the ID of the pool that contains the compute node. nodeID is the ID of the compute node that contains
|
||||
// the file. filePath is the path to the compute node file that you want to get the content of. timeout is the
|
||||
// maximum time that the server can spend processing the request, in seconds. The default is 30 seconds.
|
||||
// clientRequestID is the caller-generated request identity, in the form of a GUID with no decoration such as curly
|
||||
// braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0. returnClientRequestID is whether the server should return the
|
||||
// client-request-id in the response. ocpDate is the time the request was issued. Client libraries typically set
|
||||
// this to the current system clock time; set it explicitly if you are calling the REST API directly. ocpRange is
|
||||
// the byte range to be retrieved. The default is to retrieve the entire file. The format is
|
||||
// bytes=startRange-endRange. ifModifiedSince is a timestamp indicating the last modified time of the resource
|
||||
// known to the client. The operation will be performed only if the resource on the service has been modified since
|
||||
// the specified time. ifUnmodifiedSince is a timestamp indicating the last modified time of the resource known to
|
||||
// the client. The operation will be performed only if the resource on the service has not been modified since the
|
||||
// specified time.
|
||||
func (client FileClient) GetFromComputeNode(ctx context.Context, poolID string, nodeID string, filePath string, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123, ocpRange string, ifModifiedSince *date.TimeRFC1123, ifUnmodifiedSince *date.TimeRFC1123) (result ReadCloser, err error) {
|
||||
req, err := client.GetFromComputeNodePreparer(ctx, poolID, nodeID, filePath, timeout, clientRequestID, returnClientRequestID, ocpDate, ocpRange, ifModifiedSince, ifUnmodifiedSince)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "GetFromComputeNode", nil, "Failure preparing request")
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.GetFromComputeNodeSender(req)
|
||||
if err != nil {
|
||||
result.Response = autorest.Response{Response: resp}
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "GetFromComputeNode", resp, "Failure sending request")
|
||||
return
|
||||
}
|
||||
|
||||
result, err = client.GetFromComputeNodeResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "GetFromComputeNode", resp, "Failure responding to request")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetFromComputeNodePreparer prepares the GetFromComputeNode request.
|
||||
func (client FileClient) GetFromComputeNodePreparer(ctx context.Context, poolID string, nodeID string, filePath string, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123, ocpRange string, ifModifiedSince *date.TimeRFC1123, ifUnmodifiedSince *date.TimeRFC1123) (*http.Request, error) {
|
||||
pathParameters := map[string]interface{}{
|
||||
"filePath": autorest.Encode("path", filePath),
|
||||
"nodeId": autorest.Encode("path", nodeID),
|
||||
"poolId": autorest.Encode("path", poolID),
|
||||
}
|
||||
|
||||
const APIVersion = "2017-09-01.6.0"
|
||||
queryParameters := map[string]interface{}{
|
||||
"api-version": APIVersion,
|
||||
}
|
||||
if timeout != nil {
|
||||
queryParameters["timeout"] = autorest.Encode("query", *timeout)
|
||||
} else {
|
||||
queryParameters["timeout"] = autorest.Encode("query", 30)
|
||||
}
|
||||
|
||||
preparer := autorest.CreatePreparer(
|
||||
autorest.AsGet(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
autorest.WithPathParameters("/pools/{poolId}/nodes/{nodeId}/files/{filePath}", pathParameters),
|
||||
autorest.WithQueryParameters(queryParameters))
|
||||
if clientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("client-request-id", autorest.String(clientRequestID)))
|
||||
}
|
||||
if returnClientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(returnClientRequestID)))
|
||||
} else {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(false)))
|
||||
}
|
||||
if ocpDate != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("ocp-date", autorest.String(ocpDate)))
|
||||
}
|
||||
if len(ocpRange) > 0 {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("ocp-range", autorest.String(ocpRange)))
|
||||
}
|
||||
if ifModifiedSince != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("If-Modified-Since", autorest.String(ifModifiedSince)))
|
||||
}
|
||||
if ifUnmodifiedSince != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("If-Unmodified-Since", autorest.String(ifUnmodifiedSince)))
|
||||
}
|
||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||
}
|
||||
|
||||
// GetFromComputeNodeSender sends the GetFromComputeNode request. The method will close the
|
||||
// http.Response Body if it receives an error.
|
||||
func (client FileClient) GetFromComputeNodeSender(req *http.Request) (*http.Response, error) {
|
||||
return autorest.SendWithSender(client, req,
|
||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
|
||||
}
|
||||
|
||||
// GetFromComputeNodeResponder handles the response to the GetFromComputeNode request. The method always
|
||||
// closes the http.Response Body.
|
||||
func (client FileClient) GetFromComputeNodeResponder(resp *http.Response) (result ReadCloser, err error) {
|
||||
result.Value = &resp.Body
|
||||
err = autorest.Respond(
|
||||
resp,
|
||||
client.ByInspecting(),
|
||||
azure.WithErrorUnlessStatusCode(http.StatusOK))
|
||||
result.Response = autorest.Response{Response: resp}
|
||||
return
|
||||
}
|
||||
|
||||
// GetFromTask returns the content of the specified task file.
|
||||
//
|
||||
// jobID is the ID of the job that contains the task. taskID is the ID of the task whose file you want to retrieve.
|
||||
// filePath is the path to the task file that you want to get the content of. timeout is the maximum time that the
|
||||
// server can spend processing the request, in seconds. The default is 30 seconds. clientRequestID is the
|
||||
// caller-generated request identity, in the form of a GUID with no decoration such as curly braces, e.g.
|
||||
// 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0. returnClientRequestID is whether the server should return the
|
||||
// client-request-id in the response. ocpDate is the time the request was issued. Client libraries typically set
|
||||
// this to the current system clock time; set it explicitly if you are calling the REST API directly. ocpRange is
|
||||
// the byte range to be retrieved. The default is to retrieve the entire file. The format is
|
||||
// bytes=startRange-endRange. ifModifiedSince is a timestamp indicating the last modified time of the resource
|
||||
// known to the client. The operation will be performed only if the resource on the service has been modified since
|
||||
// the specified time. ifUnmodifiedSince is a timestamp indicating the last modified time of the resource known to
|
||||
// the client. The operation will be performed only if the resource on the service has not been modified since the
|
||||
// specified time.
|
||||
func (client FileClient) GetFromTask(ctx context.Context, jobID string, taskID string, filePath string, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123, ocpRange string, ifModifiedSince *date.TimeRFC1123, ifUnmodifiedSince *date.TimeRFC1123) (result ReadCloser, err error) {
|
||||
req, err := client.GetFromTaskPreparer(ctx, jobID, taskID, filePath, timeout, clientRequestID, returnClientRequestID, ocpDate, ocpRange, ifModifiedSince, ifUnmodifiedSince)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "GetFromTask", nil, "Failure preparing request")
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.GetFromTaskSender(req)
|
||||
if err != nil {
|
||||
result.Response = autorest.Response{Response: resp}
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "GetFromTask", resp, "Failure sending request")
|
||||
return
|
||||
}
|
||||
|
||||
result, err = client.GetFromTaskResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "GetFromTask", resp, "Failure responding to request")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetFromTaskPreparer prepares the GetFromTask request.
|
||||
func (client FileClient) GetFromTaskPreparer(ctx context.Context, jobID string, taskID string, filePath string, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123, ocpRange string, ifModifiedSince *date.TimeRFC1123, ifUnmodifiedSince *date.TimeRFC1123) (*http.Request, error) {
|
||||
pathParameters := map[string]interface{}{
|
||||
"filePath": autorest.Encode("path", filePath),
|
||||
"jobId": autorest.Encode("path", jobID),
|
||||
"taskId": autorest.Encode("path", taskID),
|
||||
}
|
||||
|
||||
const APIVersion = "2017-09-01.6.0"
|
||||
queryParameters := map[string]interface{}{
|
||||
"api-version": APIVersion,
|
||||
}
|
||||
if timeout != nil {
|
||||
queryParameters["timeout"] = autorest.Encode("query", *timeout)
|
||||
} else {
|
||||
queryParameters["timeout"] = autorest.Encode("query", 30)
|
||||
}
|
||||
|
||||
preparer := autorest.CreatePreparer(
|
||||
autorest.AsGet(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
autorest.WithPathParameters("/jobs/{jobId}/tasks/{taskId}/files/{filePath}", pathParameters),
|
||||
autorest.WithQueryParameters(queryParameters))
|
||||
if clientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("client-request-id", autorest.String(clientRequestID)))
|
||||
}
|
||||
if returnClientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(returnClientRequestID)))
|
||||
} else {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(false)))
|
||||
}
|
||||
if ocpDate != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("ocp-date", autorest.String(ocpDate)))
|
||||
}
|
||||
if len(ocpRange) > 0 {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("ocp-range", autorest.String(ocpRange)))
|
||||
}
|
||||
if ifModifiedSince != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("If-Modified-Since", autorest.String(ifModifiedSince)))
|
||||
}
|
||||
if ifUnmodifiedSince != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("If-Unmodified-Since", autorest.String(ifUnmodifiedSince)))
|
||||
}
|
||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||
}
|
||||
|
||||
// GetFromTaskSender sends the GetFromTask request. The method will close the
|
||||
// http.Response Body if it receives an error.
|
||||
func (client FileClient) GetFromTaskSender(req *http.Request) (*http.Response, error) {
|
||||
return autorest.SendWithSender(client, req,
|
||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
|
||||
}
|
||||
|
||||
// GetFromTaskResponder handles the response to the GetFromTask request. The method always
|
||||
// closes the http.Response Body.
|
||||
func (client FileClient) GetFromTaskResponder(resp *http.Response) (result ReadCloser, err error) {
|
||||
result.Value = &resp.Body
|
||||
err = autorest.Respond(
|
||||
resp,
|
||||
client.ByInspecting(),
|
||||
azure.WithErrorUnlessStatusCode(http.StatusOK))
|
||||
result.Response = autorest.Response{Response: resp}
|
||||
return
|
||||
}
|
||||
|
||||
// GetPropertiesFromComputeNode gets the properties of the specified compute node file.
|
||||
//
|
||||
// poolID is the ID of the pool that contains the compute node. nodeID is the ID of the compute node that contains
|
||||
// the file. filePath is the path to the compute node file that you want to get the properties of. timeout is the
|
||||
// maximum time that the server can spend processing the request, in seconds. The default is 30 seconds.
|
||||
// clientRequestID is the caller-generated request identity, in the form of a GUID with no decoration such as curly
|
||||
// braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0. returnClientRequestID is whether the server should return the
|
||||
// client-request-id in the response. ocpDate is the time the request was issued. Client libraries typically set
|
||||
// this to the current system clock time; set it explicitly if you are calling the REST API directly.
|
||||
// ifModifiedSince is a timestamp indicating the last modified time of the resource known to the client. The
|
||||
// operation will be performed only if the resource on the service has been modified since the specified time.
|
||||
// ifUnmodifiedSince is a timestamp indicating the last modified time of the resource known to the client. The
|
||||
// operation will be performed only if the resource on the service has not been modified since the specified time.
|
||||
func (client FileClient) GetPropertiesFromComputeNode(ctx context.Context, poolID string, nodeID string, filePath string, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123, ifModifiedSince *date.TimeRFC1123, ifUnmodifiedSince *date.TimeRFC1123) (result autorest.Response, err error) {
|
||||
req, err := client.GetPropertiesFromComputeNodePreparer(ctx, poolID, nodeID, filePath, timeout, clientRequestID, returnClientRequestID, ocpDate, ifModifiedSince, ifUnmodifiedSince)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "GetPropertiesFromComputeNode", nil, "Failure preparing request")
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.GetPropertiesFromComputeNodeSender(req)
|
||||
if err != nil {
|
||||
result.Response = resp
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "GetPropertiesFromComputeNode", resp, "Failure sending request")
|
||||
return
|
||||
}
|
||||
|
||||
result, err = client.GetPropertiesFromComputeNodeResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "GetPropertiesFromComputeNode", resp, "Failure responding to request")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetPropertiesFromComputeNodePreparer prepares the GetPropertiesFromComputeNode request.
|
||||
func (client FileClient) GetPropertiesFromComputeNodePreparer(ctx context.Context, poolID string, nodeID string, filePath string, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123, ifModifiedSince *date.TimeRFC1123, ifUnmodifiedSince *date.TimeRFC1123) (*http.Request, error) {
|
||||
pathParameters := map[string]interface{}{
|
||||
"filePath": autorest.Encode("path", filePath),
|
||||
"nodeId": autorest.Encode("path", nodeID),
|
||||
"poolId": autorest.Encode("path", poolID),
|
||||
}
|
||||
|
||||
const APIVersion = "2017-09-01.6.0"
|
||||
queryParameters := map[string]interface{}{
|
||||
"api-version": APIVersion,
|
||||
}
|
||||
if timeout != nil {
|
||||
queryParameters["timeout"] = autorest.Encode("query", *timeout)
|
||||
} else {
|
||||
queryParameters["timeout"] = autorest.Encode("query", 30)
|
||||
}
|
||||
|
||||
preparer := autorest.CreatePreparer(
|
||||
autorest.AsHead(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
autorest.WithPathParameters("/pools/{poolId}/nodes/{nodeId}/files/{filePath}", pathParameters),
|
||||
autorest.WithQueryParameters(queryParameters))
|
||||
if clientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("client-request-id", autorest.String(clientRequestID)))
|
||||
}
|
||||
if returnClientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(returnClientRequestID)))
|
||||
} else {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(false)))
|
||||
}
|
||||
if ocpDate != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("ocp-date", autorest.String(ocpDate)))
|
||||
}
|
||||
if ifModifiedSince != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("If-Modified-Since", autorest.String(ifModifiedSince)))
|
||||
}
|
||||
if ifUnmodifiedSince != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("If-Unmodified-Since", autorest.String(ifUnmodifiedSince)))
|
||||
}
|
||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||
}
|
||||
|
||||
// GetPropertiesFromComputeNodeSender sends the GetPropertiesFromComputeNode request. The method will close the
|
||||
// http.Response Body if it receives an error.
|
||||
func (client FileClient) GetPropertiesFromComputeNodeSender(req *http.Request) (*http.Response, error) {
|
||||
return autorest.SendWithSender(client, req,
|
||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
|
||||
}
|
||||
|
||||
// GetPropertiesFromComputeNodeResponder handles the response to the GetPropertiesFromComputeNode request. The method always
|
||||
// closes the http.Response Body.
|
||||
func (client FileClient) GetPropertiesFromComputeNodeResponder(resp *http.Response) (result autorest.Response, err error) {
|
||||
err = autorest.Respond(
|
||||
resp,
|
||||
client.ByInspecting(),
|
||||
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||
autorest.ByClosing())
|
||||
result.Response = resp
|
||||
return
|
||||
}
|
||||
|
||||
// GetPropertiesFromTask gets the properties of the specified task file.
|
||||
//
|
||||
// jobID is the ID of the job that contains the task. taskID is the ID of the task whose file you want to get the
|
||||
// properties of. filePath is the path to the task file that you want to get the properties of. timeout is the
|
||||
// maximum time that the server can spend processing the request, in seconds. The default is 30 seconds.
|
||||
// clientRequestID is the caller-generated request identity, in the form of a GUID with no decoration such as curly
|
||||
// braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0. returnClientRequestID is whether the server should return the
|
||||
// client-request-id in the response. ocpDate is the time the request was issued. Client libraries typically set
|
||||
// this to the current system clock time; set it explicitly if you are calling the REST API directly.
|
||||
// ifModifiedSince is a timestamp indicating the last modified time of the resource known to the client. The
|
||||
// operation will be performed only if the resource on the service has been modified since the specified time.
|
||||
// ifUnmodifiedSince is a timestamp indicating the last modified time of the resource known to the client. The
|
||||
// operation will be performed only if the resource on the service has not been modified since the specified time.
|
||||
func (client FileClient) GetPropertiesFromTask(ctx context.Context, jobID string, taskID string, filePath string, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123, ifModifiedSince *date.TimeRFC1123, ifUnmodifiedSince *date.TimeRFC1123) (result autorest.Response, err error) {
|
||||
req, err := client.GetPropertiesFromTaskPreparer(ctx, jobID, taskID, filePath, timeout, clientRequestID, returnClientRequestID, ocpDate, ifModifiedSince, ifUnmodifiedSince)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "GetPropertiesFromTask", nil, "Failure preparing request")
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.GetPropertiesFromTaskSender(req)
|
||||
if err != nil {
|
||||
result.Response = resp
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "GetPropertiesFromTask", resp, "Failure sending request")
|
||||
return
|
||||
}
|
||||
|
||||
result, err = client.GetPropertiesFromTaskResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "GetPropertiesFromTask", resp, "Failure responding to request")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetPropertiesFromTaskPreparer prepares the GetPropertiesFromTask request.
|
||||
func (client FileClient) GetPropertiesFromTaskPreparer(ctx context.Context, jobID string, taskID string, filePath string, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123, ifModifiedSince *date.TimeRFC1123, ifUnmodifiedSince *date.TimeRFC1123) (*http.Request, error) {
|
||||
pathParameters := map[string]interface{}{
|
||||
"filePath": autorest.Encode("path", filePath),
|
||||
"jobId": autorest.Encode("path", jobID),
|
||||
"taskId": autorest.Encode("path", taskID),
|
||||
}
|
||||
|
||||
const APIVersion = "2017-09-01.6.0"
|
||||
queryParameters := map[string]interface{}{
|
||||
"api-version": APIVersion,
|
||||
}
|
||||
if timeout != nil {
|
||||
queryParameters["timeout"] = autorest.Encode("query", *timeout)
|
||||
} else {
|
||||
queryParameters["timeout"] = autorest.Encode("query", 30)
|
||||
}
|
||||
|
||||
preparer := autorest.CreatePreparer(
|
||||
autorest.AsHead(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
autorest.WithPathParameters("/jobs/{jobId}/tasks/{taskId}/files/{filePath}", pathParameters),
|
||||
autorest.WithQueryParameters(queryParameters))
|
||||
if clientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("client-request-id", autorest.String(clientRequestID)))
|
||||
}
|
||||
if returnClientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(returnClientRequestID)))
|
||||
} else {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(false)))
|
||||
}
|
||||
if ocpDate != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("ocp-date", autorest.String(ocpDate)))
|
||||
}
|
||||
if ifModifiedSince != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("If-Modified-Since", autorest.String(ifModifiedSince)))
|
||||
}
|
||||
if ifUnmodifiedSince != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("If-Unmodified-Since", autorest.String(ifUnmodifiedSince)))
|
||||
}
|
||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||
}
|
||||
|
||||
// GetPropertiesFromTaskSender sends the GetPropertiesFromTask request. The method will close the
|
||||
// http.Response Body if it receives an error.
|
||||
func (client FileClient) GetPropertiesFromTaskSender(req *http.Request) (*http.Response, error) {
|
||||
return autorest.SendWithSender(client, req,
|
||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
|
||||
}
|
||||
|
||||
// GetPropertiesFromTaskResponder handles the response to the GetPropertiesFromTask request. The method always
|
||||
// closes the http.Response Body.
|
||||
func (client FileClient) GetPropertiesFromTaskResponder(resp *http.Response) (result autorest.Response, err error) {
|
||||
err = autorest.Respond(
|
||||
resp,
|
||||
client.ByInspecting(),
|
||||
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||
autorest.ByClosing())
|
||||
result.Response = resp
|
||||
return
|
||||
}
|
||||
|
||||
// ListFromComputeNode sends the list from compute node request.
|
||||
//
|
||||
// poolID is the ID of the pool that contains the compute node. nodeID is the ID of the compute node whose files
|
||||
// you want to list. filter is an OData $filter clause. For more information on constructing this filter, see
|
||||
// https://docs.microsoft.com/en-us/rest/api/batchservice/odata-filters-in-batch#list-compute-node-files. recursive
|
||||
// is whether to list children of a directory. maxResults is the maximum number of items to return in the response.
|
||||
// A maximum of 1000 files can be returned. timeout is the maximum time that the server can spend processing the
|
||||
// request, in seconds. The default is 30 seconds. clientRequestID is the caller-generated request identity, in the
|
||||
// form of a GUID with no decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.
|
||||
// returnClientRequestID is whether the server should return the client-request-id in the response. ocpDate is the
|
||||
// time the request was issued. Client libraries typically set this to the current system clock time; set it
|
||||
// explicitly if you are calling the REST API directly.
|
||||
func (client FileClient) ListFromComputeNode(ctx context.Context, poolID string, nodeID string, filter string, recursive *bool, maxResults *int32, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (result NodeFileListResultPage, err error) {
|
||||
if err := validation.Validate([]validation.Validation{
|
||||
{TargetValue: maxResults,
|
||||
Constraints: []validation.Constraint{{Target: "maxResults", Name: validation.Null, Rule: false,
|
||||
Chain: []validation.Constraint{{Target: "maxResults", Name: validation.InclusiveMaximum, Rule: 1000, Chain: nil},
|
||||
{Target: "maxResults", Name: validation.InclusiveMinimum, Rule: 1, Chain: nil},
|
||||
}}}}}); err != nil {
|
||||
return result, validation.NewError("batch.FileClient", "ListFromComputeNode", err.Error())
|
||||
}
|
||||
|
||||
result.fn = client.listFromComputeNodeNextResults
|
||||
req, err := client.ListFromComputeNodePreparer(ctx, poolID, nodeID, filter, recursive, maxResults, timeout, clientRequestID, returnClientRequestID, ocpDate)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "ListFromComputeNode", nil, "Failure preparing request")
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.ListFromComputeNodeSender(req)
|
||||
if err != nil {
|
||||
result.nflr.Response = autorest.Response{Response: resp}
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "ListFromComputeNode", resp, "Failure sending request")
|
||||
return
|
||||
}
|
||||
|
||||
result.nflr, err = client.ListFromComputeNodeResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "ListFromComputeNode", resp, "Failure responding to request")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ListFromComputeNodePreparer prepares the ListFromComputeNode request.
|
||||
func (client FileClient) ListFromComputeNodePreparer(ctx context.Context, poolID string, nodeID string, filter string, recursive *bool, maxResults *int32, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (*http.Request, error) {
|
||||
pathParameters := map[string]interface{}{
|
||||
"nodeId": autorest.Encode("path", nodeID),
|
||||
"poolId": autorest.Encode("path", poolID),
|
||||
}
|
||||
|
||||
const APIVersion = "2017-09-01.6.0"
|
||||
queryParameters := map[string]interface{}{
|
||||
"api-version": APIVersion,
|
||||
}
|
||||
if len(filter) > 0 {
|
||||
queryParameters["$filter"] = autorest.Encode("query", filter)
|
||||
}
|
||||
if recursive != nil {
|
||||
queryParameters["recursive"] = autorest.Encode("query", *recursive)
|
||||
}
|
||||
if maxResults != nil {
|
||||
queryParameters["maxresults"] = autorest.Encode("query", *maxResults)
|
||||
} else {
|
||||
queryParameters["maxresults"] = autorest.Encode("query", 1000)
|
||||
}
|
||||
if timeout != nil {
|
||||
queryParameters["timeout"] = autorest.Encode("query", *timeout)
|
||||
} else {
|
||||
queryParameters["timeout"] = autorest.Encode("query", 30)
|
||||
}
|
||||
|
||||
preparer := autorest.CreatePreparer(
|
||||
autorest.AsGet(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
autorest.WithPathParameters("/pools/{poolId}/nodes/{nodeId}/files", pathParameters),
|
||||
autorest.WithQueryParameters(queryParameters))
|
||||
if clientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("client-request-id", autorest.String(clientRequestID)))
|
||||
}
|
||||
if returnClientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(returnClientRequestID)))
|
||||
} else {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(false)))
|
||||
}
|
||||
if ocpDate != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("ocp-date", autorest.String(ocpDate)))
|
||||
}
|
||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||
}
|
||||
|
||||
// ListFromComputeNodeSender sends the ListFromComputeNode request. The method will close the
|
||||
// http.Response Body if it receives an error.
|
||||
func (client FileClient) ListFromComputeNodeSender(req *http.Request) (*http.Response, error) {
|
||||
return autorest.SendWithSender(client, req,
|
||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
|
||||
}
|
||||
|
||||
// ListFromComputeNodeResponder handles the response to the ListFromComputeNode request. The method always
|
||||
// closes the http.Response Body.
|
||||
func (client FileClient) ListFromComputeNodeResponder(resp *http.Response) (result NodeFileListResult, err error) {
|
||||
err = autorest.Respond(
|
||||
resp,
|
||||
client.ByInspecting(),
|
||||
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||
autorest.ByUnmarshallingJSON(&result),
|
||||
autorest.ByClosing())
|
||||
result.Response = autorest.Response{Response: resp}
|
||||
return
|
||||
}
|
||||
|
||||
// listFromComputeNodeNextResults retrieves the next set of results, if any.
|
||||
func (client FileClient) listFromComputeNodeNextResults(lastResults NodeFileListResult) (result NodeFileListResult, err error) {
|
||||
req, err := lastResults.nodeFileListResultPreparer()
|
||||
if err != nil {
|
||||
return result, autorest.NewErrorWithError(err, "batch.FileClient", "listFromComputeNodeNextResults", nil, "Failure preparing next results request")
|
||||
}
|
||||
if req == nil {
|
||||
return
|
||||
}
|
||||
resp, err := client.ListFromComputeNodeSender(req)
|
||||
if err != nil {
|
||||
result.Response = autorest.Response{Response: resp}
|
||||
return result, autorest.NewErrorWithError(err, "batch.FileClient", "listFromComputeNodeNextResults", resp, "Failure sending next results request")
|
||||
}
|
||||
result, err = client.ListFromComputeNodeResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "listFromComputeNodeNextResults", resp, "Failure responding to next results request")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ListFromComputeNodeComplete enumerates all values, automatically crossing page boundaries as required.
|
||||
func (client FileClient) ListFromComputeNodeComplete(ctx context.Context, poolID string, nodeID string, filter string, recursive *bool, maxResults *int32, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (result NodeFileListResultIterator, err error) {
|
||||
result.page, err = client.ListFromComputeNode(ctx, poolID, nodeID, filter, recursive, maxResults, timeout, clientRequestID, returnClientRequestID, ocpDate)
|
||||
return
|
||||
}
|
||||
|
||||
// ListFromTask sends the list from task request.
|
||||
//
|
||||
// jobID is the ID of the job that contains the task. taskID is the ID of the task whose files you want to list.
|
||||
// filter is an OData $filter clause. For more information on constructing this filter, see
|
||||
// https://docs.microsoft.com/en-us/rest/api/batchservice/odata-filters-in-batch#list-task-files. recursive is
|
||||
// whether to list children of the task directory. This parameter can be used in combination with the filter
|
||||
// parameter to list specific type of files. maxResults is the maximum number of items to return in the response. A
|
||||
// maximum of 1000 files can be returned. timeout is the maximum time that the server can spend processing the
|
||||
// request, in seconds. The default is 30 seconds. clientRequestID is the caller-generated request identity, in the
|
||||
// form of a GUID with no decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.
|
||||
// returnClientRequestID is whether the server should return the client-request-id in the response. ocpDate is the
|
||||
// time the request was issued. Client libraries typically set this to the current system clock time; set it
|
||||
// explicitly if you are calling the REST API directly.
|
||||
func (client FileClient) ListFromTask(ctx context.Context, jobID string, taskID string, filter string, recursive *bool, maxResults *int32, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (result NodeFileListResultPage, err error) {
|
||||
if err := validation.Validate([]validation.Validation{
|
||||
{TargetValue: maxResults,
|
||||
Constraints: []validation.Constraint{{Target: "maxResults", Name: validation.Null, Rule: false,
|
||||
Chain: []validation.Constraint{{Target: "maxResults", Name: validation.InclusiveMaximum, Rule: 1000, Chain: nil},
|
||||
{Target: "maxResults", Name: validation.InclusiveMinimum, Rule: 1, Chain: nil},
|
||||
}}}}}); err != nil {
|
||||
return result, validation.NewError("batch.FileClient", "ListFromTask", err.Error())
|
||||
}
|
||||
|
||||
result.fn = client.listFromTaskNextResults
|
||||
req, err := client.ListFromTaskPreparer(ctx, jobID, taskID, filter, recursive, maxResults, timeout, clientRequestID, returnClientRequestID, ocpDate)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "ListFromTask", nil, "Failure preparing request")
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := client.ListFromTaskSender(req)
|
||||
if err != nil {
|
||||
result.nflr.Response = autorest.Response{Response: resp}
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "ListFromTask", resp, "Failure sending request")
|
||||
return
|
||||
}
|
||||
|
||||
result.nflr, err = client.ListFromTaskResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "ListFromTask", resp, "Failure responding to request")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ListFromTaskPreparer prepares the ListFromTask request.
|
||||
func (client FileClient) ListFromTaskPreparer(ctx context.Context, jobID string, taskID string, filter string, recursive *bool, maxResults *int32, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (*http.Request, error) {
|
||||
pathParameters := map[string]interface{}{
|
||||
"jobId": autorest.Encode("path", jobID),
|
||||
"taskId": autorest.Encode("path", taskID),
|
||||
}
|
||||
|
||||
const APIVersion = "2017-09-01.6.0"
|
||||
queryParameters := map[string]interface{}{
|
||||
"api-version": APIVersion,
|
||||
}
|
||||
if len(filter) > 0 {
|
||||
queryParameters["$filter"] = autorest.Encode("query", filter)
|
||||
}
|
||||
if recursive != nil {
|
||||
queryParameters["recursive"] = autorest.Encode("query", *recursive)
|
||||
}
|
||||
if maxResults != nil {
|
||||
queryParameters["maxresults"] = autorest.Encode("query", *maxResults)
|
||||
} else {
|
||||
queryParameters["maxresults"] = autorest.Encode("query", 1000)
|
||||
}
|
||||
if timeout != nil {
|
||||
queryParameters["timeout"] = autorest.Encode("query", *timeout)
|
||||
} else {
|
||||
queryParameters["timeout"] = autorest.Encode("query", 30)
|
||||
}
|
||||
|
||||
preparer := autorest.CreatePreparer(
|
||||
autorest.AsGet(),
|
||||
autorest.WithBaseURL(client.BaseURI),
|
||||
autorest.WithPathParameters("/jobs/{jobId}/tasks/{taskId}/files", pathParameters),
|
||||
autorest.WithQueryParameters(queryParameters))
|
||||
if clientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("client-request-id", autorest.String(clientRequestID)))
|
||||
}
|
||||
if returnClientRequestID != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(returnClientRequestID)))
|
||||
} else {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("return-client-request-id", autorest.String(false)))
|
||||
}
|
||||
if ocpDate != nil {
|
||||
preparer = autorest.DecoratePreparer(preparer,
|
||||
autorest.WithHeader("ocp-date", autorest.String(ocpDate)))
|
||||
}
|
||||
return preparer.Prepare((&http.Request{}).WithContext(ctx))
|
||||
}
|
||||
|
||||
// ListFromTaskSender sends the ListFromTask request. The method will close the
|
||||
// http.Response Body if it receives an error.
|
||||
func (client FileClient) ListFromTaskSender(req *http.Request) (*http.Response, error) {
|
||||
return autorest.SendWithSender(client, req,
|
||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...))
|
||||
}
|
||||
|
||||
// ListFromTaskResponder handles the response to the ListFromTask request. The method always
|
||||
// closes the http.Response Body.
|
||||
func (client FileClient) ListFromTaskResponder(resp *http.Response) (result NodeFileListResult, err error) {
|
||||
err = autorest.Respond(
|
||||
resp,
|
||||
client.ByInspecting(),
|
||||
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||
autorest.ByUnmarshallingJSON(&result),
|
||||
autorest.ByClosing())
|
||||
result.Response = autorest.Response{Response: resp}
|
||||
return
|
||||
}
|
||||
|
||||
// listFromTaskNextResults retrieves the next set of results, if any.
|
||||
func (client FileClient) listFromTaskNextResults(lastResults NodeFileListResult) (result NodeFileListResult, err error) {
|
||||
req, err := lastResults.nodeFileListResultPreparer()
|
||||
if err != nil {
|
||||
return result, autorest.NewErrorWithError(err, "batch.FileClient", "listFromTaskNextResults", nil, "Failure preparing next results request")
|
||||
}
|
||||
if req == nil {
|
||||
return
|
||||
}
|
||||
resp, err := client.ListFromTaskSender(req)
|
||||
if err != nil {
|
||||
result.Response = autorest.Response{Response: resp}
|
||||
return result, autorest.NewErrorWithError(err, "batch.FileClient", "listFromTaskNextResults", resp, "Failure sending next results request")
|
||||
}
|
||||
result, err = client.ListFromTaskResponder(resp)
|
||||
if err != nil {
|
||||
err = autorest.NewErrorWithError(err, "batch.FileClient", "listFromTaskNextResults", resp, "Failure responding to next results request")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ListFromTaskComplete enumerates all values, automatically crossing page boundaries as required.
|
||||
func (client FileClient) ListFromTaskComplete(ctx context.Context, jobID string, taskID string, filter string, recursive *bool, maxResults *int32, timeout *int32, clientRequestID *uuid.UUID, returnClientRequestID *bool, ocpDate *date.TimeRFC1123) (result NodeFileListResultIterator, err error) {
|
||||
result.page, err = client.ListFromTask(ctx, jobID, taskID, filter, recursive, maxResults, timeout, clientRequestID, returnClientRequestID, ocpDate)
|
||||
return
|
||||
}
|
||||
1660
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/job.go
generated
vendored
Normal file
1660
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/job.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1324
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/jobschedule.go
generated
vendored
Normal file
1324
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/jobschedule.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3418
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/models.go
generated
vendored
Normal file
3418
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/models.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1897
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/pool.go
generated
vendored
Normal file
1897
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/pool.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1081
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/task.go
generated
vendored
Normal file
1081
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/task.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
30
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/version.go
generated
vendored
Normal file
30
vendor/github.com/Azure/azure-sdk-for-go/services/batch/2017-09-01.6.0/batch/version.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
package batch
|
||||
|
||||
import "github.com/Azure/azure-sdk-for-go/version"
|
||||
|
||||
// Copyright (c) Microsoft and contributors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
|
||||
|
||||
// UserAgent returns the UserAgent string to use when sending http.Requests.
|
||||
func UserAgent() string {
|
||||
return "Azure-SDK-For-Go/" + version.Number + " batch/2017-09-01.6.0"
|
||||
}
|
||||
|
||||
// Version returns the semantic version (see http://semver.org) of the client.
|
||||
func Version() string {
|
||||
return version.Number
|
||||
}
|
||||
21
vendor/github.com/Azure/azure-sdk-for-go/version/version.go
generated
vendored
Normal file
21
vendor/github.com/Azure/azure-sdk-for-go/version/version.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
package version
|
||||
|
||||
// Copyright (c) Microsoft and contributors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
|
||||
|
||||
// Number contains the semantic version of this SDK.
|
||||
const Number = "v15.1.1"
|
||||
259
vendor/github.com/Azure/go-autorest/autorest/authorization.go
generated
vendored
Normal file
259
vendor/github.com/Azure/go-autorest/autorest/authorization.go
generated
vendored
Normal file
@@ -0,0 +1,259 @@
|
||||
package autorest
|
||||
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/go-autorest/autorest/adal"
|
||||
)
|
||||
|
||||
const (
|
||||
bearerChallengeHeader = "Www-Authenticate"
|
||||
bearer = "Bearer"
|
||||
tenantID = "tenantID"
|
||||
apiKeyAuthorizerHeader = "Ocp-Apim-Subscription-Key"
|
||||
bingAPISdkHeader = "X-BingApis-SDK-Client"
|
||||
golangBingAPISdkHeaderValue = "Go-SDK"
|
||||
)
|
||||
|
||||
// Authorizer is the interface that provides a PrepareDecorator used to supply request
|
||||
// authorization. Most often, the Authorizer decorator runs last so it has access to the full
|
||||
// state of the formed HTTP request.
|
||||
type Authorizer interface {
|
||||
WithAuthorization() PrepareDecorator
|
||||
}
|
||||
|
||||
// NullAuthorizer implements a default, "do nothing" Authorizer.
|
||||
type NullAuthorizer struct{}
|
||||
|
||||
// WithAuthorization returns a PrepareDecorator that does nothing.
|
||||
func (na NullAuthorizer) WithAuthorization() PrepareDecorator {
|
||||
return WithNothing()
|
||||
}
|
||||
|
||||
// APIKeyAuthorizer implements API Key authorization.
|
||||
type APIKeyAuthorizer struct {
|
||||
headers map[string]interface{}
|
||||
queryParameters map[string]interface{}
|
||||
}
|
||||
|
||||
// NewAPIKeyAuthorizerWithHeaders creates an ApiKeyAuthorizer with headers.
|
||||
func NewAPIKeyAuthorizerWithHeaders(headers map[string]interface{}) *APIKeyAuthorizer {
|
||||
return NewAPIKeyAuthorizer(headers, nil)
|
||||
}
|
||||
|
||||
// NewAPIKeyAuthorizerWithQueryParameters creates an ApiKeyAuthorizer with query parameters.
|
||||
func NewAPIKeyAuthorizerWithQueryParameters(queryParameters map[string]interface{}) *APIKeyAuthorizer {
|
||||
return NewAPIKeyAuthorizer(nil, queryParameters)
|
||||
}
|
||||
|
||||
// NewAPIKeyAuthorizer creates an ApiKeyAuthorizer with headers.
|
||||
func NewAPIKeyAuthorizer(headers map[string]interface{}, queryParameters map[string]interface{}) *APIKeyAuthorizer {
|
||||
return &APIKeyAuthorizer{headers: headers, queryParameters: queryParameters}
|
||||
}
|
||||
|
||||
// WithAuthorization returns a PrepareDecorator that adds an HTTP headers and Query Paramaters
|
||||
func (aka *APIKeyAuthorizer) WithAuthorization() PrepareDecorator {
|
||||
return func(p Preparer) Preparer {
|
||||
return DecoratePreparer(p, WithHeaders(aka.headers), WithQueryParameters(aka.queryParameters))
|
||||
}
|
||||
}
|
||||
|
||||
// CognitiveServicesAuthorizer implements authorization for Cognitive Services.
|
||||
type CognitiveServicesAuthorizer struct {
|
||||
subscriptionKey string
|
||||
}
|
||||
|
||||
// NewCognitiveServicesAuthorizer is
|
||||
func NewCognitiveServicesAuthorizer(subscriptionKey string) *CognitiveServicesAuthorizer {
|
||||
return &CognitiveServicesAuthorizer{subscriptionKey: subscriptionKey}
|
||||
}
|
||||
|
||||
// WithAuthorization is
|
||||
func (csa *CognitiveServicesAuthorizer) WithAuthorization() PrepareDecorator {
|
||||
headers := make(map[string]interface{})
|
||||
headers[apiKeyAuthorizerHeader] = csa.subscriptionKey
|
||||
headers[bingAPISdkHeader] = golangBingAPISdkHeaderValue
|
||||
|
||||
return NewAPIKeyAuthorizerWithHeaders(headers).WithAuthorization()
|
||||
}
|
||||
|
||||
// BearerAuthorizer implements the bearer authorization
|
||||
type BearerAuthorizer struct {
|
||||
tokenProvider adal.OAuthTokenProvider
|
||||
}
|
||||
|
||||
// NewBearerAuthorizer crates a BearerAuthorizer using the given token provider
|
||||
func NewBearerAuthorizer(tp adal.OAuthTokenProvider) *BearerAuthorizer {
|
||||
return &BearerAuthorizer{tokenProvider: tp}
|
||||
}
|
||||
|
||||
// WithAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose
|
||||
// value is "Bearer " followed by the token.
|
||||
//
|
||||
// By default, the token will be automatically refreshed through the Refresher interface.
|
||||
func (ba *BearerAuthorizer) WithAuthorization() PrepareDecorator {
|
||||
return func(p Preparer) Preparer {
|
||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
r, err := p.Prepare(r)
|
||||
if err == nil {
|
||||
// the ordering is important here, prefer RefresherWithContext if available
|
||||
if refresher, ok := ba.tokenProvider.(adal.RefresherWithContext); ok {
|
||||
err = refresher.EnsureFreshWithContext(r.Context())
|
||||
} else if refresher, ok := ba.tokenProvider.(adal.Refresher); ok {
|
||||
err = refresher.EnsureFresh()
|
||||
}
|
||||
if err != nil {
|
||||
var resp *http.Response
|
||||
if tokError, ok := err.(adal.TokenRefreshError); ok {
|
||||
resp = tokError.Response()
|
||||
}
|
||||
return r, NewErrorWithError(err, "azure.BearerAuthorizer", "WithAuthorization", resp,
|
||||
"Failed to refresh the Token for request to %s", r.URL)
|
||||
}
|
||||
return Prepare(r, WithHeader(headerAuthorization, fmt.Sprintf("Bearer %s", ba.tokenProvider.OAuthToken())))
|
||||
}
|
||||
return r, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// BearerAuthorizerCallbackFunc is the authentication callback signature.
|
||||
type BearerAuthorizerCallbackFunc func(tenantID, resource string) (*BearerAuthorizer, error)
|
||||
|
||||
// BearerAuthorizerCallback implements bearer authorization via a callback.
|
||||
type BearerAuthorizerCallback struct {
|
||||
sender Sender
|
||||
callback BearerAuthorizerCallbackFunc
|
||||
}
|
||||
|
||||
// NewBearerAuthorizerCallback creates a bearer authorization callback. The callback
|
||||
// is invoked when the HTTP request is submitted.
|
||||
func NewBearerAuthorizerCallback(sender Sender, callback BearerAuthorizerCallbackFunc) *BearerAuthorizerCallback {
|
||||
if sender == nil {
|
||||
sender = &http.Client{}
|
||||
}
|
||||
return &BearerAuthorizerCallback{sender: sender, callback: callback}
|
||||
}
|
||||
|
||||
// WithAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose value
|
||||
// is "Bearer " followed by the token. The BearerAuthorizer is obtained via a user-supplied callback.
|
||||
//
|
||||
// By default, the token will be automatically refreshed through the Refresher interface.
|
||||
func (bacb *BearerAuthorizerCallback) WithAuthorization() PrepareDecorator {
|
||||
return func(p Preparer) Preparer {
|
||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
r, err := p.Prepare(r)
|
||||
if err == nil {
|
||||
// make a copy of the request and remove the body as it's not
|
||||
// required and avoids us having to create a copy of it.
|
||||
rCopy := *r
|
||||
removeRequestBody(&rCopy)
|
||||
|
||||
resp, err := bacb.sender.Do(&rCopy)
|
||||
if err == nil && resp.StatusCode == 401 {
|
||||
defer resp.Body.Close()
|
||||
if hasBearerChallenge(resp) {
|
||||
bc, err := newBearerChallenge(resp)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
if bacb.callback != nil {
|
||||
ba, err := bacb.callback(bc.values[tenantID], bc.values["resource"])
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
return Prepare(r, ba.WithAuthorization())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return r, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// returns true if the HTTP response contains a bearer challenge
|
||||
func hasBearerChallenge(resp *http.Response) bool {
|
||||
authHeader := resp.Header.Get(bearerChallengeHeader)
|
||||
if len(authHeader) == 0 || strings.Index(authHeader, bearer) < 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
type bearerChallenge struct {
|
||||
values map[string]string
|
||||
}
|
||||
|
||||
func newBearerChallenge(resp *http.Response) (bc bearerChallenge, err error) {
|
||||
challenge := strings.TrimSpace(resp.Header.Get(bearerChallengeHeader))
|
||||
trimmedChallenge := challenge[len(bearer)+1:]
|
||||
|
||||
// challenge is a set of key=value pairs that are comma delimited
|
||||
pairs := strings.Split(trimmedChallenge, ",")
|
||||
if len(pairs) < 1 {
|
||||
err = fmt.Errorf("challenge '%s' contains no pairs", challenge)
|
||||
return bc, err
|
||||
}
|
||||
|
||||
bc.values = make(map[string]string)
|
||||
for i := range pairs {
|
||||
trimmedPair := strings.TrimSpace(pairs[i])
|
||||
pair := strings.Split(trimmedPair, "=")
|
||||
if len(pair) == 2 {
|
||||
// remove the enclosing quotes
|
||||
key := strings.Trim(pair[0], "\"")
|
||||
value := strings.Trim(pair[1], "\"")
|
||||
|
||||
switch key {
|
||||
case "authorization", "authorization_uri":
|
||||
// strip the tenant ID from the authorization URL
|
||||
asURL, err := url.Parse(value)
|
||||
if err != nil {
|
||||
return bc, err
|
||||
}
|
||||
bc.values[tenantID] = asURL.Path[1:]
|
||||
default:
|
||||
bc.values[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bc, err
|
||||
}
|
||||
|
||||
// EventGridKeyAuthorizer implements authorization for event grid using key authentication.
|
||||
type EventGridKeyAuthorizer struct {
|
||||
topicKey string
|
||||
}
|
||||
|
||||
// NewEventGridKeyAuthorizer creates a new EventGridKeyAuthorizer
|
||||
// with the specified topic key.
|
||||
func NewEventGridKeyAuthorizer(topicKey string) EventGridKeyAuthorizer {
|
||||
return EventGridKeyAuthorizer{topicKey: topicKey}
|
||||
}
|
||||
|
||||
// WithAuthorization returns a PrepareDecorator that adds the aeg-sas-key authentication header.
|
||||
func (egta EventGridKeyAuthorizer) WithAuthorization() PrepareDecorator {
|
||||
headers := map[string]interface{}{
|
||||
"aeg-sas-key": egta.topicKey,
|
||||
}
|
||||
return NewAPIKeyAuthorizerWithHeaders(headers).WithAuthorization()
|
||||
}
|
||||
150
vendor/github.com/Azure/go-autorest/autorest/autorest.go
generated
vendored
Normal file
150
vendor/github.com/Azure/go-autorest/autorest/autorest.go
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
Package autorest implements an HTTP request pipeline suitable for use across multiple go-routines
|
||||
and provides the shared routines relied on by AutoRest (see https://github.com/Azure/autorest/)
|
||||
generated Go code.
|
||||
|
||||
The package breaks sending and responding to HTTP requests into three phases: Preparing, Sending,
|
||||
and Responding. A typical pattern is:
|
||||
|
||||
req, err := Prepare(&http.Request{},
|
||||
token.WithAuthorization())
|
||||
|
||||
resp, err := Send(req,
|
||||
WithLogging(logger),
|
||||
DoErrorIfStatusCode(http.StatusInternalServerError),
|
||||
DoCloseIfError(),
|
||||
DoRetryForAttempts(5, time.Second))
|
||||
|
||||
err = Respond(resp,
|
||||
ByDiscardingBody(),
|
||||
ByClosing())
|
||||
|
||||
Each phase relies on decorators to modify and / or manage processing. Decorators may first modify
|
||||
and then pass the data along, pass the data first and then modify the result, or wrap themselves
|
||||
around passing the data (such as a logger might do). Decorators run in the order provided. For
|
||||
example, the following:
|
||||
|
||||
req, err := Prepare(&http.Request{},
|
||||
WithBaseURL("https://microsoft.com/"),
|
||||
WithPath("a"),
|
||||
WithPath("b"),
|
||||
WithPath("c"))
|
||||
|
||||
will set the URL to:
|
||||
|
||||
https://microsoft.com/a/b/c
|
||||
|
||||
Preparers and Responders may be shared and re-used (assuming the underlying decorators support
|
||||
sharing and re-use). Performant use is obtained by creating one or more Preparers and Responders
|
||||
shared among multiple go-routines, and a single Sender shared among multiple sending go-routines,
|
||||
all bound together by means of input / output channels.
|
||||
|
||||
Decorators hold their passed state within a closure (such as the path components in the example
|
||||
above). Be careful to share Preparers and Responders only in a context where such held state
|
||||
applies. For example, it may not make sense to share a Preparer that applies a query string from a
|
||||
fixed set of values. Similarly, sharing a Responder that reads the response body into a passed
|
||||
struct (e.g., ByUnmarshallingJson) is likely incorrect.
|
||||
|
||||
Lastly, the Swagger specification (https://swagger.io) that drives AutoRest
|
||||
(https://github.com/Azure/autorest/) precisely defines two date forms: date and date-time. The
|
||||
github.com/Azure/go-autorest/autorest/date package provides time.Time derivations to ensure
|
||||
correct parsing and formatting.
|
||||
|
||||
Errors raised by autorest objects and methods will conform to the autorest.Error interface.
|
||||
|
||||
See the included examples for more detail. For details on the suggested use of this package by
|
||||
generated clients, see the Client described below.
|
||||
*/
|
||||
package autorest
|
||||
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// HeaderLocation specifies the HTTP Location header.
|
||||
HeaderLocation = "Location"
|
||||
|
||||
// HeaderRetryAfter specifies the HTTP Retry-After header.
|
||||
HeaderRetryAfter = "Retry-After"
|
||||
)
|
||||
|
||||
// ResponseHasStatusCode returns true if the status code in the HTTP Response is in the passed set
|
||||
// and false otherwise.
|
||||
func ResponseHasStatusCode(resp *http.Response, codes ...int) bool {
|
||||
if resp == nil {
|
||||
return false
|
||||
}
|
||||
return containsInt(codes, resp.StatusCode)
|
||||
}
|
||||
|
||||
// GetLocation retrieves the URL from the Location header of the passed response.
|
||||
func GetLocation(resp *http.Response) string {
|
||||
return resp.Header.Get(HeaderLocation)
|
||||
}
|
||||
|
||||
// GetRetryAfter extracts the retry delay from the Retry-After header of the passed response. If
|
||||
// the header is absent or is malformed, it will return the supplied default delay time.Duration.
|
||||
func GetRetryAfter(resp *http.Response, defaultDelay time.Duration) time.Duration {
|
||||
retry := resp.Header.Get(HeaderRetryAfter)
|
||||
if retry == "" {
|
||||
return defaultDelay
|
||||
}
|
||||
|
||||
d, err := time.ParseDuration(retry + "s")
|
||||
if err != nil {
|
||||
return defaultDelay
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
// NewPollingRequest allocates and returns a new http.Request to poll for the passed response.
|
||||
func NewPollingRequest(resp *http.Response, cancel <-chan struct{}) (*http.Request, error) {
|
||||
location := GetLocation(resp)
|
||||
if location == "" {
|
||||
return nil, NewErrorWithResponse("autorest", "NewPollingRequest", resp, "Location header missing from response that requires polling")
|
||||
}
|
||||
|
||||
req, err := Prepare(&http.Request{Cancel: cancel},
|
||||
AsGet(),
|
||||
WithBaseURL(location))
|
||||
if err != nil {
|
||||
return nil, NewErrorWithError(err, "autorest", "NewPollingRequest", nil, "Failure creating poll request to %s", location)
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
// NewPollingRequestWithContext allocates and returns a new http.Request with the specified context to poll for the passed response.
|
||||
func NewPollingRequestWithContext(ctx context.Context, resp *http.Response) (*http.Request, error) {
|
||||
location := GetLocation(resp)
|
||||
if location == "" {
|
||||
return nil, NewErrorWithResponse("autorest", "NewPollingRequestWithContext", resp, "Location header missing from response that requires polling")
|
||||
}
|
||||
|
||||
req, err := Prepare((&http.Request{}).WithContext(ctx),
|
||||
AsGet(),
|
||||
WithBaseURL(location))
|
||||
if err != nil {
|
||||
return nil, NewErrorWithError(err, "autorest", "NewPollingRequestWithContext", nil, "Failure creating poll request to %s", location)
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
511
vendor/github.com/Azure/go-autorest/autorest/azure/async.go
generated
vendored
Normal file
511
vendor/github.com/Azure/go-autorest/autorest/azure/async.go
generated
vendored
Normal file
@@ -0,0 +1,511 @@
|
||||
package azure
|
||||
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/Azure/go-autorest/autorest/date"
|
||||
)
|
||||
|
||||
const (
|
||||
headerAsyncOperation = "Azure-AsyncOperation"
|
||||
)
|
||||
|
||||
const (
|
||||
operationInProgress string = "InProgress"
|
||||
operationCanceled string = "Canceled"
|
||||
operationFailed string = "Failed"
|
||||
operationSucceeded string = "Succeeded"
|
||||
)
|
||||
|
||||
var pollingCodes = [...]int{http.StatusNoContent, http.StatusAccepted, http.StatusCreated, http.StatusOK}
|
||||
|
||||
// Future provides a mechanism to access the status and results of an asynchronous request.
|
||||
// Since futures are stateful they should be passed by value to avoid race conditions.
|
||||
type Future struct {
|
||||
req *http.Request
|
||||
resp *http.Response
|
||||
ps pollingState
|
||||
}
|
||||
|
||||
// NewFuture returns a new Future object initialized with the specified request.
|
||||
func NewFuture(req *http.Request) Future {
|
||||
return Future{req: req}
|
||||
}
|
||||
|
||||
// Response returns the last HTTP response or nil if there isn't one.
|
||||
func (f Future) Response() *http.Response {
|
||||
return f.resp
|
||||
}
|
||||
|
||||
// Status returns the last status message of the operation.
|
||||
func (f Future) Status() string {
|
||||
if f.ps.State == "" {
|
||||
return "Unknown"
|
||||
}
|
||||
return f.ps.State
|
||||
}
|
||||
|
||||
// PollingMethod returns the method used to monitor the status of the asynchronous operation.
|
||||
func (f Future) PollingMethod() PollingMethodType {
|
||||
return f.ps.PollingMethod
|
||||
}
|
||||
|
||||
// Done queries the service to see if the operation has completed.
|
||||
func (f *Future) Done(sender autorest.Sender) (bool, error) {
|
||||
// exit early if this future has terminated
|
||||
if f.ps.hasTerminated() {
|
||||
return true, f.errorInfo()
|
||||
}
|
||||
resp, err := sender.Do(f.req)
|
||||
f.resp = resp
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if !autorest.ResponseHasStatusCode(resp, pollingCodes[:]...) {
|
||||
// check response body for error content
|
||||
if resp.Body != nil {
|
||||
type respErr struct {
|
||||
ServiceError ServiceError `json:"error"`
|
||||
}
|
||||
re := respErr{}
|
||||
|
||||
defer resp.Body.Close()
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
err = json.Unmarshal(b, &re)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return false, re.ServiceError
|
||||
}
|
||||
|
||||
// try to return something meaningful
|
||||
return false, ServiceError{
|
||||
Code: fmt.Sprintf("%v", resp.StatusCode),
|
||||
Message: resp.Status,
|
||||
}
|
||||
}
|
||||
|
||||
err = updatePollingState(resp, &f.ps)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if f.ps.hasTerminated() {
|
||||
return true, f.errorInfo()
|
||||
}
|
||||
|
||||
f.req, err = newPollingRequest(f.ps)
|
||||
return false, err
|
||||
}
|
||||
|
||||
// GetPollingDelay returns a duration the application should wait before checking
|
||||
// the status of the asynchronous request and true; this value is returned from
|
||||
// the service via the Retry-After response header. If the header wasn't returned
|
||||
// then the function returns the zero-value time.Duration and false.
|
||||
func (f Future) GetPollingDelay() (time.Duration, bool) {
|
||||
if f.resp == nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
retry := f.resp.Header.Get(autorest.HeaderRetryAfter)
|
||||
if retry == "" {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
d, err := time.ParseDuration(retry + "s")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return d, true
|
||||
}
|
||||
|
||||
// WaitForCompletion will return when one of the following conditions is met: the long
|
||||
// running operation has completed, the provided context is cancelled, or the client's
|
||||
// polling duration has been exceeded. It will retry failed polling attempts based on
|
||||
// the retry value defined in the client up to the maximum retry attempts.
|
||||
func (f Future) WaitForCompletion(ctx context.Context, client autorest.Client) error {
|
||||
ctx, cancel := context.WithTimeout(ctx, client.PollingDuration)
|
||||
defer cancel()
|
||||
|
||||
done, err := f.Done(client)
|
||||
for attempts := 0; !done; done, err = f.Done(client) {
|
||||
if attempts >= client.RetryAttempts {
|
||||
return autorest.NewErrorWithError(err, "azure", "WaitForCompletion", f.resp, "the number of retries has been exceeded")
|
||||
}
|
||||
// we want delayAttempt to be zero in the non-error case so
|
||||
// that DelayForBackoff doesn't perform exponential back-off
|
||||
var delayAttempt int
|
||||
var delay time.Duration
|
||||
if err == nil {
|
||||
// check for Retry-After delay, if not present use the client's polling delay
|
||||
var ok bool
|
||||
delay, ok = f.GetPollingDelay()
|
||||
if !ok {
|
||||
delay = client.PollingDelay
|
||||
}
|
||||
} else {
|
||||
// there was an error polling for status so perform exponential
|
||||
// back-off based on the number of attempts using the client's retry
|
||||
// duration. update attempts after delayAttempt to avoid off-by-one.
|
||||
delayAttempt = attempts
|
||||
delay = client.RetryDuration
|
||||
attempts++
|
||||
}
|
||||
// wait until the delay elapses or the context is cancelled
|
||||
delayElapsed := autorest.DelayForBackoff(delay, delayAttempt, ctx.Done())
|
||||
if !delayElapsed {
|
||||
return autorest.NewErrorWithError(ctx.Err(), "azure", "WaitForCompletion", f.resp, "context has been cancelled")
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// if the operation failed the polling state will contain
|
||||
// error information and implements the error interface
|
||||
func (f *Future) errorInfo() error {
|
||||
if !f.ps.hasSucceeded() {
|
||||
return f.ps
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json.Marshaler interface.
|
||||
func (f Future) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(&f.ps)
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||
func (f *Future) UnmarshalJSON(data []byte) error {
|
||||
err := json.Unmarshal(data, &f.ps)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.req, err = newPollingRequest(f.ps)
|
||||
return err
|
||||
}
|
||||
|
||||
// PollingURL returns the URL used for retrieving the status of the long-running operation.
|
||||
// For LROs that use the Location header the final URL value is used to retrieve the result.
|
||||
func (f Future) PollingURL() string {
|
||||
return f.ps.URI
|
||||
}
|
||||
|
||||
// DoPollForAsynchronous returns a SendDecorator that polls if the http.Response is for an Azure
|
||||
// long-running operation. It will delay between requests for the duration specified in the
|
||||
// RetryAfter header or, if the header is absent, the passed delay. Polling may be canceled by
|
||||
// closing the optional channel on the http.Request.
|
||||
func DoPollForAsynchronous(delay time.Duration) autorest.SendDecorator {
|
||||
return func(s autorest.Sender) autorest.Sender {
|
||||
return autorest.SenderFunc(func(r *http.Request) (resp *http.Response, err error) {
|
||||
resp, err = s.Do(r)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
if !autorest.ResponseHasStatusCode(resp, pollingCodes[:]...) {
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
ps := pollingState{}
|
||||
for err == nil {
|
||||
err = updatePollingState(resp, &ps)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if ps.hasTerminated() {
|
||||
if !ps.hasSucceeded() {
|
||||
err = ps
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
r, err = newPollingRequest(ps)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
r = r.WithContext(resp.Request.Context())
|
||||
|
||||
delay = autorest.GetRetryAfter(resp, delay)
|
||||
resp, err = autorest.SendWithSender(s, r,
|
||||
autorest.AfterDelay(delay))
|
||||
}
|
||||
|
||||
return resp, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func getAsyncOperation(resp *http.Response) string {
|
||||
return resp.Header.Get(http.CanonicalHeaderKey(headerAsyncOperation))
|
||||
}
|
||||
|
||||
func hasSucceeded(state string) bool {
|
||||
return strings.EqualFold(state, operationSucceeded)
|
||||
}
|
||||
|
||||
func hasTerminated(state string) bool {
|
||||
return strings.EqualFold(state, operationCanceled) || strings.EqualFold(state, operationFailed) || strings.EqualFold(state, operationSucceeded)
|
||||
}
|
||||
|
||||
func hasFailed(state string) bool {
|
||||
return strings.EqualFold(state, operationFailed)
|
||||
}
|
||||
|
||||
type provisioningTracker interface {
|
||||
state() string
|
||||
hasSucceeded() bool
|
||||
hasTerminated() bool
|
||||
}
|
||||
|
||||
type operationResource struct {
|
||||
// Note:
|
||||
// The specification states services should return the "id" field. However some return it as
|
||||
// "operationId".
|
||||
ID string `json:"id"`
|
||||
OperationID string `json:"operationId"`
|
||||
Name string `json:"name"`
|
||||
Status string `json:"status"`
|
||||
Properties map[string]interface{} `json:"properties"`
|
||||
OperationError ServiceError `json:"error"`
|
||||
StartTime date.Time `json:"startTime"`
|
||||
EndTime date.Time `json:"endTime"`
|
||||
PercentComplete float64 `json:"percentComplete"`
|
||||
}
|
||||
|
||||
func (or operationResource) state() string {
|
||||
return or.Status
|
||||
}
|
||||
|
||||
func (or operationResource) hasSucceeded() bool {
|
||||
return hasSucceeded(or.state())
|
||||
}
|
||||
|
||||
func (or operationResource) hasTerminated() bool {
|
||||
return hasTerminated(or.state())
|
||||
}
|
||||
|
||||
type provisioningProperties struct {
|
||||
ProvisioningState string `json:"provisioningState"`
|
||||
}
|
||||
|
||||
type provisioningStatus struct {
|
||||
Properties provisioningProperties `json:"properties,omitempty"`
|
||||
ProvisioningError ServiceError `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func (ps provisioningStatus) state() string {
|
||||
return ps.Properties.ProvisioningState
|
||||
}
|
||||
|
||||
func (ps provisioningStatus) hasSucceeded() bool {
|
||||
return hasSucceeded(ps.state())
|
||||
}
|
||||
|
||||
func (ps provisioningStatus) hasTerminated() bool {
|
||||
return hasTerminated(ps.state())
|
||||
}
|
||||
|
||||
func (ps provisioningStatus) hasProvisioningError() bool {
|
||||
// code and message are required fields so only check them
|
||||
return len(ps.ProvisioningError.Code) > 0 ||
|
||||
len(ps.ProvisioningError.Message) > 0
|
||||
}
|
||||
|
||||
// PollingMethodType defines a type used for enumerating polling mechanisms.
|
||||
type PollingMethodType string
|
||||
|
||||
const (
|
||||
// PollingAsyncOperation indicates the polling method uses the Azure-AsyncOperation header.
|
||||
PollingAsyncOperation PollingMethodType = "AsyncOperation"
|
||||
|
||||
// PollingLocation indicates the polling method uses the Location header.
|
||||
PollingLocation PollingMethodType = "Location"
|
||||
|
||||
// PollingUnknown indicates an unknown polling method and is the default value.
|
||||
PollingUnknown PollingMethodType = ""
|
||||
)
|
||||
|
||||
type pollingState struct {
|
||||
PollingMethod PollingMethodType `json:"pollingMethod"`
|
||||
URI string `json:"uri"`
|
||||
State string `json:"state"`
|
||||
ServiceError *ServiceError `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func (ps pollingState) hasSucceeded() bool {
|
||||
return hasSucceeded(ps.State)
|
||||
}
|
||||
|
||||
func (ps pollingState) hasTerminated() bool {
|
||||
return hasTerminated(ps.State)
|
||||
}
|
||||
|
||||
func (ps pollingState) hasFailed() bool {
|
||||
return hasFailed(ps.State)
|
||||
}
|
||||
|
||||
func (ps pollingState) Error() string {
|
||||
s := fmt.Sprintf("Long running operation terminated with status '%s'", ps.State)
|
||||
if ps.ServiceError != nil {
|
||||
s = fmt.Sprintf("%s: %+v", s, *ps.ServiceError)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// updatePollingState maps the operation status -- retrieved from either a provisioningState
|
||||
// field, the status field of an OperationResource, or inferred from the HTTP status code --
|
||||
// into a well-known states. Since the process begins from the initial request, the state
|
||||
// always comes from either a the provisioningState returned or is inferred from the HTTP
|
||||
// status code. Subsequent requests will read an Azure OperationResource object if the
|
||||
// service initially returned the Azure-AsyncOperation header. The responseFormat field notes
|
||||
// the expected response format.
|
||||
func updatePollingState(resp *http.Response, ps *pollingState) error {
|
||||
// Determine the response shape
|
||||
// -- The first response will always be a provisioningStatus response; only the polling requests,
|
||||
// depending on the header returned, may be something otherwise.
|
||||
var pt provisioningTracker
|
||||
if ps.PollingMethod == PollingAsyncOperation {
|
||||
pt = &operationResource{}
|
||||
} else {
|
||||
pt = &provisioningStatus{}
|
||||
}
|
||||
|
||||
// If this is the first request (that is, the polling response shape is unknown), determine how
|
||||
// to poll and what to expect
|
||||
if ps.PollingMethod == PollingUnknown {
|
||||
req := resp.Request
|
||||
if req == nil {
|
||||
return autorest.NewError("azure", "updatePollingState", "Azure Polling Error - Original HTTP request is missing")
|
||||
}
|
||||
|
||||
// Prefer the Azure-AsyncOperation header
|
||||
ps.URI = getAsyncOperation(resp)
|
||||
if ps.URI != "" {
|
||||
ps.PollingMethod = PollingAsyncOperation
|
||||
} else {
|
||||
ps.PollingMethod = PollingLocation
|
||||
}
|
||||
|
||||
// Else, use the Location header
|
||||
if ps.URI == "" {
|
||||
ps.URI = autorest.GetLocation(resp)
|
||||
}
|
||||
|
||||
// Lastly, requests against an existing resource, use the last request URI
|
||||
if ps.URI == "" {
|
||||
m := strings.ToUpper(req.Method)
|
||||
if m == http.MethodPatch || m == http.MethodPut || m == http.MethodGet {
|
||||
ps.URI = req.URL.String()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read and interpret the response (saving the Body in case no polling is necessary)
|
||||
b := &bytes.Buffer{}
|
||||
err := autorest.Respond(resp,
|
||||
autorest.ByCopying(b),
|
||||
autorest.ByUnmarshallingJSON(pt),
|
||||
autorest.ByClosing())
|
||||
resp.Body = ioutil.NopCloser(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Interpret the results
|
||||
// -- Terminal states apply regardless
|
||||
// -- Unknown states are per-service inprogress states
|
||||
// -- Otherwise, infer state from HTTP status code
|
||||
if pt.hasTerminated() {
|
||||
ps.State = pt.state()
|
||||
} else if pt.state() != "" {
|
||||
ps.State = operationInProgress
|
||||
} else {
|
||||
switch resp.StatusCode {
|
||||
case http.StatusAccepted:
|
||||
ps.State = operationInProgress
|
||||
|
||||
case http.StatusNoContent, http.StatusCreated, http.StatusOK:
|
||||
ps.State = operationSucceeded
|
||||
|
||||
default:
|
||||
ps.State = operationFailed
|
||||
}
|
||||
}
|
||||
|
||||
if strings.EqualFold(ps.State, operationInProgress) && ps.URI == "" {
|
||||
return autorest.NewError("azure", "updatePollingState", "Azure Polling Error - Unable to obtain polling URI for %s %s", resp.Request.Method, resp.Request.URL)
|
||||
}
|
||||
|
||||
// For failed operation, check for error code and message in
|
||||
// -- Operation resource
|
||||
// -- Response
|
||||
// -- Otherwise, Unknown
|
||||
if ps.hasFailed() {
|
||||
if or, ok := pt.(*operationResource); ok {
|
||||
ps.ServiceError = &or.OperationError
|
||||
} else if p, ok := pt.(*provisioningStatus); ok && p.hasProvisioningError() {
|
||||
ps.ServiceError = &p.ProvisioningError
|
||||
} else {
|
||||
ps.ServiceError = &ServiceError{
|
||||
Code: "Unknown",
|
||||
Message: "None",
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newPollingRequest(ps pollingState) (*http.Request, error) {
|
||||
reqPoll, err := autorest.Prepare(&http.Request{},
|
||||
autorest.AsGet(),
|
||||
autorest.WithBaseURL(ps.URI))
|
||||
if err != nil {
|
||||
return nil, autorest.NewErrorWithError(err, "azure", "newPollingRequest", nil, "Failure creating poll request to %s", ps.URI)
|
||||
}
|
||||
|
||||
return reqPoll, nil
|
||||
}
|
||||
|
||||
// AsyncOpIncompleteError is the type that's returned from a future that has not completed.
|
||||
type AsyncOpIncompleteError struct {
|
||||
// FutureType is the name of the type composed of a azure.Future.
|
||||
FutureType string
|
||||
}
|
||||
|
||||
// Error returns an error message including the originating type name of the error.
|
||||
func (e AsyncOpIncompleteError) Error() string {
|
||||
return fmt.Sprintf("%s: asynchronous operation has not completed", e.FutureType)
|
||||
}
|
||||
|
||||
// NewAsyncOpIncompleteError creates a new AsyncOpIncompleteError with the specified parameters.
|
||||
func NewAsyncOpIncompleteError(futureType string) AsyncOpIncompleteError {
|
||||
return AsyncOpIncompleteError{
|
||||
FutureType: futureType,
|
||||
}
|
||||
}
|
||||
301
vendor/github.com/Azure/go-autorest/autorest/azure/azure.go
generated
vendored
Normal file
301
vendor/github.com/Azure/go-autorest/autorest/azure/azure.go
generated
vendored
Normal file
@@ -0,0 +1,301 @@
|
||||
// Package azure provides Azure-specific implementations used with AutoRest.
|
||||
// See the included examples for more detail.
|
||||
package azure
|
||||
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
)
|
||||
|
||||
const (
|
||||
// HeaderClientID is the Azure extension header to set a user-specified request ID.
|
||||
HeaderClientID = "x-ms-client-request-id"
|
||||
|
||||
// HeaderReturnClientID is the Azure extension header to set if the user-specified request ID
|
||||
// should be included in the response.
|
||||
HeaderReturnClientID = "x-ms-return-client-request-id"
|
||||
|
||||
// HeaderRequestID is the Azure extension header of the service generated request ID returned
|
||||
// in the response.
|
||||
HeaderRequestID = "x-ms-request-id"
|
||||
)
|
||||
|
||||
// ServiceError encapsulates the error response from an Azure service.
|
||||
// It adhears to the OData v4 specification for error responses.
|
||||
type ServiceError struct {
|
||||
Code string `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Target *string `json:"target"`
|
||||
Details []map[string]interface{} `json:"details"`
|
||||
InnerError map[string]interface{} `json:"innererror"`
|
||||
}
|
||||
|
||||
func (se ServiceError) Error() string {
|
||||
result := fmt.Sprintf("Code=%q Message=%q", se.Code, se.Message)
|
||||
|
||||
if se.Target != nil {
|
||||
result += fmt.Sprintf(" Target=%q", *se.Target)
|
||||
}
|
||||
|
||||
if se.Details != nil {
|
||||
d, err := json.Marshal(se.Details)
|
||||
if err != nil {
|
||||
result += fmt.Sprintf(" Details=%v", se.Details)
|
||||
}
|
||||
result += fmt.Sprintf(" Details=%v", string(d))
|
||||
}
|
||||
|
||||
if se.InnerError != nil {
|
||||
d, err := json.Marshal(se.InnerError)
|
||||
if err != nil {
|
||||
result += fmt.Sprintf(" InnerError=%v", se.InnerError)
|
||||
}
|
||||
result += fmt.Sprintf(" InnerError=%v", string(d))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaler interface for the ServiceError type.
|
||||
func (se *ServiceError) UnmarshalJSON(b []byte) error {
|
||||
// per the OData v4 spec the details field must be an array of JSON objects.
|
||||
// unfortunately not all services adhear to the spec and just return a single
|
||||
// object instead of an array with one object. so we have to perform some
|
||||
// shenanigans to accommodate both cases.
|
||||
// http://docs.oasis-open.org/odata/odata-json-format/v4.0/os/odata-json-format-v4.0-os.html#_Toc372793091
|
||||
|
||||
type serviceError1 struct {
|
||||
Code string `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Target *string `json:"target"`
|
||||
Details []map[string]interface{} `json:"details"`
|
||||
InnerError map[string]interface{} `json:"innererror"`
|
||||
}
|
||||
|
||||
type serviceError2 struct {
|
||||
Code string `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Target *string `json:"target"`
|
||||
Details map[string]interface{} `json:"details"`
|
||||
InnerError map[string]interface{} `json:"innererror"`
|
||||
}
|
||||
|
||||
se1 := serviceError1{}
|
||||
err := json.Unmarshal(b, &se1)
|
||||
if err == nil {
|
||||
se.populate(se1.Code, se1.Message, se1.Target, se1.Details, se1.InnerError)
|
||||
return nil
|
||||
}
|
||||
|
||||
se2 := serviceError2{}
|
||||
err = json.Unmarshal(b, &se2)
|
||||
if err == nil {
|
||||
se.populate(se2.Code, se2.Message, se2.Target, nil, se2.InnerError)
|
||||
se.Details = append(se.Details, se2.Details)
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (se *ServiceError) populate(code, message string, target *string, details []map[string]interface{}, inner map[string]interface{}) {
|
||||
se.Code = code
|
||||
se.Message = message
|
||||
se.Target = target
|
||||
se.Details = details
|
||||
se.InnerError = inner
|
||||
}
|
||||
|
||||
// RequestError describes an error response returned by Azure service.
|
||||
type RequestError struct {
|
||||
autorest.DetailedError
|
||||
|
||||
// The error returned by the Azure service.
|
||||
ServiceError *ServiceError `json:"error"`
|
||||
|
||||
// The request id (from the x-ms-request-id-header) of the request.
|
||||
RequestID string
|
||||
}
|
||||
|
||||
// Error returns a human-friendly error message from service error.
|
||||
func (e RequestError) Error() string {
|
||||
return fmt.Sprintf("autorest/azure: Service returned an error. Status=%v %v",
|
||||
e.StatusCode, e.ServiceError)
|
||||
}
|
||||
|
||||
// IsAzureError returns true if the passed error is an Azure Service error; false otherwise.
|
||||
func IsAzureError(e error) bool {
|
||||
_, ok := e.(*RequestError)
|
||||
return ok
|
||||
}
|
||||
|
||||
// Resource contains details about an Azure resource.
|
||||
type Resource struct {
|
||||
SubscriptionID string
|
||||
ResourceGroup string
|
||||
Provider string
|
||||
ResourceType string
|
||||
ResourceName string
|
||||
}
|
||||
|
||||
// ParseResourceID parses a resource ID into a ResourceDetails struct.
|
||||
// See https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-template-functions-resource#return-value-4.
|
||||
func ParseResourceID(resourceID string) (Resource, error) {
|
||||
|
||||
const resourceIDPatternText = `(?i)subscriptions/(.+)/resourceGroups/(.+)/providers/(.+?)/(.+?)/(.+)`
|
||||
resourceIDPattern := regexp.MustCompile(resourceIDPatternText)
|
||||
match := resourceIDPattern.FindStringSubmatch(resourceID)
|
||||
|
||||
if len(match) == 0 {
|
||||
return Resource{}, fmt.Errorf("parsing failed for %s. Invalid resource Id format", resourceID)
|
||||
}
|
||||
|
||||
v := strings.Split(match[5], "/")
|
||||
resourceName := v[len(v)-1]
|
||||
|
||||
result := Resource{
|
||||
SubscriptionID: match[1],
|
||||
ResourceGroup: match[2],
|
||||
Provider: match[3],
|
||||
ResourceType: match[4],
|
||||
ResourceName: resourceName,
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// NewErrorWithError creates a new Error conforming object from the
|
||||
// passed packageType, method, statusCode of the given resp (UndefinedStatusCode
|
||||
// if resp is nil), message, and original error. message is treated as a format
|
||||
// string to which the optional args apply.
|
||||
func NewErrorWithError(original error, packageType string, method string, resp *http.Response, message string, args ...interface{}) RequestError {
|
||||
if v, ok := original.(*RequestError); ok {
|
||||
return *v
|
||||
}
|
||||
|
||||
statusCode := autorest.UndefinedStatusCode
|
||||
if resp != nil {
|
||||
statusCode = resp.StatusCode
|
||||
}
|
||||
return RequestError{
|
||||
DetailedError: autorest.DetailedError{
|
||||
Original: original,
|
||||
PackageType: packageType,
|
||||
Method: method,
|
||||
StatusCode: statusCode,
|
||||
Message: fmt.Sprintf(message, args...),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// WithReturningClientID returns a PrepareDecorator that adds an HTTP extension header of
|
||||
// x-ms-client-request-id whose value is the passed, undecorated UUID (e.g.,
|
||||
// "0F39878C-5F76-4DB8-A25D-61D2C193C3CA"). It also sets the x-ms-return-client-request-id
|
||||
// header to true such that UUID accompanies the http.Response.
|
||||
func WithReturningClientID(uuid string) autorest.PrepareDecorator {
|
||||
preparer := autorest.CreatePreparer(
|
||||
WithClientID(uuid),
|
||||
WithReturnClientID(true))
|
||||
|
||||
return func(p autorest.Preparer) autorest.Preparer {
|
||||
return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
r, err := p.Prepare(r)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
return preparer.Prepare(r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// WithClientID returns a PrepareDecorator that adds an HTTP extension header of
|
||||
// x-ms-client-request-id whose value is passed, undecorated UUID (e.g.,
|
||||
// "0F39878C-5F76-4DB8-A25D-61D2C193C3CA").
|
||||
func WithClientID(uuid string) autorest.PrepareDecorator {
|
||||
return autorest.WithHeader(HeaderClientID, uuid)
|
||||
}
|
||||
|
||||
// WithReturnClientID returns a PrepareDecorator that adds an HTTP extension header of
|
||||
// x-ms-return-client-request-id whose boolean value indicates if the value of the
|
||||
// x-ms-client-request-id header should be included in the http.Response.
|
||||
func WithReturnClientID(b bool) autorest.PrepareDecorator {
|
||||
return autorest.WithHeader(HeaderReturnClientID, strconv.FormatBool(b))
|
||||
}
|
||||
|
||||
// ExtractClientID extracts the client identifier from the x-ms-client-request-id header set on the
|
||||
// http.Request sent to the service (and returned in the http.Response)
|
||||
func ExtractClientID(resp *http.Response) string {
|
||||
return autorest.ExtractHeaderValue(HeaderClientID, resp)
|
||||
}
|
||||
|
||||
// ExtractRequestID extracts the Azure server generated request identifier from the
|
||||
// x-ms-request-id header.
|
||||
func ExtractRequestID(resp *http.Response) string {
|
||||
return autorest.ExtractHeaderValue(HeaderRequestID, resp)
|
||||
}
|
||||
|
||||
// WithErrorUnlessStatusCode returns a RespondDecorator that emits an
|
||||
// azure.RequestError by reading the response body unless the response HTTP status code
|
||||
// is among the set passed.
|
||||
//
|
||||
// If there is a chance service may return responses other than the Azure error
|
||||
// format and the response cannot be parsed into an error, a decoding error will
|
||||
// be returned containing the response body. In any case, the Responder will
|
||||
// return an error if the status code is not satisfied.
|
||||
//
|
||||
// If this Responder returns an error, the response body will be replaced with
|
||||
// an in-memory reader, which needs no further closing.
|
||||
func WithErrorUnlessStatusCode(codes ...int) autorest.RespondDecorator {
|
||||
return func(r autorest.Responder) autorest.Responder {
|
||||
return autorest.ResponderFunc(func(resp *http.Response) error {
|
||||
err := r.Respond(resp)
|
||||
if err == nil && !autorest.ResponseHasStatusCode(resp, codes...) {
|
||||
var e RequestError
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Copy and replace the Body in case it does not contain an error object.
|
||||
// This will leave the Body available to the caller.
|
||||
b, decodeErr := autorest.CopyAndDecode(autorest.EncodedAsJSON, resp.Body, &e)
|
||||
resp.Body = ioutil.NopCloser(&b)
|
||||
if decodeErr != nil {
|
||||
return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b.String(), decodeErr)
|
||||
} else if e.ServiceError == nil {
|
||||
// Check if error is unwrapped ServiceError
|
||||
if err := json.Unmarshal(b.Bytes(), &e.ServiceError); err != nil || e.ServiceError.Message == "" {
|
||||
e.ServiceError = &ServiceError{
|
||||
Code: "Unknown",
|
||||
Message: "Unknown service error",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
e.RequestID = ExtractRequestID(resp)
|
||||
if e.StatusCode == nil {
|
||||
e.StatusCode = resp.StatusCode
|
||||
}
|
||||
err = &e
|
||||
}
|
||||
return err
|
||||
})
|
||||
}
|
||||
}
|
||||
191
vendor/github.com/Azure/go-autorest/autorest/azure/environments.go
generated
vendored
Normal file
191
vendor/github.com/Azure/go-autorest/autorest/azure/environments.go
generated
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
package azure
|
||||
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// EnvironmentFilepathName captures the name of the environment variable containing the path to the file
|
||||
// to be used while populating the Azure Environment.
|
||||
const EnvironmentFilepathName = "AZURE_ENVIRONMENT_FILEPATH"
|
||||
|
||||
var environments = map[string]Environment{
|
||||
"AZURECHINACLOUD": ChinaCloud,
|
||||
"AZUREGERMANCLOUD": GermanCloud,
|
||||
"AZUREPUBLICCLOUD": PublicCloud,
|
||||
"AZUREUSGOVERNMENTCLOUD": USGovernmentCloud,
|
||||
}
|
||||
|
||||
// Environment represents a set of endpoints for each of Azure's Clouds.
|
||||
type Environment struct {
|
||||
Name string `json:"name"`
|
||||
ManagementPortalURL string `json:"managementPortalURL"`
|
||||
PublishSettingsURL string `json:"publishSettingsURL"`
|
||||
ServiceManagementEndpoint string `json:"serviceManagementEndpoint"`
|
||||
ResourceManagerEndpoint string `json:"resourceManagerEndpoint"`
|
||||
ActiveDirectoryEndpoint string `json:"activeDirectoryEndpoint"`
|
||||
GalleryEndpoint string `json:"galleryEndpoint"`
|
||||
KeyVaultEndpoint string `json:"keyVaultEndpoint"`
|
||||
GraphEndpoint string `json:"graphEndpoint"`
|
||||
ServiceBusEndpoint string `json:"serviceBusEndpoint"`
|
||||
BatchManagementEndpoint string `json:"batchManagementEndpoint"`
|
||||
StorageEndpointSuffix string `json:"storageEndpointSuffix"`
|
||||
SQLDatabaseDNSSuffix string `json:"sqlDatabaseDNSSuffix"`
|
||||
TrafficManagerDNSSuffix string `json:"trafficManagerDNSSuffix"`
|
||||
KeyVaultDNSSuffix string `json:"keyVaultDNSSuffix"`
|
||||
ServiceBusEndpointSuffix string `json:"serviceBusEndpointSuffix"`
|
||||
ServiceManagementVMDNSSuffix string `json:"serviceManagementVMDNSSuffix"`
|
||||
ResourceManagerVMDNSSuffix string `json:"resourceManagerVMDNSSuffix"`
|
||||
ContainerRegistryDNSSuffix string `json:"containerRegistryDNSSuffix"`
|
||||
TokenAudience string `json:"tokenAudience"`
|
||||
}
|
||||
|
||||
var (
|
||||
// PublicCloud is the default public Azure cloud environment
|
||||
PublicCloud = Environment{
|
||||
Name: "AzurePublicCloud",
|
||||
ManagementPortalURL: "https://manage.windowsazure.com/",
|
||||
PublishSettingsURL: "https://manage.windowsazure.com/publishsettings/index",
|
||||
ServiceManagementEndpoint: "https://management.core.windows.net/",
|
||||
ResourceManagerEndpoint: "https://management.azure.com/",
|
||||
ActiveDirectoryEndpoint: "https://login.microsoftonline.com/",
|
||||
GalleryEndpoint: "https://gallery.azure.com/",
|
||||
KeyVaultEndpoint: "https://vault.azure.net/",
|
||||
GraphEndpoint: "https://graph.windows.net/",
|
||||
ServiceBusEndpoint: "https://servicebus.windows.net/",
|
||||
BatchManagementEndpoint: "https://batch.core.windows.net/",
|
||||
StorageEndpointSuffix: "core.windows.net",
|
||||
SQLDatabaseDNSSuffix: "database.windows.net",
|
||||
TrafficManagerDNSSuffix: "trafficmanager.net",
|
||||
KeyVaultDNSSuffix: "vault.azure.net",
|
||||
ServiceBusEndpointSuffix: "servicebus.windows.net",
|
||||
ServiceManagementVMDNSSuffix: "cloudapp.net",
|
||||
ResourceManagerVMDNSSuffix: "cloudapp.azure.com",
|
||||
ContainerRegistryDNSSuffix: "azurecr.io",
|
||||
TokenAudience: "https://management.azure.com/",
|
||||
}
|
||||
|
||||
// USGovernmentCloud is the cloud environment for the US Government
|
||||
USGovernmentCloud = Environment{
|
||||
Name: "AzureUSGovernmentCloud",
|
||||
ManagementPortalURL: "https://manage.windowsazure.us/",
|
||||
PublishSettingsURL: "https://manage.windowsazure.us/publishsettings/index",
|
||||
ServiceManagementEndpoint: "https://management.core.usgovcloudapi.net/",
|
||||
ResourceManagerEndpoint: "https://management.usgovcloudapi.net/",
|
||||
ActiveDirectoryEndpoint: "https://login.microsoftonline.us/",
|
||||
GalleryEndpoint: "https://gallery.usgovcloudapi.net/",
|
||||
KeyVaultEndpoint: "https://vault.usgovcloudapi.net/",
|
||||
GraphEndpoint: "https://graph.windows.net/",
|
||||
ServiceBusEndpoint: "https://servicebus.usgovcloudapi.net/",
|
||||
BatchManagementEndpoint: "https://batch.core.usgovcloudapi.net/",
|
||||
StorageEndpointSuffix: "core.usgovcloudapi.net",
|
||||
SQLDatabaseDNSSuffix: "database.usgovcloudapi.net",
|
||||
TrafficManagerDNSSuffix: "usgovtrafficmanager.net",
|
||||
KeyVaultDNSSuffix: "vault.usgovcloudapi.net",
|
||||
ServiceBusEndpointSuffix: "servicebus.usgovcloudapi.net",
|
||||
ServiceManagementVMDNSSuffix: "usgovcloudapp.net",
|
||||
ResourceManagerVMDNSSuffix: "cloudapp.windowsazure.us",
|
||||
ContainerRegistryDNSSuffix: "azurecr.io",
|
||||
TokenAudience: "https://management.usgovcloudapi.net/",
|
||||
}
|
||||
|
||||
// ChinaCloud is the cloud environment operated in China
|
||||
ChinaCloud = Environment{
|
||||
Name: "AzureChinaCloud",
|
||||
ManagementPortalURL: "https://manage.chinacloudapi.com/",
|
||||
PublishSettingsURL: "https://manage.chinacloudapi.com/publishsettings/index",
|
||||
ServiceManagementEndpoint: "https://management.core.chinacloudapi.cn/",
|
||||
ResourceManagerEndpoint: "https://management.chinacloudapi.cn/",
|
||||
ActiveDirectoryEndpoint: "https://login.chinacloudapi.cn/",
|
||||
GalleryEndpoint: "https://gallery.chinacloudapi.cn/",
|
||||
KeyVaultEndpoint: "https://vault.azure.cn/",
|
||||
GraphEndpoint: "https://graph.chinacloudapi.cn/",
|
||||
ServiceBusEndpoint: "https://servicebus.chinacloudapi.cn/",
|
||||
BatchManagementEndpoint: "https://batch.chinacloudapi.cn/",
|
||||
StorageEndpointSuffix: "core.chinacloudapi.cn",
|
||||
SQLDatabaseDNSSuffix: "database.chinacloudapi.cn",
|
||||
TrafficManagerDNSSuffix: "trafficmanager.cn",
|
||||
KeyVaultDNSSuffix: "vault.azure.cn",
|
||||
ServiceBusEndpointSuffix: "servicebus.chinacloudapi.cn",
|
||||
ServiceManagementVMDNSSuffix: "chinacloudapp.cn",
|
||||
ResourceManagerVMDNSSuffix: "cloudapp.azure.cn",
|
||||
ContainerRegistryDNSSuffix: "azurecr.io",
|
||||
TokenAudience: "https://management.chinacloudapi.cn/",
|
||||
}
|
||||
|
||||
// GermanCloud is the cloud environment operated in Germany
|
||||
GermanCloud = Environment{
|
||||
Name: "AzureGermanCloud",
|
||||
ManagementPortalURL: "http://portal.microsoftazure.de/",
|
||||
PublishSettingsURL: "https://manage.microsoftazure.de/publishsettings/index",
|
||||
ServiceManagementEndpoint: "https://management.core.cloudapi.de/",
|
||||
ResourceManagerEndpoint: "https://management.microsoftazure.de/",
|
||||
ActiveDirectoryEndpoint: "https://login.microsoftonline.de/",
|
||||
GalleryEndpoint: "https://gallery.cloudapi.de/",
|
||||
KeyVaultEndpoint: "https://vault.microsoftazure.de/",
|
||||
GraphEndpoint: "https://graph.cloudapi.de/",
|
||||
ServiceBusEndpoint: "https://servicebus.cloudapi.de/",
|
||||
BatchManagementEndpoint: "https://batch.cloudapi.de/",
|
||||
StorageEndpointSuffix: "core.cloudapi.de",
|
||||
SQLDatabaseDNSSuffix: "database.cloudapi.de",
|
||||
TrafficManagerDNSSuffix: "azuretrafficmanager.de",
|
||||
KeyVaultDNSSuffix: "vault.microsoftazure.de",
|
||||
ServiceBusEndpointSuffix: "servicebus.cloudapi.de",
|
||||
ServiceManagementVMDNSSuffix: "azurecloudapp.de",
|
||||
ResourceManagerVMDNSSuffix: "cloudapp.microsoftazure.de",
|
||||
ContainerRegistryDNSSuffix: "azurecr.io",
|
||||
TokenAudience: "https://management.microsoftazure.de/",
|
||||
}
|
||||
)
|
||||
|
||||
// EnvironmentFromName returns an Environment based on the common name specified.
|
||||
func EnvironmentFromName(name string) (Environment, error) {
|
||||
// IMPORTANT
|
||||
// As per @radhikagupta5:
|
||||
// This is technical debt, fundamentally here because Kubernetes is not currently accepting
|
||||
// contributions to the providers. Once that is an option, the provider should be updated to
|
||||
// directly call `EnvironmentFromFile`. Until then, we rely on dispatching Azure Stack environment creation
|
||||
// from this method based on the name that is provided to us.
|
||||
if strings.EqualFold(name, "AZURESTACKCLOUD") {
|
||||
return EnvironmentFromFile(os.Getenv(EnvironmentFilepathName))
|
||||
}
|
||||
|
||||
name = strings.ToUpper(name)
|
||||
env, ok := environments[name]
|
||||
if !ok {
|
||||
return env, fmt.Errorf("autorest/azure: There is no cloud environment matching the name %q", name)
|
||||
}
|
||||
|
||||
return env, nil
|
||||
}
|
||||
|
||||
// EnvironmentFromFile loads an Environment from a configuration file available on disk.
|
||||
// This function is particularly useful in the Hybrid Cloud model, where one must define their own
|
||||
// endpoints.
|
||||
func EnvironmentFromFile(location string) (unmarshaled Environment, err error) {
|
||||
fileContents, err := ioutil.ReadFile(location)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal(fileContents, &unmarshaled)
|
||||
|
||||
return
|
||||
}
|
||||
245
vendor/github.com/Azure/go-autorest/autorest/azure/metadata_environment.go
generated
vendored
Normal file
245
vendor/github.com/Azure/go-autorest/autorest/azure/metadata_environment.go
generated
vendored
Normal file
@@ -0,0 +1,245 @@
|
||||
package azure
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
)
|
||||
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
type audience []string
|
||||
|
||||
type authentication struct {
|
||||
LoginEndpoint string `json:"loginEndpoint"`
|
||||
Audiences audience `json:"audiences"`
|
||||
}
|
||||
|
||||
type environmentMetadataInfo struct {
|
||||
GalleryEndpoint string `json:"galleryEndpoint"`
|
||||
GraphEndpoint string `json:"graphEndpoint"`
|
||||
PortalEndpoint string `json:"portalEndpoint"`
|
||||
Authentication authentication `json:"authentication"`
|
||||
}
|
||||
|
||||
// EnvironmentProperty represent property names that clients can override
|
||||
type EnvironmentProperty string
|
||||
|
||||
const (
|
||||
// EnvironmentName ...
|
||||
EnvironmentName EnvironmentProperty = "name"
|
||||
// EnvironmentManagementPortalURL ..
|
||||
EnvironmentManagementPortalURL EnvironmentProperty = "managementPortalURL"
|
||||
// EnvironmentPublishSettingsURL ...
|
||||
EnvironmentPublishSettingsURL EnvironmentProperty = "publishSettingsURL"
|
||||
// EnvironmentServiceManagementEndpoint ...
|
||||
EnvironmentServiceManagementEndpoint EnvironmentProperty = "serviceManagementEndpoint"
|
||||
// EnvironmentResourceManagerEndpoint ...
|
||||
EnvironmentResourceManagerEndpoint EnvironmentProperty = "resourceManagerEndpoint"
|
||||
// EnvironmentActiveDirectoryEndpoint ...
|
||||
EnvironmentActiveDirectoryEndpoint EnvironmentProperty = "activeDirectoryEndpoint"
|
||||
// EnvironmentGalleryEndpoint ...
|
||||
EnvironmentGalleryEndpoint EnvironmentProperty = "galleryEndpoint"
|
||||
// EnvironmentKeyVaultEndpoint ...
|
||||
EnvironmentKeyVaultEndpoint EnvironmentProperty = "keyVaultEndpoint"
|
||||
// EnvironmentGraphEndpoint ...
|
||||
EnvironmentGraphEndpoint EnvironmentProperty = "graphEndpoint"
|
||||
// EnvironmentServiceBusEndpoint ...
|
||||
EnvironmentServiceBusEndpoint EnvironmentProperty = "serviceBusEndpoint"
|
||||
// EnvironmentBatchManagementEndpoint ...
|
||||
EnvironmentBatchManagementEndpoint EnvironmentProperty = "batchManagementEndpoint"
|
||||
// EnvironmentStorageEndpointSuffix ...
|
||||
EnvironmentStorageEndpointSuffix EnvironmentProperty = "storageEndpointSuffix"
|
||||
// EnvironmentSQLDatabaseDNSSuffix ...
|
||||
EnvironmentSQLDatabaseDNSSuffix EnvironmentProperty = "sqlDatabaseDNSSuffix"
|
||||
// EnvironmentTrafficManagerDNSSuffix ...
|
||||
EnvironmentTrafficManagerDNSSuffix EnvironmentProperty = "trafficManagerDNSSuffix"
|
||||
// EnvironmentKeyVaultDNSSuffix ...
|
||||
EnvironmentKeyVaultDNSSuffix EnvironmentProperty = "keyVaultDNSSuffix"
|
||||
// EnvironmentServiceBusEndpointSuffix ...
|
||||
EnvironmentServiceBusEndpointSuffix EnvironmentProperty = "serviceBusEndpointSuffix"
|
||||
// EnvironmentServiceManagementVMDNSSuffix ...
|
||||
EnvironmentServiceManagementVMDNSSuffix EnvironmentProperty = "serviceManagementVMDNSSuffix"
|
||||
// EnvironmentResourceManagerVMDNSSuffix ...
|
||||
EnvironmentResourceManagerVMDNSSuffix EnvironmentProperty = "resourceManagerVMDNSSuffix"
|
||||
// EnvironmentContainerRegistryDNSSuffix ...
|
||||
EnvironmentContainerRegistryDNSSuffix EnvironmentProperty = "containerRegistryDNSSuffix"
|
||||
// EnvironmentTokenAudience ...
|
||||
EnvironmentTokenAudience EnvironmentProperty = "tokenAudience"
|
||||
)
|
||||
|
||||
// OverrideProperty represents property name and value that clients can override
|
||||
type OverrideProperty struct {
|
||||
Key EnvironmentProperty
|
||||
Value string
|
||||
}
|
||||
|
||||
// EnvironmentFromURL loads an Environment from a URL
|
||||
// This function is particularly useful in the Hybrid Cloud model, where one may define their own
|
||||
// endpoints.
|
||||
func EnvironmentFromURL(resourceManagerEndpoint string, properties ...OverrideProperty) (environment Environment, err error) {
|
||||
var metadataEnvProperties environmentMetadataInfo
|
||||
|
||||
if resourceManagerEndpoint == "" {
|
||||
return environment, fmt.Errorf("Metadata resource manager endpoint is empty")
|
||||
}
|
||||
|
||||
if metadataEnvProperties, err = retrieveMetadataEnvironment(resourceManagerEndpoint); err != nil {
|
||||
return environment, err
|
||||
}
|
||||
|
||||
// Give priority to user's override values
|
||||
overrideProperties(&environment, properties)
|
||||
|
||||
if environment.Name == "" {
|
||||
environment.Name = "HybridEnvironment"
|
||||
}
|
||||
stampDNSSuffix := environment.StorageEndpointSuffix
|
||||
if stampDNSSuffix == "" {
|
||||
stampDNSSuffix = strings.TrimSuffix(strings.TrimPrefix(strings.Replace(resourceManagerEndpoint, strings.Split(resourceManagerEndpoint, ".")[0], "", 1), "."), "/")
|
||||
environment.StorageEndpointSuffix = stampDNSSuffix
|
||||
}
|
||||
if environment.KeyVaultDNSSuffix == "" {
|
||||
environment.KeyVaultDNSSuffix = fmt.Sprintf("%s.%s", "vault", stampDNSSuffix)
|
||||
}
|
||||
if environment.KeyVaultEndpoint == "" {
|
||||
environment.KeyVaultEndpoint = fmt.Sprintf("%s%s", "https://", environment.KeyVaultDNSSuffix)
|
||||
}
|
||||
if environment.TokenAudience == "" {
|
||||
environment.TokenAudience = metadataEnvProperties.Authentication.Audiences[0]
|
||||
}
|
||||
if environment.ActiveDirectoryEndpoint == "" {
|
||||
environment.ActiveDirectoryEndpoint = metadataEnvProperties.Authentication.LoginEndpoint
|
||||
}
|
||||
if environment.ResourceManagerEndpoint == "" {
|
||||
environment.ResourceManagerEndpoint = resourceManagerEndpoint
|
||||
}
|
||||
if environment.GalleryEndpoint == "" {
|
||||
environment.GalleryEndpoint = metadataEnvProperties.GalleryEndpoint
|
||||
}
|
||||
if environment.GraphEndpoint == "" {
|
||||
environment.GraphEndpoint = metadataEnvProperties.GraphEndpoint
|
||||
}
|
||||
|
||||
return environment, nil
|
||||
}
|
||||
|
||||
func overrideProperties(environment *Environment, properties []OverrideProperty) {
|
||||
for _, property := range properties {
|
||||
switch property.Key {
|
||||
case EnvironmentName:
|
||||
{
|
||||
environment.Name = property.Value
|
||||
}
|
||||
case EnvironmentManagementPortalURL:
|
||||
{
|
||||
environment.ManagementPortalURL = property.Value
|
||||
}
|
||||
case EnvironmentPublishSettingsURL:
|
||||
{
|
||||
environment.PublishSettingsURL = property.Value
|
||||
}
|
||||
case EnvironmentServiceManagementEndpoint:
|
||||
{
|
||||
environment.ServiceManagementEndpoint = property.Value
|
||||
}
|
||||
case EnvironmentResourceManagerEndpoint:
|
||||
{
|
||||
environment.ResourceManagerEndpoint = property.Value
|
||||
}
|
||||
case EnvironmentActiveDirectoryEndpoint:
|
||||
{
|
||||
environment.ActiveDirectoryEndpoint = property.Value
|
||||
}
|
||||
case EnvironmentGalleryEndpoint:
|
||||
{
|
||||
environment.GalleryEndpoint = property.Value
|
||||
}
|
||||
case EnvironmentKeyVaultEndpoint:
|
||||
{
|
||||
environment.KeyVaultEndpoint = property.Value
|
||||
}
|
||||
case EnvironmentGraphEndpoint:
|
||||
{
|
||||
environment.GraphEndpoint = property.Value
|
||||
}
|
||||
case EnvironmentServiceBusEndpoint:
|
||||
{
|
||||
environment.ServiceBusEndpoint = property.Value
|
||||
}
|
||||
case EnvironmentBatchManagementEndpoint:
|
||||
{
|
||||
environment.BatchManagementEndpoint = property.Value
|
||||
}
|
||||
case EnvironmentStorageEndpointSuffix:
|
||||
{
|
||||
environment.StorageEndpointSuffix = property.Value
|
||||
}
|
||||
case EnvironmentSQLDatabaseDNSSuffix:
|
||||
{
|
||||
environment.SQLDatabaseDNSSuffix = property.Value
|
||||
}
|
||||
case EnvironmentTrafficManagerDNSSuffix:
|
||||
{
|
||||
environment.TrafficManagerDNSSuffix = property.Value
|
||||
}
|
||||
case EnvironmentKeyVaultDNSSuffix:
|
||||
{
|
||||
environment.KeyVaultDNSSuffix = property.Value
|
||||
}
|
||||
case EnvironmentServiceBusEndpointSuffix:
|
||||
{
|
||||
environment.ServiceBusEndpointSuffix = property.Value
|
||||
}
|
||||
case EnvironmentServiceManagementVMDNSSuffix:
|
||||
{
|
||||
environment.ServiceManagementVMDNSSuffix = property.Value
|
||||
}
|
||||
case EnvironmentResourceManagerVMDNSSuffix:
|
||||
{
|
||||
environment.ResourceManagerVMDNSSuffix = property.Value
|
||||
}
|
||||
case EnvironmentContainerRegistryDNSSuffix:
|
||||
{
|
||||
environment.ContainerRegistryDNSSuffix = property.Value
|
||||
}
|
||||
case EnvironmentTokenAudience:
|
||||
{
|
||||
environment.TokenAudience = property.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func retrieveMetadataEnvironment(endpoint string) (environment environmentMetadataInfo, err error) {
|
||||
client := autorest.NewClientWithUserAgent("")
|
||||
managementEndpoint := fmt.Sprintf("%s%s", strings.TrimSuffix(endpoint, "/"), "/metadata/endpoints?api-version=1.0")
|
||||
req, _ := http.NewRequest("GET", managementEndpoint, nil)
|
||||
response, err := client.Do(req)
|
||||
if err != nil {
|
||||
return environment, err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
jsonResponse, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return environment, err
|
||||
}
|
||||
err = json.Unmarshal(jsonResponse, &environment)
|
||||
return environment, err
|
||||
}
|
||||
200
vendor/github.com/Azure/go-autorest/autorest/azure/rp.go
generated
vendored
Normal file
200
vendor/github.com/Azure/go-autorest/autorest/azure/rp.go
generated
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package azure
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
)
|
||||
|
||||
// DoRetryWithRegistration tries to register the resource provider in case it is unregistered.
|
||||
// It also handles request retries
|
||||
func DoRetryWithRegistration(client autorest.Client) autorest.SendDecorator {
|
||||
return func(s autorest.Sender) autorest.Sender {
|
||||
return autorest.SenderFunc(func(r *http.Request) (resp *http.Response, err error) {
|
||||
rr := autorest.NewRetriableRequest(r)
|
||||
for currentAttempt := 0; currentAttempt < client.RetryAttempts; currentAttempt++ {
|
||||
err = rr.Prepare()
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
resp, err = autorest.SendWithSender(s, rr.Request(),
|
||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...),
|
||||
)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusConflict || client.SkipResourceProviderRegistration {
|
||||
return resp, err
|
||||
}
|
||||
var re RequestError
|
||||
err = autorest.Respond(
|
||||
resp,
|
||||
autorest.ByUnmarshallingJSON(&re),
|
||||
)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
err = re
|
||||
|
||||
if re.ServiceError != nil && re.ServiceError.Code == "MissingSubscriptionRegistration" {
|
||||
regErr := register(client, r, re)
|
||||
if regErr != nil {
|
||||
return resp, fmt.Errorf("failed auto registering Resource Provider: %s. Original error: %s", regErr, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return resp, fmt.Errorf("failed request: %s", err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func getProvider(re RequestError) (string, error) {
|
||||
if re.ServiceError != nil && len(re.ServiceError.Details) > 0 {
|
||||
return re.ServiceError.Details[0]["target"].(string), nil
|
||||
}
|
||||
return "", errors.New("provider was not found in the response")
|
||||
}
|
||||
|
||||
func register(client autorest.Client, originalReq *http.Request, re RequestError) error {
|
||||
subID := getSubscription(originalReq.URL.Path)
|
||||
if subID == "" {
|
||||
return errors.New("missing parameter subscriptionID to register resource provider")
|
||||
}
|
||||
providerName, err := getProvider(re)
|
||||
if err != nil {
|
||||
return fmt.Errorf("missing parameter provider to register resource provider: %s", err)
|
||||
}
|
||||
newURL := url.URL{
|
||||
Scheme: originalReq.URL.Scheme,
|
||||
Host: originalReq.URL.Host,
|
||||
}
|
||||
|
||||
// taken from the resources SDK
|
||||
// with almost identical code, this sections are easier to mantain
|
||||
// It is also not a good idea to import the SDK here
|
||||
// https://github.com/Azure/azure-sdk-for-go/blob/9f366792afa3e0ddaecdc860e793ba9d75e76c27/arm/resources/resources/providers.go#L252
|
||||
pathParameters := map[string]interface{}{
|
||||
"resourceProviderNamespace": autorest.Encode("path", providerName),
|
||||
"subscriptionId": autorest.Encode("path", subID),
|
||||
}
|
||||
|
||||
const APIVersion = "2016-09-01"
|
||||
queryParameters := map[string]interface{}{
|
||||
"api-version": APIVersion,
|
||||
}
|
||||
|
||||
preparer := autorest.CreatePreparer(
|
||||
autorest.AsPost(),
|
||||
autorest.WithBaseURL(newURL.String()),
|
||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/{resourceProviderNamespace}/register", pathParameters),
|
||||
autorest.WithQueryParameters(queryParameters),
|
||||
)
|
||||
|
||||
req, err := preparer.Prepare(&http.Request{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req = req.WithContext(originalReq.Context())
|
||||
|
||||
resp, err := autorest.SendWithSender(client, req,
|
||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
type Provider struct {
|
||||
RegistrationState *string `json:"registrationState,omitempty"`
|
||||
}
|
||||
var provider Provider
|
||||
|
||||
err = autorest.Respond(
|
||||
resp,
|
||||
WithErrorUnlessStatusCode(http.StatusOK),
|
||||
autorest.ByUnmarshallingJSON(&provider),
|
||||
autorest.ByClosing(),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// poll for registered provisioning state
|
||||
now := time.Now()
|
||||
for err == nil && time.Since(now) < client.PollingDuration {
|
||||
// taken from the resources SDK
|
||||
// https://github.com/Azure/azure-sdk-for-go/blob/9f366792afa3e0ddaecdc860e793ba9d75e76c27/arm/resources/resources/providers.go#L45
|
||||
preparer := autorest.CreatePreparer(
|
||||
autorest.AsGet(),
|
||||
autorest.WithBaseURL(newURL.String()),
|
||||
autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/{resourceProviderNamespace}", pathParameters),
|
||||
autorest.WithQueryParameters(queryParameters),
|
||||
)
|
||||
req, err = preparer.Prepare(&http.Request{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req = req.WithContext(originalReq.Context())
|
||||
|
||||
resp, err := autorest.SendWithSender(client, req,
|
||||
autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = autorest.Respond(
|
||||
resp,
|
||||
WithErrorUnlessStatusCode(http.StatusOK),
|
||||
autorest.ByUnmarshallingJSON(&provider),
|
||||
autorest.ByClosing(),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if provider.RegistrationState != nil &&
|
||||
*provider.RegistrationState == "Registered" {
|
||||
break
|
||||
}
|
||||
|
||||
delayed := autorest.DelayWithRetryAfter(resp, originalReq.Context().Done())
|
||||
if !delayed && !autorest.DelayForBackoff(client.PollingDelay, 0, originalReq.Context().Done()) {
|
||||
return originalReq.Context().Err()
|
||||
}
|
||||
}
|
||||
if !(time.Since(now) < client.PollingDuration) {
|
||||
return errors.New("polling for resource provider registration has exceeded the polling duration")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func getSubscription(path string) string {
|
||||
parts := strings.Split(path, "/")
|
||||
for i, v := range parts {
|
||||
if v == "subscriptions" && (i+1) < len(parts) {
|
||||
return parts[i+1]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
264
vendor/github.com/Azure/go-autorest/autorest/client.go
generated
vendored
Normal file
264
vendor/github.com/Azure/go-autorest/autorest/client.go
generated
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
package autorest
|
||||
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultPollingDelay is a reasonable delay between polling requests.
|
||||
DefaultPollingDelay = 60 * time.Second
|
||||
|
||||
// DefaultPollingDuration is a reasonable total polling duration.
|
||||
DefaultPollingDuration = 15 * time.Minute
|
||||
|
||||
// DefaultRetryAttempts is number of attempts for retry status codes (5xx).
|
||||
DefaultRetryAttempts = 3
|
||||
|
||||
// DefaultRetryDuration is the duration to wait between retries.
|
||||
DefaultRetryDuration = 30 * time.Second
|
||||
)
|
||||
|
||||
var (
|
||||
// defaultUserAgent builds a string containing the Go version, system archityecture and OS,
|
||||
// and the go-autorest version.
|
||||
defaultUserAgent = fmt.Sprintf("Go/%s (%s-%s) go-autorest/%s",
|
||||
runtime.Version(),
|
||||
runtime.GOARCH,
|
||||
runtime.GOOS,
|
||||
Version(),
|
||||
)
|
||||
|
||||
// StatusCodesForRetry are a defined group of status code for which the client will retry
|
||||
StatusCodesForRetry = []int{
|
||||
http.StatusRequestTimeout, // 408
|
||||
http.StatusTooManyRequests, // 429
|
||||
http.StatusInternalServerError, // 500
|
||||
http.StatusBadGateway, // 502
|
||||
http.StatusServiceUnavailable, // 503
|
||||
http.StatusGatewayTimeout, // 504
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
requestFormat = `HTTP Request Begin ===================================================
|
||||
%s
|
||||
===================================================== HTTP Request End
|
||||
`
|
||||
responseFormat = `HTTP Response Begin ===================================================
|
||||
%s
|
||||
===================================================== HTTP Response End
|
||||
`
|
||||
)
|
||||
|
||||
// Response serves as the base for all responses from generated clients. It provides access to the
|
||||
// last http.Response.
|
||||
type Response struct {
|
||||
*http.Response `json:"-"`
|
||||
}
|
||||
|
||||
// LoggingInspector implements request and response inspectors that log the full request and
|
||||
// response to a supplied log.
|
||||
type LoggingInspector struct {
|
||||
Logger *log.Logger
|
||||
}
|
||||
|
||||
// WithInspection returns a PrepareDecorator that emits the http.Request to the supplied logger. The
|
||||
// body is restored after being emitted.
|
||||
//
|
||||
// Note: Since it reads the entire Body, this decorator should not be used where body streaming is
|
||||
// important. It is best used to trace JSON or similar body values.
|
||||
func (li LoggingInspector) WithInspection() PrepareDecorator {
|
||||
return func(p Preparer) Preparer {
|
||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
var body, b bytes.Buffer
|
||||
|
||||
defer r.Body.Close()
|
||||
|
||||
r.Body = ioutil.NopCloser(io.TeeReader(r.Body, &body))
|
||||
if err := r.Write(&b); err != nil {
|
||||
return nil, fmt.Errorf("Failed to write response: %v", err)
|
||||
}
|
||||
|
||||
li.Logger.Printf(requestFormat, b.String())
|
||||
|
||||
r.Body = ioutil.NopCloser(&body)
|
||||
return p.Prepare(r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ByInspecting returns a RespondDecorator that emits the http.Response to the supplied logger. The
|
||||
// body is restored after being emitted.
|
||||
//
|
||||
// Note: Since it reads the entire Body, this decorator should not be used where body streaming is
|
||||
// important. It is best used to trace JSON or similar body values.
|
||||
func (li LoggingInspector) ByInspecting() RespondDecorator {
|
||||
return func(r Responder) Responder {
|
||||
return ResponderFunc(func(resp *http.Response) error {
|
||||
var body, b bytes.Buffer
|
||||
defer resp.Body.Close()
|
||||
resp.Body = ioutil.NopCloser(io.TeeReader(resp.Body, &body))
|
||||
if err := resp.Write(&b); err != nil {
|
||||
return fmt.Errorf("Failed to write response: %v", err)
|
||||
}
|
||||
|
||||
li.Logger.Printf(responseFormat, b.String())
|
||||
|
||||
resp.Body = ioutil.NopCloser(&body)
|
||||
return r.Respond(resp)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Client is the base for autorest generated clients. It provides default, "do nothing"
|
||||
// implementations of an Authorizer, RequestInspector, and ResponseInspector. It also returns the
|
||||
// standard, undecorated http.Client as a default Sender.
|
||||
//
|
||||
// Generated clients should also use Error (see NewError and NewErrorWithError) for errors and
|
||||
// return responses that compose with Response.
|
||||
//
|
||||
// Most customization of generated clients is best achieved by supplying a custom Authorizer, custom
|
||||
// RequestInspector, and / or custom ResponseInspector. Users may log requests, implement circuit
|
||||
// breakers (see https://msdn.microsoft.com/en-us/library/dn589784.aspx) or otherwise influence
|
||||
// sending the request by providing a decorated Sender.
|
||||
type Client struct {
|
||||
Authorizer Authorizer
|
||||
Sender Sender
|
||||
RequestInspector PrepareDecorator
|
||||
ResponseInspector RespondDecorator
|
||||
|
||||
// PollingDelay sets the polling frequency used in absence of a Retry-After HTTP header
|
||||
PollingDelay time.Duration
|
||||
|
||||
// PollingDuration sets the maximum polling time after which an error is returned.
|
||||
PollingDuration time.Duration
|
||||
|
||||
// RetryAttempts sets the default number of retry attempts for client.
|
||||
RetryAttempts int
|
||||
|
||||
// RetryDuration sets the delay duration for retries.
|
||||
RetryDuration time.Duration
|
||||
|
||||
// UserAgent, if not empty, will be set as the HTTP User-Agent header on all requests sent
|
||||
// through the Do method.
|
||||
UserAgent string
|
||||
|
||||
Jar http.CookieJar
|
||||
|
||||
// Set to true to skip attempted registration of resource providers (false by default).
|
||||
SkipResourceProviderRegistration bool
|
||||
}
|
||||
|
||||
// NewClientWithUserAgent returns an instance of a Client with the UserAgent set to the passed
|
||||
// string.
|
||||
func NewClientWithUserAgent(ua string) Client {
|
||||
c := Client{
|
||||
PollingDelay: DefaultPollingDelay,
|
||||
PollingDuration: DefaultPollingDuration,
|
||||
RetryAttempts: DefaultRetryAttempts,
|
||||
RetryDuration: DefaultRetryDuration,
|
||||
UserAgent: defaultUserAgent,
|
||||
}
|
||||
c.Sender = c.sender()
|
||||
c.AddToUserAgent(ua)
|
||||
return c
|
||||
}
|
||||
|
||||
// AddToUserAgent adds an extension to the current user agent
|
||||
func (c *Client) AddToUserAgent(extension string) error {
|
||||
if extension != "" {
|
||||
c.UserAgent = fmt.Sprintf("%s %s", c.UserAgent, extension)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Extension was empty, User Agent stayed as %s", c.UserAgent)
|
||||
}
|
||||
|
||||
// Do implements the Sender interface by invoking the active Sender after applying authorization.
|
||||
// If Sender is not set, it uses a new instance of http.Client. In both cases it will, if UserAgent
|
||||
// is set, apply set the User-Agent header.
|
||||
func (c Client) Do(r *http.Request) (*http.Response, error) {
|
||||
if r.UserAgent() == "" {
|
||||
r, _ = Prepare(r,
|
||||
WithUserAgent(c.UserAgent))
|
||||
}
|
||||
// NOTE: c.WithInspection() must be last in the list so that it can inspect all preceding operations
|
||||
r, err := Prepare(r,
|
||||
c.WithAuthorization(),
|
||||
c.WithInspection())
|
||||
if err != nil {
|
||||
var resp *http.Response
|
||||
if detErr, ok := err.(DetailedError); ok {
|
||||
// if the authorization failed (e.g. invalid credentials) there will
|
||||
// be a response associated with the error, be sure to return it.
|
||||
resp = detErr.Response
|
||||
}
|
||||
return resp, NewErrorWithError(err, "autorest/Client", "Do", nil, "Preparing request failed")
|
||||
}
|
||||
|
||||
resp, err := SendWithSender(c.sender(), r)
|
||||
Respond(resp, c.ByInspecting())
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// sender returns the Sender to which to send requests.
|
||||
func (c Client) sender() Sender {
|
||||
if c.Sender == nil {
|
||||
j, _ := cookiejar.New(nil)
|
||||
return &http.Client{Jar: j}
|
||||
}
|
||||
return c.Sender
|
||||
}
|
||||
|
||||
// WithAuthorization is a convenience method that returns the WithAuthorization PrepareDecorator
|
||||
// from the current Authorizer. If not Authorizer is set, it uses the NullAuthorizer.
|
||||
func (c Client) WithAuthorization() PrepareDecorator {
|
||||
return c.authorizer().WithAuthorization()
|
||||
}
|
||||
|
||||
// authorizer returns the Authorizer to use.
|
||||
func (c Client) authorizer() Authorizer {
|
||||
if c.Authorizer == nil {
|
||||
return NullAuthorizer{}
|
||||
}
|
||||
return c.Authorizer
|
||||
}
|
||||
|
||||
// WithInspection is a convenience method that passes the request to the supplied RequestInspector,
|
||||
// if present, or returns the WithNothing PrepareDecorator otherwise.
|
||||
func (c Client) WithInspection() PrepareDecorator {
|
||||
if c.RequestInspector == nil {
|
||||
return WithNothing()
|
||||
}
|
||||
return c.RequestInspector
|
||||
}
|
||||
|
||||
// ByInspecting is a convenience method that passes the response to the supplied ResponseInspector,
|
||||
// if present, or returns the ByIgnoring RespondDecorator otherwise.
|
||||
func (c Client) ByInspecting() RespondDecorator {
|
||||
if c.ResponseInspector == nil {
|
||||
return ByIgnoring()
|
||||
}
|
||||
return c.ResponseInspector
|
||||
}
|
||||
98
vendor/github.com/Azure/go-autorest/autorest/error.go
generated
vendored
Normal file
98
vendor/github.com/Azure/go-autorest/autorest/error.go
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
package autorest
|
||||
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const (
|
||||
// UndefinedStatusCode is used when HTTP status code is not available for an error.
|
||||
UndefinedStatusCode = 0
|
||||
)
|
||||
|
||||
// DetailedError encloses a error with details of the package, method, and associated HTTP
|
||||
// status code (if any).
|
||||
type DetailedError struct {
|
||||
Original error
|
||||
|
||||
// PackageType is the package type of the object emitting the error. For types, the value
|
||||
// matches that produced the the '%T' format specifier of the fmt package. For other elements,
|
||||
// such as functions, it is just the package name (e.g., "autorest").
|
||||
PackageType string
|
||||
|
||||
// Method is the name of the method raising the error.
|
||||
Method string
|
||||
|
||||
// StatusCode is the HTTP Response StatusCode (if non-zero) that led to the error.
|
||||
StatusCode interface{}
|
||||
|
||||
// Message is the error message.
|
||||
Message string
|
||||
|
||||
// Service Error is the response body of failed API in bytes
|
||||
ServiceError []byte
|
||||
|
||||
// Response is the response object that was returned during failure if applicable.
|
||||
Response *http.Response
|
||||
}
|
||||
|
||||
// NewError creates a new Error conforming object from the passed packageType, method, and
|
||||
// message. message is treated as a format string to which the optional args apply.
|
||||
func NewError(packageType string, method string, message string, args ...interface{}) DetailedError {
|
||||
return NewErrorWithError(nil, packageType, method, nil, message, args...)
|
||||
}
|
||||
|
||||
// NewErrorWithResponse creates a new Error conforming object from the passed
|
||||
// packageType, method, statusCode of the given resp (UndefinedStatusCode if
|
||||
// resp is nil), and message. message is treated as a format string to which the
|
||||
// optional args apply.
|
||||
func NewErrorWithResponse(packageType string, method string, resp *http.Response, message string, args ...interface{}) DetailedError {
|
||||
return NewErrorWithError(nil, packageType, method, resp, message, args...)
|
||||
}
|
||||
|
||||
// NewErrorWithError creates a new Error conforming object from the
|
||||
// passed packageType, method, statusCode of the given resp (UndefinedStatusCode
|
||||
// if resp is nil), message, and original error. message is treated as a format
|
||||
// string to which the optional args apply.
|
||||
func NewErrorWithError(original error, packageType string, method string, resp *http.Response, message string, args ...interface{}) DetailedError {
|
||||
if v, ok := original.(DetailedError); ok {
|
||||
return v
|
||||
}
|
||||
|
||||
statusCode := UndefinedStatusCode
|
||||
if resp != nil {
|
||||
statusCode = resp.StatusCode
|
||||
}
|
||||
|
||||
return DetailedError{
|
||||
Original: original,
|
||||
PackageType: packageType,
|
||||
Method: method,
|
||||
StatusCode: statusCode,
|
||||
Message: fmt.Sprintf(message, args...),
|
||||
Response: resp,
|
||||
}
|
||||
}
|
||||
|
||||
// Error returns a formatted containing all available details (i.e., PackageType, Method,
|
||||
// StatusCode, Message, and original error (if any)).
|
||||
func (e DetailedError) Error() string {
|
||||
if e.Original == nil {
|
||||
return fmt.Sprintf("%s#%s: %s: StatusCode=%d", e.PackageType, e.Method, e.Message, e.StatusCode)
|
||||
}
|
||||
return fmt.Sprintf("%s#%s: %s: StatusCode=%d -- Original Error: %v", e.PackageType, e.Method, e.Message, e.StatusCode, e.Original)
|
||||
}
|
||||
480
vendor/github.com/Azure/go-autorest/autorest/preparer.go
generated
vendored
Normal file
480
vendor/github.com/Azure/go-autorest/autorest/preparer.go
generated
vendored
Normal file
@@ -0,0 +1,480 @@
|
||||
package autorest
|
||||
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
mimeTypeJSON = "application/json"
|
||||
mimeTypeOctetStream = "application/octet-stream"
|
||||
mimeTypeFormPost = "application/x-www-form-urlencoded"
|
||||
|
||||
headerAuthorization = "Authorization"
|
||||
headerContentType = "Content-Type"
|
||||
headerUserAgent = "User-Agent"
|
||||
)
|
||||
|
||||
// Preparer is the interface that wraps the Prepare method.
|
||||
//
|
||||
// Prepare accepts and possibly modifies an http.Request (e.g., adding Headers). Implementations
|
||||
// must ensure to not share or hold per-invocation state since Preparers may be shared and re-used.
|
||||
type Preparer interface {
|
||||
Prepare(*http.Request) (*http.Request, error)
|
||||
}
|
||||
|
||||
// PreparerFunc is a method that implements the Preparer interface.
|
||||
type PreparerFunc func(*http.Request) (*http.Request, error)
|
||||
|
||||
// Prepare implements the Preparer interface on PreparerFunc.
|
||||
func (pf PreparerFunc) Prepare(r *http.Request) (*http.Request, error) {
|
||||
return pf(r)
|
||||
}
|
||||
|
||||
// PrepareDecorator takes and possibly decorates, by wrapping, a Preparer. Decorators may affect the
|
||||
// http.Request and pass it along or, first, pass the http.Request along then affect the result.
|
||||
type PrepareDecorator func(Preparer) Preparer
|
||||
|
||||
// CreatePreparer creates, decorates, and returns a Preparer.
|
||||
// Without decorators, the returned Preparer returns the passed http.Request unmodified.
|
||||
// Preparers are safe to share and re-use.
|
||||
func CreatePreparer(decorators ...PrepareDecorator) Preparer {
|
||||
return DecoratePreparer(
|
||||
Preparer(PreparerFunc(func(r *http.Request) (*http.Request, error) { return r, nil })),
|
||||
decorators...)
|
||||
}
|
||||
|
||||
// DecoratePreparer accepts a Preparer and a, possibly empty, set of PrepareDecorators, which it
|
||||
// applies to the Preparer. Decorators are applied in the order received, but their affect upon the
|
||||
// request depends on whether they are a pre-decorator (change the http.Request and then pass it
|
||||
// along) or a post-decorator (pass the http.Request along and alter it on return).
|
||||
func DecoratePreparer(p Preparer, decorators ...PrepareDecorator) Preparer {
|
||||
for _, decorate := range decorators {
|
||||
p = decorate(p)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// Prepare accepts an http.Request and a, possibly empty, set of PrepareDecorators.
|
||||
// It creates a Preparer from the decorators which it then applies to the passed http.Request.
|
||||
func Prepare(r *http.Request, decorators ...PrepareDecorator) (*http.Request, error) {
|
||||
if r == nil {
|
||||
return nil, NewError("autorest", "Prepare", "Invoked without an http.Request")
|
||||
}
|
||||
return CreatePreparer(decorators...).Prepare(r)
|
||||
}
|
||||
|
||||
// WithNothing returns a "do nothing" PrepareDecorator that makes no changes to the passed
|
||||
// http.Request.
|
||||
func WithNothing() PrepareDecorator {
|
||||
return func(p Preparer) Preparer {
|
||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
return p.Prepare(r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// WithHeader returns a PrepareDecorator that sets the specified HTTP header of the http.Request to
|
||||
// the passed value. It canonicalizes the passed header name (via http.CanonicalHeaderKey) before
|
||||
// adding the header.
|
||||
func WithHeader(header string, value string) PrepareDecorator {
|
||||
return func(p Preparer) Preparer {
|
||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
r, err := p.Prepare(r)
|
||||
if err == nil {
|
||||
if r.Header == nil {
|
||||
r.Header = make(http.Header)
|
||||
}
|
||||
r.Header.Set(http.CanonicalHeaderKey(header), value)
|
||||
}
|
||||
return r, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// WithHeaders returns a PrepareDecorator that sets the specified HTTP headers of the http.Request to
|
||||
// the passed value. It canonicalizes the passed headers name (via http.CanonicalHeaderKey) before
|
||||
// adding them.
|
||||
func WithHeaders(headers map[string]interface{}) PrepareDecorator {
|
||||
h := ensureValueStrings(headers)
|
||||
return func(p Preparer) Preparer {
|
||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
r, err := p.Prepare(r)
|
||||
if err == nil {
|
||||
if r.Header == nil {
|
||||
r.Header = make(http.Header)
|
||||
}
|
||||
|
||||
for name, value := range h {
|
||||
r.Header.Set(http.CanonicalHeaderKey(name), value)
|
||||
}
|
||||
}
|
||||
return r, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// WithBearerAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose
|
||||
// value is "Bearer " followed by the supplied token.
|
||||
func WithBearerAuthorization(token string) PrepareDecorator {
|
||||
return WithHeader(headerAuthorization, fmt.Sprintf("Bearer %s", token))
|
||||
}
|
||||
|
||||
// AsContentType returns a PrepareDecorator that adds an HTTP Content-Type header whose value
|
||||
// is the passed contentType.
|
||||
func AsContentType(contentType string) PrepareDecorator {
|
||||
return WithHeader(headerContentType, contentType)
|
||||
}
|
||||
|
||||
// WithUserAgent returns a PrepareDecorator that adds an HTTP User-Agent header whose value is the
|
||||
// passed string.
|
||||
func WithUserAgent(ua string) PrepareDecorator {
|
||||
return WithHeader(headerUserAgent, ua)
|
||||
}
|
||||
|
||||
// AsFormURLEncoded returns a PrepareDecorator that adds an HTTP Content-Type header whose value is
|
||||
// "application/x-www-form-urlencoded".
|
||||
func AsFormURLEncoded() PrepareDecorator {
|
||||
return AsContentType(mimeTypeFormPost)
|
||||
}
|
||||
|
||||
// AsJSON returns a PrepareDecorator that adds an HTTP Content-Type header whose value is
|
||||
// "application/json".
|
||||
func AsJSON() PrepareDecorator {
|
||||
return AsContentType(mimeTypeJSON)
|
||||
}
|
||||
|
||||
// AsOctetStream returns a PrepareDecorator that adds the "application/octet-stream" Content-Type header.
|
||||
func AsOctetStream() PrepareDecorator {
|
||||
return AsContentType(mimeTypeOctetStream)
|
||||
}
|
||||
|
||||
// WithMethod returns a PrepareDecorator that sets the HTTP method of the passed request. The
|
||||
// decorator does not validate that the passed method string is a known HTTP method.
|
||||
func WithMethod(method string) PrepareDecorator {
|
||||
return func(p Preparer) Preparer {
|
||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
r.Method = method
|
||||
return p.Prepare(r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// AsDelete returns a PrepareDecorator that sets the HTTP method to DELETE.
|
||||
func AsDelete() PrepareDecorator { return WithMethod("DELETE") }
|
||||
|
||||
// AsGet returns a PrepareDecorator that sets the HTTP method to GET.
|
||||
func AsGet() PrepareDecorator { return WithMethod("GET") }
|
||||
|
||||
// AsHead returns a PrepareDecorator that sets the HTTP method to HEAD.
|
||||
func AsHead() PrepareDecorator { return WithMethod("HEAD") }
|
||||
|
||||
// AsOptions returns a PrepareDecorator that sets the HTTP method to OPTIONS.
|
||||
func AsOptions() PrepareDecorator { return WithMethod("OPTIONS") }
|
||||
|
||||
// AsPatch returns a PrepareDecorator that sets the HTTP method to PATCH.
|
||||
func AsPatch() PrepareDecorator { return WithMethod("PATCH") }
|
||||
|
||||
// AsPost returns a PrepareDecorator that sets the HTTP method to POST.
|
||||
func AsPost() PrepareDecorator { return WithMethod("POST") }
|
||||
|
||||
// AsPut returns a PrepareDecorator that sets the HTTP method to PUT.
|
||||
func AsPut() PrepareDecorator { return WithMethod("PUT") }
|
||||
|
||||
// WithBaseURL returns a PrepareDecorator that populates the http.Request with a url.URL constructed
|
||||
// from the supplied baseUrl.
|
||||
func WithBaseURL(baseURL string) PrepareDecorator {
|
||||
return func(p Preparer) Preparer {
|
||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
r, err := p.Prepare(r)
|
||||
if err == nil {
|
||||
var u *url.URL
|
||||
if u, err = url.Parse(baseURL); err != nil {
|
||||
return r, err
|
||||
}
|
||||
if u.Scheme == "" {
|
||||
err = fmt.Errorf("autorest: No scheme detected in URL %s", baseURL)
|
||||
}
|
||||
if err == nil {
|
||||
r.URL = u
|
||||
}
|
||||
}
|
||||
return r, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// WithCustomBaseURL returns a PrepareDecorator that replaces brace-enclosed keys within the
|
||||
// request base URL (i.e., http.Request.URL) with the corresponding values from the passed map.
|
||||
func WithCustomBaseURL(baseURL string, urlParameters map[string]interface{}) PrepareDecorator {
|
||||
parameters := ensureValueStrings(urlParameters)
|
||||
for key, value := range parameters {
|
||||
baseURL = strings.Replace(baseURL, "{"+key+"}", value, -1)
|
||||
}
|
||||
return WithBaseURL(baseURL)
|
||||
}
|
||||
|
||||
// WithFormData returns a PrepareDecoratore that "URL encodes" (e.g., bar=baz&foo=quux) into the
|
||||
// http.Request body.
|
||||
func WithFormData(v url.Values) PrepareDecorator {
|
||||
return func(p Preparer) Preparer {
|
||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
r, err := p.Prepare(r)
|
||||
if err == nil {
|
||||
s := v.Encode()
|
||||
|
||||
if r.Header == nil {
|
||||
r.Header = make(http.Header)
|
||||
}
|
||||
r.Header.Set(http.CanonicalHeaderKey(headerContentType), mimeTypeFormPost)
|
||||
r.ContentLength = int64(len(s))
|
||||
r.Body = ioutil.NopCloser(strings.NewReader(s))
|
||||
}
|
||||
return r, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// WithMultiPartFormData returns a PrepareDecoratore that "URL encodes" (e.g., bar=baz&foo=quux) form parameters
|
||||
// into the http.Request body.
|
||||
func WithMultiPartFormData(formDataParameters map[string]interface{}) PrepareDecorator {
|
||||
return func(p Preparer) Preparer {
|
||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
r, err := p.Prepare(r)
|
||||
if err == nil {
|
||||
var body bytes.Buffer
|
||||
writer := multipart.NewWriter(&body)
|
||||
for key, value := range formDataParameters {
|
||||
if rc, ok := value.(io.ReadCloser); ok {
|
||||
var fd io.Writer
|
||||
if fd, err = writer.CreateFormFile(key, key); err != nil {
|
||||
return r, err
|
||||
}
|
||||
if _, err = io.Copy(fd, rc); err != nil {
|
||||
return r, err
|
||||
}
|
||||
} else {
|
||||
if err = writer.WriteField(key, ensureValueString(value)); err != nil {
|
||||
return r, err
|
||||
}
|
||||
}
|
||||
}
|
||||
if err = writer.Close(); err != nil {
|
||||
return r, err
|
||||
}
|
||||
if r.Header == nil {
|
||||
r.Header = make(http.Header)
|
||||
}
|
||||
r.Header.Set(http.CanonicalHeaderKey(headerContentType), writer.FormDataContentType())
|
||||
r.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
|
||||
r.ContentLength = int64(body.Len())
|
||||
return r, err
|
||||
}
|
||||
return r, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// WithFile returns a PrepareDecorator that sends file in request body.
|
||||
func WithFile(f io.ReadCloser) PrepareDecorator {
|
||||
return func(p Preparer) Preparer {
|
||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
r, err := p.Prepare(r)
|
||||
if err == nil {
|
||||
b, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
r.Body = ioutil.NopCloser(bytes.NewReader(b))
|
||||
r.ContentLength = int64(len(b))
|
||||
}
|
||||
return r, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// WithBool returns a PrepareDecorator that encodes the passed bool into the body of the request
|
||||
// and sets the Content-Length header.
|
||||
func WithBool(v bool) PrepareDecorator {
|
||||
return WithString(fmt.Sprintf("%v", v))
|
||||
}
|
||||
|
||||
// WithFloat32 returns a PrepareDecorator that encodes the passed float32 into the body of the
|
||||
// request and sets the Content-Length header.
|
||||
func WithFloat32(v float32) PrepareDecorator {
|
||||
return WithString(fmt.Sprintf("%v", v))
|
||||
}
|
||||
|
||||
// WithFloat64 returns a PrepareDecorator that encodes the passed float64 into the body of the
|
||||
// request and sets the Content-Length header.
|
||||
func WithFloat64(v float64) PrepareDecorator {
|
||||
return WithString(fmt.Sprintf("%v", v))
|
||||
}
|
||||
|
||||
// WithInt32 returns a PrepareDecorator that encodes the passed int32 into the body of the request
|
||||
// and sets the Content-Length header.
|
||||
func WithInt32(v int32) PrepareDecorator {
|
||||
return WithString(fmt.Sprintf("%v", v))
|
||||
}
|
||||
|
||||
// WithInt64 returns a PrepareDecorator that encodes the passed int64 into the body of the request
|
||||
// and sets the Content-Length header.
|
||||
func WithInt64(v int64) PrepareDecorator {
|
||||
return WithString(fmt.Sprintf("%v", v))
|
||||
}
|
||||
|
||||
// WithString returns a PrepareDecorator that encodes the passed string into the body of the request
|
||||
// and sets the Content-Length header.
|
||||
func WithString(v string) PrepareDecorator {
|
||||
return func(p Preparer) Preparer {
|
||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
r, err := p.Prepare(r)
|
||||
if err == nil {
|
||||
r.ContentLength = int64(len(v))
|
||||
r.Body = ioutil.NopCloser(strings.NewReader(v))
|
||||
}
|
||||
return r, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// WithJSON returns a PrepareDecorator that encodes the data passed as JSON into the body of the
|
||||
// request and sets the Content-Length header.
|
||||
func WithJSON(v interface{}) PrepareDecorator {
|
||||
return func(p Preparer) Preparer {
|
||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
r, err := p.Prepare(r)
|
||||
if err == nil {
|
||||
b, err := json.Marshal(v)
|
||||
if err == nil {
|
||||
r.ContentLength = int64(len(b))
|
||||
r.Body = ioutil.NopCloser(bytes.NewReader(b))
|
||||
}
|
||||
}
|
||||
return r, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// WithPath returns a PrepareDecorator that adds the supplied path to the request URL. If the path
|
||||
// is absolute (that is, it begins with a "/"), it replaces the existing path.
|
||||
func WithPath(path string) PrepareDecorator {
|
||||
return func(p Preparer) Preparer {
|
||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
r, err := p.Prepare(r)
|
||||
if err == nil {
|
||||
if r.URL == nil {
|
||||
return r, NewError("autorest", "WithPath", "Invoked with a nil URL")
|
||||
}
|
||||
if r.URL, err = parseURL(r.URL, path); err != nil {
|
||||
return r, err
|
||||
}
|
||||
}
|
||||
return r, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// WithEscapedPathParameters returns a PrepareDecorator that replaces brace-enclosed keys within the
|
||||
// request path (i.e., http.Request.URL.Path) with the corresponding values from the passed map. The
|
||||
// values will be escaped (aka URL encoded) before insertion into the path.
|
||||
func WithEscapedPathParameters(path string, pathParameters map[string]interface{}) PrepareDecorator {
|
||||
parameters := escapeValueStrings(ensureValueStrings(pathParameters))
|
||||
return func(p Preparer) Preparer {
|
||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
r, err := p.Prepare(r)
|
||||
if err == nil {
|
||||
if r.URL == nil {
|
||||
return r, NewError("autorest", "WithEscapedPathParameters", "Invoked with a nil URL")
|
||||
}
|
||||
for key, value := range parameters {
|
||||
path = strings.Replace(path, "{"+key+"}", value, -1)
|
||||
}
|
||||
if r.URL, err = parseURL(r.URL, path); err != nil {
|
||||
return r, err
|
||||
}
|
||||
}
|
||||
return r, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// WithPathParameters returns a PrepareDecorator that replaces brace-enclosed keys within the
|
||||
// request path (i.e., http.Request.URL.Path) with the corresponding values from the passed map.
|
||||
func WithPathParameters(path string, pathParameters map[string]interface{}) PrepareDecorator {
|
||||
parameters := ensureValueStrings(pathParameters)
|
||||
return func(p Preparer) Preparer {
|
||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
r, err := p.Prepare(r)
|
||||
if err == nil {
|
||||
if r.URL == nil {
|
||||
return r, NewError("autorest", "WithPathParameters", "Invoked with a nil URL")
|
||||
}
|
||||
for key, value := range parameters {
|
||||
path = strings.Replace(path, "{"+key+"}", value, -1)
|
||||
}
|
||||
|
||||
if r.URL, err = parseURL(r.URL, path); err != nil {
|
||||
return r, err
|
||||
}
|
||||
}
|
||||
return r, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func parseURL(u *url.URL, path string) (*url.URL, error) {
|
||||
p := strings.TrimRight(u.String(), "/")
|
||||
if !strings.HasPrefix(path, "/") {
|
||||
path = "/" + path
|
||||
}
|
||||
return url.Parse(p + path)
|
||||
}
|
||||
|
||||
// WithQueryParameters returns a PrepareDecorators that encodes and applies the query parameters
|
||||
// given in the supplied map (i.e., key=value).
|
||||
func WithQueryParameters(queryParameters map[string]interface{}) PrepareDecorator {
|
||||
parameters := ensureValueStrings(queryParameters)
|
||||
return func(p Preparer) Preparer {
|
||||
return PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
r, err := p.Prepare(r)
|
||||
if err == nil {
|
||||
if r.URL == nil {
|
||||
return r, NewError("autorest", "WithQueryParameters", "Invoked with a nil URL")
|
||||
}
|
||||
|
||||
v := r.URL.Query()
|
||||
for key, value := range parameters {
|
||||
d, err := url.QueryUnescape(value)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
v.Add(key, d)
|
||||
}
|
||||
r.URL.RawQuery = v.Encode()
|
||||
}
|
||||
return r, err
|
||||
})
|
||||
}
|
||||
}
|
||||
250
vendor/github.com/Azure/go-autorest/autorest/responder.go
generated
vendored
Normal file
250
vendor/github.com/Azure/go-autorest/autorest/responder.go
generated
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
package autorest
|
||||
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Responder is the interface that wraps the Respond method.
|
||||
//
|
||||
// Respond accepts and reacts to an http.Response. Implementations must ensure to not share or hold
|
||||
// state since Responders may be shared and re-used.
|
||||
type Responder interface {
|
||||
Respond(*http.Response) error
|
||||
}
|
||||
|
||||
// ResponderFunc is a method that implements the Responder interface.
|
||||
type ResponderFunc func(*http.Response) error
|
||||
|
||||
// Respond implements the Responder interface on ResponderFunc.
|
||||
func (rf ResponderFunc) Respond(r *http.Response) error {
|
||||
return rf(r)
|
||||
}
|
||||
|
||||
// RespondDecorator takes and possibly decorates, by wrapping, a Responder. Decorators may react to
|
||||
// the http.Response and pass it along or, first, pass the http.Response along then react.
|
||||
type RespondDecorator func(Responder) Responder
|
||||
|
||||
// CreateResponder creates, decorates, and returns a Responder. Without decorators, the returned
|
||||
// Responder returns the passed http.Response unmodified. Responders may or may not be safe to share
|
||||
// and re-used: It depends on the applied decorators. For example, a standard decorator that closes
|
||||
// the response body is fine to share whereas a decorator that reads the body into a passed struct
|
||||
// is not.
|
||||
//
|
||||
// To prevent memory leaks, ensure that at least one Responder closes the response body.
|
||||
func CreateResponder(decorators ...RespondDecorator) Responder {
|
||||
return DecorateResponder(
|
||||
Responder(ResponderFunc(func(r *http.Response) error { return nil })),
|
||||
decorators...)
|
||||
}
|
||||
|
||||
// DecorateResponder accepts a Responder and a, possibly empty, set of RespondDecorators, which it
|
||||
// applies to the Responder. Decorators are applied in the order received, but their affect upon the
|
||||
// request depends on whether they are a pre-decorator (react to the http.Response and then pass it
|
||||
// along) or a post-decorator (pass the http.Response along and then react).
|
||||
func DecorateResponder(r Responder, decorators ...RespondDecorator) Responder {
|
||||
for _, decorate := range decorators {
|
||||
r = decorate(r)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Respond accepts an http.Response and a, possibly empty, set of RespondDecorators.
|
||||
// It creates a Responder from the decorators it then applies to the passed http.Response.
|
||||
func Respond(r *http.Response, decorators ...RespondDecorator) error {
|
||||
if r == nil {
|
||||
return nil
|
||||
}
|
||||
return CreateResponder(decorators...).Respond(r)
|
||||
}
|
||||
|
||||
// ByIgnoring returns a RespondDecorator that ignores the passed http.Response passing it unexamined
|
||||
// to the next RespondDecorator.
|
||||
func ByIgnoring() RespondDecorator {
|
||||
return func(r Responder) Responder {
|
||||
return ResponderFunc(func(resp *http.Response) error {
|
||||
return r.Respond(resp)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ByCopying copies the contents of the http.Response Body into the passed bytes.Buffer as
|
||||
// the Body is read.
|
||||
func ByCopying(b *bytes.Buffer) RespondDecorator {
|
||||
return func(r Responder) Responder {
|
||||
return ResponderFunc(func(resp *http.Response) error {
|
||||
err := r.Respond(resp)
|
||||
if err == nil && resp != nil && resp.Body != nil {
|
||||
resp.Body = TeeReadCloser(resp.Body, b)
|
||||
}
|
||||
return err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ByDiscardingBody returns a RespondDecorator that first invokes the passed Responder after which
|
||||
// it copies the remaining bytes (if any) in the response body to ioutil.Discard. Since the passed
|
||||
// Responder is invoked prior to discarding the response body, the decorator may occur anywhere
|
||||
// within the set.
|
||||
func ByDiscardingBody() RespondDecorator {
|
||||
return func(r Responder) Responder {
|
||||
return ResponderFunc(func(resp *http.Response) error {
|
||||
err := r.Respond(resp)
|
||||
if err == nil && resp != nil && resp.Body != nil {
|
||||
if _, err := io.Copy(ioutil.Discard, resp.Body); err != nil {
|
||||
return fmt.Errorf("Error discarding the response body: %v", err)
|
||||
}
|
||||
}
|
||||
return err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ByClosing returns a RespondDecorator that first invokes the passed Responder after which it
|
||||
// closes the response body. Since the passed Responder is invoked prior to closing the response
|
||||
// body, the decorator may occur anywhere within the set.
|
||||
func ByClosing() RespondDecorator {
|
||||
return func(r Responder) Responder {
|
||||
return ResponderFunc(func(resp *http.Response) error {
|
||||
err := r.Respond(resp)
|
||||
if resp != nil && resp.Body != nil {
|
||||
if err := resp.Body.Close(); err != nil {
|
||||
return fmt.Errorf("Error closing the response body: %v", err)
|
||||
}
|
||||
}
|
||||
return err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ByClosingIfError returns a RespondDecorator that first invokes the passed Responder after which
|
||||
// it closes the response if the passed Responder returns an error and the response body exists.
|
||||
func ByClosingIfError() RespondDecorator {
|
||||
return func(r Responder) Responder {
|
||||
return ResponderFunc(func(resp *http.Response) error {
|
||||
err := r.Respond(resp)
|
||||
if err != nil && resp != nil && resp.Body != nil {
|
||||
if err := resp.Body.Close(); err != nil {
|
||||
return fmt.Errorf("Error closing the response body: %v", err)
|
||||
}
|
||||
}
|
||||
return err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ByUnmarshallingJSON returns a RespondDecorator that decodes a JSON document returned in the
|
||||
// response Body into the value pointed to by v.
|
||||
func ByUnmarshallingJSON(v interface{}) RespondDecorator {
|
||||
return func(r Responder) Responder {
|
||||
return ResponderFunc(func(resp *http.Response) error {
|
||||
err := r.Respond(resp)
|
||||
if err == nil {
|
||||
b, errInner := ioutil.ReadAll(resp.Body)
|
||||
// Some responses might include a BOM, remove for successful unmarshalling
|
||||
b = bytes.TrimPrefix(b, []byte("\xef\xbb\xbf"))
|
||||
if errInner != nil {
|
||||
err = fmt.Errorf("Error occurred reading http.Response#Body - Error = '%v'", errInner)
|
||||
} else if len(strings.Trim(string(b), " ")) > 0 {
|
||||
errInner = json.Unmarshal(b, v)
|
||||
if errInner != nil {
|
||||
err = fmt.Errorf("Error occurred unmarshalling JSON - Error = '%v' JSON = '%s'", errInner, string(b))
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ByUnmarshallingXML returns a RespondDecorator that decodes a XML document returned in the
|
||||
// response Body into the value pointed to by v.
|
||||
func ByUnmarshallingXML(v interface{}) RespondDecorator {
|
||||
return func(r Responder) Responder {
|
||||
return ResponderFunc(func(resp *http.Response) error {
|
||||
err := r.Respond(resp)
|
||||
if err == nil {
|
||||
b, errInner := ioutil.ReadAll(resp.Body)
|
||||
if errInner != nil {
|
||||
err = fmt.Errorf("Error occurred reading http.Response#Body - Error = '%v'", errInner)
|
||||
} else {
|
||||
errInner = xml.Unmarshal(b, v)
|
||||
if errInner != nil {
|
||||
err = fmt.Errorf("Error occurred unmarshalling Xml - Error = '%v' Xml = '%s'", errInner, string(b))
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// WithErrorUnlessStatusCode returns a RespondDecorator that emits an error unless the response
|
||||
// StatusCode is among the set passed. On error, response body is fully read into a buffer and
|
||||
// presented in the returned error, as well as in the response body.
|
||||
func WithErrorUnlessStatusCode(codes ...int) RespondDecorator {
|
||||
return func(r Responder) Responder {
|
||||
return ResponderFunc(func(resp *http.Response) error {
|
||||
err := r.Respond(resp)
|
||||
if err == nil && !ResponseHasStatusCode(resp, codes...) {
|
||||
derr := NewErrorWithResponse("autorest", "WithErrorUnlessStatusCode", resp, "%v %v failed with %s",
|
||||
resp.Request.Method,
|
||||
resp.Request.URL,
|
||||
resp.Status)
|
||||
if resp.Body != nil {
|
||||
defer resp.Body.Close()
|
||||
b, _ := ioutil.ReadAll(resp.Body)
|
||||
derr.ServiceError = b
|
||||
resp.Body = ioutil.NopCloser(bytes.NewReader(b))
|
||||
}
|
||||
err = derr
|
||||
}
|
||||
return err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// WithErrorUnlessOK returns a RespondDecorator that emits an error if the response StatusCode is
|
||||
// anything other than HTTP 200.
|
||||
func WithErrorUnlessOK() RespondDecorator {
|
||||
return WithErrorUnlessStatusCode(http.StatusOK)
|
||||
}
|
||||
|
||||
// ExtractHeader extracts all values of the specified header from the http.Response. It returns an
|
||||
// empty string slice if the passed http.Response is nil or the header does not exist.
|
||||
func ExtractHeader(header string, resp *http.Response) []string {
|
||||
if resp != nil && resp.Header != nil {
|
||||
return resp.Header[http.CanonicalHeaderKey(header)]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExtractHeaderValue extracts the first value of the specified header from the http.Response. It
|
||||
// returns an empty string if the passed http.Response is nil or the header does not exist.
|
||||
func ExtractHeaderValue(header string, resp *http.Response) string {
|
||||
h := ExtractHeader(header, resp)
|
||||
if len(h) > 0 {
|
||||
return h[0]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
52
vendor/github.com/Azure/go-autorest/autorest/retriablerequest.go
generated
vendored
Normal file
52
vendor/github.com/Azure/go-autorest/autorest/retriablerequest.go
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
package autorest
|
||||
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// NewRetriableRequest returns a wrapper around an HTTP request that support retry logic.
|
||||
func NewRetriableRequest(req *http.Request) *RetriableRequest {
|
||||
return &RetriableRequest{req: req}
|
||||
}
|
||||
|
||||
// Request returns the wrapped HTTP request.
|
||||
func (rr *RetriableRequest) Request() *http.Request {
|
||||
return rr.req
|
||||
}
|
||||
|
||||
func (rr *RetriableRequest) prepareFromByteReader() (err error) {
|
||||
// fall back to making a copy (only do this once)
|
||||
b := []byte{}
|
||||
if rr.req.ContentLength > 0 {
|
||||
b = make([]byte, rr.req.ContentLength)
|
||||
_, err = io.ReadFull(rr.req.Body, b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
b, err = ioutil.ReadAll(rr.req.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
rr.br = bytes.NewReader(b)
|
||||
rr.req.Body = ioutil.NopCloser(rr.br)
|
||||
return err
|
||||
}
|
||||
54
vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.7.go
generated
vendored
Normal file
54
vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.7.go
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
// +build !go1.8
|
||||
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package autorest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// RetriableRequest provides facilities for retrying an HTTP request.
|
||||
type RetriableRequest struct {
|
||||
req *http.Request
|
||||
br *bytes.Reader
|
||||
}
|
||||
|
||||
// Prepare signals that the request is about to be sent.
|
||||
func (rr *RetriableRequest) Prepare() (err error) {
|
||||
// preserve the request body; this is to support retry logic as
|
||||
// the underlying transport will always close the reqeust body
|
||||
if rr.req.Body != nil {
|
||||
if rr.br != nil {
|
||||
_, err = rr.br.Seek(0, 0 /*io.SeekStart*/)
|
||||
rr.req.Body = ioutil.NopCloser(rr.br)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rr.br == nil {
|
||||
// fall back to making a copy (only do this once)
|
||||
err = rr.prepareFromByteReader()
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func removeRequestBody(req *http.Request) {
|
||||
req.Body = nil
|
||||
req.ContentLength = 0
|
||||
}
|
||||
66
vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.8.go
generated
vendored
Normal file
66
vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.8.go
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
// +build go1.8
|
||||
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package autorest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// RetriableRequest provides facilities for retrying an HTTP request.
|
||||
type RetriableRequest struct {
|
||||
req *http.Request
|
||||
rc io.ReadCloser
|
||||
br *bytes.Reader
|
||||
}
|
||||
|
||||
// Prepare signals that the request is about to be sent.
|
||||
func (rr *RetriableRequest) Prepare() (err error) {
|
||||
// preserve the request body; this is to support retry logic as
|
||||
// the underlying transport will always close the reqeust body
|
||||
if rr.req.Body != nil {
|
||||
if rr.rc != nil {
|
||||
rr.req.Body = rr.rc
|
||||
} else if rr.br != nil {
|
||||
_, err = rr.br.Seek(0, io.SeekStart)
|
||||
rr.req.Body = ioutil.NopCloser(rr.br)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rr.req.GetBody != nil {
|
||||
// this will allow us to preserve the body without having to
|
||||
// make a copy. note we need to do this on each iteration
|
||||
rr.rc, err = rr.req.GetBody()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if rr.br == nil {
|
||||
// fall back to making a copy (only do this once)
|
||||
err = rr.prepareFromByteReader()
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func removeRequestBody(req *http.Request) {
|
||||
req.Body = nil
|
||||
req.GetBody = nil
|
||||
req.ContentLength = 0
|
||||
}
|
||||
325
vendor/github.com/Azure/go-autorest/autorest/sender.go
generated
vendored
Normal file
325
vendor/github.com/Azure/go-autorest/autorest/sender.go
generated
vendored
Normal file
@@ -0,0 +1,325 @@
|
||||
package autorest
|
||||
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Sender is the interface that wraps the Do method to send HTTP requests.
|
||||
//
|
||||
// The standard http.Client conforms to this interface.
|
||||
type Sender interface {
|
||||
Do(*http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
// SenderFunc is a method that implements the Sender interface.
|
||||
type SenderFunc func(*http.Request) (*http.Response, error)
|
||||
|
||||
// Do implements the Sender interface on SenderFunc.
|
||||
func (sf SenderFunc) Do(r *http.Request) (*http.Response, error) {
|
||||
return sf(r)
|
||||
}
|
||||
|
||||
// SendDecorator takes and possibily decorates, by wrapping, a Sender. Decorators may affect the
|
||||
// http.Request and pass it along or, first, pass the http.Request along then react to the
|
||||
// http.Response result.
|
||||
type SendDecorator func(Sender) Sender
|
||||
|
||||
// CreateSender creates, decorates, and returns, as a Sender, the default http.Client.
|
||||
func CreateSender(decorators ...SendDecorator) Sender {
|
||||
return DecorateSender(&http.Client{}, decorators...)
|
||||
}
|
||||
|
||||
// DecorateSender accepts a Sender and a, possibly empty, set of SendDecorators, which is applies to
|
||||
// the Sender. Decorators are applied in the order received, but their affect upon the request
|
||||
// depends on whether they are a pre-decorator (change the http.Request and then pass it along) or a
|
||||
// post-decorator (pass the http.Request along and react to the results in http.Response).
|
||||
func DecorateSender(s Sender, decorators ...SendDecorator) Sender {
|
||||
for _, decorate := range decorators {
|
||||
s = decorate(s)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Send sends, by means of the default http.Client, the passed http.Request, returning the
|
||||
// http.Response and possible error. It also accepts a, possibly empty, set of SendDecorators which
|
||||
// it will apply the http.Client before invoking the Do method.
|
||||
//
|
||||
// Send is a convenience method and not recommended for production. Advanced users should use
|
||||
// SendWithSender, passing and sharing their own Sender (e.g., instance of http.Client).
|
||||
//
|
||||
// Send will not poll or retry requests.
|
||||
func Send(r *http.Request, decorators ...SendDecorator) (*http.Response, error) {
|
||||
return SendWithSender(&http.Client{}, r, decorators...)
|
||||
}
|
||||
|
||||
// SendWithSender sends the passed http.Request, through the provided Sender, returning the
|
||||
// http.Response and possible error. It also accepts a, possibly empty, set of SendDecorators which
|
||||
// it will apply the http.Client before invoking the Do method.
|
||||
//
|
||||
// SendWithSender will not poll or retry requests.
|
||||
func SendWithSender(s Sender, r *http.Request, decorators ...SendDecorator) (*http.Response, error) {
|
||||
return DecorateSender(s, decorators...).Do(r)
|
||||
}
|
||||
|
||||
// AfterDelay returns a SendDecorator that delays for the passed time.Duration before
|
||||
// invoking the Sender. The delay may be terminated by closing the optional channel on the
|
||||
// http.Request. If canceled, no further Senders are invoked.
|
||||
func AfterDelay(d time.Duration) SendDecorator {
|
||||
return func(s Sender) Sender {
|
||||
return SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
if !DelayForBackoff(d, 0, r.Context().Done()) {
|
||||
return nil, fmt.Errorf("autorest: AfterDelay canceled before full delay")
|
||||
}
|
||||
return s.Do(r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// AsIs returns a SendDecorator that invokes the passed Sender without modifying the http.Request.
|
||||
func AsIs() SendDecorator {
|
||||
return func(s Sender) Sender {
|
||||
return SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
return s.Do(r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// DoCloseIfError returns a SendDecorator that first invokes the passed Sender after which
|
||||
// it closes the response if the passed Sender returns an error and the response body exists.
|
||||
func DoCloseIfError() SendDecorator {
|
||||
return func(s Sender) Sender {
|
||||
return SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
resp, err := s.Do(r)
|
||||
if err != nil {
|
||||
Respond(resp, ByDiscardingBody(), ByClosing())
|
||||
}
|
||||
return resp, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// DoErrorIfStatusCode returns a SendDecorator that emits an error if the response StatusCode is
|
||||
// among the set passed. Since these are artificial errors, the response body may still require
|
||||
// closing.
|
||||
func DoErrorIfStatusCode(codes ...int) SendDecorator {
|
||||
return func(s Sender) Sender {
|
||||
return SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
resp, err := s.Do(r)
|
||||
if err == nil && ResponseHasStatusCode(resp, codes...) {
|
||||
err = NewErrorWithResponse("autorest", "DoErrorIfStatusCode", resp, "%v %v failed with %s",
|
||||
resp.Request.Method,
|
||||
resp.Request.URL,
|
||||
resp.Status)
|
||||
}
|
||||
return resp, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// DoErrorUnlessStatusCode returns a SendDecorator that emits an error unless the response
|
||||
// StatusCode is among the set passed. Since these are artificial errors, the response body
|
||||
// may still require closing.
|
||||
func DoErrorUnlessStatusCode(codes ...int) SendDecorator {
|
||||
return func(s Sender) Sender {
|
||||
return SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
resp, err := s.Do(r)
|
||||
if err == nil && !ResponseHasStatusCode(resp, codes...) {
|
||||
err = NewErrorWithResponse("autorest", "DoErrorUnlessStatusCode", resp, "%v %v failed with %s",
|
||||
resp.Request.Method,
|
||||
resp.Request.URL,
|
||||
resp.Status)
|
||||
}
|
||||
return resp, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// DoPollForStatusCodes returns a SendDecorator that polls if the http.Response contains one of the
|
||||
// passed status codes. It expects the http.Response to contain a Location header providing the
|
||||
// URL at which to poll (using GET) and will poll until the time passed is equal to or greater than
|
||||
// the supplied duration. It will delay between requests for the duration specified in the
|
||||
// RetryAfter header or, if the header is absent, the passed delay. Polling may be canceled by
|
||||
// closing the optional channel on the http.Request.
|
||||
func DoPollForStatusCodes(duration time.Duration, delay time.Duration, codes ...int) SendDecorator {
|
||||
return func(s Sender) Sender {
|
||||
return SenderFunc(func(r *http.Request) (resp *http.Response, err error) {
|
||||
resp, err = s.Do(r)
|
||||
|
||||
if err == nil && ResponseHasStatusCode(resp, codes...) {
|
||||
r, err = NewPollingRequestWithContext(r.Context(), resp)
|
||||
|
||||
for err == nil && ResponseHasStatusCode(resp, codes...) {
|
||||
Respond(resp,
|
||||
ByDiscardingBody(),
|
||||
ByClosing())
|
||||
resp, err = SendWithSender(s, r,
|
||||
AfterDelay(GetRetryAfter(resp, delay)))
|
||||
}
|
||||
}
|
||||
|
||||
return resp, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// DoRetryForAttempts returns a SendDecorator that retries a failed request for up to the specified
|
||||
// number of attempts, exponentially backing off between requests using the supplied backoff
|
||||
// time.Duration (which may be zero). Retrying may be canceled by closing the optional channel on
|
||||
// the http.Request.
|
||||
func DoRetryForAttempts(attempts int, backoff time.Duration) SendDecorator {
|
||||
return func(s Sender) Sender {
|
||||
return SenderFunc(func(r *http.Request) (resp *http.Response, err error) {
|
||||
rr := NewRetriableRequest(r)
|
||||
for attempt := 0; attempt < attempts; attempt++ {
|
||||
err = rr.Prepare()
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
resp, err = s.Do(rr.Request())
|
||||
if err == nil {
|
||||
return resp, err
|
||||
}
|
||||
if !DelayForBackoff(backoff, attempt, r.Context().Done()) {
|
||||
return nil, r.Context().Err()
|
||||
}
|
||||
}
|
||||
return resp, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// DoRetryForStatusCodes returns a SendDecorator that retries for specified statusCodes for up to the specified
|
||||
// number of attempts, exponentially backing off between requests using the supplied backoff
|
||||
// time.Duration (which may be zero). Retrying may be canceled by closing the optional channel on
|
||||
// the http.Request.
|
||||
func DoRetryForStatusCodes(attempts int, backoff time.Duration, codes ...int) SendDecorator {
|
||||
return func(s Sender) Sender {
|
||||
return SenderFunc(func(r *http.Request) (resp *http.Response, err error) {
|
||||
rr := NewRetriableRequest(r)
|
||||
// Increment to add the first call (attempts denotes number of retries)
|
||||
attempts++
|
||||
for attempt := 0; attempt < attempts; {
|
||||
err = rr.Prepare()
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
resp, err = s.Do(rr.Request())
|
||||
// if the error isn't temporary don't bother retrying
|
||||
if err != nil && !IsTemporaryNetworkError(err) {
|
||||
return nil, err
|
||||
}
|
||||
// we want to retry if err is not nil (e.g. transient network failure). note that for failed authentication
|
||||
// resp and err will both have a value, so in this case we don't want to retry as it will never succeed.
|
||||
if err == nil && !ResponseHasStatusCode(resp, codes...) || IsTokenRefreshError(err) {
|
||||
return resp, err
|
||||
}
|
||||
delayed := DelayWithRetryAfter(resp, r.Context().Done())
|
||||
if !delayed && !DelayForBackoff(backoff, attempt, r.Context().Done()) {
|
||||
return nil, r.Context().Err()
|
||||
}
|
||||
// don't count a 429 against the number of attempts
|
||||
// so that we continue to retry until it succeeds
|
||||
if resp == nil || resp.StatusCode != http.StatusTooManyRequests {
|
||||
attempt++
|
||||
}
|
||||
}
|
||||
return resp, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// DelayWithRetryAfter invokes time.After for the duration specified in the "Retry-After" header in
|
||||
// responses with status code 429
|
||||
func DelayWithRetryAfter(resp *http.Response, cancel <-chan struct{}) bool {
|
||||
if resp == nil {
|
||||
return false
|
||||
}
|
||||
retryAfter, _ := strconv.Atoi(resp.Header.Get("Retry-After"))
|
||||
if resp.StatusCode == http.StatusTooManyRequests && retryAfter > 0 {
|
||||
select {
|
||||
case <-time.After(time.Duration(retryAfter) * time.Second):
|
||||
return true
|
||||
case <-cancel:
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// DoRetryForDuration returns a SendDecorator that retries the request until the total time is equal
|
||||
// to or greater than the specified duration, exponentially backing off between requests using the
|
||||
// supplied backoff time.Duration (which may be zero). Retrying may be canceled by closing the
|
||||
// optional channel on the http.Request.
|
||||
func DoRetryForDuration(d time.Duration, backoff time.Duration) SendDecorator {
|
||||
return func(s Sender) Sender {
|
||||
return SenderFunc(func(r *http.Request) (resp *http.Response, err error) {
|
||||
rr := NewRetriableRequest(r)
|
||||
end := time.Now().Add(d)
|
||||
for attempt := 0; time.Now().Before(end); attempt++ {
|
||||
err = rr.Prepare()
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
resp, err = s.Do(rr.Request())
|
||||
if err == nil {
|
||||
return resp, err
|
||||
}
|
||||
if !DelayForBackoff(backoff, attempt, r.Context().Done()) {
|
||||
return nil, r.Context().Err()
|
||||
}
|
||||
}
|
||||
return resp, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// WithLogging returns a SendDecorator that implements simple before and after logging of the
|
||||
// request.
|
||||
func WithLogging(logger *log.Logger) SendDecorator {
|
||||
return func(s Sender) Sender {
|
||||
return SenderFunc(func(r *http.Request) (*http.Response, error) {
|
||||
logger.Printf("Sending %s %s", r.Method, r.URL)
|
||||
resp, err := s.Do(r)
|
||||
if err != nil {
|
||||
logger.Printf("%s %s received error '%v'", r.Method, r.URL, err)
|
||||
} else {
|
||||
logger.Printf("%s %s received %s", r.Method, r.URL, resp.Status)
|
||||
}
|
||||
return resp, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// DelayForBackoff invokes time.After for the supplied backoff duration raised to the power of
|
||||
// passed attempt (i.e., an exponential backoff delay). Backoff duration is in seconds and can set
|
||||
// to zero for no delay. The delay may be canceled by closing the passed channel. If terminated early,
|
||||
// returns false.
|
||||
// Note: Passing attempt 1 will result in doubling "backoff" duration. Treat this as a zero-based attempt
|
||||
// count.
|
||||
func DelayForBackoff(backoff time.Duration, attempt int, cancel <-chan struct{}) bool {
|
||||
select {
|
||||
case <-time.After(time.Duration(backoff.Seconds()*math.Pow(2, float64(attempt))) * time.Second):
|
||||
return true
|
||||
case <-cancel:
|
||||
return false
|
||||
}
|
||||
}
|
||||
147
vendor/github.com/Azure/go-autorest/autorest/to/convert.go
generated
vendored
Normal file
147
vendor/github.com/Azure/go-autorest/autorest/to/convert.go
generated
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
Package to provides helpers to ease working with pointer values of marshalled structures.
|
||||
*/
|
||||
package to
|
||||
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// String returns a string value for the passed string pointer. It returns the empty string if the
|
||||
// pointer is nil.
|
||||
func String(s *string) string {
|
||||
if s != nil {
|
||||
return *s
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// StringPtr returns a pointer to the passed string.
|
||||
func StringPtr(s string) *string {
|
||||
return &s
|
||||
}
|
||||
|
||||
// StringSlice returns a string slice value for the passed string slice pointer. It returns a nil
|
||||
// slice if the pointer is nil.
|
||||
func StringSlice(s *[]string) []string {
|
||||
if s != nil {
|
||||
return *s
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// StringSlicePtr returns a pointer to the passed string slice.
|
||||
func StringSlicePtr(s []string) *[]string {
|
||||
return &s
|
||||
}
|
||||
|
||||
// StringMap returns a map of strings built from the map of string pointers. The empty string is
|
||||
// used for nil pointers.
|
||||
func StringMap(msp map[string]*string) map[string]string {
|
||||
ms := make(map[string]string, len(msp))
|
||||
for k, sp := range msp {
|
||||
if sp != nil {
|
||||
ms[k] = *sp
|
||||
} else {
|
||||
ms[k] = ""
|
||||
}
|
||||
}
|
||||
return ms
|
||||
}
|
||||
|
||||
// StringMapPtr returns a pointer to a map of string pointers built from the passed map of strings.
|
||||
func StringMapPtr(ms map[string]string) *map[string]*string {
|
||||
msp := make(map[string]*string, len(ms))
|
||||
for k, s := range ms {
|
||||
msp[k] = StringPtr(s)
|
||||
}
|
||||
return &msp
|
||||
}
|
||||
|
||||
// Bool returns a bool value for the passed bool pointer. It returns false if the pointer is nil.
|
||||
func Bool(b *bool) bool {
|
||||
if b != nil {
|
||||
return *b
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// BoolPtr returns a pointer to the passed bool.
|
||||
func BoolPtr(b bool) *bool {
|
||||
return &b
|
||||
}
|
||||
|
||||
// Int returns an int value for the passed int pointer. It returns 0 if the pointer is nil.
|
||||
func Int(i *int) int {
|
||||
if i != nil {
|
||||
return *i
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// IntPtr returns a pointer to the passed int.
|
||||
func IntPtr(i int) *int {
|
||||
return &i
|
||||
}
|
||||
|
||||
// Int32 returns an int value for the passed int pointer. It returns 0 if the pointer is nil.
|
||||
func Int32(i *int32) int32 {
|
||||
if i != nil {
|
||||
return *i
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Int32Ptr returns a pointer to the passed int32.
|
||||
func Int32Ptr(i int32) *int32 {
|
||||
return &i
|
||||
}
|
||||
|
||||
// Int64 returns an int value for the passed int pointer. It returns 0 if the pointer is nil.
|
||||
func Int64(i *int64) int64 {
|
||||
if i != nil {
|
||||
return *i
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Int64Ptr returns a pointer to the passed int64.
|
||||
func Int64Ptr(i int64) *int64 {
|
||||
return &i
|
||||
}
|
||||
|
||||
// Float32 returns an int value for the passed int pointer. It returns 0.0 if the pointer is nil.
|
||||
func Float32(i *float32) float32 {
|
||||
if i != nil {
|
||||
return *i
|
||||
}
|
||||
return 0.0
|
||||
}
|
||||
|
||||
// Float32Ptr returns a pointer to the passed float32.
|
||||
func Float32Ptr(i float32) *float32 {
|
||||
return &i
|
||||
}
|
||||
|
||||
// Float64 returns an int value for the passed int pointer. It returns 0.0 if the pointer is nil.
|
||||
func Float64(i *float64) float64 {
|
||||
if i != nil {
|
||||
return *i
|
||||
}
|
||||
return 0.0
|
||||
}
|
||||
|
||||
// Float64Ptr returns a pointer to the passed float64.
|
||||
func Float64Ptr(i float64) *float64 {
|
||||
return &i
|
||||
}
|
||||
227
vendor/github.com/Azure/go-autorest/autorest/utility.go
generated
vendored
Normal file
227
vendor/github.com/Azure/go-autorest/autorest/utility.go
generated
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
package autorest
|
||||
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/go-autorest/autorest/adal"
|
||||
)
|
||||
|
||||
// EncodedAs is a series of constants specifying various data encodings
|
||||
type EncodedAs string
|
||||
|
||||
const (
|
||||
// EncodedAsJSON states that data is encoded as JSON
|
||||
EncodedAsJSON EncodedAs = "JSON"
|
||||
|
||||
// EncodedAsXML states that data is encoded as Xml
|
||||
EncodedAsXML EncodedAs = "XML"
|
||||
)
|
||||
|
||||
// Decoder defines the decoding method json.Decoder and xml.Decoder share
|
||||
type Decoder interface {
|
||||
Decode(v interface{}) error
|
||||
}
|
||||
|
||||
// NewDecoder creates a new decoder appropriate to the passed encoding.
|
||||
// encodedAs specifies the type of encoding and r supplies the io.Reader containing the
|
||||
// encoded data.
|
||||
func NewDecoder(encodedAs EncodedAs, r io.Reader) Decoder {
|
||||
if encodedAs == EncodedAsJSON {
|
||||
return json.NewDecoder(r)
|
||||
} else if encodedAs == EncodedAsXML {
|
||||
return xml.NewDecoder(r)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CopyAndDecode decodes the data from the passed io.Reader while making a copy. Having a copy
|
||||
// is especially useful if there is a chance the data will fail to decode.
|
||||
// encodedAs specifies the expected encoding, r provides the io.Reader to the data, and v
|
||||
// is the decoding destination.
|
||||
func CopyAndDecode(encodedAs EncodedAs, r io.Reader, v interface{}) (bytes.Buffer, error) {
|
||||
b := bytes.Buffer{}
|
||||
return b, NewDecoder(encodedAs, io.TeeReader(r, &b)).Decode(v)
|
||||
}
|
||||
|
||||
// TeeReadCloser returns a ReadCloser that writes to w what it reads from rc.
|
||||
// It utilizes io.TeeReader to copy the data read and has the same behavior when reading.
|
||||
// Further, when it is closed, it ensures that rc is closed as well.
|
||||
func TeeReadCloser(rc io.ReadCloser, w io.Writer) io.ReadCloser {
|
||||
return &teeReadCloser{rc, io.TeeReader(rc, w)}
|
||||
}
|
||||
|
||||
type teeReadCloser struct {
|
||||
rc io.ReadCloser
|
||||
r io.Reader
|
||||
}
|
||||
|
||||
func (t *teeReadCloser) Read(p []byte) (int, error) {
|
||||
return t.r.Read(p)
|
||||
}
|
||||
|
||||
func (t *teeReadCloser) Close() error {
|
||||
return t.rc.Close()
|
||||
}
|
||||
|
||||
func containsInt(ints []int, n int) bool {
|
||||
for _, i := range ints {
|
||||
if i == n {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func escapeValueStrings(m map[string]string) map[string]string {
|
||||
for key, value := range m {
|
||||
m[key] = url.QueryEscape(value)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func ensureValueStrings(mapOfInterface map[string]interface{}) map[string]string {
|
||||
mapOfStrings := make(map[string]string)
|
||||
for key, value := range mapOfInterface {
|
||||
mapOfStrings[key] = ensureValueString(value)
|
||||
}
|
||||
return mapOfStrings
|
||||
}
|
||||
|
||||
func ensureValueString(value interface{}) string {
|
||||
if value == nil {
|
||||
return ""
|
||||
}
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
return v
|
||||
case []byte:
|
||||
return string(v)
|
||||
default:
|
||||
return fmt.Sprintf("%v", v)
|
||||
}
|
||||
}
|
||||
|
||||
// MapToValues method converts map[string]interface{} to url.Values.
|
||||
func MapToValues(m map[string]interface{}) url.Values {
|
||||
v := url.Values{}
|
||||
for key, value := range m {
|
||||
x := reflect.ValueOf(value)
|
||||
if x.Kind() == reflect.Array || x.Kind() == reflect.Slice {
|
||||
for i := 0; i < x.Len(); i++ {
|
||||
v.Add(key, ensureValueString(x.Index(i)))
|
||||
}
|
||||
} else {
|
||||
v.Add(key, ensureValueString(value))
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// AsStringSlice method converts interface{} to []string. This expects a
|
||||
//that the parameter passed to be a slice or array of a type that has the underlying
|
||||
//type a string.
|
||||
func AsStringSlice(s interface{}) ([]string, error) {
|
||||
v := reflect.ValueOf(s)
|
||||
if v.Kind() != reflect.Slice && v.Kind() != reflect.Array {
|
||||
return nil, NewError("autorest", "AsStringSlice", "the value's type is not an array.")
|
||||
}
|
||||
stringSlice := make([]string, 0, v.Len())
|
||||
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
stringSlice = append(stringSlice, v.Index(i).String())
|
||||
}
|
||||
return stringSlice, nil
|
||||
}
|
||||
|
||||
// String method converts interface v to string. If interface is a list, it
|
||||
// joins list elements using the seperator. Note that only sep[0] will be used for
|
||||
// joining if any separator is specified.
|
||||
func String(v interface{}, sep ...string) string {
|
||||
if len(sep) == 0 {
|
||||
return ensureValueString(v)
|
||||
}
|
||||
stringSlice, ok := v.([]string)
|
||||
if ok == false {
|
||||
var err error
|
||||
stringSlice, err = AsStringSlice(v)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("autorest: Couldn't convert value to a string %s.", err))
|
||||
}
|
||||
}
|
||||
return ensureValueString(strings.Join(stringSlice, sep[0]))
|
||||
}
|
||||
|
||||
// Encode method encodes url path and query parameters.
|
||||
func Encode(location string, v interface{}, sep ...string) string {
|
||||
s := String(v, sep...)
|
||||
switch strings.ToLower(location) {
|
||||
case "path":
|
||||
return pathEscape(s)
|
||||
case "query":
|
||||
return queryEscape(s)
|
||||
default:
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
func pathEscape(s string) string {
|
||||
return strings.Replace(url.QueryEscape(s), "+", "%20", -1)
|
||||
}
|
||||
|
||||
func queryEscape(s string) string {
|
||||
return url.QueryEscape(s)
|
||||
}
|
||||
|
||||
// ChangeToGet turns the specified http.Request into a GET (it assumes it wasn't).
|
||||
// This is mainly useful for long-running operations that use the Azure-AsyncOperation
|
||||
// header, so we change the initial PUT into a GET to retrieve the final result.
|
||||
func ChangeToGet(req *http.Request) *http.Request {
|
||||
req.Method = "GET"
|
||||
req.Body = nil
|
||||
req.ContentLength = 0
|
||||
req.Header.Del("Content-Length")
|
||||
return req
|
||||
}
|
||||
|
||||
// IsTokenRefreshError returns true if the specified error implements the TokenRefreshError
|
||||
// interface. If err is a DetailedError it will walk the chain of Original errors.
|
||||
func IsTokenRefreshError(err error) bool {
|
||||
if _, ok := err.(adal.TokenRefreshError); ok {
|
||||
return true
|
||||
}
|
||||
if de, ok := err.(DetailedError); ok {
|
||||
return IsTokenRefreshError(de.Original)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsTemporaryNetworkError returns true if the specified error is a temporary network error.
|
||||
func IsTemporaryNetworkError(err error) bool {
|
||||
if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
48
vendor/github.com/Azure/go-autorest/autorest/validation/error.go
generated
vendored
Normal file
48
vendor/github.com/Azure/go-autorest/autorest/validation/error.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
package validation
|
||||
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Error is the type that's returned when the validation of an APIs arguments constraints fails.
|
||||
type Error struct {
|
||||
// PackageType is the package type of the object emitting the error. For types, the value
|
||||
// matches that produced the the '%T' format specifier of the fmt package. For other elements,
|
||||
// such as functions, it is just the package name (e.g., "autorest").
|
||||
PackageType string
|
||||
|
||||
// Method is the name of the method raising the error.
|
||||
Method string
|
||||
|
||||
// Message is the error message.
|
||||
Message string
|
||||
}
|
||||
|
||||
// Error returns a string containing the details of the validation failure.
|
||||
func (e Error) Error() string {
|
||||
return fmt.Sprintf("%s#%s: Invalid input: %s", e.PackageType, e.Method, e.Message)
|
||||
}
|
||||
|
||||
// NewError creates a new Error object with the specified parameters.
|
||||
// message is treated as a format string to which the optional args apply.
|
||||
func NewError(packageType string, method string, message string, args ...interface{}) Error {
|
||||
return Error{
|
||||
PackageType: packageType,
|
||||
Method: method,
|
||||
Message: fmt.Sprintf(message, args...),
|
||||
}
|
||||
}
|
||||
397
vendor/github.com/Azure/go-autorest/autorest/validation/validation.go
generated
vendored
Normal file
397
vendor/github.com/Azure/go-autorest/autorest/validation/validation.go
generated
vendored
Normal file
@@ -0,0 +1,397 @@
|
||||
/*
|
||||
Package validation provides methods for validating parameter value using reflection.
|
||||
*/
|
||||
package validation
|
||||
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Constraint stores constraint name, target field name
|
||||
// Rule and chain validations.
|
||||
type Constraint struct {
|
||||
|
||||
// Target field name for validation.
|
||||
Target string
|
||||
|
||||
// Constraint name e.g. minLength, MaxLength, Pattern, etc.
|
||||
Name string
|
||||
|
||||
// Rule for constraint e.g. greater than 10, less than 5 etc.
|
||||
Rule interface{}
|
||||
|
||||
// Chain Validations for struct type
|
||||
Chain []Constraint
|
||||
}
|
||||
|
||||
// Validation stores parameter-wise validation.
|
||||
type Validation struct {
|
||||
TargetValue interface{}
|
||||
Constraints []Constraint
|
||||
}
|
||||
|
||||
// Constraint list
|
||||
const (
|
||||
Empty = "Empty"
|
||||
Null = "Null"
|
||||
ReadOnly = "ReadOnly"
|
||||
Pattern = "Pattern"
|
||||
MaxLength = "MaxLength"
|
||||
MinLength = "MinLength"
|
||||
MaxItems = "MaxItems"
|
||||
MinItems = "MinItems"
|
||||
MultipleOf = "MultipleOf"
|
||||
UniqueItems = "UniqueItems"
|
||||
InclusiveMaximum = "InclusiveMaximum"
|
||||
ExclusiveMaximum = "ExclusiveMaximum"
|
||||
ExclusiveMinimum = "ExclusiveMinimum"
|
||||
InclusiveMinimum = "InclusiveMinimum"
|
||||
)
|
||||
|
||||
// Validate method validates constraints on parameter
|
||||
// passed in validation array.
|
||||
func Validate(m []Validation) error {
|
||||
for _, item := range m {
|
||||
v := reflect.ValueOf(item.TargetValue)
|
||||
for _, constraint := range item.Constraints {
|
||||
var err error
|
||||
switch v.Kind() {
|
||||
case reflect.Ptr:
|
||||
err = validatePtr(v, constraint)
|
||||
case reflect.String:
|
||||
err = validateString(v, constraint)
|
||||
case reflect.Struct:
|
||||
err = validateStruct(v, constraint)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
err = validateInt(v, constraint)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
err = validateFloat(v, constraint)
|
||||
case reflect.Array, reflect.Slice, reflect.Map:
|
||||
err = validateArrayMap(v, constraint)
|
||||
default:
|
||||
err = createError(v, constraint, fmt.Sprintf("unknown type %v", v.Kind()))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateStruct(x reflect.Value, v Constraint, name ...string) error {
|
||||
//Get field name from target name which is in format a.b.c
|
||||
s := strings.Split(v.Target, ".")
|
||||
f := x.FieldByName(s[len(s)-1])
|
||||
if isZero(f) {
|
||||
return createError(x, v, fmt.Sprintf("field %q doesn't exist", v.Target))
|
||||
}
|
||||
|
||||
return Validate([]Validation{
|
||||
{
|
||||
TargetValue: getInterfaceValue(f),
|
||||
Constraints: []Constraint{v},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func validatePtr(x reflect.Value, v Constraint) error {
|
||||
if v.Name == ReadOnly {
|
||||
if !x.IsNil() {
|
||||
return createError(x.Elem(), v, "readonly parameter; must send as nil or empty in request")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if x.IsNil() {
|
||||
return checkNil(x, v)
|
||||
}
|
||||
if v.Chain != nil {
|
||||
return Validate([]Validation{
|
||||
{
|
||||
TargetValue: getInterfaceValue(x.Elem()),
|
||||
Constraints: v.Chain,
|
||||
},
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateInt(x reflect.Value, v Constraint) error {
|
||||
i := x.Int()
|
||||
r, ok := v.Rule.(int)
|
||||
if !ok {
|
||||
return createError(x, v, fmt.Sprintf("rule must be integer value for %v constraint; got: %v", v.Name, v.Rule))
|
||||
}
|
||||
switch v.Name {
|
||||
case MultipleOf:
|
||||
if i%int64(r) != 0 {
|
||||
return createError(x, v, fmt.Sprintf("value must be a multiple of %v", r))
|
||||
}
|
||||
case ExclusiveMinimum:
|
||||
if i <= int64(r) {
|
||||
return createError(x, v, fmt.Sprintf("value must be greater than %v", r))
|
||||
}
|
||||
case ExclusiveMaximum:
|
||||
if i >= int64(r) {
|
||||
return createError(x, v, fmt.Sprintf("value must be less than %v", r))
|
||||
}
|
||||
case InclusiveMinimum:
|
||||
if i < int64(r) {
|
||||
return createError(x, v, fmt.Sprintf("value must be greater than or equal to %v", r))
|
||||
}
|
||||
case InclusiveMaximum:
|
||||
if i > int64(r) {
|
||||
return createError(x, v, fmt.Sprintf("value must be less than or equal to %v", r))
|
||||
}
|
||||
default:
|
||||
return createError(x, v, fmt.Sprintf("constraint %v is not applicable for type integer", v.Name))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateFloat(x reflect.Value, v Constraint) error {
|
||||
f := x.Float()
|
||||
r, ok := v.Rule.(float64)
|
||||
if !ok {
|
||||
return createError(x, v, fmt.Sprintf("rule must be float value for %v constraint; got: %v", v.Name, v.Rule))
|
||||
}
|
||||
switch v.Name {
|
||||
case ExclusiveMinimum:
|
||||
if f <= r {
|
||||
return createError(x, v, fmt.Sprintf("value must be greater than %v", r))
|
||||
}
|
||||
case ExclusiveMaximum:
|
||||
if f >= r {
|
||||
return createError(x, v, fmt.Sprintf("value must be less than %v", r))
|
||||
}
|
||||
case InclusiveMinimum:
|
||||
if f < r {
|
||||
return createError(x, v, fmt.Sprintf("value must be greater than or equal to %v", r))
|
||||
}
|
||||
case InclusiveMaximum:
|
||||
if f > r {
|
||||
return createError(x, v, fmt.Sprintf("value must be less than or equal to %v", r))
|
||||
}
|
||||
default:
|
||||
return createError(x, v, fmt.Sprintf("constraint %s is not applicable for type float", v.Name))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateString(x reflect.Value, v Constraint) error {
|
||||
s := x.String()
|
||||
switch v.Name {
|
||||
case Empty:
|
||||
if len(s) == 0 {
|
||||
return checkEmpty(x, v)
|
||||
}
|
||||
case Pattern:
|
||||
reg, err := regexp.Compile(v.Rule.(string))
|
||||
if err != nil {
|
||||
return createError(x, v, err.Error())
|
||||
}
|
||||
if !reg.MatchString(s) {
|
||||
return createError(x, v, fmt.Sprintf("value doesn't match pattern %v", v.Rule))
|
||||
}
|
||||
case MaxLength:
|
||||
if _, ok := v.Rule.(int); !ok {
|
||||
return createError(x, v, fmt.Sprintf("rule must be integer value for %v constraint; got: %v", v.Name, v.Rule))
|
||||
}
|
||||
if len(s) > v.Rule.(int) {
|
||||
return createError(x, v, fmt.Sprintf("value length must be less than or equal to %v", v.Rule))
|
||||
}
|
||||
case MinLength:
|
||||
if _, ok := v.Rule.(int); !ok {
|
||||
return createError(x, v, fmt.Sprintf("rule must be integer value for %v constraint; got: %v", v.Name, v.Rule))
|
||||
}
|
||||
if len(s) < v.Rule.(int) {
|
||||
return createError(x, v, fmt.Sprintf("value length must be greater than or equal to %v", v.Rule))
|
||||
}
|
||||
case ReadOnly:
|
||||
if len(s) > 0 {
|
||||
return createError(reflect.ValueOf(s), v, "readonly parameter; must send as nil or empty in request")
|
||||
}
|
||||
default:
|
||||
return createError(x, v, fmt.Sprintf("constraint %s is not applicable to string type", v.Name))
|
||||
}
|
||||
|
||||
if v.Chain != nil {
|
||||
return Validate([]Validation{
|
||||
{
|
||||
TargetValue: getInterfaceValue(x),
|
||||
Constraints: v.Chain,
|
||||
},
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateArrayMap(x reflect.Value, v Constraint) error {
|
||||
switch v.Name {
|
||||
case Null:
|
||||
if x.IsNil() {
|
||||
return checkNil(x, v)
|
||||
}
|
||||
case Empty:
|
||||
if x.IsNil() || x.Len() == 0 {
|
||||
return checkEmpty(x, v)
|
||||
}
|
||||
case MaxItems:
|
||||
if _, ok := v.Rule.(int); !ok {
|
||||
return createError(x, v, fmt.Sprintf("rule must be integer for %v constraint; got: %v", v.Name, v.Rule))
|
||||
}
|
||||
if x.Len() > v.Rule.(int) {
|
||||
return createError(x, v, fmt.Sprintf("maximum item limit is %v; got: %v", v.Rule, x.Len()))
|
||||
}
|
||||
case MinItems:
|
||||
if _, ok := v.Rule.(int); !ok {
|
||||
return createError(x, v, fmt.Sprintf("rule must be integer for %v constraint; got: %v", v.Name, v.Rule))
|
||||
}
|
||||
if x.Len() < v.Rule.(int) {
|
||||
return createError(x, v, fmt.Sprintf("minimum item limit is %v; got: %v", v.Rule, x.Len()))
|
||||
}
|
||||
case UniqueItems:
|
||||
if x.Kind() == reflect.Array || x.Kind() == reflect.Slice {
|
||||
if !checkForUniqueInArray(x) {
|
||||
return createError(x, v, fmt.Sprintf("all items in parameter %q must be unique; got:%v", v.Target, x))
|
||||
}
|
||||
} else if x.Kind() == reflect.Map {
|
||||
if !checkForUniqueInMap(x) {
|
||||
return createError(x, v, fmt.Sprintf("all items in parameter %q must be unique; got:%v", v.Target, x))
|
||||
}
|
||||
} else {
|
||||
return createError(x, v, fmt.Sprintf("type must be array, slice or map for constraint %v; got: %v", v.Name, x.Kind()))
|
||||
}
|
||||
case ReadOnly:
|
||||
if x.Len() != 0 {
|
||||
return createError(x, v, "readonly parameter; must send as nil or empty in request")
|
||||
}
|
||||
case Pattern:
|
||||
reg, err := regexp.Compile(v.Rule.(string))
|
||||
if err != nil {
|
||||
return createError(x, v, err.Error())
|
||||
}
|
||||
keys := x.MapKeys()
|
||||
for _, k := range keys {
|
||||
if !reg.MatchString(k.String()) {
|
||||
return createError(k, v, fmt.Sprintf("map key doesn't match pattern %v", v.Rule))
|
||||
}
|
||||
}
|
||||
default:
|
||||
return createError(x, v, fmt.Sprintf("constraint %v is not applicable to array, slice and map type", v.Name))
|
||||
}
|
||||
|
||||
if v.Chain != nil {
|
||||
return Validate([]Validation{
|
||||
{
|
||||
TargetValue: getInterfaceValue(x),
|
||||
Constraints: v.Chain,
|
||||
},
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkNil(x reflect.Value, v Constraint) error {
|
||||
if _, ok := v.Rule.(bool); !ok {
|
||||
return createError(x, v, fmt.Sprintf("rule must be bool value for %v constraint; got: %v", v.Name, v.Rule))
|
||||
}
|
||||
if v.Rule.(bool) {
|
||||
return createError(x, v, "value can not be null; required parameter")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkEmpty(x reflect.Value, v Constraint) error {
|
||||
if _, ok := v.Rule.(bool); !ok {
|
||||
return createError(x, v, fmt.Sprintf("rule must be bool value for %v constraint; got: %v", v.Name, v.Rule))
|
||||
}
|
||||
|
||||
if v.Rule.(bool) {
|
||||
return createError(x, v, "value can not be null or empty; required parameter")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkForUniqueInArray(x reflect.Value) bool {
|
||||
if x == reflect.Zero(reflect.TypeOf(x)) || x.Len() == 0 {
|
||||
return false
|
||||
}
|
||||
arrOfInterface := make([]interface{}, x.Len())
|
||||
|
||||
for i := 0; i < x.Len(); i++ {
|
||||
arrOfInterface[i] = x.Index(i).Interface()
|
||||
}
|
||||
|
||||
m := make(map[interface{}]bool)
|
||||
for _, val := range arrOfInterface {
|
||||
if m[val] {
|
||||
return false
|
||||
}
|
||||
m[val] = true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func checkForUniqueInMap(x reflect.Value) bool {
|
||||
if x == reflect.Zero(reflect.TypeOf(x)) || x.Len() == 0 {
|
||||
return false
|
||||
}
|
||||
mapOfInterface := make(map[interface{}]interface{}, x.Len())
|
||||
|
||||
keys := x.MapKeys()
|
||||
for _, k := range keys {
|
||||
mapOfInterface[k.Interface()] = x.MapIndex(k).Interface()
|
||||
}
|
||||
|
||||
m := make(map[interface{}]bool)
|
||||
for _, val := range mapOfInterface {
|
||||
if m[val] {
|
||||
return false
|
||||
}
|
||||
m[val] = true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func getInterfaceValue(x reflect.Value) interface{} {
|
||||
if x.Kind() == reflect.Invalid {
|
||||
return nil
|
||||
}
|
||||
return x.Interface()
|
||||
}
|
||||
|
||||
func isZero(x interface{}) bool {
|
||||
return x == reflect.Zero(reflect.TypeOf(x)).Interface()
|
||||
}
|
||||
|
||||
func createError(x reflect.Value, v Constraint, err string) error {
|
||||
return fmt.Errorf("autorest/validation: validation failed: parameter=%s constraint=%s value=%#v details: %s",
|
||||
v.Target, v.Name, getInterfaceValue(x), err)
|
||||
}
|
||||
|
||||
// NewErrorWithValidationError appends package type and method name in
|
||||
// validation error.
|
||||
//
|
||||
// Deprecated: Please use validation.NewError() instead.
|
||||
func NewErrorWithValidationError(err error, packageType, method string) error {
|
||||
return NewError(packageType, method, err.Error())
|
||||
}
|
||||
20
vendor/github.com/Azure/go-autorest/autorest/version.go
generated
vendored
Normal file
20
vendor/github.com/Azure/go-autorest/autorest/version.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
package autorest
|
||||
|
||||
// Copyright 2017 Microsoft Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Version returns the semantic version (see http://semver.org).
|
||||
func Version() string {
|
||||
return "v10.8.1"
|
||||
}
|
||||
21
vendor/github.com/lawrencegripper/pod2docker/LICENSE
generated
vendored
Normal file
21
vendor/github.com/lawrencegripper/pod2docker/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Lawrence Gripper
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
105
vendor/github.com/lawrencegripper/pod2docker/pod2docker.go
generated
vendored
Normal file
105
vendor/github.com/lawrencegripper/pod2docker/pod2docker.go
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
package pod2docker
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
// ImageRegistryCredential - Used to input a credential used by docker login
|
||||
type ImageRegistryCredential struct {
|
||||
Server string `json:"server,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
}
|
||||
|
||||
// PodComponents provides details to run a pod
|
||||
type PodComponents struct {
|
||||
PullCredentials []ImageRegistryCredential
|
||||
InitContainers []v1.Container
|
||||
Containers []v1.Container
|
||||
Volumes []v1.Volume
|
||||
PodName string
|
||||
}
|
||||
|
||||
// GetBashCommand generates the bash script to execute the pod
|
||||
func GetBashCommand(p PodComponents) (string, error) {
|
||||
template := template.New("run.sh.tmpl").Option("missingkey=error").Funcs(template.FuncMap{
|
||||
"getLaunchCommand": getLaunchCommand,
|
||||
"isHostPathVolume": isHostPathVolume,
|
||||
"isEmptyDirVolume": isEmptyDirVolume,
|
||||
"isPullAlways": isPullAlways,
|
||||
"getValidVolumeMounts": getValidVolumeMounts,
|
||||
"isNvidiaRuntime": isNvidiaRuntime,
|
||||
})
|
||||
|
||||
template, err := template.Parse(azureBatchPodTemplate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var output bytes.Buffer
|
||||
err = template.Execute(&output, p)
|
||||
return output.String(), err
|
||||
}
|
||||
|
||||
func getLaunchCommand(container v1.Container) (cmd string) {
|
||||
if len(container.Command) > 0 {
|
||||
cmd += strings.Join(container.Command, " ")
|
||||
}
|
||||
if len(cmd) > 0 {
|
||||
cmd += " "
|
||||
}
|
||||
if len(container.Args) > 0 {
|
||||
cmd += strings.Join(container.Args, " ")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func isNvidiaRuntime(c v1.Container) bool {
|
||||
if _, exists := c.Resources.Limits["nvidia.com/gpu"]; exists {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isHostPathVolume(v v1.Volume) bool {
|
||||
if v.HostPath == nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func isEmptyDirVolume(v v1.Volume) bool {
|
||||
if v.EmptyDir == nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func isPullAlways(c v1.Container) bool {
|
||||
if c.ImagePullPolicy == v1.PullAlways {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func getValidVolumeMounts(container v1.Container, volumes []v1.Volume) []v1.VolumeMount {
|
||||
volDic := make(map[string]v1.Volume)
|
||||
for _, vol := range volumes {
|
||||
volDic[vol.Name] = vol
|
||||
}
|
||||
var mounts []v1.VolumeMount
|
||||
for _, mount := range container.VolumeMounts {
|
||||
vol, ok := volDic[mount.Name]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if vol.EmptyDir == nil && vol.HostPath == nil {
|
||||
continue
|
||||
}
|
||||
mounts = append(mounts, mount)
|
||||
}
|
||||
return mounts
|
||||
}
|
||||
167
vendor/github.com/lawrencegripper/pod2docker/pod2docker_template.go
generated
vendored
Normal file
167
vendor/github.com/lawrencegripper/pod2docker/pod2docker_template.go
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
package pod2docker
|
||||
|
||||
// Todo: Investigate a better way to inline this template - especially when escaping the backticks.
|
||||
// Consider: https://mattjibson.com/blog/2014/11/19/esc-embedding-static-assets/
|
||||
const azureBatchPodTemplate = `
|
||||
#!/bin/bash
|
||||
set -eE
|
||||
trap cleanup EXIT
|
||||
|
||||
if ! type 'docker' > /dev/null; then
|
||||
echo 'Docker not installed... exiting'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
{{/* Vars */}}
|
||||
{{$podName := .PodName}}
|
||||
{{$volumes := .Volumes}}
|
||||
|
||||
{{/* Login to required image repositories */}}
|
||||
{{range .PullCredentials }}
|
||||
docker login -u {{.Username}} -p {{.Password}} {{.Server}}
|
||||
{{end}}
|
||||
|
||||
function cleanup(){
|
||||
{{/* Take a copy of the container log is removed when container is deleted */}}
|
||||
echo 'Pod Exited: Copying logs'
|
||||
{{range $index, $container := .InitContainers}}
|
||||
if [[ -f ./initcontainer-{{$index}}.cid ]]; then
|
||||
container_{{$index}}_ID=$(<./initcontainer-{{$index}}.cid)
|
||||
container_{{$index}}_Log_Path=$(docker inspect --format='{{"{{.LogPath}}"}}' $container_{{$index}}_ID)
|
||||
cp $container_{{$index}}_Log_Path ./{{$container.Name}}.log
|
||||
|
||||
docker rm -f $container_{{$index}}_ID
|
||||
rm -f ./initcontainer-{{$index}}.cid
|
||||
fi
|
||||
{{end}}
|
||||
|
||||
{{range $index, $container := .Containers}}
|
||||
if [[ -f ./{{$container.Name}}.log && -f ./container-{{$index}}.cid ]]; then
|
||||
container_{{$index}}_ID=$(<./container-{{$index}}.cid)
|
||||
container_{{$index}}_Log_Path=$(docker inspect --format='{{"{{.LogPath}}"}}' $container_{{$index}}_ID)
|
||||
rm ./{{$container.Name}}.log {{/* Remove the existing symlink */}}
|
||||
cp $container_{{$index}}_Log_Path ./{{$container.Name}}.log
|
||||
fi
|
||||
{{end}}
|
||||
|
||||
{{/* Remove the containers, network and volumes */}}
|
||||
|
||||
echo 'Pod Exited: Removing all containers'
|
||||
if ls container-* 1> /dev/null 2>&1; then
|
||||
for line in ` + "`ls container-*`" + `
|
||||
do
|
||||
id=$(cat $line)
|
||||
echo '-Logs container..'
|
||||
docker logs $id
|
||||
echo '-Removing container..'
|
||||
docker rm -f $id
|
||||
rm -f $line
|
||||
done
|
||||
fi
|
||||
echo '-Removing pause container..'
|
||||
docker rm -f {{$podName}} || echo 'Remove pause container failed'
|
||||
rm -f ./pauseid.cid
|
||||
echo '-Removing network container..'
|
||||
docker network rm {{$podName}} || echo 'Remove network failed'
|
||||
|
||||
echo '-Removing volumes..'
|
||||
{{range .Volumes}}
|
||||
docker volume rm -f {{$podName}}_{{.Name}} || echo 'Remove volume failed'
|
||||
{{end}}
|
||||
}
|
||||
|
||||
{{/* Create Pod network and start it */}}
|
||||
docker network create {{$podName}}
|
||||
docker run -d --network {{$podName}} --name {{$podName}} --cidfile="./pauseid.cid" gcr.io/google_containers/pause:1.0
|
||||
|
||||
{{/* Handle volumes */}}
|
||||
{{range .Volumes}}
|
||||
{{if isHostPathVolume .}}
|
||||
docker volume create --name {{$podName}}_{{.Name}} --opt type=none --opt device={{.VolumeSource.HostPath.Path}} --opt o=bind
|
||||
{{end}}
|
||||
{{if isEmptyDirVolume .}}
|
||||
docker volume create {{$podName}}_{{.Name}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{/* Run the init containers in the Pod. Attaching to shared namespace */}}
|
||||
{{range $index, $container := .InitContainers}}
|
||||
echo 'Running init container {{$index}}..'
|
||||
{{if isPullAlways .}}
|
||||
docker pull {{$container.Image}}
|
||||
{{end}}
|
||||
docker run --network container:{{$podName}} --ipc container:{{$podName}} \
|
||||
{{- if isNvidiaRuntime $container}}
|
||||
--runtime nvidia \
|
||||
{{- end}}
|
||||
{{- range $index, $envs := $container.Env}}
|
||||
-e "{{$envs.Name}}:{{$envs.Value}}" \
|
||||
{{- end}}
|
||||
{{- range $index, $mount := getValidVolumeMounts $container $volumes}}
|
||||
-v {{$podName}}_{{$mount.Name}}:{{$mount.MountPath}} \
|
||||
{{- end}}
|
||||
--cidfile=./initcontainer-{{$index}}.cid {{$container.Image}} {{getLaunchCommand $container}}
|
||||
{{end}}
|
||||
|
||||
|
||||
{{/* Run the containers in the Pod. Attaching to shared namespace */}}
|
||||
{{range $index, $container := .Containers}}
|
||||
{{if isPullAlways .}}
|
||||
docker pull {{$container.Image}}
|
||||
{{end}}
|
||||
docker run -d --network container:{{$podName}} --ipc container:{{$podName}} \
|
||||
{{- if isNvidiaRuntime $container}}
|
||||
--runtime nvidia \
|
||||
{{- end}}
|
||||
{{- range $index, $envs := $container.Env}}
|
||||
-e "{{$envs.Name}}:{{$envs.Value}}" \
|
||||
{{- end}}
|
||||
{{- range $index, $mount := getValidVolumeMounts $container $volumes}}
|
||||
-v {{$podName}}_{{$mount.Name}}:{{$mount.MountPath}} \
|
||||
{{- end}}
|
||||
--cidfile=./container-{{$index}}.cid {{$container.Image}} {{getLaunchCommand $container}}
|
||||
{{end}}
|
||||
|
||||
{{/* Symlink all container logs files to task directory */}}
|
||||
{{range $index, $container := .Containers}}
|
||||
container_{{$index}}_ID=$(<./container-{{$index}}.cid)
|
||||
container_{{$index}}_Log_Path=$(docker inspect --format='{{"{{.LogPath}}"}}' $container_{{$index}}_ID)
|
||||
ln -f -s $container_{{$index}}_Log_Path ./{{$container.Name}}.log
|
||||
{{end}}
|
||||
|
||||
echo 'Running Pod: {{.PodName}}'
|
||||
|
||||
{{/* Wait until any of these containers stop */}}
|
||||
echo 'Waiting for any of the containers to exit'
|
||||
for line in ` + "`ls container-*`" + `
|
||||
do
|
||||
id=$(cat $line)
|
||||
docker wait $id &
|
||||
done
|
||||
|
||||
while [ $(jobs -p | wc -l) == {{.Containers | len}} ]
|
||||
do
|
||||
sleep 2
|
||||
done
|
||||
|
||||
|
||||
{{/* Get exit codes from containers */}}
|
||||
echo 'Checking container exit codes'
|
||||
overallExitCode=0
|
||||
for line in ` + "`ls container-*`" + `
|
||||
do
|
||||
id=$(cat $line)
|
||||
echo 'Getting exitcode'
|
||||
exitCode=$(docker inspect -f {{"{{.State.ExitCode}}"}} $id)
|
||||
|
||||
echo 'ID: ' $id ' ExitCode: ' $exitCode
|
||||
echo 'Checking exitcode'
|
||||
if (($exitCode != 0))
|
||||
then
|
||||
echo 'Assigning exitcode'
|
||||
overallExitCode=$exitCode
|
||||
fi
|
||||
done
|
||||
|
||||
exit $overallExitCode
|
||||
`
|
||||
20
vendor/github.com/satori/go.uuid/LICENSE
generated
vendored
Normal file
20
vendor/github.com/satori/go.uuid/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
206
vendor/github.com/satori/go.uuid/codec.go
generated
vendored
Normal file
206
vendor/github.com/satori/go.uuid/codec.go
generated
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
package uuid
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// FromBytes returns UUID converted from raw byte slice input.
|
||||
// It will return error if the slice isn't 16 bytes long.
|
||||
func FromBytes(input []byte) (u UUID, err error) {
|
||||
err = u.UnmarshalBinary(input)
|
||||
return
|
||||
}
|
||||
|
||||
// FromBytesOrNil returns UUID converted from raw byte slice input.
|
||||
// Same behavior as FromBytes, but returns a Nil UUID on error.
|
||||
func FromBytesOrNil(input []byte) UUID {
|
||||
uuid, err := FromBytes(input)
|
||||
if err != nil {
|
||||
return Nil
|
||||
}
|
||||
return uuid
|
||||
}
|
||||
|
||||
// FromString returns UUID parsed from string input.
|
||||
// Input is expected in a form accepted by UnmarshalText.
|
||||
func FromString(input string) (u UUID, err error) {
|
||||
err = u.UnmarshalText([]byte(input))
|
||||
return
|
||||
}
|
||||
|
||||
// FromStringOrNil returns UUID parsed from string input.
|
||||
// Same behavior as FromString, but returns a Nil UUID on error.
|
||||
func FromStringOrNil(input string) UUID {
|
||||
uuid, err := FromString(input)
|
||||
if err != nil {
|
||||
return Nil
|
||||
}
|
||||
return uuid
|
||||
}
|
||||
|
||||
// MarshalText implements the encoding.TextMarshaler interface.
|
||||
// The encoding is the same as returned by String.
|
||||
func (u UUID) MarshalText() (text []byte, err error) {
|
||||
text = []byte(u.String())
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalText implements the encoding.TextUnmarshaler interface.
|
||||
// Following formats are supported:
|
||||
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
|
||||
// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
|
||||
// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
|
||||
// "6ba7b8109dad11d180b400c04fd430c8"
|
||||
// ABNF for supported UUID text representation follows:
|
||||
// uuid := canonical | hashlike | braced | urn
|
||||
// plain := canonical | hashlike
|
||||
// canonical := 4hexoct '-' 2hexoct '-' 2hexoct '-' 6hexoct
|
||||
// hashlike := 12hexoct
|
||||
// braced := '{' plain '}'
|
||||
// urn := URN ':' UUID-NID ':' plain
|
||||
// URN := 'urn'
|
||||
// UUID-NID := 'uuid'
|
||||
// 12hexoct := 6hexoct 6hexoct
|
||||
// 6hexoct := 4hexoct 2hexoct
|
||||
// 4hexoct := 2hexoct 2hexoct
|
||||
// 2hexoct := hexoct hexoct
|
||||
// hexoct := hexdig hexdig
|
||||
// hexdig := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' |
|
||||
// 'a' | 'b' | 'c' | 'd' | 'e' | 'f' |
|
||||
// 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
|
||||
func (u *UUID) UnmarshalText(text []byte) (err error) {
|
||||
switch len(text) {
|
||||
case 32:
|
||||
return u.decodeHashLike(text)
|
||||
case 36:
|
||||
return u.decodeCanonical(text)
|
||||
case 38:
|
||||
return u.decodeBraced(text)
|
||||
case 41:
|
||||
fallthrough
|
||||
case 45:
|
||||
return u.decodeURN(text)
|
||||
default:
|
||||
return fmt.Errorf("uuid: incorrect UUID length: %s", text)
|
||||
}
|
||||
}
|
||||
|
||||
// decodeCanonical decodes UUID string in format
|
||||
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8".
|
||||
func (u *UUID) decodeCanonical(t []byte) (err error) {
|
||||
if t[8] != '-' || t[13] != '-' || t[18] != '-' || t[23] != '-' {
|
||||
return fmt.Errorf("uuid: incorrect UUID format %s", t)
|
||||
}
|
||||
|
||||
src := t[:]
|
||||
dst := u[:]
|
||||
|
||||
for i, byteGroup := range byteGroups {
|
||||
if i > 0 {
|
||||
src = src[1:] // skip dash
|
||||
}
|
||||
_, err = hex.Decode(dst[:byteGroup/2], src[:byteGroup])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
src = src[byteGroup:]
|
||||
dst = dst[byteGroup/2:]
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// decodeHashLike decodes UUID string in format
|
||||
// "6ba7b8109dad11d180b400c04fd430c8".
|
||||
func (u *UUID) decodeHashLike(t []byte) (err error) {
|
||||
src := t[:]
|
||||
dst := u[:]
|
||||
|
||||
if _, err = hex.Decode(dst, src); err != nil {
|
||||
return err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// decodeBraced decodes UUID string in format
|
||||
// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" or in format
|
||||
// "{6ba7b8109dad11d180b400c04fd430c8}".
|
||||
func (u *UUID) decodeBraced(t []byte) (err error) {
|
||||
l := len(t)
|
||||
|
||||
if t[0] != '{' || t[l-1] != '}' {
|
||||
return fmt.Errorf("uuid: incorrect UUID format %s", t)
|
||||
}
|
||||
|
||||
return u.decodePlain(t[1 : l-1])
|
||||
}
|
||||
|
||||
// decodeURN decodes UUID string in format
|
||||
// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" or in format
|
||||
// "urn:uuid:6ba7b8109dad11d180b400c04fd430c8".
|
||||
func (u *UUID) decodeURN(t []byte) (err error) {
|
||||
total := len(t)
|
||||
|
||||
urn_uuid_prefix := t[:9]
|
||||
|
||||
if !bytes.Equal(urn_uuid_prefix, urnPrefix) {
|
||||
return fmt.Errorf("uuid: incorrect UUID format: %s", t)
|
||||
}
|
||||
|
||||
return u.decodePlain(t[9:total])
|
||||
}
|
||||
|
||||
// decodePlain decodes UUID string in canonical format
|
||||
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8" or in hash-like format
|
||||
// "6ba7b8109dad11d180b400c04fd430c8".
|
||||
func (u *UUID) decodePlain(t []byte) (err error) {
|
||||
switch len(t) {
|
||||
case 32:
|
||||
return u.decodeHashLike(t)
|
||||
case 36:
|
||||
return u.decodeCanonical(t)
|
||||
default:
|
||||
return fmt.Errorf("uuid: incorrrect UUID length: %s", t)
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalBinary implements the encoding.BinaryMarshaler interface.
|
||||
func (u UUID) MarshalBinary() (data []byte, err error) {
|
||||
data = u.Bytes()
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
|
||||
// It will return error if the slice isn't 16 bytes long.
|
||||
func (u *UUID) UnmarshalBinary(data []byte) (err error) {
|
||||
if len(data) != Size {
|
||||
err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data))
|
||||
return
|
||||
}
|
||||
copy(u[:], data)
|
||||
|
||||
return
|
||||
}
|
||||
239
vendor/github.com/satori/go.uuid/generator.go
generated
vendored
Normal file
239
vendor/github.com/satori/go.uuid/generator.go
generated
vendored
Normal file
@@ -0,0 +1,239 @@
|
||||
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
package uuid
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"encoding/binary"
|
||||
"hash"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Difference in 100-nanosecond intervals between
|
||||
// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970).
|
||||
const epochStart = 122192928000000000
|
||||
|
||||
var (
|
||||
global = newDefaultGenerator()
|
||||
|
||||
epochFunc = unixTimeFunc
|
||||
posixUID = uint32(os.Getuid())
|
||||
posixGID = uint32(os.Getgid())
|
||||
)
|
||||
|
||||
// NewV1 returns UUID based on current timestamp and MAC address.
|
||||
func NewV1() UUID {
|
||||
return global.NewV1()
|
||||
}
|
||||
|
||||
// NewV2 returns DCE Security UUID based on POSIX UID/GID.
|
||||
func NewV2(domain byte) UUID {
|
||||
return global.NewV2(domain)
|
||||
}
|
||||
|
||||
// NewV3 returns UUID based on MD5 hash of namespace UUID and name.
|
||||
func NewV3(ns UUID, name string) UUID {
|
||||
return global.NewV3(ns, name)
|
||||
}
|
||||
|
||||
// NewV4 returns random generated UUID.
|
||||
func NewV4() UUID {
|
||||
return global.NewV4()
|
||||
}
|
||||
|
||||
// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
|
||||
func NewV5(ns UUID, name string) UUID {
|
||||
return global.NewV5(ns, name)
|
||||
}
|
||||
|
||||
// Generator provides interface for generating UUIDs.
|
||||
type Generator interface {
|
||||
NewV1() UUID
|
||||
NewV2(domain byte) UUID
|
||||
NewV3(ns UUID, name string) UUID
|
||||
NewV4() UUID
|
||||
NewV5(ns UUID, name string) UUID
|
||||
}
|
||||
|
||||
// Default generator implementation.
|
||||
type generator struct {
|
||||
storageOnce sync.Once
|
||||
storageMutex sync.Mutex
|
||||
|
||||
lastTime uint64
|
||||
clockSequence uint16
|
||||
hardwareAddr [6]byte
|
||||
}
|
||||
|
||||
func newDefaultGenerator() Generator {
|
||||
return &generator{}
|
||||
}
|
||||
|
||||
// NewV1 returns UUID based on current timestamp and MAC address.
|
||||
func (g *generator) NewV1() UUID {
|
||||
u := UUID{}
|
||||
|
||||
timeNow, clockSeq, hardwareAddr := g.getStorage()
|
||||
|
||||
binary.BigEndian.PutUint32(u[0:], uint32(timeNow))
|
||||
binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
|
||||
binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
|
||||
binary.BigEndian.PutUint16(u[8:], clockSeq)
|
||||
|
||||
copy(u[10:], hardwareAddr)
|
||||
|
||||
u.SetVersion(V1)
|
||||
u.SetVariant(VariantRFC4122)
|
||||
|
||||
return u
|
||||
}
|
||||
|
||||
// NewV2 returns DCE Security UUID based on POSIX UID/GID.
|
||||
func (g *generator) NewV2(domain byte) UUID {
|
||||
u := UUID{}
|
||||
|
||||
timeNow, clockSeq, hardwareAddr := g.getStorage()
|
||||
|
||||
switch domain {
|
||||
case DomainPerson:
|
||||
binary.BigEndian.PutUint32(u[0:], posixUID)
|
||||
case DomainGroup:
|
||||
binary.BigEndian.PutUint32(u[0:], posixGID)
|
||||
}
|
||||
|
||||
binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
|
||||
binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
|
||||
binary.BigEndian.PutUint16(u[8:], clockSeq)
|
||||
u[9] = domain
|
||||
|
||||
copy(u[10:], hardwareAddr)
|
||||
|
||||
u.SetVersion(V2)
|
||||
u.SetVariant(VariantRFC4122)
|
||||
|
||||
return u
|
||||
}
|
||||
|
||||
// NewV3 returns UUID based on MD5 hash of namespace UUID and name.
|
||||
func (g *generator) NewV3(ns UUID, name string) UUID {
|
||||
u := newFromHash(md5.New(), ns, name)
|
||||
u.SetVersion(V3)
|
||||
u.SetVariant(VariantRFC4122)
|
||||
|
||||
return u
|
||||
}
|
||||
|
||||
// NewV4 returns random generated UUID.
|
||||
func (g *generator) NewV4() UUID {
|
||||
u := UUID{}
|
||||
g.safeRandom(u[:])
|
||||
u.SetVersion(V4)
|
||||
u.SetVariant(VariantRFC4122)
|
||||
|
||||
return u
|
||||
}
|
||||
|
||||
// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
|
||||
func (g *generator) NewV5(ns UUID, name string) UUID {
|
||||
u := newFromHash(sha1.New(), ns, name)
|
||||
u.SetVersion(V5)
|
||||
u.SetVariant(VariantRFC4122)
|
||||
|
||||
return u
|
||||
}
|
||||
|
||||
func (g *generator) initStorage() {
|
||||
g.initClockSequence()
|
||||
g.initHardwareAddr()
|
||||
}
|
||||
|
||||
func (g *generator) initClockSequence() {
|
||||
buf := make([]byte, 2)
|
||||
g.safeRandom(buf)
|
||||
g.clockSequence = binary.BigEndian.Uint16(buf)
|
||||
}
|
||||
|
||||
func (g *generator) initHardwareAddr() {
|
||||
interfaces, err := net.Interfaces()
|
||||
if err == nil {
|
||||
for _, iface := range interfaces {
|
||||
if len(iface.HardwareAddr) >= 6 {
|
||||
copy(g.hardwareAddr[:], iface.HardwareAddr)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize hardwareAddr randomly in case
|
||||
// of real network interfaces absence
|
||||
g.safeRandom(g.hardwareAddr[:])
|
||||
|
||||
// Set multicast bit as recommended in RFC 4122
|
||||
g.hardwareAddr[0] |= 0x01
|
||||
}
|
||||
|
||||
func (g *generator) safeRandom(dest []byte) {
|
||||
if _, err := rand.Read(dest); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns UUID v1/v2 storage state.
|
||||
// Returns epoch timestamp, clock sequence, and hardware address.
|
||||
func (g *generator) getStorage() (uint64, uint16, []byte) {
|
||||
g.storageOnce.Do(g.initStorage)
|
||||
|
||||
g.storageMutex.Lock()
|
||||
defer g.storageMutex.Unlock()
|
||||
|
||||
timeNow := epochFunc()
|
||||
// Clock changed backwards since last UUID generation.
|
||||
// Should increase clock sequence.
|
||||
if timeNow <= g.lastTime {
|
||||
g.clockSequence++
|
||||
}
|
||||
g.lastTime = timeNow
|
||||
|
||||
return timeNow, g.clockSequence, g.hardwareAddr[:]
|
||||
}
|
||||
|
||||
// Returns difference in 100-nanosecond intervals between
|
||||
// UUID epoch (October 15, 1582) and current time.
|
||||
// This is default epoch calculation function.
|
||||
func unixTimeFunc() uint64 {
|
||||
return epochStart + uint64(time.Now().UnixNano()/100)
|
||||
}
|
||||
|
||||
// Returns UUID based on hashing of namespace UUID and name.
|
||||
func newFromHash(h hash.Hash, ns UUID, name string) UUID {
|
||||
u := UUID{}
|
||||
h.Write(ns[:])
|
||||
h.Write([]byte(name))
|
||||
copy(u[:], h.Sum(nil))
|
||||
|
||||
return u
|
||||
}
|
||||
78
vendor/github.com/satori/go.uuid/sql.go
generated
vendored
Normal file
78
vendor/github.com/satori/go.uuid/sql.go
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
package uuid
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Value implements the driver.Valuer interface.
|
||||
func (u UUID) Value() (driver.Value, error) {
|
||||
return u.String(), nil
|
||||
}
|
||||
|
||||
// Scan implements the sql.Scanner interface.
|
||||
// A 16-byte slice is handled by UnmarshalBinary, while
|
||||
// a longer byte slice or a string is handled by UnmarshalText.
|
||||
func (u *UUID) Scan(src interface{}) error {
|
||||
switch src := src.(type) {
|
||||
case []byte:
|
||||
if len(src) == Size {
|
||||
return u.UnmarshalBinary(src)
|
||||
}
|
||||
return u.UnmarshalText(src)
|
||||
|
||||
case string:
|
||||
return u.UnmarshalText([]byte(src))
|
||||
}
|
||||
|
||||
return fmt.Errorf("uuid: cannot convert %T to UUID", src)
|
||||
}
|
||||
|
||||
// NullUUID can be used with the standard sql package to represent a
|
||||
// UUID value that can be NULL in the database
|
||||
type NullUUID struct {
|
||||
UUID UUID
|
||||
Valid bool
|
||||
}
|
||||
|
||||
// Value implements the driver.Valuer interface.
|
||||
func (u NullUUID) Value() (driver.Value, error) {
|
||||
if !u.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
// Delegate to UUID Value function
|
||||
return u.UUID.Value()
|
||||
}
|
||||
|
||||
// Scan implements the sql.Scanner interface.
|
||||
func (u *NullUUID) Scan(src interface{}) error {
|
||||
if src == nil {
|
||||
u.UUID, u.Valid = Nil, false
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delegate to UUID Scan function
|
||||
u.Valid = true
|
||||
return u.UUID.Scan(src)
|
||||
}
|
||||
161
vendor/github.com/satori/go.uuid/uuid.go
generated
vendored
Normal file
161
vendor/github.com/satori/go.uuid/uuid.go
generated
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// Package uuid provides implementation of Universally Unique Identifier (UUID).
|
||||
// Supported versions are 1, 3, 4 and 5 (as specified in RFC 4122) and
|
||||
// version 2 (as specified in DCE 1.1).
|
||||
package uuid
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
// Size of a UUID in bytes.
|
||||
const Size = 16
|
||||
|
||||
// UUID representation compliant with specification
|
||||
// described in RFC 4122.
|
||||
type UUID [Size]byte
|
||||
|
||||
// UUID versions
|
||||
const (
|
||||
_ byte = iota
|
||||
V1
|
||||
V2
|
||||
V3
|
||||
V4
|
||||
V5
|
||||
)
|
||||
|
||||
// UUID layout variants.
|
||||
const (
|
||||
VariantNCS byte = iota
|
||||
VariantRFC4122
|
||||
VariantMicrosoft
|
||||
VariantFuture
|
||||
)
|
||||
|
||||
// UUID DCE domains.
|
||||
const (
|
||||
DomainPerson = iota
|
||||
DomainGroup
|
||||
DomainOrg
|
||||
)
|
||||
|
||||
// String parse helpers.
|
||||
var (
|
||||
urnPrefix = []byte("urn:uuid:")
|
||||
byteGroups = []int{8, 4, 4, 4, 12}
|
||||
)
|
||||
|
||||
// Nil is special form of UUID that is specified to have all
|
||||
// 128 bits set to zero.
|
||||
var Nil = UUID{}
|
||||
|
||||
// Predefined namespace UUIDs.
|
||||
var (
|
||||
NamespaceDNS = Must(FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
|
||||
NamespaceURL = Must(FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8"))
|
||||
NamespaceOID = Must(FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8"))
|
||||
NamespaceX500 = Must(FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8"))
|
||||
)
|
||||
|
||||
// Equal returns true if u1 and u2 equals, otherwise returns false.
|
||||
func Equal(u1 UUID, u2 UUID) bool {
|
||||
return bytes.Equal(u1[:], u2[:])
|
||||
}
|
||||
|
||||
// Version returns algorithm version used to generate UUID.
|
||||
func (u UUID) Version() byte {
|
||||
return u[6] >> 4
|
||||
}
|
||||
|
||||
// Variant returns UUID layout variant.
|
||||
func (u UUID) Variant() byte {
|
||||
switch {
|
||||
case (u[8] >> 7) == 0x00:
|
||||
return VariantNCS
|
||||
case (u[8] >> 6) == 0x02:
|
||||
return VariantRFC4122
|
||||
case (u[8] >> 5) == 0x06:
|
||||
return VariantMicrosoft
|
||||
case (u[8] >> 5) == 0x07:
|
||||
fallthrough
|
||||
default:
|
||||
return VariantFuture
|
||||
}
|
||||
}
|
||||
|
||||
// Bytes returns bytes slice representation of UUID.
|
||||
func (u UUID) Bytes() []byte {
|
||||
return u[:]
|
||||
}
|
||||
|
||||
// Returns canonical string representation of UUID:
|
||||
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
|
||||
func (u UUID) String() string {
|
||||
buf := make([]byte, 36)
|
||||
|
||||
hex.Encode(buf[0:8], u[0:4])
|
||||
buf[8] = '-'
|
||||
hex.Encode(buf[9:13], u[4:6])
|
||||
buf[13] = '-'
|
||||
hex.Encode(buf[14:18], u[6:8])
|
||||
buf[18] = '-'
|
||||
hex.Encode(buf[19:23], u[8:10])
|
||||
buf[23] = '-'
|
||||
hex.Encode(buf[24:], u[10:])
|
||||
|
||||
return string(buf)
|
||||
}
|
||||
|
||||
// SetVersion sets version bits.
|
||||
func (u *UUID) SetVersion(v byte) {
|
||||
u[6] = (u[6] & 0x0f) | (v << 4)
|
||||
}
|
||||
|
||||
// SetVariant sets variant bits.
|
||||
func (u *UUID) SetVariant(v byte) {
|
||||
switch v {
|
||||
case VariantNCS:
|
||||
u[8] = (u[8]&(0xff>>1) | (0x00 << 7))
|
||||
case VariantRFC4122:
|
||||
u[8] = (u[8]&(0xff>>2) | (0x02 << 6))
|
||||
case VariantMicrosoft:
|
||||
u[8] = (u[8]&(0xff>>3) | (0x06 << 5))
|
||||
case VariantFuture:
|
||||
fallthrough
|
||||
default:
|
||||
u[8] = (u[8]&(0xff>>3) | (0x07 << 5))
|
||||
}
|
||||
}
|
||||
|
||||
// Must is a helper that wraps a call to a function returning (UUID, error)
|
||||
// and panics if the error is non-nil. It is intended for use in variable
|
||||
// initializations such as
|
||||
// var packageUUID = uuid.Must(uuid.FromString("123e4567-e89b-12d3-a456-426655440000"));
|
||||
func Must(u UUID, err error) UUID {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return u
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package vkubelet
|
||||
import (
|
||||
"github.com/virtual-kubelet/virtual-kubelet/providers/aws"
|
||||
"github.com/virtual-kubelet/virtual-kubelet/providers/azure"
|
||||
"github.com/virtual-kubelet/virtual-kubelet/providers/azurebatch"
|
||||
"github.com/virtual-kubelet/virtual-kubelet/providers/cri"
|
||||
"github.com/virtual-kubelet/virtual-kubelet/providers/hypersh"
|
||||
"github.com/virtual-kubelet/virtual-kubelet/providers/web"
|
||||
@@ -14,6 +15,7 @@ var _ Provider = (*aws.FargateProvider)(nil)
|
||||
var _ Provider = (*azure.ACIProvider)(nil)
|
||||
var _ Provider = (*hypersh.HyperProvider)(nil)
|
||||
var _ Provider = (*web.BrokerProvider)(nil)
|
||||
var _ Provider = (*azurebatch.Provider)(nil)
|
||||
var _ Provider = (*cri.CRIProvider)(nil)
|
||||
|
||||
// Provider contains the methods required to implement a virtual-kubelet provider.
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/virtual-kubelet/virtual-kubelet/manager"
|
||||
"github.com/virtual-kubelet/virtual-kubelet/providers/aws"
|
||||
"github.com/virtual-kubelet/virtual-kubelet/providers/azure"
|
||||
"github.com/virtual-kubelet/virtual-kubelet/providers/azurebatch"
|
||||
"github.com/virtual-kubelet/virtual-kubelet/providers/cri"
|
||||
"github.com/virtual-kubelet/virtual-kubelet/providers/hypersh"
|
||||
"github.com/virtual-kubelet/virtual-kubelet/providers/mock"
|
||||
@@ -90,6 +91,11 @@ func New(nodeName, operatingSystem, namespace, kubeConfig, taint, provider, prov
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case "azurebatch":
|
||||
p, err = azurebatch.NewBatchProvider(providerConfig, rm, nodeName, operatingSystem, internalIP, daemonEndpointPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case "hyper":
|
||||
p, err = hypersh.NewHyperProvider(providerConfig, rm, nodeName, operatingSystem)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user