Merge pull request #514 from feiskyer/node-pools
Add support for Azure virtual machine availability sets (VMAS)
This commit is contained in:
commit
c24580a55b
|
|
@ -36,6 +36,11 @@
|
||||||
"Comment": "v11.1.1-beta",
|
"Comment": "v11.1.1-beta",
|
||||||
"Rev": "509eea43b93cec2f3f17acbe2578ef58703923f8"
|
"Rev": "509eea43b93cec2f3f17acbe2578ef58703923f8"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/Azure/azure-sdk-for-go/arm/resources/resources",
|
||||||
|
"Comment": "v11.1.1-beta",
|
||||||
|
"Rev": "509eea43b93cec2f3f17acbe2578ef58703923f8"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/Azure/azure-sdk-for-go/arm/storage",
|
"ImportPath": "github.com/Azure/azure-sdk-for-go/arm/storage",
|
||||||
"Comment": "v11.1.1-beta",
|
"Comment": "v11.1.1-beta",
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
# Cluster Autoscaler on Azure
|
# Cluster Autoscaler on Azure
|
||||||
|
|
||||||
The cluster autoscaler on Azure scales worker nodes within any specified autoscaling group. It will run as a `Deployment` in your cluster. This README will go over some of the necessary steps required to get the cluster autoscaler up and running.
|
The cluster autoscaler on Azure scales worker nodes within any specified autoscaling group. It will run as a Kubernetes deployment in your cluster. This README will go over some of the necessary steps required to get the cluster autoscaler up and running.
|
||||||
|
|
||||||
## Kubernetes Version
|
## Kubernetes Version
|
||||||
|
|
||||||
Cluster autoscaler must run on Kubernetes with Azure VMSS support ([kubernetes#43287](https://github.com/kubernetes/kubernetes/issues/43287)). It is planed in Kubernetes v1.10.
|
Cluster autoscaler support two VM types with Azure cloud provider:
|
||||||
|
|
||||||
|
- vmss: For kubernetes cluster running on VMSS instances. Azure cloud provider's `vmType` parameter must be configured as 'vmss'. It requires Kubernetes with Azure VMSS support ([kubernetes#43287](https://github.com/kubernetes/kubernetes/issues/43287)), which is planed in Kubernetes v1.10.
|
||||||
|
- standard: For kubernetes cluster running on VMAS instances. Azure cloud provider's `vmType` parameter must be configured as 'standard'. It only supports Kubernetes cluster deployed via [acs-engine](https://github.com/Azure/acs-engine).
|
||||||
|
|
||||||
## Permissions
|
## Permissions
|
||||||
|
|
||||||
|
|
@ -15,188 +18,77 @@ Get azure credentials by running the following command
|
||||||
az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/<subscription-id>" --output json
|
az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/<subscription-id>" --output json
|
||||||
```
|
```
|
||||||
|
|
||||||
And fill the values with the result you got into the configmap
|
## Deployment manifests
|
||||||
|
|
||||||
```yaml
|
### VMSS deployment
|
||||||
apiVersion: v1
|
|
||||||
data:
|
|
||||||
ClientID: <client-id>
|
|
||||||
ClientSecret: <client-secret>
|
|
||||||
ResourceGroup: <resource-group>
|
|
||||||
SubscriptionID: <subscription-id>
|
|
||||||
TenantID: <tenand-id>
|
|
||||||
ScaleSetName: <scale-set-name>
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: cluster-autoscaler-azure
|
|
||||||
namespace: kube-system
|
|
||||||
```
|
|
||||||
|
|
||||||
Create the configmap by running
|
Pre-requirements:
|
||||||
|
|
||||||
|
- Get credentials from above `permissions` step.
|
||||||
|
- Get the scale set name which is used for nodes scaling.
|
||||||
|
- Encode each data with base64.
|
||||||
|
|
||||||
|
Fill the values of cluster-autoscaler-azure secret in [cluster-autoscaler-vmss.yaml](cluster-autoscaler-vmss.yaml), including
|
||||||
|
|
||||||
|
- ClientID: `<base64-encoded-client-id>`
|
||||||
|
- ClientSecret: `<base64-encoded-client-secret>`
|
||||||
|
- ResourceGroup: `<base64-encoded-resource-group>`
|
||||||
|
- SubscriptionID: `<base64-encode-subscription-id>`
|
||||||
|
- TenantID: `<base64-encoded-tenant-id>`
|
||||||
|
- NodeGroup: `<base64-encoded-scale-set-name>`
|
||||||
|
|
||||||
|
Note that all data should be encoded with base64.
|
||||||
|
|
||||||
|
Then deploy cluster-autoscaler by running
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
kubectl create -f cluster-autoscaler-azure-configmap.yaml
|
kubectl create -f cluster-autoscaler-vmss.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
## Deployment
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
apiVersion: extensions/v1beta1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: cluster-autoscaler
|
|
||||||
namespace: kube-system
|
|
||||||
labels:
|
|
||||||
app: cluster-autoscaler
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: cluster-autoscaler
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: cluster-autoscaler
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- image: k8s.gcr.io/cluster-autoscaler:{{ ca_version }}
|
|
||||||
name: cluster-autoscaler
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpu: 100m
|
|
||||||
memory: 300Mi
|
|
||||||
requests:
|
|
||||||
cpu: 100m
|
|
||||||
memory: 300Mi
|
|
||||||
env:
|
|
||||||
- name: ARM_SUBSCRIPTION_ID
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: cluster-autoscaler-azure
|
|
||||||
key: SubscriptionID
|
|
||||||
- name: ARM_RESOURCE_GROUP
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: cluster-autoscaler-azure
|
|
||||||
key: ResourceGroup
|
|
||||||
- name: ARM_TENANT_ID
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: cluster-autoscaler-azure
|
|
||||||
key: TenantID
|
|
||||||
- name: ARM_CLIENT_ID
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: cluster-autoscaler-azure
|
|
||||||
key: ClientID
|
|
||||||
- name: ARM_CLIENT_SECRET
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: cluster-autoscaler-azure
|
|
||||||
key: ClientSecret
|
|
||||||
- name: ARM_SCALE_SET_NAME
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: cluster-autoscaler-azure
|
|
||||||
key: ScaleSetName
|
|
||||||
command:
|
|
||||||
- ./cluster-autoscaler
|
|
||||||
- --v=4
|
|
||||||
- --cloud-provider=azure
|
|
||||||
- --skip-nodes-with-local-storage=false
|
|
||||||
- --nodes="1:10:$(ARM_SCALE_SET_NAME)"
|
|
||||||
volumeMounts:
|
|
||||||
- name: ssl-certs
|
|
||||||
mountPath: /etc/ssl/certs/ca-certificates.crt
|
|
||||||
readOnly: true
|
|
||||||
imagePullPolicy: "Always"
|
|
||||||
volumes:
|
|
||||||
- name: ssl-certs
|
|
||||||
hostPath:
|
|
||||||
path: "/etc/ssl/certs/ca-certificates.crt"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Deploy in master node
|
|
||||||
|
|
||||||
To run a CA pod in master node - CA deployment should tolerate the master `taint` and `nodeSelector` should be used to schedule the pods in master node.
|
To run a CA pod in master node - CA deployment should tolerate the master `taint` and `nodeSelector` should be used to schedule the pods in master node.
|
||||||
|
|
||||||
```yaml
|
```sh
|
||||||
apiVersion: extensions/v1beta1
|
kubectl create -f cluster-autoscaler-vmss-master.yaml
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: cluster-autoscaler
|
|
||||||
namespace: kube-system
|
|
||||||
labels:
|
|
||||||
app: cluster-autoscaler
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: cluster-autoscaler
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: cluster-autoscaler
|
|
||||||
spec:
|
|
||||||
tolerations:
|
|
||||||
- effect: NoSchedule
|
|
||||||
key: node-role.kubernetes.io/master
|
|
||||||
nodeSelector:
|
|
||||||
kubernetes.io/role: master
|
|
||||||
containers:
|
|
||||||
- image: k8s.gcr.io/cluster-autoscaler:{{ ca_version }}
|
|
||||||
name: cluster-autoscaler
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpu: 100m
|
|
||||||
memory: 300Mi
|
|
||||||
requests:
|
|
||||||
cpu: 100m
|
|
||||||
memory: 300Mi
|
|
||||||
env:
|
|
||||||
- name: ARM_SUBSCRIPTION_ID
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: cluster-autoscaler-azure
|
|
||||||
key: SubscriptionID
|
|
||||||
- name: ARM_RESOURCE_GROUP
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: cluster-autoscaler-azure
|
|
||||||
key: ResourceGroup
|
|
||||||
- name: ARM_TENANT_ID
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: cluster-autoscaler-azure
|
|
||||||
key: TenantID
|
|
||||||
- name: ARM_CLIENT_ID
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: cluster-autoscaler-azure
|
|
||||||
key: ClientID
|
|
||||||
- name: ARM_CLIENT_SECRET
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: cluster-autoscaler-azure
|
|
||||||
key: ClientSecret
|
|
||||||
- name: ARM_SCALE_SET_NAME
|
|
||||||
valueFrom:
|
|
||||||
configMapKeyRef:
|
|
||||||
name: cluster-autoscaler-azure
|
|
||||||
key: ScaleSetName
|
|
||||||
command:
|
|
||||||
- ./cluster-autoscaler
|
|
||||||
- --v=4
|
|
||||||
- --cloud-provider=azure
|
|
||||||
- --skip-nodes-with-local-storage=false
|
|
||||||
- --nodes="1:10:$(ARM_SCALE_SET_NAME)"
|
|
||||||
volumeMounts:
|
|
||||||
- name: ssl-certs
|
|
||||||
mountPath: /etc/ssl/certs/ca-certificates.crt
|
|
||||||
readOnly: true
|
|
||||||
imagePullPolicy: "Always"
|
|
||||||
volumes:
|
|
||||||
- name: ssl-certs
|
|
||||||
hostPath:
|
|
||||||
path: "/etc/ssl/certs/ca-certificates.crt"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Standard deployment
|
||||||
|
|
||||||
|
Pre-requirements:
|
||||||
|
|
||||||
|
- Get credentials from above `permissions` step.
|
||||||
|
- Get the required paramters from acs-engine deployments (usually under directory `_output/<master-dns-prefix>` after running `acs-engine deploy` command)
|
||||||
|
- Get `APIServerPrivateKey`, `CAPrivateKey`, `ClientPrivateKey` and `KubeConfigPrivateKey` from `azuredeploy.parameters.json`
|
||||||
|
- If windows nodes are included, also get `WindowsAdminPassword` from acs-engine deployment manifests
|
||||||
|
- Get the initial Azure deployment name from azure portal. If you have multiple deployments (e.g. have run `acs-engine scale` command), make sure to get the first one
|
||||||
|
- Get a node pool name for nodes scaling from acs-engine deployment manifests
|
||||||
|
- Encode each data with base64.
|
||||||
|
|
||||||
|
Fill the values of cluster-autoscaler-azure secret in [cluster-autoscaler-standard.yaml](cluster-autoscaler-standard.yaml), including
|
||||||
|
|
||||||
|
- ClientID: `<base64-encoded-client-id>`
|
||||||
|
- ClientSecret: `<base64-encoded-client-secret>`
|
||||||
|
- ResourceGroup: `<base64-encoded-resource-group>`
|
||||||
|
- SubscriptionID: `<base64-encode-subscription-id>`
|
||||||
|
- TenantID: `<base64-encoded-tenant-id>`
|
||||||
|
- NodeGroup: `<base64-encoded-node-pool-name>`
|
||||||
|
- Deployment: `<base64-encoded-azure-initial-deploy-name>`
|
||||||
|
- APIServerPrivateKey: `<base64-encoded-apiserver-private-key>`
|
||||||
|
- CAPrivateKey: `<base64-encoded-ca-private-key>`
|
||||||
|
- ClientPrivateKey: `<base64-encoded-client-private-key>`
|
||||||
|
- KubeConfigPrivateKey: `<base64-encoded-kubeconfig-private-key>`
|
||||||
|
- WindowsAdminPassword: `<base64-encoded-windows-admin-password>`
|
||||||
|
|
||||||
|
Note that all data should be encoded with base64.
|
||||||
|
|
||||||
|
Then deploy cluster-autoscaler by running
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kubectl create -f cluster-autoscaler-standard.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
To run a CA pod in master node - CA deployment should tolerate the master `taint` and `nodeSelector` should be used to schedule the pods in master node.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kubectl create -f cluster-autoscaler-standard-master.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,513 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
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 (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/Azure/azure-sdk-for-go/arm/compute"
|
||||||
|
"github.com/Azure/azure-sdk-for-go/arm/resources/resources"
|
||||||
|
azStorage "github.com/Azure/azure-sdk-for-go/storage"
|
||||||
|
"github.com/Azure/go-autorest/autorest/to"
|
||||||
|
"github.com/golang/glog"
|
||||||
|
|
||||||
|
apiv1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
|
||||||
|
"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AgentPool implements NodeGroup interface for agent pools deployed by acs-engine.
|
||||||
|
type AgentPool struct {
|
||||||
|
AzureRef
|
||||||
|
*AzureManager
|
||||||
|
|
||||||
|
minSize int
|
||||||
|
maxSize int
|
||||||
|
|
||||||
|
template map[string]interface{}
|
||||||
|
parameters map[string]interface{}
|
||||||
|
|
||||||
|
mutex sync.Mutex
|
||||||
|
targetSize int
|
||||||
|
provisioning bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// VirtualMachineID contains VMID and ID of a virtual machine.
|
||||||
|
type VirtualMachineID struct {
|
||||||
|
ID string
|
||||||
|
VMID string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAgentPool creates a new AgentPool.
|
||||||
|
func NewAgentPool(name string, minSize, maxSize int, az *AzureManager) (*AgentPool, error) {
|
||||||
|
as := &AgentPool{
|
||||||
|
AzureRef: AzureRef{
|
||||||
|
Name: name,
|
||||||
|
},
|
||||||
|
minSize: minSize,
|
||||||
|
maxSize: maxSize,
|
||||||
|
targetSize: -1,
|
||||||
|
AzureManager: az,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := as.initialize(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return as, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (as *AgentPool) initialize() error {
|
||||||
|
deploy, err := as.deploymentsClient.Get(as.config.ResourceGroup, as.config.Deployment)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("deploymentsClient.Get(%s, %s) failed: %v", as.config.ResourceGroup, as.config.Deployment, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
template, err := as.deploymentsClient.ExportTemplate(as.config.ResourceGroup, as.config.Deployment)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("deploymentsClient.ExportTemplate(%s, %s) failed: %v", as.config.ResourceGroup, as.config.Deployment, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
as.parameters = *deploy.Properties.Parameters
|
||||||
|
as.preprocessParameters()
|
||||||
|
|
||||||
|
as.template = *template.Template
|
||||||
|
return normalizeForK8sVMASScalingUp(as.template)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (as *AgentPool) preprocessParameters() {
|
||||||
|
// Delete type key from parameters.
|
||||||
|
for k := range as.parameters {
|
||||||
|
if v, ok := as.parameters[k].(map[string]interface{}); ok {
|
||||||
|
delete(v, "type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fulfill secure parameters.
|
||||||
|
as.parameters["apiServerPrivateKey"] = map[string]string{"value": as.config.APIServerPrivateKey}
|
||||||
|
as.parameters["caPrivateKey"] = map[string]string{"value": as.config.CAPrivateKey}
|
||||||
|
as.parameters["clientPrivateKey"] = map[string]string{"value": as.config.ClientPrivateKey}
|
||||||
|
as.parameters["kubeConfigPrivateKey"] = map[string]string{"value": as.config.KubeConfigPrivateKey}
|
||||||
|
as.parameters["servicePrincipalClientId"] = map[string]string{"value": as.config.AADClientID}
|
||||||
|
as.parameters["servicePrincipalClientSecret"] = map[string]string{"value": as.config.AADClientSecret}
|
||||||
|
if as.config.WindowsAdminPassword != "" {
|
||||||
|
as.parameters["windowsAdminPassword"] = map[string]string{"value": as.config.WindowsAdminPassword}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MinSize returns minimum size of the node group.
|
||||||
|
func (as *AgentPool) MinSize() int {
|
||||||
|
return as.minSize
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exist checks if the node group really exists on the cloud provider side. Allows to tell the
|
||||||
|
// theoretical node group from the real one.
|
||||||
|
func (as *AgentPool) Exist() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create creates the node group on the cloud provider side.
|
||||||
|
func (as *AgentPool) Create() error {
|
||||||
|
return cloudprovider.ErrAlreadyExist
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete deletes the node group on the cloud provider side.
|
||||||
|
// This will be executed only for autoprovisioned node groups, once their size drops to 0.
|
||||||
|
func (as *AgentPool) Delete() error {
|
||||||
|
return cloudprovider.ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
// Autoprovisioned returns true if the node group is autoprovisioned.
|
||||||
|
func (as *AgentPool) Autoprovisioned() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxSize returns maximum size of the node group.
|
||||||
|
func (as *AgentPool) MaxSize() int {
|
||||||
|
return as.maxSize
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVMIndexes gets indexes of all virtual machines belongting to the agent pool.
|
||||||
|
func (as *AgentPool) GetVMIndexes() ([]int, map[int]VirtualMachineID, error) {
|
||||||
|
instances, err := as.GetVirtualMachines()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
indexes := make([]int, 0)
|
||||||
|
indexToVM := make(map[int]VirtualMachineID)
|
||||||
|
for _, instance := range instances {
|
||||||
|
index, err := GetVMNameIndex(instance.StorageProfile.OsDisk.OsType, *instance.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
indexes = append(indexes, index)
|
||||||
|
indexToVM[index] = VirtualMachineID{
|
||||||
|
ID: "azure://" + strings.ToLower(*instance.ID),
|
||||||
|
VMID: "azure://" + strings.ToLower(*instance.VMID),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sortedIndexes := sort.IntSlice(indexes)
|
||||||
|
sortedIndexes.Sort()
|
||||||
|
return sortedIndexes, indexToVM, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetSize returns the current TARGET size of the node group. It is possible that the
|
||||||
|
// number is different from the number of nodes registered in Kubernetes.
|
||||||
|
func (as *AgentPool) TargetSize() (int, error) {
|
||||||
|
as.mutex.Lock()
|
||||||
|
defer as.mutex.Unlock()
|
||||||
|
|
||||||
|
if as.targetSize != -1 {
|
||||||
|
return as.targetSize, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
indexes, _, err := as.GetVMIndexes()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
as.targetSize = len(indexes)
|
||||||
|
return as.targetSize, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IncreaseSize increases agent pool size
|
||||||
|
func (as *AgentPool) IncreaseSize(delta int) error {
|
||||||
|
as.mutex.Lock()
|
||||||
|
defer as.mutex.Unlock()
|
||||||
|
|
||||||
|
if delta <= 0 {
|
||||||
|
return fmt.Errorf("size increase must be positive")
|
||||||
|
}
|
||||||
|
|
||||||
|
indexes, _, err := as.GetVMIndexes()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
curSize := len(indexes)
|
||||||
|
if curSize+delta > as.MaxSize() {
|
||||||
|
return fmt.Errorf("size increase too large - desired:%d max:%d", curSize+delta, as.MaxSize())
|
||||||
|
}
|
||||||
|
|
||||||
|
highestUsedIndex := indexes[len(indexes)-1]
|
||||||
|
countForTemplate := curSize + delta
|
||||||
|
as.targetSize = countForTemplate
|
||||||
|
if highestUsedIndex != 0 {
|
||||||
|
countForTemplate += highestUsedIndex + 1 - curSize
|
||||||
|
}
|
||||||
|
as.parameters[as.Name+"Count"] = map[string]int{"value": countForTemplate}
|
||||||
|
as.parameters[as.Name+"Offset"] = map[string]int{"value": highestUsedIndex + 1}
|
||||||
|
|
||||||
|
cancel := make(chan struct{})
|
||||||
|
newDeploymentName := fmt.Sprintf("cluster-autoscaler-%d", rand.New(rand.NewSource(time.Now().UnixNano())).Int31())
|
||||||
|
newDeployment := resources.Deployment{
|
||||||
|
Properties: &resources.DeploymentProperties{
|
||||||
|
Template: &as.template,
|
||||||
|
Parameters: &as.parameters,
|
||||||
|
Mode: resources.Incremental,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, errChan := as.deploymentsClient.CreateOrUpdate(as.config.ResourceGroup, newDeploymentName, newDeployment, cancel)
|
||||||
|
glog.V(3).Infof("Waiting for deploymentsClient.CreateOrUpdate(%s, %s, %s)", as.config.ResourceGroup, newDeploymentName, newDeployment)
|
||||||
|
return <-errChan
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVirtualMachines returns list of nodes for the given agent pool.
|
||||||
|
func (as *AgentPool) GetVirtualMachines() (instances []compute.VirtualMachine, err error) {
|
||||||
|
result, err := as.virtualMachinesClient.List(as.config.ResourceGroup)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
moreResult := (result.Value != nil && len(*result.Value) > 0)
|
||||||
|
for moreResult {
|
||||||
|
for _, instance := range *result.Value {
|
||||||
|
if instance.Tags == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
tags := *instance.Tags
|
||||||
|
vmPoolName := tags["poolName"]
|
||||||
|
if *vmPoolName != as.Id() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
instances = append(instances, instance)
|
||||||
|
}
|
||||||
|
|
||||||
|
moreResult = false
|
||||||
|
if result.NextLink != nil {
|
||||||
|
result, err = as.virtualMachinesClient.ListNextResults(result)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("virtualMachinesClient.ListNextResults failed: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
moreResult = (result.Value != nil && len(*result.Value) > 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return instances, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecreaseTargetSize decreases the target size of the node group. This function
|
||||||
|
// doesn't permit to delete any existing node and can be used only to reduce the
|
||||||
|
// request for new nodes that have not been yet fulfilled. Delta should be negative.
|
||||||
|
// It is assumed that cloud provider will not delete the existing nodes if the size
|
||||||
|
// when there is an option to just decrease the target.
|
||||||
|
func (as *AgentPool) DecreaseTargetSize(delta int) error {
|
||||||
|
as.mutex.Lock()
|
||||||
|
defer as.mutex.Unlock()
|
||||||
|
|
||||||
|
nodes, err := as.GetVirtualMachines()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
curTargetSize := as.targetSize
|
||||||
|
if curTargetSize+delta < len(nodes) {
|
||||||
|
return fmt.Errorf("attempt to delete existing nodes targetSize:%d delta:%d existingNodes: %d",
|
||||||
|
curTargetSize, delta, len(nodes))
|
||||||
|
}
|
||||||
|
|
||||||
|
as.targetSize = curTargetSize + delta
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Belongs returns true if the given node belongs to the NodeGroup.
|
||||||
|
func (as *AgentPool) Belongs(node *apiv1.Node) (bool, error) {
|
||||||
|
glog.V(6).Infof("Check if node belongs to this agent pool: AgentPool:%v, node:%v\n", as, node)
|
||||||
|
|
||||||
|
ref := &AzureRef{
|
||||||
|
Name: strings.ToLower(node.Spec.ProviderID),
|
||||||
|
}
|
||||||
|
|
||||||
|
targetAsg, err := as.GetNodeGroupForInstance(ref)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if targetAsg == nil {
|
||||||
|
return false, fmt.Errorf("%s doesn't belong to a known agent pool", node.Name)
|
||||||
|
}
|
||||||
|
if targetAsg.Id() != as.Id() {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteInstances deletes the given instances. All instances must be controlled by the same ASG.
|
||||||
|
func (as *AgentPool) DeleteInstances(instances []*AzureRef) error {
|
||||||
|
if len(instances) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
commonAsg, err := as.GetNodeGroupForInstance(instances[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, instance := range instances {
|
||||||
|
asg, err := as.GetNodeGroupForInstance(instance)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if asg != commonAsg {
|
||||||
|
return fmt.Errorf("cannot delete instance (%s) which don't belong to the same node pool (%q)", instance.GetKey(), commonAsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, instance := range instances {
|
||||||
|
name, err := resourceName((*instance).Name)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("Get name for instance %q failed: %v", *instance, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = as.deleteVirtualMachine(name)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("Delete virtual machine %q failed: %v", name, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteNodes deletes the nodes from the group.
|
||||||
|
func (as *AgentPool) DeleteNodes(nodes []*apiv1.Node) error {
|
||||||
|
glog.V(8).Infof("Delete nodes requested: %v\n", nodes)
|
||||||
|
indexes, _, err := as.GetVMIndexes()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(indexes) <= as.MinSize() {
|
||||||
|
return fmt.Errorf("min size reached, nodes will not be deleted")
|
||||||
|
}
|
||||||
|
|
||||||
|
refs := make([]*AzureRef, 0, len(nodes))
|
||||||
|
for _, node := range nodes {
|
||||||
|
belongs, err := as.Belongs(node)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if belongs != true {
|
||||||
|
return fmt.Errorf("%s belongs to a different asg than %s", node.Name, as.Id())
|
||||||
|
}
|
||||||
|
|
||||||
|
azureRef := &AzureRef{
|
||||||
|
Name: strings.ToLower(node.Spec.ProviderID),
|
||||||
|
}
|
||||||
|
refs = append(refs, azureRef)
|
||||||
|
}
|
||||||
|
|
||||||
|
return as.DeleteInstances(refs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Id returns AgentPool id.
|
||||||
|
func (as *AgentPool) Id() string {
|
||||||
|
return as.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug returns a debug string for the agent pool.
|
||||||
|
func (as *AgentPool) Debug() string {
|
||||||
|
return fmt.Sprintf("%s (%d:%d)", as.Id(), as.MinSize(), as.MaxSize())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TemplateNodeInfo returns a node template for this agent pool.
|
||||||
|
func (as *AgentPool) TemplateNodeInfo() (*schedulercache.NodeInfo, error) {
|
||||||
|
return nil, cloudprovider.ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nodes returns a list of all nodes that belong to this node group.
|
||||||
|
func (as *AgentPool) Nodes() ([]string, error) {
|
||||||
|
instances, err := as.GetVirtualMachines()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes := make([]string, 0, len(instances))
|
||||||
|
for _, instance := range instances {
|
||||||
|
// Convert to lower because instance.ID is in different in different API calls (e.g. GET and LIST).
|
||||||
|
name := "azure://" + strings.ToLower(*instance.ID)
|
||||||
|
nodes = append(nodes, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (as *AgentPool) deleteBlob(accountName, vhdContainer, vhdBlob string) error {
|
||||||
|
storageKeysResult, err := as.storageAccountsClient.ListKeys(as.config.ResourceGroup, accountName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
keys := *storageKeysResult.Keys
|
||||||
|
client, err := azStorage.NewBasicClientOnSovereignCloud(accountName, to.String(keys[0].Value), as.env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
bs := client.GetBlobService()
|
||||||
|
containerRef := bs.GetContainerReference(vhdContainer)
|
||||||
|
blobRef := containerRef.GetBlobReference(vhdBlob)
|
||||||
|
|
||||||
|
return blobRef.Delete(&azStorage.DeleteBlobOptions{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// deleteVirtualMachine deletes a VM and any associated OS disk
|
||||||
|
func (as *AgentPool) deleteVirtualMachine(name string) error {
|
||||||
|
vm, err := as.virtualMachinesClient.Get(as.config.ResourceGroup, name, "")
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("failed to get VM: %s/%s: %s", as.config.ResourceGroup, name, err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
vhd := vm.VirtualMachineProperties.StorageProfile.OsDisk.Vhd
|
||||||
|
managedDisk := vm.VirtualMachineProperties.StorageProfile.OsDisk.ManagedDisk
|
||||||
|
if vhd == nil && managedDisk == nil {
|
||||||
|
glog.Errorf("failed to get a valid os disk URI for VM: %s/%s", as.config.ResourceGroup, name)
|
||||||
|
return fmt.Errorf("os disk does not have a VHD URI")
|
||||||
|
}
|
||||||
|
|
||||||
|
osDiskName := vm.VirtualMachineProperties.StorageProfile.OsDisk.Name
|
||||||
|
var nicName string
|
||||||
|
nicID := (*vm.VirtualMachineProperties.NetworkProfile.NetworkInterfaces)[0].ID
|
||||||
|
if nicID == nil {
|
||||||
|
glog.Warningf("NIC ID is not set for VM (%s/%s)", as.config.ResourceGroup, name)
|
||||||
|
} else {
|
||||||
|
nicName, err = resourceName(*nicID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
glog.Infof("found nic name for VM (%s/%s): %s", as.config.ResourceGroup, name, nicName)
|
||||||
|
}
|
||||||
|
glog.Infof("deleting VM: %s/%s", as.config.ResourceGroup, name)
|
||||||
|
_, deleteErrChan := as.virtualMachinesClient.Delete(as.config.ResourceGroup, name, nil)
|
||||||
|
glog.Infof("waiting for vm deletion: %s/%s", as.config.ResourceGroup, name)
|
||||||
|
if err := <-deleteErrChan; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(nicName) > 0 {
|
||||||
|
glog.Infof("deleting nic: %s/%s", as.config.ResourceGroup, nicName)
|
||||||
|
_, nicErrChan := as.interfacesClient.Delete(as.config.ResourceGroup, nicName, nil)
|
||||||
|
glog.Infof("waiting for nic deletion: %s/%s", as.config.ResourceGroup, nicName)
|
||||||
|
if nicErr := <-nicErrChan; nicErr != nil {
|
||||||
|
return nicErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if vhd != nil {
|
||||||
|
accountName, vhdContainer, vhdBlob, err := splitBlobURI(*vhd.URI)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.Infof("found os disk storage reference: %s %s %s", accountName, vhdContainer, vhdBlob)
|
||||||
|
|
||||||
|
glog.Infof("deleting blob: %s/%s", vhdContainer, vhdBlob)
|
||||||
|
if err = as.deleteBlob(accountName, vhdContainer, vhdBlob); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if managedDisk != nil {
|
||||||
|
if osDiskName == nil {
|
||||||
|
glog.Warningf("osDisk is not set for VM %s/%s", as.config.ResourceGroup, name)
|
||||||
|
} else {
|
||||||
|
glog.Infof("deleting managed disk: %s/%s", as.config.ResourceGroup, *osDiskName)
|
||||||
|
_, diskErrChan := as.disksClient.Delete(as.config.ResourceGroup, *osDiskName, nil)
|
||||||
|
|
||||||
|
if err := <-diskErrChan; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -27,7 +27,6 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
|
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
|
||||||
"k8s.io/autoscaler/cluster-autoscaler/utils/errors"
|
"k8s.io/autoscaler/cluster-autoscaler/utils/errors"
|
||||||
"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -38,7 +37,7 @@ const (
|
||||||
// AzureCloudProvider provides implementation of CloudProvider interface for Azure.
|
// AzureCloudProvider provides implementation of CloudProvider interface for Azure.
|
||||||
type AzureCloudProvider struct {
|
type AzureCloudProvider struct {
|
||||||
azureManager *AzureManager
|
azureManager *AzureManager
|
||||||
scaleSets []*ScaleSet
|
nodeGroups []cloudprovider.NodeGroup
|
||||||
resourceLimiter *cloudprovider.ResourceLimiter
|
resourceLimiter *cloudprovider.ResourceLimiter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,12 +65,13 @@ func (azure *AzureCloudProvider) Cleanup() error {
|
||||||
// addNodeGroup adds node group defined in string spec. Format:
|
// addNodeGroup adds node group defined in string spec. Format:
|
||||||
// minNodes:maxNodes:scaleSetName
|
// minNodes:maxNodes:scaleSetName
|
||||||
func (azure *AzureCloudProvider) addNodeGroup(spec string) error {
|
func (azure *AzureCloudProvider) addNodeGroup(spec string) error {
|
||||||
scaleSet, err := buildScaleSet(spec, azure.azureManager)
|
nodeGroup, err := azure.buildNodeGroup(spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
azure.scaleSets = append(azure.scaleSets, scaleSet)
|
|
||||||
azure.azureManager.RegisterScaleSet(scaleSet)
|
azure.nodeGroups = append(azure.nodeGroups, nodeGroup)
|
||||||
|
azure.azureManager.RegisterNodeGroup(nodeGroup)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,9 +82,9 @@ func (azure *AzureCloudProvider) Name() string {
|
||||||
|
|
||||||
// NodeGroups returns all node groups configured for this cloud provider.
|
// NodeGroups returns all node groups configured for this cloud provider.
|
||||||
func (azure *AzureCloudProvider) NodeGroups() []cloudprovider.NodeGroup {
|
func (azure *AzureCloudProvider) NodeGroups() []cloudprovider.NodeGroup {
|
||||||
result := make([]cloudprovider.NodeGroup, 0, len(azure.scaleSets))
|
result := make([]cloudprovider.NodeGroup, 0, len(azure.nodeGroups))
|
||||||
for _, scaleSet := range azure.scaleSets {
|
for _, nodeGroup := range azure.nodeGroups {
|
||||||
result = append(result, scaleSet)
|
result = append(result, nodeGroup)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
@ -96,9 +96,7 @@ func (azure *AzureCloudProvider) NodeGroupForNode(node *apiv1.Node) (cloudprovid
|
||||||
Name: strings.ToLower(node.Spec.ProviderID),
|
Name: strings.ToLower(node.Spec.ProviderID),
|
||||||
}
|
}
|
||||||
|
|
||||||
scaleSet, err := azure.azureManager.GetScaleSetForInstance(ref)
|
return azure.azureManager.GetNodeGroupForInstance(ref)
|
||||||
|
|
||||||
return scaleSet, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pricing returns pricing model for this cloud provider or error if not available.
|
// Pricing returns pricing model for this cloud provider or error if not available.
|
||||||
|
|
@ -128,6 +126,46 @@ func (azure *AzureCloudProvider) Refresh() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create nodeGroup from provided spec.
|
||||||
|
// spec is in the following format: min-size:max-size:scale-set-name.
|
||||||
|
func (azure *AzureCloudProvider) buildNodeGroup(spec string) (cloudprovider.NodeGroup, error) {
|
||||||
|
tokens := strings.SplitN(spec, ":", 3)
|
||||||
|
if len(tokens) != 3 {
|
||||||
|
return nil, fmt.Errorf("wrong nodes configuration: %s", spec)
|
||||||
|
}
|
||||||
|
|
||||||
|
minSize := 0
|
||||||
|
maxSize := 0
|
||||||
|
name := tokens[2]
|
||||||
|
if size, err := strconv.Atoi(tokens[0]); err == nil {
|
||||||
|
if size <= 0 {
|
||||||
|
return nil, fmt.Errorf("min size must be >= 1, got: %d", size)
|
||||||
|
}
|
||||||
|
minSize = size
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("failed to set min size: %s, expected integer", tokens[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if size, err := strconv.Atoi(tokens[1]); err == nil {
|
||||||
|
if size < minSize {
|
||||||
|
return nil, fmt.Errorf("max size must be greater or equal to min size")
|
||||||
|
}
|
||||||
|
maxSize = size
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("failed to set max size: %s, expected integer", tokens[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
if tokens[2] == "" {
|
||||||
|
return nil, fmt.Errorf("scale set name must not be blank, got spec: %s", spec)
|
||||||
|
}
|
||||||
|
|
||||||
|
if azure.azureManager.config.VMType == vmTypeStandard {
|
||||||
|
return NewAgentPool(name, minSize, maxSize, azure.azureManager)
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewScaleSet(name, minSize, maxSize, azure.azureManager)
|
||||||
|
}
|
||||||
|
|
||||||
// AzureRef contains a reference to some entity in Azure world.
|
// AzureRef contains a reference to some entity in Azure world.
|
||||||
type AzureRef struct {
|
type AzureRef struct {
|
||||||
Name string
|
Name string
|
||||||
|
|
@ -137,207 +175,3 @@ type AzureRef struct {
|
||||||
func (m *AzureRef) GetKey() string {
|
func (m *AzureRef) GetKey() string {
|
||||||
return m.Name
|
return m.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
// AzureRefFromProviderId creates InstanceConfig object from provider id which
|
|
||||||
// must be in format: azure:///resourceGroupName/name
|
|
||||||
func AzureRefFromProviderId(id string) (*AzureRef, error) {
|
|
||||||
splitted := strings.Split(id[9:], "/")
|
|
||||||
if len(splitted) != 2 {
|
|
||||||
return nil, fmt.Errorf("Wrong id: expected format azure:///<unique-id>, got %v", id)
|
|
||||||
}
|
|
||||||
return &AzureRef{
|
|
||||||
Name: splitted[len(splitted)-1],
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScaleSet implements NodeGroup interface.
|
|
||||||
type ScaleSet struct {
|
|
||||||
AzureRef
|
|
||||||
|
|
||||||
azureManager *AzureManager
|
|
||||||
minSize int
|
|
||||||
maxSize int
|
|
||||||
}
|
|
||||||
|
|
||||||
// MinSize returns minimum size of the node group.
|
|
||||||
func (scaleSet *ScaleSet) MinSize() int {
|
|
||||||
return scaleSet.minSize
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exist checks if the node group really exists on the cloud provider side. Allows to tell the
|
|
||||||
// theoretical node group from the real one.
|
|
||||||
func (scaleSet *ScaleSet) Exist() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create creates the node group on the cloud provider side.
|
|
||||||
func (scaleSet *ScaleSet) Create() error {
|
|
||||||
return cloudprovider.ErrAlreadyExist
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete deletes the node group on the cloud provider side.
|
|
||||||
// This will be executed only for autoprovisioned node groups, once their size drops to 0.
|
|
||||||
func (scaleSet *ScaleSet) Delete() error {
|
|
||||||
return cloudprovider.ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
// Autoprovisioned returns true if the node group is autoprovisioned.
|
|
||||||
func (scaleSet *ScaleSet) Autoprovisioned() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// MaxSize returns maximum size of the node group.
|
|
||||||
func (scaleSet *ScaleSet) MaxSize() int {
|
|
||||||
return scaleSet.maxSize
|
|
||||||
}
|
|
||||||
|
|
||||||
// TargetSize returns the current TARGET size of the node group. It is possible that the
|
|
||||||
// number is different from the number of nodes registered in Kubernetes.
|
|
||||||
func (scaleSet *ScaleSet) TargetSize() (int, error) {
|
|
||||||
size, err := scaleSet.azureManager.GetScaleSetSize(scaleSet)
|
|
||||||
return int(size), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// IncreaseSize increases Scale Set size
|
|
||||||
func (scaleSet *ScaleSet) IncreaseSize(delta int) error {
|
|
||||||
if delta <= 0 {
|
|
||||||
return fmt.Errorf("size increase must be positive")
|
|
||||||
}
|
|
||||||
size, err := scaleSet.azureManager.GetScaleSetSize(scaleSet)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if int(size)+delta > scaleSet.MaxSize() {
|
|
||||||
return fmt.Errorf("size increase too large - desired:%d max:%d", int(size)+delta, scaleSet.MaxSize())
|
|
||||||
}
|
|
||||||
return scaleSet.azureManager.SetScaleSetSize(scaleSet, size+int64(delta))
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecreaseTargetSize decreases the target size of the node group. This function
|
|
||||||
// doesn't permit to delete any existing node and can be used only to reduce the
|
|
||||||
// request for new nodes that have not been yet fulfilled. Delta should be negative.
|
|
||||||
// It is assumed that cloud provider will not delete the existing nodes if the size
|
|
||||||
// when there is an option to just decrease the target.
|
|
||||||
func (scaleSet *ScaleSet) DecreaseTargetSize(delta int) error {
|
|
||||||
if delta >= 0 {
|
|
||||||
return fmt.Errorf("size decrease size must be negative")
|
|
||||||
}
|
|
||||||
size, err := scaleSet.azureManager.GetScaleSetSize(scaleSet)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
nodes, err := scaleSet.azureManager.GetScaleSetVms(scaleSet)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if int(size)+delta < len(nodes) {
|
|
||||||
return fmt.Errorf("attempt to delete existing nodes targetSize:%d delta:%d existingNodes: %d",
|
|
||||||
size, delta, len(nodes))
|
|
||||||
}
|
|
||||||
return scaleSet.azureManager.SetScaleSetSize(scaleSet, size+int64(delta))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Belongs returns true if the given node belongs to the NodeGroup.
|
|
||||||
func (scaleSet *ScaleSet) Belongs(node *apiv1.Node) (bool, error) {
|
|
||||||
glog.V(6).Infof("Check if node belongs to this scale set: scaleset:%v, node:%v\n", scaleSet, node)
|
|
||||||
|
|
||||||
ref := &AzureRef{
|
|
||||||
Name: strings.ToLower(node.Spec.ProviderID),
|
|
||||||
}
|
|
||||||
|
|
||||||
targetAsg, err := scaleSet.azureManager.GetScaleSetForInstance(ref)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if targetAsg == nil {
|
|
||||||
return false, fmt.Errorf("%s doesn't belong to a known scale set", node.Name)
|
|
||||||
}
|
|
||||||
if targetAsg.Id() != scaleSet.Id() {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteNodes deletes the nodes from the group.
|
|
||||||
func (scaleSet *ScaleSet) DeleteNodes(nodes []*apiv1.Node) error {
|
|
||||||
glog.V(8).Infof("Delete nodes requested: %v\n", nodes)
|
|
||||||
size, err := scaleSet.azureManager.GetScaleSetSize(scaleSet)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if int(size) <= scaleSet.MinSize() {
|
|
||||||
return fmt.Errorf("min size reached, nodes will not be deleted")
|
|
||||||
}
|
|
||||||
refs := make([]*AzureRef, 0, len(nodes))
|
|
||||||
for _, node := range nodes {
|
|
||||||
belongs, err := scaleSet.Belongs(node)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if belongs != true {
|
|
||||||
return fmt.Errorf("%s belongs to a different asg than %s", node.Name, scaleSet.Id())
|
|
||||||
}
|
|
||||||
azureRef := &AzureRef{
|
|
||||||
Name: strings.ToLower(node.Spec.ProviderID),
|
|
||||||
}
|
|
||||||
refs = append(refs, azureRef)
|
|
||||||
}
|
|
||||||
return scaleSet.azureManager.DeleteInstances(refs)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Id returns ScaleSet id.
|
|
||||||
func (scaleSet *ScaleSet) Id() string {
|
|
||||||
return scaleSet.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debug returns a debug string for the Scale Set.
|
|
||||||
func (scaleSet *ScaleSet) Debug() string {
|
|
||||||
return fmt.Sprintf("%s (%d:%d)", scaleSet.Id(), scaleSet.MinSize(), scaleSet.MaxSize())
|
|
||||||
}
|
|
||||||
|
|
||||||
// TemplateNodeInfo returns a node template for this scale set.
|
|
||||||
func (scaleSet *ScaleSet) TemplateNodeInfo() (*schedulercache.NodeInfo, error) {
|
|
||||||
return nil, cloudprovider.ErrNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create ScaleSet from provided spec.
|
|
||||||
// spec is in the following format: min-size:max-size:scale-set-name.
|
|
||||||
func buildScaleSet(spec string, azureManager *AzureManager) (*ScaleSet, error) {
|
|
||||||
tokens := strings.SplitN(spec, ":", 3)
|
|
||||||
if len(tokens) != 3 {
|
|
||||||
return nil, fmt.Errorf("wrong nodes configuration: %s", spec)
|
|
||||||
}
|
|
||||||
|
|
||||||
scaleSet := ScaleSet{
|
|
||||||
azureManager: azureManager,
|
|
||||||
}
|
|
||||||
if size, err := strconv.Atoi(tokens[0]); err == nil {
|
|
||||||
if size <= 0 {
|
|
||||||
return nil, fmt.Errorf("min size must be >= 1, got: %d", size)
|
|
||||||
}
|
|
||||||
scaleSet.minSize = size
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("failed to set min size: %s, expected integer", tokens[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
if size, err := strconv.Atoi(tokens[1]); err == nil {
|
|
||||||
if size < scaleSet.minSize {
|
|
||||||
return nil, fmt.Errorf("max size must be greater or equal to min size")
|
|
||||||
}
|
|
||||||
scaleSet.maxSize = size
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("failed to set max size: %s, expected integer", tokens[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
if tokens[2] == "" {
|
|
||||||
return nil, fmt.Errorf("scale set name must not be blank, got spec: %s", spec)
|
|
||||||
}
|
|
||||||
|
|
||||||
scaleSet.Name = tokens[2]
|
|
||||||
return &scaleSet, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nodes returns a list of all nodes that belong to this node group.
|
|
||||||
func (scaleSet *ScaleSet) Nodes() ([]string, error) {
|
|
||||||
return scaleSet.azureManager.GetScaleSetVms(scaleSet)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -17,100 +17,47 @@ limitations under the License.
|
||||||
package azure
|
package azure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/Azure/azure-sdk-for-go/arm/compute"
|
"github.com/Azure/go-autorest/autorest/azure"
|
||||||
"github.com/Azure/go-autorest/autorest"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/mock"
|
|
||||||
|
|
||||||
apiv1 "k8s.io/api/core/v1"
|
apiv1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
|
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Mock for VirtualMachineScaleSetsClient
|
func newTestAzureManager() *AzureManager {
|
||||||
type VirtualMachineScaleSetsClientMock struct {
|
return &AzureManager{
|
||||||
mock.Mock
|
config: &Config{VMType: vmTypeVMSS},
|
||||||
}
|
env: azure.PublicCloud,
|
||||||
|
|
||||||
func (client *VirtualMachineScaleSetsClientMock) Get(resourceGroupName string,
|
|
||||||
vmScaleSetName string) (result compute.VirtualMachineScaleSet, err error) {
|
|
||||||
capacity := int64(2)
|
|
||||||
properties := compute.VirtualMachineScaleSetProperties{}
|
|
||||||
return compute.VirtualMachineScaleSet{
|
|
||||||
Name: &vmScaleSetName,
|
|
||||||
Sku: &compute.Sku{
|
|
||||||
Capacity: &capacity,
|
|
||||||
},
|
|
||||||
VirtualMachineScaleSetProperties: &properties,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *VirtualMachineScaleSetsClientMock) CreateOrUpdate(
|
|
||||||
resourceGroupName string, vmScaleSetName string, parameters compute.VirtualMachineScaleSet, cancel <-chan struct{}) (<-chan compute.VirtualMachineScaleSet, <-chan error) {
|
|
||||||
errChan := make(chan error)
|
|
||||||
go func() {
|
|
||||||
errChan <- nil
|
|
||||||
}()
|
|
||||||
return nil, errChan
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *VirtualMachineScaleSetsClientMock) DeleteInstances(resourceGroupName string, vmScaleSetName string,
|
|
||||||
vmInstanceIDs compute.VirtualMachineScaleSetVMInstanceRequiredIDs, cancel <-chan struct{}) (<-chan compute.OperationStatusResponse, <-chan error) {
|
|
||||||
args := client.Called(resourceGroupName, vmScaleSetName, vmInstanceIDs, cancel)
|
|
||||||
errChan := make(chan error)
|
|
||||||
go func() {
|
|
||||||
errChan <- args.Error(1)
|
|
||||||
}()
|
|
||||||
return nil, errChan
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mock for VirtualMachineScaleSetVMsClient
|
|
||||||
type VirtualMachineScaleSetVMsClientMock struct {
|
|
||||||
mock.Mock
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *VirtualMachineScaleSetVMsClientMock) List(resourceGroupName string, virtualMachineScaleSetName string, filter string, selectParameter string, expand string) (result compute.VirtualMachineScaleSetVMListResult, err error) {
|
|
||||||
value := make([]compute.VirtualMachineScaleSetVM, 1)
|
|
||||||
vmInstanceID := "test-instance-id"
|
|
||||||
properties := compute.VirtualMachineScaleSetVMProperties{}
|
|
||||||
vmID := "123E4567-E89B-12D3-A456-426655440000"
|
|
||||||
properties.VMID = &vmID
|
|
||||||
value[0] = compute.VirtualMachineScaleSetVM{
|
|
||||||
ID: &vmID,
|
|
||||||
InstanceID: &vmInstanceID,
|
|
||||||
VirtualMachineScaleSetVMProperties: &properties,
|
|
||||||
}
|
|
||||||
|
|
||||||
return compute.VirtualMachineScaleSetVMListResult{
|
|
||||||
Value: &value,
|
|
||||||
}, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var testAzureManager = &AzureManager{
|
|
||||||
scaleSets: make([]*scaleSetInformation, 0),
|
|
||||||
scaleSetClient: &VirtualMachineScaleSetsClientMock{},
|
|
||||||
scaleSetVmClient: &VirtualMachineScaleSetVMsClientMock{},
|
|
||||||
scaleSetCache: make(map[AzureRef]*ScaleSet),
|
|
||||||
interrupt: make(chan struct{}),
|
interrupt: make(chan struct{}),
|
||||||
|
instanceIDsCache: make(map[string]string),
|
||||||
|
nodeGroups: make([]cloudprovider.NodeGroup, 0),
|
||||||
|
nodeGroupsCache: make(map[AzureRef]cloudprovider.NodeGroup),
|
||||||
|
|
||||||
|
disksClient: &DisksClientMock{},
|
||||||
|
interfacesClient: &InterfacesClientMock{},
|
||||||
|
storageAccountsClient: &AccountsClientMock{},
|
||||||
|
deploymentsClient: &DeploymentsClientMock{},
|
||||||
|
virtualMachinesClient: &VirtualMachinesClientMock{},
|
||||||
|
virtualMachineScaleSetsClient: &VirtualMachineScaleSetsClientMock{},
|
||||||
|
virtualMachineScaleSetVMsClient: &VirtualMachineScaleSetVMsClientMock{},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testProvider(t *testing.T, m *AzureManager) *AzureCloudProvider {
|
func newTestProvider() (*AzureCloudProvider, error) {
|
||||||
|
manager := newTestAzureManager()
|
||||||
resourceLimiter := cloudprovider.NewResourceLimiter(
|
resourceLimiter := cloudprovider.NewResourceLimiter(
|
||||||
map[string]int64{cloudprovider.ResourceNameCores: 1, cloudprovider.ResourceNameMemory: 10000000},
|
map[string]int64{cloudprovider.ResourceNameCores: 1, cloudprovider.ResourceNameMemory: 10000000},
|
||||||
map[string]int64{cloudprovider.ResourceNameCores: 10, cloudprovider.ResourceNameMemory: 100000000})
|
map[string]int64{cloudprovider.ResourceNameCores: 10, cloudprovider.ResourceNameMemory: 100000000})
|
||||||
provider, err := BuildAzureCloudProvider(m, nil, resourceLimiter)
|
return BuildAzureCloudProvider(manager, nil, resourceLimiter)
|
||||||
assert.NoError(t, err)
|
|
||||||
return provider
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildAzureCloudProvider(t *testing.T) {
|
func TestBuildAzureCloudProvider(t *testing.T) {
|
||||||
resourceLimiter := cloudprovider.NewResourceLimiter(
|
resourceLimiter := cloudprovider.NewResourceLimiter(
|
||||||
map[string]int64{cloudprovider.ResourceNameCores: 1, cloudprovider.ResourceNameMemory: 10000000},
|
map[string]int64{cloudprovider.ResourceNameCores: 1, cloudprovider.ResourceNameMemory: 10000000},
|
||||||
map[string]int64{cloudprovider.ResourceNameCores: 10, cloudprovider.ResourceNameMemory: 100000000})
|
map[string]int64{cloudprovider.ResourceNameCores: 10, cloudprovider.ResourceNameMemory: 100000000})
|
||||||
m := testAzureManager
|
m := newTestAzureManager()
|
||||||
_, err := BuildAzureCloudProvider(m, []string{"bad spec"}, resourceLimiter)
|
_, err := BuildAzureCloudProvider(m, []string{"bad spec"}, resourceLimiter)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
|
@ -119,56 +66,50 @@ func TestBuildAzureCloudProvider(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddNodeGroup(t *testing.T) {
|
func TestAddNodeGroup(t *testing.T) {
|
||||||
provider := testProvider(t, testAzureManager)
|
provider, err := newTestProvider()
|
||||||
err := provider.addNodeGroup("bad spec")
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = provider.addNodeGroup("bad spec")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Equal(t, len(provider.scaleSets), 0)
|
assert.Equal(t, len(provider.nodeGroups), 0)
|
||||||
|
|
||||||
err = provider.addNodeGroup("1:5:test-asg")
|
err = provider.addNodeGroup("1:5:test-asg")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, len(provider.scaleSets), 1)
|
assert.Equal(t, len(provider.nodeGroups), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestName(t *testing.T) {
|
func TestName(t *testing.T) {
|
||||||
provider := testProvider(t, testAzureManager)
|
provider, err := newTestProvider()
|
||||||
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, provider.Name(), "azure")
|
assert.Equal(t, provider.Name(), "azure")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNodeGroups(t *testing.T) {
|
func TestNodeGroups(t *testing.T) {
|
||||||
provider := testProvider(t, testAzureManager)
|
provider, err := newTestProvider()
|
||||||
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, len(provider.NodeGroups()), 0)
|
assert.Equal(t, len(provider.NodeGroups()), 0)
|
||||||
err := provider.addNodeGroup("1:5:test-asg")
|
|
||||||
|
err = provider.addNodeGroup("1:5:test-asg")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, len(provider.NodeGroups()), 1)
|
assert.Equal(t, len(provider.NodeGroups()), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNodeGroupForNode(t *testing.T) {
|
func TestNodeGroupForNode(t *testing.T) {
|
||||||
|
provider, err := newTestProvider()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = provider.addNodeGroup("1:5:test-asg")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, len(provider.nodeGroups), 1)
|
||||||
|
|
||||||
node := &apiv1.Node{
|
node := &apiv1.Node{
|
||||||
Spec: apiv1.NodeSpec{
|
Spec: apiv1.NodeSpec{
|
||||||
ProviderID: "azure://123E4567-E89B-12D3-A456-426655440000",
|
ProviderID: "azure://123E4567-E89B-12D3-A456-426655440000",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
scaleSetVmClient := VirtualMachineScaleSetVMsClientMock{}
|
|
||||||
|
|
||||||
var testAzureManager = &AzureManager{
|
|
||||||
scaleSets: make([]*scaleSetInformation, 0),
|
|
||||||
scaleSetClient: &VirtualMachineScaleSetsClientMock{},
|
|
||||||
scaleSetVmClient: &scaleSetVmClient,
|
|
||||||
scaleSetCache: make(map[AzureRef]*ScaleSet),
|
|
||||||
}
|
|
||||||
|
|
||||||
provider := testProvider(t, testAzureManager)
|
|
||||||
err := provider.addNodeGroup("1:5:test-asg")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
assert.Equal(t, len(provider.scaleSets), 1)
|
|
||||||
|
|
||||||
group, err := provider.NodeGroupForNode(node)
|
group, err := provider.NodeGroupForNode(node)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, group, "Group should not be nil")
|
assert.NotNil(t, group, "Group should not be nil")
|
||||||
|
|
||||||
assert.Equal(t, group.Id(), "test-asg")
|
assert.Equal(t, group.Id(), "test-asg")
|
||||||
assert.Equal(t, group.MinSize(), 1)
|
assert.Equal(t, group.MinSize(), 1)
|
||||||
assert.Equal(t, group.MaxSize(), 5)
|
assert.Equal(t, group.MaxSize(), 5)
|
||||||
|
|
@ -179,173 +120,36 @@ func TestNodeGroupForNode(t *testing.T) {
|
||||||
ProviderID: "azure:///subscriptions/subscripion/resourceGroups/test-resource-group/providers/Microsoft.Compute/virtualMachines/test-instance-id-not-in-group",
|
ProviderID: "azure:///subscriptions/subscripion/resourceGroups/test-resource-group/providers/Microsoft.Compute/virtualMachines/test-instance-id-not-in-group",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
group, err = provider.NodeGroupForNode(nodeNotInGroup)
|
group, err = provider.NodeGroupForNode(nodeNotInGroup)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Nil(t, group)
|
assert.Nil(t, group)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAzureRefFromProviderId(t *testing.T) {
|
func TestBuildNodeGroup(t *testing.T) {
|
||||||
_, err := AzureRefFromProviderId("azure:///123")
|
provider, err := newTestProvider()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = provider.buildNodeGroup("a")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
_, err = AzureRefFromProviderId("azure://test/rg/test-instance-id")
|
_, err = provider.buildNodeGroup("a:b:c")
|
||||||
|
assert.Error(t, err)
|
||||||
|
_, err = provider.buildNodeGroup("1:")
|
||||||
|
assert.Error(t, err)
|
||||||
|
_, err = provider.buildNodeGroup("1:2:")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
// Example id: "azure:///subscriptions/subscriptionId/resourceGroups/kubernetes/providers/Microsoft.Compute/virtualMachines/kubernetes-master"
|
_, err = provider.buildNodeGroup("-1:2:")
|
||||||
azureRef, err := AzureRefFromProviderId("azure:////kubernetes-master")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, &AzureRef{
|
|
||||||
Name: "kubernetes-master",
|
|
||||||
}, azureRef)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMaxSize(t *testing.T) {
|
|
||||||
provider := testProvider(t, testAzureManager)
|
|
||||||
err := provider.addNodeGroup("1:5:test-asg")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, len(provider.scaleSets), 1)
|
|
||||||
assert.Equal(t, provider.scaleSets[0].MaxSize(), 5)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMinSize(t *testing.T) {
|
|
||||||
provider := testProvider(t, testAzureManager)
|
|
||||||
err := provider.addNodeGroup("1:5:test-asg")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, len(provider.scaleSets), 1)
|
|
||||||
assert.Equal(t, provider.scaleSets[0].MinSize(), 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTargetSize(t *testing.T) {
|
|
||||||
provider := testProvider(t, testAzureManager)
|
|
||||||
err := provider.addNodeGroup("1:5:test-asg")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
targetSize, err := provider.scaleSets[0].TargetSize()
|
|
||||||
assert.Equal(t, targetSize, 2)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIncreaseSize(t *testing.T) {
|
|
||||||
var testAzureManager = &AzureManager{
|
|
||||||
scaleSets: make([]*scaleSetInformation, 0),
|
|
||||||
scaleSetClient: &VirtualMachineScaleSetsClientMock{},
|
|
||||||
scaleSetVmClient: &VirtualMachineScaleSetVMsClientMock{},
|
|
||||||
scaleSetCache: make(map[AzureRef]*ScaleSet),
|
|
||||||
}
|
|
||||||
|
|
||||||
provider := testProvider(t, testAzureManager)
|
|
||||||
|
|
||||||
err := provider.addNodeGroup("1:5:test-asg")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, len(provider.scaleSets), 1)
|
|
||||||
|
|
||||||
err = provider.scaleSets[0].IncreaseSize(1)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBelongs(t *testing.T) {
|
|
||||||
var testAzureManager = &AzureManager{
|
|
||||||
scaleSets: make([]*scaleSetInformation, 0),
|
|
||||||
scaleSetClient: &VirtualMachineScaleSetsClientMock{},
|
|
||||||
scaleSetVmClient: &VirtualMachineScaleSetVMsClientMock{},
|
|
||||||
scaleSetCache: make(map[AzureRef]*ScaleSet),
|
|
||||||
}
|
|
||||||
|
|
||||||
provider := testProvider(t, testAzureManager)
|
|
||||||
err := provider.addNodeGroup("1:5:test-asg")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
invalidNode := &apiv1.Node{
|
|
||||||
Spec: apiv1.NodeSpec{
|
|
||||||
ProviderID: "azure:///subscriptions/subscriptionId/resourceGroups/kubernetes/providers/Microsoft.Compute/virtualMachines/invalid-instance-id",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = provider.scaleSets[0].Belongs(invalidNode)
|
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
validNode := &apiv1.Node{
|
_, err = provider.buildNodeGroup("5:3:")
|
||||||
Spec: apiv1.NodeSpec{
|
|
||||||
ProviderID: "azure://123E4567-E89B-12D3-A456-426655440000",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
belongs, err := provider.scaleSets[0].Belongs(validNode)
|
|
||||||
assert.Equal(t, belongs, true)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDeleteNodes(t *testing.T) {
|
|
||||||
scaleSetClient := &VirtualMachineScaleSetsClientMock{}
|
|
||||||
m := &AzureManager{
|
|
||||||
scaleSets: make([]*scaleSetInformation, 0),
|
|
||||||
scaleSetClient: scaleSetClient,
|
|
||||||
scaleSetVmClient: &VirtualMachineScaleSetVMsClientMock{},
|
|
||||||
scaleSetCache: make(map[AzureRef]*ScaleSet),
|
|
||||||
}
|
|
||||||
|
|
||||||
instanceIds := make([]string, 1)
|
|
||||||
instanceIds[0] = "test-instance-id"
|
|
||||||
response := autorest.Response{
|
|
||||||
Response: &http.Response{
|
|
||||||
Status: "OK",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
scaleSetClient.On("DeleteInstances", mock.Anything, "test-asg", mock.Anything, mock.Anything).Return(response, nil)
|
|
||||||
|
|
||||||
provider := testProvider(t, m)
|
|
||||||
err := provider.addNodeGroup("1:5:test-asg")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
node := &apiv1.Node{
|
|
||||||
Spec: apiv1.NodeSpec{
|
|
||||||
ProviderID: "azure://123E4567-E89B-12D3-A456-426655440000",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
err = provider.scaleSets[0].DeleteNodes([]*apiv1.Node{node})
|
|
||||||
assert.NoError(t, err)
|
|
||||||
scaleSetClient.AssertNumberOfCalls(t, "DeleteInstances", 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestId(t *testing.T) {
|
|
||||||
provider := testProvider(t, testAzureManager)
|
|
||||||
err := provider.addNodeGroup("1:5:test-asg")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, len(provider.scaleSets), 1)
|
|
||||||
assert.Equal(t, provider.scaleSets[0].Id(), "test-asg")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDebug(t *testing.T) {
|
|
||||||
asg := ScaleSet{
|
|
||||||
azureManager: testAzureManager,
|
|
||||||
minSize: 5,
|
|
||||||
maxSize: 55,
|
|
||||||
}
|
|
||||||
asg.Name = "test-scale-set"
|
|
||||||
assert.Equal(t, asg.Debug(), "test-scale-set (5:55)")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildAsg(t *testing.T) {
|
|
||||||
_, err := buildScaleSet("a", nil)
|
|
||||||
assert.Error(t, err)
|
|
||||||
_, err = buildScaleSet("a:b:c", nil)
|
|
||||||
assert.Error(t, err)
|
|
||||||
_, err = buildScaleSet("1:", nil)
|
|
||||||
assert.Error(t, err)
|
|
||||||
_, err = buildScaleSet("1:2:", nil)
|
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
_, err = buildScaleSet("-1:2:", nil)
|
_, err = provider.buildNodeGroup("5:ddd:test-name")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
_, err = buildScaleSet("5:3:", nil)
|
asg, err := provider.buildNodeGroup("111:222:test-name")
|
||||||
assert.Error(t, err)
|
|
||||||
|
|
||||||
_, err = buildScaleSet("5:ddd:test-name", nil)
|
|
||||||
assert.Error(t, err)
|
|
||||||
|
|
||||||
asg, err := buildScaleSet("111:222:test-name", nil)
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 111, asg.MinSize())
|
assert.Equal(t, 111, asg.MinSize())
|
||||||
assert.Equal(t, 222, asg.MaxSize())
|
assert.Equal(t, 222, asg.MaxSize())
|
||||||
assert.Equal(t, "test-name", asg.Name)
|
assert.Equal(t, "test-name", asg.Id())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,284 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
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 (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/Azure/azure-sdk-for-go/arm/compute"
|
||||||
|
"github.com/Azure/azure-sdk-for-go/arm/disk"
|
||||||
|
"github.com/Azure/azure-sdk-for-go/arm/resources/resources"
|
||||||
|
"github.com/Azure/azure-sdk-for-go/arm/storage"
|
||||||
|
"github.com/Azure/go-autorest/autorest"
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// VirtualMachineScaleSetsClientMock mocks for VirtualMachineScaleSetsClient.
|
||||||
|
type VirtualMachineScaleSetsClientMock struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get gets the VirtualMachineScaleSet by vmScaleSetName.
|
||||||
|
func (client *VirtualMachineScaleSetsClientMock) Get(resourceGroupName string,
|
||||||
|
vmScaleSetName string) (result compute.VirtualMachineScaleSet, err error) {
|
||||||
|
capacity := int64(2)
|
||||||
|
properties := compute.VirtualMachineScaleSetProperties{}
|
||||||
|
return compute.VirtualMachineScaleSet{
|
||||||
|
Name: &vmScaleSetName,
|
||||||
|
Sku: &compute.Sku{
|
||||||
|
Capacity: &capacity,
|
||||||
|
},
|
||||||
|
VirtualMachineScaleSetProperties: &properties,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdate creates or updates the VirtualMachineScaleSet.
|
||||||
|
func (client *VirtualMachineScaleSetsClientMock) CreateOrUpdate(
|
||||||
|
resourceGroupName string, vmScaleSetName string, parameters compute.VirtualMachineScaleSet, cancel <-chan struct{}) (<-chan compute.VirtualMachineScaleSet, <-chan error) {
|
||||||
|
errChan := make(chan error)
|
||||||
|
go func() {
|
||||||
|
errChan <- nil
|
||||||
|
}()
|
||||||
|
return nil, errChan
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteInstances deletes a set of instances for specified VirtualMachineScaleSet.
|
||||||
|
func (client *VirtualMachineScaleSetsClientMock) DeleteInstances(resourceGroupName string, vmScaleSetName string,
|
||||||
|
vmInstanceIDs compute.VirtualMachineScaleSetVMInstanceRequiredIDs, cancel <-chan struct{}) (<-chan compute.OperationStatusResponse, <-chan error) {
|
||||||
|
args := client.Called(resourceGroupName, vmScaleSetName, vmInstanceIDs, cancel)
|
||||||
|
errChan := make(chan error)
|
||||||
|
go func() {
|
||||||
|
errChan <- args.Error(1)
|
||||||
|
}()
|
||||||
|
return nil, errChan
|
||||||
|
}
|
||||||
|
|
||||||
|
// VirtualMachineScaleSetVMsClientMock mocks for VirtualMachineScaleSetVMsClient.
|
||||||
|
type VirtualMachineScaleSetVMsClientMock struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// List gets a list of VirtualMachineScaleSetVMs.
|
||||||
|
func (m *VirtualMachineScaleSetVMsClientMock) List(resourceGroupName string, virtualMachineScaleSetName string, filter string, selectParameter string, expand string) (result compute.VirtualMachineScaleSetVMListResult, err error) {
|
||||||
|
value := make([]compute.VirtualMachineScaleSetVM, 1)
|
||||||
|
vmInstanceID := "test-instance-id"
|
||||||
|
properties := compute.VirtualMachineScaleSetVMProperties{}
|
||||||
|
vmID := "123E4567-E89B-12D3-A456-426655440000"
|
||||||
|
properties.VMID = &vmID
|
||||||
|
value[0] = compute.VirtualMachineScaleSetVM{
|
||||||
|
ID: &vmID,
|
||||||
|
InstanceID: &vmInstanceID,
|
||||||
|
VirtualMachineScaleSetVMProperties: &properties,
|
||||||
|
}
|
||||||
|
|
||||||
|
return compute.VirtualMachineScaleSetVMListResult{
|
||||||
|
Value: &value,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListNextResults gets more results from previous VirtualMachineScaleSetVMListResult.
|
||||||
|
func (m *VirtualMachineScaleSetVMsClientMock) ListNextResults(lastResults compute.VirtualMachineScaleSetVMListResult) (result compute.VirtualMachineScaleSetVMListResult, err error) {
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// VirtualMachinesClientMock mocks for VirtualMachinesClient.
|
||||||
|
type VirtualMachinesClientMock struct {
|
||||||
|
mock.Mock
|
||||||
|
|
||||||
|
mutex *sync.Mutex
|
||||||
|
FakeStore map[string]map[string]compute.VirtualMachine
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdate creates or updates the VirtualMachine.
|
||||||
|
func (m *VirtualMachinesClientMock) CreateOrUpdate(resourceGroupName string, VMName string, parameters compute.VirtualMachine, cancel <-chan struct{}) (<-chan compute.VirtualMachine, <-chan error) {
|
||||||
|
m.mutex.Lock()
|
||||||
|
defer m.mutex.Unlock()
|
||||||
|
resultChan := make(chan compute.VirtualMachine, 1)
|
||||||
|
errChan := make(chan error, 1)
|
||||||
|
var result compute.VirtualMachine
|
||||||
|
var err error
|
||||||
|
defer func() {
|
||||||
|
resultChan <- result
|
||||||
|
errChan <- err
|
||||||
|
close(resultChan)
|
||||||
|
close(errChan)
|
||||||
|
}()
|
||||||
|
if _, ok := m.FakeStore[resourceGroupName]; !ok {
|
||||||
|
m.FakeStore[resourceGroupName] = make(map[string]compute.VirtualMachine)
|
||||||
|
}
|
||||||
|
m.FakeStore[resourceGroupName][VMName] = parameters
|
||||||
|
result = m.FakeStore[resourceGroupName][VMName]
|
||||||
|
result.Response.Response = &http.Response{
|
||||||
|
StatusCode: http.StatusOK,
|
||||||
|
}
|
||||||
|
err = nil
|
||||||
|
return resultChan, errChan
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get gets the VirtualMachine by VMName.
|
||||||
|
func (m *VirtualMachinesClientMock) Get(resourceGroupName string, VMName string, expand compute.InstanceViewTypes) (result compute.VirtualMachine, err error) {
|
||||||
|
m.mutex.Lock()
|
||||||
|
defer m.mutex.Unlock()
|
||||||
|
if _, ok := m.FakeStore[resourceGroupName]; ok {
|
||||||
|
if entity, ok := m.FakeStore[resourceGroupName][VMName]; ok {
|
||||||
|
return entity, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result, autorest.DetailedError{
|
||||||
|
StatusCode: http.StatusNotFound,
|
||||||
|
Message: "Not such VM",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// List gets a lit of VirtualMachine inside the resource group.
|
||||||
|
func (m *VirtualMachinesClientMock) List(resourceGroupName string) (result compute.VirtualMachineListResult, err error) {
|
||||||
|
m.mutex.Lock()
|
||||||
|
defer m.mutex.Unlock()
|
||||||
|
|
||||||
|
var value []compute.VirtualMachine
|
||||||
|
if _, ok := m.FakeStore[resourceGroupName]; ok {
|
||||||
|
for _, v := range m.FakeStore[resourceGroupName] {
|
||||||
|
value = append(value, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.Response.Response = &http.Response{
|
||||||
|
StatusCode: http.StatusOK,
|
||||||
|
}
|
||||||
|
result.NextLink = nil
|
||||||
|
result.Value = &value
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListNextResults gets more results from previous VirtualMachineListResult.
|
||||||
|
func (m *VirtualMachinesClientMock) ListNextResults(lastResults compute.VirtualMachineListResult) (result compute.VirtualMachineListResult, err error) {
|
||||||
|
m.mutex.Lock()
|
||||||
|
defer m.mutex.Unlock()
|
||||||
|
return compute.VirtualMachineListResult{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete deletes the VirtualMachine by VMName.
|
||||||
|
func (m *VirtualMachinesClientMock) Delete(resourceGroupName string, VMName string, cancel <-chan struct{}) (<-chan compute.OperationStatusResponse, <-chan error) {
|
||||||
|
args := m.Called(resourceGroupName, VMName, cancel)
|
||||||
|
errChan := make(chan error)
|
||||||
|
go func() {
|
||||||
|
errChan <- args.Error(1)
|
||||||
|
}()
|
||||||
|
return nil, errChan
|
||||||
|
}
|
||||||
|
|
||||||
|
// InterfacesClientMock mocks for InterfacesClient.
|
||||||
|
type InterfacesClientMock struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete deletes the interface by networkInterfaceName.
|
||||||
|
func (m *InterfacesClientMock) Delete(resourceGroupName string, networkInterfaceName string, cancel <-chan struct{}) (<-chan autorest.Response, <-chan error) {
|
||||||
|
args := m.Called(resourceGroupName, networkInterfaceName, cancel)
|
||||||
|
errChan := make(chan error)
|
||||||
|
go func() {
|
||||||
|
errChan <- args.Error(1)
|
||||||
|
}()
|
||||||
|
return nil, errChan
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisksClientMock mocks for DisksClient.
|
||||||
|
type DisksClientMock struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete deletes the disk by diskName.
|
||||||
|
func (m *DisksClientMock) Delete(resourceGroupName string, diskName string, cancel <-chan struct{}) (<-chan disk.OperationStatusResponse, <-chan error) {
|
||||||
|
args := m.Called(resourceGroupName, diskName, cancel)
|
||||||
|
errChan := make(chan error)
|
||||||
|
go func() {
|
||||||
|
errChan <- args.Error(1)
|
||||||
|
}()
|
||||||
|
return nil, errChan
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccountsClientMock mocks for AccountsClient.
|
||||||
|
type AccountsClientMock struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListKeys get a list of keys by accountName.
|
||||||
|
func (m *AccountsClientMock) ListKeys(resourceGroupName string, accountName string) (result storage.AccountListKeysResult, err error) {
|
||||||
|
args := m.Called(resourceGroupName, accountName)
|
||||||
|
return storage.AccountListKeysResult{}, args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeploymentsClientMock mocks for DeploymentsClient.
|
||||||
|
type DeploymentsClientMock struct {
|
||||||
|
mock.Mock
|
||||||
|
|
||||||
|
mutex *sync.Mutex
|
||||||
|
FakeStore map[string]resources.DeploymentExtended
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get gets the DeploymentExtended by deploymentName.
|
||||||
|
func (m *DeploymentsClientMock) Get(resourceGroupName string, deploymentName string) (result resources.DeploymentExtended, err error) {
|
||||||
|
m.mutex.Lock()
|
||||||
|
defer m.mutex.Unlock()
|
||||||
|
|
||||||
|
deploy, ok := m.FakeStore[deploymentName]
|
||||||
|
if !ok {
|
||||||
|
return result, fmt.Errorf("deployment not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return deploy, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportTemplate exports the deployment's template.
|
||||||
|
func (m *DeploymentsClientMock) ExportTemplate(resourceGroupName string, deploymentName string) (result resources.DeploymentExportResult, err error) {
|
||||||
|
m.mutex.Lock()
|
||||||
|
defer m.mutex.Unlock()
|
||||||
|
|
||||||
|
deploy, ok := m.FakeStore[deploymentName]
|
||||||
|
if !ok {
|
||||||
|
return result, fmt.Errorf("deployment not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return resources.DeploymentExportResult{
|
||||||
|
Template: deploy.Properties.Template,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdate creates or updates the Deployment.
|
||||||
|
func (m *DeploymentsClientMock) CreateOrUpdate(resourceGroupName string, deploymentName string, parameters resources.Deployment, cancel <-chan struct{}) (<-chan resources.DeploymentExtended, <-chan error) {
|
||||||
|
m.mutex.Lock()
|
||||||
|
defer m.mutex.Unlock()
|
||||||
|
|
||||||
|
errChan := make(chan error)
|
||||||
|
go func() {
|
||||||
|
errChan <- nil
|
||||||
|
}()
|
||||||
|
|
||||||
|
deploy, ok := m.FakeStore[deploymentName]
|
||||||
|
if !ok {
|
||||||
|
deploy = resources.DeploymentExtended{
|
||||||
|
Properties: &resources.DeploymentPropertiesExtended{},
|
||||||
|
}
|
||||||
|
m.FakeStore[deploymentName] = deploy
|
||||||
|
}
|
||||||
|
|
||||||
|
deploy.Properties.Parameters = parameters.Properties.Parameters
|
||||||
|
deploy.Properties.Template = parameters.Properties.Template
|
||||||
|
return nil, errChan
|
||||||
|
}
|
||||||
|
|
@ -19,13 +19,18 @@ package azure
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Azure/azure-sdk-for-go/arm/compute"
|
"github.com/Azure/azure-sdk-for-go/arm/compute"
|
||||||
|
"github.com/Azure/azure-sdk-for-go/arm/disk"
|
||||||
|
"github.com/Azure/azure-sdk-for-go/arm/network"
|
||||||
|
"github.com/Azure/azure-sdk-for-go/arm/resources/resources"
|
||||||
|
"github.com/Azure/azure-sdk-for-go/arm/storage"
|
||||||
"github.com/Azure/go-autorest/autorest"
|
"github.com/Azure/go-autorest/autorest"
|
||||||
"github.com/Azure/go-autorest/autorest/adal"
|
"github.com/Azure/go-autorest/autorest/adal"
|
||||||
"github.com/Azure/go-autorest/autorest/azure"
|
"github.com/Azure/go-autorest/autorest/azure"
|
||||||
|
|
@ -33,35 +38,75 @@ import (
|
||||||
|
|
||||||
"gopkg.in/gcfg.v1"
|
"gopkg.in/gcfg.v1"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
|
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
|
||||||
)
|
)
|
||||||
|
|
||||||
type scaleSetInformation struct {
|
const (
|
||||||
config *ScaleSet
|
vmTypeVMSS = "vmss"
|
||||||
basename string
|
vmTypeStandard = "standard"
|
||||||
}
|
)
|
||||||
|
|
||||||
type scaleSetClient interface {
|
// VirtualMachineScaleSetsClient defines needed functions for azure compute.VirtualMachineScaleSetsClient.
|
||||||
|
type VirtualMachineScaleSetsClient interface {
|
||||||
Get(resourceGroupName string, vmScaleSetName string) (result compute.VirtualMachineScaleSet, err error)
|
Get(resourceGroupName string, vmScaleSetName string) (result compute.VirtualMachineScaleSet, err error)
|
||||||
CreateOrUpdate(resourceGroupName string, name string, parameters compute.VirtualMachineScaleSet, cancel <-chan struct{}) (<-chan compute.VirtualMachineScaleSet, <-chan error)
|
CreateOrUpdate(resourceGroupName string, name string, parameters compute.VirtualMachineScaleSet, cancel <-chan struct{}) (<-chan compute.VirtualMachineScaleSet, <-chan error)
|
||||||
DeleteInstances(resourceGroupName string, vmScaleSetName string, vmInstanceIDs compute.VirtualMachineScaleSetVMInstanceRequiredIDs, cancel <-chan struct{}) (<-chan compute.OperationStatusResponse, <-chan error)
|
DeleteInstances(resourceGroupName string, vmScaleSetName string, vmInstanceIDs compute.VirtualMachineScaleSetVMInstanceRequiredIDs, cancel <-chan struct{}) (<-chan compute.OperationStatusResponse, <-chan error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type scaleSetVMClient interface {
|
// VirtualMachineScaleSetVMsClient defines needed functions for azure compute.VirtualMachineScaleSetVMsClient.
|
||||||
|
type VirtualMachineScaleSetVMsClient interface {
|
||||||
List(resourceGroupName string, virtualMachineScaleSetName string, filter string, selectParameter string, expand string) (result compute.VirtualMachineScaleSetVMListResult, err error)
|
List(resourceGroupName string, virtualMachineScaleSetName string, filter string, selectParameter string, expand string) (result compute.VirtualMachineScaleSetVMListResult, err error)
|
||||||
|
ListNextResults(lastResults compute.VirtualMachineScaleSetVMListResult) (result compute.VirtualMachineScaleSetVMListResult, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// VirtualMachinesClient defines needed functions for azure compute.VirtualMachinesClient.
|
||||||
|
type VirtualMachinesClient interface {
|
||||||
|
Get(resourceGroupName string, VMName string, expand compute.InstanceViewTypes) (result compute.VirtualMachine, err error)
|
||||||
|
Delete(resourceGroupName string, VMName string, cancel <-chan struct{}) (<-chan compute.OperationStatusResponse, <-chan error)
|
||||||
|
List(resourceGroupName string) (result compute.VirtualMachineListResult, err error)
|
||||||
|
ListNextResults(lastResults compute.VirtualMachineListResult) (result compute.VirtualMachineListResult, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InterfacesClient defines needed functions for azure network.InterfacesClient.
|
||||||
|
type InterfacesClient interface {
|
||||||
|
Delete(resourceGroupName string, networkInterfaceName string, cancel <-chan struct{}) (<-chan autorest.Response, <-chan error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeploymentsClient defines needed functions for azure network.DeploymentsClient.
|
||||||
|
type DeploymentsClient interface {
|
||||||
|
Get(resourceGroupName string, deploymentName string) (result resources.DeploymentExtended, err error)
|
||||||
|
ExportTemplate(resourceGroupName string, deploymentName string) (result resources.DeploymentExportResult, err error)
|
||||||
|
CreateOrUpdate(resourceGroupName string, deploymentName string, parameters resources.Deployment, cancel <-chan struct{}) (<-chan resources.DeploymentExtended, <-chan error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisksClient defines needed functions for azure disk.DisksClient.
|
||||||
|
type DisksClient interface {
|
||||||
|
Delete(resourceGroupName string, diskName string, cancel <-chan struct{}) (<-chan disk.OperationStatusResponse, <-chan error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccountsClient defines needed functions for azure storage.AccountsClient.
|
||||||
|
type AccountsClient interface {
|
||||||
|
ListKeys(resourceGroupName string, accountName string) (result storage.AccountListKeysResult, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AzureManager handles Azure communication and data caching.
|
// AzureManager handles Azure communication and data caching.
|
||||||
type AzureManager struct {
|
type AzureManager struct {
|
||||||
resourceGroupName string
|
config *Config
|
||||||
subscription string
|
env azure.Environment
|
||||||
scaleSetClient scaleSetClient
|
|
||||||
scaleSetVmClient scaleSetVMClient
|
|
||||||
|
|
||||||
scaleSets []*scaleSetInformation
|
virtualMachineScaleSetsClient VirtualMachineScaleSetsClient
|
||||||
scaleSetCache map[AzureRef]*ScaleSet
|
virtualMachineScaleSetVMsClient VirtualMachineScaleSetVMsClient
|
||||||
|
virtualMachinesClient VirtualMachinesClient
|
||||||
|
deploymentsClient DeploymentsClient
|
||||||
|
interfacesClient InterfacesClient
|
||||||
|
disksClient DisksClient
|
||||||
|
storageAccountsClient AccountsClient
|
||||||
|
|
||||||
// cache of mapping from instance id to the scale set id
|
nodeGroups []cloudprovider.NodeGroup
|
||||||
scaleSetIdCache map[string]string
|
// cache of mapping from instance name to nodeGroup.
|
||||||
|
nodeGroupsCache map[AzureRef]cloudprovider.NodeGroup
|
||||||
|
// cache of mapping from instance name to instanceID.
|
||||||
|
instanceIDsCache map[string]string
|
||||||
|
|
||||||
cacheMutex sync.Mutex
|
cacheMutex sync.Mutex
|
||||||
interrupt chan struct{}
|
interrupt chan struct{}
|
||||||
|
|
@ -73,98 +118,179 @@ type Config struct {
|
||||||
TenantID string `json:"tenantId" yaml:"tenantId"`
|
TenantID string `json:"tenantId" yaml:"tenantId"`
|
||||||
SubscriptionID string `json:"subscriptionId" yaml:"subscriptionId"`
|
SubscriptionID string `json:"subscriptionId" yaml:"subscriptionId"`
|
||||||
ResourceGroup string `json:"resourceGroup" yaml:"resourceGroup"`
|
ResourceGroup string `json:"resourceGroup" yaml:"resourceGroup"`
|
||||||
Location string `json:"location" yaml:"location"`
|
VMType string `json:"vmType" yaml:"vmType"`
|
||||||
VnetName string `json:"vnetName" yaml:"vnetName"`
|
|
||||||
SubnetName string `json:"subnetName" yaml:"subnetName"`
|
|
||||||
SecurityGroupName string `json:"securityGroupName" yaml:"securityGroupName"`
|
|
||||||
RouteTableName string `json:"routeTableName" yaml:"routeTableName"`
|
|
||||||
PrimaryAvailabilitySetName string `json:"primaryAvailabilitySetName" yaml:"primaryAvailabilitySetName"`
|
|
||||||
|
|
||||||
AADClientID string `json:"aadClientId" yaml:"aadClientId"`
|
AADClientID string `json:"aadClientId" yaml:"aadClientId"`
|
||||||
AADClientSecret string `json:"aadClientSecret" yaml:"aadClientSecret"`
|
AADClientSecret string `json:"aadClientSecret" yaml:"aadClientSecret"`
|
||||||
AADTenantID string `json:"aadTenantId" yaml:"aadTenantId"`
|
AADClientCertPath string `json:"aadClientCertPath" yaml:"aadClientCertPath"`
|
||||||
|
AADClientCertPassword string `json:"aadClientCertPassword" yaml:"aadClientCertPassword"`
|
||||||
|
UseManagedIdentityExtension bool `json:"useManagedIdentityExtension" yaml:"useManagedIdentityExtension"`
|
||||||
|
|
||||||
|
// Configs only for standard vmType (agent pools).
|
||||||
|
Deployment string `json:"deployment" yaml:"deployment"`
|
||||||
|
APIServerPrivateKey string `json:"apiServerPrivateKey" yaml:"apiServerPrivateKey"`
|
||||||
|
CAPrivateKey string `json:"caPrivateKey" yaml:"caPrivateKey"`
|
||||||
|
ClientPrivateKey string `json:"clientPrivateKey" yaml:"clientPrivateKey"`
|
||||||
|
KubeConfigPrivateKey string `json:"kubeConfigPrivateKey" yaml:"kubeConfigPrivateKey"`
|
||||||
|
WindowsAdminPassword string `json:"windowsAdminPassword" yaml:"windowsAdminPassword"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateAzureManager creates Azure Manager object to work with Azure.
|
// CreateAzureManager creates Azure Manager object to work with Azure.
|
||||||
func CreateAzureManager(configReader io.Reader) (*AzureManager, error) {
|
func CreateAzureManager(configReader io.Reader) (*AzureManager, error) {
|
||||||
subscriptionId := string("")
|
var err error
|
||||||
resourceGroup := string("")
|
|
||||||
tenantId := string("")
|
|
||||||
clientId := string("")
|
|
||||||
clientSecret := string("")
|
|
||||||
var scaleSetAPI scaleSetClient
|
|
||||||
var scaleSetVmAPI scaleSetVMClient
|
|
||||||
if configReader != nil {
|
|
||||||
var cfg Config
|
var cfg Config
|
||||||
|
|
||||||
|
if configReader != nil {
|
||||||
if err := gcfg.ReadInto(&cfg, configReader); err != nil {
|
if err := gcfg.ReadInto(&cfg, configReader); err != nil {
|
||||||
glog.Errorf("Couldn't read config: %v", err)
|
glog.Errorf("Couldn't read config: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
subscriptionId = cfg.SubscriptionID
|
|
||||||
resourceGroup = cfg.ResourceGroup
|
|
||||||
tenantId = cfg.AADTenantID
|
|
||||||
clientId = cfg.AADClientID
|
|
||||||
clientSecret = cfg.AADClientSecret
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
subscriptionId = os.Getenv("ARM_SUBSCRIPTION_ID")
|
cfg.Cloud = os.Getenv("ARM_CLOUD")
|
||||||
resourceGroup = os.Getenv("ARM_RESOURCE_GROUP")
|
cfg.SubscriptionID = os.Getenv("ARM_SUBSCRIPTION_ID")
|
||||||
tenantId = os.Getenv("ARM_TENANT_ID")
|
cfg.ResourceGroup = os.Getenv("ARM_RESOURCE_GROUP")
|
||||||
clientId = os.Getenv("ARM_CLIENT_ID")
|
cfg.TenantID = os.Getenv("ARM_TENANT_ID")
|
||||||
clientSecret = os.Getenv("ARM_CLIENT_SECRET")
|
cfg.AADClientID = os.Getenv("ARM_CLIENT_ID")
|
||||||
}
|
cfg.AADClientSecret = os.Getenv("ARM_CLIENT_SECRET")
|
||||||
|
cfg.VMType = strings.ToLower(os.Getenv("ARM_VM_TYPE"))
|
||||||
|
cfg.AADClientCertPath = os.Getenv("ARM_CLIENT_CERT_PATH")
|
||||||
|
cfg.AADClientCertPassword = os.Getenv("ARM_CLIENT_CERT_PASSWORD")
|
||||||
|
cfg.Deployment = os.Getenv("ARM_DEPLOYMENT")
|
||||||
|
cfg.APIServerPrivateKey = os.Getenv("ARM_APISEVER_PRIVATE_KEY")
|
||||||
|
cfg.CAPrivateKey = os.Getenv("ARM_CA_PRIVATE_KEY")
|
||||||
|
cfg.ClientPrivateKey = os.Getenv("ARM_CLIENT_PRIVATE_KEY")
|
||||||
|
cfg.KubeConfigPrivateKey = os.Getenv("ARM_KUBECONFIG_PRIVATE_KEY")
|
||||||
|
cfg.WindowsAdminPassword = os.Getenv("ARM_WINDOWS_ADMIN_PASSWORD")
|
||||||
|
|
||||||
if resourceGroup == "" {
|
useManagedIdentityExtensionFromEnv := os.Getenv("ARM_USE_MANAGED_IDENTITY_EXTENSION")
|
||||||
panic("Resource group not found")
|
if len(useManagedIdentityExtensionFromEnv) > 0 {
|
||||||
}
|
cfg.UseManagedIdentityExtension, err = strconv.ParseBool(useManagedIdentityExtensionFromEnv)
|
||||||
|
|
||||||
if subscriptionId == "" {
|
|
||||||
panic("Subscription ID not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
if tenantId == "" {
|
|
||||||
panic("Tenant ID not found.")
|
|
||||||
}
|
|
||||||
|
|
||||||
if clientId == "" {
|
|
||||||
panic("ARM Client ID not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
if clientSecret == "" {
|
|
||||||
panic("ARM Client Secret not found.")
|
|
||||||
}
|
|
||||||
|
|
||||||
glog.Infof("read configuration: %v", subscriptionId)
|
|
||||||
|
|
||||||
spt, err := NewServicePrincipalTokenFromCredentials(tenantId, clientId, clientSecret, azure.PublicCloud.ServiceManagementEndpoint)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scaleSetAPI = compute.NewVirtualMachineScaleSetsClient(subscriptionId)
|
// Defaulting vmType to vmss.
|
||||||
scaleSetsClient := scaleSetAPI.(compute.VirtualMachineScaleSetsClient)
|
if cfg.VMType == "" {
|
||||||
|
cfg.VMType = vmTypeVMSS
|
||||||
|
}
|
||||||
|
|
||||||
|
env := azure.PublicCloud
|
||||||
|
if cfg.Cloud != "" {
|
||||||
|
env, err = azure.EnvironmentFromName(cfg.Cloud)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.ResourceGroup == "" {
|
||||||
|
return nil, fmt.Errorf("resource group not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.SubscriptionID == "" {
|
||||||
|
return nil, fmt.Errorf("subscription ID not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.TenantID == "" {
|
||||||
|
return nil, fmt.Errorf("tenant ID not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.AADClientID == "" {
|
||||||
|
return nil, fmt.Errorf("ARM Client ID not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.VMType == vmTypeStandard {
|
||||||
|
if cfg.Deployment == "" {
|
||||||
|
return nil, fmt.Errorf("deployment not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.APIServerPrivateKey == "" {
|
||||||
|
return nil, fmt.Errorf("apiServerPrivateKey not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.CAPrivateKey == "" {
|
||||||
|
return nil, fmt.Errorf("caPrivateKey not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.ClientPrivateKey == "" {
|
||||||
|
return nil, fmt.Errorf("clientPrivateKey not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.KubeConfigPrivateKey == "" {
|
||||||
|
return nil, fmt.Errorf("kubeConfigPrivateKey not set")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.Infof("Starting azure manager with subscription ID %q", cfg.SubscriptionID)
|
||||||
|
|
||||||
|
spt, err := NewServicePrincipalTokenFromCredentials(&cfg, &env)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
scaleSetsClient := compute.NewVirtualMachineScaleSetsClient(cfg.SubscriptionID)
|
||||||
|
scaleSetsClient.BaseURI = env.ResourceManagerEndpoint
|
||||||
scaleSetsClient.Authorizer = autorest.NewBearerAuthorizer(spt)
|
scaleSetsClient.Authorizer = autorest.NewBearerAuthorizer(spt)
|
||||||
scaleSetsClient.Sender = autorest.CreateSender()
|
scaleSetsClient.PollingDelay = 5 * time.Second
|
||||||
|
configureUserAgent(&scaleSetsClient.Client)
|
||||||
|
glog.V(5).Infof("Created scale set client with authorizer: %v", scaleSetsClient)
|
||||||
|
|
||||||
glog.Infof("Created scale set client with authorizer: %v", scaleSetsClient)
|
scaleSetVMsClient := compute.NewVirtualMachineScaleSetVMsClient(cfg.SubscriptionID)
|
||||||
|
scaleSetVMsClient.BaseURI = env.ResourceManagerEndpoint
|
||||||
scaleSetVmAPI = compute.NewVirtualMachineScaleSetVMsClient(subscriptionId)
|
|
||||||
scaleSetVMsClient := scaleSetVmAPI.(compute.VirtualMachineScaleSetVMsClient)
|
|
||||||
scaleSetVMsClient.Authorizer = autorest.NewBearerAuthorizer(spt)
|
scaleSetVMsClient.Authorizer = autorest.NewBearerAuthorizer(spt)
|
||||||
scaleSetVMsClient.RequestInspector = withInspection()
|
scaleSetVMsClient.PollingDelay = 5 * time.Second
|
||||||
scaleSetVMsClient.ResponseInspector = byInspecting()
|
configureUserAgent(&scaleSetVMsClient.Client)
|
||||||
|
glog.V(5).Infof("Created scale set vm client with authorizer: %v", scaleSetVMsClient)
|
||||||
|
|
||||||
glog.Infof("Created scale set vm client with authorizer: %v", scaleSetVMsClient)
|
virtualMachinesClient := compute.NewVirtualMachinesClient(cfg.SubscriptionID)
|
||||||
|
virtualMachinesClient.BaseURI = env.ResourceManagerEndpoint
|
||||||
|
virtualMachinesClient.Authorizer = autorest.NewBearerAuthorizer(spt)
|
||||||
|
virtualMachinesClient.PollingDelay = 5 * time.Second
|
||||||
|
configureUserAgent(&virtualMachinesClient.Client)
|
||||||
|
glog.V(5).Infof("Created vm client with authorizer: %v", virtualMachinesClient)
|
||||||
|
|
||||||
// Create Availability Sets Azure Client.
|
deploymentsClient := resources.NewDeploymentsClient(cfg.SubscriptionID)
|
||||||
|
deploymentsClient.BaseURI = env.ResourceManagerEndpoint
|
||||||
|
deploymentsClient.Authorizer = autorest.NewBearerAuthorizer(spt)
|
||||||
|
deploymentsClient.PollingDelay = 5 * time.Second
|
||||||
|
configureUserAgent(&deploymentsClient.Client)
|
||||||
|
glog.V(5).Infof("Created deployments client with authorizer: %v", deploymentsClient)
|
||||||
|
|
||||||
|
interfacesClient := network.NewInterfacesClient(cfg.SubscriptionID)
|
||||||
|
interfacesClient.BaseURI = env.ResourceManagerEndpoint
|
||||||
|
interfacesClient.Authorizer = autorest.NewBearerAuthorizer(spt)
|
||||||
|
interfacesClient.PollingDelay = 5 * time.Second
|
||||||
|
glog.V(5).Infof("Created interfaces client with authorizer: %v", interfacesClient)
|
||||||
|
|
||||||
|
storageAccountsClient := storage.NewAccountsClient(cfg.SubscriptionID)
|
||||||
|
storageAccountsClient.BaseURI = env.ResourceManagerEndpoint
|
||||||
|
storageAccountsClient.Authorizer = autorest.NewBearerAuthorizer(spt)
|
||||||
|
storageAccountsClient.PollingDelay = 5 * time.Second
|
||||||
|
glog.V(5).Infof("Created storage accounts client with authorizer: %v", storageAccountsClient)
|
||||||
|
|
||||||
|
disksClient := disk.NewDisksClient(cfg.SubscriptionID)
|
||||||
|
disksClient.BaseURI = env.ResourceManagerEndpoint
|
||||||
|
disksClient.Authorizer = autorest.NewBearerAuthorizer(spt)
|
||||||
|
disksClient.PollingDelay = 5 * time.Second
|
||||||
|
glog.V(5).Infof("Created disks client with authorizer: %v", disksClient)
|
||||||
|
|
||||||
|
// Create azure manager.
|
||||||
manager := &AzureManager{
|
manager := &AzureManager{
|
||||||
subscription: subscriptionId,
|
config: &cfg,
|
||||||
resourceGroupName: resourceGroup,
|
env: env,
|
||||||
scaleSetClient: scaleSetsClient,
|
disksClient: disksClient,
|
||||||
scaleSetVmClient: scaleSetVMsClient,
|
interfacesClient: interfacesClient,
|
||||||
scaleSets: make([]*scaleSetInformation, 0),
|
virtualMachineScaleSetsClient: scaleSetsClient,
|
||||||
scaleSetCache: make(map[AzureRef]*ScaleSet),
|
virtualMachineScaleSetVMsClient: scaleSetVMsClient,
|
||||||
|
deploymentsClient: deploymentsClient,
|
||||||
|
virtualMachinesClient: virtualMachinesClient,
|
||||||
|
storageAccountsClient: storageAccountsClient,
|
||||||
|
|
||||||
interrupt: make(chan struct{}),
|
interrupt: make(chan struct{}),
|
||||||
|
instanceIDsCache: make(map[string]string),
|
||||||
|
nodeGroups: make([]cloudprovider.NodeGroup, 0),
|
||||||
|
nodeGroupsCache: make(map[AzureRef]cloudprovider.NodeGroup),
|
||||||
}
|
}
|
||||||
|
|
||||||
go wait.Until(func() {
|
go wait.Until(func() {
|
||||||
|
|
@ -173,184 +299,237 @@ func CreateAzureManager(configReader io.Reader) (*AzureManager, error) {
|
||||||
if err := manager.regenerateCache(); err != nil {
|
if err := manager.regenerateCache(); err != nil {
|
||||||
glog.Errorf("Error while regenerating AS cache: %v", err)
|
glog.Errorf("Error while regenerating AS cache: %v", err)
|
||||||
}
|
}
|
||||||
}, time.Hour, manager.interrupt)
|
}, 5*time.Minute, manager.interrupt)
|
||||||
|
|
||||||
return manager, nil
|
return manager, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServicePrincipalTokenFromCredentials creates a new ServicePrincipalToken using values of the
|
// NewServicePrincipalTokenFromCredentials creates a new ServicePrincipalToken using values of the
|
||||||
// passed credentials map.
|
// passed credentials map.
|
||||||
func NewServicePrincipalTokenFromCredentials(tenantID string, clientID string, clientSecret string, scope string) (*adal.ServicePrincipalToken, error) {
|
func NewServicePrincipalTokenFromCredentials(config *Config, env *azure.Environment) (*adal.ServicePrincipalToken, error) {
|
||||||
oauthConfig, err := adal.NewOAuthConfig(azure.PublicCloud.ActiveDirectoryEndpoint, tenantID)
|
oauthConfig, err := adal.NewOAuthConfig(env.ActiveDirectoryEndpoint, config.TenantID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return nil, fmt.Errorf("creating the OAuth config: %v", err)
|
||||||
}
|
}
|
||||||
return adal.NewServicePrincipalToken(*oauthConfig, clientID, clientSecret, scope)
|
|
||||||
|
if config.UseManagedIdentityExtension {
|
||||||
|
glog.V(2).Infoln("azure: using managed identity extension to retrieve access token")
|
||||||
|
msiEndpoint, err := adal.GetMSIVMEndpoint()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Getting the managed service identity endpoint: %v", err)
|
||||||
|
}
|
||||||
|
return adal.NewServicePrincipalTokenFromMSI(
|
||||||
|
msiEndpoint,
|
||||||
|
env.ServiceManagementEndpoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(config.AADClientSecret) > 0 {
|
||||||
|
glog.V(2).Infoln("azure: using client_id+client_secret to retrieve access token")
|
||||||
|
return adal.NewServicePrincipalToken(
|
||||||
|
*oauthConfig,
|
||||||
|
config.AADClientID,
|
||||||
|
config.AADClientSecret,
|
||||||
|
env.ServiceManagementEndpoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(config.AADClientCertPath) > 0 && len(config.AADClientCertPassword) > 0 {
|
||||||
|
glog.V(2).Infoln("azure: using jwt client_assertion (client_cert+client_private_key) to retrieve access token")
|
||||||
|
certData, err := ioutil.ReadFile(config.AADClientCertPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("reading the client certificate from file %s: %v", config.AADClientCertPath, err)
|
||||||
|
}
|
||||||
|
certificate, privateKey, err := decodePkcs12(certData, config.AADClientCertPassword)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("decoding the client certificate: %v", err)
|
||||||
|
}
|
||||||
|
return adal.NewServicePrincipalTokenFromCertificate(
|
||||||
|
*oauthConfig,
|
||||||
|
config.AADClientID,
|
||||||
|
certificate,
|
||||||
|
privateKey,
|
||||||
|
env.ServiceManagementEndpoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("No credentials provided for AAD application %s", config.AADClientID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func withInspection() autorest.PrepareDecorator {
|
// RegisterNodeGroup registers node group in Azure Manager.
|
||||||
return func(p autorest.Preparer) autorest.Preparer {
|
func (m *AzureManager) RegisterNodeGroup(nodeGroup cloudprovider.NodeGroup) {
|
||||||
return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
|
||||||
glog.Infof("Inspecting Request: %s %s\n", r.Method, r.URL)
|
|
||||||
return p.Prepare(r)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func byInspecting() autorest.RespondDecorator {
|
|
||||||
return func(r autorest.Responder) autorest.Responder {
|
|
||||||
return autorest.ResponderFunc(func(resp *http.Response) error {
|
|
||||||
glog.Infof("Inspecting Response: %s for %s %s\n", resp.Status, resp.Request.Method, resp.Request.URL)
|
|
||||||
return r.Respond(resp)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RegisterScaleSet registers scale set in Azure Manager.
|
|
||||||
func (m *AzureManager) RegisterScaleSet(scaleSet *ScaleSet) {
|
|
||||||
m.cacheMutex.Lock()
|
m.cacheMutex.Lock()
|
||||||
defer m.cacheMutex.Unlock()
|
defer m.cacheMutex.Unlock()
|
||||||
|
|
||||||
m.scaleSets = append(m.scaleSets,
|
m.nodeGroups = append(m.nodeGroups, nodeGroup)
|
||||||
&scaleSetInformation{
|
|
||||||
config: scaleSet,
|
|
||||||
basename: scaleSet.Name,
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetScaleSetSize gets Scale Set size.
|
func (m *AzureManager) nodeGroupRegisted(nodeGroup string) bool {
|
||||||
func (m *AzureManager) GetScaleSetSize(asConfig *ScaleSet) (int64, error) {
|
for _, ng := range m.nodeGroups {
|
||||||
glog.V(5).Infof("Get scale set size: %v\n", asConfig)
|
if nodeGroup == ng.Id() {
|
||||||
set, err := m.scaleSetClient.Get(m.resourceGroupName, asConfig.Name)
|
return true
|
||||||
if err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
}
|
||||||
glog.V(5).Infof("Returning scale set capacity: %d\n", *set.Sku.Capacity)
|
|
||||||
return *set.Sku.Capacity, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetScaleSetSize sets ScaleSet size.
|
|
||||||
func (m *AzureManager) SetScaleSetSize(asConfig *ScaleSet, size int64) error {
|
|
||||||
op, err := m.scaleSetClient.Get(m.resourceGroupName, asConfig.Name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
op.Sku.Capacity = &size
|
|
||||||
op.VirtualMachineScaleSetProperties.ProvisioningState = nil
|
|
||||||
cancel := make(chan struct{})
|
|
||||||
|
|
||||||
_, errChan := m.scaleSetClient.CreateOrUpdate(m.resourceGroupName, asConfig.Name, op, cancel)
|
return false
|
||||||
return <-errChan
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetScaleSetForInstance returns ScaleSetConfig of the given Instance
|
// GetNodeGroupForInstance returns nodeGroup of the given Instance
|
||||||
func (m *AzureManager) GetScaleSetForInstance(instance *AzureRef) (*ScaleSet, error) {
|
func (m *AzureManager) GetNodeGroupForInstance(instance *AzureRef) (cloudprovider.NodeGroup, error) {
|
||||||
glog.V(5).Infof("Looking for scale set for instance: %v\n", instance)
|
glog.V(5).Infof("Looking for node group for instance: %q", instance)
|
||||||
|
|
||||||
glog.V(8).Infof("Cache BEFORE: %v\n", m.scaleSetCache)
|
glog.V(8).Infof("Cache BEFORE: %v\n", m.nodeGroupsCache)
|
||||||
|
|
||||||
m.cacheMutex.Lock()
|
m.cacheMutex.Lock()
|
||||||
defer m.cacheMutex.Unlock()
|
defer m.cacheMutex.Unlock()
|
||||||
if config, found := m.scaleSetCache[*instance]; found {
|
if nodeGroup, found := m.nodeGroupsCache[*instance]; found {
|
||||||
return config, nil
|
return nodeGroup, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := m.regenerateCache(); err != nil {
|
if err := m.regenerateCache(); err != nil {
|
||||||
return nil, fmt.Errorf("Error while looking for ScaleSet for instance %+v, error: %v", *instance, err)
|
return nil, fmt.Errorf("Error while looking for nodeGroup for instance %+v, error: %v", *instance, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
glog.V(8).Infof("Cache AFTER: %v\n", m.scaleSetCache)
|
glog.V(8).Infof("Cache AFTER: %v\n", m.nodeGroupsCache)
|
||||||
|
|
||||||
if config, found := m.scaleSetCache[*instance]; found {
|
if nodeGroup, found := m.nodeGroupsCache[*instance]; found {
|
||||||
return config, nil
|
return nodeGroup, nil
|
||||||
}
|
}
|
||||||
// instance does not belong to any configured Scale Set
|
|
||||||
|
// instance does not belong to any configured nodeGroup.
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteInstances deletes the given instances. All instances must be controlled by the same ASG.
|
// GetInstanceIDs gets instanceIDs for specified instances.
|
||||||
func (m *AzureManager) DeleteInstances(instances []*AzureRef) error {
|
func (m *AzureManager) GetInstanceIDs(instances []*AzureRef) []string {
|
||||||
if len(instances) == 0 {
|
m.cacheMutex.Lock()
|
||||||
return nil
|
defer m.cacheMutex.Unlock()
|
||||||
}
|
|
||||||
commonAsg, err := m.GetScaleSetForInstance(instances[0])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, instance := range instances {
|
|
||||||
asg, err := m.GetScaleSetForInstance(instance)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if asg != commonAsg {
|
|
||||||
return fmt.Errorf("cannot delete instance (%s) which don't belong to the same Scale Set", instance.GetKey())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
instanceIds := make([]string, len(instances))
|
instanceIds := make([]string, len(instances))
|
||||||
for i, instance := range instances {
|
for i, instance := range instances {
|
||||||
instanceIds[i] = m.scaleSetIdCache[instance.Name]
|
instanceIds[i] = m.instanceIDsCache[instance.Name]
|
||||||
}
|
}
|
||||||
requiredIds := &compute.VirtualMachineScaleSetVMInstanceRequiredIDs{
|
|
||||||
InstanceIds: &instanceIds,
|
return instanceIds
|
||||||
}
|
|
||||||
cancel := make(chan struct{})
|
|
||||||
_, errChan := m.scaleSetClient.DeleteInstances(m.resourceGroupName, commonAsg.Name, *requiredIds, cancel)
|
|
||||||
return <-errChan
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *AzureManager) regenerateCache() error {
|
func (m *AzureManager) regenerateCache() (err error) {
|
||||||
newCache := make(map[AzureRef]*ScaleSet)
|
var newCache map[AzureRef]cloudprovider.NodeGroup
|
||||||
newScaleSetIdCache := make(map[string]string)
|
var newInstanceIDsCache map[string]string
|
||||||
|
|
||||||
for _, sset := range m.scaleSets {
|
switch m.config.VMType {
|
||||||
glog.V(4).Infof("Regenerating Scale Set information for %s", sset.config.Name)
|
case vmTypeVMSS:
|
||||||
scaleSet, err := m.scaleSetClient.Get(m.resourceGroupName, sset.config.Name)
|
newCache, newInstanceIDsCache, err = m.listScaleSets()
|
||||||
if err != nil {
|
case vmTypeStandard:
|
||||||
glog.Errorf("Failed to get scaleSet with name %s: %v", sset.config.Name, err)
|
newCache, newInstanceIDsCache, err = m.listAgentPools()
|
||||||
return err
|
default:
|
||||||
|
err = fmt.Errorf("vmType %q not supported", m.config.VMType)
|
||||||
}
|
}
|
||||||
sset.basename = *scaleSet.Name
|
|
||||||
|
|
||||||
result, err := m.scaleSetVmClient.List(m.resourceGroupName, sset.basename, "", "", "")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Failed to list vm for scaleSet %s: %v", sset.config.Name, err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, instance := range *result.Value {
|
m.nodeGroupsCache = newCache
|
||||||
// Convert to lower because instance.ID is in different in different API calls (e.g. GET and LIST).
|
m.instanceIDsCache = newInstanceIDsCache
|
||||||
name := "azure://" + strings.ToLower(*instance.ID)
|
|
||||||
ref := AzureRef{
|
|
||||||
Name: name,
|
|
||||||
}
|
|
||||||
newCache[ref] = sset.config
|
|
||||||
newScaleSetIdCache[name] = *instance.InstanceID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m.scaleSetCache = newCache
|
|
||||||
m.scaleSetIdCache = newScaleSetIdCache
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetScaleSetVms returns list of nodes for the given scale set.
|
func (m *AzureManager) getNodeGroupByID(id string) cloudprovider.NodeGroup {
|
||||||
func (m *AzureManager) GetScaleSetVms(scaleSet *ScaleSet) ([]string, error) {
|
for _, ng := range m.nodeGroups {
|
||||||
instances, err := m.scaleSetVmClient.List(m.resourceGroupName, scaleSet.Name, "", "", "")
|
if id == ng.Id() {
|
||||||
|
return ng
|
||||||
if err != nil {
|
|
||||||
glog.V(4).Infof("Failed AS info request for %s: %v", scaleSet.Name, err)
|
|
||||||
return []string{}, err
|
|
||||||
}
|
}
|
||||||
result := make([]string, 0)
|
}
|
||||||
for _, instance := range *instances.Value {
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *AzureManager) listAgentPools() (map[AzureRef]cloudprovider.NodeGroup, map[string]string, error) {
|
||||||
|
as := make(map[AzureRef]cloudprovider.NodeGroup)
|
||||||
|
instanceIDs := make(map[string]string)
|
||||||
|
|
||||||
|
for _, nodeGroup := range m.nodeGroups {
|
||||||
|
agentPool, ok := nodeGroup.(*AgentPool)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("node group %q is not AgentPool", nodeGroup)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, vmIndex, err := agentPool.GetVMIndexes()
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("GetVMIndexes for node group %q failed: %v", nodeGroup.Id(), err)
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx := range vmIndex {
|
||||||
|
id := vmIndex[idx].ID
|
||||||
|
vmID := vmIndex[idx].VMID
|
||||||
|
|
||||||
|
idRef := AzureRef{
|
||||||
|
Name: id,
|
||||||
|
}
|
||||||
|
vmIDRef := AzureRef{
|
||||||
|
Name: vmID,
|
||||||
|
}
|
||||||
|
as[idRef] = nodeGroup
|
||||||
|
as[vmIDRef] = nodeGroup
|
||||||
|
instanceIDs[id] = fmt.Sprintf("%d", idx)
|
||||||
|
instanceIDs[vmID] = fmt.Sprintf("%d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return as, instanceIDs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// listScaleSets gets a list of scale sets and instanceIDs.
|
||||||
|
func (m *AzureManager) listScaleSets() (map[AzureRef]cloudprovider.NodeGroup, map[string]string, error) {
|
||||||
|
var err error
|
||||||
|
scaleSets := make(map[AzureRef]cloudprovider.NodeGroup)
|
||||||
|
instanceIDs := make(map[string]string)
|
||||||
|
|
||||||
|
for _, sset := range m.nodeGroups {
|
||||||
|
glog.V(4).Infof("Listing Scale Set information for %s", sset.Id())
|
||||||
|
|
||||||
|
resourceGroup := m.config.ResourceGroup
|
||||||
|
ssInfo, err := m.virtualMachineScaleSetsClient.Get(resourceGroup, sset.Id())
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("Failed to get scaleSet with name %s: %v", sset.Id(), err)
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := m.virtualMachineScaleSetVMsClient.List(resourceGroup, *ssInfo.Name, "", "", "")
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("Failed to list vm for scaleSet %s: %v", *ssInfo.Name, err)
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
moreResult := (result.Value != nil && len(*result.Value) > 0)
|
||||||
|
for moreResult {
|
||||||
|
for _, instance := range *result.Value {
|
||||||
// Convert to lower because instance.ID is in different in different API calls (e.g. GET and LIST).
|
// Convert to lower because instance.ID is in different in different API calls (e.g. GET and LIST).
|
||||||
name := "azure://" + strings.ToLower(*instance.ID)
|
name := "azure://" + strings.ToLower(*instance.ID)
|
||||||
result = append(result, name)
|
vmID := "azure://" + strings.ToLower(*instance.VMID)
|
||||||
|
ref := AzureRef{
|
||||||
|
Name: name,
|
||||||
|
}
|
||||||
|
vmIDRef := AzureRef{
|
||||||
|
Name: vmID,
|
||||||
|
}
|
||||||
|
scaleSets[ref] = sset
|
||||||
|
scaleSets[vmIDRef] = sset
|
||||||
|
instanceIDs[name] = *instance.InstanceID
|
||||||
}
|
}
|
||||||
return result, nil
|
|
||||||
|
|
||||||
|
moreResult = false
|
||||||
|
if result.NextLink != nil {
|
||||||
|
result, err = m.virtualMachineScaleSetVMsClient.ListNextResults(result)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("virtualMachineScaleSetVMsClient.ListNextResults failed: %v", err)
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
moreResult = (result.Value != nil && len(*result.Value) > 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return scaleSets, instanceIDs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup closes the channel to signal the go routine to stop that is handling the cache
|
// Cleanup closes the channel to signal the go routine to stop that is handling the cache
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,290 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
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 (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/Azure/azure-sdk-for-go/arm/compute"
|
||||||
|
"github.com/golang/glog"
|
||||||
|
|
||||||
|
apiv1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
|
||||||
|
"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ScaleSet implements NodeGroup interface.
|
||||||
|
type ScaleSet struct {
|
||||||
|
AzureRef
|
||||||
|
*AzureManager
|
||||||
|
|
||||||
|
minSize int
|
||||||
|
maxSize int
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewScaleSet creates a new NewScaleSet.
|
||||||
|
func NewScaleSet(name string, minSize, maxSize int, az *AzureManager) (*ScaleSet, error) {
|
||||||
|
scaleSet := &ScaleSet{
|
||||||
|
AzureRef: AzureRef{
|
||||||
|
Name: name,
|
||||||
|
},
|
||||||
|
minSize: minSize,
|
||||||
|
maxSize: maxSize,
|
||||||
|
AzureManager: az,
|
||||||
|
}
|
||||||
|
|
||||||
|
return scaleSet, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MinSize returns minimum size of the node group.
|
||||||
|
func (scaleSet *ScaleSet) MinSize() int {
|
||||||
|
return scaleSet.minSize
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exist checks if the node group really exists on the cloud provider side. Allows to tell the
|
||||||
|
// theoretical node group from the real one.
|
||||||
|
func (scaleSet *ScaleSet) Exist() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create creates the node group on the cloud provider side.
|
||||||
|
func (scaleSet *ScaleSet) Create() error {
|
||||||
|
return cloudprovider.ErrAlreadyExist
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete deletes the node group on the cloud provider side.
|
||||||
|
// This will be executed only for autoprovisioned node groups, once their size drops to 0.
|
||||||
|
func (scaleSet *ScaleSet) Delete() error {
|
||||||
|
return cloudprovider.ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
// Autoprovisioned returns true if the node group is autoprovisioned.
|
||||||
|
func (scaleSet *ScaleSet) Autoprovisioned() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxSize returns maximum size of the node group.
|
||||||
|
func (scaleSet *ScaleSet) MaxSize() int {
|
||||||
|
return scaleSet.maxSize
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetScaleSetSize gets Scale Set size.
|
||||||
|
func (scaleSet *ScaleSet) GetScaleSetSize() (int64, error) {
|
||||||
|
glog.V(5).Infof("Get scale set size for %q", scaleSet.Name)
|
||||||
|
resourceGroup := scaleSet.config.ResourceGroup
|
||||||
|
set, err := scaleSet.virtualMachineScaleSetsClient.Get(resourceGroup, scaleSet.Name)
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
glog.V(5).Infof("Returning scale set (%q) capacity: %d\n", scaleSet.Name, *set.Sku.Capacity)
|
||||||
|
return *set.Sku.Capacity, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetScaleSetSize sets ScaleSet size.
|
||||||
|
func (scaleSet *ScaleSet) SetScaleSetSize(size int64) error {
|
||||||
|
resourceGroup := scaleSet.config.ResourceGroup
|
||||||
|
op, err := scaleSet.virtualMachineScaleSetsClient.Get(resourceGroup, scaleSet.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
op.Sku.Capacity = &size
|
||||||
|
op.VirtualMachineScaleSetProperties.ProvisioningState = nil
|
||||||
|
cancel := make(chan struct{})
|
||||||
|
|
||||||
|
_, errChan := scaleSet.virtualMachineScaleSetsClient.CreateOrUpdate(resourceGroup, scaleSet.Name, op, cancel)
|
||||||
|
return <-errChan
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetSize returns the current TARGET size of the node group. It is possible that the
|
||||||
|
// number is different from the number of nodes registered in Kubernetes.
|
||||||
|
func (scaleSet *ScaleSet) TargetSize() (int, error) {
|
||||||
|
size, err := scaleSet.GetScaleSetSize()
|
||||||
|
return int(size), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IncreaseSize increases Scale Set size
|
||||||
|
func (scaleSet *ScaleSet) IncreaseSize(delta int) error {
|
||||||
|
if delta <= 0 {
|
||||||
|
return fmt.Errorf("size increase must be positive")
|
||||||
|
}
|
||||||
|
|
||||||
|
size, err := scaleSet.GetScaleSetSize()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if int(size)+delta > scaleSet.MaxSize() {
|
||||||
|
return fmt.Errorf("size increase too large - desired:%d max:%d", int(size)+delta, scaleSet.MaxSize())
|
||||||
|
}
|
||||||
|
|
||||||
|
return scaleSet.SetScaleSetSize(size + int64(delta))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetScaleSetVms returns list of nodes for the given scale set.
|
||||||
|
func (scaleSet *ScaleSet) GetScaleSetVms() ([]string, error) {
|
||||||
|
resourceGroup := scaleSet.config.ResourceGroup
|
||||||
|
instances, err := scaleSet.virtualMachineScaleSetVMsClient.List(resourceGroup, scaleSet.Name, "", "", "")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
glog.V(4).Infof("VirtualMachineScaleSetVMsClient.List failed for %s: %v", scaleSet.Name, err)
|
||||||
|
return []string{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make([]string, 0)
|
||||||
|
for _, instance := range *instances.Value {
|
||||||
|
// Convert to lower because instance.ID is in different in different API calls (e.g. GET and LIST).
|
||||||
|
name := "azure://" + strings.ToLower(*instance.ID)
|
||||||
|
result = append(result, name)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecreaseTargetSize decreases the target size of the node group. This function
|
||||||
|
// doesn't permit to delete any existing node and can be used only to reduce the
|
||||||
|
// request for new nodes that have not been yet fulfilled. Delta should be negative.
|
||||||
|
// It is assumed that cloud provider will not delete the existing nodes if the size
|
||||||
|
// when there is an option to just decrease the target.
|
||||||
|
func (scaleSet *ScaleSet) DecreaseTargetSize(delta int) error {
|
||||||
|
if delta >= 0 {
|
||||||
|
return fmt.Errorf("size decrease size must be negative")
|
||||||
|
}
|
||||||
|
|
||||||
|
size, err := scaleSet.GetScaleSetSize()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes, err := scaleSet.GetScaleSetVms()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if int(size)+delta < len(nodes) {
|
||||||
|
return fmt.Errorf("attempt to delete existing nodes targetSize:%d delta:%d existingNodes: %d",
|
||||||
|
size, delta, len(nodes))
|
||||||
|
}
|
||||||
|
|
||||||
|
return scaleSet.SetScaleSetSize(size + int64(delta))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Belongs returns true if the given node belongs to the NodeGroup.
|
||||||
|
func (scaleSet *ScaleSet) Belongs(node *apiv1.Node) (bool, error) {
|
||||||
|
glog.V(6).Infof("Check if node belongs to this scale set: scaleset:%v, node:%v\n", scaleSet, node)
|
||||||
|
|
||||||
|
ref := &AzureRef{
|
||||||
|
Name: strings.ToLower(node.Spec.ProviderID),
|
||||||
|
}
|
||||||
|
|
||||||
|
targetAsg, err := scaleSet.GetNodeGroupForInstance(ref)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if targetAsg == nil {
|
||||||
|
return false, fmt.Errorf("%s doesn't belong to a known scale set", node.Name)
|
||||||
|
}
|
||||||
|
if targetAsg.Id() != scaleSet.Id() {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteInstances deletes the given instances. All instances must be controlled by the same ASG.
|
||||||
|
func (scaleSet *ScaleSet) DeleteInstances(instances []*AzureRef) error {
|
||||||
|
if len(instances) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
commonAsg, err := scaleSet.GetNodeGroupForInstance(instances[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, instance := range instances {
|
||||||
|
asg, err := scaleSet.GetNodeGroupForInstance(instance)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if asg != commonAsg {
|
||||||
|
return fmt.Errorf("cannot delete instance (%s) which don't belong to the same Scale Set (%q)", instance.GetKey(), commonAsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
instanceIds := scaleSet.GetInstanceIDs(instances)
|
||||||
|
requiredIds := &compute.VirtualMachineScaleSetVMInstanceRequiredIDs{
|
||||||
|
InstanceIds: &instanceIds,
|
||||||
|
}
|
||||||
|
cancel := make(chan struct{})
|
||||||
|
resourceGroup := scaleSet.config.ResourceGroup
|
||||||
|
_, errChan := scaleSet.virtualMachineScaleSetsClient.DeleteInstances(resourceGroup, commonAsg.Id(), *requiredIds, cancel)
|
||||||
|
return <-errChan
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteNodes deletes the nodes from the group.
|
||||||
|
func (scaleSet *ScaleSet) DeleteNodes(nodes []*apiv1.Node) error {
|
||||||
|
glog.V(8).Infof("Delete nodes requested: %v\n", nodes)
|
||||||
|
size, err := scaleSet.GetScaleSetSize()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if int(size) <= scaleSet.MinSize() {
|
||||||
|
return fmt.Errorf("min size reached, nodes will not be deleted")
|
||||||
|
}
|
||||||
|
|
||||||
|
refs := make([]*AzureRef, 0, len(nodes))
|
||||||
|
for _, node := range nodes {
|
||||||
|
belongs, err := scaleSet.Belongs(node)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if belongs != true {
|
||||||
|
return fmt.Errorf("%s belongs to a different asg than %s", node.Name, scaleSet.Id())
|
||||||
|
}
|
||||||
|
|
||||||
|
azureRef := &AzureRef{
|
||||||
|
Name: strings.ToLower(node.Spec.ProviderID),
|
||||||
|
}
|
||||||
|
refs = append(refs, azureRef)
|
||||||
|
}
|
||||||
|
|
||||||
|
return scaleSet.DeleteInstances(refs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Id returns ScaleSet id.
|
||||||
|
func (scaleSet *ScaleSet) Id() string {
|
||||||
|
return scaleSet.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug returns a debug string for the Scale Set.
|
||||||
|
func (scaleSet *ScaleSet) Debug() string {
|
||||||
|
return fmt.Sprintf("%s (%d:%d)", scaleSet.Id(), scaleSet.MinSize(), scaleSet.MaxSize())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TemplateNodeInfo returns a node template for this scale set.
|
||||||
|
func (scaleSet *ScaleSet) TemplateNodeInfo() (*schedulercache.NodeInfo, error) {
|
||||||
|
return nil, cloudprovider.ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nodes returns a list of all nodes that belong to this node group.
|
||||||
|
func (scaleSet *ScaleSet) Nodes() ([]string, error) {
|
||||||
|
return scaleSet.GetScaleSetVms()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
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 (
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/Azure/go-autorest/autorest"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
apiv1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMaxSize(t *testing.T) {
|
||||||
|
provider, err := newTestProvider()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = provider.addNodeGroup("1:5:test-asg")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, len(provider.nodeGroups), 1)
|
||||||
|
assert.Equal(t, provider.nodeGroups[0].MaxSize(), 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMinSize(t *testing.T) {
|
||||||
|
provider, err := newTestProvider()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = provider.addNodeGroup("1:5:test-asg")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, len(provider.nodeGroups), 1)
|
||||||
|
assert.Equal(t, provider.nodeGroups[0].MinSize(), 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTargetSize(t *testing.T) {
|
||||||
|
provider, err := newTestProvider()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = provider.addNodeGroup("1:5:test-asg")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
targetSize, err := provider.nodeGroups[0].TargetSize()
|
||||||
|
assert.Equal(t, targetSize, 2)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIncreaseSize(t *testing.T) {
|
||||||
|
provider, err := newTestProvider()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = provider.addNodeGroup("1:5:test-asg")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, len(provider.nodeGroups), 1)
|
||||||
|
|
||||||
|
err = provider.nodeGroups[0].IncreaseSize(1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBelongs(t *testing.T) {
|
||||||
|
provider, err := newTestProvider()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = provider.addNodeGroup("1:5:test-asg")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
scaleSet, ok := provider.nodeGroups[0].(*ScaleSet)
|
||||||
|
assert.True(t, ok)
|
||||||
|
|
||||||
|
invalidNode := &apiv1.Node{
|
||||||
|
Spec: apiv1.NodeSpec{
|
||||||
|
ProviderID: "azure:///subscriptions/subscriptionId/resourceGroups/kubernetes/providers/Microsoft.Compute/virtualMachines/invalid-instance-id",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err = scaleSet.Belongs(invalidNode)
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
validNode := &apiv1.Node{
|
||||||
|
Spec: apiv1.NodeSpec{
|
||||||
|
ProviderID: "azure://123E4567-E89B-12D3-A456-426655440000",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
belongs, err := scaleSet.Belongs(validNode)
|
||||||
|
assert.Equal(t, true, belongs)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeleteNodes(t *testing.T) {
|
||||||
|
manager := newTestAzureManager()
|
||||||
|
scaleSetClient := &VirtualMachineScaleSetsClientMock{}
|
||||||
|
instanceIds := make([]string, 1)
|
||||||
|
instanceIds[0] = "test-instance-id"
|
||||||
|
response := autorest.Response{
|
||||||
|
Response: &http.Response{
|
||||||
|
Status: "OK",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
scaleSetClient.On("DeleteInstances", mock.Anything, "test-asg", mock.Anything, mock.Anything).Return(response, nil)
|
||||||
|
manager.virtualMachineScaleSetsClient = scaleSetClient
|
||||||
|
|
||||||
|
resourceLimiter := cloudprovider.NewResourceLimiter(
|
||||||
|
map[string]int64{cloudprovider.ResourceNameCores: 1, cloudprovider.ResourceNameMemory: 10000000},
|
||||||
|
map[string]int64{cloudprovider.ResourceNameCores: 10, cloudprovider.ResourceNameMemory: 100000000})
|
||||||
|
provider, err := BuildAzureCloudProvider(manager, nil, resourceLimiter)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = provider.addNodeGroup("1:5:test-asg")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
node := &apiv1.Node{
|
||||||
|
Spec: apiv1.NodeSpec{
|
||||||
|
ProviderID: "azure://123E4567-E89B-12D3-A456-426655440000",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
scaleSet, ok := provider.nodeGroups[0].(*ScaleSet)
|
||||||
|
assert.True(t, ok)
|
||||||
|
err = scaleSet.DeleteNodes([]*apiv1.Node{node})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
scaleSetClient.AssertNumberOfCalls(t, "DeleteInstances", 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestId(t *testing.T) {
|
||||||
|
provider, err := newTestProvider()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = provider.addNodeGroup("1:5:test-asg")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, len(provider.nodeGroups), 1)
|
||||||
|
assert.Equal(t, provider.nodeGroups[0].Id(), "test-asg")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDebug(t *testing.T) {
|
||||||
|
asg := ScaleSet{
|
||||||
|
AzureManager: newTestAzureManager(),
|
||||||
|
minSize: 5,
|
||||||
|
maxSize: 55,
|
||||||
|
}
|
||||||
|
asg.Name = "test-scale-set"
|
||||||
|
assert.Equal(t, asg.Debug(), "test-scale-set (5:55)")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,349 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
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 (
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"regexp"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/Azure/azure-sdk-for-go/arm/compute"
|
||||||
|
"github.com/Azure/go-autorest/autorest"
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"golang.org/x/crypto/pkcs12"
|
||||||
|
"k8s.io/client-go/pkg/version"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
//Field names
|
||||||
|
customDataFieldName = "customData"
|
||||||
|
dependsOnFieldName = "dependsOn"
|
||||||
|
hardwareProfileFieldName = "hardwareProfile"
|
||||||
|
imageReferenceFieldName = "imageReference"
|
||||||
|
nameFieldName = "name"
|
||||||
|
osProfileFieldName = "osProfile"
|
||||||
|
propertiesFieldName = "properties"
|
||||||
|
resourcesFieldName = "resources"
|
||||||
|
storageProfileFieldName = "storageProfile"
|
||||||
|
typeFieldName = "type"
|
||||||
|
vmSizeFieldName = "vmSize"
|
||||||
|
|
||||||
|
// ARM resource Types
|
||||||
|
nsgResourceType = "Microsoft.Network/networkSecurityGroups"
|
||||||
|
rtResourceType = "Microsoft.Network/routeTables"
|
||||||
|
vmResourceType = "Microsoft.Compute/virtualMachines"
|
||||||
|
vmExtensionType = "Microsoft.Compute/virtualMachines/extensions"
|
||||||
|
|
||||||
|
// resource ids
|
||||||
|
nsgID = "nsgID"
|
||||||
|
rtID = "routeTableID"
|
||||||
|
|
||||||
|
k8sLinuxVMNamingFormat = "^[0-9a-zA-Z]{3}-(.+)-([0-9a-fA-F]{8})-{0,2}([0-9]+)$"
|
||||||
|
k8sLinuxVMAgentPoolNameIndex = 1
|
||||||
|
k8sLinuxVMAgentClusterIDIndex = 2
|
||||||
|
k8sLinuxVMAgentIndexArrayIndex = 3
|
||||||
|
|
||||||
|
k8sWindowsVMNamingFormat = "^([a-fA-F0-9]{5})([0-9a-zA-Z]{3})([a-zA-Z0-9]{4,6})$"
|
||||||
|
k8sWindowsVMAgentPoolPrefixIndex = 1
|
||||||
|
k8sWindowsVMAgentOrchestratorNameIndex = 2
|
||||||
|
k8sWindowsVMAgentPoolInfoIndex = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
vmnameLinuxRegexp = regexp.MustCompile(k8sLinuxVMNamingFormat)
|
||||||
|
vmnameWindowsRegexp = regexp.MustCompile(k8sWindowsVMNamingFormat)
|
||||||
|
)
|
||||||
|
|
||||||
|
// decodePkcs12 decodes a PKCS#12 client certificate by extracting the public certificate and
|
||||||
|
// the private RSA key
|
||||||
|
func decodePkcs12(pkcs []byte, password string) (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||||
|
privateKey, certificate, err := pkcs12.Decode(pkcs, password)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("decoding the PKCS#12 client certificate: %v", err)
|
||||||
|
}
|
||||||
|
rsaPrivateKey, isRsaKey := privateKey.(*rsa.PrivateKey)
|
||||||
|
if !isRsaKey {
|
||||||
|
return nil, nil, fmt.Errorf("PKCS#12 certificate must contain a RSA private key")
|
||||||
|
}
|
||||||
|
|
||||||
|
return certificate, rsaPrivateKey, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// configureUserAgent configures the autorest client with a user agent that
|
||||||
|
// includes "autoscaler" and the full client version string
|
||||||
|
// example:
|
||||||
|
// Azure-SDK-for-Go/7.0.1-beta arm-network/2016-09-01; cluster-autoscaler/v1.7.0-alpha.2.711+a2fadef8170bb0-dirty;
|
||||||
|
func configureUserAgent(client *autorest.Client) {
|
||||||
|
k8sVersion := version.Get().GitVersion
|
||||||
|
client.UserAgent = fmt.Sprintf("%s; cluster-autoscaler/%s", client.UserAgent, k8sVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalizeForK8sVMASScalingUp takes a template and removes elements that are unwanted in a K8s VMAS scale up/down case
|
||||||
|
func normalizeForK8sVMASScalingUp(templateMap map[string]interface{}) error {
|
||||||
|
if err := normalizeMasterResourcesForScaling(templateMap); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rtIndex := -1
|
||||||
|
nsgIndex := -1
|
||||||
|
resources := templateMap[resourcesFieldName].([]interface{})
|
||||||
|
for index, resource := range resources {
|
||||||
|
resourceMap, ok := resource.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
glog.Warningf("Template improperly formatted for resource")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
resourceType, ok := resourceMap[typeFieldName].(string)
|
||||||
|
if ok && resourceType == nsgResourceType {
|
||||||
|
if nsgIndex != -1 {
|
||||||
|
err := fmt.Errorf("Found 2 resources with type %s in the template. There should only be 1", nsgResourceType)
|
||||||
|
glog.Errorf(err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
nsgIndex = index
|
||||||
|
}
|
||||||
|
if ok && resourceType == rtResourceType {
|
||||||
|
if rtIndex != -1 {
|
||||||
|
err := fmt.Errorf("Found 2 resources with type %s in the template. There should only be 1", rtResourceType)
|
||||||
|
glog.Warningf(err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rtIndex = index
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies, ok := resourceMap[dependsOnFieldName].([]interface{})
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for dIndex := len(dependencies) - 1; dIndex >= 0; dIndex-- {
|
||||||
|
dependency := dependencies[dIndex].(string)
|
||||||
|
if strings.Contains(dependency, nsgResourceType) || strings.Contains(dependency, nsgID) ||
|
||||||
|
strings.Contains(dependency, rtResourceType) || strings.Contains(dependency, rtID) {
|
||||||
|
dependencies = append(dependencies[:dIndex], dependencies[dIndex+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(dependencies) > 0 {
|
||||||
|
resourceMap[dependsOnFieldName] = dependencies
|
||||||
|
} else {
|
||||||
|
delete(resourceMap, dependsOnFieldName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
indexesToRemove := []int{}
|
||||||
|
if nsgIndex == -1 {
|
||||||
|
err := fmt.Errorf("Found no resources with type %s in the template. There should have been 1", nsgResourceType)
|
||||||
|
glog.Errorf(err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if rtIndex == -1 {
|
||||||
|
glog.Infof("Found no resources with type %s in the template.", rtResourceType)
|
||||||
|
} else {
|
||||||
|
indexesToRemove = append(indexesToRemove, rtIndex)
|
||||||
|
}
|
||||||
|
indexesToRemove = append(indexesToRemove, nsgIndex)
|
||||||
|
templateMap[resourcesFieldName] = removeIndexesFromArray(resources, indexesToRemove)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeIndexesFromArray(array []interface{}, indexes []int) []interface{} {
|
||||||
|
sort.Sort(sort.Reverse(sort.IntSlice(indexes)))
|
||||||
|
for _, index := range indexes {
|
||||||
|
array = append(array[:index], array[index+1:]...)
|
||||||
|
}
|
||||||
|
return array
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalizeMasterResourcesForScaling takes a template and removes elements that are unwanted in any scale up/down case
|
||||||
|
func normalizeMasterResourcesForScaling(templateMap map[string]interface{}) error {
|
||||||
|
resources := templateMap[resourcesFieldName].([]interface{})
|
||||||
|
indexesToRemove := []int{}
|
||||||
|
//update master nodes resources
|
||||||
|
for index, resource := range resources {
|
||||||
|
resourceMap, ok := resource.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
glog.Warningf("Template improperly formatted")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
resourceType, ok := resourceMap[typeFieldName].(string)
|
||||||
|
if !ok || resourceType != vmResourceType {
|
||||||
|
resourceName, ok := resourceMap[nameFieldName].(string)
|
||||||
|
if !ok {
|
||||||
|
glog.Warningf("Template improperly formatted")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.Contains(resourceName, "variables('masterVMNamePrefix')") && resourceType == vmExtensionType {
|
||||||
|
indexesToRemove = append(indexesToRemove, index)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
resourceName, ok := resourceMap[nameFieldName].(string)
|
||||||
|
if !ok {
|
||||||
|
glog.Warningf("Template improperly formatted")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure this is only modifying the master vms
|
||||||
|
if !strings.Contains(resourceName, "variables('masterVMNamePrefix')") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
resourceProperties, ok := resourceMap[propertiesFieldName].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
glog.Warningf("Template improperly formatted")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
hardwareProfile, ok := resourceProperties[hardwareProfileFieldName].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
glog.Warningf("Template improperly formatted")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if hardwareProfile[vmSizeFieldName] != nil {
|
||||||
|
delete(hardwareProfile, vmSizeFieldName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !removeCustomData(resourceProperties) || !removeImageReference(resourceProperties) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
templateMap[resourcesFieldName] = removeIndexesFromArray(resources, indexesToRemove)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeCustomData(resourceProperties map[string]interface{}) bool {
|
||||||
|
osProfile, ok := resourceProperties[osProfileFieldName].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
glog.Warningf("Template improperly formatted")
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
if osProfile[customDataFieldName] != nil {
|
||||||
|
delete(osProfile, customDataFieldName)
|
||||||
|
}
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeImageReference(resourceProperties map[string]interface{}) bool {
|
||||||
|
storageProfile, ok := resourceProperties[storageProfileFieldName].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
glog.Warningf("Template improperly formatted. Could not find: %s", storageProfileFieldName)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
if storageProfile[imageReferenceFieldName] != nil {
|
||||||
|
delete(storageProfile, imageReferenceFieldName)
|
||||||
|
}
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// resourceName returns the last segment (the resource name) for the specified resource identifier.
|
||||||
|
func resourceName(ID string) (string, error) {
|
||||||
|
parts := strings.Split(ID, "/")
|
||||||
|
name := parts[len(parts)-1]
|
||||||
|
if len(name) == 0 {
|
||||||
|
return "", fmt.Errorf("resource name was missing from identifier")
|
||||||
|
}
|
||||||
|
|
||||||
|
return name, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// splitBlobURI returns a decomposed blob URI parts: accountName, containerName, blobName.
|
||||||
|
func splitBlobURI(URI string) (string, string, string, error) {
|
||||||
|
uri, err := url.Parse(URI)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
accountName := strings.Split(uri.Host, ".")[0]
|
||||||
|
urlParts := strings.Split(uri.Path, "/")
|
||||||
|
|
||||||
|
containerName := urlParts[1]
|
||||||
|
blobPath := strings.Join(urlParts[2:], "/")
|
||||||
|
|
||||||
|
return accountName, containerName, blobPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// k8sLinuxVMNameParts returns parts of Linux VM name e.g: k8s-agentpool1-11290731-0
|
||||||
|
func k8sLinuxVMNameParts(vmName string) (poolIdentifier, nameSuffix string, agentIndex int, err error) {
|
||||||
|
vmNameParts := vmnameLinuxRegexp.FindStringSubmatch(vmName)
|
||||||
|
if len(vmNameParts) != 4 {
|
||||||
|
return "", "", -1, fmt.Errorf("resource name was missing from identifier")
|
||||||
|
}
|
||||||
|
|
||||||
|
vmNum, err := strconv.Atoi(vmNameParts[k8sLinuxVMAgentIndexArrayIndex])
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", "", -1, fmt.Errorf("Error parsing VM Name: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return vmNameParts[k8sLinuxVMAgentPoolNameIndex], vmNameParts[k8sLinuxVMAgentClusterIDIndex], vmNum, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// windowsVMNameParts returns parts of Windows VM name e.g: 50621k8s9000
|
||||||
|
func windowsVMNameParts(vmName string) (poolPrefix string, acsStr string, poolIndex int, agentIndex int, err error) {
|
||||||
|
vmNameParts := vmnameWindowsRegexp.FindStringSubmatch(vmName)
|
||||||
|
if len(vmNameParts) != 4 {
|
||||||
|
return "", "", -1, -1, fmt.Errorf("resource name was missing from identifier")
|
||||||
|
}
|
||||||
|
|
||||||
|
poolPrefix = vmNameParts[k8sWindowsVMAgentPoolPrefixIndex]
|
||||||
|
acsStr = vmNameParts[k8sWindowsVMAgentOrchestratorNameIndex]
|
||||||
|
poolInfo := vmNameParts[k8sWindowsVMAgentPoolInfoIndex]
|
||||||
|
|
||||||
|
poolIndex, err = strconv.Atoi(poolInfo[:3])
|
||||||
|
if err != nil {
|
||||||
|
return "", "", -1, -1, fmt.Errorf("Error parsing VM Name: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
agentIndex, err = strconv.Atoi(poolInfo[3:])
|
||||||
|
if err != nil {
|
||||||
|
return "", "", -1, -1, fmt.Errorf("Error parsing VM Name: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return poolPrefix, acsStr, poolIndex, agentIndex, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVMNameIndex return the index of VM in the node pools.
|
||||||
|
func GetVMNameIndex(osType compute.OperatingSystemTypes, vmName string) (int, error) {
|
||||||
|
var agentIndex int
|
||||||
|
var err error
|
||||||
|
if osType == compute.Linux {
|
||||||
|
_, _, agentIndex, err = k8sLinuxVMNameParts(vmName)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
} else if osType == compute.Windows {
|
||||||
|
_, _, _, agentIndex, err = windowsVMNameParts(vmName)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return agentIndex, nil
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
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 (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/Azure/azure-sdk-for-go/arm/compute"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSplitBlobURI(t *testing.T) {
|
||||||
|
expectedAccountName := "vhdstorage8h8pjybi9hbsl6"
|
||||||
|
expectedContainerName := "vhds"
|
||||||
|
expectedBlobPath := "osdisks/disk1234.vhd"
|
||||||
|
accountName, containerName, blobPath, err := splitBlobURI("https://vhdstorage8h8pjybi9hbsl6.blob.core.windows.net/vhds/osdisks/disk1234.vhd")
|
||||||
|
if accountName != expectedAccountName {
|
||||||
|
t.Fatalf("incorrect account name. expected=%s actual=%s", expectedAccountName, accountName)
|
||||||
|
}
|
||||||
|
if containerName != expectedContainerName {
|
||||||
|
t.Fatalf("incorrect account name. expected=%s actual=%s", expectedContainerName, containerName)
|
||||||
|
}
|
||||||
|
if blobPath != expectedBlobPath {
|
||||||
|
t.Fatalf("incorrect account name. expected=%s actual=%s", expectedBlobPath, blobPath)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestK8sLinuxVMNameParts(t *testing.T) {
|
||||||
|
data := []struct {
|
||||||
|
poolIdentifier, nameSuffix string
|
||||||
|
agentIndex int
|
||||||
|
}{
|
||||||
|
{"agentpool1", "38988164", 10},
|
||||||
|
{"agent-pool1", "38988164", 8},
|
||||||
|
{"agent-pool-1", "38988164", 0},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, el := range data {
|
||||||
|
vmName := fmt.Sprintf("k8s-%s-%s-%d", el.poolIdentifier, el.nameSuffix, el.agentIndex)
|
||||||
|
poolIdentifier, nameSuffix, agentIndex, err := k8sLinuxVMNameParts(vmName)
|
||||||
|
if poolIdentifier != el.poolIdentifier {
|
||||||
|
t.Fatalf("incorrect poolIdentifier. expected=%s actual=%s", el.poolIdentifier, poolIdentifier)
|
||||||
|
}
|
||||||
|
if nameSuffix != el.nameSuffix {
|
||||||
|
t.Fatalf("incorrect nameSuffix. expected=%s actual=%s", el.nameSuffix, nameSuffix)
|
||||||
|
}
|
||||||
|
if agentIndex != el.agentIndex {
|
||||||
|
t.Fatalf("incorrect agentIndex. expected=%d actual=%d", el.agentIndex, agentIndex)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWindowsVMNameParts(t *testing.T) {
|
||||||
|
expectedPoolPrefix := "38988"
|
||||||
|
expectedAcs := "k8s"
|
||||||
|
expectedPoolIndex := 903
|
||||||
|
expectedAgentIndex := 12
|
||||||
|
|
||||||
|
poolPrefix, acs, poolIndex, agentIndex, err := windowsVMNameParts("38988k8s90312")
|
||||||
|
if poolPrefix != expectedPoolPrefix {
|
||||||
|
t.Fatalf("incorrect poolPrefix. expected=%s actual=%s", expectedPoolPrefix, poolPrefix)
|
||||||
|
}
|
||||||
|
if acs != expectedAcs {
|
||||||
|
t.Fatalf("incorrect acs string. expected=%s actual=%s", expectedAcs, acs)
|
||||||
|
}
|
||||||
|
if poolIndex != expectedPoolIndex {
|
||||||
|
t.Fatalf("incorrect poolIndex. expected=%d actual=%d", expectedPoolIndex, poolIndex)
|
||||||
|
}
|
||||||
|
if agentIndex != expectedAgentIndex {
|
||||||
|
t.Fatalf("incorrect agentIndex. expected=%d actual=%d", expectedAgentIndex, agentIndex)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetVMNameIndexLinux(t *testing.T) {
|
||||||
|
expectedAgentIndex := 65
|
||||||
|
|
||||||
|
agentIndex, err := GetVMNameIndex(compute.Linux, "k8s-agentpool1-38988164-65")
|
||||||
|
if agentIndex != expectedAgentIndex {
|
||||||
|
t.Fatalf("incorrect agentIndex. expected=%d actual=%d", expectedAgentIndex, agentIndex)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetVMNameIndexWindows(t *testing.T) {
|
||||||
|
expectedAgentIndex := 20
|
||||||
|
|
||||||
|
agentIndex, err := GetVMNameIndex(compute.Windows, "38988k8s90320")
|
||||||
|
if agentIndex != expectedAgentIndex {
|
||||||
|
t.Fatalf("incorrect agentIndex. expected=%d actual=%d", expectedAgentIndex, agentIndex)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,137 @@
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
ClientID: <base64-encoded-client-id>
|
||||||
|
ClientSecret: <base64-encoded-client-secret>
|
||||||
|
ResourceGroup: <base64-encoded-resource-group>
|
||||||
|
SubscriptionID: <base64-encode-subscription-id>
|
||||||
|
TenantID: <base64-encoded-tenant-id>
|
||||||
|
NodeGroup: <base64-encoded-node-pool-name>
|
||||||
|
Deployment: <base64-encoded-azure-initial-deploy-name>
|
||||||
|
APIServerPrivateKey: <base64-encoded-apiserver-private-key>
|
||||||
|
CAPrivateKey: <base64-encoded-ca-private-key>
|
||||||
|
ClientPrivateKey: <base64-encoded-client-private-key>
|
||||||
|
KubeConfigPrivateKey: <base64-encoded-kubeconfig-private-key>
|
||||||
|
WindowsAdminPassword: <base64-encoded-windows-admin-password>
|
||||||
|
VMType: c3RhbmRhcmQ=
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
namespace: kube-system
|
||||||
|
---
|
||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: cluster-autoscaler
|
||||||
|
name: cluster-autoscaler
|
||||||
|
namespace: kube-system
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: cluster-autoscaler
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: cluster-autoscaler
|
||||||
|
spec:
|
||||||
|
tolerations:
|
||||||
|
- effect: NoSchedule
|
||||||
|
key: node-role.kubernetes.io/master
|
||||||
|
nodeSelector:
|
||||||
|
kubernetes.io/role: master
|
||||||
|
containers:
|
||||||
|
- command:
|
||||||
|
- ./cluster-autoscaler
|
||||||
|
- --v=3
|
||||||
|
- --logtostderr=true
|
||||||
|
- --cloud-provider=azure
|
||||||
|
- --skip-nodes-with-local-storage=false
|
||||||
|
- --nodes=1:10:$(ARM_NODE_GROUP)
|
||||||
|
env:
|
||||||
|
- name: ARM_SUBSCRIPTION_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: SubscriptionID
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_RESOURCE_GROUP
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: ResourceGroup
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_TENANT_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: TenantID
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_CLIENT_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: ClientID
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_CLIENT_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: ClientSecret
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_NODE_GROUP
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: NodeGroup
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_VM_TYPE
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: VMType
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_DEPLOYMENT
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: Deployment
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_APISEVER_PRIVATE_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: APIServerPrivateKey
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_CA_PRIVATE_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: CAPrivateKey
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_CLIENT_PRIVATE_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: ClientPrivateKey
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_KUBECONFIG_PRIVATE_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: KubeConfigPrivateKey
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_WINDOWS_ADMIN_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: WindowsAdminPassword
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
image: gcr.io/google_containers/cluster-autoscaler:{{ ca_version }}
|
||||||
|
imagePullPolicy: Always
|
||||||
|
name: cluster-autoscaler
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 300Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 300Mi
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /etc/ssl/certs/ca-certificates.crt
|
||||||
|
name: ssl-certs
|
||||||
|
readOnly: true
|
||||||
|
dnsPolicy: ClusterFirst
|
||||||
|
restartPolicy: Always
|
||||||
|
volumes:
|
||||||
|
- hostPath:
|
||||||
|
path: /etc/ssl/certs/ca-certificates.crt
|
||||||
|
type: ""
|
||||||
|
name: ssl-certs
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
ClientID: <base64-encoded-client-id>
|
||||||
|
ClientSecret: <base64-encoded-client-secret>
|
||||||
|
ResourceGroup: <base64-encoded-resource-group>
|
||||||
|
SubscriptionID: <base64-encode-subscription-id>
|
||||||
|
TenantID: <base64-encoded-tenant-id>
|
||||||
|
NodeGroup: <base64-encoded-node-pool-name>
|
||||||
|
Deployment: <base64-encoded-azure-initial-deploy-name>
|
||||||
|
APIServerPrivateKey: <base64-encoded-apiserver-private-key>
|
||||||
|
CAPrivateKey: <base64-encoded-ca-private-key>
|
||||||
|
ClientPrivateKey: <base64-encoded-client-private-key>
|
||||||
|
KubeConfigPrivateKey: <base64-encoded-kubeconfig-private-key>
|
||||||
|
WindowsAdminPassword: <base64-encoded-windows-admin-password>
|
||||||
|
VMType: c3RhbmRhcmQ=
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
namespace: kube-system
|
||||||
|
---
|
||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: cluster-autoscaler
|
||||||
|
name: cluster-autoscaler
|
||||||
|
namespace: kube-system
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: cluster-autoscaler
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: cluster-autoscaler
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- command:
|
||||||
|
- ./cluster-autoscaler
|
||||||
|
- --v=3
|
||||||
|
- --logtostderr=true
|
||||||
|
- --cloud-provider=azure
|
||||||
|
- --skip-nodes-with-local-storage=false
|
||||||
|
- --nodes=1:10:$(ARM_NODE_GROUP)
|
||||||
|
env:
|
||||||
|
- name: ARM_SUBSCRIPTION_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: SubscriptionID
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_RESOURCE_GROUP
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: ResourceGroup
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_TENANT_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: TenantID
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_CLIENT_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: ClientID
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_CLIENT_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: ClientSecret
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_NODE_GROUP
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: NodeGroup
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_VM_TYPE
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: VMType
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_DEPLOYMENT
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: Deployment
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_APISEVER_PRIVATE_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: APIServerPrivateKey
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_CA_PRIVATE_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: CAPrivateKey
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_CLIENT_PRIVATE_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: ClientPrivateKey
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_KUBECONFIG_PRIVATE_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: KubeConfigPrivateKey
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_WINDOWS_ADMIN_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: WindowsAdminPassword
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
image: gcr.io/google_containers/cluster-autoscaler:{{ ca_version }}
|
||||||
|
imagePullPolicy: Always
|
||||||
|
name: cluster-autoscaler
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 300Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 300Mi
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /etc/ssl/certs/ca-certificates.crt
|
||||||
|
name: ssl-certs
|
||||||
|
readOnly: true
|
||||||
|
dnsPolicy: ClusterFirst
|
||||||
|
restartPolicy: Always
|
||||||
|
volumes:
|
||||||
|
- hostPath:
|
||||||
|
path: /etc/ssl/certs/ca-certificates.crt
|
||||||
|
type: ""
|
||||||
|
name: ssl-certs
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
ClientID: <base64-encoded-client-id>
|
||||||
|
ClientSecret: <base64-encoded-client-secret>
|
||||||
|
ResourceGroup: <base64-encoded-resource-group>
|
||||||
|
SubscriptionID: <base64-encode-subscription-id>
|
||||||
|
TenantID: <base64-encoded-tenant-id>
|
||||||
|
NodeGroup: <base64-encoded-scale-set-name>
|
||||||
|
VMType: dm1zcw==
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
namespace: kube-system
|
||||||
|
---
|
||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: cluster-autoscaler
|
||||||
|
name: cluster-autoscaler
|
||||||
|
namespace: kube-system
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: cluster-autoscaler
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: cluster-autoscaler
|
||||||
|
spec:
|
||||||
|
tolerations:
|
||||||
|
- effect: NoSchedule
|
||||||
|
key: node-role.kubernetes.io/master
|
||||||
|
nodeSelector:
|
||||||
|
kubernetes.io/role: master
|
||||||
|
containers:
|
||||||
|
- command:
|
||||||
|
- ./cluster-autoscaler
|
||||||
|
- --v=3
|
||||||
|
- --logtostderr=true
|
||||||
|
- --cloud-provider=azure
|
||||||
|
- --skip-nodes-with-local-storage=false
|
||||||
|
- --nodes=1:10:$(ARM_NODE_GROUP)
|
||||||
|
env:
|
||||||
|
- name: ARM_SUBSCRIPTION_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: SubscriptionID
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_RESOURCE_GROUP
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: ResourceGroup
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_TENANT_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: TenantID
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_CLIENT_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: ClientID
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_CLIENT_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: ClientSecret
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_NODE_GROUP
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: NodeGroup
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_VM_TYPE
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: VMType
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- image: gcr.io/google_containers/cluster-autoscaler:{{ ca_version }}
|
||||||
|
imagePullPolicy: Always
|
||||||
|
name: cluster-autoscaler
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 300Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 300Mi
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /etc/ssl/certs/ca-certificates.crt
|
||||||
|
name: ssl-certs
|
||||||
|
readOnly: true
|
||||||
|
restartPolicy: Always
|
||||||
|
volumes:
|
||||||
|
- hostPath:
|
||||||
|
path: /etc/ssl/certs/ca-certificates.crt
|
||||||
|
type: ""
|
||||||
|
name: ssl-certs
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
ClientID: <base64-encoded-client-id>
|
||||||
|
ClientSecret: <base64-encoded-client-secret>
|
||||||
|
ResourceGroup: <base64-encoded-resource-group>
|
||||||
|
SubscriptionID: <base64-encode-subscription-id>
|
||||||
|
TenantID: <base64-encoded-tenant-id>
|
||||||
|
NodeGroup: <base64-encoded-scale-set-name>
|
||||||
|
VMType: dm1zcw==
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
namespace: kube-system
|
||||||
|
---
|
||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: cluster-autoscaler
|
||||||
|
name: cluster-autoscaler
|
||||||
|
namespace: kube-system
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: cluster-autoscaler
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: cluster-autoscaler
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- command:
|
||||||
|
- ./cluster-autoscaler
|
||||||
|
- --v=3
|
||||||
|
- --logtostderr=true
|
||||||
|
- --cloud-provider=azure
|
||||||
|
- --skip-nodes-with-local-storage=false
|
||||||
|
- --nodes=1:10:$(ARM_NODE_GROUP)
|
||||||
|
env:
|
||||||
|
- name: ARM_SUBSCRIPTION_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: SubscriptionID
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_RESOURCE_GROUP
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: ResourceGroup
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_TENANT_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: TenantID
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_CLIENT_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: ClientID
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_CLIENT_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: ClientSecret
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_NODE_GROUP
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: NodeGroup
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- name: ARM_VM_TYPE
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
key: VMType
|
||||||
|
name: cluster-autoscaler-azure
|
||||||
|
- image: gcr.io/google_containers/cluster-autoscaler:{{ ca_version }}
|
||||||
|
imagePullPolicy: Always
|
||||||
|
name: cluster-autoscaler
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 300Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 300Mi
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /etc/ssl/certs/ca-certificates.crt
|
||||||
|
name: ssl-certs
|
||||||
|
readOnly: true
|
||||||
|
restartPolicy: Always
|
||||||
|
volumes:
|
||||||
|
- hostPath:
|
||||||
|
path: /etc/ssl/certs/ca-certificates.crt
|
||||||
|
type: ""
|
||||||
|
name: ssl-certs
|
||||||
51
cluster-autoscaler/vendor/github.com/Azure/azure-sdk-for-go/arm/resources/resources/client.go
generated
vendored
Executable file
51
cluster-autoscaler/vendor/github.com/Azure/azure-sdk-for-go/arm/resources/resources/client.go
generated
vendored
Executable file
|
|
@ -0,0 +1,51 @@
|
||||||
|
// Package resources implements the Azure ARM Resources service API version 2017-05-10.
|
||||||
|
//
|
||||||
|
// Provides operations for working with resources and resource groups.
|
||||||
|
package resources
|
||||||
|
|
||||||
|
// 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 Resources
|
||||||
|
DefaultBaseURI = "https://management.azure.com"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ManagementClient is the base client for Resources.
|
||||||
|
type ManagementClient struct {
|
||||||
|
autorest.Client
|
||||||
|
BaseURI string
|
||||||
|
SubscriptionID string
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates an instance of the ManagementClient client.
|
||||||
|
func New(subscriptionID string) ManagementClient {
|
||||||
|
return NewWithBaseURI(DefaultBaseURI, subscriptionID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithBaseURI creates an instance of the ManagementClient client.
|
||||||
|
func NewWithBaseURI(baseURI string, subscriptionID string) ManagementClient {
|
||||||
|
return ManagementClient{
|
||||||
|
Client: autorest.NewClientWithUserAgent(UserAgent()),
|
||||||
|
BaseURI: baseURI,
|
||||||
|
SubscriptionID: subscriptionID,
|
||||||
|
}
|
||||||
|
}
|
||||||
269
cluster-autoscaler/vendor/github.com/Azure/azure-sdk-for-go/arm/resources/resources/deploymentoperations.go
generated
vendored
Executable file
269
cluster-autoscaler/vendor/github.com/Azure/azure-sdk-for-go/arm/resources/resources/deploymentoperations.go
generated
vendored
Executable file
|
|
@ -0,0 +1,269 @@
|
||||||
|
package resources
|
||||||
|
|
||||||
|
// 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"
|
||||||
|
"github.com/Azure/go-autorest/autorest/azure"
|
||||||
|
"github.com/Azure/go-autorest/autorest/validation"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeploymentOperationsClient is the provides operations for working with resources and resource groups.
|
||||||
|
type DeploymentOperationsClient struct {
|
||||||
|
ManagementClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDeploymentOperationsClient creates an instance of the DeploymentOperationsClient client.
|
||||||
|
func NewDeploymentOperationsClient(subscriptionID string) DeploymentOperationsClient {
|
||||||
|
return NewDeploymentOperationsClientWithBaseURI(DefaultBaseURI, subscriptionID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDeploymentOperationsClientWithBaseURI creates an instance of the DeploymentOperationsClient client.
|
||||||
|
func NewDeploymentOperationsClientWithBaseURI(baseURI string, subscriptionID string) DeploymentOperationsClient {
|
||||||
|
return DeploymentOperationsClient{NewWithBaseURI(baseURI, subscriptionID)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get gets a deployments operation.
|
||||||
|
//
|
||||||
|
// resourceGroupName is the name of the resource group. The name is case insensitive. deploymentName is the name of the
|
||||||
|
// deployment. operationID is the ID of the operation to get.
|
||||||
|
func (client DeploymentOperationsClient) Get(resourceGroupName string, deploymentName string, operationID string) (result DeploymentOperation, err error) {
|
||||||
|
if err := validation.Validate([]validation.Validation{
|
||||||
|
{TargetValue: resourceGroupName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}},
|
||||||
|
{TargetValue: deploymentName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "deploymentName", Name: validation.MaxLength, Rule: 64, Chain: nil},
|
||||||
|
{Target: "deploymentName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "deploymentName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil {
|
||||||
|
return result, validation.NewErrorWithValidationError(err, "resources.DeploymentOperationsClient", "Get")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := client.GetPreparer(resourceGroupName, deploymentName, operationID)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentOperationsClient", "Get", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.GetSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentOperationsClient", "Get", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.GetResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentOperationsClient", "Get", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPreparer prepares the Get request.
|
||||||
|
func (client DeploymentOperationsClient) GetPreparer(resourceGroupName string, deploymentName string, operationID string) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"deploymentName": autorest.Encode("path", deploymentName),
|
||||||
|
"operationId": autorest.Encode("path", operationID),
|
||||||
|
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsGet(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/deployments/{deploymentName}/operations/{operationId}", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSender sends the Get request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client DeploymentOperationsClient) GetSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetResponder handles the response to the Get request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client DeploymentOperationsClient) GetResponder(resp *http.Response) (result DeploymentOperation, 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 gets all deployments operations for a deployment.
|
||||||
|
//
|
||||||
|
// resourceGroupName is the name of the resource group. The name is case insensitive. deploymentName is the name of the
|
||||||
|
// deployment with the operation to get. top is the number of results to return.
|
||||||
|
func (client DeploymentOperationsClient) List(resourceGroupName string, deploymentName string, top *int32) (result DeploymentOperationsListResult, err error) {
|
||||||
|
if err := validation.Validate([]validation.Validation{
|
||||||
|
{TargetValue: resourceGroupName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}},
|
||||||
|
{TargetValue: deploymentName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "deploymentName", Name: validation.MaxLength, Rule: 64, Chain: nil},
|
||||||
|
{Target: "deploymentName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "deploymentName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil {
|
||||||
|
return result, validation.NewErrorWithValidationError(err, "resources.DeploymentOperationsClient", "List")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := client.ListPreparer(resourceGroupName, deploymentName, top)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentOperationsClient", "List", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.ListSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentOperationsClient", "List", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.ListResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentOperationsClient", "List", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPreparer prepares the List request.
|
||||||
|
func (client DeploymentOperationsClient) ListPreparer(resourceGroupName string, deploymentName string, top *int32) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"deploymentName": autorest.Encode("path", deploymentName),
|
||||||
|
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
if top != nil {
|
||||||
|
queryParameters["$top"] = autorest.Encode("query", *top)
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsGet(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/deployments/{deploymentName}/operations", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListSender sends the List request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client DeploymentOperationsClient) ListSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListResponder handles the response to the List request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client DeploymentOperationsClient) ListResponder(resp *http.Response) (result DeploymentOperationsListResult, 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 DeploymentOperationsClient) ListNextResults(lastResults DeploymentOperationsListResult) (result DeploymentOperationsListResult, err error) {
|
||||||
|
req, err := lastResults.DeploymentOperationsListResultPreparer()
|
||||||
|
if err != nil {
|
||||||
|
return result, autorest.NewErrorWithError(err, "resources.DeploymentOperationsClient", "List", 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, "resources.DeploymentOperationsClient", "List", resp, "Failure sending next results request")
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.ListResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentOperationsClient", "List", resp, "Failure responding to next results request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListComplete gets all elements from the list without paging.
|
||||||
|
func (client DeploymentOperationsClient) ListComplete(resourceGroupName string, deploymentName string, top *int32, cancel <-chan struct{}) (<-chan DeploymentOperation, <-chan error) {
|
||||||
|
resultChan := make(chan DeploymentOperation)
|
||||||
|
errChan := make(chan error, 1)
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
close(resultChan)
|
||||||
|
close(errChan)
|
||||||
|
}()
|
||||||
|
list, err := client.List(resourceGroupName, deploymentName, top)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if list.Value != nil {
|
||||||
|
for _, item := range *list.Value {
|
||||||
|
select {
|
||||||
|
case <-cancel:
|
||||||
|
return
|
||||||
|
case resultChan <- item:
|
||||||
|
// Intentionally left blank
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for list.NextLink != nil {
|
||||||
|
list, err = client.ListNextResults(list)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if list.Value != nil {
|
||||||
|
for _, item := range *list.Value {
|
||||||
|
select {
|
||||||
|
case <-cancel:
|
||||||
|
return
|
||||||
|
case resultChan <- item:
|
||||||
|
// Intentionally left blank
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return resultChan, errChan
|
||||||
|
}
|
||||||
799
cluster-autoscaler/vendor/github.com/Azure/azure-sdk-for-go/arm/resources/resources/deployments.go
generated
vendored
Executable file
799
cluster-autoscaler/vendor/github.com/Azure/azure-sdk-for-go/arm/resources/resources/deployments.go
generated
vendored
Executable file
|
|
@ -0,0 +1,799 @@
|
||||||
|
package resources
|
||||||
|
|
||||||
|
// 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"
|
||||||
|
"github.com/Azure/go-autorest/autorest/azure"
|
||||||
|
"github.com/Azure/go-autorest/autorest/validation"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeploymentsClient is the provides operations for working with resources and resource groups.
|
||||||
|
type DeploymentsClient struct {
|
||||||
|
ManagementClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDeploymentsClient creates an instance of the DeploymentsClient client.
|
||||||
|
func NewDeploymentsClient(subscriptionID string) DeploymentsClient {
|
||||||
|
return NewDeploymentsClientWithBaseURI(DefaultBaseURI, subscriptionID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDeploymentsClientWithBaseURI creates an instance of the DeploymentsClient client.
|
||||||
|
func NewDeploymentsClientWithBaseURI(baseURI string, subscriptionID string) DeploymentsClient {
|
||||||
|
return DeploymentsClient{NewWithBaseURI(baseURI, subscriptionID)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel you can cancel a deployment only if the provisioningState is Accepted or Running. After the deployment is
|
||||||
|
// canceled, the provisioningState is set to Canceled. Canceling a template deployment stops the currently running
|
||||||
|
// template deployment and leaves the resource group partially deployed.
|
||||||
|
//
|
||||||
|
// resourceGroupName is the name of the resource group. The name is case insensitive. deploymentName is the name of the
|
||||||
|
// deployment to cancel.
|
||||||
|
func (client DeploymentsClient) Cancel(resourceGroupName string, deploymentName string) (result autorest.Response, err error) {
|
||||||
|
if err := validation.Validate([]validation.Validation{
|
||||||
|
{TargetValue: resourceGroupName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}},
|
||||||
|
{TargetValue: deploymentName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "deploymentName", Name: validation.MaxLength, Rule: 64, Chain: nil},
|
||||||
|
{Target: "deploymentName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "deploymentName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil {
|
||||||
|
return result, validation.NewErrorWithValidationError(err, "resources.DeploymentsClient", "Cancel")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := client.CancelPreparer(resourceGroupName, deploymentName)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "Cancel", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.CancelSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = resp
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "Cancel", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.CancelResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "Cancel", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelPreparer prepares the Cancel request.
|
||||||
|
func (client DeploymentsClient) CancelPreparer(resourceGroupName string, deploymentName string) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"deploymentName": autorest.Encode("path", deploymentName),
|
||||||
|
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsPost(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Resources/deployments/{deploymentName}/cancel", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelSender sends the Cancel request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client DeploymentsClient) CancelSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelResponder handles the response to the Cancel request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client DeploymentsClient) CancelResponder(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
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckExistence checks whether the deployment exists.
|
||||||
|
//
|
||||||
|
// resourceGroupName is the name of the resource group with the deployment to check. The name is case insensitive.
|
||||||
|
// deploymentName is the name of the deployment to check.
|
||||||
|
func (client DeploymentsClient) CheckExistence(resourceGroupName string, deploymentName string) (result autorest.Response, err error) {
|
||||||
|
if err := validation.Validate([]validation.Validation{
|
||||||
|
{TargetValue: resourceGroupName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}},
|
||||||
|
{TargetValue: deploymentName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "deploymentName", Name: validation.MaxLength, Rule: 64, Chain: nil},
|
||||||
|
{Target: "deploymentName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "deploymentName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil {
|
||||||
|
return result, validation.NewErrorWithValidationError(err, "resources.DeploymentsClient", "CheckExistence")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := client.CheckExistencePreparer(resourceGroupName, deploymentName)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "CheckExistence", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.CheckExistenceSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = resp
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "CheckExistence", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.CheckExistenceResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "CheckExistence", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckExistencePreparer prepares the CheckExistence request.
|
||||||
|
func (client DeploymentsClient) CheckExistencePreparer(resourceGroupName string, deploymentName string) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"deploymentName": autorest.Encode("path", deploymentName),
|
||||||
|
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsHead(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Resources/deployments/{deploymentName}", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckExistenceSender sends the CheckExistence request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client DeploymentsClient) CheckExistenceSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckExistenceResponder handles the response to the CheckExistence request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client DeploymentsClient) CheckExistenceResponder(resp *http.Response) (result autorest.Response, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusNoContent, http.StatusNotFound),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = resp
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdate you can provide the template and parameters directly in the request or link to JSON files. This
|
||||||
|
// method may poll for completion. Polling can be canceled by passing the cancel channel argument. The channel will be
|
||||||
|
// used to cancel polling and any outstanding HTTP requests.
|
||||||
|
//
|
||||||
|
// resourceGroupName is the name of the resource group to deploy the resources to. The name is case insensitive. The
|
||||||
|
// resource group must already exist. deploymentName is the name of the deployment. parameters is additional parameters
|
||||||
|
// supplied to the operation.
|
||||||
|
func (client DeploymentsClient) CreateOrUpdate(resourceGroupName string, deploymentName string, parameters Deployment, cancel <-chan struct{}) (<-chan DeploymentExtended, <-chan error) {
|
||||||
|
resultChan := make(chan DeploymentExtended, 1)
|
||||||
|
errChan := make(chan error, 1)
|
||||||
|
if err := validation.Validate([]validation.Validation{
|
||||||
|
{TargetValue: resourceGroupName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}},
|
||||||
|
{TargetValue: deploymentName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "deploymentName", Name: validation.MaxLength, Rule: 64, Chain: nil},
|
||||||
|
{Target: "deploymentName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "deploymentName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}},
|
||||||
|
{TargetValue: parameters,
|
||||||
|
Constraints: []validation.Constraint{{Target: "parameters.Properties", Name: validation.Null, Rule: true,
|
||||||
|
Chain: []validation.Constraint{{Target: "parameters.Properties.TemplateLink", Name: validation.Null, Rule: false,
|
||||||
|
Chain: []validation.Constraint{{Target: "parameters.Properties.TemplateLink.URI", Name: validation.Null, Rule: true, Chain: nil}}},
|
||||||
|
{Target: "parameters.Properties.ParametersLink", Name: validation.Null, Rule: false,
|
||||||
|
Chain: []validation.Constraint{{Target: "parameters.Properties.ParametersLink.URI", Name: validation.Null, Rule: true, Chain: nil}}},
|
||||||
|
}}}}}); err != nil {
|
||||||
|
errChan <- validation.NewErrorWithValidationError(err, "resources.DeploymentsClient", "CreateOrUpdate")
|
||||||
|
close(errChan)
|
||||||
|
close(resultChan)
|
||||||
|
return resultChan, errChan
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
var err error
|
||||||
|
var result DeploymentExtended
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
}
|
||||||
|
resultChan <- result
|
||||||
|
close(resultChan)
|
||||||
|
close(errChan)
|
||||||
|
}()
|
||||||
|
req, err := client.CreateOrUpdatePreparer(resourceGroupName, deploymentName, parameters, cancel)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "CreateOrUpdate", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.CreateOrUpdateSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "CreateOrUpdate", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.CreateOrUpdateResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "CreateOrUpdate", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return resultChan, errChan
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdatePreparer prepares the CreateOrUpdate request.
|
||||||
|
func (client DeploymentsClient) CreateOrUpdatePreparer(resourceGroupName string, deploymentName string, parameters Deployment, cancel <-chan struct{}) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"deploymentName": autorest.Encode("path", deploymentName),
|
||||||
|
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsJSON(),
|
||||||
|
autorest.AsPut(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Resources/deployments/{deploymentName}", pathParameters),
|
||||||
|
autorest.WithJSON(parameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{Cancel: cancel})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdateSender sends the CreateOrUpdate request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client DeploymentsClient) CreateOrUpdateSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client,
|
||||||
|
req,
|
||||||
|
azure.DoPollForAsynchronous(client.PollingDelay))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdateResponder handles the response to the CreateOrUpdate request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client DeploymentsClient) CreateOrUpdateResponder(resp *http.Response) (result DeploymentExtended, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusCreated),
|
||||||
|
autorest.ByUnmarshallingJSON(&result),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete a template deployment that is currently running cannot be deleted. Deleting a template deployment removes the
|
||||||
|
// associated deployment operations. Deleting a template deployment does not affect the state of the resource group.
|
||||||
|
// This is an asynchronous operation that returns a status of 202 until the template deployment is successfully
|
||||||
|
// deleted. The Location response header contains the URI that is used to obtain the status of the process. While the
|
||||||
|
// process is running, a call to the URI in the Location header returns a status of 202. When the process finishes, the
|
||||||
|
// URI in the Location header returns a status of 204 on success. If the asynchronous request failed, the URI in the
|
||||||
|
// Location header returns an error-level status code. This method may poll for completion. Polling can be canceled by
|
||||||
|
// passing the cancel channel argument. The channel will be used to cancel polling and any outstanding HTTP requests.
|
||||||
|
//
|
||||||
|
// resourceGroupName is the name of the resource group with the deployment to delete. The name is case insensitive.
|
||||||
|
// deploymentName is the name of the deployment to delete.
|
||||||
|
func (client DeploymentsClient) Delete(resourceGroupName string, deploymentName string, cancel <-chan struct{}) (<-chan autorest.Response, <-chan error) {
|
||||||
|
resultChan := make(chan autorest.Response, 1)
|
||||||
|
errChan := make(chan error, 1)
|
||||||
|
if err := validation.Validate([]validation.Validation{
|
||||||
|
{TargetValue: resourceGroupName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}},
|
||||||
|
{TargetValue: deploymentName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "deploymentName", Name: validation.MaxLength, Rule: 64, Chain: nil},
|
||||||
|
{Target: "deploymentName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "deploymentName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil {
|
||||||
|
errChan <- validation.NewErrorWithValidationError(err, "resources.DeploymentsClient", "Delete")
|
||||||
|
close(errChan)
|
||||||
|
close(resultChan)
|
||||||
|
return resultChan, errChan
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
var err error
|
||||||
|
var result autorest.Response
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
}
|
||||||
|
resultChan <- result
|
||||||
|
close(resultChan)
|
||||||
|
close(errChan)
|
||||||
|
}()
|
||||||
|
req, err := client.DeletePreparer(resourceGroupName, deploymentName, cancel)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "Delete", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.DeleteSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = resp
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "Delete", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.DeleteResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "Delete", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return resultChan, errChan
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletePreparer prepares the Delete request.
|
||||||
|
func (client DeploymentsClient) DeletePreparer(resourceGroupName string, deploymentName string, cancel <-chan struct{}) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"deploymentName": autorest.Encode("path", deploymentName),
|
||||||
|
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsDelete(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Resources/deployments/{deploymentName}", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{Cancel: cancel})
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteSender sends the Delete request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client DeploymentsClient) DeleteSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client,
|
||||||
|
req,
|
||||||
|
azure.DoPollForAsynchronous(client.PollingDelay))
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteResponder handles the response to the Delete request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client DeploymentsClient) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusAccepted, http.StatusNoContent),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = resp
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportTemplate exports the template used for specified deployment.
|
||||||
|
//
|
||||||
|
// resourceGroupName is the name of the resource group. The name is case insensitive. deploymentName is the name of the
|
||||||
|
// deployment from which to get the template.
|
||||||
|
func (client DeploymentsClient) ExportTemplate(resourceGroupName string, deploymentName string) (result DeploymentExportResult, err error) {
|
||||||
|
if err := validation.Validate([]validation.Validation{
|
||||||
|
{TargetValue: resourceGroupName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}},
|
||||||
|
{TargetValue: deploymentName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "deploymentName", Name: validation.MaxLength, Rule: 64, Chain: nil},
|
||||||
|
{Target: "deploymentName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "deploymentName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil {
|
||||||
|
return result, validation.NewErrorWithValidationError(err, "resources.DeploymentsClient", "ExportTemplate")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := client.ExportTemplatePreparer(resourceGroupName, deploymentName)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "ExportTemplate", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.ExportTemplateSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "ExportTemplate", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.ExportTemplateResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "ExportTemplate", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportTemplatePreparer prepares the ExportTemplate request.
|
||||||
|
func (client DeploymentsClient) ExportTemplatePreparer(resourceGroupName string, deploymentName string) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"deploymentName": autorest.Encode("path", deploymentName),
|
||||||
|
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsPost(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Resources/deployments/{deploymentName}/exportTemplate", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportTemplateSender sends the ExportTemplate request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client DeploymentsClient) ExportTemplateSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportTemplateResponder handles the response to the ExportTemplate request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client DeploymentsClient) ExportTemplateResponder(resp *http.Response) (result DeploymentExportResult, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||||
|
autorest.ByUnmarshallingJSON(&result),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get gets a deployment.
|
||||||
|
//
|
||||||
|
// resourceGroupName is the name of the resource group. The name is case insensitive. deploymentName is the name of the
|
||||||
|
// deployment to get.
|
||||||
|
func (client DeploymentsClient) Get(resourceGroupName string, deploymentName string) (result DeploymentExtended, err error) {
|
||||||
|
if err := validation.Validate([]validation.Validation{
|
||||||
|
{TargetValue: resourceGroupName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}},
|
||||||
|
{TargetValue: deploymentName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "deploymentName", Name: validation.MaxLength, Rule: 64, Chain: nil},
|
||||||
|
{Target: "deploymentName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "deploymentName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil {
|
||||||
|
return result, validation.NewErrorWithValidationError(err, "resources.DeploymentsClient", "Get")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := client.GetPreparer(resourceGroupName, deploymentName)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "Get", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.GetSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "Get", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.GetResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "Get", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPreparer prepares the Get request.
|
||||||
|
func (client DeploymentsClient) GetPreparer(resourceGroupName string, deploymentName string) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"deploymentName": autorest.Encode("path", deploymentName),
|
||||||
|
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsGet(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Resources/deployments/{deploymentName}", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSender sends the Get request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client DeploymentsClient) GetSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetResponder handles the response to the Get request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client DeploymentsClient) GetResponder(resp *http.Response) (result DeploymentExtended, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||||
|
autorest.ByUnmarshallingJSON(&result),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListByResourceGroup get all the deployments for a resource group.
|
||||||
|
//
|
||||||
|
// resourceGroupName is the name of the resource group with the deployments to get. The name is case insensitive.
|
||||||
|
// filter is the filter to apply on the operation. For example, you can use $filter=provisioningState eq '{state}'. top
|
||||||
|
// is the number of results to get. If null is passed, returns all deployments.
|
||||||
|
func (client DeploymentsClient) ListByResourceGroup(resourceGroupName string, filter string, top *int32) (result DeploymentListResult, err error) {
|
||||||
|
if err := validation.Validate([]validation.Validation{
|
||||||
|
{TargetValue: resourceGroupName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil {
|
||||||
|
return result, validation.NewErrorWithValidationError(err, "resources.DeploymentsClient", "ListByResourceGroup")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := client.ListByResourceGroupPreparer(resourceGroupName, filter, top)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "ListByResourceGroup", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.ListByResourceGroupSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "ListByResourceGroup", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.ListByResourceGroupResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "ListByResourceGroup", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListByResourceGroupPreparer prepares the ListByResourceGroup request.
|
||||||
|
func (client DeploymentsClient) ListByResourceGroupPreparer(resourceGroupName string, filter string, top *int32) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
if len(filter) > 0 {
|
||||||
|
queryParameters["$filter"] = autorest.Encode("query", filter)
|
||||||
|
}
|
||||||
|
if top != nil {
|
||||||
|
queryParameters["$top"] = autorest.Encode("query", *top)
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsGet(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Resources/deployments/", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListByResourceGroupSender sends the ListByResourceGroup request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client DeploymentsClient) ListByResourceGroupSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListByResourceGroupResponder handles the response to the ListByResourceGroup request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client DeploymentsClient) ListByResourceGroupResponder(resp *http.Response) (result DeploymentListResult, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||||
|
autorest.ByUnmarshallingJSON(&result),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListByResourceGroupNextResults retrieves the next set of results, if any.
|
||||||
|
func (client DeploymentsClient) ListByResourceGroupNextResults(lastResults DeploymentListResult) (result DeploymentListResult, err error) {
|
||||||
|
req, err := lastResults.DeploymentListResultPreparer()
|
||||||
|
if err != nil {
|
||||||
|
return result, autorest.NewErrorWithError(err, "resources.DeploymentsClient", "ListByResourceGroup", nil, "Failure preparing next results request")
|
||||||
|
}
|
||||||
|
if req == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.ListByResourceGroupSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
return result, autorest.NewErrorWithError(err, "resources.DeploymentsClient", "ListByResourceGroup", resp, "Failure sending next results request")
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.ListByResourceGroupResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "ListByResourceGroup", resp, "Failure responding to next results request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListByResourceGroupComplete gets all elements from the list without paging.
|
||||||
|
func (client DeploymentsClient) ListByResourceGroupComplete(resourceGroupName string, filter string, top *int32, cancel <-chan struct{}) (<-chan DeploymentExtended, <-chan error) {
|
||||||
|
resultChan := make(chan DeploymentExtended)
|
||||||
|
errChan := make(chan error, 1)
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
close(resultChan)
|
||||||
|
close(errChan)
|
||||||
|
}()
|
||||||
|
list, err := client.ListByResourceGroup(resourceGroupName, filter, top)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if list.Value != nil {
|
||||||
|
for _, item := range *list.Value {
|
||||||
|
select {
|
||||||
|
case <-cancel:
|
||||||
|
return
|
||||||
|
case resultChan <- item:
|
||||||
|
// Intentionally left blank
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for list.NextLink != nil {
|
||||||
|
list, err = client.ListByResourceGroupNextResults(list)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if list.Value != nil {
|
||||||
|
for _, item := range *list.Value {
|
||||||
|
select {
|
||||||
|
case <-cancel:
|
||||||
|
return
|
||||||
|
case resultChan <- item:
|
||||||
|
// Intentionally left blank
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return resultChan, errChan
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates whether the specified template is syntactically correct and will be accepted by Azure Resource
|
||||||
|
// Manager..
|
||||||
|
//
|
||||||
|
// resourceGroupName is the name of the resource group the template will be deployed to. The name is case insensitive.
|
||||||
|
// deploymentName is the name of the deployment. parameters is parameters to validate.
|
||||||
|
func (client DeploymentsClient) Validate(resourceGroupName string, deploymentName string, parameters Deployment) (result DeploymentValidateResult, err error) {
|
||||||
|
if err := validation.Validate([]validation.Validation{
|
||||||
|
{TargetValue: resourceGroupName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}},
|
||||||
|
{TargetValue: deploymentName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "deploymentName", Name: validation.MaxLength, Rule: 64, Chain: nil},
|
||||||
|
{Target: "deploymentName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "deploymentName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}},
|
||||||
|
{TargetValue: parameters,
|
||||||
|
Constraints: []validation.Constraint{{Target: "parameters.Properties", Name: validation.Null, Rule: true,
|
||||||
|
Chain: []validation.Constraint{{Target: "parameters.Properties.TemplateLink", Name: validation.Null, Rule: false,
|
||||||
|
Chain: []validation.Constraint{{Target: "parameters.Properties.TemplateLink.URI", Name: validation.Null, Rule: true, Chain: nil}}},
|
||||||
|
{Target: "parameters.Properties.ParametersLink", Name: validation.Null, Rule: false,
|
||||||
|
Chain: []validation.Constraint{{Target: "parameters.Properties.ParametersLink.URI", Name: validation.Null, Rule: true, Chain: nil}}},
|
||||||
|
}}}}}); err != nil {
|
||||||
|
return result, validation.NewErrorWithValidationError(err, "resources.DeploymentsClient", "Validate")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := client.ValidatePreparer(resourceGroupName, deploymentName, parameters)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "Validate", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.ValidateSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "Validate", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.ValidateResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.DeploymentsClient", "Validate", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidatePreparer prepares the Validate request.
|
||||||
|
func (client DeploymentsClient) ValidatePreparer(resourceGroupName string, deploymentName string, parameters Deployment) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"deploymentName": autorest.Encode("path", deploymentName),
|
||||||
|
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsJSON(),
|
||||||
|
autorest.AsPost(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Resources/deployments/{deploymentName}/validate", pathParameters),
|
||||||
|
autorest.WithJSON(parameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateSender sends the Validate request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client DeploymentsClient) ValidateSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateResponder handles the response to the Validate request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client DeploymentsClient) ValidateResponder(resp *http.Response) (result DeploymentValidateResult, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusBadRequest),
|
||||||
|
autorest.ByUnmarshallingJSON(&result),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
return
|
||||||
|
}
|
||||||
1181
cluster-autoscaler/vendor/github.com/Azure/azure-sdk-for-go/arm/resources/resources/group.go
generated
vendored
Normal file
1181
cluster-autoscaler/vendor/github.com/Azure/azure-sdk-for-go/arm/resources/resources/group.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
642
cluster-autoscaler/vendor/github.com/Azure/azure-sdk-for-go/arm/resources/resources/groups.go
generated
vendored
Executable file
642
cluster-autoscaler/vendor/github.com/Azure/azure-sdk-for-go/arm/resources/resources/groups.go
generated
vendored
Executable file
|
|
@ -0,0 +1,642 @@
|
||||||
|
package resources
|
||||||
|
|
||||||
|
// 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"
|
||||||
|
"github.com/Azure/go-autorest/autorest/azure"
|
||||||
|
"github.com/Azure/go-autorest/autorest/validation"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GroupsClient is the provides operations for working with resources and resource groups.
|
||||||
|
type GroupsClient struct {
|
||||||
|
ManagementClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGroupsClient creates an instance of the GroupsClient client.
|
||||||
|
func NewGroupsClient(subscriptionID string) GroupsClient {
|
||||||
|
return NewGroupsClientWithBaseURI(DefaultBaseURI, subscriptionID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGroupsClientWithBaseURI creates an instance of the GroupsClient client.
|
||||||
|
func NewGroupsClientWithBaseURI(baseURI string, subscriptionID string) GroupsClient {
|
||||||
|
return GroupsClient{NewWithBaseURI(baseURI, subscriptionID)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckExistence checks whether a resource group exists.
|
||||||
|
//
|
||||||
|
// resourceGroupName is the name of the resource group to check. The name is case insensitive.
|
||||||
|
func (client GroupsClient) CheckExistence(resourceGroupName string) (result autorest.Response, err error) {
|
||||||
|
if err := validation.Validate([]validation.Validation{
|
||||||
|
{TargetValue: resourceGroupName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil {
|
||||||
|
return result, validation.NewErrorWithValidationError(err, "resources.GroupsClient", "CheckExistence")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := client.CheckExistencePreparer(resourceGroupName)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "CheckExistence", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.CheckExistenceSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = resp
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "CheckExistence", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.CheckExistenceResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "CheckExistence", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckExistencePreparer prepares the CheckExistence request.
|
||||||
|
func (client GroupsClient) CheckExistencePreparer(resourceGroupName string) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsHead(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckExistenceSender sends the CheckExistence request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client GroupsClient) CheckExistenceSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckExistenceResponder handles the response to the CheckExistence request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client GroupsClient) CheckExistenceResponder(resp *http.Response) (result autorest.Response, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusNoContent, http.StatusNotFound),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = resp
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdate creates or updates a resource group.
|
||||||
|
//
|
||||||
|
// resourceGroupName is the name of the resource group to create or update. parameters is parameters supplied to the
|
||||||
|
// create or update a resource group.
|
||||||
|
func (client GroupsClient) CreateOrUpdate(resourceGroupName string, parameters Group) (result Group, err error) {
|
||||||
|
if err := validation.Validate([]validation.Validation{
|
||||||
|
{TargetValue: resourceGroupName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}},
|
||||||
|
{TargetValue: parameters,
|
||||||
|
Constraints: []validation.Constraint{{Target: "parameters.Location", Name: validation.Null, Rule: true, Chain: nil}}}}); err != nil {
|
||||||
|
return result, validation.NewErrorWithValidationError(err, "resources.GroupsClient", "CreateOrUpdate")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := client.CreateOrUpdatePreparer(resourceGroupName, parameters)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "CreateOrUpdate", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.CreateOrUpdateSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "CreateOrUpdate", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.CreateOrUpdateResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "CreateOrUpdate", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdatePreparer prepares the CreateOrUpdate request.
|
||||||
|
func (client GroupsClient) CreateOrUpdatePreparer(resourceGroupName string, parameters Group) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsJSON(),
|
||||||
|
autorest.AsPut(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}", pathParameters),
|
||||||
|
autorest.WithJSON(parameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdateSender sends the CreateOrUpdate request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client GroupsClient) CreateOrUpdateSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdateResponder handles the response to the CreateOrUpdate request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client GroupsClient) CreateOrUpdateResponder(resp *http.Response) (result Group, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusCreated, http.StatusOK),
|
||||||
|
autorest.ByUnmarshallingJSON(&result),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete when you delete a resource group, all of its resources are also deleted. Deleting a resource group deletes
|
||||||
|
// all of its template deployments and currently stored operations. This method may poll for completion. Polling can be
|
||||||
|
// canceled by passing the cancel channel argument. The channel will be used to cancel polling and any outstanding HTTP
|
||||||
|
// requests.
|
||||||
|
//
|
||||||
|
// resourceGroupName is the name of the resource group to delete. The name is case insensitive.
|
||||||
|
func (client GroupsClient) Delete(resourceGroupName string, cancel <-chan struct{}) (<-chan autorest.Response, <-chan error) {
|
||||||
|
resultChan := make(chan autorest.Response, 1)
|
||||||
|
errChan := make(chan error, 1)
|
||||||
|
if err := validation.Validate([]validation.Validation{
|
||||||
|
{TargetValue: resourceGroupName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil {
|
||||||
|
errChan <- validation.NewErrorWithValidationError(err, "resources.GroupsClient", "Delete")
|
||||||
|
close(errChan)
|
||||||
|
close(resultChan)
|
||||||
|
return resultChan, errChan
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
var err error
|
||||||
|
var result autorest.Response
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
}
|
||||||
|
resultChan <- result
|
||||||
|
close(resultChan)
|
||||||
|
close(errChan)
|
||||||
|
}()
|
||||||
|
req, err := client.DeletePreparer(resourceGroupName, cancel)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "Delete", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.DeleteSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = resp
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "Delete", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.DeleteResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "Delete", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return resultChan, errChan
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletePreparer prepares the Delete request.
|
||||||
|
func (client GroupsClient) DeletePreparer(resourceGroupName string, cancel <-chan struct{}) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsDelete(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{Cancel: cancel})
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteSender sends the Delete request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client GroupsClient) DeleteSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client,
|
||||||
|
req,
|
||||||
|
azure.DoPollForAsynchronous(client.PollingDelay))
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteResponder handles the response to the Delete request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client GroupsClient) DeleteResponder(resp *http.Response) (result autorest.Response, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusAccepted, http.StatusOK),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = resp
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportTemplate captures the specified resource group as a template.
|
||||||
|
//
|
||||||
|
// resourceGroupName is the name of the resource group to export as a template. parameters is parameters for exporting
|
||||||
|
// the template.
|
||||||
|
func (client GroupsClient) ExportTemplate(resourceGroupName string, parameters ExportTemplateRequest) (result GroupExportResult, err error) {
|
||||||
|
if err := validation.Validate([]validation.Validation{
|
||||||
|
{TargetValue: resourceGroupName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil {
|
||||||
|
return result, validation.NewErrorWithValidationError(err, "resources.GroupsClient", "ExportTemplate")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := client.ExportTemplatePreparer(resourceGroupName, parameters)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "ExportTemplate", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.ExportTemplateSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "ExportTemplate", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.ExportTemplateResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "ExportTemplate", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportTemplatePreparer prepares the ExportTemplate request.
|
||||||
|
func (client GroupsClient) ExportTemplatePreparer(resourceGroupName string, parameters ExportTemplateRequest) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsJSON(),
|
||||||
|
autorest.AsPost(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/exportTemplate", pathParameters),
|
||||||
|
autorest.WithJSON(parameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportTemplateSender sends the ExportTemplate request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client GroupsClient) ExportTemplateSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportTemplateResponder handles the response to the ExportTemplate request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client GroupsClient) ExportTemplateResponder(resp *http.Response) (result GroupExportResult, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||||
|
autorest.ByUnmarshallingJSON(&result),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get gets a resource group.
|
||||||
|
//
|
||||||
|
// resourceGroupName is the name of the resource group to get. The name is case insensitive.
|
||||||
|
func (client GroupsClient) Get(resourceGroupName string) (result Group, err error) {
|
||||||
|
if err := validation.Validate([]validation.Validation{
|
||||||
|
{TargetValue: resourceGroupName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil {
|
||||||
|
return result, validation.NewErrorWithValidationError(err, "resources.GroupsClient", "Get")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := client.GetPreparer(resourceGroupName)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "Get", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.GetSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "Get", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.GetResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "Get", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPreparer prepares the Get request.
|
||||||
|
func (client GroupsClient) GetPreparer(resourceGroupName string) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsGet(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSender sends the Get request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client GroupsClient) GetSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetResponder handles the response to the Get request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client GroupsClient) GetResponder(resp *http.Response) (result Group, 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 gets all the resource groups for a subscription.
|
||||||
|
//
|
||||||
|
// filter is the filter to apply on the operation. top is the number of results to return. If null is passed, returns
|
||||||
|
// all resource groups.
|
||||||
|
func (client GroupsClient) List(filter string, top *int32) (result GroupListResult, err error) {
|
||||||
|
req, err := client.ListPreparer(filter, top)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "List", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.ListSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "List", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.ListResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "List", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPreparer prepares the List request.
|
||||||
|
func (client GroupsClient) ListPreparer(filter string, top *int32) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
if len(filter) > 0 {
|
||||||
|
queryParameters["$filter"] = autorest.Encode("query", filter)
|
||||||
|
}
|
||||||
|
if top != nil {
|
||||||
|
queryParameters["$top"] = autorest.Encode("query", *top)
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsGet(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourcegroups", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListSender sends the List request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client GroupsClient) ListSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListResponder handles the response to the List request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client GroupsClient) ListResponder(resp *http.Response) (result GroupListResult, 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 GroupsClient) ListNextResults(lastResults GroupListResult) (result GroupListResult, err error) {
|
||||||
|
req, err := lastResults.GroupListResultPreparer()
|
||||||
|
if err != nil {
|
||||||
|
return result, autorest.NewErrorWithError(err, "resources.GroupsClient", "List", 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, "resources.GroupsClient", "List", resp, "Failure sending next results request")
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.ListResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "List", resp, "Failure responding to next results request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListComplete gets all elements from the list without paging.
|
||||||
|
func (client GroupsClient) ListComplete(filter string, top *int32, cancel <-chan struct{}) (<-chan Group, <-chan error) {
|
||||||
|
resultChan := make(chan Group)
|
||||||
|
errChan := make(chan error, 1)
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
close(resultChan)
|
||||||
|
close(errChan)
|
||||||
|
}()
|
||||||
|
list, err := client.List(filter, top)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if list.Value != nil {
|
||||||
|
for _, item := range *list.Value {
|
||||||
|
select {
|
||||||
|
case <-cancel:
|
||||||
|
return
|
||||||
|
case resultChan <- item:
|
||||||
|
// Intentionally left blank
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for list.NextLink != nil {
|
||||||
|
list, err = client.ListNextResults(list)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if list.Value != nil {
|
||||||
|
for _, item := range *list.Value {
|
||||||
|
select {
|
||||||
|
case <-cancel:
|
||||||
|
return
|
||||||
|
case resultChan <- item:
|
||||||
|
// Intentionally left blank
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return resultChan, errChan
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update resource groups can be updated through a simple PATCH operation to a group address. The format of the request
|
||||||
|
// is the same as that for creating a resource group. If a field is unspecified, the current value is retained.
|
||||||
|
//
|
||||||
|
// resourceGroupName is the name of the resource group to update. The name is case insensitive. parameters is
|
||||||
|
// parameters supplied to update a resource group.
|
||||||
|
func (client GroupsClient) Update(resourceGroupName string, parameters GroupPatchable) (result Group, err error) {
|
||||||
|
if err := validation.Validate([]validation.Validation{
|
||||||
|
{TargetValue: resourceGroupName,
|
||||||
|
Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil},
|
||||||
|
{Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil {
|
||||||
|
return result, validation.NewErrorWithValidationError(err, "resources.GroupsClient", "Update")
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := client.UpdatePreparer(resourceGroupName, parameters)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "Update", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.UpdateSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "Update", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.UpdateResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.GroupsClient", "Update", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdatePreparer prepares the Update request.
|
||||||
|
func (client GroupsClient) UpdatePreparer(resourceGroupName string, parameters GroupPatchable) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"resourceGroupName": autorest.Encode("path", resourceGroupName),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsJSON(),
|
||||||
|
autorest.AsPatch(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}", pathParameters),
|
||||||
|
autorest.WithJSON(parameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateSender sends the Update request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client GroupsClient) UpdateSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateResponder handles the response to the Update request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client GroupsClient) UpdateResponder(resp *http.Response) (result Group, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||||
|
autorest.ByUnmarshallingJSON(&result),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
return
|
||||||
|
}
|
||||||
459
cluster-autoscaler/vendor/github.com/Azure/azure-sdk-for-go/arm/resources/resources/models.go
generated
vendored
Executable file
459
cluster-autoscaler/vendor/github.com/Azure/azure-sdk-for-go/arm/resources/resources/models.go
generated
vendored
Executable file
|
|
@ -0,0 +1,459 @@
|
||||||
|
package resources
|
||||||
|
|
||||||
|
// 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"
|
||||||
|
"github.com/Azure/go-autorest/autorest/date"
|
||||||
|
"github.com/Azure/go-autorest/autorest/to"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeploymentMode enumerates the values for deployment mode.
|
||||||
|
type DeploymentMode string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Complete specifies the complete state for deployment mode.
|
||||||
|
Complete DeploymentMode = "Complete"
|
||||||
|
// Incremental specifies the incremental state for deployment mode.
|
||||||
|
Incremental DeploymentMode = "Incremental"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ResourceIdentityType enumerates the values for resource identity type.
|
||||||
|
type ResourceIdentityType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// SystemAssigned specifies the system assigned state for resource identity type.
|
||||||
|
SystemAssigned ResourceIdentityType = "SystemAssigned"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AliasPathType is the type of the paths for alias.
|
||||||
|
type AliasPathType struct {
|
||||||
|
Path *string `json:"path,omitempty"`
|
||||||
|
APIVersions *[]string `json:"apiVersions,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AliasType is the alias type.
|
||||||
|
type AliasType struct {
|
||||||
|
Name *string `json:"name,omitempty"`
|
||||||
|
Paths *[]AliasPathType `json:"paths,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// BasicDependency is deployment dependency information.
|
||||||
|
type BasicDependency struct {
|
||||||
|
ID *string `json:"id,omitempty"`
|
||||||
|
ResourceType *string `json:"resourceType,omitempty"`
|
||||||
|
ResourceName *string `json:"resourceName,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DebugSetting is
|
||||||
|
type DebugSetting struct {
|
||||||
|
DetailLevel *string `json:"detailLevel,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dependency is deployment dependency information.
|
||||||
|
type Dependency struct {
|
||||||
|
DependsOn *[]BasicDependency `json:"dependsOn,omitempty"`
|
||||||
|
ID *string `json:"id,omitempty"`
|
||||||
|
ResourceType *string `json:"resourceType,omitempty"`
|
||||||
|
ResourceName *string `json:"resourceName,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deployment is deployment operation parameters.
|
||||||
|
type Deployment struct {
|
||||||
|
Properties *DeploymentProperties `json:"properties,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeploymentExportResult is the deployment export result.
|
||||||
|
type DeploymentExportResult struct {
|
||||||
|
autorest.Response `json:"-"`
|
||||||
|
Template *map[string]interface{} `json:"template,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeploymentExtended is deployment information.
|
||||||
|
type DeploymentExtended struct {
|
||||||
|
autorest.Response `json:"-"`
|
||||||
|
ID *string `json:"id,omitempty"`
|
||||||
|
Name *string `json:"name,omitempty"`
|
||||||
|
Properties *DeploymentPropertiesExtended `json:"properties,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeploymentExtendedFilter is deployment filter.
|
||||||
|
type DeploymentExtendedFilter struct {
|
||||||
|
ProvisioningState *string `json:"provisioningState,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeploymentListResult is list of deployments.
|
||||||
|
type DeploymentListResult struct {
|
||||||
|
autorest.Response `json:"-"`
|
||||||
|
Value *[]DeploymentExtended `json:"value,omitempty"`
|
||||||
|
NextLink *string `json:"nextLink,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeploymentListResultPreparer prepares a request to retrieve the next set of results. It returns
|
||||||
|
// nil if no more results exist.
|
||||||
|
func (client DeploymentListResult) DeploymentListResultPreparer() (*http.Request, error) {
|
||||||
|
if client.NextLink == nil || len(to.String(client.NextLink)) <= 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return autorest.Prepare(&http.Request{},
|
||||||
|
autorest.AsJSON(),
|
||||||
|
autorest.AsGet(),
|
||||||
|
autorest.WithBaseURL(to.String(client.NextLink)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeploymentOperation is deployment operation information.
|
||||||
|
type DeploymentOperation struct {
|
||||||
|
autorest.Response `json:"-"`
|
||||||
|
ID *string `json:"id,omitempty"`
|
||||||
|
OperationID *string `json:"operationId,omitempty"`
|
||||||
|
Properties *DeploymentOperationProperties `json:"properties,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeploymentOperationProperties is deployment operation properties.
|
||||||
|
type DeploymentOperationProperties struct {
|
||||||
|
ProvisioningState *string `json:"provisioningState,omitempty"`
|
||||||
|
Timestamp *date.Time `json:"timestamp,omitempty"`
|
||||||
|
ServiceRequestID *string `json:"serviceRequestId,omitempty"`
|
||||||
|
StatusCode *string `json:"statusCode,omitempty"`
|
||||||
|
StatusMessage *map[string]interface{} `json:"statusMessage,omitempty"`
|
||||||
|
TargetResource *TargetResource `json:"targetResource,omitempty"`
|
||||||
|
Request *HTTPMessage `json:"request,omitempty"`
|
||||||
|
Response *HTTPMessage `json:"response,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeploymentOperationsListResult is list of deployment operations.
|
||||||
|
type DeploymentOperationsListResult struct {
|
||||||
|
autorest.Response `json:"-"`
|
||||||
|
Value *[]DeploymentOperation `json:"value,omitempty"`
|
||||||
|
NextLink *string `json:"nextLink,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeploymentOperationsListResultPreparer prepares a request to retrieve the next set of results. It returns
|
||||||
|
// nil if no more results exist.
|
||||||
|
func (client DeploymentOperationsListResult) DeploymentOperationsListResultPreparer() (*http.Request, error) {
|
||||||
|
if client.NextLink == nil || len(to.String(client.NextLink)) <= 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return autorest.Prepare(&http.Request{},
|
||||||
|
autorest.AsJSON(),
|
||||||
|
autorest.AsGet(),
|
||||||
|
autorest.WithBaseURL(to.String(client.NextLink)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeploymentProperties is deployment properties.
|
||||||
|
type DeploymentProperties struct {
|
||||||
|
Template *map[string]interface{} `json:"template,omitempty"`
|
||||||
|
TemplateLink *TemplateLink `json:"templateLink,omitempty"`
|
||||||
|
Parameters *map[string]interface{} `json:"parameters,omitempty"`
|
||||||
|
ParametersLink *ParametersLink `json:"parametersLink,omitempty"`
|
||||||
|
Mode DeploymentMode `json:"mode,omitempty"`
|
||||||
|
DebugSetting *DebugSetting `json:"debugSetting,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeploymentPropertiesExtended is deployment properties with additional details.
|
||||||
|
type DeploymentPropertiesExtended struct {
|
||||||
|
ProvisioningState *string `json:"provisioningState,omitempty"`
|
||||||
|
CorrelationID *string `json:"correlationId,omitempty"`
|
||||||
|
Timestamp *date.Time `json:"timestamp,omitempty"`
|
||||||
|
Outputs *map[string]interface{} `json:"outputs,omitempty"`
|
||||||
|
Providers *[]Provider `json:"providers,omitempty"`
|
||||||
|
Dependencies *[]Dependency `json:"dependencies,omitempty"`
|
||||||
|
Template *map[string]interface{} `json:"template,omitempty"`
|
||||||
|
TemplateLink *TemplateLink `json:"templateLink,omitempty"`
|
||||||
|
Parameters *map[string]interface{} `json:"parameters,omitempty"`
|
||||||
|
ParametersLink *ParametersLink `json:"parametersLink,omitempty"`
|
||||||
|
Mode DeploymentMode `json:"mode,omitempty"`
|
||||||
|
DebugSetting *DebugSetting `json:"debugSetting,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeploymentValidateResult is information from validate template deployment response.
|
||||||
|
type DeploymentValidateResult struct {
|
||||||
|
autorest.Response `json:"-"`
|
||||||
|
Error *ManagementErrorWithDetails `json:"error,omitempty"`
|
||||||
|
Properties *DeploymentPropertiesExtended `json:"properties,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExportTemplateRequest is export resource group template request parameters.
|
||||||
|
type ExportTemplateRequest struct {
|
||||||
|
ResourcesProperty *[]string `json:"resources,omitempty"`
|
||||||
|
Options *string `json:"options,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenericResource is resource information.
|
||||||
|
type GenericResource struct {
|
||||||
|
autorest.Response `json:"-"`
|
||||||
|
ID *string `json:"id,omitempty"`
|
||||||
|
Name *string `json:"name,omitempty"`
|
||||||
|
Type *string `json:"type,omitempty"`
|
||||||
|
Location *string `json:"location,omitempty"`
|
||||||
|
Tags *map[string]*string `json:"tags,omitempty"`
|
||||||
|
Plan *Plan `json:"plan,omitempty"`
|
||||||
|
Properties *map[string]interface{} `json:"properties,omitempty"`
|
||||||
|
Kind *string `json:"kind,omitempty"`
|
||||||
|
ManagedBy *string `json:"managedBy,omitempty"`
|
||||||
|
Sku *Sku `json:"sku,omitempty"`
|
||||||
|
Identity *Identity `json:"identity,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenericResourceFilter is resource filter.
|
||||||
|
type GenericResourceFilter struct {
|
||||||
|
ResourceType *string `json:"resourceType,omitempty"`
|
||||||
|
Tagname *string `json:"tagname,omitempty"`
|
||||||
|
Tagvalue *string `json:"tagvalue,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group is resource group information.
|
||||||
|
type Group struct {
|
||||||
|
autorest.Response `json:"-"`
|
||||||
|
ID *string `json:"id,omitempty"`
|
||||||
|
Name *string `json:"name,omitempty"`
|
||||||
|
Properties *GroupProperties `json:"properties,omitempty"`
|
||||||
|
Location *string `json:"location,omitempty"`
|
||||||
|
ManagedBy *string `json:"managedBy,omitempty"`
|
||||||
|
Tags *map[string]*string `json:"tags,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupExportResult is resource group export result.
|
||||||
|
type GroupExportResult struct {
|
||||||
|
autorest.Response `json:"-"`
|
||||||
|
Template *map[string]interface{} `json:"template,omitempty"`
|
||||||
|
Error *ManagementErrorWithDetails `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupFilter is resource group filter.
|
||||||
|
type GroupFilter struct {
|
||||||
|
TagName *string `json:"tagName,omitempty"`
|
||||||
|
TagValue *string `json:"tagValue,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupListResult is list of resource groups.
|
||||||
|
type GroupListResult struct {
|
||||||
|
autorest.Response `json:"-"`
|
||||||
|
Value *[]Group `json:"value,omitempty"`
|
||||||
|
NextLink *string `json:"nextLink,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupListResultPreparer prepares a request to retrieve the next set of results. It returns
|
||||||
|
// nil if no more results exist.
|
||||||
|
func (client GroupListResult) GroupListResultPreparer() (*http.Request, error) {
|
||||||
|
if client.NextLink == nil || len(to.String(client.NextLink)) <= 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return autorest.Prepare(&http.Request{},
|
||||||
|
autorest.AsJSON(),
|
||||||
|
autorest.AsGet(),
|
||||||
|
autorest.WithBaseURL(to.String(client.NextLink)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupPatchable is resource group information.
|
||||||
|
type GroupPatchable struct {
|
||||||
|
Name *string `json:"name,omitempty"`
|
||||||
|
Properties *GroupProperties `json:"properties,omitempty"`
|
||||||
|
ManagedBy *string `json:"managedBy,omitempty"`
|
||||||
|
Tags *map[string]*string `json:"tags,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupProperties is the resource group properties.
|
||||||
|
type GroupProperties struct {
|
||||||
|
ProvisioningState *string `json:"provisioningState,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTPMessage is HTTP message.
|
||||||
|
type HTTPMessage struct {
|
||||||
|
Content *map[string]interface{} `json:"content,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identity is identity for the resource.
|
||||||
|
type Identity struct {
|
||||||
|
PrincipalID *string `json:"principalId,omitempty"`
|
||||||
|
TenantID *string `json:"tenantId,omitempty"`
|
||||||
|
Type ResourceIdentityType `json:"type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListResult is list of resource groups.
|
||||||
|
type ListResult struct {
|
||||||
|
autorest.Response `json:"-"`
|
||||||
|
Value *[]GenericResource `json:"value,omitempty"`
|
||||||
|
NextLink *string `json:"nextLink,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListResultPreparer prepares a request to retrieve the next set of results. It returns
|
||||||
|
// nil if no more results exist.
|
||||||
|
func (client ListResult) ListResultPreparer() (*http.Request, error) {
|
||||||
|
if client.NextLink == nil || len(to.String(client.NextLink)) <= 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return autorest.Prepare(&http.Request{},
|
||||||
|
autorest.AsJSON(),
|
||||||
|
autorest.AsGet(),
|
||||||
|
autorest.WithBaseURL(to.String(client.NextLink)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ManagementErrorWithDetails is the detailed error message of resource management.
|
||||||
|
type ManagementErrorWithDetails struct {
|
||||||
|
Code *string `json:"code,omitempty"`
|
||||||
|
Message *string `json:"message,omitempty"`
|
||||||
|
Target *string `json:"target,omitempty"`
|
||||||
|
Details *[]ManagementErrorWithDetails `json:"details,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MoveInfo is parameters of move resources.
|
||||||
|
type MoveInfo struct {
|
||||||
|
ResourcesProperty *[]string `json:"resources,omitempty"`
|
||||||
|
TargetResourceGroup *string `json:"targetResourceGroup,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParametersLink is entity representing the reference to the deployment paramaters.
|
||||||
|
type ParametersLink struct {
|
||||||
|
URI *string `json:"uri,omitempty"`
|
||||||
|
ContentVersion *string `json:"contentVersion,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plan is plan for the resource.
|
||||||
|
type Plan struct {
|
||||||
|
Name *string `json:"name,omitempty"`
|
||||||
|
Publisher *string `json:"publisher,omitempty"`
|
||||||
|
Product *string `json:"product,omitempty"`
|
||||||
|
PromotionCode *string `json:"promotionCode,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provider is resource provider information.
|
||||||
|
type Provider struct {
|
||||||
|
autorest.Response `json:"-"`
|
||||||
|
ID *string `json:"id,omitempty"`
|
||||||
|
Namespace *string `json:"namespace,omitempty"`
|
||||||
|
RegistrationState *string `json:"registrationState,omitempty"`
|
||||||
|
ResourceTypes *[]ProviderResourceType `json:"resourceTypes,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProviderListResult is list of resource providers.
|
||||||
|
type ProviderListResult struct {
|
||||||
|
autorest.Response `json:"-"`
|
||||||
|
Value *[]Provider `json:"value,omitempty"`
|
||||||
|
NextLink *string `json:"nextLink,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProviderListResultPreparer prepares a request to retrieve the next set of results. It returns
|
||||||
|
// nil if no more results exist.
|
||||||
|
func (client ProviderListResult) ProviderListResultPreparer() (*http.Request, error) {
|
||||||
|
if client.NextLink == nil || len(to.String(client.NextLink)) <= 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return autorest.Prepare(&http.Request{},
|
||||||
|
autorest.AsJSON(),
|
||||||
|
autorest.AsGet(),
|
||||||
|
autorest.WithBaseURL(to.String(client.NextLink)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProviderOperationDisplayProperties is resource provider operation's display properties.
|
||||||
|
type ProviderOperationDisplayProperties struct {
|
||||||
|
Publisher *string `json:"publisher,omitempty"`
|
||||||
|
Provider *string `json:"provider,omitempty"`
|
||||||
|
Resource *string `json:"resource,omitempty"`
|
||||||
|
Operation *string `json:"operation,omitempty"`
|
||||||
|
Description *string `json:"description,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProviderResourceType is resource type managed by the resource provider.
|
||||||
|
type ProviderResourceType struct {
|
||||||
|
ResourceType *string `json:"resourceType,omitempty"`
|
||||||
|
Locations *[]string `json:"locations,omitempty"`
|
||||||
|
Aliases *[]AliasType `json:"aliases,omitempty"`
|
||||||
|
APIVersions *[]string `json:"apiVersions,omitempty"`
|
||||||
|
Properties *map[string]*string `json:"properties,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resource is resource.
|
||||||
|
type Resource struct {
|
||||||
|
ID *string `json:"id,omitempty"`
|
||||||
|
Name *string `json:"name,omitempty"`
|
||||||
|
Type *string `json:"type,omitempty"`
|
||||||
|
Location *string `json:"location,omitempty"`
|
||||||
|
Tags *map[string]*string `json:"tags,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sku is SKU for the resource.
|
||||||
|
type Sku struct {
|
||||||
|
Name *string `json:"name,omitempty"`
|
||||||
|
Tier *string `json:"tier,omitempty"`
|
||||||
|
Size *string `json:"size,omitempty"`
|
||||||
|
Family *string `json:"family,omitempty"`
|
||||||
|
Model *string `json:"model,omitempty"`
|
||||||
|
Capacity *int32 `json:"capacity,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubResource is sub-resource.
|
||||||
|
type SubResource struct {
|
||||||
|
ID *string `json:"id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TagCount is tag count.
|
||||||
|
type TagCount struct {
|
||||||
|
Type *string `json:"type,omitempty"`
|
||||||
|
Value *int32 `json:"value,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TagDetails is tag details.
|
||||||
|
type TagDetails struct {
|
||||||
|
autorest.Response `json:"-"`
|
||||||
|
ID *string `json:"id,omitempty"`
|
||||||
|
TagName *string `json:"tagName,omitempty"`
|
||||||
|
Count *TagCount `json:"count,omitempty"`
|
||||||
|
Values *[]TagValue `json:"values,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TagsListResult is list of subscription tags.
|
||||||
|
type TagsListResult struct {
|
||||||
|
autorest.Response `json:"-"`
|
||||||
|
Value *[]TagDetails `json:"value,omitempty"`
|
||||||
|
NextLink *string `json:"nextLink,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TagsListResultPreparer prepares a request to retrieve the next set of results. It returns
|
||||||
|
// nil if no more results exist.
|
||||||
|
func (client TagsListResult) TagsListResultPreparer() (*http.Request, error) {
|
||||||
|
if client.NextLink == nil || len(to.String(client.NextLink)) <= 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return autorest.Prepare(&http.Request{},
|
||||||
|
autorest.AsJSON(),
|
||||||
|
autorest.AsGet(),
|
||||||
|
autorest.WithBaseURL(to.String(client.NextLink)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TagValue is tag information.
|
||||||
|
type TagValue struct {
|
||||||
|
autorest.Response `json:"-"`
|
||||||
|
ID *string `json:"id,omitempty"`
|
||||||
|
TagValue *string `json:"tagValue,omitempty"`
|
||||||
|
Count *TagCount `json:"count,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetResource is target resource.
|
||||||
|
type TargetResource struct {
|
||||||
|
ID *string `json:"id,omitempty"`
|
||||||
|
ResourceName *string `json:"resourceName,omitempty"`
|
||||||
|
ResourceType *string `json:"resourceType,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TemplateLink is entity representing the reference to the template.
|
||||||
|
type TemplateLink struct {
|
||||||
|
URI *string `json:"uri,omitempty"`
|
||||||
|
ContentVersion *string `json:"contentVersion,omitempty"`
|
||||||
|
}
|
||||||
375
cluster-autoscaler/vendor/github.com/Azure/azure-sdk-for-go/arm/resources/resources/providers.go
generated
vendored
Executable file
375
cluster-autoscaler/vendor/github.com/Azure/azure-sdk-for-go/arm/resources/resources/providers.go
generated
vendored
Executable file
|
|
@ -0,0 +1,375 @@
|
||||||
|
package resources
|
||||||
|
|
||||||
|
// 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"
|
||||||
|
"github.com/Azure/go-autorest/autorest/azure"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ProvidersClient is the provides operations for working with resources and resource groups.
|
||||||
|
type ProvidersClient struct {
|
||||||
|
ManagementClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewProvidersClient creates an instance of the ProvidersClient client.
|
||||||
|
func NewProvidersClient(subscriptionID string) ProvidersClient {
|
||||||
|
return NewProvidersClientWithBaseURI(DefaultBaseURI, subscriptionID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewProvidersClientWithBaseURI creates an instance of the ProvidersClient client.
|
||||||
|
func NewProvidersClientWithBaseURI(baseURI string, subscriptionID string) ProvidersClient {
|
||||||
|
return ProvidersClient{NewWithBaseURI(baseURI, subscriptionID)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get gets the specified resource provider.
|
||||||
|
//
|
||||||
|
// resourceProviderNamespace is the namespace of the resource provider. expand is the $expand query parameter. For
|
||||||
|
// example, to include property aliases in response, use $expand=resourceTypes/aliases.
|
||||||
|
func (client ProvidersClient) Get(resourceProviderNamespace string, expand string) (result Provider, err error) {
|
||||||
|
req, err := client.GetPreparer(resourceProviderNamespace, expand)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.ProvidersClient", "Get", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.GetSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.ProvidersClient", "Get", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.GetResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.ProvidersClient", "Get", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPreparer prepares the Get request.
|
||||||
|
func (client ProvidersClient) GetPreparer(resourceProviderNamespace string, expand string) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"resourceProviderNamespace": autorest.Encode("path", resourceProviderNamespace),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
if len(expand) > 0 {
|
||||||
|
queryParameters["$expand"] = autorest.Encode("query", expand)
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsGet(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/{resourceProviderNamespace}", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSender sends the Get request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client ProvidersClient) GetSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetResponder handles the response to the Get request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client ProvidersClient) GetResponder(resp *http.Response) (result Provider, 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 gets all resource providers for a subscription.
|
||||||
|
//
|
||||||
|
// top is the number of results to return. If null is passed returns all deployments. expand is the properties to
|
||||||
|
// include in the results. For example, use &$expand=metadata in the query string to retrieve resource provider
|
||||||
|
// metadata. To include property aliases in response, use $expand=resourceTypes/aliases.
|
||||||
|
func (client ProvidersClient) List(top *int32, expand string) (result ProviderListResult, err error) {
|
||||||
|
req, err := client.ListPreparer(top, expand)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.ProvidersClient", "List", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.ListSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.ProvidersClient", "List", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.ListResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.ProvidersClient", "List", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPreparer prepares the List request.
|
||||||
|
func (client ProvidersClient) ListPreparer(top *int32, expand string) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
if top != nil {
|
||||||
|
queryParameters["$top"] = autorest.Encode("query", *top)
|
||||||
|
}
|
||||||
|
if len(expand) > 0 {
|
||||||
|
queryParameters["$expand"] = autorest.Encode("query", expand)
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsGet(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListSender sends the List request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client ProvidersClient) ListSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListResponder handles the response to the List request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client ProvidersClient) ListResponder(resp *http.Response) (result ProviderListResult, 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 ProvidersClient) ListNextResults(lastResults ProviderListResult) (result ProviderListResult, err error) {
|
||||||
|
req, err := lastResults.ProviderListResultPreparer()
|
||||||
|
if err != nil {
|
||||||
|
return result, autorest.NewErrorWithError(err, "resources.ProvidersClient", "List", 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, "resources.ProvidersClient", "List", resp, "Failure sending next results request")
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.ListResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.ProvidersClient", "List", resp, "Failure responding to next results request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListComplete gets all elements from the list without paging.
|
||||||
|
func (client ProvidersClient) ListComplete(top *int32, expand string, cancel <-chan struct{}) (<-chan Provider, <-chan error) {
|
||||||
|
resultChan := make(chan Provider)
|
||||||
|
errChan := make(chan error, 1)
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
close(resultChan)
|
||||||
|
close(errChan)
|
||||||
|
}()
|
||||||
|
list, err := client.List(top, expand)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if list.Value != nil {
|
||||||
|
for _, item := range *list.Value {
|
||||||
|
select {
|
||||||
|
case <-cancel:
|
||||||
|
return
|
||||||
|
case resultChan <- item:
|
||||||
|
// Intentionally left blank
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for list.NextLink != nil {
|
||||||
|
list, err = client.ListNextResults(list)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if list.Value != nil {
|
||||||
|
for _, item := range *list.Value {
|
||||||
|
select {
|
||||||
|
case <-cancel:
|
||||||
|
return
|
||||||
|
case resultChan <- item:
|
||||||
|
// Intentionally left blank
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return resultChan, errChan
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register registers a subscription with a resource provider.
|
||||||
|
//
|
||||||
|
// resourceProviderNamespace is the namespace of the resource provider to register.
|
||||||
|
func (client ProvidersClient) Register(resourceProviderNamespace string) (result Provider, err error) {
|
||||||
|
req, err := client.RegisterPreparer(resourceProviderNamespace)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.ProvidersClient", "Register", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.RegisterSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.ProvidersClient", "Register", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.RegisterResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.ProvidersClient", "Register", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterPreparer prepares the Register request.
|
||||||
|
func (client ProvidersClient) RegisterPreparer(resourceProviderNamespace string) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"resourceProviderNamespace": autorest.Encode("path", resourceProviderNamespace),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsPost(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/{resourceProviderNamespace}/register", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterSender sends the Register request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client ProvidersClient) RegisterSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterResponder handles the response to the Register request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client ProvidersClient) RegisterResponder(resp *http.Response) (result Provider, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||||
|
autorest.ByUnmarshallingJSON(&result),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unregister unregisters a subscription from a resource provider.
|
||||||
|
//
|
||||||
|
// resourceProviderNamespace is the namespace of the resource provider to unregister.
|
||||||
|
func (client ProvidersClient) Unregister(resourceProviderNamespace string) (result Provider, err error) {
|
||||||
|
req, err := client.UnregisterPreparer(resourceProviderNamespace)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.ProvidersClient", "Unregister", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.UnregisterSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.ProvidersClient", "Unregister", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.UnregisterResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.ProvidersClient", "Unregister", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnregisterPreparer prepares the Unregister request.
|
||||||
|
func (client ProvidersClient) UnregisterPreparer(resourceProviderNamespace string) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"resourceProviderNamespace": autorest.Encode("path", resourceProviderNamespace),
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsPost(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/{resourceProviderNamespace}/unregister", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnregisterSender sends the Unregister request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client ProvidersClient) UnregisterSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnregisterResponder handles the response to the Unregister request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client ProvidersClient) UnregisterResponder(resp *http.Response) (result Provider, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK),
|
||||||
|
autorest.ByUnmarshallingJSON(&result),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
return
|
||||||
|
}
|
||||||
426
cluster-autoscaler/vendor/github.com/Azure/azure-sdk-for-go/arm/resources/resources/tags.go
generated
vendored
Executable file
426
cluster-autoscaler/vendor/github.com/Azure/azure-sdk-for-go/arm/resources/resources/tags.go
generated
vendored
Executable file
|
|
@ -0,0 +1,426 @@
|
||||||
|
package resources
|
||||||
|
|
||||||
|
// 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"
|
||||||
|
"github.com/Azure/go-autorest/autorest/azure"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TagsClient is the provides operations for working with resources and resource groups.
|
||||||
|
type TagsClient struct {
|
||||||
|
ManagementClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTagsClient creates an instance of the TagsClient client.
|
||||||
|
func NewTagsClient(subscriptionID string) TagsClient {
|
||||||
|
return NewTagsClientWithBaseURI(DefaultBaseURI, subscriptionID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTagsClientWithBaseURI creates an instance of the TagsClient client.
|
||||||
|
func NewTagsClientWithBaseURI(baseURI string, subscriptionID string) TagsClient {
|
||||||
|
return TagsClient{NewWithBaseURI(baseURI, subscriptionID)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdate the tag name can have a maximum of 512 characters and is case insensitive. Tag names created by Azure
|
||||||
|
// have prefixes of microsoft, azure, or windows. You cannot create tags with one of these prefixes.
|
||||||
|
//
|
||||||
|
// tagName is the name of the tag to create.
|
||||||
|
func (client TagsClient) CreateOrUpdate(tagName string) (result TagDetails, err error) {
|
||||||
|
req, err := client.CreateOrUpdatePreparer(tagName)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.TagsClient", "CreateOrUpdate", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.CreateOrUpdateSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.TagsClient", "CreateOrUpdate", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.CreateOrUpdateResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.TagsClient", "CreateOrUpdate", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdatePreparer prepares the CreateOrUpdate request.
|
||||||
|
func (client TagsClient) CreateOrUpdatePreparer(tagName string) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
"tagName": autorest.Encode("path", tagName),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsPut(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/tagNames/{tagName}", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdateSender sends the CreateOrUpdate request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client TagsClient) CreateOrUpdateSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdateResponder handles the response to the CreateOrUpdate request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client TagsClient) CreateOrUpdateResponder(resp *http.Response) (result TagDetails, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusCreated),
|
||||||
|
autorest.ByUnmarshallingJSON(&result),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdateValue creates a tag value. The name of the tag must already exist.
|
||||||
|
//
|
||||||
|
// tagName is the name of the tag. tagValue is the value of the tag to create.
|
||||||
|
func (client TagsClient) CreateOrUpdateValue(tagName string, tagValue string) (result TagValue, err error) {
|
||||||
|
req, err := client.CreateOrUpdateValuePreparer(tagName, tagValue)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.TagsClient", "CreateOrUpdateValue", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.CreateOrUpdateValueSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.TagsClient", "CreateOrUpdateValue", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.CreateOrUpdateValueResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.TagsClient", "CreateOrUpdateValue", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdateValuePreparer prepares the CreateOrUpdateValue request.
|
||||||
|
func (client TagsClient) CreateOrUpdateValuePreparer(tagName string, tagValue string) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
"tagName": autorest.Encode("path", tagName),
|
||||||
|
"tagValue": autorest.Encode("path", tagValue),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsPut(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/tagNames/{tagName}/tagValues/{tagValue}", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdateValueSender sends the CreateOrUpdateValue request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client TagsClient) CreateOrUpdateValueSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrUpdateValueResponder handles the response to the CreateOrUpdateValue request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client TagsClient) CreateOrUpdateValueResponder(resp *http.Response) (result TagValue, err error) {
|
||||||
|
err = autorest.Respond(
|
||||||
|
resp,
|
||||||
|
client.ByInspecting(),
|
||||||
|
azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusCreated),
|
||||||
|
autorest.ByUnmarshallingJSON(&result),
|
||||||
|
autorest.ByClosing())
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete you must remove all values from a resource tag before you can delete it.
|
||||||
|
//
|
||||||
|
// tagName is the name of the tag.
|
||||||
|
func (client TagsClient) Delete(tagName string) (result autorest.Response, err error) {
|
||||||
|
req, err := client.DeletePreparer(tagName)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.TagsClient", "Delete", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.DeleteSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = resp
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.TagsClient", "Delete", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.DeleteResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.TagsClient", "Delete", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletePreparer prepares the Delete request.
|
||||||
|
func (client TagsClient) DeletePreparer(tagName string) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
"tagName": autorest.Encode("path", tagName),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsDelete(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/tagNames/{tagName}", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteSender sends the Delete request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client TagsClient) DeleteSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteResponder handles the response to the Delete request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client TagsClient) DeleteResponder(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
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteValue deletes a tag value.
|
||||||
|
//
|
||||||
|
// tagName is the name of the tag. tagValue is the value of the tag to delete.
|
||||||
|
func (client TagsClient) DeleteValue(tagName string, tagValue string) (result autorest.Response, err error) {
|
||||||
|
req, err := client.DeleteValuePreparer(tagName, tagValue)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.TagsClient", "DeleteValue", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.DeleteValueSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = resp
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.TagsClient", "DeleteValue", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.DeleteValueResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.TagsClient", "DeleteValue", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteValuePreparer prepares the DeleteValue request.
|
||||||
|
func (client TagsClient) DeleteValuePreparer(tagName string, tagValue string) (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
"tagName": autorest.Encode("path", tagName),
|
||||||
|
"tagValue": autorest.Encode("path", tagValue),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsDelete(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/tagNames/{tagName}/tagValues/{tagValue}", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteValueSender sends the DeleteValue request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client TagsClient) DeleteValueSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteValueResponder handles the response to the DeleteValue request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client TagsClient) DeleteValueResponder(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
|
||||||
|
}
|
||||||
|
|
||||||
|
// List gets the names and values of all resource tags that are defined in a subscription.
|
||||||
|
func (client TagsClient) List() (result TagsListResult, err error) {
|
||||||
|
req, err := client.ListPreparer()
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.TagsClient", "List", nil, "Failure preparing request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.ListSender(req)
|
||||||
|
if err != nil {
|
||||||
|
result.Response = autorest.Response{Response: resp}
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.TagsClient", "List", resp, "Failure sending request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.ListResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.TagsClient", "List", resp, "Failure responding to request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPreparer prepares the List request.
|
||||||
|
func (client TagsClient) ListPreparer() (*http.Request, error) {
|
||||||
|
pathParameters := map[string]interface{}{
|
||||||
|
"subscriptionId": autorest.Encode("path", client.SubscriptionID),
|
||||||
|
}
|
||||||
|
|
||||||
|
const APIVersion = "2017-05-10"
|
||||||
|
queryParameters := map[string]interface{}{
|
||||||
|
"api-version": APIVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
preparer := autorest.CreatePreparer(
|
||||||
|
autorest.AsGet(),
|
||||||
|
autorest.WithBaseURL(client.BaseURI),
|
||||||
|
autorest.WithPathParameters("/subscriptions/{subscriptionId}/tagNames", pathParameters),
|
||||||
|
autorest.WithQueryParameters(queryParameters))
|
||||||
|
return preparer.Prepare(&http.Request{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListSender sends the List request. The method will close the
|
||||||
|
// http.Response Body if it receives an error.
|
||||||
|
func (client TagsClient) ListSender(req *http.Request) (*http.Response, error) {
|
||||||
|
return autorest.SendWithSender(client, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListResponder handles the response to the List request. The method always
|
||||||
|
// closes the http.Response Body.
|
||||||
|
func (client TagsClient) ListResponder(resp *http.Response) (result TagsListResult, 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 TagsClient) ListNextResults(lastResults TagsListResult) (result TagsListResult, err error) {
|
||||||
|
req, err := lastResults.TagsListResultPreparer()
|
||||||
|
if err != nil {
|
||||||
|
return result, autorest.NewErrorWithError(err, "resources.TagsClient", "List", 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, "resources.TagsClient", "List", resp, "Failure sending next results request")
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = client.ListResponder(resp)
|
||||||
|
if err != nil {
|
||||||
|
err = autorest.NewErrorWithError(err, "resources.TagsClient", "List", resp, "Failure responding to next results request")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListComplete gets all elements from the list without paging.
|
||||||
|
func (client TagsClient) ListComplete(cancel <-chan struct{}) (<-chan TagDetails, <-chan error) {
|
||||||
|
resultChan := make(chan TagDetails)
|
||||||
|
errChan := make(chan error, 1)
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
close(resultChan)
|
||||||
|
close(errChan)
|
||||||
|
}()
|
||||||
|
list, err := client.List()
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if list.Value != nil {
|
||||||
|
for _, item := range *list.Value {
|
||||||
|
select {
|
||||||
|
case <-cancel:
|
||||||
|
return
|
||||||
|
case resultChan <- item:
|
||||||
|
// Intentionally left blank
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for list.NextLink != nil {
|
||||||
|
list, err = client.ListNextResults(list)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if list.Value != nil {
|
||||||
|
for _, item := range *list.Value {
|
||||||
|
select {
|
||||||
|
case <-cancel:
|
||||||
|
return
|
||||||
|
case resultChan <- item:
|
||||||
|
// Intentionally left blank
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return resultChan, errChan
|
||||||
|
}
|
||||||
28
cluster-autoscaler/vendor/github.com/Azure/azure-sdk-for-go/arm/resources/resources/version.go
generated
vendored
Executable file
28
cluster-autoscaler/vendor/github.com/Azure/azure-sdk-for-go/arm/resources/resources/version.go
generated
vendored
Executable file
|
|
@ -0,0 +1,28 @@
|
||||||
|
package resources
|
||||||
|
|
||||||
|
// 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/v11.0.0-beta arm-resources/2017-05-10"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version returns the semantic version (see http://semver.org) of the client.
|
||||||
|
func Version() string {
|
||||||
|
return "v11.0.0-beta"
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue