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",
|
||||
"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",
|
||||
"Comment": "v11.1.1-beta",
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
# 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
|
||||
|
||||
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
|
||||
|
||||
|
|
@ -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
|
||||
```
|
||||
|
||||
And fill the values with the result you got into the configmap
|
||||
## Deployment manifests
|
||||
|
||||
```yaml
|
||||
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
|
||||
```
|
||||
### VMSS deployment
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
```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:
|
||||
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"
|
||||
```sh
|
||||
kubectl create -f cluster-autoscaler-vmss-master.yaml
|
||||
```
|
||||
|
||||
### 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/autoscaler/cluster-autoscaler/cloudprovider"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/utils/errors"
|
||||
"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -38,7 +37,7 @@ const (
|
|||
// AzureCloudProvider provides implementation of CloudProvider interface for Azure.
|
||||
type AzureCloudProvider struct {
|
||||
azureManager *AzureManager
|
||||
scaleSets []*ScaleSet
|
||||
nodeGroups []cloudprovider.NodeGroup
|
||||
resourceLimiter *cloudprovider.ResourceLimiter
|
||||
}
|
||||
|
||||
|
|
@ -66,12 +65,13 @@ func (azure *AzureCloudProvider) Cleanup() error {
|
|||
// addNodeGroup adds node group defined in string spec. Format:
|
||||
// minNodes:maxNodes:scaleSetName
|
||||
func (azure *AzureCloudProvider) addNodeGroup(spec string) error {
|
||||
scaleSet, err := buildScaleSet(spec, azure.azureManager)
|
||||
nodeGroup, err := azure.buildNodeGroup(spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
azure.scaleSets = append(azure.scaleSets, scaleSet)
|
||||
azure.azureManager.RegisterScaleSet(scaleSet)
|
||||
|
||||
azure.nodeGroups = append(azure.nodeGroups, nodeGroup)
|
||||
azure.azureManager.RegisterNodeGroup(nodeGroup)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -82,9 +82,9 @@ func (azure *AzureCloudProvider) Name() string {
|
|||
|
||||
// NodeGroups returns all node groups configured for this cloud provider.
|
||||
func (azure *AzureCloudProvider) NodeGroups() []cloudprovider.NodeGroup {
|
||||
result := make([]cloudprovider.NodeGroup, 0, len(azure.scaleSets))
|
||||
for _, scaleSet := range azure.scaleSets {
|
||||
result = append(result, scaleSet)
|
||||
result := make([]cloudprovider.NodeGroup, 0, len(azure.nodeGroups))
|
||||
for _, nodeGroup := range azure.nodeGroups {
|
||||
result = append(result, nodeGroup)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
@ -96,9 +96,7 @@ func (azure *AzureCloudProvider) NodeGroupForNode(node *apiv1.Node) (cloudprovid
|
|||
Name: strings.ToLower(node.Spec.ProviderID),
|
||||
}
|
||||
|
||||
scaleSet, err := azure.azureManager.GetScaleSetForInstance(ref)
|
||||
|
||||
return scaleSet, err
|
||||
return azure.azureManager.GetNodeGroupForInstance(ref)
|
||||
}
|
||||
|
||||
// Pricing returns pricing model for this cloud provider or error if not available.
|
||||
|
|
@ -128,6 +126,46 @@ func (azure *AzureCloudProvider) Refresh() error {
|
|||
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.
|
||||
type AzureRef struct {
|
||||
Name string
|
||||
|
|
@ -137,207 +175,3 @@ type AzureRef struct {
|
|||
func (m *AzureRef) GetKey() string {
|
||||
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
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/arm/compute"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
|
||||
)
|
||||
|
||||
// Mock for VirtualMachineScaleSetsClient
|
||||
type VirtualMachineScaleSetsClientMock struct {
|
||||
mock.Mock
|
||||
}
|
||||
func newTestAzureManager() *AzureManager {
|
||||
return &AzureManager{
|
||||
config: &Config{VMType: vmTypeVMSS},
|
||||
env: azure.PublicCloud,
|
||||
interrupt: make(chan struct{}),
|
||||
instanceIDsCache: make(map[string]string),
|
||||
nodeGroups: make([]cloudprovider.NodeGroup, 0),
|
||||
nodeGroupsCache: make(map[AzureRef]cloudprovider.NodeGroup),
|
||||
|
||||
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,
|
||||
disksClient: &DisksClientMock{},
|
||||
interfacesClient: &InterfacesClientMock{},
|
||||
storageAccountsClient: &AccountsClientMock{},
|
||||
deploymentsClient: &DeploymentsClientMock{},
|
||||
virtualMachinesClient: &VirtualMachinesClientMock{},
|
||||
virtualMachineScaleSetsClient: &VirtualMachineScaleSetsClientMock{},
|
||||
virtualMachineScaleSetVMsClient: &VirtualMachineScaleSetVMsClientMock{},
|
||||
}
|
||||
|
||||
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{}),
|
||||
}
|
||||
|
||||
func testProvider(t *testing.T, m *AzureManager) *AzureCloudProvider {
|
||||
func newTestProvider() (*AzureCloudProvider, error) {
|
||||
manager := newTestAzureManager()
|
||||
resourceLimiter := cloudprovider.NewResourceLimiter(
|
||||
map[string]int64{cloudprovider.ResourceNameCores: 1, cloudprovider.ResourceNameMemory: 10000000},
|
||||
map[string]int64{cloudprovider.ResourceNameCores: 10, cloudprovider.ResourceNameMemory: 100000000})
|
||||
provider, err := BuildAzureCloudProvider(m, nil, resourceLimiter)
|
||||
assert.NoError(t, err)
|
||||
return provider
|
||||
return BuildAzureCloudProvider(manager, nil, resourceLimiter)
|
||||
}
|
||||
|
||||
func TestBuildAzureCloudProvider(t *testing.T) {
|
||||
resourceLimiter := cloudprovider.NewResourceLimiter(
|
||||
map[string]int64{cloudprovider.ResourceNameCores: 1, cloudprovider.ResourceNameMemory: 10000000},
|
||||
map[string]int64{cloudprovider.ResourceNameCores: 10, cloudprovider.ResourceNameMemory: 100000000})
|
||||
m := testAzureManager
|
||||
m := newTestAzureManager()
|
||||
_, err := BuildAzureCloudProvider(m, []string{"bad spec"}, resourceLimiter)
|
||||
assert.Error(t, err)
|
||||
|
||||
|
|
@ -119,56 +66,50 @@ func TestBuildAzureCloudProvider(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAddNodeGroup(t *testing.T) {
|
||||
provider := testProvider(t, testAzureManager)
|
||||
err := provider.addNodeGroup("bad spec")
|
||||
provider, err := newTestProvider()
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = provider.addNodeGroup("bad spec")
|
||||
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")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, len(provider.scaleSets), 1)
|
||||
assert.Equal(t, len(provider.nodeGroups), 1)
|
||||
}
|
||||
|
||||
func TestName(t *testing.T) {
|
||||
provider := testProvider(t, testAzureManager)
|
||||
provider, err := newTestProvider()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, provider.Name(), "azure")
|
||||
}
|
||||
|
||||
func TestNodeGroups(t *testing.T) {
|
||||
provider := testProvider(t, testAzureManager)
|
||||
provider, err := newTestProvider()
|
||||
assert.NoError(t, err)
|
||||
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.Equal(t, len(provider.NodeGroups()), 1)
|
||||
}
|
||||
|
||||
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{
|
||||
Spec: apiv1.NodeSpec{
|
||||
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)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, group, "Group should not be nil")
|
||||
|
||||
assert.Equal(t, group.Id(), "test-asg")
|
||||
assert.Equal(t, group.MinSize(), 1)
|
||||
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",
|
||||
},
|
||||
}
|
||||
|
||||
group, err = provider.NodeGroupForNode(nodeNotInGroup)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, group)
|
||||
|
||||
}
|
||||
|
||||
func TestAzureRefFromProviderId(t *testing.T) {
|
||||
_, err := AzureRefFromProviderId("azure:///123")
|
||||
func TestBuildNodeGroup(t *testing.T) {
|
||||
provider, err := newTestProvider()
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = provider.buildNodeGroup("a")
|
||||
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)
|
||||
|
||||
// Example id: "azure:///subscriptions/subscriptionId/resourceGroups/kubernetes/providers/Microsoft.Compute/virtualMachines/kubernetes-master"
|
||||
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)
|
||||
_, err = provider.buildNodeGroup("-1:2:")
|
||||
assert.Error(t, err)
|
||||
|
||||
validNode := &apiv1.Node{
|
||||
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)
|
||||
_, err = provider.buildNodeGroup("5:3:")
|
||||
assert.Error(t, err)
|
||||
|
||||
_, err = buildScaleSet("-1:2:", nil)
|
||||
_, err = provider.buildNodeGroup("5:ddd:test-name")
|
||||
assert.Error(t, err)
|
||||
|
||||
_, err = buildScaleSet("5:3:", nil)
|
||||
assert.Error(t, err)
|
||||
|
||||
_, err = buildScaleSet("5:ddd:test-name", nil)
|
||||
assert.Error(t, err)
|
||||
|
||||
asg, err := buildScaleSet("111:222:test-name", nil)
|
||||
asg, err := provider.buildNodeGroup("111:222:test-name")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 111, asg.MinSize())
|
||||
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 (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"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/adal"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
|
|
@ -33,35 +38,75 @@ import (
|
|||
|
||||
"gopkg.in/gcfg.v1"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
|
||||
)
|
||||
|
||||
type scaleSetInformation struct {
|
||||
config *ScaleSet
|
||||
basename string
|
||||
}
|
||||
const (
|
||||
vmTypeVMSS = "vmss"
|
||||
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)
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
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.
|
||||
type AzureManager struct {
|
||||
resourceGroupName string
|
||||
subscription string
|
||||
scaleSetClient scaleSetClient
|
||||
scaleSetVmClient scaleSetVMClient
|
||||
config *Config
|
||||
env azure.Environment
|
||||
|
||||
scaleSets []*scaleSetInformation
|
||||
scaleSetCache map[AzureRef]*ScaleSet
|
||||
virtualMachineScaleSetsClient VirtualMachineScaleSetsClient
|
||||
virtualMachineScaleSetVMsClient VirtualMachineScaleSetVMsClient
|
||||
virtualMachinesClient VirtualMachinesClient
|
||||
deploymentsClient DeploymentsClient
|
||||
interfacesClient InterfacesClient
|
||||
disksClient DisksClient
|
||||
storageAccountsClient AccountsClient
|
||||
|
||||
// cache of mapping from instance id to the scale set id
|
||||
scaleSetIdCache map[string]string
|
||||
nodeGroups []cloudprovider.NodeGroup
|
||||
// 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
|
||||
interrupt chan struct{}
|
||||
|
|
@ -69,102 +114,183 @@ type AzureManager struct {
|
|||
|
||||
// Config holds the configuration parsed from the --cloud-config flag
|
||||
type Config struct {
|
||||
Cloud string `json:"cloud" yaml:"cloud"`
|
||||
TenantID string `json:"tenantId" yaml:"tenantId"`
|
||||
SubscriptionID string `json:"subscriptionId" yaml:"subscriptionId"`
|
||||
ResourceGroup string `json:"resourceGroup" yaml:"resourceGroup"`
|
||||
Location string `json:"location" yaml:"location"`
|
||||
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"`
|
||||
Cloud string `json:"cloud" yaml:"cloud"`
|
||||
TenantID string `json:"tenantId" yaml:"tenantId"`
|
||||
SubscriptionID string `json:"subscriptionId" yaml:"subscriptionId"`
|
||||
ResourceGroup string `json:"resourceGroup" yaml:"resourceGroup"`
|
||||
VMType string `json:"vmType" yaml:"vmType"`
|
||||
|
||||
AADClientID string `json:"aadClientId" yaml:"aadClientId"`
|
||||
AADClientSecret string `json:"aadClientSecret" yaml:"aadClientSecret"`
|
||||
AADTenantID string `json:"aadTenantId" yaml:"aadTenantId"`
|
||||
AADClientID string `json:"aadClientId" yaml:"aadClientId"`
|
||||
AADClientSecret string `json:"aadClientSecret" yaml:"aadClientSecret"`
|
||||
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.
|
||||
func CreateAzureManager(configReader io.Reader) (*AzureManager, error) {
|
||||
subscriptionId := string("")
|
||||
resourceGroup := string("")
|
||||
tenantId := string("")
|
||||
clientId := string("")
|
||||
clientSecret := string("")
|
||||
var scaleSetAPI scaleSetClient
|
||||
var scaleSetVmAPI scaleSetVMClient
|
||||
var err error
|
||||
var cfg Config
|
||||
|
||||
if configReader != nil {
|
||||
var cfg Config
|
||||
if err := gcfg.ReadInto(&cfg, configReader); err != nil {
|
||||
glog.Errorf("Couldn't read config: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
subscriptionId = cfg.SubscriptionID
|
||||
resourceGroup = cfg.ResourceGroup
|
||||
tenantId = cfg.AADTenantID
|
||||
clientId = cfg.AADClientID
|
||||
clientSecret = cfg.AADClientSecret
|
||||
|
||||
} else {
|
||||
subscriptionId = os.Getenv("ARM_SUBSCRIPTION_ID")
|
||||
resourceGroup = os.Getenv("ARM_RESOURCE_GROUP")
|
||||
tenantId = os.Getenv("ARM_TENANT_ID")
|
||||
clientId = os.Getenv("ARM_CLIENT_ID")
|
||||
clientSecret = os.Getenv("ARM_CLIENT_SECRET")
|
||||
cfg.Cloud = os.Getenv("ARM_CLOUD")
|
||||
cfg.SubscriptionID = os.Getenv("ARM_SUBSCRIPTION_ID")
|
||||
cfg.ResourceGroup = os.Getenv("ARM_RESOURCE_GROUP")
|
||||
cfg.TenantID = os.Getenv("ARM_TENANT_ID")
|
||||
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")
|
||||
|
||||
useManagedIdentityExtensionFromEnv := os.Getenv("ARM_USE_MANAGED_IDENTITY_EXTENSION")
|
||||
if len(useManagedIdentityExtensionFromEnv) > 0 {
|
||||
cfg.UseManagedIdentityExtension, err = strconv.ParseBool(useManagedIdentityExtensionFromEnv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if resourceGroup == "" {
|
||||
panic("Resource group not found")
|
||||
// Defaulting vmType to vmss.
|
||||
if cfg.VMType == "" {
|
||||
cfg.VMType = vmTypeVMSS
|
||||
}
|
||||
|
||||
if subscriptionId == "" {
|
||||
panic("Subscription ID not found")
|
||||
env := azure.PublicCloud
|
||||
if cfg.Cloud != "" {
|
||||
env, err = azure.EnvironmentFromName(cfg.Cloud)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if tenantId == "" {
|
||||
panic("Tenant ID not found.")
|
||||
if cfg.ResourceGroup == "" {
|
||||
return nil, fmt.Errorf("resource group not set")
|
||||
}
|
||||
|
||||
if clientId == "" {
|
||||
panic("ARM Client ID not found")
|
||||
if cfg.SubscriptionID == "" {
|
||||
return nil, fmt.Errorf("subscription ID not set")
|
||||
}
|
||||
|
||||
if clientSecret == "" {
|
||||
panic("ARM Client Secret not found.")
|
||||
if cfg.TenantID == "" {
|
||||
return nil, fmt.Errorf("tenant ID not set")
|
||||
}
|
||||
|
||||
glog.Infof("read configuration: %v", subscriptionId)
|
||||
if cfg.AADClientID == "" {
|
||||
return nil, fmt.Errorf("ARM Client ID not set")
|
||||
}
|
||||
|
||||
spt, err := NewServicePrincipalTokenFromCredentials(tenantId, clientId, clientSecret, azure.PublicCloud.ServiceManagementEndpoint)
|
||||
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 {
|
||||
panic(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
scaleSetAPI = compute.NewVirtualMachineScaleSetsClient(subscriptionId)
|
||||
scaleSetsClient := scaleSetAPI.(compute.VirtualMachineScaleSetsClient)
|
||||
scaleSetsClient := compute.NewVirtualMachineScaleSetsClient(cfg.SubscriptionID)
|
||||
scaleSetsClient.BaseURI = env.ResourceManagerEndpoint
|
||||
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)
|
||||
|
||||
scaleSetVmAPI = compute.NewVirtualMachineScaleSetVMsClient(subscriptionId)
|
||||
scaleSetVMsClient := scaleSetVmAPI.(compute.VirtualMachineScaleSetVMsClient)
|
||||
scaleSetVMsClient := compute.NewVirtualMachineScaleSetVMsClient(cfg.SubscriptionID)
|
||||
scaleSetVMsClient.BaseURI = env.ResourceManagerEndpoint
|
||||
scaleSetVMsClient.Authorizer = autorest.NewBearerAuthorizer(spt)
|
||||
scaleSetVMsClient.RequestInspector = withInspection()
|
||||
scaleSetVMsClient.ResponseInspector = byInspecting()
|
||||
scaleSetVMsClient.PollingDelay = 5 * time.Second
|
||||
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{
|
||||
subscription: subscriptionId,
|
||||
resourceGroupName: resourceGroup,
|
||||
scaleSetClient: scaleSetsClient,
|
||||
scaleSetVmClient: scaleSetVMsClient,
|
||||
scaleSets: make([]*scaleSetInformation, 0),
|
||||
scaleSetCache: make(map[AzureRef]*ScaleSet),
|
||||
interrupt: make(chan struct{}),
|
||||
config: &cfg,
|
||||
env: env,
|
||||
disksClient: disksClient,
|
||||
interfacesClient: interfacesClient,
|
||||
virtualMachineScaleSetsClient: scaleSetsClient,
|
||||
virtualMachineScaleSetVMsClient: scaleSetVMsClient,
|
||||
deploymentsClient: deploymentsClient,
|
||||
virtualMachinesClient: virtualMachinesClient,
|
||||
storageAccountsClient: storageAccountsClient,
|
||||
|
||||
interrupt: make(chan struct{}),
|
||||
instanceIDsCache: make(map[string]string),
|
||||
nodeGroups: make([]cloudprovider.NodeGroup, 0),
|
||||
nodeGroupsCache: make(map[AzureRef]cloudprovider.NodeGroup),
|
||||
}
|
||||
|
||||
go wait.Until(func() {
|
||||
|
|
@ -173,184 +299,237 @@ func CreateAzureManager(configReader io.Reader) (*AzureManager, error) {
|
|||
if err := manager.regenerateCache(); err != nil {
|
||||
glog.Errorf("Error while regenerating AS cache: %v", err)
|
||||
}
|
||||
}, time.Hour, manager.interrupt)
|
||||
}, 5*time.Minute, manager.interrupt)
|
||||
|
||||
return manager, nil
|
||||
}
|
||||
|
||||
// NewServicePrincipalTokenFromCredentials creates a new ServicePrincipalToken using values of the
|
||||
// passed credentials map.
|
||||
func NewServicePrincipalTokenFromCredentials(tenantID string, clientID string, clientSecret string, scope string) (*adal.ServicePrincipalToken, error) {
|
||||
oauthConfig, err := adal.NewOAuthConfig(azure.PublicCloud.ActiveDirectoryEndpoint, tenantID)
|
||||
func NewServicePrincipalTokenFromCredentials(config *Config, env *azure.Environment) (*adal.ServicePrincipalToken, error) {
|
||||
oauthConfig, err := adal.NewOAuthConfig(env.ActiveDirectoryEndpoint, config.TenantID)
|
||||
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 {
|
||||
return func(p autorest.Preparer) autorest.Preparer {
|
||||
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) {
|
||||
// RegisterNodeGroup registers node group in Azure Manager.
|
||||
func (m *AzureManager) RegisterNodeGroup(nodeGroup cloudprovider.NodeGroup) {
|
||||
m.cacheMutex.Lock()
|
||||
defer m.cacheMutex.Unlock()
|
||||
|
||||
m.scaleSets = append(m.scaleSets,
|
||||
&scaleSetInformation{
|
||||
config: scaleSet,
|
||||
basename: scaleSet.Name,
|
||||
})
|
||||
|
||||
m.nodeGroups = append(m.nodeGroups, nodeGroup)
|
||||
}
|
||||
|
||||
// GetScaleSetSize gets Scale Set size.
|
||||
func (m *AzureManager) GetScaleSetSize(asConfig *ScaleSet) (int64, error) {
|
||||
glog.V(5).Infof("Get scale set size: %v\n", asConfig)
|
||||
set, err := m.scaleSetClient.Get(m.resourceGroupName, asConfig.Name)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
func (m *AzureManager) nodeGroupRegisted(nodeGroup string) bool {
|
||||
for _, ng := range m.nodeGroups {
|
||||
if nodeGroup == ng.Id() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
glog.V(5).Infof("Returning scale set capacity: %d\n", *set.Sku.Capacity)
|
||||
return *set.Sku.Capacity, nil
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// 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{})
|
||||
// GetNodeGroupForInstance returns nodeGroup of the given Instance
|
||||
func (m *AzureManager) GetNodeGroupForInstance(instance *AzureRef) (cloudprovider.NodeGroup, error) {
|
||||
glog.V(5).Infof("Looking for node group for instance: %q", instance)
|
||||
|
||||
_, errChan := m.scaleSetClient.CreateOrUpdate(m.resourceGroupName, asConfig.Name, op, cancel)
|
||||
return <-errChan
|
||||
}
|
||||
|
||||
// GetScaleSetForInstance returns ScaleSetConfig of the given Instance
|
||||
func (m *AzureManager) GetScaleSetForInstance(instance *AzureRef) (*ScaleSet, error) {
|
||||
glog.V(5).Infof("Looking for scale set for instance: %v\n", instance)
|
||||
|
||||
glog.V(8).Infof("Cache BEFORE: %v\n", m.scaleSetCache)
|
||||
glog.V(8).Infof("Cache BEFORE: %v\n", m.nodeGroupsCache)
|
||||
|
||||
m.cacheMutex.Lock()
|
||||
defer m.cacheMutex.Unlock()
|
||||
if config, found := m.scaleSetCache[*instance]; found {
|
||||
return config, nil
|
||||
if nodeGroup, found := m.nodeGroupsCache[*instance]; found {
|
||||
return nodeGroup, 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 {
|
||||
return config, nil
|
||||
if nodeGroup, found := m.nodeGroupsCache[*instance]; found {
|
||||
return nodeGroup, nil
|
||||
}
|
||||
// instance does not belong to any configured Scale Set
|
||||
|
||||
// instance does not belong to any configured nodeGroup.
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// DeleteInstances deletes the given instances. All instances must be controlled by the same ASG.
|
||||
func (m *AzureManager) DeleteInstances(instances []*AzureRef) error {
|
||||
if len(instances) == 0 {
|
||||
return nil
|
||||
}
|
||||
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())
|
||||
}
|
||||
}
|
||||
// GetInstanceIDs gets instanceIDs for specified instances.
|
||||
func (m *AzureManager) GetInstanceIDs(instances []*AzureRef) []string {
|
||||
m.cacheMutex.Lock()
|
||||
defer m.cacheMutex.Unlock()
|
||||
|
||||
instanceIds := make([]string, len(instances))
|
||||
for i, instance := range instances {
|
||||
instanceIds[i] = m.scaleSetIdCache[instance.Name]
|
||||
instanceIds[i] = m.instanceIDsCache[instance.Name]
|
||||
}
|
||||
requiredIds := &compute.VirtualMachineScaleSetVMInstanceRequiredIDs{
|
||||
InstanceIds: &instanceIds,
|
||||
}
|
||||
cancel := make(chan struct{})
|
||||
_, errChan := m.scaleSetClient.DeleteInstances(m.resourceGroupName, commonAsg.Name, *requiredIds, cancel)
|
||||
return <-errChan
|
||||
|
||||
return instanceIds
|
||||
}
|
||||
|
||||
func (m *AzureManager) regenerateCache() error {
|
||||
newCache := make(map[AzureRef]*ScaleSet)
|
||||
newScaleSetIdCache := make(map[string]string)
|
||||
func (m *AzureManager) regenerateCache() (err error) {
|
||||
var newCache map[AzureRef]cloudprovider.NodeGroup
|
||||
var newInstanceIDsCache map[string]string
|
||||
|
||||
for _, sset := range m.scaleSets {
|
||||
glog.V(4).Infof("Regenerating Scale Set information for %s", sset.config.Name)
|
||||
scaleSet, err := m.scaleSetClient.Get(m.resourceGroupName, sset.config.Name)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to get scaleSet with name %s: %v", sset.config.Name, err)
|
||||
return err
|
||||
}
|
||||
sset.basename = *scaleSet.Name
|
||||
|
||||
result, err := m.scaleSetVmClient.List(m.resourceGroupName, sset.basename, "", "", "")
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to list vm for scaleSet %s: %v", sset.config.Name, err)
|
||||
return err
|
||||
}
|
||||
|
||||
for _, instance := range *result.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)
|
||||
ref := AzureRef{
|
||||
Name: name,
|
||||
}
|
||||
newCache[ref] = sset.config
|
||||
newScaleSetIdCache[name] = *instance.InstanceID
|
||||
}
|
||||
switch m.config.VMType {
|
||||
case vmTypeVMSS:
|
||||
newCache, newInstanceIDsCache, err = m.listScaleSets()
|
||||
case vmTypeStandard:
|
||||
newCache, newInstanceIDsCache, err = m.listAgentPools()
|
||||
default:
|
||||
err = fmt.Errorf("vmType %q not supported", m.config.VMType)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.scaleSetCache = newCache
|
||||
m.scaleSetIdCache = newScaleSetIdCache
|
||||
m.nodeGroupsCache = newCache
|
||||
m.instanceIDsCache = newInstanceIDsCache
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetScaleSetVms returns list of nodes for the given scale set.
|
||||
func (m *AzureManager) GetScaleSetVms(scaleSet *ScaleSet) ([]string, error) {
|
||||
instances, err := m.scaleSetVmClient.List(m.resourceGroupName, scaleSet.Name, "", "", "")
|
||||
|
||||
if err != nil {
|
||||
glog.V(4).Infof("Failed AS info request for %s: %v", scaleSet.Name, err)
|
||||
return []string{}, err
|
||||
func (m *AzureManager) getNodeGroupByID(id string) cloudprovider.NodeGroup {
|
||||
for _, ng := range m.nodeGroups {
|
||||
if id == ng.Id() {
|
||||
return ng
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
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).
|
||||
name := "azure://" + strings.ToLower(*instance.ID)
|
||||
vmID := "azure://" + strings.ToLower(*instance.VMID)
|
||||
ref := AzureRef{
|
||||
Name: name,
|
||||
}
|
||||
vmIDRef := AzureRef{
|
||||
Name: vmID,
|
||||
}
|
||||
scaleSets[ref] = sset
|
||||
scaleSets[vmIDRef] = sset
|
||||
instanceIDs[name] = *instance.InstanceID
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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