From 6ba008de99e084e8d168c17127b138b3db331ea1 Mon Sep 17 00:00:00 2001 From: Matt Boersma Date: Thu, 11 Oct 2018 09:58:12 -0600 Subject: [PATCH 01/29] Remove unsupported orchestrators and rename to "aks-engine" --- .circleci/config.yml | 20 +- .dockerignore | 8 +- .github/ISSUE_TEMPLATE.md | 4 +- .gitignore | 16 +- .prowci/README.md | 2 +- .prowci/config.yaml | 4 +- .prowci/plugins.yaml | 7 +- .vsts-ci.yaml | 12 +- CONTRIBUTING.md | 10 +- Dockerfile | 4 +- Gopkg.lock | 8 +- Gopkg.toml | 8 - Makefile | 16 +- README.md | 38 +- README_zh-CN.md | 9 +- cmd/cmd_suite_test.go | 2 +- cmd/dcos-upgrade.go | 239 ---- cmd/dcos-upgrade_test.go | 164 --- cmd/deploy.go | 61 +- cmd/deploy_test.go | 39 +- cmd/generate.go | 16 +- cmd/generate_test.go | 22 +- cmd/orchestrators.go | 4 +- cmd/root.go | 25 +- cmd/root_test.go | 2 +- cmd/scale.go | 92 +- .../{acsengine.mo => aksengine.mo} | Bin .../{acsengine.po => aksengine.po} | 28 +- cmd/upgrade.go | 21 +- cmd/version.go | 6 +- cmd/version_test.go | 8 +- docs/README.md | 9 +- ...delivery.md => aksengine-code-delivery.md} | 20 +- docs/{acsengine.md => aksengine.md} | 70 +- ...{acsengine.zh-CN.md => aksengine.zh-CN.md} | 60 +- docs/clusterdefinition.md | 42 +- docs/clusterdefinition.zh-CN.md | 12 +- docs/contributing-dcos.md | 210 --- docs/custom-vnet.md | 24 +- docs/dcos.md | 147 -- docs/design/proposed-template-refactor.md | 22 +- docs/developers.md | 58 +- docs/extensions.md | 51 +- docs/images/dcos-add-file-json.png | Bin 33068 -> 0 bytes docs/images/dcos-create-service-from-reg.png | Bin 35698 -> 0 bytes docs/images/dcos-create-service-json.png | Bin 33068 -> 0 bytes docs/images/dcos-create-service.png | Bin 35698 -> 0 bytes docs/images/dcos-docker-helloworld-logs.png | Bin 167804 -> 0 bytes docs/images/dcos-docker-helloworld-tasks.png | Bin 60025 -> 0 bytes docs/images/dcos-docker-helloworld1.png | Bin 44858 -> 0 bytes docs/images/dcos-docker-helloworld2.png | Bin 59188 -> 0 bytes docs/images/dcos-newapp-status.png | Bin 51120 -> 0 bytes .../dcos-running-service-from-reg-files.png | Bin 25864 -> 0 bytes docs/images/dcos-running-service-from-reg.png | Bin 14576 -> 0 bytes docs/images/dcos-simpleweb1.png | Bin 41493 -> 0 bytes docs/images/dcos-simpleweb2.png | Bin 55386 -> 0 bytes docs/images/dcos-simpleweb3.png | Bin 57957 -> 0 bytes docs/images/dcos-simpleweb4.png | Bin 37569 -> 0 bytes docs/images/dcos.png | Bin 19317 -> 0 bytes docs/images/dcosdashboard.png | Bin 47567 -> 0 bytes docs/images/dcosservices.png | Bin 52271 -> 0 bytes docs/images/swarm.png | Bin 15652 -> 0 bytes docs/images/swarmbrowser.png | Bin 22673 -> 0 bytes .../swarmmode-hybrid-docker-node-inspect.png | Bin 80331 -> 0 bytes .../swarmmode-hybrid-docker-node-ls.png | Bin 118922 -> 0 bytes docs/images/swarmmode-hybrid-linux-agents.png | Bin 38185 -> 0 bytes docs/images/swarmmode-hybrid-service-ls.png | Bin 57288 -> 0 bytes docs/images/swarmmode-hybrid-stack-deploy.png | Bin 58473 -> 0 bytes docs/kubernetes-day2-operations.md | 10 +- docs/kubernetes-large-clusters.md | 8 +- docs/kubernetes.md | 8 +- docs/kubernetes/aad.md | 6 +- docs/kubernetes/deploy.md | 42 +- docs/kubernetes/features.md | 30 +- docs/kubernetes/gpu.md | 2 +- docs/kubernetes/hybrid-environment.md | 16 +- docs/kubernetes/k8s-developers.md | 8 +- docs/kubernetes/monitoring.md | 4 +- docs/kubernetes/scale.md | 12 +- docs/kubernetes/troubleshooting.md | 6 +- docs/kubernetes/windows-details.md | 14 +- docs/kubernetes/windows.md | 72 +- docs/openshift.md | 11 - docs/openshift/OWNERS | 4 - docs/openshift/deploy.md | 161 --- docs/roadmap/planning-process.md | 8 +- docs/roadmap/releases.md | 32 +- docs/serviceprincipal.md | 2 +- docs/ssh.md | 2 +- docs/swarm.md | 85 -- docs/swarmmode-hybrid.md | 89 -- docs/swarmmode.md | 73 - examples/README.md | 15 +- examples/azure-cni/k8s-scale.sh | 2 +- examples/azure-cni/k8s-scaledown.json.env | 2 +- examples/azure-cni/k8s-scaleup.json.env | 2 +- .../azure-cni/k8s-vnet-scaledown.json.env | 4 +- examples/azure-cni/k8s-vnet-scaleup.json.env | 4 +- examples/customfiles/README.md | 4 +- examples/dcos-D2.json | 41 - examples/dcos-attributes/README.md | 26 - examples/dcos-attributes/dcos.json | 45 - .../dcos-attributes/images/dcosattributes.png | Bin 8450 -> 0 bytes examples/dcos-private-registry/README.md | 67 - examples/dcos-private-registry/dcos.json | 46 - examples/dcos-releases/README.md | 13 - examples/dcos-releases/dcos1.10.json | 42 - examples/dcos-releases/dcos1.8.json | 42 - examples/dcos-releases/dcos1.9.json | 42 - examples/dcos.json | 41 - examples/disks-managed/README.md | 4 +- .../dcos-preAttachedDisks-vmas.json | 39 - .../dcos-preAttachedDisks-vmas.json.env | 1 - .../dcos-preAttachedDisks-vmss.json | 33 - examples/disks-managed/dcos-vmas.json | 34 - examples/disks-managed/dcos-vmss.json | 40 - examples/disks-managed/dcos-vmss.json.env | 1 - .../swarm-preAttachedDisks-vmas.json | 47 - .../swarm-preAttachedDisks-vmss.json | 47 - examples/disks-managed/swarm-vmas.json | 47 - examples/disks-managed/swarm-vmss.json | 45 - examples/disks-managed/swarmmode-vmas.json | 47 - examples/disks-managed/swarmmode-vmss.json | 45 - examples/disks-storageaccount/README.md | 9 +- .../disks-storageaccount/dcos-master-sa.json | 42 - examples/disks-storageaccount/dcos.json | 49 - examples/disks-storageaccount/swarm.json | 49 - .../swarmmode-master-sa.json | 37 - examples/disks-storageaccount/swarmmode.json | 49 - examples/e2e-tests/openshift/definition.json | 72 - .../vmas/kubernetes-vmas-multimaster.json | 2 +- .../vmas/kubernetes-vmas.json | 2 +- .../vmss/kubernetes-vmss.json | 2 +- examples/extensions/dcos.json | 53 - examples/extensions/dcos.preprovision.json | 56 - .../extensions/prometheus-grafana-k8s.json | 2 +- .../extensions/swarmmode.preprovision.json | 51 - examples/k8s-upgrade/README.md | 20 +- examples/k8s-upgrade/k8s-upgrade.sh | 2 +- examples/k8s-upgrade/v1.7.7.json.env | 2 +- examples/k8s-upgrade/v1.7.9-hybrid.json.env | 2 +- examples/k8s-upgrade/v1.7.9-win.json.env | 2 +- examples/k8s-upgrade/v1.7.9.json.env | 2 +- examples/k8s-upgrade/v1.8.4.json.env | 2 +- examples/keyvault-params/README.md | 4 +- examples/keyvaultcerts/README.md | 10 +- examples/keyvaultcerts/dcos.json | 53 - examples/keyvaultcerts/swarm.json | 48 - examples/keyvaultcerts/swarmmode.json | 59 - examples/kubernetes-config/README.md | 2 +- examples/kubernetes-labels/README.md | 2 +- .../kubernetes-msi-userassigned/kube-vma.json | 2 +- .../kube-vmss.json | 2 +- examples/largeclusters/README.md | 12 +- examples/largeclusters/dcos-vmas.json | 97 -- examples/largeclusters/dcos.json | 85 -- examples/largeclusters/swarm-vmas.json | 97 -- examples/largeclusters/swarm.json | 85 -- examples/largeclusters/swarmmode-vmas.json | 97 -- examples/largeclusters/swarmmode.json | 85 -- examples/networkplugin/README.md | 2 +- examples/networkpolicy/README.md | 10 +- examples/openshift.json | 68 - examples/service-mesh/README.md | 2 +- examples/swarm.json | 36 - examples/swarmmode-D2.json | 36 - examples/swarmmode-rhel.json | 38 - examples/swarmmode.json | 36 - examples/v20160330/dcos.json | 35 - examples/v20160330/swarm.json | 35 - examples/v20160930/dcos.json | 35 - examples/v20170131/dcos.json | 35 - examples/v20170131/swarmmode.json | 36 - examples/v20170701/dcos.json | 41 - examples/v20170701/dockerce.json | 36 - examples/vnet/README.md | 10 +- examples/vnet/dcosvnet.json | 46 - examples/vnet/dcosvnet.json.env | 1 - .../vnet/kubernetesvnet-azure-cni.json.env | 2 +- .../vnet/kubernetesvnet-customnodesdns.json | 2 +- examples/vnet/kubernetesvnet.json.env | 4 +- examples/vnet/kubernetesvnet1.5.json.env | 4 +- examples/vnet/kubernetesvnet1.6.json.env | 4 +- examples/vnet/openshift-vnet.json | 72 - examples/vnet/swarmmodevnet.json | 45 - examples/vnet/swarmmodevnet.json.env | 1 - .../vnetarmtemplate/azuredeploy.dcos.json | 36 - .../vnetarmtemplate/azuredeploy.swarm.json | 36 - examples/vnet/vnetarmtemplate/deploy.ps1 | 2 - examples/windows/README.md | 6 +- examples/windows/dcos-win-version.json | 44 - examples/windows/dcos-win.json | 43 - examples/windows/dcos-winagent.json | 43 - examples/windows/swarmmode-hybrid.json | 47 - extensions/hello-world-dcos-windows/README.md | 46 - .../v1/hello-world-dcos.ps1 | 20 - .../v1/supported-orchestrators.json | 1 - .../v1/template-link.json | 33 - .../hello-world-dcos-windows/v1/template.json | 62 - extensions/hello-world-dcos/README.md | 46 - .../hello-world-dcos/v1/hello-world-dcos.sh | 16 - .../v1/supported-orchestrators.json | 1 - .../hello-world-dcos/v1/template-link.json | 33 - extensions/hello-world-dcos/v1/template.json | 62 - .../v1/supported-orchestrators.json | 2 +- .../v1/microsoft-oms-agent-k8s.sh | 2 +- extensions/prometheus-grafana-k8s/README.md | 4 +- .../v1/prometheus-grafana-k8s.sh | 4 +- extensions/vamp-dcos/README.md | 38 - .../vamp-dcos/v1/supported-orchestrators.json | 1 - extensions/vamp-dcos/v1/template-link.json | 33 - extensions/vamp-dcos/v1/template.json | 62 - extensions/vamp-dcos/v1/vamp-dcos.sh | 91 -- extensions/windows-patches/README.md | 4 +- labels.yaml | 8 +- .../{acsengine.po.lcl => aksengine.po.lcl} | 2 +- .../{acsengine.po.lcl => aksengine.po.lcl} | 2 +- .../{acsengine.po.lcl => aksengine.po.lcl} | 2 +- .../{acsengine.po.lcl => aksengine.po.lcl} | 2 +- .../{acsengine.po.lcl => aksengine.po.lcl} | 2 +- .../{acsengine.po.lcl => aksengine.po.lcl} | 2 +- .../{acsengine.po.lcl => aksengine.po.lcl} | 2 +- .../{acsengine.po.lcl => aksengine.po.lcl} | 2 +- .../{acsengine.po.lcl => aksengine.po.lcl} | 2 +- .../{acsengine.po.lcl => aksengine.po.lcl} | 2 +- .../{acsengine.po.lcl => aksengine.po.lcl} | 2 +- .../{acsengine.po.lcl => aksengine.po.lcl} | 2 +- .../{acsengine.po.lcl => aksengine.po.lcl} | 2 +- .../{acsengine.po.lcl => aksengine.po.lcl} | 2 +- .../{acsengine.po.lcl => aksengine.po.lcl} | 2 +- .../{acsengine.po.lcl => aksengine.po.lcl} | 2 +- .../{acsengine.po.lcl => aksengine.po.lcl} | 2 +- main.go | 2 +- makedev.ps1 | 2 +- packer/install-dependencies.sh | 2 +- parts/agentoutputs.t | 4 +- parts/dcos/bstrap/bootstrapcustomdata.yml | 87 -- parts/dcos/bstrap/bootstrapparams.t | 166 --- parts/dcos/bstrap/bootstrapprovision.sh | 34 - parts/dcos/bstrap/bootstrapresources.t | 177 --- parts/dcos/bstrap/bootstrapvars.t | 9 - parts/dcos/bstrap/dcos1.11.0.customdata.t | 99 -- parts/dcos/bstrap/dcos1.11.2.customdata.t | 87 -- parts/dcos/bstrap/dcosbase.t | 65 - parts/dcos/bstrap/dcosmasterresources.t | 357 ----- parts/dcos/bstrap/dcosmastervars.t | 141 -- parts/dcos/bstrap/dcosprovision.sh | 54 - parts/dcos/dcosWindowsAgentResourcesVmas.t | 294 ---- parts/dcos/dcosWindowsAgentResourcesVmss.t | 229 ---- parts/dcos/dcosWindowsProvision.ps1 | 214 --- parts/dcos/dcosagentresourcesvmas.t | 250 ---- parts/dcos/dcosagentresourcesvmss.t | 205 --- parts/dcos/dcosagentvars.t | 64 - parts/dcos/dcosbase.t | 65 - parts/dcos/dcoscustomdata110.t | 343 ----- parts/dcos/dcoscustomdata184.t | 371 ------ parts/dcos/dcoscustomdata187.t | 364 ----- parts/dcos/dcoscustomdata188.t | 364 ----- parts/dcos/dcoscustomdata190.t | 357 ----- parts/dcos/dcoscustomdata198.t | 357 ----- parts/dcos/dcosmasterresources.t | 423 ------ parts/dcos/dcosmastervars.t | 149 --- parts/dcos/dcosparams.t | 35 - parts/dcos/dcosprovision.sh | 49 - parts/dcos/dcosprovisionsource.sh | 58 - ...rnetesmasteraddons-omsagent-daemonset.yaml | 2 +- parts/k8s/health-monitor.sh | 2 +- parts/k8s/kubernetesagentresourcesvmas.t | 40 +- parts/k8s/kubernetesbase.t | 3 - parts/k8s/kubernetesmasterresources.t | 59 +- parts/k8s/kubernetesmasterresourcesvmss.t | 2 +- parts/k8s/kubernetesmastervars.t | 23 +- parts/k8s/kubernetesparams.t | 4 - parts/k8s/kuberneteswinagentresourcesvmas.t | 2 +- parts/k8s/kuberneteswindowssetup.ps1 | 8 +- parts/k8s/windowskubeletfunc.ps1 | 4 +- parts/masterparams.t | 4 +- parts/openshift/OWNERS | 4 - parts/openshift/infraresources.t | 157 --- .../release-3.9/openshiftmasterscript.sh | 161 --- .../release-3.9/openshiftnodescript.sh | 32 - .../unstable/openshiftmasterscript.sh | 197 --- .../openshift/unstable/openshiftnodescript.sh | 64 - .../Install-ContainerHost-And-Join-Swarm.ps1 | 214 --- parts/swarm/Join-SwarmMode-cluster.ps1 | 335 ----- parts/swarm/configure-swarm-cluster.sh | 294 ---- parts/swarm/configure-swarmmode-cluster.sh | 374 ------ parts/swarm/swarmagentresourcesvmas.t | 258 ---- parts/swarm/swarmagentresourcesvmss.t | 206 --- parts/swarm/swarmagentvars.t | 51 - parts/swarm/swarmbase.t | 50 - parts/swarm/swarmmasterresources.t | 287 ---- parts/swarm/swarmmastervars.t | 178 --- parts/swarm/swarmparams.t | 15 - parts/swarm/swarmwinagentresourcesvmas.t | 259 ---- parts/swarm/swarmwinagentresourcesvmss.t | 208 --- parts/windowsparams.t | 6 +- pkg/acsengine/doc.go | 2 - .../testdata/disks-managed/dcos-vmas.json | 47 - .../testdata/disks-managed/dcos-vmss.json | 47 - .../testdata/disks-managed/swarm-vmas.json | 47 - .../testdata/disks-managed/swarm-vmss.json | 47 - .../disks-managed/swarm-windows-vmas.json | 53 - .../disks-managed/swarm-windows-vmss.json | 53 - .../disks-managed/swarmmode-vmas.json | 47 - .../disks-managed/swarmmode-vmss.json | 47 - .../testdata/disks-storageaccount/dcos.json | 47 - .../testdata/disks-storageaccount/swarm.json | 47 - .../disks-storageaccount/swarmmode.json | 47 - pkg/acsengine/testdata/extensions/dcos.json | 53 - .../testdata/extensions/swarmmode.json | 78 -- .../testdata/key-vault-certs/dcos.json | 53 - .../testdata/key-vault-certs/swarm.json | 90 -- .../testdata/key-vault-certs/swarmmode.json | 63 - .../testdata/largeclusters/dcos-vmas.json | 103 -- .../testdata/largeclusters/dcos.json | 91 -- .../testdata/largeclusters/swarm.json | 91 -- .../testdata/largeclusters/swarmmode.json | 91 -- .../testdata/largeclusters/swarmmodevmas.json | 97 -- .../testdata/largeclusters/swarmvmas.json | 97 -- pkg/acsengine/testdata/location/dcos.json | 42 - pkg/acsengine/testdata/location/swarm.json | 42 - pkg/acsengine/testdata/simple/dcos.json | 41 - pkg/acsengine/testdata/simple/dcos1.10.0.json | 42 - pkg/acsengine/testdata/simple/dcos1.8.8.json | 42 - pkg/acsengine/testdata/simple/dcos1.9.0.json | 42 - pkg/acsengine/testdata/simple/swarm.json | 41 - pkg/acsengine/testdata/simple/swarmmode.json | 51 - .../simple/swarmmode_classicmode.json | 38 - pkg/acsengine/testdata/v20160330/dcos.json | 31 - .../testdata/v20160330/defaults.json | 28 - pkg/acsengine/testdata/v20160330/swarm.json | 35 - pkg/acsengine/testdata/v20160930/dcos.json | 31 - .../testdata/v20160930/defaults.json | 28 - pkg/acsengine/testdata/v20170131/dcos.json | 31 - .../testdata/v20170131/defaults.json | 28 - .../testdata/v20170131/swarmmode.json | 36 - pkg/acsengine/testdata/v20170701/dcos.json | 41 - .../testdata/v20170701/dockerce.json | 36 - pkg/acsengine/testdata/vnet/dcosvnet.json | 51 - .../testdata/vnet/swarmmodevnet.json | 45 - pkg/acsengine/testdata/vnet/swarmvnet.json | 45 - .../testdata/windows/swarm-vmas.json | 49 - pkg/acsengine/testdata/windows/swarm.json | 47 - .../testdata/windows/swarmWinAndLin.json | 53 - .../swarmmode-windows_classicmode.json | 43 - .../testdata/windows/swarmmodeWinAndLin.json | 58 - .../dcos_scale_template.json | 1142 ---------------- .../transformtestfiles/dcos_template.json | 1183 ----------------- pkg/api/addons.go | 4 +- pkg/api/agentPoolOnlyApi/v20170831/types.go | 2 +- .../agentPoolOnlyApi/v20170831/validate.go | 2 +- .../v20180331/apiloader_test.go | 10 +- .../agentPoolOnlyApi/v20180331/merge_test.go | 2 +- pkg/api/agentPoolOnlyApi/v20180331/types.go | 2 +- .../agentPoolOnlyApi/v20180331/validate.go | 4 +- .../v20180331/validate_test.go | 2 +- pkg/api/agentPoolOnlyApi/vlabs/types.go | 2 +- pkg/api/agentPoolOnlyApi/vlabs/validate.go | 2 +- pkg/api/apiloader.go | 81 +- pkg/api/apiloader_test.go | 33 +- pkg/api/azenvtypes.go | 56 - pkg/api/common/const.go | 73 - pkg/api/common/versions.go | 7 +- pkg/api/common/versions_test.go | 5 - pkg/api/const.go | 96 +- pkg/api/converterfromagentpoolonlyapi.go | 6 +- pkg/api/converterfromagentpoolonlyapi_test.go | 4 +- pkg/api/converterfromapi.go | 305 +---- pkg/api/converterfromosaapi.go | 68 - pkg/api/converterfromosaapi_test.go | 135 -- pkg/api/convertertoagentpoolonlyapi.go | 10 +- pkg/api/convertertoagentpoolonlyapi_test.go | 4 +- pkg/api/convertertoapi.go | 266 +--- pkg/api/convertertoapi_test.go | 109 +- pkg/api/convertertoosaapi.go | 74 -- pkg/api/convertertoosaapi_test.go | 16 - pkg/api/defaults-apiserver.go | 4 +- pkg/api/defaults-apiserver_test.go | 2 +- pkg/api/defaults-controller-manager.go | 2 +- pkg/api/defaults-controller-manager_test.go | 2 +- pkg/api/defaults-kubelet.go | 4 +- pkg/api/defaults-kubelet_test.go | 2 +- pkg/api/defaults-openshift-certs.go | 96 -- pkg/api/defaults.go | 70 +- pkg/api/defaults_test.go | 107 +- pkg/api/k8s_versions.go | 2 +- pkg/api/mocks.go | 2 +- pkg/api/orchestrators.go | 166 +-- pkg/api/orchestrators_test.go | 129 +- pkg/api/osa/vlabs/types.go | 133 -- pkg/api/osa/vlabs/types_test.go | 143 -- pkg/api/strictjson_test.go | 13 +- pkg/api/types.go | 115 +- pkg/api/types_test.go | 63 +- pkg/api/v20160330/const.go | 27 - pkg/api/v20160330/doc.go | 2 - pkg/api/v20160330/merge.go | 19 - pkg/api/v20160330/merge_test.go | 56 - pkg/api/v20160330/types.go | 270 ---- pkg/api/v20160330/types_test.go | 88 -- pkg/api/v20160330/validate.go | 142 -- pkg/api/v20160930/const.go | 6 - pkg/api/v20160930/types.go | 13 +- pkg/api/v20160930/types_test.go | 38 +- pkg/api/v20160930/validate.go | 12 +- pkg/api/v20170131/const.go | 8 - pkg/api/v20170131/types.go | 20 +- pkg/api/v20170131/types_test.go | 15 - pkg/api/v20170131/validate.go | 7 +- pkg/api/v20170701/const.go | 6 - pkg/api/v20170701/types.go | 13 +- pkg/api/v20170701/types_test.go | 26 +- pkg/api/v20170701/validate.go | 17 +- pkg/api/v20170930/const.go | 6 - pkg/api/v20170930/types.go | 2 +- pkg/api/v20170930/validate.go | 8 - pkg/api/vlabs/const.go | 8 - pkg/api/vlabs/types.go | 55 +- pkg/api/vlabs/types_test.go | 37 +- pkg/api/vlabs/validate.go | 148 +-- pkg/api/vlabs/validate_test.go | 622 +-------- pkg/armhelpers/azureclient.go | 29 +- pkg/armhelpers/azureclient_test.go | 2 +- pkg/armhelpers/deploymentError.go | 4 +- pkg/armhelpers/deploymentError_test.go | 15 +- pkg/armhelpers/interfaces.go | 12 +- pkg/armhelpers/mockclients.go | 63 +- pkg/armhelpers/storage.go | 2 +- pkg/armhelpers/storage_test.go | 2 +- pkg/armhelpers/utils/util.go | 2 +- pkg/armhelpers/utils/util_test.go | 4 +- pkg/{acsengine => engine}/artifacts.go | 8 +- pkg/{acsengine => engine}/const.go | 64 +- pkg/{acsengine => engine}/customfiles.go | 4 +- pkg/{acsengine => engine}/customfiles_test.go | 4 +- pkg/engine/doc.go | 2 + pkg/{acsengine => engine}/engine.go | 416 +----- pkg/{acsengine => engine}/engine_test.go | 42 +- pkg/{acsengine => engine}/fileloader.go | 2 +- pkg/{acsengine => engine}/output.go | 19 +- pkg/{acsengine => engine}/output_test.go | 8 +- pkg/{acsengine => engine}/params.go | 131 +- pkg/{acsengine => engine}/params_k8s.go | 11 +- pkg/{acsengine => engine}/params_k8s_test.go | 11 +- pkg/{acsengine => engine}/params_test.go | 6 +- .../template_generator.go | 272 +--- pkg/{acsengine => engine}/tenantid.go | 2 +- pkg/{acsengine => engine}/tenantid_test.go | 2 +- .../addons/kubernetes-custom-psp.json | 0 .../addons/kubernetes-kube-proxy.json | 0 .../testdata/addons/kubernetes.json | 0 .../agentPoolOnly/v20170831/agents.json | 0 .../agentPoolOnly/v20180331/agents.json | 0 .../agentsWithFullNetworkProfile.json | 0 .../agentsWithFullNetworkProfileV2.json | 0 .../agentsWithOnlyNetworkPlugin.json | 0 .../disks-managed/kubernetes-vmas.json | 0 .../disks-managed/kubernetes-vmss.json | 0 .../disks-storageaccount/kubernetes.json | 0 .../testdata/etcd-versions/kubernetes.json | 0 .../testdata/extensions/kubernetes.json | 2 +- .../testdata/key-vault-certs/kubernetes.json | 0 .../testdata/key-vault-params/kubernetes.json | 0 .../kubernetesversions/kubernetes1.7.9.json | 0 .../kubernetesversions/kubernetes1.8.2.json | 0 .../largeclusters/kubernetes-vmss.json | 0 .../testdata/largeclusters/kubernetes.json | 0 .../testdata/location/kubernetes.json | 0 pkg/{acsengine => engine}/testdata/rename.sh | 0 .../testdata/simple/kubernetes.json | 0 .../testdata/v20160930/kubernetes.json | 0 .../testdata/v20170131/kubernetes-win.json | 0 .../testdata/v20170131/kubernetes.json | 0 .../v20170701/kubernetes-default-version.json | 0 .../v20170701/kubernetes-keyvault-secret.json | 0 .../kubernetes-win-default-version.json | 0 .../testdata/v20170701/kubernetes.json | 0 .../testdata/vnet/kubernetesvnet.json | 0 .../testdata/windows/kubernetes-hybrid.json | 0 .../windows/kubernetes-kubernetesconfig.json | 0 .../testdata/windows/kubernetes-vmss.json | 0 .../testdata/windows/kubernetes.json | 0 .../transform/apimodel_merger.go | 0 .../transform/apimodel_merger_test.go | 0 pkg/{acsengine => engine}/transform/json.go | 2 +- .../transform/transform.go | 51 - .../transform/transform_test.go | 85 +- .../k8s_agent_upgrade_template.json | 4 +- .../k8s_master_upgrade_template.json | 8 +- .../k8s_scale_template.json | 8 +- .../transformtestfiles/k8s_template.json | 10 +- .../k8s_vnet_scale_template.json | 8 +- .../transformtestfiles/k8s_vnet_template.json | 10 +- pkg/{acsengine => engine}/types.go | 32 +- pkg/helpers/Get-AzureConstants.py | 31 +- pkg/helpers/azureconst.go | 200 --- pkg/helpers/filesaver.go | 2 +- pkg/helpers/helpers.go | 2 +- pkg/helpers/helpers_test.go | 2 +- pkg/i18n/README.md | 10 +- pkg/i18n/const.go | 2 +- .../{acsengine.mo => aksengine.mo} | Bin .../{acsengine.po => aksengine.po} | 4 +- pkg/openshift/OWNERS | 4 - pkg/openshift/certgen/release39/config.go | 113 -- .../certgen/release39/config_test.go | 90 -- pkg/openshift/certgen/release39/defaults.go | 63 - pkg/openshift/certgen/release39/doc.go | 4 - pkg/openshift/certgen/release39/files.go | 179 --- pkg/openshift/certgen/release39/kubeconfig.go | 288 ---- .../certgen/release39/templates/bindata.go | 560 -------- .../templates/master/etc/etcd/etcd.conf | 58 - .../master/etc/origin/master/htpasswd | 1 - .../etc/origin/master/master-config.yaml | 236 ---- .../master/etc/origin/master/scheduler.json | 88 -- .../etc/origin/master/session-secrets.yaml | 5 - .../templates/master/tmp/ansible/ansible.sh | 28 - .../ansible/azure-local-master-inventory.yml | 103 -- .../master/tmp/ansible/azure-ocp-deploy.yml | 62 - .../tmp/bootstrapconfigs/compute-config.yaml | 46 - .../tmp/bootstrapconfigs/infra-config.yaml | 45 - .../tmp/bootstrapconfigs/master-config.yaml | 46 - .../templates/node/etc/azure/azure.conf | 9 - .../node/etc/origin/node/node-dnsmasq.conf | 2 - .../node/etc/origin/node/resolv.conf | 1 - .../certgen/release39/templates/templates.go | 1 - pkg/openshift/certgen/release39/tls.go | 504 ------- pkg/openshift/certgen/unstable/config.go | 113 -- pkg/openshift/certgen/unstable/config_test.go | 90 -- pkg/openshift/certgen/unstable/defaults.go | 64 - pkg/openshift/certgen/unstable/doc.go | 4 - pkg/openshift/certgen/unstable/files.go | 179 --- pkg/openshift/certgen/unstable/kubeconfig.go | 288 ---- .../certgen/unstable/templates/bindata.go | 535 -------- .../templates/master/etc/etcd/etcd.conf | 58 - .../master/etc/origin/master/htpasswd | 1 - .../etc/origin/master/master-config.yaml | 236 ---- .../master/etc/origin/master/scheduler.json | 88 -- .../etc/origin/master/session-secrets.yaml | 5 - .../templates/master/tmp/ansible/ansible.sh | 28 - .../ansible/azure-local-master-inventory.yml | 97 -- .../master/tmp/ansible/azure-ocp-deploy.yml | 75 -- .../tmp/bootstrapconfigs/compute-config.yaml | 59 - .../tmp/bootstrapconfigs/infra-config.yaml | 59 - .../tmp/bootstrapconfigs/master-config.yaml | 59 - .../node/etc/origin/cloudprovider/azure.conf | 9 - .../node/etc/origin/node/resolv.conf | 1 - .../certgen/unstable/templates/templates.go | 1 - pkg/openshift/certgen/unstable/tls.go | 504 ------- pkg/openshift/doc.go | 3 - pkg/openshift/examples_test.go | 60 - pkg/openshift/filesystem/filesystem.go | 221 --- .../en_US/LC_MESSAGES/acsengine.mo | Bin .../en_US/LC_MESSAGES/acsengine.po | 0 pkg/operations/cordondrainvm.go | 4 +- pkg/operations/cordondrainvm_test.go | 26 +- pkg/operations/dcosupgrade/upgradecluster.go | 50 - pkg/operations/dcosupgrade/upgrader.go | 244 ---- pkg/operations/deletevm.go | 6 +- .../kubernetesupgrade/upgradeagentnode.go | 10 +- .../kubernetesupgrade/upgradecluster.go | 30 +- .../kubernetesupgrade/upgradecluster_test.go | 53 +- .../kubernetesupgrade/upgrademasternode.go | 10 +- pkg/operations/kubernetesupgrade/upgrader.go | 38 +- pkg/operations/scaledownagentpool.go | 4 +- pkg/operations/scaledownagentpool_test.go | 8 +- releases/Dockerfile.linux | 32 +- releases/README.Dockerfile.md | 34 +- scripts/build-windows-k8s.sh | 38 +- scripts/convert-lcg-lcl.sh | 6 +- scripts/devenv.ps1 | 8 +- scripts/devenv.sh | 8 +- scripts/ginkgo.coverage.sh | 2 +- scripts/update-enus-po.sh | 4 +- scripts/update-translation.sh | 4 +- scripts/validate-generated.sh | 5 +- scripts/validate-go.sh | 8 +- test.mk | 8 +- test/acse-conf/acse-feature-validation.json | 80 -- test/acse-conf/acse-pr-non-k8s.json | 12 - test/acse-conf/acse-regression-dcos.json | 24 - test/acse-conf/acse-regression.json | 61 - test/acse-conf/acse-svc-canary-dcos.json | 9 - test/acse-conf/acse-svc-canary-swarmmode.json | 9 - test/acse-conf/acse-svc-dcos.json | 124 -- test/acse-conf/acse-svc-swarmmode.json | 124 -- .../acs-engine-errors.json | 40 +- .../config/config.go | 2 +- .../config/config_test.go | 15 +- .../main.go | 24 +- .../metrics/metrics.go | 2 +- .../metrics/metrics_test.go | 0 .../promote/promote.go | 16 +- .../report/report.go | 2 +- .../report/report_test.go | 2 +- test/akse-conf/akse-feature-validation.json | 36 + test/akse-conf/akse-regression.json | 12 + .../akse-scale-vnet.json} | 0 .../akse-scale.json} | 0 .../akse-svc-canary-k8s-win.json} | 0 .../akse-svc-canary-k8s.json} | 0 .../akse-svc-k8s-win.json} | 0 .../akse-svc-k8s.json} | 0 .../akse-upgrade-lnx.json} | 0 .../akse-upgrade-win.json} | 0 ...csengine-ci.groovy => aksengine-ci.groovy} | 6 +- ...tures.groovy => aksengine-features.groovy} | 10 +- ...ne-scale.groovy => aksengine-scale.groovy} | 8 +- ...engine-svc.groovy => aksengine-svc.groovy} | 8 +- test/bootstrap/checkout-pr.sh | 4 +- .../dcos/marathon-slave-public.json | 46 - test/cluster-tests/dcos/marathon.json | 31 - test/cluster-tests/dcos/test.sh | 126 -- test/cluster-tests/swarm/test.sh | 43 - test/cluster-tests/swarmmode/test.sh | 81 -- test/common.sh | 2 +- test/e2e.sh | 2 +- test/e2e/azure/cli.go | 7 +- test/e2e/cleanup.sh | 2 +- test/e2e/config/config.go | 36 +- test/e2e/dcos-deployments.json | 20 - test/e2e/dcos/dcos.go | 365 ----- test/e2e/dcos/dcos_suite_test.go | 13 - test/e2e/dcos/dcos_test.go | 93 -- test/e2e/dcos/marathon.json | 57 - test/e2e/engine/cli.go | 16 +- test/e2e/engine/template.go | 71 +- test/e2e/kubernetes/config.go | 2 +- test/e2e/kubernetes/deployment/deployment.go | 4 +- test/e2e/kubernetes/hpa/hpa.go | 2 +- test/e2e/kubernetes/job/job.go | 4 +- test/e2e/kubernetes/kubernetes_test.go | 30 +- test/e2e/kubernetes/namespace/namespace.go | 2 +- .../kubernetes/networkpolicy/networkpolicy.go | 2 +- test/e2e/kubernetes/node/node.go | 2 +- .../persistentvolume/persistentvolume.go | 2 +- .../persistentvolumeclaims.go | 2 +- test/e2e/kubernetes/pod/pod.go | 4 +- test/e2e/kubernetes/service/service.go | 2 +- .../kubernetes/storageclass/storageclass.go | 2 +- test/e2e/openshift/OWNERS | 4 - test/e2e/openshift/node/node.go | 29 - test/e2e/openshift/openshift_suite_test.go | 13 - test/e2e/openshift/openshift_test.go | 173 --- test/e2e/openshift/util/util.go | 375 ------ test/e2e/remote/ssh.go | 2 +- test/e2e/runner.go | 33 +- test/e2e/runner/cli_provisioner.go | 54 +- test/e2e/runner/ginkgo.go | 8 +- test/e2e/swarm-deployments.json | 12 - test/e2e/swarmmode-deployments.json | 24 - test/i18n/i18ntestinput.go | 4 +- test/step.sh | 12 +- .../{acsengine.mo => aksengine.mo} | Bin .../{acsengine.po => aksengine.po} | 28 +- .../{acsengine.mo => aksengine.mo} | Bin .../{acsengine.po => aksengine.po} | 28 +- translations/en_US/LC_MESSAGES/aksengine.mo | Bin 0 -> 2658 bytes translations/en_US/LC_MESSAGES/aksengine.po | 132 ++ .../{acsengine.po.lcg => aksengine.po.lcg} | 2 +- .../{acsengine.po.lcl => aksengine.po.lcl} | 2 +- .../{acsengine.po.xml => aksengine.po.xml} | 32 +- .../{acsengine.mo => aksengine.mo} | Bin .../{acsengine.po => aksengine.po} | 28 +- .../{acsengine.mo => aksengine.mo} | Bin .../{acsengine.po => aksengine.po} | 28 +- .../{acsengine.mo => aksengine.mo} | Bin .../{acsengine.po => aksengine.po} | 28 +- .../{acsengine.mo => aksengine.mo} | Bin .../{acsengine.po => aksengine.po} | 28 +- .../{acsengine.mo => aksengine.mo} | Bin .../{acsengine.po => aksengine.po} | 28 +- .../{acsengine.mo => aksengine.mo} | Bin .../{acsengine.po => aksengine.po} | 28 +- .../{acsengine.mo => aksengine.mo} | Bin .../{acsengine.po => aksengine.po} | 28 +- .../{acsengine.mo => aksengine.mo} | Bin .../{acsengine.po => aksengine.po} | 28 +- .../{acsengine.mo => aksengine.mo} | Bin .../{acsengine.po => aksengine.po} | 28 +- .../{acsengine.mo => aksengine.mo} | Bin .../{acsengine.po => aksengine.po} | 28 +- .../{acsengine.mo => aksengine.mo} | Bin .../{acsengine.po => aksengine.po} | 28 +- .../{acsengine.mo => aksengine.mo} | Bin .../{acsengine.po => aksengine.po} | 28 +- .../{acsengine.mo => aksengine.mo} | Bin .../{acsengine.po => aksengine.po} | 28 +- .../{acsengine.mo => aksengine.mo} | Bin .../{acsengine.po => aksengine.po} | 28 +- .../{acsengine.mo => aksengine.mo} | Bin .../{acsengine.po => aksengine.po} | 28 +- vendor/golang.org/x/crypto/bcrypt/base64.go | 35 - vendor/golang.org/x/crypto/bcrypt/bcrypt.go | 295 ---- vendor/golang.org/x/crypto/blowfish/block.go | 159 --- vendor/golang.org/x/crypto/blowfish/cipher.go | 91 -- vendor/golang.org/x/crypto/blowfish/const.go | 199 --- versioning.mk | 6 +- 699 files changed, 1797 insertions(+), 33619 deletions(-) delete mode 100644 cmd/dcos-upgrade.go delete mode 100644 cmd/dcos-upgrade_test.go rename cmd/translations/en_US/LC_MESSAGES/{acsengine.mo => aksengine.mo} (100%) rename cmd/translations/en_US/LC_MESSAGES/{acsengine.po => aksengine.po} (87%) rename docs/{acsengine-code-delivery.md => aksengine-code-delivery.md} (67%) rename docs/{acsengine.md => aksengine.md} (68%) rename docs/{acsengine.zh-CN.md => aksengine.zh-CN.md} (74%) delete mode 100644 docs/contributing-dcos.md delete mode 100644 docs/dcos.md delete mode 100644 docs/images/dcos-add-file-json.png delete mode 100644 docs/images/dcos-create-service-from-reg.png delete mode 100644 docs/images/dcos-create-service-json.png delete mode 100644 docs/images/dcos-create-service.png delete mode 100644 docs/images/dcos-docker-helloworld-logs.png delete mode 100644 docs/images/dcos-docker-helloworld-tasks.png delete mode 100644 docs/images/dcos-docker-helloworld1.png delete mode 100644 docs/images/dcos-docker-helloworld2.png delete mode 100644 docs/images/dcos-newapp-status.png delete mode 100644 docs/images/dcos-running-service-from-reg-files.png delete mode 100644 docs/images/dcos-running-service-from-reg.png delete mode 100644 docs/images/dcos-simpleweb1.png delete mode 100644 docs/images/dcos-simpleweb2.png delete mode 100644 docs/images/dcos-simpleweb3.png delete mode 100644 docs/images/dcos-simpleweb4.png delete mode 100644 docs/images/dcos.png delete mode 100644 docs/images/dcosdashboard.png delete mode 100644 docs/images/dcosservices.png delete mode 100644 docs/images/swarm.png delete mode 100644 docs/images/swarmbrowser.png delete mode 100644 docs/images/swarmmode-hybrid-docker-node-inspect.png delete mode 100644 docs/images/swarmmode-hybrid-docker-node-ls.png delete mode 100644 docs/images/swarmmode-hybrid-linux-agents.png delete mode 100644 docs/images/swarmmode-hybrid-service-ls.png delete mode 100644 docs/images/swarmmode-hybrid-stack-deploy.png delete mode 100644 docs/openshift.md delete mode 100644 docs/openshift/OWNERS delete mode 100644 docs/openshift/deploy.md delete mode 100644 docs/swarm.md delete mode 100644 docs/swarmmode-hybrid.md delete mode 100644 docs/swarmmode.md delete mode 100644 examples/dcos-D2.json delete mode 100644 examples/dcos-attributes/README.md delete mode 100644 examples/dcos-attributes/dcos.json delete mode 100644 examples/dcos-attributes/images/dcosattributes.png delete mode 100644 examples/dcos-private-registry/README.md delete mode 100644 examples/dcos-private-registry/dcos.json delete mode 100644 examples/dcos-releases/README.md delete mode 100644 examples/dcos-releases/dcos1.10.json delete mode 100644 examples/dcos-releases/dcos1.8.json delete mode 100644 examples/dcos-releases/dcos1.9.json delete mode 100644 examples/dcos.json delete mode 100644 examples/disks-managed/dcos-preAttachedDisks-vmas.json delete mode 100644 examples/disks-managed/dcos-preAttachedDisks-vmas.json.env delete mode 100644 examples/disks-managed/dcos-preAttachedDisks-vmss.json delete mode 100644 examples/disks-managed/dcos-vmas.json delete mode 100644 examples/disks-managed/dcos-vmss.json delete mode 100644 examples/disks-managed/dcos-vmss.json.env delete mode 100644 examples/disks-managed/swarm-preAttachedDisks-vmas.json delete mode 100644 examples/disks-managed/swarm-preAttachedDisks-vmss.json delete mode 100644 examples/disks-managed/swarm-vmas.json delete mode 100644 examples/disks-managed/swarm-vmss.json delete mode 100644 examples/disks-managed/swarmmode-vmas.json delete mode 100644 examples/disks-managed/swarmmode-vmss.json delete mode 100644 examples/disks-storageaccount/dcos-master-sa.json delete mode 100644 examples/disks-storageaccount/dcos.json delete mode 100644 examples/disks-storageaccount/swarm.json delete mode 100644 examples/disks-storageaccount/swarmmode-master-sa.json delete mode 100644 examples/disks-storageaccount/swarmmode.json delete mode 100644 examples/e2e-tests/openshift/definition.json delete mode 100644 examples/extensions/dcos.json delete mode 100644 examples/extensions/dcos.preprovision.json delete mode 100644 examples/extensions/swarmmode.preprovision.json delete mode 100644 examples/keyvaultcerts/dcos.json delete mode 100644 examples/keyvaultcerts/swarm.json delete mode 100644 examples/keyvaultcerts/swarmmode.json delete mode 100644 examples/largeclusters/dcos-vmas.json delete mode 100644 examples/largeclusters/dcos.json delete mode 100644 examples/largeclusters/swarm-vmas.json delete mode 100644 examples/largeclusters/swarm.json delete mode 100644 examples/largeclusters/swarmmode-vmas.json delete mode 100644 examples/largeclusters/swarmmode.json delete mode 100644 examples/openshift.json delete mode 100644 examples/swarm.json delete mode 100644 examples/swarmmode-D2.json delete mode 100644 examples/swarmmode-rhel.json delete mode 100644 examples/swarmmode.json delete mode 100644 examples/v20160330/dcos.json delete mode 100644 examples/v20160330/swarm.json delete mode 100644 examples/v20160930/dcos.json delete mode 100644 examples/v20170131/dcos.json delete mode 100644 examples/v20170131/swarmmode.json delete mode 100644 examples/v20170701/dcos.json delete mode 100644 examples/v20170701/dockerce.json delete mode 100644 examples/vnet/dcosvnet.json delete mode 100644 examples/vnet/dcosvnet.json.env delete mode 100644 examples/vnet/openshift-vnet.json delete mode 100644 examples/vnet/swarmmodevnet.json delete mode 100644 examples/vnet/swarmmodevnet.json.env delete mode 100644 examples/vnet/vnetarmtemplate/azuredeploy.dcos.json delete mode 100644 examples/vnet/vnetarmtemplate/azuredeploy.swarm.json delete mode 100644 examples/windows/dcos-win-version.json delete mode 100644 examples/windows/dcos-win.json delete mode 100644 examples/windows/dcos-winagent.json delete mode 100644 examples/windows/swarmmode-hybrid.json delete mode 100644 extensions/hello-world-dcos-windows/README.md delete mode 100644 extensions/hello-world-dcos-windows/v1/hello-world-dcos.ps1 delete mode 100644 extensions/hello-world-dcos-windows/v1/supported-orchestrators.json delete mode 100644 extensions/hello-world-dcos-windows/v1/template-link.json delete mode 100644 extensions/hello-world-dcos-windows/v1/template.json delete mode 100644 extensions/hello-world-dcos/README.md delete mode 100644 extensions/hello-world-dcos/v1/hello-world-dcos.sh delete mode 100644 extensions/hello-world-dcos/v1/supported-orchestrators.json delete mode 100644 extensions/hello-world-dcos/v1/template-link.json delete mode 100644 extensions/hello-world-dcos/v1/template.json delete mode 100644 extensions/vamp-dcos/README.md delete mode 100644 extensions/vamp-dcos/v1/supported-orchestrators.json delete mode 100644 extensions/vamp-dcos/v1/template-link.json delete mode 100644 extensions/vamp-dcos/v1/template.json delete mode 100644 extensions/vamp-dcos/v1/vamp-dcos.sh rename loc/cs-CZ/{acsengine.po.lcl => aksengine.po.lcl} (96%) rename loc/de-DE/{acsengine.po.lcl => aksengine.po.lcl} (96%) rename loc/es-ES/{acsengine.po.lcl => aksengine.po.lcl} (96%) rename loc/fr-FR/{acsengine.po.lcl => aksengine.po.lcl} (96%) rename loc/hu-HU/{acsengine.po.lcl => aksengine.po.lcl} (96%) rename loc/it-IT/{acsengine.po.lcl => aksengine.po.lcl} (96%) rename loc/ja-JP/{acsengine.po.lcl => aksengine.po.lcl} (96%) rename loc/ko-KR/{acsengine.po.lcl => aksengine.po.lcl} (96%) rename loc/nl-NL/{acsengine.po.lcl => aksengine.po.lcl} (96%) rename loc/pl-PL/{acsengine.po.lcl => aksengine.po.lcl} (96%) rename loc/pt-BR/{acsengine.po.lcl => aksengine.po.lcl} (96%) rename loc/pt-PT/{acsengine.po.lcl => aksengine.po.lcl} (96%) rename loc/ru-RU/{acsengine.po.lcl => aksengine.po.lcl} (96%) rename loc/sv-SE/{acsengine.po.lcl => aksengine.po.lcl} (96%) rename loc/tr-TR/{acsengine.po.lcl => aksengine.po.lcl} (96%) rename loc/zh-CN/{acsengine.po.lcl => aksengine.po.lcl} (96%) rename loc/zh-TW/{acsengine.po.lcl => aksengine.po.lcl} (96%) delete mode 100644 parts/dcos/bstrap/bootstrapcustomdata.yml delete mode 100644 parts/dcos/bstrap/bootstrapparams.t delete mode 100644 parts/dcos/bstrap/bootstrapprovision.sh delete mode 100644 parts/dcos/bstrap/bootstrapresources.t delete mode 100644 parts/dcos/bstrap/bootstrapvars.t delete mode 100644 parts/dcos/bstrap/dcos1.11.0.customdata.t delete mode 100644 parts/dcos/bstrap/dcos1.11.2.customdata.t delete mode 100644 parts/dcos/bstrap/dcosbase.t delete mode 100644 parts/dcos/bstrap/dcosmasterresources.t delete mode 100644 parts/dcos/bstrap/dcosmastervars.t delete mode 100644 parts/dcos/bstrap/dcosprovision.sh delete mode 100644 parts/dcos/dcosWindowsAgentResourcesVmas.t delete mode 100644 parts/dcos/dcosWindowsAgentResourcesVmss.t delete mode 100644 parts/dcos/dcosWindowsProvision.ps1 delete mode 100644 parts/dcos/dcosagentresourcesvmas.t delete mode 100644 parts/dcos/dcosagentresourcesvmss.t delete mode 100644 parts/dcos/dcosagentvars.t delete mode 100644 parts/dcos/dcosbase.t delete mode 100644 parts/dcos/dcoscustomdata110.t delete mode 100644 parts/dcos/dcoscustomdata184.t delete mode 100644 parts/dcos/dcoscustomdata187.t delete mode 100644 parts/dcos/dcoscustomdata188.t delete mode 100644 parts/dcos/dcoscustomdata190.t delete mode 100644 parts/dcos/dcoscustomdata198.t delete mode 100644 parts/dcos/dcosmasterresources.t delete mode 100644 parts/dcos/dcosmastervars.t delete mode 100644 parts/dcos/dcosparams.t delete mode 100644 parts/dcos/dcosprovision.sh delete mode 100755 parts/dcos/dcosprovisionsource.sh delete mode 100644 parts/openshift/OWNERS delete mode 100644 parts/openshift/infraresources.t delete mode 100644 parts/openshift/release-3.9/openshiftmasterscript.sh delete mode 100644 parts/openshift/release-3.9/openshiftnodescript.sh delete mode 100644 parts/openshift/unstable/openshiftmasterscript.sh delete mode 100644 parts/openshift/unstable/openshiftnodescript.sh delete mode 100644 parts/swarm/Install-ContainerHost-And-Join-Swarm.ps1 delete mode 100644 parts/swarm/Join-SwarmMode-cluster.ps1 delete mode 100644 parts/swarm/configure-swarm-cluster.sh delete mode 100644 parts/swarm/configure-swarmmode-cluster.sh delete mode 100644 parts/swarm/swarmagentresourcesvmas.t delete mode 100644 parts/swarm/swarmagentresourcesvmss.t delete mode 100644 parts/swarm/swarmagentvars.t delete mode 100644 parts/swarm/swarmbase.t delete mode 100644 parts/swarm/swarmmasterresources.t delete mode 100644 parts/swarm/swarmmastervars.t delete mode 100644 parts/swarm/swarmparams.t delete mode 100644 parts/swarm/swarmwinagentresourcesvmas.t delete mode 100644 parts/swarm/swarmwinagentresourcesvmss.t delete mode 100644 pkg/acsengine/doc.go delete mode 100644 pkg/acsengine/testdata/disks-managed/dcos-vmas.json delete mode 100644 pkg/acsengine/testdata/disks-managed/dcos-vmss.json delete mode 100644 pkg/acsengine/testdata/disks-managed/swarm-vmas.json delete mode 100644 pkg/acsengine/testdata/disks-managed/swarm-vmss.json delete mode 100644 pkg/acsengine/testdata/disks-managed/swarm-windows-vmas.json delete mode 100644 pkg/acsengine/testdata/disks-managed/swarm-windows-vmss.json delete mode 100644 pkg/acsengine/testdata/disks-managed/swarmmode-vmas.json delete mode 100644 pkg/acsengine/testdata/disks-managed/swarmmode-vmss.json delete mode 100644 pkg/acsengine/testdata/disks-storageaccount/dcos.json delete mode 100644 pkg/acsengine/testdata/disks-storageaccount/swarm.json delete mode 100644 pkg/acsengine/testdata/disks-storageaccount/swarmmode.json delete mode 100644 pkg/acsengine/testdata/extensions/dcos.json delete mode 100644 pkg/acsengine/testdata/extensions/swarmmode.json delete mode 100644 pkg/acsengine/testdata/key-vault-certs/dcos.json delete mode 100644 pkg/acsengine/testdata/key-vault-certs/swarm.json delete mode 100644 pkg/acsengine/testdata/key-vault-certs/swarmmode.json delete mode 100644 pkg/acsengine/testdata/largeclusters/dcos-vmas.json delete mode 100644 pkg/acsengine/testdata/largeclusters/dcos.json delete mode 100644 pkg/acsengine/testdata/largeclusters/swarm.json delete mode 100644 pkg/acsengine/testdata/largeclusters/swarmmode.json delete mode 100644 pkg/acsengine/testdata/largeclusters/swarmmodevmas.json delete mode 100644 pkg/acsengine/testdata/largeclusters/swarmvmas.json delete mode 100644 pkg/acsengine/testdata/location/dcos.json delete mode 100644 pkg/acsengine/testdata/location/swarm.json delete mode 100644 pkg/acsengine/testdata/simple/dcos.json delete mode 100644 pkg/acsengine/testdata/simple/dcos1.10.0.json delete mode 100644 pkg/acsengine/testdata/simple/dcos1.8.8.json delete mode 100644 pkg/acsengine/testdata/simple/dcos1.9.0.json delete mode 100644 pkg/acsengine/testdata/simple/swarm.json delete mode 100644 pkg/acsengine/testdata/simple/swarmmode.json delete mode 100644 pkg/acsengine/testdata/simple/swarmmode_classicmode.json delete mode 100644 pkg/acsengine/testdata/v20160330/dcos.json delete mode 100644 pkg/acsengine/testdata/v20160330/defaults.json delete mode 100644 pkg/acsengine/testdata/v20160330/swarm.json delete mode 100644 pkg/acsengine/testdata/v20160930/dcos.json delete mode 100644 pkg/acsengine/testdata/v20160930/defaults.json delete mode 100644 pkg/acsengine/testdata/v20170131/dcos.json delete mode 100644 pkg/acsengine/testdata/v20170131/defaults.json delete mode 100644 pkg/acsengine/testdata/v20170131/swarmmode.json delete mode 100644 pkg/acsengine/testdata/v20170701/dcos.json delete mode 100644 pkg/acsengine/testdata/v20170701/dockerce.json delete mode 100644 pkg/acsengine/testdata/vnet/dcosvnet.json delete mode 100644 pkg/acsengine/testdata/vnet/swarmmodevnet.json delete mode 100644 pkg/acsengine/testdata/vnet/swarmvnet.json delete mode 100644 pkg/acsengine/testdata/windows/swarm-vmas.json delete mode 100644 pkg/acsengine/testdata/windows/swarm.json delete mode 100644 pkg/acsengine/testdata/windows/swarmWinAndLin.json delete mode 100644 pkg/acsengine/testdata/windows/swarmmode-windows_classicmode.json delete mode 100644 pkg/acsengine/testdata/windows/swarmmodeWinAndLin.json delete mode 100644 pkg/acsengine/transform/transformtestfiles/dcos_scale_template.json delete mode 100644 pkg/acsengine/transform/transformtestfiles/dcos_template.json delete mode 100644 pkg/api/converterfromosaapi.go delete mode 100644 pkg/api/converterfromosaapi_test.go delete mode 100644 pkg/api/convertertoosaapi.go delete mode 100644 pkg/api/convertertoosaapi_test.go delete mode 100644 pkg/api/defaults-openshift-certs.go delete mode 100644 pkg/api/osa/vlabs/types.go delete mode 100644 pkg/api/osa/vlabs/types_test.go delete mode 100644 pkg/api/v20160330/const.go delete mode 100644 pkg/api/v20160330/doc.go delete mode 100644 pkg/api/v20160330/merge.go delete mode 100644 pkg/api/v20160330/merge_test.go delete mode 100644 pkg/api/v20160330/types.go delete mode 100644 pkg/api/v20160330/types_test.go delete mode 100644 pkg/api/v20160330/validate.go rename pkg/{acsengine => engine}/artifacts.go (98%) rename pkg/{acsengine => engine}/const.go (73%) rename pkg/{acsengine => engine}/customfiles.go (96%) rename pkg/{acsengine => engine}/customfiles_test.go (97%) create mode 100644 pkg/engine/doc.go rename pkg/{acsengine => engine}/engine.go (67%) rename pkg/{acsengine => engine}/engine_test.go (93%) rename pkg/{acsengine => engine}/fileloader.go (94%) rename pkg/{acsengine => engine}/output.go (85%) rename pkg/{acsengine => engine}/output_test.go (95%) rename pkg/{acsengine => engine}/params.go (59%) rename pkg/{acsengine => engine}/params_k8s.go (98%) rename pkg/{acsengine => engine}/params_k8s_test.go (86%) rename pkg/{acsengine => engine}/params_test.go (92%) rename pkg/{acsengine => engine}/template_generator.go (67%) rename pkg/{acsengine => engine}/tenantid.go (99%) rename pkg/{acsengine => engine}/tenantid_test.go (99%) rename pkg/{acsengine => engine}/testdata/addons/kubernetes-custom-psp.json (100%) rename pkg/{acsengine => engine}/testdata/addons/kubernetes-kube-proxy.json (100%) rename pkg/{acsengine => engine}/testdata/addons/kubernetes.json (100%) rename pkg/{acsengine => engine}/testdata/agentPoolOnly/v20170831/agents.json (100%) rename pkg/{acsengine => engine}/testdata/agentPoolOnly/v20180331/agents.json (100%) rename pkg/{acsengine => engine}/testdata/agentPoolOnly/v20180331/agentsWithFullNetworkProfile.json (100%) rename pkg/{acsengine => engine}/testdata/agentPoolOnly/v20180331/agentsWithFullNetworkProfileV2.json (100%) rename pkg/{acsengine => engine}/testdata/agentPoolOnly/v20180331/agentsWithOnlyNetworkPlugin.json (100%) rename pkg/{acsengine => engine}/testdata/disks-managed/kubernetes-vmas.json (100%) rename pkg/{acsengine => engine}/testdata/disks-managed/kubernetes-vmss.json (100%) rename pkg/{acsengine => engine}/testdata/disks-storageaccount/kubernetes.json (100%) rename pkg/{acsengine => engine}/testdata/etcd-versions/kubernetes.json (100%) rename pkg/{acsengine => engine}/testdata/extensions/kubernetes.json (97%) rename pkg/{acsengine => engine}/testdata/key-vault-certs/kubernetes.json (100%) rename pkg/{acsengine => engine}/testdata/key-vault-params/kubernetes.json (100%) rename pkg/{acsengine => engine}/testdata/kubernetesversions/kubernetes1.7.9.json (100%) rename pkg/{acsengine => engine}/testdata/kubernetesversions/kubernetes1.8.2.json (100%) rename pkg/{acsengine => engine}/testdata/largeclusters/kubernetes-vmss.json (100%) rename pkg/{acsengine => engine}/testdata/largeclusters/kubernetes.json (100%) rename pkg/{acsengine => engine}/testdata/location/kubernetes.json (100%) rename pkg/{acsengine => engine}/testdata/rename.sh (100%) rename pkg/{acsengine => engine}/testdata/simple/kubernetes.json (100%) rename pkg/{acsengine => engine}/testdata/v20160930/kubernetes.json (100%) rename pkg/{acsengine => engine}/testdata/v20170131/kubernetes-win.json (100%) rename pkg/{acsengine => engine}/testdata/v20170131/kubernetes.json (100%) rename pkg/{acsengine => engine}/testdata/v20170701/kubernetes-default-version.json (100%) rename pkg/{acsengine => engine}/testdata/v20170701/kubernetes-keyvault-secret.json (100%) rename pkg/{acsengine => engine}/testdata/v20170701/kubernetes-win-default-version.json (100%) rename pkg/{acsengine => engine}/testdata/v20170701/kubernetes.json (100%) rename pkg/{acsengine => engine}/testdata/vnet/kubernetesvnet.json (100%) rename pkg/{acsengine => engine}/testdata/windows/kubernetes-hybrid.json (100%) rename pkg/{acsengine => engine}/testdata/windows/kubernetes-kubernetesconfig.json (100%) rename pkg/{acsengine => engine}/testdata/windows/kubernetes-vmss.json (100%) rename pkg/{acsengine => engine}/testdata/windows/kubernetes.json (100%) rename pkg/{acsengine => engine}/transform/apimodel_merger.go (100%) rename pkg/{acsengine => engine}/transform/apimodel_merger_test.go (100%) rename pkg/{acsengine => engine}/transform/json.go (98%) rename pkg/{acsengine => engine}/transform/transform.go (90%) rename pkg/{acsengine => engine}/transform/transform_test.go (64%) rename pkg/{acsengine => engine}/transform/transformtestfiles/k8s_agent_upgrade_template.json (99%) rename pkg/{acsengine => engine}/transform/transformtestfiles/k8s_master_upgrade_template.json (99%) rename pkg/{acsengine => engine}/transform/transformtestfiles/k8s_scale_template.json (99%) rename pkg/{acsengine => engine}/transform/transformtestfiles/k8s_template.json (99%) rename pkg/{acsengine => engine}/transform/transformtestfiles/k8s_vnet_scale_template.json (99%) rename pkg/{acsengine => engine}/transform/transformtestfiles/k8s_vnet_template.json (99%) rename pkg/{acsengine => engine}/types.go (61%) rename pkg/i18n/translations/en_US/LC_MESSAGES/{acsengine.mo => aksengine.mo} (100%) rename pkg/i18n/translations/en_US/LC_MESSAGES/{acsengine.po => aksengine.po} (93%) delete mode 100644 pkg/openshift/OWNERS delete mode 100644 pkg/openshift/certgen/release39/config.go delete mode 100644 pkg/openshift/certgen/release39/config_test.go delete mode 100644 pkg/openshift/certgen/release39/defaults.go delete mode 100644 pkg/openshift/certgen/release39/doc.go delete mode 100644 pkg/openshift/certgen/release39/files.go delete mode 100644 pkg/openshift/certgen/release39/kubeconfig.go delete mode 100644 pkg/openshift/certgen/release39/templates/bindata.go delete mode 100644 pkg/openshift/certgen/release39/templates/master/etc/etcd/etcd.conf delete mode 100644 pkg/openshift/certgen/release39/templates/master/etc/origin/master/htpasswd delete mode 100644 pkg/openshift/certgen/release39/templates/master/etc/origin/master/master-config.yaml delete mode 100644 pkg/openshift/certgen/release39/templates/master/etc/origin/master/scheduler.json delete mode 100644 pkg/openshift/certgen/release39/templates/master/etc/origin/master/session-secrets.yaml delete mode 100644 pkg/openshift/certgen/release39/templates/master/tmp/ansible/ansible.sh delete mode 100644 pkg/openshift/certgen/release39/templates/master/tmp/ansible/azure-local-master-inventory.yml delete mode 100644 pkg/openshift/certgen/release39/templates/master/tmp/ansible/azure-ocp-deploy.yml delete mode 100644 pkg/openshift/certgen/release39/templates/master/tmp/bootstrapconfigs/compute-config.yaml delete mode 100644 pkg/openshift/certgen/release39/templates/master/tmp/bootstrapconfigs/infra-config.yaml delete mode 100644 pkg/openshift/certgen/release39/templates/master/tmp/bootstrapconfigs/master-config.yaml delete mode 100644 pkg/openshift/certgen/release39/templates/node/etc/azure/azure.conf delete mode 100644 pkg/openshift/certgen/release39/templates/node/etc/origin/node/node-dnsmasq.conf delete mode 100644 pkg/openshift/certgen/release39/templates/node/etc/origin/node/resolv.conf delete mode 100644 pkg/openshift/certgen/release39/templates/templates.go delete mode 100644 pkg/openshift/certgen/release39/tls.go delete mode 100644 pkg/openshift/certgen/unstable/config.go delete mode 100644 pkg/openshift/certgen/unstable/config_test.go delete mode 100644 pkg/openshift/certgen/unstable/defaults.go delete mode 100644 pkg/openshift/certgen/unstable/doc.go delete mode 100644 pkg/openshift/certgen/unstable/files.go delete mode 100644 pkg/openshift/certgen/unstable/kubeconfig.go delete mode 100644 pkg/openshift/certgen/unstable/templates/bindata.go delete mode 100644 pkg/openshift/certgen/unstable/templates/master/etc/etcd/etcd.conf delete mode 100644 pkg/openshift/certgen/unstable/templates/master/etc/origin/master/htpasswd delete mode 100644 pkg/openshift/certgen/unstable/templates/master/etc/origin/master/master-config.yaml delete mode 100644 pkg/openshift/certgen/unstable/templates/master/etc/origin/master/scheduler.json delete mode 100644 pkg/openshift/certgen/unstable/templates/master/etc/origin/master/session-secrets.yaml delete mode 100644 pkg/openshift/certgen/unstable/templates/master/tmp/ansible/ansible.sh delete mode 100644 pkg/openshift/certgen/unstable/templates/master/tmp/ansible/azure-local-master-inventory.yml delete mode 100644 pkg/openshift/certgen/unstable/templates/master/tmp/ansible/azure-ocp-deploy.yml delete mode 100644 pkg/openshift/certgen/unstable/templates/master/tmp/bootstrapconfigs/compute-config.yaml delete mode 100644 pkg/openshift/certgen/unstable/templates/master/tmp/bootstrapconfigs/infra-config.yaml delete mode 100644 pkg/openshift/certgen/unstable/templates/master/tmp/bootstrapconfigs/master-config.yaml delete mode 100644 pkg/openshift/certgen/unstable/templates/node/etc/origin/cloudprovider/azure.conf delete mode 100644 pkg/openshift/certgen/unstable/templates/node/etc/origin/node/resolv.conf delete mode 100644 pkg/openshift/certgen/unstable/templates/templates.go delete mode 100644 pkg/openshift/certgen/unstable/tls.go delete mode 100644 pkg/openshift/doc.go delete mode 100644 pkg/openshift/examples_test.go delete mode 100644 pkg/openshift/filesystem/filesystem.go rename {translations => pkg/openshift/translations}/en_US/LC_MESSAGES/acsengine.mo (100%) rename {translations => pkg/openshift/translations}/en_US/LC_MESSAGES/acsengine.po (100%) delete mode 100644 pkg/operations/dcosupgrade/upgradecluster.go delete mode 100644 pkg/operations/dcosupgrade/upgrader.go delete mode 100644 test/acse-conf/acse-feature-validation.json delete mode 100644 test/acse-conf/acse-pr-non-k8s.json delete mode 100644 test/acse-conf/acse-regression-dcos.json delete mode 100644 test/acse-conf/acse-regression.json delete mode 100644 test/acse-conf/acse-svc-canary-dcos.json delete mode 100644 test/acse-conf/acse-svc-canary-swarmmode.json delete mode 100644 test/acse-conf/acse-svc-dcos.json delete mode 100644 test/acse-conf/acse-svc-swarmmode.json rename test/{acs-engine-test => aks-engine-test}/acs-engine-errors.json (80%) rename test/{acs-engine-test => aks-engine-test}/config/config.go (94%) rename test/{acs-engine-test => aks-engine-test}/config/config_test.go (58%) rename test/{acs-engine-test => aks-engine-test}/main.go (96%) rename test/{acs-engine-test => aks-engine-test}/metrics/metrics.go (95%) rename test/{acs-engine-test => aks-engine-test}/metrics/metrics_test.go (100%) rename test/{acs-engine-test => aks-engine-test}/promote/promote.go (92%) rename test/{acs-engine-test => aks-engine-test}/report/report.go (99%) rename test/{acs-engine-test => aks-engine-test}/report/report_test.go (94%) create mode 100644 test/akse-conf/akse-feature-validation.json create mode 100644 test/akse-conf/akse-regression.json rename test/{acse-conf/acse-scale-vnet.json => akse-conf/akse-scale-vnet.json} (100%) rename test/{acse-conf/acse-scale.json => akse-conf/akse-scale.json} (100%) rename test/{acse-conf/acse-svc-canary-k8s-win.json => akse-conf/akse-svc-canary-k8s-win.json} (100%) rename test/{acse-conf/acse-svc-canary-k8s.json => akse-conf/akse-svc-canary-k8s.json} (100%) rename test/{acse-conf/acse-svc-k8s-win.json => akse-conf/akse-svc-k8s-win.json} (100%) rename test/{acse-conf/acse-svc-k8s.json => akse-conf/akse-svc-k8s.json} (100%) rename test/{acse-conf/acse-upgrade-lnx.json => akse-conf/akse-upgrade-lnx.json} (100%) rename test/{acse-conf/acse-upgrade-win.json => akse-conf/akse-upgrade-win.json} (100%) rename test/{acsengine-ci.groovy => aksengine-ci.groovy} (95%) rename test/{acsengine-features.groovy => aksengine-features.groovy} (93%) rename test/{acsengine-scale.groovy => aksengine-scale.groovy} (96%) rename test/{acsengine-svc.groovy => aksengine-svc.groovy} (96%) delete mode 100644 test/cluster-tests/dcos/marathon-slave-public.json delete mode 100644 test/cluster-tests/dcos/marathon.json delete mode 100755 test/cluster-tests/dcos/test.sh delete mode 100755 test/cluster-tests/swarm/test.sh delete mode 100755 test/cluster-tests/swarmmode/test.sh delete mode 100644 test/e2e/dcos-deployments.json delete mode 100644 test/e2e/dcos/dcos.go delete mode 100644 test/e2e/dcos/dcos_suite_test.go delete mode 100644 test/e2e/dcos/dcos_test.go delete mode 100644 test/e2e/dcos/marathon.json delete mode 100644 test/e2e/openshift/OWNERS delete mode 100644 test/e2e/openshift/node/node.go delete mode 100644 test/e2e/openshift/openshift_suite_test.go delete mode 100644 test/e2e/openshift/openshift_test.go delete mode 100644 test/e2e/openshift/util/util.go delete mode 100644 test/e2e/swarm-deployments.json delete mode 100644 test/e2e/swarmmode-deployments.json rename translations/cs_CZ/LC_MESSAGES/{acsengine.mo => aksengine.mo} (100%) rename translations/cs_CZ/LC_MESSAGES/{acsengine.po => aksengine.po} (88%) rename translations/de_DE/LC_MESSAGES/{acsengine.mo => aksengine.mo} (100%) rename translations/de_DE/LC_MESSAGES/{acsengine.po => aksengine.po} (88%) create mode 100644 translations/en_US/LC_MESSAGES/aksengine.mo create mode 100644 translations/en_US/LC_MESSAGES/aksengine.po rename translations/en_US/LC_MESSAGES/{acsengine.po.lcg => aksengine.po.lcg} (98%) rename translations/en_US/LC_MESSAGES/en-US/lcl/{acsengine.po.lcl => aksengine.po.lcl} (99%) rename translations/en_US/LC_MESSAGES/en-US/metadata/{acsengine.po.xml => aksengine.po.xml} (80%) rename translations/es_ES/LC_MESSAGES/{acsengine.mo => aksengine.mo} (100%) rename translations/es_ES/LC_MESSAGES/{acsengine.po => aksengine.po} (88%) rename translations/fr_FR/LC_MESSAGES/{acsengine.mo => aksengine.mo} (100%) rename translations/fr_FR/LC_MESSAGES/{acsengine.po => aksengine.po} (88%) rename translations/hu_HU/LC_MESSAGES/{acsengine.mo => aksengine.mo} (100%) rename translations/hu_HU/LC_MESSAGES/{acsengine.po => aksengine.po} (88%) rename translations/it_IT/LC_MESSAGES/{acsengine.mo => aksengine.mo} (100%) rename translations/it_IT/LC_MESSAGES/{acsengine.po => aksengine.po} (88%) rename translations/ja_JP/LC_MESSAGES/{acsengine.mo => aksengine.mo} (100%) rename translations/ja_JP/LC_MESSAGES/{acsengine.po => aksengine.po} (89%) rename translations/ko_KR/LC_MESSAGES/{acsengine.mo => aksengine.mo} (100%) rename translations/ko_KR/LC_MESSAGES/{acsengine.po => aksengine.po} (88%) rename translations/nl_NL/LC_MESSAGES/{acsengine.mo => aksengine.mo} (100%) rename translations/nl_NL/LC_MESSAGES/{acsengine.po => aksengine.po} (88%) rename translations/pl_PL/LC_MESSAGES/{acsengine.mo => aksengine.mo} (100%) rename translations/pl_PL/LC_MESSAGES/{acsengine.po => aksengine.po} (88%) rename translations/pt_BR/LC_MESSAGES/{acsengine.mo => aksengine.mo} (100%) rename translations/pt_BR/LC_MESSAGES/{acsengine.po => aksengine.po} (88%) rename translations/pt_PT/LC_MESSAGES/{acsengine.mo => aksengine.mo} (100%) rename translations/pt_PT/LC_MESSAGES/{acsengine.po => aksengine.po} (88%) rename translations/ru_RU/LC_MESSAGES/{acsengine.mo => aksengine.mo} (100%) rename translations/ru_RU/LC_MESSAGES/{acsengine.po => aksengine.po} (89%) rename translations/sv_SE/LC_MESSAGES/{acsengine.mo => aksengine.mo} (100%) rename translations/sv_SE/LC_MESSAGES/{acsengine.po => aksengine.po} (88%) rename translations/tr_TR/LC_MESSAGES/{acsengine.mo => aksengine.mo} (100%) rename translations/tr_TR/LC_MESSAGES/{acsengine.po => aksengine.po} (88%) rename translations/zh_CN/LC_MESSAGES/{acsengine.mo => aksengine.mo} (100%) rename translations/zh_CN/LC_MESSAGES/{acsengine.po => aksengine.po} (87%) rename translations/zh_TW/LC_MESSAGES/{acsengine.mo => aksengine.mo} (100%) rename translations/zh_TW/LC_MESSAGES/{acsengine.po => aksengine.po} (87%) delete mode 100644 vendor/golang.org/x/crypto/bcrypt/base64.go delete mode 100644 vendor/golang.org/x/crypto/bcrypt/bcrypt.go delete mode 100644 vendor/golang.org/x/crypto/blowfish/block.go delete mode 100644 vendor/golang.org/x/crypto/blowfish/cipher.go delete mode 100644 vendor/golang.org/x/crypto/blowfish/const.go diff --git a/.circleci/config.yml b/.circleci/config.yml index bd4848dfd9..c365bfbc8b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,7 +1,7 @@ version: 2 defaults: &defaults - working_directory: /go/src/github.com/Azure/acs-engine + working_directory: /go/src/github.com/Azure/aks-engine docker: - image: quay.io/deis/go-dev:v1.17.2 environment: @@ -62,7 +62,7 @@ jobs: command: make test-kubernetes no_output_timeout: "30m" - store_artifacts: - path: /go/src/github.com/Azure/acs-engine/_logs + path: /go/src/github.com/Azure/aks-engine/_logs k8s-1.10-release-e2e: <<: *defaults steps: @@ -88,7 +88,7 @@ jobs: command: make test-kubernetes no_output_timeout: "30m" - store_artifacts: - path: /go/src/github.com/Azure/acs-engine/_logs + path: /go/src/github.com/Azure/aks-engine/_logs k8s-1.11-release-e2e: <<: *defaults steps: @@ -114,7 +114,7 @@ jobs: command: make test-kubernetes no_output_timeout: "30m" - store_artifacts: - path: /go/src/github.com/Azure/acs-engine/_logs + path: /go/src/github.com/Azure/aks-engine/_logs k8s-1.12-release-e2e: <<: *defaults steps: @@ -140,7 +140,7 @@ jobs: command: make test-kubernetes no_output_timeout: "30m" - store_artifacts: - path: /go/src/github.com/Azure/acs-engine/_logs + path: /go/src/github.com/Azure/aks-engine/_logs k8s-1.13-release-e2e: <<: *defaults steps: @@ -166,7 +166,7 @@ jobs: command: make test-kubernetes no_output_timeout: "30m" - store_artifacts: - path: /go/src/github.com/Azure/acs-engine/_logs + path: /go/src/github.com/Azure/aks-engine/_logs k8s-windows-1.10-release-e2e: <<: *defaults steps: @@ -189,7 +189,7 @@ jobs: command: make test-kubernetes no_output_timeout: "30m" - store_artifacts: - path: /go/src/github.com/Azure/acs-engine/_logs + path: /go/src/github.com/Azure/aks-engine/_logs k8s-windows-1.11-release-e2e: <<: *defaults steps: @@ -212,7 +212,7 @@ jobs: command: make test-kubernetes no_output_timeout: "30m" - store_artifacts: - path: /go/src/github.com/Azure/acs-engine/_logs + path: /go/src/github.com/Azure/aks-engine/_logs k8s-windows-1.12-release-e2e: <<: *defaults steps: @@ -235,7 +235,7 @@ jobs: command: make test-kubernetes no_output_timeout: "30m" - store_artifacts: - path: /go/src/github.com/Azure/acs-engine/_logs + path: /go/src/github.com/Azure/aks-engine/_logs k8s-windows-1.13-release-e2e: <<: *defaults steps: @@ -258,7 +258,7 @@ jobs: command: make test-kubernetes no_output_timeout: "30m" - store_artifacts: - path: /go/src/github.com/Azure/acs-engine/_logs + path: /go/src/github.com/Azure/aks-engine/_logs workflows: version: 2 build_and_test_pr: diff --git a/.dockerignore b/.dockerignore index 23de1aa0f1..62d978308e 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,7 +1,7 @@ -./acs-engine -./acs-engine.exe +./aks-engine +./aks-engine.exe ./_output -./test/acs-engine-test/acs-engine-test +./test/aks-engine-test/aks-engine-test ## autogenerated ./pkg/i18n/translations.go -./pkg/acsengine/templates.go +./pkg/engine/templates.go diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 27c82b99cd..8695314006 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -8,7 +8,7 @@ --- -**What version of acs-engine?**: +**What version of aks-engine?**: --- @@ -27,7 +27,7 @@ might close your issue. If we're wrong, PLEASE feel free to reopen it and explain why. --> -**Orchestrator and version (e.g. Kubernetes, DC/OS, Swarm)** +**Kubernetes version** **What happened**: diff --git a/.gitignore b/.gitignore index 493b640e0f..6350a0cb0e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -acs-engine.exe -acs-engine +aks-engine.exe +aks-engine debug _output/ _input/ @@ -7,7 +7,7 @@ _input/ .DS_Store test/user.env user.env -test/acs-engine-test/acs-engine-test +test/aks-engine-test/aks-engine-test .editorconfig _dist/ bin/ @@ -15,20 +15,18 @@ bin/ .coverprofile test/junit/ -test/acs-engine-test/acs-engine-test.exe +test/aks-engine-test/aks-engine-test.exe pkg/operations/junit.xml pkg/operations/kubernetesupgrade/junit.xml -pkg/acsengine/templates.go +pkg/engine/templates.go pkg/i18n/translations.go _logs/ -test/acs-engine-test/report/TestReport.json +test/aks-engine-test/report/TestReport.json *.swp # I have no idea why these get generated when I run the e2e test test/e2e/kubernetes/translations/ -test/e2e/openshift/translations/ -pkg/openshift/translations/ # test outputs cmd/_test_output @@ -41,4 +39,4 @@ packer/sp.json .vs # exclude vendor directory from gitignore -!/vendor/**/* \ No newline at end of file +!/vendor/**/* diff --git a/.prowci/README.md b/.prowci/README.md index ca8bf092b2..a84097b627 100644 --- a/.prowci/README.md +++ b/.prowci/README.md @@ -4,7 +4,7 @@ Prow is a CI system that offers various features such as rich Github automation, and running tests in Jenkins or on a Kubernetes cluster. You can read more about Prow in [upstream docs][0]. -## acs-engine setup +## aks-engine setup Prow is optimized to run as a Kubernetes application. There are some pre-installation steps that need to happen in a new Kubernetes cluster before deploying Prow. These diff --git a/.prowci/config.yaml b/.prowci/config.yaml index 8c13a953db..24f6a35ce7 100644 --- a/.prowci/config.yaml +++ b/.prowci/config.yaml @@ -3,10 +3,10 @@ log_level: debug tide: # target_url: http://ci-bot-aks-ingress.eastus.cloudapp.azure.com/tide.html merge_method: - Azure/acs-engine: squash + Azure/aks-engine: squash queries: - repos: - - Azure/acs-engine + - Azure/aks-engine labels: - lgtm - approved diff --git a/.prowci/plugins.yaml b/.prowci/plugins.yaml index 24fd4901e7..d7e5583512 100644 --- a/.prowci/plugins.yaml +++ b/.prowci/plugins.yaml @@ -1,6 +1,6 @@ approve: - repos: - - Azure/acs-engine + - Azure/aks-engine implicit_self_approve: true lgtm_acts_as_approve: true @@ -14,14 +14,11 @@ config_updater: label: additional_labels: - orchestrator/k8s - - orchestrator/openshift - - orchestrator/dcos - - orchestrator/swarm - DO-NOT-MERGE plugins: - Azure/acs-engine: + Azure/aks-engine: - approve - assign - cat diff --git a/.vsts-ci.yaml b/.vsts-ci.yaml index d2f405b628..1b7374a4b4 100644 --- a/.vsts-ci.yaml +++ b/.vsts-ci.yaml @@ -14,8 +14,8 @@ phases: steps: - script: | docker run --rm \ - -v ${PWD}:/go/src/github.com/Azure/acs-engine \ - -w /go/src/github.com/Azure/acs-engine \ + -v ${PWD}:/go/src/github.com/Azure/aks-engine \ + -w /go/src/github.com/Azure/aks-engine \ -e CLIENT_ID=${CLIENT_ID} \ -e CLIENT_SECRET="$(CLIENT_SECRET)" \ -e TENANT_ID=${TENANT_ID} \ @@ -33,8 +33,8 @@ phases: VHD_NAME="$(echo $OS_DISK_SAS | cut -d "/" -f 8 | cut -d "?" -f 1)" && \ printf "COPY ME ----> ${CLASSIC_BLOB}/${VHD_NAME}?" | tee -a vhd-sas && \ docker run --rm \ - -v ${PWD}:/go/src/github.com/Azure/acs-engine \ - -w /go/src/github.com/Azure/acs-engine \ + -v ${PWD}:/go/src/github.com/Azure/aks-engine \ + -w /go/src/github.com/Azure/aks-engine \ -e CLIENT_ID=${CLIENT_ID} \ -e CLIENT_SECRET="$(CLIENT_SECRET)" \ -e TENANT_ID=${TENANT_ID} \ @@ -46,8 +46,8 @@ phases: displayName: Copying resource to Classic Storage Account - script: | docker run --rm \ - -v ${PWD}:/go/src/github.com/Azure/acs-engine \ - -w /go/src/github.com/Azure/acs-engine \ + -v ${PWD}:/go/src/github.com/Azure/aks-engine \ + -w /go/src/github.com/Azure/aks-engine \ -e CLIENT_ID=${CLIENT_ID} \ -e CLIENT_SECRET="$(CLIENT_SECRET)" \ -e TENANT_ID=${TENANT_ID} \ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a060899f45..02d4770d9f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing Guidelines -The Microsoft acs-engine project accepts contributions via GitHub pull requests. This document outlines the process to help get your contribution accepted. +The Microsoft aks-engine project accepts contributions via GitHub pull requests. This document outlines the process to help get your contribution accepted. ## Contributor License Agreements @@ -18,8 +18,8 @@ signed the CLA can be accepted into the repository. This is an open source project and as such no formal support is available. However, like all good open source projects we do offer "best effort" support through github issues. GitHub issues: -- ACS-Engine: https://github.com/Azure/acs-engine/issues - file issues and PRs related to ACS-Engine -- ACS: https://github.com/Azure/acs/issues - file issues and PRs related to Azure Container Service +- AKS Engine: https://github.com/Azure/aks-engine/issues - file issues and PRs related to AKS Engine +- AKS: https://github.com/Azure/AKS/issues - file issues and PRs related to Azure Kubernetes Service Before opening a new issue or submitting a new pull request, it's helpful to search the project - it's likely that another user has already reported the issue you're facing, or it's a known issue that we're already aware of. @@ -33,11 +33,11 @@ specific upcoming bug or minor release, it would go into `2.2.1` or `2.3.0`. A milestone (and hence release) is considered done when all outstanding issues/PRs have been closed or moved to another milestone. ## Issues -Issues are used as the primary method for tracking anything to do with the acs-engine project. +Issues are used as the primary method for tracking anything to do with the aks-engine project. ### Issue Lifecycle The issue lifecycle is mainly driven by the core maintainers, but is good information for those -contributing to acs-engine. All issue types follow the same general lifecycle. Differences are noted below. +contributing to aks-engine. All issue types follow the same general lifecycle. Differences are noted below. 1. Issue creation 2. Triage - The maintainer in charge of triaging will apply the proper labels for the issue. This diff --git a/Dockerfile b/Dockerfile index ad00cb90f5..a441bee1b4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,10 +24,10 @@ RUN git clone https://github.com/akesterson/cmdarg.git /tmp/cmdarg \ RUN git clone https://github.com/akesterson/shunit.git /tmp/shunit \ && cd /tmp/shunit && make install && rm -rf /tmp/shunit -WORKDIR /gopath/src/github.com/Azure/acs-engine +WORKDIR /gopath/src/github.com/Azure/aks-engine # Cache vendor layer -ADD . /gopath/src/github.com/Azure/acs-engine/ +ADD . /gopath/src/github.com/Azure/aks-engine/ RUN make bootstrap # https://github.com/dotnet/core/blob/master/release-notes/download-archives/2.1.2-sdk-download.md diff --git a/Gopkg.lock b/Gopkg.lock index 19b186c4e7..a17741de4b 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -407,11 +407,9 @@ version = "v1.0.0" [[projects]] - digest = "1:97e7fb88da85370877f29da5e453b3c65a416deedf2bda6f43a707a0c50a8a14" + digest = "1:7fce84770ea0e3a0f0f7e83f9b1dfc9137a2dddc2cbfede697c2bba9a26ade32" name = "golang.org/x/crypto" packages = [ - "bcrypt", - "blowfish", "curve25519", "ed25519", "ed25519/internal/edwards25519", @@ -746,7 +744,6 @@ "github.com/alexcesaro/statsd", "github.com/blang/semver", "github.com/davecgh/go-spew/spew", - "github.com/ghodss/yaml", "github.com/go-bindata/go-bindata/go-bindata", "github.com/imdario/mergo", "github.com/influxdata/influxdb/client/v2", @@ -762,21 +759,18 @@ "github.com/sirupsen/logrus", "github.com/spf13/cobra", "github.com/spf13/pflag", - "golang.org/x/crypto/bcrypt", "golang.org/x/crypto/ssh", "golang.org/x/crypto/ssh/agent", "golang.org/x/sync/errgroup", "gopkg.in/fsnotify.v1", "gopkg.in/go-playground/validator.v9", "gopkg.in/ini.v1", - "gopkg.in/yaml.v2", "k8s.io/api/core/v1", "k8s.io/api/policy/v1beta1", "k8s.io/apimachinery/pkg/api/equality", "k8s.io/apimachinery/pkg/api/errors", "k8s.io/apimachinery/pkg/apis/meta/v1", "k8s.io/apimachinery/pkg/fields", - "k8s.io/apimachinery/pkg/util/errors", "k8s.io/apimachinery/pkg/util/wait", "k8s.io/client-go/kubernetes", "k8s.io/client-go/tools/clientcmd", diff --git a/Gopkg.toml b/Gopkg.toml index 9e3b0fd1ab..31ef8910a7 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -50,10 +50,6 @@ required = [ name = "github.com/blang/semver" version = "3.5.1" -[[constraint]] - name = "github.com/ghodss/yaml" - version = "1.0.0" - [[constraint]] name = "github.com/imdario/mergo" version = "0.3.5" @@ -94,10 +90,6 @@ required = [ name = "gopkg.in/go-playground/validator.v9" version = "9.4.0" -[[constraint]] - name = "gopkg.in/yaml.v2" - version = "2.0.0" - [[constraint]] name = "k8s.io/client-go" version = "v9.0.0" diff --git a/Makefile b/Makefile index c37e43a2dc..376f9fc57c 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ GO ?= go TAGS := LDFLAGS := BINDIR := $(CURDIR)/bin -BINARIES := acs-engine +BINARIES := aks-engine VERSION ?= $(shell git rev-parse HEAD) VERSION_SHORT ?= $(shell git rev-parse --short HEAD) GITTAG := $(shell git describe --exact-match --tags $(shell git log -n1 --pretty='%h') 2> /dev/null) @@ -24,7 +24,7 @@ ifeq ($(GITTAG),) GITTAG := $(VERSION_SHORT) endif -REPO_PATH := github.com/Azure/acs-engine +REPO_PATH := github.com/Azure/aks-engine DEV_ENV_IMAGE := quay.io/deis/go-dev:v1.17.2 DEV_ENV_WORK_DIR := /go/src/${REPO_PATH} DEV_ENV_OPTS := --rm -v ${CURDIR}:${DEV_ENV_WORK_DIR} -w ${DEV_ENV_WORK_DIR} ${DEV_ENV_VARS} @@ -58,22 +58,22 @@ generate: bootstrap .PHONY: generate-azure-constants generate-azure-constants: - python pkg/acsengine/Get-AzureConstants.py + python pkg/engine/Get-AzureConstants.py .PHONY: build build: generate GOBIN=$(BINDIR) $(GO) install $(GOFLAGS) -ldflags '$(LDFLAGS)' - cd test/acs-engine-test; go build $(GOFLAGS) + cd test/aks-engine-test; go build $(GOFLAGS) build-binary: generate - go build $(GOFLAGS) -v -ldflags "${LDFLAGS}" -o ${BINARY_DEST_DIR}/acs-engine . + go build $(GOFLAGS) -v -ldflags "${LDFLAGS}" -o ${BINARY_DEST_DIR}/aks-engine . # usage: make clean build-cross dist VERSION=v0.4.0 .PHONY: build-cross build-cross: build build-cross: LDFLAGS += -extldflags "-static" build-cross: - CGO_ENABLED=0 gox -output="_dist/acs-engine-${GITTAG}-{{.OS}}-{{.Arch}}/{{.Dir}}" -osarch='$(TARGETS)' $(GOFLAGS) -tags '$(TAGS)' -ldflags '$(LDFLAGS)' + CGO_ENABLED=0 gox -output="_dist/aks-engine-${GITTAG}-{{.OS}}-{{.Arch}}/{{.Dir}}" -osarch='$(TARGETS)' $(GOFLAGS) -tags '$(TAGS)' -ldflags '$(LDFLAGS)' .PHONY: build-windows-k8s build-windows-k8s: @@ -101,11 +101,11 @@ clean: GIT_BASEDIR = $(shell git rev-parse --show-toplevel 2>/dev/null) ifneq ($(GIT_BASEDIR),) - LDFLAGS += -X github.com/Azure/acs-engine/pkg/test.JUnitOutDir=${GIT_BASEDIR}/test/junit + LDFLAGS += -X github.com/Azure/aks-engine/pkg/test.JUnitOutDir=${GIT_BASEDIR}/test/junit endif test: generate - ginkgo -skipPackage test/e2e/dcos,test/e2e/kubernetes,test/e2e/openshift -failFast -r . + ginkgo -skipPackage test/e2e/kubernetes -failFast -r . .PHONY: test-style test-style: diff --git a/README.md b/README.md index 2f5561beab..29bb115d81 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,32 @@ -# Microsoft Azure Container Service Engine - Builds Docker Enabled Clusters +# Microsoft Azure Kubernetes Service Engine - Builds Kubernetes Clusters -[![Coverage Status](https://codecov.io/gh/Azure/acs-engine/branch/master/graph/badge.svg)](https://codecov.io/gh/Azure/acs-engine) -[![CircleCI](https://circleci.com/gh/Azure/acs-engine/tree/master.svg?style=svg)](https://circleci.com/gh/Azure/acs-engine/tree/master) -[![GoDoc](https://godoc.org/github.com/Azure/acs-engine?status.svg)](https://godoc.org/github.com/Azure/acs-engine) +[![Coverage Status](https://codecov.io/gh/Azure/aks-engine/branch/master/graph/badge.svg)](https://codecov.io/gh/Azure/aks-engine) +[![CircleCI](https://circleci.com/gh/Azure/aks-engine/tree/master.svg?style=svg)](https://circleci.com/gh/Azure/aks-engine/tree/master) +[![GoDoc](https://godoc.org/github.com/Azure/aks-engine?status.svg)](https://godoc.org/github.com/Azure/aks-engine) ## Overview -The Azure Container Service Engine (`acs-engine`) generates ARM (Azure Resource Manager) templates for Docker enabled clusters on Microsoft Azure with your choice of DC/OS, Kubernetes, OpenShift, Swarm Mode, or Swarm orchestrators. The input to the tool is a cluster definition. The cluster definition (or apimodel) is very similar to (in many cases the same as) the ARM template syntax used to deploy a Microsoft Azure Container Service cluster. +The Azure Kubernetes Service Engine (`aks-engine`) generates ARM (Azure Resource Manager) templates for Kubernetes clusters on Microsoft Azure. The input to the tool is a cluster definition. The cluster definition (or apimodel) is very similar to (in many cases the same as) the ARM template syntax used to deploy a Microsoft Azure Kubernetes Service cluster. -The cluster definition file enables you to customize your Docker enabled cluster in many ways including: +The cluster definition file enables you to customize your Kubernetes cluster in many ways, including: -* Choice of DC/OS, Kubernetes, OpenShift, Swarm Mode, or Swarm orchestrators -* Multiple agent pools where each agent pool can specify: - * Standard or premium VM Sizes, including GPU optimized VM sizes - * Node count - * Virtual Machine ScaleSets or Availability Sets - * Storage Account Disks or Managed Disks - * OS and distro +* Kubernetes version +* multiple agent pools where each agent pool can specify: + * standard or premium VM Sizes, including GPU optimized VM sizes + * Node count + * Virtual Machine ScaleSets or Availability Sets + * Storage Account Disks or Managed Disks + * OS and distro * Custom VNET * Extensions -More info, including a thorough walkthrough is [here](docs/acsengine.md). +More info, including a thorough walkthrough is [here](docs/aksengine.md). ## User guides -These guides show how to create your first deployment for each orchestrator: +These guides show how to create your first deployment: -* [DC/OS Walkthrough](docs/dcos.md) - shows how to create a DC/OS cluster on Azure * [Kubernetes Walkthrough](docs/kubernetes.md) - shows how to create a Linux or Windows Kubernetes cluster on Azure -* [OpenShift Walkthrough](docs/openshift.md) - shows how to create an OpenShift cluster on Azure -* [Swarm Mode Walkthrough](docs/swarmmode.md) - shows how to create a [Docker Swarm Mode](https://docs.docker.com/engine/swarm/) cluster on Azure -* [Standalone Swarm Walkthrough](docs/swarm.md) - shows how to create a [Docker Standalone Swarm](https://docs.docker.com/swarm/) cluster on Azure These guides cover more advanced features to try out after you have built your first cluster: @@ -44,7 +40,7 @@ These guides cover more advanced features to try out after you have built your f Follow the [developers guide](docs/developers.md) to set up your environment. -To build acs-engine, run `make build`. If you are developing with a working [Docker environment](https://docs.docker.com/engine), you can also run `make dev` (or `makedev.ps1` on Windows) first to start a Docker container and run `make build` inside the container. +To build aks-engine, run `make build`. If you are developing with a working [Docker environment](https://docs.docker.com/engine), you can also run `make dev` (or `makedev.ps1` on Windows) first to start a Docker container and run `make build` inside the container. Please follow these instructions before submitting a PR: @@ -65,7 +61,7 @@ $ vim examples/kubernetes.json # insert your preferred, unique DNS prefix # insert your SSH public key -$ ./acs-engine generate examples/kubernetes.json +$ ./aks-engine generate examples/kubernetes.json ``` This produces a new directory inside `_output/` that contains an ARM template for deploying Kubernetes into Azure. (In the case of Kubernetes, some additional needed assets are generated and placed in the output directory.) diff --git a/README_zh-CN.md b/README_zh-CN.md index 2e55797cfb..695fa37750 100644 --- a/README_zh-CN.md +++ b/README_zh-CN.md @@ -2,10 +2,10 @@ ## 概览 -微软容器服务引擎(`acs-engine`)用于将一个容器集群描述文件转化成一组ARM(Azure Resource Manager)模板,通过在Azure上部署这些模板,用户可以很方便地在Azure上建立一套基于Docker的容器服务集群。用户可以自由地选择集群编排引擎DC/OS, Kubernetes或者是Swarm/Swarm Mode。集群描述文件使用和ARM模板相同的语法,它们都可以用来部署Azure容器服务。 +微软容器服务引擎(`aks-engine`)用于将一个容器集群描述文件转化成一组ARM(Azure Resource Manager)模板,通过在Azure上部署这些模板,用户可以很方便地在Azure上建立一套基于Docker的容器服务集群。用户可以自由地选择集群编排引擎Kubernetes。集群描述文件使用和ARM模板相同的语法,它们都可以用来部署Azure容器服务。 集群描述文件提供了一下几个功能: -* 可以自由选择DC/OS, Kubernetes, Swarm Mode和Swarm等多种编排引擎 +* 可以自由选择Kubernetes等多种编排引擎 * 可以自由定制集群节点的规格,包括: * 虚机的规格 * 节点的数量 @@ -16,12 +16,9 @@ ## 演示链接 -* [ACS Engine](docs/acsengine.md) - 演示如何使用ACS引擎来生成基于Docker的容器集群 +* [AKS Engine](docs/aksengine.md) - 演示如何使用ACS引擎来生成基于Docker的容器集群 * [Cluster Definition](docs/clusterdefinition.md) - 详细介绍集群描述文件的格式 -* [DC/OS Walkthrough](docs/dcos.md) - 演示如何使用ACS引擎在Azure上创建DC/OS集群 * [Kubernetes Walkthrough](docs/kubernetes.md) - 演示如何使用ACS引擎在Azure上创建Kubernetes集群 -* [Swarm Walkthrough](docs/swarm.md) - 演示如何使用ACS引擎在Azure上创建Swarm集群 -* [Swarm Mode Walkthrough](docs/swarmmode.md) - 演示如何使用ACS引擎在Azure上创建Swarm Mode集群 * [Custom VNET](examples/vnet) - 演示如何在用户自定义VNET上创建容器集群 * [Attached Disks](examples/disks-storageaccount) - 演示如何在一个集群节点上创建4个磁盘 * [Managed Disks](examples/disks-managed) - 演示如何管理托管磁盘 diff --git a/cmd/cmd_suite_test.go b/cmd/cmd_suite_test.go index 2b0051f1bb..c3e9405372 100644 --- a/cmd/cmd_suite_test.go +++ b/cmd/cmd_suite_test.go @@ -3,7 +3,7 @@ package cmd_test import ( "testing" - . "github.com/Azure/acs-engine/pkg/test" + . "github.com/Azure/aks-engine/pkg/test" ) func TestCmd(t *testing.T) { diff --git a/cmd/dcos-upgrade.go b/cmd/dcos-upgrade.go deleted file mode 100644 index d8679d46b1..0000000000 --- a/cmd/dcos-upgrade.go +++ /dev/null @@ -1,239 +0,0 @@ -package cmd - -import ( - "context" - "encoding/json" - "io/ioutil" - "os" - "path" - "path/filepath" - - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/armhelpers" - "github.com/Azure/acs-engine/pkg/helpers" - "github.com/Azure/acs-engine/pkg/i18n" - "github.com/Azure/acs-engine/pkg/operations/dcosupgrade" - "github.com/leonelquinteros/gotext" - "github.com/pkg/errors" - - log "github.com/sirupsen/logrus" - "github.com/spf13/cobra" -) - -const ( - dcosUpgradeName = "dcos-upgrade" - dcosUpgradeShortDescription = "Upgrade an existing DC/OS cluster" - dcosUpgradeLongDescription = "Upgrade an existing DC/OS cluster" -) - -type dcosUpgradeCmd struct { - authArgs - - // user input - resourceGroupName string - deploymentDirectory string - upgradeVersion string - location string - sshPrivateKeyPath string - - // derived - containerService *api.ContainerService - apiVersion string - currentDcosVersion string - client armhelpers.ACSEngineClient - locale *gotext.Locale - nameSuffix string - sshPrivateKey []byte -} - -func newDcosUpgradeCmd() *cobra.Command { - uc := dcosUpgradeCmd{} - - dcosUpgradeCmd := &cobra.Command{ - Use: dcosUpgradeName, - Short: dcosUpgradeShortDescription, - Long: dcosUpgradeLongDescription, - RunE: func(cmd *cobra.Command, args []string) error { - return uc.run(cmd, args) - }, - } - - f := dcosUpgradeCmd.Flags() - f.StringVarP(&uc.location, "location", "l", "", "location the cluster is deployed in (required)") - f.StringVarP(&uc.resourceGroupName, "resource-group", "g", "", "the resource group where the cluster is deployed (required)") - f.StringVar(&uc.deploymentDirectory, "deployment-dir", "", "the location of the output from `generate` (required)") - f.StringVar(&uc.sshPrivateKeyPath, "ssh-private-key-path", "", "ssh private key path (default: /id_rsa)") - f.StringVar(&uc.upgradeVersion, "upgrade-version", "", "desired DC/OS version (required)") - addAuthFlags(&uc.authArgs, f) - - return dcosUpgradeCmd -} - -func (uc *dcosUpgradeCmd) validate(cmd *cobra.Command) error { - log.Infoln("validating...") - - var err error - - uc.locale, err = i18n.LoadTranslations() - if err != nil { - return errors.Wrap(err, "error loading translation files") - } - - if len(uc.resourceGroupName) == 0 { - cmd.Usage() - return errors.New("--resource-group must be specified") - } - - if len(uc.location) == 0 { - cmd.Usage() - return errors.New("--location must be specified") - } - uc.location = helpers.NormalizeAzureRegion(uc.location) - - if len(uc.upgradeVersion) == 0 { - cmd.Usage() - return errors.New("--upgrade-version must be specified") - } - - if len(uc.deploymentDirectory) == 0 { - cmd.Usage() - return errors.New("--deployment-dir must be specified") - } - - if len(uc.sshPrivateKeyPath) == 0 { - uc.sshPrivateKeyPath = filepath.Join(uc.deploymentDirectory, "id_rsa") - } - if uc.sshPrivateKey, err = ioutil.ReadFile(uc.sshPrivateKeyPath); err != nil { - cmd.Usage() - return errors.Wrap(err, "ssh-private-key-path must be specified") - } - - if err = uc.authArgs.validateAuthArgs(); err != nil { - return err - } - return nil -} - -func (uc *dcosUpgradeCmd) loadCluster(cmd *cobra.Command) error { - var err error - - if uc.client, err = uc.authArgs.getClient(); err != nil { - return errors.Wrap(err, "Failed to get client") - } - - ctx := context.Background() - _, err = uc.client.EnsureResourceGroup(ctx, uc.resourceGroupName, uc.location, nil) - if err != nil { - return errors.Wrap(err, "Error ensuring resource group") - } - - // load apimodel from the deployment directory - apiModelPath := path.Join(uc.deploymentDirectory, "apimodel.json") - - if _, err = os.Stat(apiModelPath); os.IsNotExist(err) { - return errors.Errorf("specified api model does not exist (%s)", apiModelPath) - } - - apiloader := &api.Apiloader{ - Translator: &i18n.Translator{ - Locale: uc.locale, - }, - } - uc.containerService, uc.apiVersion, err = apiloader.LoadContainerServiceFromFile(apiModelPath, true, true, nil) - if err != nil { - return errors.Wrap(err, "error parsing the api model") - } - uc.currentDcosVersion = uc.containerService.Properties.OrchestratorProfile.OrchestratorVersion - - if uc.currentDcosVersion == uc.upgradeVersion { - return errors.Errorf("already running DCOS %s", uc.upgradeVersion) - } - - if len(uc.containerService.Location) == 0 { - uc.containerService.Location = uc.location - } else if uc.containerService.Location != uc.location { - return errors.New("--location does not match api model location") - } - - // get available upgrades for container service - orchestratorInfo, err := api.GetOrchestratorVersionProfile(uc.containerService.Properties.OrchestratorProfile, false) - if err != nil { - return errors.Wrap(err, "error getting list of available upgrades") - } - // add the current version if upgrade has failed - orchestratorInfo.Upgrades = append(orchestratorInfo.Upgrades, &api.OrchestratorProfile{ - OrchestratorType: uc.containerService.Properties.OrchestratorProfile.OrchestratorType, - OrchestratorVersion: uc.containerService.Properties.OrchestratorProfile.OrchestratorVersion}) - - // validate desired upgrade version and set goal state - found := false - for _, up := range orchestratorInfo.Upgrades { - if up.OrchestratorVersion == uc.upgradeVersion { - uc.containerService.Properties.OrchestratorProfile.OrchestratorVersion = uc.upgradeVersion - found = true - break - } - } - if !found { - return errors.Errorf("upgrade to DCOS %s is not supported", uc.upgradeVersion) - } - - // Read name suffix to identify nodes in the resource group that belong - // to this cluster. - templatePath := path.Join(uc.deploymentDirectory, "azuredeploy.json") - contents, _ := ioutil.ReadFile(templatePath) - - var template interface{} - json.Unmarshal(contents, &template) - - templateMap := template.(map[string]interface{}) - templateParameters := templateMap["parameters"].(map[string]interface{}) - - nameSuffixParam := templateParameters["nameSuffix"].(map[string]interface{}) - uc.nameSuffix = nameSuffixParam["defaultValue"].(string) - log.Infof("Name suffix: %s", uc.nameSuffix) - return nil -} - -func (uc *dcosUpgradeCmd) run(cmd *cobra.Command, args []string) error { - err := uc.validate(cmd) - if err != nil { - log.Fatalf("error validating upgrade command: %v", err) - } - - err = uc.loadCluster(cmd) - if err != nil { - log.Fatalf("error loading existing cluster: %v", err) - } - - upgradeCluster := dcosupgrade.UpgradeCluster{ - Translator: &i18n.Translator{ - Locale: uc.locale, - }, - Logger: log.NewEntry(log.New()), - Client: uc.client, - } - - if err = upgradeCluster.UpgradeCluster(uc.authArgs.SubscriptionID, uc.resourceGroupName, uc.currentDcosVersion, - uc.containerService, uc.nameSuffix, uc.sshPrivateKey); err != nil { - log.Fatalf("Error upgrading cluster: %v", err) - } - - apiloader := &api.Apiloader{ - Translator: &i18n.Translator{ - Locale: uc.locale, - }, - } - b, err := apiloader.SerializeContainerService(uc.containerService, uc.apiVersion) - if err != nil { - return err - } - - f := helpers.FileSaver{ - Translator: &i18n.Translator{ - Locale: uc.locale, - }, - } - - return f.SaveFile(uc.deploymentDirectory, "apimodel.json", b) -} diff --git a/cmd/dcos-upgrade_test.go b/cmd/dcos-upgrade_test.go deleted file mode 100644 index 7d51815bbf..0000000000 --- a/cmd/dcos-upgrade_test.go +++ /dev/null @@ -1,164 +0,0 @@ -package cmd - -import ( - "io/ioutil" - "os" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var _ = Describe("the upgrade command", func() { - - It("should create a DCOS upgrade command", func() { - output := newDcosUpgradeCmd() - - Expect(output.Use).Should(Equal(dcosUpgradeName)) - Expect(output.Short).Should(Equal(dcosUpgradeShortDescription)) - Expect(output.Long).Should(Equal(dcosUpgradeLongDescription)) - Expect(output.Flags().Lookup("location")).NotTo(BeNil()) - Expect(output.Flags().Lookup("resource-group")).NotTo(BeNil()) - Expect(output.Flags().Lookup("deployment-dir")).NotTo(BeNil()) - Expect(output.Flags().Lookup("ssh-private-key-path")).NotTo(BeNil()) - Expect(output.Flags().Lookup("upgrade-version")).NotTo(BeNil()) - }) - - It("should validate DCOS upgrade command", func() { - r := &cobra.Command{} - privKey, err := ioutil.TempFile("", "id_rsa") - Expect(err).To(BeNil()) - defer os.Remove(privKey.Name()) - - cases := []struct { - uc *dcosUpgradeCmd - expectedErr error - hideLocalAzConfig bool - }{ - { - uc: &dcosUpgradeCmd{ - resourceGroupName: "", - deploymentDirectory: "_output/test", - upgradeVersion: "1.8.9", - location: "centralus", - sshPrivateKeyPath: privKey.Name(), - authArgs: authArgs{ - rawSubscriptionID: "99999999-0000-0000-0000-000000000000", - }, - }, - expectedErr: errors.New("--resource-group must be specified"), - }, - { - uc: &dcosUpgradeCmd{ - resourceGroupName: "test", - deploymentDirectory: "_output/test", - upgradeVersion: "1.8.9", - location: "", - sshPrivateKeyPath: privKey.Name(), - authArgs: authArgs{ - rawSubscriptionID: "99999999-0000-0000-0000-000000000000", - }, - }, - expectedErr: errors.New("--location must be specified"), - }, - { - uc: &dcosUpgradeCmd{ - resourceGroupName: "test", - deploymentDirectory: "_output/test", - upgradeVersion: "", - location: "southcentralus", - sshPrivateKeyPath: privKey.Name(), - authArgs: authArgs{ - rawSubscriptionID: "99999999-0000-0000-0000-000000000000", - }, - }, - expectedErr: errors.New("--upgrade-version must be specified"), - }, - { - uc: &dcosUpgradeCmd{ - resourceGroupName: "test", - deploymentDirectory: "", - upgradeVersion: "1.9.0", - location: "southcentralus", - sshPrivateKeyPath: privKey.Name(), - authArgs: authArgs{ - rawSubscriptionID: "99999999-0000-0000-0000-000000000000", - }, - }, - expectedErr: errors.New("--deployment-dir must be specified"), - }, - { - uc: &dcosUpgradeCmd{ - resourceGroupName: "test", - deploymentDirectory: "", - upgradeVersion: "1.9.0", - location: "southcentralus", - sshPrivateKeyPath: privKey.Name(), - authArgs: authArgs{ - rawSubscriptionID: "99999999-0000-0000-0000-000000000000", - }, - }, - expectedErr: errors.New("--deployment-dir must be specified"), - }, - { - uc: &dcosUpgradeCmd{ - resourceGroupName: "test", - deploymentDirectory: "_output/mydir", - upgradeVersion: "1.9.0", - location: "southcentralus", - sshPrivateKeyPath: privKey.Name(), - authArgs: authArgs{}, - }, - expectedErr: errors.New("--subscription-id is required (and must be a valid UUID)"), - hideLocalAzConfig: true, - }, - { - uc: &dcosUpgradeCmd{ - resourceGroupName: "test", - deploymentDirectory: "_output/mydir", - upgradeVersion: "1.9.0", - location: "southcentralus", - authArgs: authArgs{}, - }, - expectedErr: errors.New("ssh-private-key-path must be specified: open _output/mydir/id_rsa: no such file or directory"), - }, - { - uc: &dcosUpgradeCmd{ - resourceGroupName: "test", - deploymentDirectory: "_output/mydir", - upgradeVersion: "1.9.0", - location: "southcentralus", - sshPrivateKeyPath: privKey.Name(), - authArgs: authArgs{ - rawSubscriptionID: "99999999-0000-0000-0000-000000000000", - RawAzureEnvironment: "AzurePublicCloud", - AuthMethod: "device", - }, - }, - expectedErr: nil, - }, - } - - for _, c := range cases { - - if c.hideLocalAzConfig { - // Temporarily unset HOME env var so local subscription won't override test config - home := os.Getenv("HOME") - os.Setenv("HOME", "") - err = c.uc.validate(r) - os.Setenv("HOME", home) - } else { - err = c.uc.validate(r) - } - - if c.expectedErr != nil && err != nil { - Expect(err.Error()).To(Equal(c.expectedErr.Error())) - } else { - Expect(err).To(BeNil()) - Expect(c.expectedErr).To(BeNil()) - } - } - - }) -}) diff --git a/cmd/deploy.go b/cmd/deploy.go index 629c5327eb..ef43974efb 100644 --- a/cmd/deploy.go +++ b/cmd/deploy.go @@ -2,6 +2,7 @@ package cmd import ( "context" + "encoding/json" "fmt" "io/ioutil" "math/rand" @@ -12,35 +13,24 @@ import ( "strings" "time" - "github.com/leonelquinteros/gotext" - log "github.com/sirupsen/logrus" - "github.com/spf13/cobra" - - "encoding/json" - - "github.com/Azure/acs-engine/pkg/acsengine" - "github.com/Azure/acs-engine/pkg/acsengine/transform" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/armhelpers" - "github.com/Azure/acs-engine/pkg/helpers" - "github.com/Azure/acs-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/armhelpers" + "github.com/Azure/aks-engine/pkg/engine" + "github.com/Azure/aks-engine/pkg/engine/transform" + "github.com/Azure/aks-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/i18n" "github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac" "github.com/Azure/go-autorest/autorest/to" + "github.com/leonelquinteros/gotext" "github.com/pkg/errors" + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" ) const ( deployName = "deploy" deployShortDescription = "Deploy an Azure Resource Manager template" deployLongDescription = "Deploy an Azure Resource Manager template, parameters file and other assets for a cluster" - - // aadServicePrincipal is a hard-coded service principal which represents - // Azure Active Dirctory (see az ad sp list) - aadServicePrincipal = "00000002-0000-0000-c000-000000000000" - - // aadPermissionUserRead is the User.Read hard-coded permission on - // aadServicePrincipal (see az ad sp list) - aadPermissionUserRead = "311a71cc-e848-46a1-bdf8-97ff7156d8e6" ) type deployCmd struct { @@ -60,7 +50,7 @@ type deployCmd struct { apiVersion string locale *gotext.Locale - client armhelpers.ACSEngineClient + client armhelpers.AKSEngineClient resourceGroup string random *rand.Rand location string @@ -323,22 +313,6 @@ func autofillApimodel(dc *deployCmd) error { appURL := fmt.Sprintf("https://%s/", appName) var replyURLs *[]string var requiredResourceAccess *[]graphrbac.RequiredResourceAccess - if dc.containerService.Properties.OrchestratorProfile.OrchestratorType == api.OpenShift { - appName = fmt.Sprintf("%s.%s.cloudapp.azure.com", appName, dc.containerService.Properties.AzProfile.Location) - appURL = fmt.Sprintf("https://%s:8443/", appName) - replyURLs = to.StringSlicePtr([]string{fmt.Sprintf("https://%s:8443/oauth2callback/Azure%%20AD", appName)}) - requiredResourceAccess = &[]graphrbac.RequiredResourceAccess{ - { - ResourceAppID: to.StringPtr(aadServicePrincipal), - ResourceAccess: &[]graphrbac.ResourceAccess{ - { - ID: to.StringPtr(aadPermissionUserRead), - Type: to.StringPtr("Scope"), - }, - }, - }, - } - } applicationResp, servicePrincipalObjectID, secret, err := dc.client.CreateApp(ctx, appName, appURL, replyURLs, requiredResourceAccess) if err != nil { return errors.Wrap(err, "apimodel invalid: ServicePrincipalProfile was empty, and we failed to create valid credentials") @@ -394,13 +368,13 @@ func (dc *deployCmd) validateApimodel() (*api.ContainerService, string, error) { } func (dc *deployCmd) run() error { - ctx := acsengine.Context{ + ctx := engine.Context{ Translator: &i18n.Translator{ Locale: dc.locale, }, } - templateGenerator, err := acsengine.InitializeTemplateGenerator(ctx) + templateGenerator, err := engine.InitializeTemplateGenerator(ctx) if err != nil { log.Fatalf("failed to initialize template generator: %s", err.Error()) } @@ -411,7 +385,7 @@ func (dc *deployCmd) run() error { os.Exit(1) } - template, parameters, err := templateGenerator.GenerateTemplate(dc.containerService, acsengine.DefaultGeneratorCode, BuildTag) + template, parameters, err := templateGenerator.GenerateTemplate(dc.containerService, engine.DefaultGeneratorCode, BuildTag) if err != nil { log.Fatalf("error generating template %s: %s", dc.apimodelPath, err.Error()) os.Exit(1) @@ -425,7 +399,7 @@ func (dc *deployCmd) run() error { log.Fatalf("error pretty printing template parameters: %s \n", err.Error()) } - writer := &acsengine.ArtifactWriter{ + writer := &engine.ArtifactWriter{ Translator: &i18n.Translator{ Locale: dc.locale, }, @@ -466,10 +440,5 @@ func (dc *deployCmd) run() error { log.Fatalln(err) } - if dc.containerService.Properties.OrchestratorProfile.OrchestratorType == api.OpenShift { - // TODO: when the Azure client library is updated, read this from the template `masterFQDN` output - fmt.Printf("OpenShift web UI available at https://%s.%s.cloudapp.azure.com:8443/\n", dc.containerService.Properties.MasterProfile.DNSPrefix, dc.location) - } - return nil } diff --git a/cmd/deploy_test.go b/cmd/deploy_test.go index 09ffa641d3..67cbc6faa6 100644 --- a/cmd/deploy_test.go +++ b/cmd/deploy_test.go @@ -2,13 +2,12 @@ package cmd import ( "fmt" + "os" "strconv" "testing" - "os" - - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/armhelpers" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/armhelpers" "github.com/pkg/errors" "github.com/satori/go.uuid" "github.com/spf13/cobra" @@ -57,13 +56,13 @@ const ExampleAPIModelWithoutServicePrincipalProfile = `{ //mockAuthProvider implements AuthProvider and allows in particular to stub out getClient() type mockAuthProvider struct { - getClientMock armhelpers.ACSEngineClient + getClientMock armhelpers.AKSEngineClient *authArgs } -func (provider *mockAuthProvider) getClient() (armhelpers.ACSEngineClient, error) { +func (provider *mockAuthProvider) getClient() (armhelpers.AKSEngineClient, error) { if provider.getClientMock == nil { - return &armhelpers.MockACSEngineClient{}, nil + return &armhelpers.MockAKSEngineClient{}, nil } return provider.getClientMock, nil @@ -238,7 +237,7 @@ func TestAutoSufixWithDnsPrefixInApiModel(t *testing.T) { containerService: cs, apiVersion: ver, - client: &armhelpers.MockACSEngineClient{}, + client: &armhelpers.MockAKSEngineClient{}, authProvider: &mockAuthProvider{ authArgs: &authArgs{}, }, @@ -282,7 +281,7 @@ func TestAPIModelWithoutServicePrincipalProfileAndClientIdAndSecretInCmd(t *test containerService: cs, apiVersion: ver, - client: &armhelpers.MockACSEngineClient{}, + client: &armhelpers.MockAKSEngineClient{}, authProvider: &mockAuthProvider{ authArgs: &authArgs{}, }, @@ -335,7 +334,7 @@ func TestAPIModelWithEmptyServicePrincipalProfileAndClientIdAndSecretInCmd(t *te containerService: cs, apiVersion: ver, - client: &armhelpers.MockACSEngineClient{}, + client: &armhelpers.MockAKSEngineClient{}, authProvider: &mockAuthProvider{ authArgs: &authArgs{}, }, @@ -381,7 +380,7 @@ func TestAPIModelWithoutServicePrincipalProfileAndWithoutClientIdAndSecretInCmd( containerService: cs, apiVersion: ver, - client: &armhelpers.MockACSEngineClient{}, + client: &armhelpers.MockAKSEngineClient{}, authProvider: &mockAuthProvider{ authArgs: &authArgs{}, }, @@ -418,7 +417,7 @@ func TestAPIModelWithEmptyServicePrincipalProfileAndWithoutClientIdAndSecretInCm containerService: cs, apiVersion: ver, - client: &armhelpers.MockACSEngineClient{}, + client: &armhelpers.MockAKSEngineClient{}, authProvider: &mockAuthProvider{ authArgs: &authArgs{}, }, @@ -470,7 +469,7 @@ func testAutodeployCredentialHandling(t *testing.T, useManagedIdentity bool, cli containerService: cs, apiVersion: ver, - client: &armhelpers.MockACSEngineClient{}, + client: &armhelpers.MockAKSEngineClient{}, authProvider: &mockAuthProvider{ authArgs: &authArgs{}, }, @@ -504,14 +503,14 @@ func testAutodeployCredentialHandling(t *testing.T, useManagedIdentity bool, cli func TestDeployCmdMergeAPIModel(t *testing.T) { d := &deployCmd{} - d.apimodelPath = "../pkg/acsengine/testdata/simple/kubernetes.json" + d.apimodelPath = "../pkg/engine/testdata/simple/kubernetes.json" err := d.mergeAPIModel() if err != nil { t.Fatalf("unexpected error calling mergeAPIModel with no --set flag defined: %s", err.Error()) } d = &deployCmd{} - d.apimodelPath = "../pkg/acsengine/testdata/simple/kubernetes.json" + d.apimodelPath = "../pkg/engine/testdata/simple/kubernetes.json" d.set = []string{"masterProfile.count=3,linuxProfile.adminUsername=testuser"} err = d.mergeAPIModel() if err != nil { @@ -519,7 +518,7 @@ func TestDeployCmdMergeAPIModel(t *testing.T) { } d = &deployCmd{} - d.apimodelPath = "../pkg/acsengine/testdata/simple/kubernetes.json" + d.apimodelPath = "../pkg/engine/testdata/simple/kubernetes.json" d.set = []string{"masterProfile.count=3", "linuxProfile.adminUsername=testuser"} err = d.mergeAPIModel() if err != nil { @@ -527,7 +526,7 @@ func TestDeployCmdMergeAPIModel(t *testing.T) { } d = &deployCmd{} - d.apimodelPath = "../pkg/acsengine/testdata/simple/kubernetes.json" + d.apimodelPath = "../pkg/engine/testdata/simple/kubernetes.json" d.set = []string{"agentPoolProfiles[0].count=1"} err = d.mergeAPIModel() if err != nil { @@ -537,10 +536,10 @@ func TestDeployCmdMergeAPIModel(t *testing.T) { func TestDeployCmdRun(t *testing.T) { d := &deployCmd{ - client: &armhelpers.MockACSEngineClient{}, + client: &armhelpers.MockAKSEngineClient{}, authProvider: &mockAuthProvider{ authArgs: &authArgs{}, - getClientMock: &armhelpers.MockACSEngineClient{}, + getClientMock: &armhelpers.MockAKSEngineClient{}, }, apimodelPath: "./this/is/unused.json", outputDirectory: "_test_output", @@ -559,7 +558,7 @@ func TestDeployCmdRun(t *testing.T) { t.Fatalf("Invalid SubscriptionId in Test: %s", err) } - d.apimodelPath = "../pkg/acsengine/testdata/simple/kubernetes.json" + d.apimodelPath = "../pkg/engine/testdata/simple/kubernetes.json" d.getAuthArgs().SubscriptionID = fakeSubscriptionID d.getAuthArgs().rawSubscriptionID = fakeRawSubscriptionID diff --git a/cmd/generate.go b/cmd/generate.go index b3d3e8e15a..ad33977b4a 100644 --- a/cmd/generate.go +++ b/cmd/generate.go @@ -6,10 +6,10 @@ import ( "os" "path" - "github.com/Azure/acs-engine/pkg/acsengine" - "github.com/Azure/acs-engine/pkg/acsengine/transform" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/engine" + "github.com/Azure/aks-engine/pkg/engine/transform" + "github.com/Azure/aks-engine/pkg/i18n" "github.com/leonelquinteros/gotext" "github.com/pkg/errors" log "github.com/sirupsen/logrus" @@ -169,12 +169,12 @@ func (gc *generateCmd) loadAPIModel(cmd *cobra.Command, args []string) error { func (gc *generateCmd) run() error { log.Infoln(fmt.Sprintf("Generating assets into %s...", gc.outputDirectory)) - ctx := acsengine.Context{ + ctx := engine.Context{ Translator: &i18n.Translator{ Locale: gc.locale, }, } - templateGenerator, err := acsengine.InitializeTemplateGenerator(ctx) + templateGenerator, err := engine.InitializeTemplateGenerator(ctx) if err != nil { log.Fatalf("failed to initialize template generator: %s", err.Error()) } @@ -184,7 +184,7 @@ func (gc *generateCmd) run() error { log.Fatalf("error in SetPropertiesDefaults template %s: %s", gc.apimodelPath, err.Error()) os.Exit(1) } - template, parameters, err := templateGenerator.GenerateTemplate(gc.containerService, acsengine.DefaultGeneratorCode, BuildTag) + template, parameters, err := templateGenerator.GenerateTemplate(gc.containerService, engine.DefaultGeneratorCode, BuildTag) if err != nil { log.Fatalf("error generating template %s: %s", gc.apimodelPath, err.Error()) os.Exit(1) @@ -199,7 +199,7 @@ func (gc *generateCmd) run() error { } } - writer := &acsengine.ArtifactWriter{ + writer := &engine.ArtifactWriter{ Translator: &i18n.Translator{ Locale: gc.locale, }, diff --git a/cmd/generate_test.go b/cmd/generate_test.go index cc7b17e8d3..087384784d 100644 --- a/cmd/generate_test.go +++ b/cmd/generate_test.go @@ -25,7 +25,7 @@ func TestGenerateCmdValidate(t *testing.T) { r := &cobra.Command{} // validate cmd with 1 arg - err := g.validate(r, []string{"../pkg/acsengine/testdata/simple/kubernetes.json"}) + err := g.validate(r, []string{"../pkg/engine/testdata/simple/kubernetes.json"}) if err != nil { t.Fatalf("unexpected error validating 1 arg: %s", err.Error()) } @@ -42,7 +42,7 @@ func TestGenerateCmdValidate(t *testing.T) { g = &generateCmd{} // validate cmd with more than 1 arg - err = g.validate(r, []string{"../pkg/acsengine/testdata/simple/kubernetes.json", "arg1"}) + err = g.validate(r, []string{"../pkg/engine/testdata/simple/kubernetes.json", "arg1"}) t.Logf(err.Error()) if err == nil { t.Fatalf("expected error validating multiple args") @@ -52,14 +52,14 @@ func TestGenerateCmdValidate(t *testing.T) { func TestGenerateCmdMergeAPIModel(t *testing.T) { g := &generateCmd{} - g.apimodelPath = "../pkg/acsengine/testdata/simple/kubernetes.json" + g.apimodelPath = "../pkg/engine/testdata/simple/kubernetes.json" err := g.mergeAPIModel() if err != nil { t.Fatalf("unexpected error calling mergeAPIModel with no --set flag defined: %s", err.Error()) } g = &generateCmd{} - g.apimodelPath = "../pkg/acsengine/testdata/simple/kubernetes.json" + g.apimodelPath = "../pkg/engine/testdata/simple/kubernetes.json" g.set = []string{"masterProfile.count=3,linuxProfile.adminUsername=testuser"} err = g.mergeAPIModel() if err != nil { @@ -67,7 +67,7 @@ func TestGenerateCmdMergeAPIModel(t *testing.T) { } g = &generateCmd{} - g.apimodelPath = "../pkg/acsengine/testdata/simple/kubernetes.json" + g.apimodelPath = "../pkg/engine/testdata/simple/kubernetes.json" g.set = []string{"masterProfile.count=3", "linuxProfile.adminUsername=testuser"} err = g.mergeAPIModel() if err != nil { @@ -75,7 +75,7 @@ func TestGenerateCmdMergeAPIModel(t *testing.T) { } g = &generateCmd{} - g.apimodelPath = "../pkg/acsengine/testdata/simple/kubernetes.json" + g.apimodelPath = "../pkg/engine/testdata/simple/kubernetes.json" g.set = []string{"agentPoolProfiles[0].count=1"} err = g.mergeAPIModel() if err != nil { @@ -84,7 +84,7 @@ func TestGenerateCmdMergeAPIModel(t *testing.T) { // test with an ssh key that contains == sign g = &generateCmd{} - g.apimodelPath = "../pkg/acsengine/testdata/simple/kubernetes.json" + g.apimodelPath = "../pkg/engine/testdata/simple/kubernetes.json" g.set = []string{"linuxProfile.ssh.publicKeys[0].keyData=\"ssh-rsa AAAAB3NO8b9== azureuser@cluster.local\",servicePrincipalProfile.clientId=\"123a4321-c6eb-4b61-9d6f-7db123e14a7a\",servicePrincipalProfile.secret=\"=#msRock5!t=\""} err = g.mergeAPIModel() if err != nil { @@ -93,7 +93,7 @@ func TestGenerateCmdMergeAPIModel(t *testing.T) { // test with simple quote g = &generateCmd{} - g.apimodelPath = "../pkg/acsengine/testdata/simple/kubernetes.json" + g.apimodelPath = "../pkg/engine/testdata/simple/kubernetes.json" g.set = []string{"servicePrincipalProfile.secret='=MsR0ck5!t='"} err = g.mergeAPIModel() if err != nil { @@ -105,12 +105,12 @@ func TestGenerateCmdMLoadAPIModel(t *testing.T) { g := &generateCmd{} r := &cobra.Command{} - g.apimodelPath = "../pkg/acsengine/testdata/simple/kubernetes.json" + g.apimodelPath = "../pkg/engine/testdata/simple/kubernetes.json" g.set = []string{"agentPoolProfiles[0].count=1"} - g.validate(r, []string{"../pkg/acsengine/testdata/simple/kubernetes.json"}) + g.validate(r, []string{"../pkg/engine/testdata/simple/kubernetes.json"}) g.mergeAPIModel() - err := g.loadAPIModel(r, []string{"../pkg/acsengine/testdata/simple/kubernetes.json"}) + err := g.loadAPIModel(r, []string{"../pkg/engine/testdata/simple/kubernetes.json"}) if err != nil { t.Fatalf("unexpected error loading api model: %s", err.Error()) } diff --git a/cmd/orchestrators.go b/cmd/orchestrators.go index 4a5066a033..fe41f5150f 100644 --- a/cmd/orchestrators.go +++ b/cmd/orchestrators.go @@ -3,8 +3,8 @@ package cmd import ( "fmt" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/helpers" "github.com/spf13/cobra" ) diff --git a/cmd/root.go b/cmd/root.go index fe3490c7c3..7881146772 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -6,10 +6,10 @@ import ( "os" "path/filepath" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/api/vlabs" - "github.com/Azure/acs-engine/pkg/armhelpers" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/api/vlabs" + "github.com/Azure/aks-engine/pkg/armhelpers" + "github.com/Azure/aks-engine/pkg/helpers" "github.com/Azure/go-autorest/autorest/azure" "github.com/pkg/errors" uuid "github.com/satori/go.uuid" @@ -20,9 +20,9 @@ import ( ) const ( - rootName = "acs-engine" - rootShortDescription = "ACS-Engine deploys and manages container orchestrators in Azure" - rootLongDescription = "ACS-Engine deploys and manages Kubernetes, OpenShift, Swarm Mode, and DC/OS clusters in Azure" + rootName = "aks-engine" + rootShortDescription = "AKS-Engine deploys and manages Kubernetes clusters in Azure" + rootLongDescription = "AKS-Engine deploys and manages Kubernetes clusters in Azure" ) var ( @@ -30,7 +30,7 @@ var ( dumpDefaultModel bool ) -// NewRootCmd returns the root command for ACS-Engine. +// NewRootCmd returns the root command for AKS-Engine. func NewRootCmd() *cobra.Command { rootCmd := &cobra.Command{ Use: rootName, @@ -61,7 +61,6 @@ func NewRootCmd() *cobra.Command { rootCmd.AddCommand(newOrchestratorsCmd()) rootCmd.AddCommand(newUpgradeCmd()) rootCmd.AddCommand(newScaleCmd()) - rootCmd.AddCommand(newDcosUpgradeCmd()) rootCmd.AddCommand(getCompletionCmd(rootCmd)) return rootCmd @@ -87,7 +86,7 @@ func writeDefaultModel(out io.Writer) error { type authProvider interface { getAuthArgs() *authArgs - getClient() (armhelpers.ACSEngineClient, error) + getClient() (armhelpers.AKSEngineClient, error) } type authArgs struct { @@ -190,7 +189,7 @@ func getCloudSubFromAzConfig(cloud string, f *ini.File) (uuid.UUID, error) { return uuid.FromString(sub.String()) } -func (authArgs *authArgs) getClient() (armhelpers.ACSEngineClient, error) { +func (authArgs *authArgs) getClient() (armhelpers.AKSEngineClient, error) { var client *armhelpers.AzureClient env, err := azure.EnvironmentFromName(authArgs.RawAzureEnvironment) if err != nil { @@ -223,12 +222,12 @@ func getCompletionCmd(root *cobra.Command) *cobra.Command { Short: "Generates bash completion scripts", Long: `To load completion run - source <(acs-engine completion) + source <(aks-engine completion) To configure your bash shell to load completions for each session, add this to your bashrc # ~/.bashrc or ~/.profile - source <(acs-engine completion) + source <(aks-engine completion) `, Run: func(cmd *cobra.Command, args []string) { root.GenBashCompletion(os.Stdout) diff --git a/cmd/root_test.go b/cmd/root_test.go index f22fb9288a..f1186e7c6c 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -13,7 +13,7 @@ func TestNewRootCmd(t *testing.T) { if output.Use != rootName || output.Short != rootShortDescription || output.Long != rootLongDescription { t.Fatalf("root command should have use %s equal %s, short %s equal %s and long %s equal to %s", output.Use, rootName, output.Short, rootShortDescription, output.Long, rootLongDescription) } - expectedCommands := []*cobra.Command{getCompletionCmd(output), newDcosUpgradeCmd(), newDeployCmd(), newGenerateCmd(), newOrchestratorsCmd(), newScaleCmd(), newUpgradeCmd(), newVersionCmd()} + expectedCommands := []*cobra.Command{getCompletionCmd(output), newDeployCmd(), newGenerateCmd(), newOrchestratorsCmd(), newScaleCmd(), newUpgradeCmd(), newVersionCmd()} rc := output.Commands() for i, c := range expectedCommands { if rc[i].Use != c.Use { diff --git a/cmd/scale.go b/cmd/scale.go index e039a36ee8..c3f9b1d7b1 100644 --- a/cmd/scale.go +++ b/cmd/scale.go @@ -1,7 +1,6 @@ package cmd import ( - "bytes" "context" "encoding/json" "fmt" @@ -13,15 +12,14 @@ import ( "strings" "time" - "github.com/Azure/acs-engine/pkg/acsengine" - "github.com/Azure/acs-engine/pkg/acsengine/transform" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/armhelpers" - "github.com/Azure/acs-engine/pkg/armhelpers/utils" - "github.com/Azure/acs-engine/pkg/helpers" - "github.com/Azure/acs-engine/pkg/i18n" - "github.com/Azure/acs-engine/pkg/openshift/filesystem" - "github.com/Azure/acs-engine/pkg/operations" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/armhelpers" + "github.com/Azure/aks-engine/pkg/armhelpers/utils" + "github.com/Azure/aks-engine/pkg/engine" + "github.com/Azure/aks-engine/pkg/engine/transform" + "github.com/Azure/aks-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/operations" "github.com/leonelquinteros/gotext" "github.com/pkg/errors" log "github.com/sirupsen/logrus" @@ -44,7 +42,7 @@ type scaleCmd struct { apiVersion string apiModelPath string agentPool *api.AgentPoolProfile - client armhelpers.ACSEngineClient + client armhelpers.AKSEngineClient locale *gotext.Locale nameSuffix string agentPoolIndex int @@ -53,8 +51,8 @@ type scaleCmd struct { const ( scaleName = "scale" - scaleShortDescription = "Scale an existing Kubernetes or OpenShift cluster" - scaleLongDescription = "Scale an existing Kubernetes or OpenShift cluster by specifying increasing or decreasing the node count of an agentpool" + scaleShortDescription = "Scale an existing Kubernetes cluster" + scaleLongDescription = "Scale an existing Kubernetes cluster by specifying increasing or decreasing the node count of an agentpool" ) // NewScaleCmd run a command to upgrade a Kubernetes cluster @@ -209,7 +207,6 @@ func (sc *scaleCmd) run(cmd *cobra.Command, args []string) error { ctx, cancel := context.WithTimeout(context.Background(), armhelpers.DefaultARMOperationTimeout) defer cancel() - orchestratorInfo := sc.containerService.Properties.OrchestratorProfile var currentNodeCount, highestUsedIndex, index, winPoolIndex int winPoolIndex = -1 indexes := make([]int, 0) @@ -265,30 +262,13 @@ func (sc *scaleCmd) run(cmd *cobra.Command, args []string) error { vmsToDelete = append(vmsToDelete, indexToVM[index]) } - switch orchestratorInfo.OrchestratorType { - case api.Kubernetes: - kubeConfig, err := acsengine.GenerateKubeConfig(sc.containerService.Properties, sc.location) - if err != nil { - return errors.Wrap(err, "failed to generate kube config") - } - err = sc.drainNodes(kubeConfig, vmsToDelete) - if err != nil { - return errors.Wrap(err, "Got error while draining the nodes to be deleted") - } - case api.OpenShift: - bundle := bytes.NewReader(sc.containerService.Properties.OrchestratorProfile.OpenShiftConfig.ConfigBundles["master"]) - fs, err := filesystem.NewTGZReader(bundle) - if err != nil { - return errors.Wrap(err, "failed to read master bundle") - } - kubeConfig, err := fs.ReadFile("etc/origin/master/admin.kubeconfig") - if err != nil { - return errors.Wrap(err, "failed to read kube config") - } - err = sc.drainNodes(string(kubeConfig), vmsToDelete) - if err != nil { - return errors.Wrap(err, "Got error while draining the nodes to be deleted") - } + kubeConfig, err := engine.GenerateKubeConfig(sc.containerService.Properties, sc.location) + if err != nil { + return errors.Wrap(err, "failed to generate kube config") + } + err = sc.drainNodes(kubeConfig, vmsToDelete) + if err != nil { + return errors.Wrap(err, "Got error while draining the nodes to be deleted") } errList := operations.ScaleDownVMs(sc.client, sc.logger, sc.SubscriptionID.String(), sc.resourceGroupName, vmsToDelete...) @@ -333,12 +313,12 @@ func (sc *scaleCmd) run(cmd *cobra.Command, args []string) error { } } - translator := acsengine.Context{ + translator := engine.Context{ Translator: &i18n.Translator{ Locale: sc.locale, }, } - templateGenerator, err := acsengine.InitializeTemplateGenerator(translator) + templateGenerator, err := engine.InitializeTemplateGenerator(translator) if err != nil { return errors.Wrap(err, "failed to initialize template generator") } @@ -350,7 +330,7 @@ func (sc *scaleCmd) run(cmd *cobra.Command, args []string) error { log.Fatalf("error in SetPropertiesDefaults template %s: %s", sc.apiModelPath, err.Error()) os.Exit(1) } - template, parameters, err := templateGenerator.GenerateTemplate(sc.containerService, acsengine.DefaultGeneratorCode, BuildTag) + template, parameters, err := templateGenerator.GenerateTemplate(sc.containerService, engine.DefaultGeneratorCode, BuildTag) if err != nil { return errors.Wrapf(err, "error generating template %s", sc.apiModelPath) } @@ -384,30 +364,12 @@ func (sc *scaleCmd) run(cmd *cobra.Command, args []string) error { if winPoolIndex != -1 { templateJSON["variables"].(map[string]interface{})[sc.agentPool.Name+"Index"] = winPoolIndex } - switch orchestratorInfo.OrchestratorType { - case api.OpenShift: - err = transformer.NormalizeForOpenShiftVMASScalingUp(sc.logger, sc.agentPool.Name, templateJSON) - if err != nil { - return errors.Wrapf(err, "error tranforming the template for scaling template %s", sc.apiModelPath) - } - if sc.agentPool.IsAvailabilitySets() { - addValue(parametersJSON, fmt.Sprintf("%sOffset", sc.agentPool.Name), highestUsedIndex+1) - } - case api.Kubernetes: - err = transformer.NormalizeForK8sVMASScalingUp(sc.logger, templateJSON) - if err != nil { - return errors.Wrapf(err, "error tranforming the template for scaling template %s", sc.apiModelPath) - } - if sc.agentPool.IsAvailabilitySets() { - addValue(parametersJSON, fmt.Sprintf("%sOffset", sc.agentPool.Name), highestUsedIndex+1) - } - case api.Swarm: - case api.SwarmMode: - case api.DCOS: - if sc.agentPool.IsAvailabilitySets() { - return errors.Errorf("scaling isn't supported for orchestrator %q, with availability sets", orchestratorInfo.OrchestratorType) - } - transformer.NormalizeForVMSSScaling(sc.logger, templateJSON) + err = transformer.NormalizeForK8sVMASScalingUp(sc.logger, templateJSON) + if err != nil { + return errors.Wrapf(err, "error tranforming the template for scaling template %s", sc.apiModelPath) + } + if sc.agentPool.IsAvailabilitySets() { + addValue(parametersJSON, fmt.Sprintf("%sOffset", sc.agentPool.Name), highestUsedIndex+1) } random := rand.New(rand.NewSource(time.Now().UnixNano())) diff --git a/cmd/translations/en_US/LC_MESSAGES/acsengine.mo b/cmd/translations/en_US/LC_MESSAGES/aksengine.mo similarity index 100% rename from cmd/translations/en_US/LC_MESSAGES/acsengine.mo rename to cmd/translations/en_US/LC_MESSAGES/aksengine.mo diff --git a/cmd/translations/en_US/LC_MESSAGES/acsengine.po b/cmd/translations/en_US/LC_MESSAGES/aksengine.po similarity index 87% rename from cmd/translations/en_US/LC_MESSAGES/acsengine.po rename to cmd/translations/en_US/LC_MESSAGES/aksengine.po index d6b886a6d3..cabe086eb5 100644 --- a/cmd/translations/en_US/LC_MESSAGES/acsengine.po +++ b/cmd/translations/en_US/LC_MESSAGES/aksengine.po @@ -1,11 +1,11 @@ -# English translations for acs-engine package. +# English translations for aks-engine package. # Copyright (C) 2017 -# This file is distributed under the same license as the acs-engine package. +# This file is distributed under the same license as the aks-engine package. # Jiangtian Li , 2017. # msgid "" msgstr "" -"Project-Id-Version: acsengine\n" +"Project-Id-Version: aksengine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-25 00:04+0000\n" "PO-Revision-Date: 2017-07-24 17:23-0700\n" @@ -18,7 +18,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.0.3\n" -#: pkg/acsengine/engine.go:239 +#: pkg/engine/engine.go:239 #, c-format msgid "Error reading file %s, Error: %s" msgstr "Error reading file %s, Error: %s" @@ -28,12 +28,12 @@ msgstr "Error reading file %s, Error: %s" msgid "Error while querying ARM for resources: %+v" msgstr "Error while querying ARM for resources: %+v" -#: pkg/acsengine/transform.go:99 +#: pkg/engine/transform.go:99 #, c-format msgid "Found 2 resources with type %s in the template. There should only be 1" msgstr "Found 2 resources with type %s in the template. There should only be 1" -#: pkg/acsengine/transform.go:122 +#: pkg/engine/transform.go:122 #, c-format msgid "Found no resources with type %s in the template. There should have been 1" msgstr "Found no resources with type %s in the template. There should have been 1" @@ -53,12 +53,12 @@ msgstr "Upgrade to Kubernetes 1.6.2 is not supported from version: %s" msgid "Upgrade to Kubernetes version: %s is not supported from version: %s" msgstr "Upgrade to Kubernetes version: %s is not supported from version: %s" -#: pkg/acsengine/filesaver.go:24 +#: pkg/engine/filesaver.go:24 #, c-format msgid "error creating directory '%s': %s" msgstr "error creating directory '%s': %s" -#: pkg/acsengine/engine.go:1194 +#: pkg/engine/engine.go:1194 #, c-format msgid "error executing template for file %s: %v" msgstr "error executing template for file %s: %v" @@ -70,7 +70,7 @@ msgstr "error executing template for file %s: %v" msgid "error generating upgrade template: %s" msgstr "error generating upgrade template: %s" -#: pkg/acsengine/engine.go:1189 +#: pkg/engine/engine.go:1189 #, c-format msgid "error parsing file %s: %v" msgstr "error parsing file %s: %v" @@ -80,12 +80,12 @@ msgstr "error parsing file %s: %v" msgid "error reading file %s: %s" msgstr "error reading file %s: %s" -#: pkg/acsengine/ssh.go:55 +#: pkg/engine/ssh.go:55 #, c-format msgid "failed to create openssh public key string: %q" msgstr "failed to create openssh public key string: %q" -#: pkg/acsengine/ssh.go:49 +#: pkg/engine/ssh.go:49 #, c-format msgid "failed to generate private key for ssh: %q" msgstr "failed to generate private key for ssh: %q" @@ -100,12 +100,12 @@ msgstr "failed to initialize template generator: %s" msgid "invalid version %s for conversion back from unversioned object" msgstr "invalid version %s for conversion back from unversioned object" -#: pkg/acsengine/engine.go:322 +#: pkg/engine/engine.go:322 #, c-format msgid "orchestrator '%s' is unsupported" msgstr "orchestrator '%s' is unsupported" -#: pkg/acsengine/engine.go:187 +#: pkg/engine/engine.go:187 #, c-format msgid "template file %s does not exist" msgstr "template file %s does not exist" @@ -115,7 +115,7 @@ msgstr "template file %s does not exist" msgid "unrecognized APIVersion '%s'" msgstr "unrecognized APIVersion '%s'" -#: pkg/acsengine/engine.go:1183 +#: pkg/engine/engine.go:1183 #, c-format msgid "yaml file %s does not exist" msgstr "yaml file %s does not exist" diff --git a/cmd/upgrade.go b/cmd/upgrade.go index cdc6d2ae29..e8bd85c9b0 100644 --- a/cmd/upgrade.go +++ b/cmd/upgrade.go @@ -9,15 +9,14 @@ import ( "path" "time" - "github.com/Azure/acs-engine/pkg/acsengine" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/armhelpers" - "github.com/Azure/acs-engine/pkg/helpers" - "github.com/Azure/acs-engine/pkg/i18n" - "github.com/Azure/acs-engine/pkg/operations/kubernetesupgrade" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/armhelpers" + "github.com/Azure/aks-engine/pkg/engine" + "github.com/Azure/aks-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/operations/kubernetesupgrade" "github.com/leonelquinteros/gotext" "github.com/pkg/errors" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -41,7 +40,7 @@ type upgradeCmd struct { // derived containerService *api.ContainerService apiVersion string - client armhelpers.ACSEngineClient + client armhelpers.AKSEngineClient locale *gotext.Locale nameSuffix string agentPoolsToUpgrade []string @@ -175,14 +174,14 @@ func (uc *upgradeCmd) loadCluster(cmd *cobra.Command) error { } } if !found { - return errors.Errorf("Upgrading to version %s is not supported. To see a list of available upgrades, use 'acs-engine orchestrators --orchestrator kubernetes --version %s'", uc.upgradeVersion, uc.containerService.Properties.OrchestratorProfile.OrchestratorVersion) + return errors.Errorf("Upgrading to version %s is not supported. To see a list of available upgrades, use 'aks-engine orchestrators --orchestrator kubernetes --version %s'", uc.upgradeVersion, uc.containerService.Properties.OrchestratorProfile.OrchestratorVersion) } // Read name suffix to identify nodes in the resource group that belong // to this cluster. // TODO: Also update to read namesuffix from the parameters file as // user could have specified a name suffix instead of using the default - // value generated by ACS Engine + // value generated by AKS Engine templatePath := path.Join(uc.deploymentDirectory, "azuredeploy.json") contents, _ := ioutil.ReadFile(templatePath) @@ -224,7 +223,7 @@ func (uc *upgradeCmd) run(cmd *cobra.Command, args []string) error { StepTimeout: uc.timeout, } - kubeConfig, err := acsengine.GenerateKubeConfig(uc.containerService.Properties, uc.location) + kubeConfig, err := engine.GenerateKubeConfig(uc.containerService.Properties, uc.location) if err != nil { log.Fatalf("failed to generate kube config: %v", err) // TODO: cleanup } diff --git a/cmd/version.go b/cmd/version.go index 597f53eb30..4dc62406fc 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -3,7 +3,7 @@ package cmd import ( "fmt" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/helpers" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -26,8 +26,8 @@ var ( const ( versionName = "version" - versionShortDescription = "Print the version of ACS-Engine" - versionLongDescription = "Print the version of ACS-Engine" + versionShortDescription = "Print the version of AKS Engine" + versionLongDescription = "Print the version of AKS Engine" ) type versionInfo struct { diff --git a/cmd/version_test.go b/cmd/version_test.go index 236976ee13..0fb365a2c5 100644 --- a/cmd/version_test.go +++ b/cmd/version_test.go @@ -3,7 +3,7 @@ package cmd import ( "fmt" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/helpers" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) @@ -17,14 +17,14 @@ var _ = Describe("the version command", func() { Expect(output.Flags().Lookup("output")).NotTo(BeNil()) }) - It("should print a json version of ACS-Engine", func() { + It("should print a json version of AKS Engine", func() { output := getVersion("json") expectedOutput, _ := helpers.JSONMarshalIndent(version, "", " ", false) Expect(output).Should(Equal(string(expectedOutput))) }) - It("should print a humanized version of ACS-Engine", func() { + It("should print a humanized version of AKS Engine", func() { output := getVersion("human") expectedOutput := fmt.Sprintf("Version: %s\nGitCommit: %s\nGitTreeState: %s", @@ -35,7 +35,7 @@ var _ = Describe("the version command", func() { Expect(output).Should(Equal(expectedOutput)) }) - It("should print a json version of ACS-Engine", func() { + It("should print a json version of AKS Engine", func() { output := getVersion("json") expectedOutput, _ := helpers.JSONMarshalIndent(version, "", " ", false) diff --git a/docs/README.md b/docs/README.md index 850323e729..f931a703fa 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,21 +1,18 @@ -# Microsoft Azure Container Service Engine - Builds Docker Enabled Clusters +# Microsoft Azure Kubernetes Service Engine - Builds Kubernetes Clusters ## Overview -This cluster definition examples demonstrate how to create a customized Docker Enabled Cluster on Microsoft Azure. +This cluster definition examples demonstrate how to create a customized Kubernetes Cluster on Microsoft Azure. ## User Guides -* [ACS Engine](acsengine.md) - shows you how to build and use the ACS engine to generate custom Docker enabled container clusters +* [AKS Engine](aksengine.md) - shows you how to build and use the AKS Engine to generate custom Kubernetes container clusters * [Cluster Definition](clusterdefinition.md) - describes the components of the cluster definition file -* [DC/OS Walkthrough](dcos.md) - shows how to create a DC/OS enabled Docker cluster on Azure * [Kubernetes Walkthrough](kubernetes.md) - shows how to create a Kubernetes enabled Docker cluster on Azure * [Kubernetes Windows Walkthrough](kubernetes/windows.md) - shows how to create a hybrid Kubernetes Windows enabled Docker cluster on Azure. * [Kubernetes with GPU support Walkthrough](kubernetes/gpu.md) - shows how to create a Kubernetes cluster with GPU support. * [Kubernetes AAD integration Walkthrough](kubernetes/aad.md) - shows how to create a Kubernetes cluster with AAD as authentication provider. * [Kubernetes Monitoring Walkthrough](kubernetes/monitoring.md) - shows how to set up monitoring of your Kubernetes cluster -* [Swarm Walkthrough](swarm.md) - shows how to create a Swarm enabled Docker cluster on Azure -* [Swarm Mode Walkthrough](swarmmode.md) - shows how to create a Swarm Mode cluster on Azure * [Custom VNET](../examples/vnet) - shows how to use a custom VNET * [Attached Disks](../examples/disks-storageaccount) - shows how to attach up to 4 disks per node * [Managed Disks](../examples/disks-managed) (under private preview) - shows how to use managed disks diff --git a/docs/acsengine-code-delivery.md b/docs/aksengine-code-delivery.md similarity index 67% rename from docs/acsengine-code-delivery.md rename to docs/aksengine-code-delivery.md index b9d68f4d4f..1a3f72fc99 100644 --- a/docs/acsengine-code-delivery.md +++ b/docs/aksengine-code-delivery.md @@ -1,17 +1,17 @@ -# ACS Engine code delivery guide +# AKS Engine code delivery guide -[![ACS Engine](https://azurecomcdn.azureedge.net/mediahandler/acomblog/media/Default/blog/a8f28783-3ddc-4081-a57d-6d97147467bf.png)](https://github.com/azure/acs-engine) +[![AKS Engine](https://azurecomcdn.azureedge.net/mediahandler/acomblog/media/Default/blog/a8f28783-3ddc-4081-a57d-6d97147467bf.png)](https://github.com/Azure/aks-engine) -ACS Engine is an open source project to generate ARM (Azure Resource Manager) templates DC/OS, Kubernetes, Swarm Mode clusters on Microsoft Azure. -This documents provides guidelines to the acs-engine testing and continuous integration process. +AKS Engine is an open source project to generate ARM (Azure Resource Manager) templates for Kubernetes clusters on Microsoft Azure. +This documents provides guidelines to the aks-engine testing and continuous integration process. ## Development pipeline -ACS Engine employs CI system that incorporates Jenkins server, configured to interact with ACS Engine GitHub project. -A recommended way to contribute to ACS Engine is to fork github.com/Azure/acs-engine project. +AKS Engine employs CI system that incorporates a Jenkins server, configured to interact with AKS Engine GitHub project. +A recommended way to contribute to AKS Engine is to fork github.com/Azure/aks-engine project. and create a separated branch (a feature branch) for the feature you are working on. -The following steps constitute ACS Engine delivery pipeline +The following steps constitute AKS Engine delivery pipeline 1. Complete the current iteration of the code change, and check it into the feature branch 2. Invoke unit test. Return to step (1) if failed. @@ -20,7 +20,7 @@ The following steps constitute ACS Engine delivery pipeline ``` 3. Create a template. Return to step (1) if failed. ```sh - $ acs-engine generate --api-model kubernetes.json + $ aks-engine generate --api-model kubernetes.json ``` 4. Deploy the template in Azure. Return to step (1) if failed. ```sh @@ -31,7 +31,7 @@ The following steps constitute ACS Engine delivery pipeline --template-file azuredeploy.json \ --parameters @azuredeploy.parameters.json ``` - 5. Create a pull request (PR) from github.com/Azure/acs-engine portal. + 5. Create a pull request (PR) from github.com/Azure/aks-engine portal. 6. The PR triggers a Jenkins job that + applies the changes to the HEAD of the master branch + generates multiple ARM templates for different deployment scenarios @@ -39,6 +39,6 @@ The following steps constitute ACS Engine delivery pipeline This test might take 20-40 minutes. If the test fails, review the logs. If the failure was caused by your code change, return to step (1). Sometimes the test might fail because of intermittent Azure issues, such as resource unavailability of provisioning timeout. In this case manually trigger Jenkins PR job from your GitHub PR page. - 7. The PR is reviewed by the members of ACS Engine team. Should the changes have been requested, return to step (1). + 7. The PR is reviewed by the members of AKS Engine team. Should the changes have been requested, return to step (1). 8. Once the PR is approved, and Jenkins PR job has passed, the PR could be merged into the master branch 9. Once merged, another Jenkins job is triggered, to verify integrity of the master branch. This job is similar to the PR job. diff --git a/docs/acsengine.md b/docs/aksengine.md similarity index 68% rename from docs/acsengine.md rename to docs/aksengine.md index 559a8d1b4f..3e5de02729 100644 --- a/docs/acsengine.md +++ b/docs/aksengine.md @@ -1,28 +1,28 @@ -# Microsoft Azure Container Service Engine +# Microsoft Azure Kubernetes Service Engine -The Azure Container Service Engine (`acs-engine`) generates ARM (Azure Resource Manager) templates for Docker enabled clusters on Microsoft Azure with your choice of DCOS, [Kubernetes](kubernetes/deploy.md), or Swarm orchestrators. The input to acs-engine is a cluster definition file which describes the desired cluster, including orchestrator, features, and agents. The structure of the input files is very similar to the public API for Azure Container Service. +The Azure Kubernetes Service Engine (`aks-engine`) generates ARM (Azure Resource Manager) templates for Kubernetes clusters on Microsoft Azure. The input to aks-engine is a cluster definition file which describes the desired cluster, including orchestrator, features, and agents. The structure of the input files is very similar to the public API for Azure Container Service. - + ## Install -Binary downloads for the latest version of acs-engine for are available [here](https://github.com/Azure/acs-engine/releases/latest). Download `acs-engine` for your operating system. Extract the binary and copy it to your `$PATH`. +Binary downloads for the latest version of aks-engine for are available [here](https://github.com/Azure/aks-engine/releases/latest). Download `aks-engine` for your operating system. Extract the binary and copy it to your `$PATH`. -You can also choose to install acs-engine using [gofish](https://gofi.sh/#about), to do so execute the command `gofish install acs-engine` . You can install gofish following the [instructions](https://gofi.sh/#install) for your OS. +You can also choose to install aks-engine using [gofish](https://gofi.sh/#about), to do so execute the command `gofish install aks-engine` . You can install gofish following the [instructions](https://gofi.sh/#install) for your OS. -If you would prefer to build `acs-engine` from source or you are interested in contributing to `acs-engine` see [building from source](#build-acs-engine-from-source) below. +If you would prefer to build `aks-engine` from source or you are interested in contributing to `aks-engine` see [building from source](#build-aks-engine-from-source) below. ## Completion -`acs-engine` supports bash completion. To enable this, add the following to your `.bashrc` or `~/.profile` +`aks-engine` supports bash completion. To enable this, add the following to your `.bashrc` or `~/.profile` ```bash -source <(acs-engine completion) +source <(aks-engine completion) ``` ## Usage -`acs-engine` reads a JSON [cluster definition](./clusterdefinition.md) and generates a number of files that may be submitted to Azure Resource Manager (ARM). The generated files include: +`aks-engine` reads a JSON [cluster definition](./clusterdefinition.md) and generates a number of files that may be submitted to Azure Resource Manager (ARM). The generated files include: 1. **apimodel.json**: is an expanded version of the cluster definition provided to the generate command. All default or computed values will be expanded during the generate phase. 2. **azuredeploy.json**: represents a complete description of all Azure resources required to fulfill the cluster definition from `apimodel.json`. @@ -31,9 +31,9 @@ source <(acs-engine completion) ### Generate Templates -ACS Engine consumes a cluster definition which outlines the desired shape, size, and configuration of Kubernetes. There are a number of features that can be enabled through the cluster definition. +AKS Engine consumes a cluster definition which outlines the desired shape, size, and configuration of Kubernetes. There are a number of features that can be enabled through the cluster definition. -See [ACS Engine The Long Way](kubernetes/deploy.md#acs-engine-the-long-way) for an example on generating templates by hand. +See [AKS Engine The Long Way](kubernetes/deploy.md#aks-engine-the-long-way) for an example on generating templates by hand. @@ -81,36 +81,36 @@ New-AzureRmResourceGroupDeployment ` -## Build ACS Engine from Source +## Build AKS Engine from Source ### Docker Development Environment -The easiest way to start hacking on `acs-engine` is to use a Docker-based environment. If you already have Docker installed then you can get started with a few commands. +The easiest way to start hacking on `aks-engine` is to use a Docker-based environment. If you already have Docker installed then you can get started with a few commands. * Windows (PowerShell): `.\scripts\devenv.ps1` * Linux/OSX (bash): `./scripts/devenv.sh` -This script mounts the `acs-engine` source directory as a volume into the Docker container, which means you can edit your source code in your favorite editor on your machine, while still being able to compile and test inside of the Docker container. This environment mirrors the environment used in the acs-engine continuous integration (CI) system. +This script mounts the `aks-engine` source directory as a volume into the Docker container, which means you can edit your source code in your favorite editor on your machine, while still being able to compile and test inside of the Docker container. This environment mirrors the environment used in the aks-engine continuous integration (CI) system. When the script `devenv.ps1` or `devenv.sh` completes, you will be left at a command prompt. -Run the following commands to pull the latest dependencies and build the `acs-engine` tool. +Run the following commands to pull the latest dependencies and build the `aks-engine` tool. ```sh # install and download build dependencies make bootstrap -# build the `acs-engine` binary +# build the `aks-engine` binary make build ``` -The build process leaves the compiled `acs-engine` binary in the `bin` directory. Make sure everything completed successfully by running `bin/acs-engine` without any arguments: +The build process leaves the compiled `aks-engine` binary in the `bin` directory. Make sure everything completed successfully by running `bin/aks-engine` without any arguments: ```sh -$ ./bin/acs-engine -ACS-Engine deploys and manages Kubernetes, OpenShift, Swarm Mode, and DC/OS clusters in Azure +$ ./bin/aks-engine +AKS Engine deploys and manages Kubernetes clusters in Azure Usage: - acs-engine [command] + aks-engine [command] Available Commands: deploy Deploy an Azure Resource Manager template @@ -119,22 +119,22 @@ Available Commands: orchestrators Display info about supported orchestrators scale Scale an existing Kubernetes cluster upgrade Upgrade an existing Kubernetes cluster - version Print the version of ACS-Engine + version Print the version of AKS Engine Flags: --debug enable verbose debug logs - -h, --help help for acs-engine + -h, --help help for aks-engine -Use "acs-engine [command] --help" for more information about a command. +Use "aks-engine [command] --help" for more information about a command. ``` -[Here is a reference to the information on Kubernetes cluster upgrade.](https://github.com/Azure/acs-engine/blob/master/examples/k8s-upgrade/README.md) +[Here is a reference to the information on Kubernetes cluster upgrade.](https://github.com/Azure/aks-engine/blob/master/examples/k8s-upgrade/README.md) [Here's a quick demo video showing the dev/build/test cycle with this setup.](https://www.youtube.com/watch?v=lc6UZmqxQMs) ## Building on Windows, OSX, and Linux -Building ACS Engine from source has a few requirements for each of the platforms. Download and install the pre-reqs for your platform, Windows, Linux, or Mac: +Building AKS Engine from source has a few requirements for each of the platforms. Download and install the pre-reqs for your platform, Windows, Linux, or Mac: ### Prerequisite @@ -151,22 +151,22 @@ Setup steps: 3. Add `c:\go\bin` and `c:\gopath\bin` to your PATH variables 4. Click "new" and add new environment variable named `GOPATH` and set the value to `c:\gopath` -* Build acs-engine: +* Build aks-engine: 1. Type Windows key-R to open the run prompt 2. Type `cmd` to open a command prompt 3. Type `mkdir %GOPATH%` to create your gopath 4. Type `cd %GOPATH%` - 5. Type `go get -d github.com/Azure/acs-engine` to download acs-engine from GitHub + 5. Type `go get -d github.com/Azure/aks-engine` to download aks-engine from GitHub 6. Type `go get all` to get the supporting components 7. Type `go get -u github.com/go-bindata/go-bindata/...` - 8. Type `cd %GOPATH%\src\github.com\Azure\acs-engine\pkg\acsengine` + 8. Type `cd %GOPATH%\src\github.com\Azure\aks-engine\pkg\aksengine` 9. Type `go generate` - 10. Type `cd %GOPATH%\src\github.com\Azure\acs-engine\pkg\i18n` + 10. Type `cd %GOPATH%\src\github.com\Azure\aks-engine\pkg\i18n` 11. Type `go generate` - 12. Type `cd %GOPATH%\src\github.com\Azure\acs-engine` + 12. Type `cd %GOPATH%\src\github.com\Azure\aks-engine` 13. Type `go build` to build the project 14. Type `go install` to install the project - 15. Run `acs-engine.exe` to see the command line parameters + 15. Run `aks-engine.exe` to see the command line parameters ### OS X and Linux @@ -181,10 +181,10 @@ Setup steps: ``` 4. `source $HOME/.bash_profile` -Build acs-engine: +Build aks-engine: - 1. Type `go get github.com/Azure/acs-engine` to get the acs-engine Github project - 2. Type `cd $GOPATH/src/github.com/Azure/acs-engine` to change to the source directory + 1. Type `go get github.com/Azure/aks-engine` to get the aks-engine Github project + 2. Type `cd $GOPATH/src/github.com/Azure/aks-engine` to change to the source directory 3. Type `make bootstrap` to install supporting components 4. Type `make build` to build the project - 5. Type `./bin/acs-engine` to see the command line parameters + 5. Type `./bin/aks-engine` to see the command line parameters diff --git a/docs/acsengine.zh-CN.md b/docs/aksengine.zh-CN.md similarity index 74% rename from docs/acsengine.zh-CN.md rename to docs/aksengine.zh-CN.md index 4046dd08b4..55a64f8879 100644 --- a/docs/acsengine.zh-CN.md +++ b/docs/aksengine.zh-CN.md @@ -1,34 +1,34 @@ # 微软Azure容器服务引擎 -微软容器服务引擎(`acs-engine`)用于将一个容器集群描述文件转化成一组ARM(Azure Resource Manager)模板,通过在Azure上部署这些模板,用户可以很方便地在Azure上建立一套基于Docker的容器服务集群。用户可以自由地选择集群编排引擎DC/OS, Kubernetes或者是Swarm/Swarm Mode。集群描述文件使用和ARM模板相同的语法,它们都可以用来部署Azure容器服务。 +微软容器服务引擎(`aks-engine`)用于将一个容器集群描述文件转化成一组ARM(Azure Resource Manager)模板,通过在Azure上部署这些模板,用户可以很方便地在Azure上建立一套基于Docker的容器服务集群。用户可以自由地选择集群编排引擎, Kubernetes或者是。集群描述文件使用和ARM模板相同的语法,它们都可以用来部署Azure容器服务。 # 基于Docker的部署 -最简单的开始使用`acs-engine`的方式是使用Docker。如果本地计算机安装了Docker或者windows、Mac版本的Docker的话,无需安装任何软件就可以直接使用`acs-engine`了。 +最简单的开始使用`aks-engine`的方式是使用Docker。如果本地计算机安装了Docker或者windows、Mac版本的Docker的话,无需安装任何软件就可以直接使用`aks-engine`了。 * Windows (PowerShell): `.\scripts\devenv.ps1` * Linux (bash): `./scripts/devenv.sh` -上面的这段脚本在Docker容器中挂载了`acs-engine`源目录。你可以在任何熟悉的编辑器上修改这些源代码,所做的修改可以直接在Docker容器中编译和测试(本项目的持续集成系统中也采用了同样的方式)。 +上面的这段脚本在Docker容器中挂载了`aks-engine`源目录。你可以在任何熟悉的编辑器上修改这些源代码,所做的修改可以直接在Docker容器中编译和测试(本项目的持续集成系统中也采用了同样的方式)。 ``` make bootstrap ``` -当`devenv.{ps1,sh}`执行完毕的时候,你可以在容器中查看对应的日志,最后执行下面的脚本就可以生成`acs-engine`工具了: +当`devenv.{ps1,sh}`执行完毕的时候,你可以在容器中查看对应的日志,最后执行下面的脚本就可以生成`aks-engine`工具了: ``` make build ``` -当项目编译通过后,可以使用如下的命令来验证`acs-engine`是否正常运行: +当项目编译通过后,可以使用如下的命令来验证`aks-engine`是否正常运行: ``` -# ./bin/acs-engine -ACS-Engine deploys and manages Kubernetes, OpenShift, Swarm Mode, and DC/OS clusters in Azure +# ./bin/aks-engine +AKS Engine deploys and manages Kubernetes clusters in Azure Usage: - acs-engine [command] + aks-engine [command] Available Commands: deploy Deploy an Azure Resource Manager template @@ -37,13 +37,13 @@ Available Commands: orchestrators Display info about supported orchestrators scale Scale an existing Kubernetes cluster upgrade Upgrade an existing Kubernetes cluster - version Print the version of ACS-Engine + version Print the version of AKS Engine Flags: --debug enable verbose debug logs - -h, --help help for acs-engine + -h, --help help for aks-engine -Use "acs-engine [command] --help" for more information about a command. +Use "aks-engine [command] --help" for more information about a command. ``` [详细的开发,编译,测试过程和步骤可以参考这个视频](https://www.youtube.com/watch?v=lc6UZmqxQMs) @@ -57,10 +57,10 @@ ACS引擎具有跨平台特性,可以在windows,OS X和Linux上运行。以 安装依赖软件: - Git for Windows. [点击这里下载安装](https://git-scm.com/download/win) - Go for Windows. [点击这里下载安装](https://golang.org/dl/), 缺省默认安装. -- Powershell +- Powershell + +编译步骤: -编译步骤: - 1. 设置工作目录。 这里假设使用`c:\gopath`作为工作目录: 1. 使用Windows + R组合键打开运行窗口 2. 执行命令:`rundll32 sysdm.cpl,EditEnvironmentVariables`打开系统环境变量设置对话框 @@ -71,18 +71,18 @@ ACS引擎具有跨平台特性,可以在windows,OS X和Linux上运行。以 2. 运行`cmd`命令打开命令行窗口 3. 运行命令mkdir %GOPATH% 4. cd %GOPATH% - 5. 运行`go get github.com/Azure/acs-engine`命令获取ACS引擎在github上的最新代码 + 5. 运行`go get github.com/Azure/aks-engine`命令获取ACS引擎在github上的最新代码 6. 运行`go get all`命令安装ACS引擎需要的依赖组件 - 7. `cd %GOPATH%\src\github.com\Azure\acs-engine` + 7. `cd %GOPATH%\src\github.com\Azure\aks-engine` 8. 运行`go build`编译项目 -3. 运行`acs-engine`命令,如果能看到命令参数提示就说明已经正确编译成功了。 +3. 运行`aks-engine`命令,如果能看到命令参数提示就说明已经正确编译成功了。 ## OS X 安装依赖软件:: - Go for OS X. [点击这里下载安装](https://golang.org/dl/) -安装步骤: +安装步骤: 1. 打开命令行窗口并设置GOPATH环境变量: 1. `mkdir $HOME/gopath` @@ -93,11 +93,11 @@ ACS引擎具有跨平台特性,可以在windows,OS X和Linux上运行。以 ``` 3. `source $HOME/.sh_profile`使配置生效。 2. 编译ACS引擎: - 1. 运行`go get github.com/Azure/acs-engine`命令获取ACS引擎在github上的最新代码。 + 1. 运行`go get github.com/Azure/aks-engine`命令获取ACS引擎在github上的最新代码。 2. 运行`go get all`命令安装ACS引擎需要的依赖组件 - 3. `cd $GOPATH/src/github.com/Azure/acs-engine` + 3. `cd $GOPATH/src/github.com/Azure/aks-engine` 4. `go build`编译项目 -3. 运行`acs-engine`命令,如果能看到命令参数提示就说明已经正确编译成功了。 +3. 运行`aks-engine`命令,如果能看到命令参数提示就说明已经正确编译成功了。 ## Linux @@ -107,7 +107,7 @@ ACS引擎具有跨平台特性,可以在windows,OS X和Linux上运行。以 - 执行命令sudo tar -C /usr/local -xzf go$VERSION.$OS-$ARCH.tar.gz解压并替换原有文件。 - `git` -编译步骤: +编译步骤: 1. 设置GOPATH: 1. 运行命令`mkdir $HOME/gopath`新建gopath目录 @@ -118,11 +118,11 @@ ACS引擎具有跨平台特性,可以在windows,OS X和Linux上运行。以 ``` 3. 运行命令`source $HOME/.profile`使配置生效。 2. 编译ACS引擎: - 1. 运行命令`go get github.com/Azure/acs-engine`获取ACS引擎在github上的最新代码。 + 1. 运行命令`go get github.com/Azure/aks-engine`获取ACS引擎在github上的最新代码。 2. 运行`go get all`命令安装ACS引擎需要的依赖组件 - 3. `cd $GOPATH/src/github.com/Azure/acs-engine` + 3. `cd $GOPATH/src/github.com/Azure/aks-engine` 4. 运行`go build`命令编译项目 -3. 运行`acs-engine`命令,如果能看到命令参数提示就说明已经正确编译成功了。 +3. 运行`aks-engine`命令,如果能看到命令参数提示就说明已经正确编译成功了。 # 生成模板 @@ -134,17 +134,17 @@ ACS引擎使用json格式的[集群定义文件](clusterdefinition.md)作为输 3. **azuredeploy.parameters.json** - 部署参数文件,其中的参数可以自定义 4. **certificate and access config files** - 某些编排引擎例如kubernetes需要生成一些证书,这些证书文件和它依赖的kube config配置文件也存放在和ARM模板同级目录下面 -需要注意的是,当修改已有的Docker容器集群的时候,应该修改`apimodel.json`文件来保证最新的部署不会影响到目前集群中已有的资源。举个例子,如果一个容器集群中的节点数量不够的时候,可以修改`apimodel.json`中的集群节点数量,然后重新运行`acs-engine`命令并将`apimodel.json`作为输入参数来生成新的ARM模板。这样部署以后,集群中的旧的节点就不会有变化,新的节点会自动加入。 +需要注意的是,当修改已有的Docker容器集群的时候,应该修改`apimodel.json`文件来保证最新的部署不会影响到目前集群中已有的资源。举个例子,如果一个容器集群中的节点数量不够的时候,可以修改`apimodel.json`中的集群节点数量,然后重新运行`aks-engine`命令并将`apimodel.json`作为输入参数来生成新的ARM模板。这样部署以后,集群中的旧的节点就不会有变化,新的节点会自动加入。 # 演示 -这里通过部署一个kubernetes容器集群来演示如何使用`acs-engine`。kubernetes集群定义文件使用[examples/kubernetes.json](../examples/kubernetes.json)。 +这里通过部署一个kubernetes容器集群来演示如何使用`aks-engine`。kubernetes集群定义文件使用[examples/kubernetes.json](../examples/kubernetes.json)。 1. 首先需要准备一个[SSH 公钥私钥对](ssh.md#ssh-key-generation). 2. 编辑[examples/kubernetes.json](../examples/kubernetes.json)将其需要的参数配置好. -3. 运行`./bin/acs-engine generate examples/kubernetes.json`命令在_output/Kubernetes-UNIQUEID目录中生成对应的模板。(UNIQUEID是master节点的FQDN前缀的hash值) -4. 按照README中指定的方式使用`azuredeploy.json`和`azuredeploy.parameters.json`部署容器集群 [deployment usage](../acsengine.md#deployment-usage). +3. 运行`./bin/aks-engine generate examples/kubernetes.json`命令在_output/Kubernetes-UNIQUEID目录中生成对应的模板。(UNIQUEID是master节点的FQDN前缀的hash值) +4. 按照README中指定的方式使用`azuredeploy.json`和`azuredeploy.parameters.json`部署容器集群 [deployment usage](../aksengine.md#deployment-usage). # 部署方法 -[部署方式请参考这里](../acsengine.md#deployment-usage). +[部署方式请参考这里](../aksengine.md#deployment-usage). diff --git a/docs/clusterdefinition.md b/docs/clusterdefinition.md index 5944f9878c..41d3ef1199 100644 --- a/docs/clusterdefinition.md +++ b/docs/clusterdefinition.md @@ -1,4 +1,4 @@ -# Microsoft Azure Container Service Engine - Cluster Definition +# Microsoft Azure Kubernetes Service Engine - Cluster Definition ## Cluster Defintions for apiVersion "vlabs" @@ -22,15 +22,11 @@ Here are the cluster definitions for apiVersion "vlabs": Here are the valid values for the orchestrator types: -1. `DCOS` - this represents the [DC/OS orchestrator](dcos.md). [Older releases of DCOS 1.8 may be specified](../examples/dcos-releases). -2. `Kubernetes` - this represents the [Kubernetes orchestrator](kubernetes.md). -3. `Swarm` - this represents the [Swarm orchestrator](swarm.md). -4. `Swarm Mode` - this represents the [Swarm Mode orchestrator](swarmmode.md). -5. `OpenShift` - this represents the [OpenShift orchestrator](openshift.md). +1. `Kubernetes` - this represents the [Kubernetes orchestrator](kubernetes.md). To learn more about supported orchestrators and versions, run the orchestrators command: -```/bin/acs-engine orchestrators``` +```/bin/aks-engine orchestrators``` ### kubernetesConfig @@ -45,7 +41,7 @@ To learn more about supported orchestrators and versions, run the orchestrators | clusterSubnet | no | The IP subnet used for allocating IP addresses for pod network interfaces. The subnet must be in the VNET address space. With Azure CNI enabled, the default value is 10.240.0.0/12. Without Azure CNI, the default value is 10.244.0.0/16. | | containerRuntime | no | The container runtime to use as a backend. The default is `docker`. The other options are `clear-containers`, `kata-containers`, and `containerd` | | controllerManagerConfig | no | Configure various runtime configuration for controller-manager. See `controllerManagerConfig` [below](#feat-controller-manager-config) | -| customWindowsPackageURL | no | Configure custom windows Kubernetes release package URL for deployment on Windows that is generated by scripts/build-windows-k8s.sh. The format of this file is a zip file with multiple items (binaries, cni, infra container) in it. This setting will be depreciated in future release of acs-engine where the binaries will be pulled in the format of Kubernetes releases that only contain the kubernetes binaries. | +| customWindowsPackageURL | no | Configure custom windows Kubernetes release package URL for deployment on Windows that is generated by scripts/build-windows-k8s.sh. The format of this file is a zip file with multiple items (binaries, cni, infra container) in it. This setting will be depreciated in future release of aks-engine where the binaries will be pulled in the format of Kubernetes releases that only contain the kubernetes binaries. | | WindowsNodeBinariesURL | no | Windows Kubernetes Node binaries can be provided in the format of Kubernetes release (example: https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.11.md#node-binaries-1). This setting allows overriding the binaries for custom builds. | | dnsServiceIP | no | IP address for kube-dns to listen on. If specified must be in the range of `serviceCidr` | | dockerBridgeSubnet | no | The specific IP and subnet used for allocating IP addresses for the docker bridge network created on the kubernetes master and agents. Default value is 172.17.0.1/16. This value is used to configure the docker daemon using the [--bip flag](https://docs.docker.com/engine/userguide/networking/default_network/custom-docker0) | @@ -196,14 +192,14 @@ Additionally above, we specified a custom docker image for tiller, let's say we The reason for the unsightly gzip+base64 encoded input type is to optimize delivery payload, and to squash a human-maintainable yaml file representation into something that can be tightly pasted into a JSON string value without the arguably more unsightly carriage returns / whitespace that would be delivered with a literal copy/paste of a Kubernetes manifest. -Finally, the `addons.enabled` boolean property was omitted above; that's by design. If you specify a `containers` configuration, acs-engine assumes you're enabling the addon. The very first example above demonstrates a simple "enable this addon with default configuration" declaration. +Finally, the `addons.enabled` boolean property was omitted above; that's by design. If you specify a `containers` configuration, aks-engine assumes you're enabling the addon. The very first example above demonstrates a simple "enable this addon with default configuration" declaration. #### External Custom YAML scripts External YAML scripts can be configured for these supported addons and the manifest files for kube-scheduler, kube-controller-manager, cloud-controller-manager, kube-apiserver and PodSecurityPolicy. For addons, you will need to pass in a _base64_ encoded string of the kubernetes addon YAML file that you wish to use to `addons.Data` property. When `addons.Data` is provided with a value, the `containers` and `config` are required to be empty. CAVEAT: Please note that this is an experimental feature. Since Addons.Data allows you to provide your own scripts, you face the risk of any unintended/undesirable consequences of the errors and failures from running that script. - + ``` "kubernetesConfig": { "addons": [ @@ -249,7 +245,7 @@ and to pass a custom pod security policy config, do the following: See [here](https://kubernetes.io/docs/reference/generated/kubelet/) for a reference of supported kubelet options. -Below is a list of kubelet options that acs-engine will configure by default: +Below is a list of kubelet options that aks-engine will configure by default: | kubelet option | default value | | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -303,7 +299,7 @@ Below is a list of kubelet options that are _not_ currently user-configurable, e See [here](https://kubernetes.io/docs/reference/generated/kube-controller-manager/) for a reference of supported controller-manager options. -Below is a list of controller-manager options that acs-engine will configure by default: +Below is a list of controller-manager options that aks-engine will configure by default: | controller-manager option | default value | | ------------------------------- | ------------------------------------------ | @@ -348,7 +344,7 @@ Below is a list of controller-manager options that are _not_ currently user-conf See [here](https://kubernetes.io/docs/reference/generated/cloud-controller-manager/) for a reference of supported controller-manager options. -Below is a list of cloud-controller-manager options that acs-engine will configure by default: +Below is a list of cloud-controller-manager options that aks-engine will configure by default: | controller-manager option | default value | | ------------------------------- | ------------- | @@ -397,7 +393,7 @@ Or perhaps you want to customize/override the set of admission-control flags pas See [here](https://kubernetes.io/docs/reference/generated/kube-apiserver/) for a reference of supported apiserver options. -Below is a list of apiserver options that acs-engine will configure by default: +Below is a list of apiserver options that aks-engine will configure by default: | apiserver option | default value | | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -470,7 +466,7 @@ Below is a list of apiserver options that are _not_ currently user-configurable, See [here](https://kubernetes.io/docs/reference/generated/kube-scheduler/) for a reference of supported kube-scheduler options. -Below is a list of scheduler options that acs-engine will configure by default: +Below is a list of scheduler options that aks-engine will configure by default: | kube-scheduler option | default value | | --------------------- | ------------------------------------------ | @@ -500,7 +496,7 @@ We consider `kubeletConfig`, `controllerManagerConfig`, `apiServerConfig`, and ` #### jumpboxProfile -`jumpboxProfile` describes the settings for a jumpbox deployed via acs-engine to access a private cluster. It is a child property of `privateCluster`. +`jumpboxProfile` describes the settings for a jumpbox deployed via aks-engine to access a private cluster. It is a child property of `privateCluster`. | Name | Required | Description | | -------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -528,7 +524,7 @@ We consider `kubeletConfig`, `controllerManagerConfig`, `apiServerConfig`, and ` | vnetCidr | no | Specifies the VNET cidr when using a custom VNET ([bring your own VNET examples](../examples/vnet)). This VNET cidr should include both the master and the agent subnets. | | imageReference.name | no | The name of the Linux OS image. Needs to be used in conjunction with resourceGroup, below | | imageReference.resourceGroup | no | Resource group that contains the Linux OS image. Needs to be used in conjunction with name, above | -| distro | no | Select Master(s) Operating System (Linux only). Currently supported values are: `ubuntu`, `aks` and `coreos` (CoreOS support is currently experimental). Defaults to `aks` if undefined. `aks` is a custom image based on `ubuntu` that comes with pre-installed software necessary for Kubernetes deployments (Azure Public Cloud only for now). Currently supported OS and orchestrator configurations -- `ubuntu` and `aks`: DCOS, Docker Swarm, Kubernetes; `RHEL`: OpenShift; `coreos`: Kubernetes. [Example of CoreOS Master with CoreOS Agents](../examples/coreos/kubernetes-coreos.json) | +| distro | no | Select Master(s) Operating System (Linux only). Currently supported values are: `ubuntu`, `aks` and `coreos` (CoreOS support is currently experimental). Defaults to `aks` if undefined. `aks` is a custom image based on `ubuntu` that comes with pre-installed software necessary for Kubernetes deployments (Azure Public Cloud only for now). Currently supported OS and orchestrator configurations -- `ubuntu` and `aks`: Kubernetes; `coreos`: Kubernetes. [Example of CoreOS Master with CoreOS Agents](../examples/coreos/kubernetes-coreos.json) | | customFiles | no | The custom files to be provisioned to the master nodes. Defined as an array of json objects with each defined as `"source":"absolute-local-path", "dest":"absolute-path-on-masternodes"`.[See examples](../examples/customfiles) | | availabilityProfile | no | Supported values are `AvailabilitySet` (default) and `VirtualMachineScaleSets` (still under development: upgrade not supported; requires Kubernetes clusters version 1.10+ and agent pool availabilityProfile must also be `VirtualMachineScaleSets`). When MasterProfile is using `VirtualMachineScaleSets`, to SSH into a master node, you need to use `ssh -p 50001` instead of port 22. | | agentVnetSubnetId | only required when using custom VNET and when MasterProfile is using `VirtualMachineScaleSets` | Specifies the Id of an alternate VNET subnet for all the agent pool nodes. The subnet id must specify a valid VNET ID owned by the same subscription. ([bring your own VNET examples](../examples/vnet)). When MasterProfile is using `VirtualMachineScaleSets`, this value should be the subnetId of the subnet for all agent pool nodes. | @@ -557,7 +553,7 @@ A cluster can have 0 to 12 agent pool profiles. Agent Pool Profiles are used for | imageReference.name | no | The name of a a Linux OS image. Needs to be used in conjunction with resourceGroup, below | | imageReference.resourceGroup | no | Resource group that contains the Linux OS image. Needs to be used in conjunction with name, above | | osType | no | Specifies the agent pool's Operating System. Supported values are `Windows` and `Linux`. Defaults to `Linux` | -| distro | no | Specifies the agent pool's Linux distribution. Supported values are `ubuntu`, `aks` and `coreos` (CoreOS support is currently experimental). Defaults to `aks` if undefined, unless `osType` is defined as `Windows` (in which case `distro` is unused). `aks` is a custom image based on `ubuntu` that comes with pre-installed software necessary for Kubernetes deployments (Azure Public Cloud only for now). Currently supported OS and orchestrator configurations -- `ubuntu`: DCOS, Docker Swarm, Kubernetes; `RHEL`: OpenShift; `coreos`: Kubernetes. [Example of CoreOS Master with Windows and Linux (CoreOS and Ubuntu) Agents](../examples/coreos/kubernetes-coreos-hybrid.json) | +| distro | no | Specifies the agent pool's Linux distribution. Supported values are `ubuntu`, `aks` and `coreos` (CoreOS support is currently experimental). Defaults to `aks` if undefined, unless `osType` is defined as `Windows` (in which case `distro` is unused). `aks` is a custom image based on `ubuntu` that comes with pre-installed software necessary for Kubernetes deployments (Azure Public Cloud only for now). Currently supported OS and orchestrator configurations -- `ubuntu`: Kubernetes; `coreos`: Kubernetes. [Example of CoreOS Master with Windows and Linux (CoreOS and Ubuntu) Agents](../examples/coreos/kubernetes-coreos-hybrid.json) | | acceleratedNetworkingEnabled | no | Use [Azure Accelerated Networking](https://azure.microsoft.com/en-us/blog/maximize-your-vm-s-performance-with-accelerated-networking-now-generally-available-for-both-windows-and-linux/) feature for Linux agents (You must select a VM SKU that supports Accelerated Networking). Defaults to `true` if the VM SKU selected supports Accelerated Networking | | acceleratedNetworkingEnabledWindows | no | Use [Azure Accelerated Networking](https://azure.microsoft.com/en-us/blog/maximize-your-vm-s-performance-with-accelerated-networking-now-generally-available-for-both-windows-and-linux/) feature for Windows agents (You must select a VM SKU that supports Accelerated Networking). Defaults to `false` | @@ -659,7 +655,7 @@ format for `keyvaultSecretRef.vaultId`, can be obtained in cli, or found in the ## Cluster Defintions for apiVersion "2016-03-30" -Here are the cluster definitions for apiVersion "2016-03-30". This matches the api version of the Azure Container Service Engine. +Here are the cluster definitions for apiVersion "2016-03-30". This matches the api version of the Azure Kubernetes Service Engine. ### apiVersion @@ -677,11 +673,7 @@ Here are the cluster definitions for apiVersion "2016-03-30". This matches the a Here are the valid values for the orchestrator types: -1. `DCOS` - this represents the [DC/OS orchestrator](dcos.md). -2. `Swarm` - this represents the [Swarm orchestrator](swarm.md). -3. `Kubernetes` - this represents the [Kubernetes orchestrator](kubernetes.md). -4. `Swarm Mode` - this represents the [Swarm Mode orchestrator](swarmmode.md). -5. `OpenShift` - this represents the [OpenShift orchestrator](openshift.md) +1. `Kubernetes` - this represents the [Kubernetes orchestrator](kubernetes.md). ### masterProfile @@ -725,7 +717,7 @@ For apiVersion "2016-03-30", a cluster may have only 1 agent pool profiles. ### extensionProfiles -A cluster can have 0 - N extensions in extension profiles. Extension profiles allow a user to easily add pre-packaged functionality into a cluster. An example would be configuring a monitoring solution on your cluster. You can think of extensions like a marketplace for acs clusters. +A cluster can have 0 - N extensions in extension profiles. Extension profiles allow a user to easily add pre-packaged functionality into a cluster. An example would be configuring a monitoring solution on your cluster. You can think of extensions like a marketplace for AKS clusters. | Name | Required | Description | | ------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | diff --git a/docs/clusterdefinition.zh-CN.md b/docs/clusterdefinition.zh-CN.md index 6774476362..fa7981a319 100644 --- a/docs/clusterdefinition.zh-CN.md +++ b/docs/clusterdefinition.zh-CN.md @@ -20,10 +20,7 @@ 可选的编排引擎如下所示: -1. `DCOS` - 指定编排引擎为 [DC/OS编排引擎](dcos.md)。 -2. `Kubernetes` - 指定编排引擎为 [Kubernetes编排引擎](kubernetes.md)。 -3. `Swarm` - 指定编排引擎为 [Swarm编排引擎](swarm.md)。 -4. `Swarm Mode` - 指定编排引擎为 [Swarm Mode编排引擎](swarmmode.md)。 +1. `Kubernetes` - 指定编排引擎为 [Kubernetes编排引擎](kubernetes.md)。 ### masterProfile `masterProfile` 指定了集群中master节点的各种配置。 @@ -90,7 +87,7 @@ ## "2016-03-30"版本apiVersion的集群定义文件 -以下是"2016-03-30"版本apiVersion的集群定义文件,这个版本的api和Azure Container Service Engine的一致。 +以下是"2016-03-30"版本apiVersion的集群定义文件,这个版本的api和Azure Kubernetes Service Engine的一致。 ### apiVersion @@ -107,10 +104,7 @@ 可选的编排引擎如下所示: -1. `DCOS` - 指定编排引擎为 [DC/OS编排引擎](dcos.md)。 -2. `Swarm` - 指定编排引擎为 [Swarm编排引擎](swarm.md)。 -3. `Kubernetes` - 指定编排引擎为 [Kubernetes编排引擎](kubernetes.md)。 -4. `Swarm Mode` - 指定编排引擎为 [Swarm Mode编排引擎](swarmmode.md)。 +1. `Kubernetes` - 指定编排引擎为 [Kubernetes编排引擎](kubernetes.md)。 ### masterProfile `masterProfile` 指定了集群中master节点的各种配置。 diff --git a/docs/contributing-dcos.md b/docs/contributing-dcos.md deleted file mode 100644 index fef6963463..0000000000 --- a/docs/contributing-dcos.md +++ /dev/null @@ -1,210 +0,0 @@ -# Porting a new DC/OS version to ACS-Engine - -## 1. Locate the official ARM Template - -Go to `https://dcos.io/docs/X.X/administration/installing/cloud/azure/`, where `X.X` should be replaced by the version you are looking to port. -In the documentation, you will the link to the ARM templates you are looking for. -The latest stable templates should be at `https://downloads.dcos.io/dcos/stable/azure.html` -Early Access at: `https://downloads.dcos.io/dcos/EarlyAccess/azure.html` -Etc. - -## 2. Find the package GUIDs - -Following the previous step, you should now have 3 ARM templates (1, 3 and 5 masters variants). -We now need to find the package GUID of each variant. -In each template you should find a string that looks like: `dcos-config--setup_`, this GUID is what we are looking for. -Extract the GUIDs from the 3 differents templates, and them in `engine.go/getPackageGUID` for your specific DC/OS version. - -In DC/OS 1.11 and greater, you should find a the contents for `/etc/mesosphere/setup-flags/repository-url` in each 3 ARM templates (1, 3 and 5 masters variants). -Extract the GUIDs from the 3 differents templates, and them in `dcos/dcoscustomdataXXX.t` for your specific DC/OS version. - - -## 3. Extract the cloud-config data from the template - -In one of the template (no matter which one), grab the data from the MasterVM.osProfile.customData. -If you remove the concat operation, you should end up which a big string of unescaped JSON. -Unescape it (for example using this [online tool](http://www.freeformatter.com/javascript-escape.html#ad-output)), and convert it to yaml (you can use [json2yaml](https://www.json2yaml.com/)). -You should now have a clean yaml. - -## 4. Create and customize the custom data file. - -under the `parts` directory, create a new file called `dcoscustomdataXXX.t` replacing `XXX` by the correct version number. -Paste the yaml from the previous step inside. - -In the new file, under the `runcmd` section you should find 4 sucessive `curl` calls downloading some `.deb` packages followed by a bash script installing each one of them. This is handled by `parts\dcos\dcosprovision.sh` in ACS-Engine, so make sure the dependencies didn't change and replace the `curl` and `bash` calls by a link to the script. - -For example, in DC/OS 1.9: -```yaml -- curl -fLsSv --retry 20 -Y 100000 -y 60 -o /var/tmp/1.deb https://az837203.vo.msecnd.net/dcos-deps/libipset3_6.29-1_amd64.deb -- curl -fLsSv --retry 20 -Y 100000 -y 60 -o /var/tmp/2.deb https://az837203.vo.msecnd.net/dcos-deps/ipset_6.29-1_amd64.deb -- curl -fLsSv --retry 20 -Y 100000 -y 60 -o /var/tmp/3.deb https://az837203.vo.msecnd.net/dcos-deps/unzip_6.0-20ubuntu1_amd64.deb -- curl -fLsSv --retry 20 -Y 100000 -y 60 -o /var/tmp/4.deb https://az837203.vo.msecnd.net/dcos-deps/libltdl7_2.4.6-0.1_amd64.deb -- sed -i "s/^Port 22$/Port 22\nPort 2222/1" /etc/ssh/sshd_config -- service ssh restart -- bash -c "try=1;until dpkg -i /var/tmp/{1,2,3,4}.deb || ((try>9));do echo retry \$((try++));sleep - \$((try*try));done" -``` - -becomes - -```yaml -- /opt/azure/containers/provision.sh -``` - -Additional modifications under `runcmd`: -* Replace every occurence of the Package GUID (that we found in step 2) by `DCOSGUID`. -* the `content` of the cmd with path `/etc/mesosphere/setup-flags/late-config.yaml` should be modified to accept ACS-Engine bindings instead of variable where needed (look at a previous custom data file for reference). -* At the very end of the file, replace -```yaml -- content: '' - path: "/etc/mesosphere/roles/master" -- content: '' - path: "/etc/mesosphere/roles/azure_master" -- content: '' - path: "/etc/mesosphere/roles/azure" -``` - -by - -```yaml -- content: '' - path: /etc/mesosphere/roles/azure -- content: 'PROVISION_STR' - path: "/opt/azure/containers/provision.sh" - permissions: "0744" - owner: "root" -``` - -## 5. Adding the support of the new version inside to .go files - -### pkg/acsengine/defaults.go - -- Around line 30, add your `DCOSXXXBootstrapDownloadURL` variable (replace XXX with the version number), inside the `fmt.Sprintf()` function replace the second and third parameters with the version `EA, Stable, Beta, ...` and the commit hash. - -> You can find the commit hash from the https://downloads.dcos.io/dcos/stable/X.XX.X/azure.html page. - -Example for version 1.10 -[https://downloads.dcos.io/dcos/stable/1.10.0/azure.html](https://downloads.dcos.io/dcos/stable/1.10.0/azure.html) - -``` -DCOS110BootstrapDownloadURL: fmt.Sprintf(AzureEdgeDCOSBootstrapDownloadURL, "stable", "e38ab2aa282077c8eb7bf103c6fff7b0f08db1a4"), -``` - -### pkg/acsengine/engine.go - -- Around line 39, add `dcosCustomDataXXX = "dcos/dcoscustomdataXXX.t"` variable - -Example for version 1.10: -``` -dcosCustomData110 = "dcos/dcoscustomdata110.t" -``` - -- Around line 578, add the code case block for your version. - -Example for version 1.10: -``` -case api.DCOSRelease1Dot10: - dcosBootstrapURL = cloudSpecConfig.DCOSSpecConfig.DCOS110BootstrapDownloadURL - ``` - -- Around line 1170, add your api case version. - - Example for version 1.10: - ``` - case api.DCOSRelease1Dot10: - switch masterCount { - case 1: - return "c4ec6210f396b8e435177b82e3280a2cef0ce721" - case 3: - return "08197947cb57d479eddb077a429fa15c139d7d20" - case 5: - return "f286ad9d3641da5abb622e4a8781f73ecd8492fa" - } - ``` - - > In the return function, paste the package GUID from the step 2 for each cases. - -- Around line 1558, add your api case version. - -Example for version 1.10: -``` - case api.DCOSRelease1Dot10: - yamlFilename = dcosCustomData110 -``` - -### pkg/acsengine/types.go - -- Around line 40, add your the type for your new version. - -Example for version 1.10 : -``` -DCOS110BootstrapDownloadURL string -``` - -### pkg/api/common/const.go - -- Around line 59, declare a new const with your `DCOSRelease` - -Example for version 1.10 : -``` -// DCOSRelease1Dot10 is the major.minor string prefix for 1.9 versions of DCOS -DCOSRelease1Dot10 string = "1.10" -``` - -- Around line 72, add your `DCOSReleaseToVersion` in the map - -Example for version 1.10 : -``` -DCOSRelease1Dot10: "1.10.0", -``` - -### pkg/api/const.go - -- Around line 76, add the const for your DCOS release - -Example for version 1.10 : -``` -// DCOSRelease1Dot10 is the major.minor string prefix for 1.10 versions of DCOS -DCOSRelease1Dot10 string = "1.10" -``` - -### pkg/api/convertertoapi.go - -- Around line 572 and 601 (two places) add the case for your release - -Example for version 1.10 : -``` -case DCOSRelease1Dot10, DCOSRelease1Dot9, DCOSRelease1Dot8: -``` -``` -case DCOSRelease1Dot10, DCOSRelease1Dot9, DCOSRelease1Dot8, DCOSRelease1Dot7: -``` - -### pkg/api/v20170701/validate.go - -- Around line 33, add the case for your release - -Example for version 1.10 : -``` -case common.DCOSRelease1Dot10: -``` - -### pkg/api/vlabs/validate.go - -- Around line 37, add the case for your release - -Example for version 1.10 : -``` -case common.DCOSRelease1Dot10: -``` - - -## Conclusion - -We encourage you to look at previous PR as example, listed bellow : - -- [Adding DC/OS 1.10 stable version support #1439](https://github.com/Azure/acs-engine/pull/1439/files) -- [setting dcos test to 1.9 (current default)](https://github.com/Azure/acs-engine/pull/1443) -- [[DC/OS] Set 1.9 as default DCOS version and upgrade Packages](https://github.com/Azure/acs-engine/pull/457) -- [[DC/OS] Add support for DCOS 1.9 EA](https://github.com/Azure/acs-engine/pull/360) -- [DCOS 1.8.8 Support](https://github.com/Azure/acs-engine/pull/278) diff --git a/docs/custom-vnet.md b/docs/custom-vnet.md index 175eed83b0..529f6d9011 100644 --- a/docs/custom-vnet.md +++ b/docs/custom-vnet.md @@ -1,16 +1,16 @@ # Using a custom virtual network with Azure Container Service -In this tutorial you are going to learn how to use [ACS Engine](https://github.com/Azure/acs-engine) to deploy a brand new cluster into an existing or pre-created virtual network. +In this tutorial you are going to learn how to use [AKS Engine](https://github.com/Azure/aks-engine) to deploy a brand new cluster into an existing or pre-created virtual network. By doing this, you will be able to control the properties of the virtual network or integrate a new cluster into your existing infrastructure. -*Note: This article describes the procedure with Docker Swarm but it will work in the exact same way with the all the orchestrators available with ACS Engine: Docker Swarm, Kubernetes and DC/OS.* +*Note: This article describes the procedure with Docker Swarm but it will work in the exact same way with the all the orchestrators available with AKS Engine: Kubernetes.* -*For Kubernetes, the cluster should be deployed in the same resource group as the virtual network and the service principal you use for the cluster needs permissions on the VNET resource's group too. Custom VNET for Kubernetes Windows cluster has a [known issue](https://github.com/Azure/acs-engine/issues/1767).* +*For Kubernetes, the cluster should be deployed in the same resource group as the virtual network and the service principal you use for the cluster needs permissions on the VNET resource's group too. Custom VNET for Kubernetes Windows cluster has a [known issue](https://github.com/Azure/aks-engine/issues/1767).* ## Prerequisites You can run this walkthrough on OS X, Windows, or Linux. - You need an Azure subscription. If you don't have one, you can [sign up for an account](https://azure.microsoft.com/). - Install the [Azure CLI 2.0](/cli/azure/install-az-cli2). -- Install the [ACS Engine](https://github.com/Azure/acs-engine/blob/master/docs/acsengine.md) +- Install the [AKS Engine](https://github.com/Azure/aks-engine/blob/master/docs/aksengine.md) ## Create the virtual network *You need a virtual network before creating the new cluster. If you already have one, you can skip this step.* @@ -78,12 +78,12 @@ az group deployment create -g acs-custom-vnet --name "CustomVNet" --template-fil Once the deployment is completed you should see the virtual network in the resource group. -## Create the template for ACS Engine -ACS Engine uses a JSON template in input and generates the ARM template and ARM parameters files in output. +## Create the template for AKS Engine +AKS Engine uses a JSON template in input and generates the ARM template and ARM parameters files in output. Depending on the orchestrator you want to deploy, the number of agent pools, the machine size you want (etc.) this input template could differ from the one we are going to detail here. -There are a lot of examples available on the [ACS Engine GitHub](https://github.com/Azure/acs-engine/tree/master/examples) and you can find [one dedicated for virtual network](https://github.com/Azure/acs-engine/blob/master/examples/vnet/README.md). +There are a lot of examples available on the [AKS Engine GitHub](https://github.com/Azure/aks-engine/tree/master/examples) and you can find [one dedicated for virtual network](https://github.com/Azure/aks-engine/blob/master/examples/vnet/README.md). In this case, we are going to use the following template: @@ -140,10 +140,10 @@ As you can see, for all node pools definition (master or agents) you can use the *Note: Make sure the the vnetSubnetId matches with your subnet, by giving your **SUBSCRIPTION_ID**, **RESOURCE_GROUP_NAME**, virtual network and subnet names. You also need to fill DNS prefix for all the public pools you want to create, give an SSH keys...* ## Generate the cluster Azure Resource Manager template -Once your are ready with the cluster definition file, you can use ACS Engine to generate the ARM template that will be used to deploy the cluster on Azure: +Once your are ready with the cluster definition file, you can use AKS Engine to generate the ARM template that will be used to deploy the cluster on Azure: ```bash -acs-engine azuredeploy.swarm.clusterdefinition.json +aks-engine azuredeploy.swarm.clusterdefinition.json ``` This command will output three files: @@ -152,15 +152,15 @@ This command will output three files: wrote _output/Swarm-12652785/apimodel.json wrote _output/Swarm-12652785/azuredeploy.json wrote _output/Swarm-12652785/azuredeploy.parameters.json -acsengine took 37.1384ms +aksengine took 37.1384ms ``` -- apimodel.json: this is the cluster definition file you gave to ACS Engine +- apimodel.json: this is the cluster definition file you gave to AKS Engine - azuredeploy.json: this is the Azure Resource Manager JSON template that you are going to use to deploy the cluster - azuredeploy.parameters.json: this is the parameters file that you are going to use to deploy the cluster ## Deploy the Azure Container Service cluster -Now that you have generated the ARM templates and its parameters file using ACS Engine, you can use Azure CLI 2.0 to start the deployment of the cluster: +Now that you have generated the ARM templates and its parameters file using AKS Engine, you can use Azure CLI 2.0 to start the deployment of the cluster: ```bash az group deployment create -g acs-custom-vnet --name "ClusterDeployment" --template-file azuredeploy.json --parameters "@azuredeploy.parameters.json" diff --git a/docs/dcos.md b/docs/dcos.md deleted file mode 100644 index ea31996fc2..0000000000 --- a/docs/dcos.md +++ /dev/null @@ -1,147 +0,0 @@ -# Microsoft Azure Container Service Engine - DC/OS Walkthrough - -### `Note:` -Support for DC/OS `1.11` and later continues in the forked project [dcos-engine](https://github.com/Azure/dcos-engine). - -## Deployment - -Here are the steps to deploy a simple DC/OS cluster: - -1. [install acs-engine](acsengine.md#downloading-and-building-acs-engine) -2. [generate your ssh key](ssh.md#ssh-key-generation) -3. edit the [DC/OS example](../examples/dcos.json) and fill in the blank strings -4. [generate the template](acsengine.md#generate-templates) -5. [deploy the output azuredeploy.json and azuredeploy.parameters.json](acsengine.md#deploy-templates) - -## Walkthrough - -Once your DC/OS cluster has deployed you will have a resource group containing: - -1. a set of 1,3, or 5 masters in a master specific availability set. Each master's SSH can be accessed via the public dns address at ports 2200..2204 - -2. a set of public agents in an Virtual Machine Scale Set (VMSS). The agent VMs can be accessed through a master. See [agent forwarding](ssh.md#key-management-and-agent-forwarding-with-windows-pageant) for an example of how to do this. - -3. a set of private agents in an Virtual Machine Scale Set (VMSS). - -The following image shows the architecture of a container service cluster with 3 masters, and 6 agents: - -![Image of DC/OS container service on azure](images/dcos.png) - -In the image above, you can see the following parts: - -1. **Admin Router on port 80** - The admin router enables you to access all DC/OS services. For example, if you create an SSH tunnel to port 80 you can access the services on the following urls, you can see the DC/OS dashboard by browsing to -2. **Masters** - Masters run the DC/OS processes that schedule and manage workloads on the agent nodes. -3. **Public Agents** - Public agents, deployed in a VM scale set, are publicly accessible through the Azure Load Balancer to ports 80, 443, and 8080. Jobs can be assigned to public agents using role `slave_public`. -4. **Private Agents** - Private agents, deployed in a VM scale set, are not publicly accessible. Workloads are scheduled to private agents by default. -5. **Docker on port 2375** - The Docker engine runs containerized workloads and each Agent runs the Docker engine. DC/OS runs Docker workloads, and examples on how to do this are provided in the Marathon walkthrough sections of this readme. - -All VMs are in the same VNET where the masters are on private subnet 172.16.0.0/24 and the agents are on the private subnet, 10.0.0.0/8, and fully accessible to each other. - -## Create your First Three DC/OS Services: hello-world, Docker app, and Docker web app - -This walk through is inspired by the wonderful digital ocean tutorial: https://www.digitalocean.com/community/tutorials/how-to-configure-a-production-ready-mesosphere-cluster-on-ubuntu-14-04. After completing this walkthrough you will know how to: - * access DC/OS dashboard for cluster health, - * deploy a simple hello-world app, - * deploy a simple docker app, - * look at logs of your workload, - * and deploy a simple web app publicly available to the world. - - - 1. After successfully deploying the template write down the two output master and agent FQDNs (Fully Qualified Domain Name). - 1. If using Powershell or CLI, the output parameters are in the OutputsString section named 'agentFQDN' and 'masterFQDN' - 2. If using Portal, to get the output you need to: - 1. navigate to "resource group" - 2. click on the resource group you just created - 3. then click on "Succeeded" under *last deployment* - 4. then click on the "Microsoft.Template" - 5. now you can copy the output FQDNs and sample SSH commands - ![Image of docker scaling](images/findingoutputs.png) - - 2. Create an [SSH tunnel to port 80](ssh.md#create-port-80-tunnel-to-the-master) on the master FQDN. - - 3. browse to the DC/OS UI . This displays the main DC/OS dashboard: - - 4. The front page shows the DC/OS Dashboard: - 1. Scroll down to see your CPU, Memory and Disk Allocation. This also shows you services, node, and component health. - - ![Image of the DC/OS dashboard](images/dcosdashboard.png) - - 2. On the left side click "Services" - - ![Image of DC/OS services on Azure](images/dcosservices.png) - - 3. start a long running service - 1. click "Deploy Service" - 2. type "myfirstapp" for the id - 3. type `/bin/bash -c 'for i in {1..5}; do echo MyFirstApp $i; sleep 1; done'` for the command - 4. scroll to bottom and click Deploy - - ![Image of Deploy New Service dialog](images/deployfirstapp.png) - - 5. you will notice the new app change state from not running to running - - ![Image of the new application status](images/dcos-newapp-status.png) - - 6. To run a Docker app browse back to Services, and click "Deploy Service" and set id to "/helloworld": - - ![Image of setting up docker application dialog 1](images/dcos-docker-helloworld1.png) - - 7. Click "Container Settings", type `hello-world` for image and click "Deploy" - - ![Image of setting up docker application dialog 2](images/dcos-docker-helloworld2.png) - - 8. Once deployed, click on the "helloworld" service, and you will see all the finished tasks: - - ![Image of helloworld tasks](images/dcos-docker-helloworld-tasks.png) - - 9. Click on the most recent finished tasks, and click "Logs" and you will see the "Hello from Docker!" message: - - ![Image of helloworld tasks](images/dcos-docker-helloworld-logs.png) - - 10. The next step is to deploy a docker web app accessible to the world. The public agents have a load balancer exposing port 80, 443, and 8080. On the DC/OS page, browse back to Services, and click "Deploy Service" and set id to "/simpleweb": - - ![Image of docker web app](images/dcos-simpleweb1.png) - - 11. On left, click "Container Settings" and container image "yeasy/simple-web". This is the image that will be downloaded from DockerHub - - ![Image of docker web app](images/dcos-simpleweb2.png) - - 12. Next on left, click "Network" and type in port 80. This is how you expose port 80 to the world. - - ![Image of docker web app](images/dcos-simpleweb3.png) - - 13. Next on left, click "Optional" and set role type "slave_public". This ensures the Docker web app is running on the public agent. - - ![Image of docker web app](images/dcos-simpleweb4.png) - - 14. Finally click deploy and watch the web app deploy. Once it goes to running state, open the FQDN retrieved in step 1 during deployment, and you will see the web app. - - ![Image of web app](images/simpleweb.png) - -# DCOS upgrade - -Starting from DC/OS 1.11, acs-engine deploys a bootstrap node as part of DC/OS cluster. This enables upgrade operation on an existing cluster. - -To start the upgrade, run this following command: -``` -acs-engine dcos-upgrade \ - --subscription-id \ - --resource-group \ - --location \ - --upgrade-version \ - --deployment-dir \ - --ssh-private-key-path -``` -The upgrade is an idempotent operation. If failed, it could be re-run and will pick the execution from the last successful checkpoint. - -# Learning More - -Here are recommended links to learn more about DC/OS: - -1. [Azure DC/OS documentation](https://azure.microsoft.com/en-us/documentation/services/container-service/) - -## DC/OS Community Documentation - -1. [DC/OS Overview](https://dcos.io/docs/1.8/overview/) - provides overview of DC/OS, Architecture, Features, and Concepts. - -2. [DC/OS Tutorials](https://docs.mesosphere.com/1.8/usage/tutorials/) - provides various tutorials for DC/OS. diff --git a/docs/design/proposed-template-refactor.md b/docs/design/proposed-template-refactor.md index 3652de0e1c..8e579dc031 100644 --- a/docs/design/proposed-template-refactor.md +++ b/docs/design/proposed-template-refactor.md @@ -1,18 +1,18 @@ -# Acs-engine +# AKS Engine -The Azure Container Service Engine (acs-engine) is a command line tool that generates ARM (Azure Resource Manager) templates in order for one to deploy container-based clusters (like Kubernetes , DCOS, Openshift, Docker swarm) on the Azure platform. +The Azure Kubernetes Service Engine (aks-engine) is a command line tool that generates ARM (Azure Resource Manager) templates in order for one to deploy Kubernetes clusters on the Azure platform. -This design document provides a brief and high-level overview of what acs-engine does internally to achieve deployment of containerized clusters. The scope of this document will be limited to the execution of acs-engine when creating Kubernetes clusters. +This design document provides a brief and high-level overview of what aks-engine does internally to achieve deployment of containerized clusters. The scope of this document will be limited to the execution of aks-engine when creating Kubernetes clusters. ## Architecture Diagram -![Alt text](../images/proposed-template-refactor.jpg "acs-engine architecture diagram") +![Alt text](../images/proposed-template-refactor.jpg "aks-engine architecture diagram") ## Components ### Cluster api model -Acs-engine accepts JSONs of cluster api models as inputs. These api models allow the user to specify cluster configuration items such as +AKS Engine accepts JSONs of cluster api models as inputs. These api models allow the user to specify cluster configuration items such as - Master and worker nodes configuration - Kubernetes version @@ -227,11 +227,11 @@ The template generator then creates the following artifacts ### ARM Interface -Acs-engine interfaces with Azure Resource Manager (ARM) through the Azure Go SDK. The Go SDK provides interfaces to perform functions like template deployment, validation. +AKS Engine interfaces with Azure Resource Manager (ARM) through the Azure Go SDK. The Go SDK provides interfaces to perform functions like template deployment, validation. ### Kubernetes Client API -Acs-engine also performs kubernetes cluster management operations (kubectl) through the imported Kubernetes API libraries. The Client API calls are made during the scale and upgrade commands of acs-engine. +AKS Engine also performs kubernetes cluster management operations (kubectl) through the imported Kubernetes API libraries. The Client API calls are made during the scale and upgrade commands of aks-engine. Design challenges and proposals @@ -244,7 +244,7 @@ We find that the current implementation of templating leads to challenges in ter - There is no direct and intuitive mapping between the input apimodels and the ARM templates. The placeholder substitutions are performed at very specific areas in the template skeletons. It's hard to draw any generality from it and this makes it difficult to create the template JSONs purely through code as opposed to performing the placeholder substitutions. -- This also limits the capabilities of acs-engine as far as extensibility is concerned. If we were to introduce more changes and customizations, it would potentially entail modifying the template skeleton layouts. This would just add more complexity. +- This also limits the capabilities of aks-engine as far as extensibility is concerned. If we were to introduce more changes and customizations, it would potentially entail modifying the template skeleton layouts. This would just add more complexity. #### Possible Solutions @@ -258,7 +258,7 @@ _**Pros**_ - This will allow us to accommodate future ARM template customization more effectively, because we can express and maintain the variety of inter-dependent outputs natively, as first class data representations. -- Template validation can be done within the acs-engine layer itself. Currently, template validation can only be performed via the Azure GO SDK and this entails a network call. +- Template validation can be done within the aks-engine layer itself. Currently, template validation can only be performed via the Azure GO SDK and this entails a network call. _**Cons/Challenges**_ @@ -268,7 +268,7 @@ _**Cons/Challenges**_ **YAML-based templates** -We could also do away with our current JSON-based template skeletons and use YAML templating instead. +We could also do away with our current JSON-based template skeletons and use YAML templating instead. _**Pros**_ @@ -281,4 +281,4 @@ _**Pros**_ _**Cons/Challenges**_ -- While this method is easier to implement, the benefits of extensibility and maintainability are significantly lesser than that provided by a strong schema type. \ No newline at end of file +- While this method is easier to implement, the benefits of extensibility and maintainability are significantly lesser than that provided by a strong schema type. diff --git a/docs/developers.md b/docs/developers.md index 3225b77798..8257991e13 100644 --- a/docs/developers.md +++ b/docs/developers.md @@ -1,7 +1,7 @@ # Developers Guide This guide explains how to set up your environment for developing on -acs-engine. +aks-engine. ## Prerequisites @@ -21,11 +21,11 @@ elegant and high-quality open source code so that our users will benefit. Make sure you have read and understood the main CONTRIBUTING guide: -https://github.com/Azure/acs-engine/blob/master/CONTRIBUTING.md +https://github.com/Azure/aks-engine/blob/master/CONTRIBUTING.md ### Structure of the Code -The code for the acs-engine project is organized as follows: +The code for the aks-engine project is organized as follows: - The individual programs are located in `cmd/`. Code inside of `cmd/` is not designed for library re-use. @@ -46,9 +46,9 @@ home of the current development candidate. Releases are tagged. We accept changes to the code via GitHub Pull Requests (PRs). One workflow for doing this is as follows: -1. Use `go get` to clone the acs-engine repository: `go get github.com/Azure/acs-engine` +1. Use `go get` to clone the aks-engine repository: `go get github.com/Azure/aks-engine` 2. Fork that repository into your GitHub account -3. Add your repository as a remote for `$GOPATH/github.com/Azure/acs-engine` +3. Add your repository as a remote for `$GOPATH/github.com/Azure/aks-engine` 4. Create a new working branch (`git checkout -b feat/my-feature`) and do your work on that branch. 5. When you are ready for us to review, push your branch to GitHub, and @@ -56,9 +56,9 @@ workflow for doing this is as follows: ### Third Party Dependencies -Third party dependencies reside locally inside the repository under the `vendor/` directory. We use [dep](https://github.com/golang/dep) to enforce our dependency graph, declared in [Gopkg.toml](https://github.com/Azure/acs-engine/blob/master/CONTRIBUTING.md) in the project root. +Third party dependencies reside locally inside the repository under the `vendor/` directory. We use [dep](https://github.com/golang/dep) to enforce our dependency graph, declared in [Gopkg.toml](https://github.com/Azure/aks-engine/blob/master/CONTRIBUTING.md) in the project root. -If you wish to introduce a new third party dependency into `acs-engine`, please file an [issue](https://github.com/Azure/acs-engine/issues), and include the canonical VCS path (e.g., `github.com/Azure/azure-sdk-for-go`) along with either the desired release string expression to depend on (e.g., `~8.1.0`), or the commit hash to pin to a static commit (e.g., `4cdb38c072b86bf795d2c81de50784d9fdd6eb77`). A project maintainer will then own the effort to update the codebase with that dependency, including relevant updates to `Gopkg.toml` and `vendor/`. +If you wish to introduce a new third party dependency into `aks-engine`, please file an [issue](https://github.com/Azure/aks-engine/issues), and include the canonical VCS path (e.g., `github.com/Azure/azure-sdk-for-go`) along with either the desired release string expression to depend on (e.g., `~8.1.0`), or the commit hash to pin to a static commit (e.g., `4cdb38c072b86bf795d2c81de50784d9fdd6eb77`). A project maintainer will then own the effort to update the codebase with that dependency, including relevant updates to `Gopkg.toml` and `vendor/`. As a rule we want to distinguish dependency update PRs from feature/bug PRs; we may ask that feature/bug PRs which include updates to `vendor/` and/or contain any other dependency-related overhead to be triaged into separate PRs that can be managed independently, pre-requisite dependency changes in one, and features/bugs in another. The objective of enforcing these distinctions is to help focus the PR review process, and to make manageable the difficult task of rationalizing a multitude of parallel PRs in flight, many of which which may carry hard-to-reconcile dependency side-effects when aggressively updated with a fresh dependency graph as part of the PR payload. @@ -81,8 +81,8 @@ Unit tests may be run locally via `make test`. ### End-to-end Tests -End-to-end tests for the DCOS, Kubernetes and OpenShift orchestrators may be run -via `make test-{dcos,kubernetes,openshift}`. The test process can optionally +End-to-end tests for the Kubernetes orchestrator may be run +via `make test-kubernetes`. The test process can optionally deploy and tear down a cluster as part of the test (this is enabled by default). You'll need access to an Azure subscription, as well as at least the following environment variables to be set: @@ -92,51 +92,21 @@ environment variables to be set: * `SUBSCRIPTION_ID`: Azure subscription UUID * `TENANT_ID`: Azure tenant UUID -#### OpenShift - -To test the OpenShift orchestrator, you'll need to enable programmatic -deployment of the underlying image. In the Azure console, find the image under -Home > New > Marketplace > Everything. Click "Want to deploy programmatically? -Get started". Enable your subscription and click Save. - -You'll also need to have `oc` and `kubectl` binaries locally in your PATH which -correspond to the cluster version being tested. Download the `oc` binary, then -make a symlink or copy of it and name the new file `kubectl`. - -To have the test process deploy and tear down a cluster, set the following -environment variables: - -* `CLUSTER_DEFINITION=examples/openshift.json` -* `DISTRO=openshift39_centos` -* `LOCATION=eastus` - -Alternatively, to run tests on a pre-deployed OpenShift cluster, set the -following environment variables: - -* `CLEANUP_ON_EXIT=false` -* `LOCATION=eastus` -* `NAME=`: dnsPrefix of the pre-deployed cluster - -Finally, you'll need to make sure that the apimodel.json corresponding to the -pre-deployed cluster is available at `_output/$NAME.json`. If you previously -used `acs-engine deploy` directly to deploy the cluster, you will need to run -`cp _output/$NAME/apimodel.json _output/$NAME.json`. - ### Debugging -For acs-engine code debugging you can use [Delve](https://github.com/derekparker/delve) debugger. +For aks-engine code debugging you can use [Delve](https://github.com/derekparker/delve) debugger. #### CLI Run command: ``` -dlv debug github.com/Azure/acs-engine -- generate ~/Documents/azure/openshift.json +dlv debug github.com/Azure/aks-engine -- generate ~/Documents/azure/kubernetes.json ``` Test individual package and individual test: ``` -dlv test github.com/Azure/acs-engine/pkg/acsengine -dlv test github.com/Azure/acs-engine/pkg/acsengine -- -test.run ^TestNetworkPolicyDefaults$ +dlv test github.com/Azure/aks-engine/pkg/engine +dlv test github.com/Azure/aks-engine/pkg/engine -- -test.run ^TestNetworkPolicyDefaults$ ``` #### Visual Code Studio @@ -158,7 +128,7 @@ Example launch.json file: "mode": "debug", "program": "${workspaceRoot}", "env": {}, - "args": ["generate", "${workspaceRoot}/examples/openshift.json"], + "args": ["generate", "${workspaceRoot}/examples/kubernetes.json"], "showLog": true } ] diff --git a/docs/extensions.md b/docs/extensions.md index c66d32ed6a..8aba453d8a 100644 --- a/docs/extensions.md +++ b/docs/extensions.md @@ -1,13 +1,13 @@ -# Microsoft Azure Container Service Engine - Extensions +# Microsoft Azure Kubernetes Service Engine - Extensions -Extensions in acs-engine provide an easy way for acs-engine users to add pre-packaged functionality into their cluster. For example, an extension could configure a monitoring solution on an ACS cluster. The user would not need to know the details of how to install the monitoring solution. Rather, the user would simply add the extension into the extensionProfiles section of the template. +Extensions in aks-engine provide an easy way for aks-engine users to add pre-packaged functionality into their cluster. For example, an extension could configure a monitoring solution on an AKS cluster. The user would not need to know the details of how to install the monitoring solution. Rather, the user would simply add the extension into the extensionProfiles section of the template. # extensionProfiles The extensionProfiles contains the extensions that the cluster will install. The following illustrates a template with a hello-world-dcos extension. ``` javascript -{ +{ ... "extensionProfiles": [ { @@ -35,7 +35,7 @@ You normally would not provide a rootURL. The extensions are normally loaded fr - Create a blob container called 'extensions' - Under 'extensions', create a folder called 'extension-one' - Under 'extension-one', create a folder called 'v1' -- Under 'v1', upload your files (see Required Extension Files) +- Under 'v1', upload your files (see Required Extension Files) - Set the rootURL to: 'https://mystorageaccount.blob.core.windows.net/' # masterProfile @@ -50,7 +50,7 @@ Extensions, in the current implementation run a script on a master node. The ext "osType": "Linux", "firstConsecutiveStaticIP": "10.240.255.5", "extensions": [ - { + { "name": "hello-world-k8s", "singleOrAll": "single" } @@ -78,7 +78,7 @@ Or they can be referenced as a preprovision extension, this will run during clou "name": "hello-world", "singleOrAll": "All" } - + }, "extensionProfiles": [ { @@ -92,7 +92,7 @@ Or they can be referenced as a preprovision extension, this will run during clou ``` |Name|Required|Description| |---|---|---| -|name|yes|The name of the extension. This must match the name in the extensionProfiles| +|name|yes|The name of the extension. This must match the name in the extensionProfiles| # Required Extension Files @@ -103,7 +103,7 @@ In order to install a preprovision extension, there are two required files - sup |File Name|Description| |-----------------------------|---| -|supported-orchestrators.json |Defines what orchestrators are supported by the extension (Swarm, Dcos, OpenShift or Kubernetes)| +|supported-orchestrators.json |Defines what orchestrators are supported by the extension (Kubernetes)| |template.json |The ARM template used to deploy the extension| |template-link.json |The ARM template snippet which will be injected into azuredeploy.json to call template.json| |EXTENSION-NAME.sh |The script file that will execute on the VM itself via Custom Script Extension to perform installation of the extension| @@ -120,7 +120,7 @@ The supported-orchestrators.json file is a simple one line file that contains th The template.json file is a linked template that will be called by the main cluster deployment template and must adhere to all the rules of a normal ARM template. All the necessary parameters needed from the azuredeploy.json file must be passed into this template and defined appropriately. -Additional variables can be defined for use in creating additional resources. Additional resources can also be created. The key resource for installing the extension is the custom script extension. +Additional variables can be defined for use in creating additional resources. Additional resources can also be created. The key resource for installing the extension is the custom script extension. Modify the commandToExecute entry with the necessary command and paramters to install the desired extension. Replace EXTENSION-NAME with the name of the extension. The resource name of the custom script extension has to have the same name as the other custom script on the box as we aren't allowed to have two, this is also why we use a linked deployment so we can have the same resource twice and just make this one depend on the other so that it always runs after the provision extension is done. @@ -130,7 +130,7 @@ The following is an example of the template.json file. { "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", - "parameters": { + "parameters": { "apiVersionStorage": { "type": "string", "minLength": 1, @@ -167,21 +167,21 @@ The following is an example of the template.json file. } } }, - "variables": { + "variables": { "singleQuote": "'", "sampleStorageAccountName": "[concat(uniqueString(concat(parameters('storageAccountBaseName'), 'sample')), 'aa')]" - "initScriptUrl": "https://raw.githubusercontent.com/Azure/acs-engine/master/extensions/EXTENSION-NAME/v1/EXTENSION-NAME.sh" + "initScriptUrl": "https://raw.githubusercontent.com/Azure/aks-engine/master/extensions/EXTENSION-NAME/v1/EXTENSION-NAME.sh" }, - "resources": [ + "resources": [ { - "apiVersion": "[parameters('apiVersionStorage')]", - "dependsOn": [], - "location": "[resourceGroup().location]", - "name": "[variables('sampleStorageAccountName')]", + "apiVersion": "[parameters('apiVersionStorage')]", + "dependsOn": [], + "location": "[resourceGroup().location]", + "name": "[variables('sampleStorageAccountName')]", "properties": { "accountType": "Standard_LRS" - }, - "type": "Microsoft.Storage/storageAccounts" + }, + "type": "Microsoft.Storage/storageAccounts" }, { "apiVersion": "[parameters('apiVersionCompute')]", "dependsOn": [], @@ -194,8 +194,8 @@ The following is an example of the template.json file. "typeHandlerVersion": "1.5", "autoUpgradeMinorVersion": true, "settings": { - "fileUris": [ - "[variables('initScriptUrl')]" + "fileUris": [ + "[variables('initScriptUrl')]" ] }, "protectedSettings": { @@ -207,10 +207,10 @@ The following is an example of the template.json file. "outputs": { } } ``` - + # Creating extension template-link.json -When acs-engine generates the azuredeploy.json file, this JSON snippet will be injected. This code calls the linked template (template.json) defined above. +When aks-engine generates the azuredeploy.json file, this JSON snippet will be injected. This code calls the linked template (template.json) defined above. Any parameters from the main azuredeploy.json file that is needed by template.json must be passed in via the parameters section. The parameter, "extensionParameters" is an optional parameter that is passed in directly by the user in the **extensionProfiles** section as defined in an earlier section. This special parameter can be used to pass in information such as an activation key or access code (as an example). If the extension does not need this capability, this optional parameter can be deleted. @@ -229,7 +229,7 @@ Replace "**EXTENSION-NAME**" with the name of the extension. "properties": { "mode": "Incremental", "templateLink": { - "uri": "https://raw.githubusercontent.com/Azure/acs-engine/master/extensions/EXTENSION-NAME/v1/template.json", + "uri": "https://raw.githubusercontent.com/Azure/aks-engine/master/extensions/EXTENSION-NAME/v1/template.json", "contentVersion": "1.0.0.0" }, "parameters": { @@ -292,8 +292,7 @@ echo $(date) " - Script complete" ``` # Current list of extensions -- [hello-world-dcos](../extensions/hello-world-dcos/README.md) - [hello-world-k8s](../extensions/hello-world-k8s/README.md) # Known issues -Kubernetes extensions that run after provisioning don't currently work if the VM needs to reboot for security reboots. this is a timing issue. the extension script is started before the vm reboots and it will be cutoff before it finishes but will still report success. I've tried to get the provision script to only finish as reboot happens and I haven't gotten that to work. An extension could work most of the time if it cancelled the restart at the start and checked if a restart was needed and scheduled one at the end of its work \ No newline at end of file +Kubernetes extensions that run after provisioning don't currently work if the VM needs to reboot for security reboots. this is a timing issue. the extension script is started before the vm reboots and it will be cutoff before it finishes but will still report success. I've tried to get the provision script to only finish as reboot happens and I haven't gotten that to work. An extension could work most of the time if it cancelled the restart at the start and checked if a restart was needed and scheduled one at the end of its work diff --git a/docs/images/dcos-add-file-json.png b/docs/images/dcos-add-file-json.png deleted file mode 100644 index d550b417f0d987e7b915346dcf777774d2803ed8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33068 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

;Gyhz#S8#1*~ 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 z zoiGyLH7!d`oixB#n|ggtcrfJ$wwX5I@*zN^^G-!(>sMpIF%~)$oNQNi2oUkU0>?@x z$G^hfR|!zbQ^ZY;e}h?ij?8WVkLA^Dxr@bI{Gg%>+X55ZU~vYW$FfFcMttcG|7w${ zW=-E80X*(+W$kOmkXsaKLUr<=xfrHb=C6kgqMj6|a$1rOCF(moH~9OFcZ;pH?aaBU zBLLCHtK8JBW{SS99eT*bTL?J;Bv1v(TqG>ZUrYoi_$7sqCh@KNw*~iZJT-8c?vn;u zAJsk|Vx9_Cdf^xlU%CGC5>m+&6K%eoI%3)zy$IsP28#>V@BF;Ji{qz-~26mVa97@*n_|7ZqQGnTRoSW%Dk}*~vt=N$jpzOp$W(FRqZ*`_~=@1-gHPaZ^K0K(;)5D>J7U`*S;~V^< z6Jg?`?ks{c)RHVIU^K<~aQ5ujTeE>_`OphkXTH|u{HZaVSB}^(Kdah1anKleFp6Xt z3{V7AZCX4EsGV%X)R1m=rD{l3vc2hh`_e~P#ae@D#GK_^`FW6N;bOH(UCbI*nHQ}b z3n2+roG0HKg*G2nNh9;@Oa;uZkxTs2-ijbu_{x4rpYyZeerP({0d_P?Nv)7~o`h#b zZqz~OKvBI};l;l}<(i^{u-E+C#a%+>8}-$3PbRE0oxem;BglJ&DtGN;fVGXZI!SU! zH%8N~ZSj;&01)~KZ5RN-;T7ltKE<2+0XnTJC*78n3x5xcM7N!EWR7cAT!$aW+XKs- z+bFh>kbd&sLSo(+pH&c-x0?a2N-}Zlqh)s4Pgr*$;mu~#zjBEG!7X64{l)M}%d~r=gRnKHz!su=wQH?{>A>}P#fNV@ z^D4PIMPBJP&n^zCOymC?aU}$9c6BOxGV~skH24W4C;d5nPvy?bl*YcBUmq*C?bu^) zJd!sx+TQLPR3-Vw8F;E^pCv`$m82A6Ii$Uu%ygoYH*}2|d6+%#RBt1eqfcNXSn=dU3uD`%W42XFDR)LptN1jE zpheAXBhkjH5)_Dh?!q_EfU9S`p1B+J3y4Wk7h0|x{|95d6Hvl zI3m04!|`nM8zlg~D7a*=_px7D@3plOE#(c5)4A<*mEGAp*-;0Xlg^vd?k%J5c@C<| z5%@;5iDzUPpUhma{?g`Q%gNwpQ~{%C`J0e(bs6i}@JqQFf`<6L2OhnMybL2~*@pb0 z+eJG4Vbyi&I~#Qs#aT~ZWo=CKf0UKUX~+*=mACnIX&gHHx?e4q-gM!8`^o^I4*7N# zHrH1?e_r|qVg-{q@&pEoiTP?04<|mB)>Y6&tImBKT93BWg1AN%fsC|gvAiT#%5WWyfdc@P<920CTM0GnpziS85)>UdhCOqWy3Y`_ihI(lss$a<6B4vB! zT|#ytJN%>_mCThTp`V!Vqve9YhUMcHN!di zJgdZh&=2S?Pk+D_HdAeZG^;bgJ

Owh?B*SvdB_&gZ%ULk}p;a^{qw1JeYN=QB=pR*$Tc}!&>WSFyfSrTZ1 zz4=KcKkN+vfrj)anr~-U@|$4z^EZ-6gS3i-nUer zXjcNf{-tQg(AcRM^s_zj6eYZ7X4Cm`-Or}uGr{WcGYo`<^bFYcE)Bre&?33h9Luqd zMtMC>+km`qo6n>#XRJ4m=TXL-*h#=rw;sn*>165<+XM|?r^HImbVJxyb(~H@9lt;N zEy3EXcw`cOn5G2miAw+WdN_NbY~c}upV5$kPe<*vQIx5mipP0|RdN8G#B`9uq+;a+ zP+@#~o-*rtu3cVV%KU~sSSV!5g6?fr_XGX7%-)*2|G9z<*0#LAWmG-fc(Xm-=I*2B zI@H{=k@2^Zw}Z8#nu2S}`)c}mtAW%0vX4NoLrjYt%7JA$hLS6fEQ$66*HT}+bp-~k zmwOqm1RgXVb&Mxb-d@%77#JAd6S!97T5#YJ18?Q&O|1~v0rJ18L&FR}O|Do}z&u-w z5a~h!3&nf?4Fnh(#l_|yrxmLIX_fGQUUAW_aDVIXxrc|5sXoS6|FM@)Q_@x}mA8EJ FKLG3#^UweQ diff --git a/docs/images/dcos-create-service-json.png b/docs/images/dcos-create-service-json.png deleted file mode 100644 index d550b417f0d987e7b915346dcf777774d2803ed8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33068 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

;Gyhz#S8#1*~ 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 z zoiGyLH7!d`oixB#n|ggtcrfJ$wwX5I@*zN^^G-!(>sMpIF%~)$oNQNi2oUkU0>?@x z$G^hfR|!zbQ^ZY;e}h?ij?8WVkLA^Dxr@bI{Gg%>+X55ZU~vYW$FfFcMttcG|7w${ zW=-E80X*(+W$kOmkXsaKLUr<=xfrHb=C6kgqMj6|a$1rOCF(moH~9OFcZ;pH?aaBU zBLLCHtK8JBW{SS99eT*bTL?J;Bv1v(TqG>ZUrYoi_$7sqCh@KNw*~iZJT-8c?vn;u zAJsk|Vx9_Cdf^xlU%CGC5>m+&6K%eoI%3)zy$IsP28#>V@BF;Ji{qz-~26mVa97@*n_|7ZqQGnTRoSW%Dk}*~vt=N$jpzOp$W(FRqZ*`_~=@1-gHPaZ^K0K(;)5D>J7U`*S;~V^< z6Jg?`?ks{c)RHVIU^K<~aQ5ujTeE>_`OphkXTH|u{HZaVSB}^(Kdah1anKleFp6Xt z3{V7AZCX4EsGV%X)R1m=rD{l3vc2hh`_e~P#ae@D#GK_^`FW6N;bOH(UCbI*nHQ}b z3n2+roG0HKg*G2nNh9;@Oa;uZkxTs2-ijbu_{x4rpYyZeerP({0d_P?Nv)7~o`h#b zZqz~OKvBI};l;l}<(i^{u-E+C#a%+>8}-$3PbRE0oxem;BglJ&DtGN;fVGXZI!SU! zH%8N~ZSj;&01)~KZ5RN-;T7ltKE<2+0XnTJC*78n3x5xcM7N!EWR7cAT!$aW+XKs- z+bFh>kbd&sLSo(+pH&c-x0?a2N-}Zlqh)s4Pgr*$;mu~#zjBEG!7X64{l)M}%d~r=gRnKHz!su=wQH?{>A>}P#fNV@ z^D4PIMPBJP&n^zCOymC?aU}$9c6BOxGV~skH24W4C;d5nPvy?bl*YcBUmq*C?bu^) zJd!sx+TQLPR3-Vw8F;E^pCv`$m82A6Ii$Uu%ygoYH*}2|d6+%#RBt1eqfcNXSn=dU3uD`%W42XFDR)LptN1jE zpheAXBhkjH5)_Dh?!q_EfU9S`p1B+J3y4Wk7h0|x{|95d6Hvl zI3m04!|`nM8zlg~D7a*=_px7D@3plOE#(c5)4A<*mEGAp*-;0Xlg^vd?k%J5c@C<| z5%@;5iDzUPpUhma{?g`Q%gNwpQ~{%C`J0e(bs6i}@JqQFf`<6L2OhnMybL2~*@pb0 z+eJG4Vbyi&I~#Qs#aT~ZWo=CKf0UKUX~+*=mACnIX&gHHx?e4q-gM!8`^o^I4*7N# zHrH1?e_r|qVg-{q@&pEoiTP?04<|mB)>Y6&tImBKT93BWg1AN%fsC|gvAiT#%5WWyfdc@P<920CTM0GnpziS85)>UdhCOqWy3Y`_ihI(lss$a<6B4vB! zT|#ytJN%>_mCThTp`V!Vqve9YhUMcHN!di zJgdZh&=2S?Pk+D_HdAeZG^;bgJ

Owh?B*SvdB_&gZ%ULk}p;a^{qw1JeYN=QB=pR*$Tc}!&>WSFyfSrTZ1 zz4=KcKkN+vfrj)anr~-U@|$4z^EZ-6gS3i-nUer zXjcNf{-tQg(AcRM^s_zj6eYZ7X4Cm`-Or}uGr{WcGYo`<^bFYcE)Bre&?33h9Luqd zMtMC>+km`qo6n>#XRJ4m=TXL-*h#=rw;sn*>165<+XM|?r^HImbVJxyb(~H@9lt;N zEy3EXcw`cOn5G2miAw+WdN_NbY~c}upV5$kPe<*vQIx5mipP0|RdN8G#B`9uq+;a+ zP+@#~o-*rtu3cVV%KU~sSSV!5g6?fr_XGX7%-)*2|G9z<*0#LAWmG-fc(Xm-=I*2B zI@H{=k@2^Zw}Z8#nu2S}`)c}mtAW%0vX4NoLrjYt%7JA$hLS6fEQ$66*HT}+bp-~k zmwOqm1RgXVb&Mxb-d@%77#JAd6S!97T5#YJ18?Q&O|1~v0rJ18L&FR}O|Do}z&u-w z5a~h!3&nf?4Fnh(#l_|yrxmLIX_fGQUUAW_aDVIXxrc|5sXoS6|FM@)Q_@x}mA8EJ FKLG3#^UweQ diff --git a/docs/images/dcos-docker-helloworld-logs.png b/docs/images/dcos-docker-helloworld-logs.png deleted file mode 100644 index de3df374ad763122d4908eda4dc782b7b9656cd5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 167804 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%0A}Nn;Pdv#3o0hV8Q87mQWzJo9 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

XUWntrQA|@G-(A??G_4|h;hYm4?lLY8473P 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 Nd1)1?8VQq-{|CT+j%@${ diff --git a/docs/images/dcos-docker-helloworld-tasks.png b/docs/images/dcos-docker-helloworld-tasks.png deleted file mode 100644 index f0883d5c843dc46224429c2c7bfaafaecadb68f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60025 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

    &2LfL2_DbsH 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 diff --git a/docs/images/dcos-docker-helloworld2.png b/docs/images/dcos-docker-helloworld2.png deleted file mode 100644 index 62e8a40627c3bfac28ed48f855fd295ee3870fa2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59188 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%0AJn`vjA>8(_tJ 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 diff --git a/docs/images/dcos-running-service-from-reg-files.png b/docs/images/dcos-running-service-from-reg-files.png deleted file mode 100644 index 50e620aac6010626360191bae8496f97315280b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25864 zcmd?Q=T}o*)IEv?8wvsf(iNmg73m;EsRGiZNsaUxLhmFhy-SVsD!uobi1aSK1c=lC zAyf$^g#38k`{Dix_r3Ri*yEgi&e?mfGsZ4!%{6C)mWJ}92MiBLNJt*3yjS>0LUMEI zy3pObdHrOJ)6@IM-vBHF0E@=A_s4`!4Sd-APE8!~QEb z;x-PgNl2_RRTSRo`j}yt?gk_&{_Z>Upt||u`{VF0|5zfQkbVm;{gxGOt61%_9O37e zvZgTht>d#lHY=-WH8+d2lUz04EacDgw_E%-s3zVA+InX_)Xd_ack-&EJ_`hlaSb2u z%37026EjoM^M7k=YoA>k@hJEy@!H_q3@x`wNVdM2T;F@V6SzS_()tW`{o3@q8VSi4 zfqo7WlDBm0R3s!hWN!CKNdA!izxZ=S7em8T?b}-HI1u-zGn9N@wfmB5OE)w$7X0!G zhk(atkdlnVt9?mhr&f8?O{vV5^Id~vE6(KR)c2p+Ea}pqCLtXGz885KpX&MgIi|f! zB@8b4xkuyc9*p1qa@EiAR^8zr54|Iu-(nK?ndhgiCLMU*M3PfPg8pxy5Z|BHknf3x zyJdHt=18SL{D!%w-=ku5EQ%a12S+{oPC?w?H;f9n31Kg1&5+XP3qqQN?`Bqfw_P^x zy9m^XCf+8++fzmK%{|Hq`w~nwu=rkwG5rHA6t@pPjgZi*M)yIX?bUxiJ@^|<{nx~e zr>VZYepoZHhT>U{E>~=eFvqi-5E6KTH_sUN4cp>`Z_)f^DWg}eqqD+L+R0&7sBy<^ z^L8}dUz3men|%Xfi?=msuortJNP!P5fh!Gy5ZI`}7z5R>UMdylw{HbT&*@}%4-%Cm?VaberBGz6pyJLR^;=DmM$jwoNQ2S^wFu{#lbIV>o_ z5oHS}$&Pb(sbl5s@r#ki^x^-OXXKUh^FobqYZKEL9Fw%4M4!ZJ@ei9Cbt%)u{m8Ff zc(2&|Ffzxe^C}z>{pS2Fo6_)#>%npC``x1s@W|!np*4{9st>dJ;%S9DzTKzmX0aPtXj3C z3@yBZo;Q})=6v50qx-j?s%1!{Y7 zKWII%XG^*rBEG#?R;%?fp~H6V5;#-HJnO*Z*@?sAt-0@)WY75@{MDwTV0l@nR!XO; z>gH8tj605$=`#^0RcMl~0uQz3tqyBwnx@e9J3Rl>(rvC4F34ppc4#(UI7SRuO4NZa zn9gH#GJv{B+0F!IqPvyO;hl2i%6rX~X>z`oiPgn73Mj0`;i5 z3wh_b2rvyNr}pDIi(FUX%iI_He+y}jXRI^k$6r)}(o=-YpTFxg7eaer=ej=`r6=#A z&iwrKdGzkTTlBS?kxt_+{zDhj#B8&KKo{hM zubM%Ttsd@^e7Xl_aZv1D#n!=04D#k|1KnRp27&SNtgtxy@j}jo(i?-DN?dfz5OL&OH5grM?tE>%zghnfWa<@C1XD#ptRolEE8b*PwA@XQh)3X-PC;^T&< zVpl!3`{r9N(og6c<;m2xJhy!-*5w3~pD?LtF4d#orueBLIVAS`;#F})qlTVZ0gM!C zTd(q<7;a0~n9^L61kY*-yq$_lt|!n}56oLZ&HPcH;fW#QC?)HTx*Vg(ePNr@LYKp+ zrbU@9NW}1gjb%1u^=jP*@1`6QmJ)b=-YE-Zlou$mcHm3%iC2@83o`PknndqhQ}3=_Uz{JD3=pVE0KH1=EaZC%k;;h}?O(CXkr> z(0DEW2@@ry(I-1-xwCsj1-t$B>WOl<%&n9mLYCTtdqd5L!hP?x4n(j;3?XcTDO%M0Ir`Qc zQ>)%Rw)j~Y?MxFlzlUeB?D)8Ws5-@7jx6Ny>bqI9*X`b9XwkDO&6umcINU_Pzdqni zw?4O2^Bz8%h(8ANird;Cukz^`TUKhL{9m-55q`G_o

    c{q6sdMeVcN2#fY`M8K&*q5lT*GbtzChQzF1@0sVoChd?oUio3&ZUs zX`zRmNy#FLXAAWDzOvtmYt8}5S?RGlTH$RDal}MY{OR7I#XoNd!It;(mD!~ zA&-0@e!1TFt^+h0_k?w;H#+D?clDfm`(T%SHp*@CpRRw+araKFJ^$cBt;@`A6~wU3 zzUk77TXu46djdgZ?Te=0$wM#XF0~!}sRg61>^2vt%HPynoUgH9M2T146Cm$fx!7!nLm-#m_zj?N>G} z!&fyCm$Kd+7fQ}$9Sh!=z?J?aKo)92lP>wdF)WsgAW?BKWj_lj)sA{)oQE?q`~yEJ z5+kH}uYPIMq!Prt?k;hAA|JJ%6vo3&G$VyOBG3KN9irzk+uOL`?OL zKAJ4dq{V)DHZ{JZGW+aTcIc1gt43EN!S;h>nW}p=mcW4ht1B954~I%tE^fQi{koaK z*o;=t9h14bn!w!W?%1j_uZ8rhbdL^+`IC}#aUFN6G$U@{(~*Jv1Z?bh#FN#H?M3!ks9 zc$0K5WIh$IV?c1+S)+ioj9j}(HEtJyvl`7S@neWjEy|%(@5*aI8&y>@N2gKFe%^2= zuxE~bM&oDW9_Mc|LpEbSE=DIZd#O;9xzh#B#k>8ndFAqE0g^QX?*+{Wo})L2rp2#b z*sK@O*+NCO3v+4YA|6j$^b_K)YU(oPrENz)8oJr!-s7mrXZ1g+K%~h>JRZOHNMOX1 z+40`H`w`pO0d2~(w^sTinATz#^#vO(Kv+5su10?2%gKrQrBun+NpmSQo2-C(+mlNa zE$DE4_e+8$(t!Bd_N1_btJcb{nxA)2(p3a|$^j6ZhYSxjC4bDsqOqn;muSf{oyj=G6U|pG8Sd9ugA)7Hn;#?q*YbO0xj}Y8^~}=wt%s}eNkhYOSPwShl@vA zY)MZx&^D|eG>wIzSGyb1WdygWFPrLAyQrP0IM#Vv;NP0|_8naJg*a^P=v@RW7h>BB z+x@(kUP4jYtZgl;$kt!TMSN|xXb*wSM8&LAnpN3bgqg!mB?W~lzf!`;8X>p|^|3K` z)Ip}u>4`sT-n;@d%ItL>Qmfnk`OxhgI#H6>QwC2Q5N)5$xsgTjndbv>Z=2WI?>MUd zDB!d7l{?;4BnQ|QY!ky46GHxa6YkL^lMRDn8X9oM3_HgYkY-}zEY#Cy*zg$GW}jem z=s^ap>%OhVzr|(bv2_~>5!%@r&AYi~6vr|kt=+oUwwO6|tTtFCf_NH$(J^Rt#_UM= z)Q|s4sxwD#r*J9r_bna&Rg4%#cC3cIIs0|b(yDI(wFyf8$zV_mp1qM@_|TEb;ObEi z^r*4wQ{9RS+-E?ZeP=2v2K3aFOD<4`pZ`s*=Sb;Na=_e1q(}7tWH02*jAiMWtQZfE zTwo)NhH0tAY6QL$V5V=0_eH`4j8h?UnMsaq#m+%_nUMCIFBBkoeP*8h^U2?x&v?gp=h8_SvoP+i5w@TLGF;GH^Ir8@{AmN~Ar$?A>#P1@WOp$}t-+b`= z=->feh0*ToA5SVjwd(dJ+<`q}SvfSgPZ{d$?-ddttRy12-^c|t5dkt0F<@ETuXNT9 zaSU>-$NWRb&wWXnGFTppNPsCr>Z)jFM9vqQ;FliDv-=&yVU(EFN#$%hSx074Clch zEc(73To;#ORY;eti*u&-o;y=p4xMjd8+jUab2CF}qiBMzMcT3DG`I#WNx|W@GB9Ak zF=%lSd2-jPL@7CAuH7jeTTlM{MPuNsd)dSnY|OW7myqSmme2hM zov;|DfOm{*MkR<^XpabGxPP(Lkch{Ga$PJcTN~h}-%f?Z7dREh27B1%;Q|wT)D@)a?(O_i^V_mS z0>7oodynX*qN=mE&I<`N{&nmAz&8fWe&np8PE$QWVUKo2?fU=5vnyYkyPRsM=UK%V z`?(R1HjwJ_ObniFe<0chLJfk%rTtcQd_M>7<tF z{9(t*3SFgeO#4eC+=6A@?tR{JeDhs^pZP8+jmBBM=oI2?v0({&SG)OWNRuvo;fsF7 zxrW*A%Fb}*?7DJp1rfVxOv2DbrseQOh~=$;oOQV90Y zYi7H>=sa6% zG-88xUMZu)W1h#qQ`<|UTdxTqF*Q&78&A$;6Tmr)x6YcZN-p2gbr8Zv!pcT zF}Xwt!Uh^v1t8}Yu1hi)rFr3Fq@Z=P=7E6aJ~J1B9DP}D5!3M*mJN{lr!c>4D zu;%=2A>pFsxu*s4gkItoHe@)EvjEa&W|}TxpK>2G@v^4o@V@DH&kv3FC1{wCh3S*1 zZ}-*hxHQk69M#6Wd#Z=tz)|eI36O&;=2MMHBO0Qj4Vnn&nPU|iKoIWbTAc(>snMET zS+3RTs0T9c=w3Y9Ykz5eL$W1T-S6MdQ?Bfq)oZNFcPUhlJ#VMKw5s{+-&=YL1!aR% zKx{TrO~I|Y-sQ~ebwjK~W~pH5l42s@;^3I8?_nLGx7A9GivlIGH}MiBMZtAzBckZ#%C95EBXQE-N^xzyBbIy14Q);v17_)77eZmd4E!&QX9;F& zUCbvBIaFQ3v8%ysnd>aPl8sG11kDz_SO$+*vqvprqX=@+1klKMbrNR1T?njt;&dy{ zDd_8+Gw8EWVu*rBxMSiJK7o?X!&~T1FIsMuTDt8bjdi}j+!t-Fk%iHsoG1<%a@S&` zwj44RaXXG<{K<3VhR5TWlI%sBU5Ci`Dj68k<^*aOGVA9_Yvo@^@q7+a!?6fKY`9*) z4QEvaz8f{UV+xf_6FdWe4I0LWP0dGNv>VFKg2Tch?5J4w2*hXCOF`nr{cMet70#3a z@1nQL4UB%rWZA}(1G$p>K!5Bc>Zie35^e2FIgnG0Aa&}BpAd-@PortXdXH^Hz$s6A@+I# z(lEXsPV~ti>^g{_+8j zc7NL1;Njmg?+lCHexX(dHMX|5o2zq4jaJrUIBfOY7g+23XP3C{yDa0e`d!_Ch}Z;u=d8b6@0WT)x6WOK?(L zc|#lEz>Dm-td{fED7-glW|*}|m3iouY$^Ni%OB)B4Lj}|TTvS#7pr8W`;WogKi; z{4g}4)Zkp6W=DxZ)6URLqoO&(#jLW)^vm+0zrai0`#6-Yxk$w1z^T*r`oM)#Q1vDA6cwY(~H7XY4S)IwGPJcrPR`%FP4w`QRjlKYI4PEK$)oByn z?wMnW;knmJz6%E?DiI}PuOVBetTMu-`G=^6>&-iFmgO9+$PRAa9;l+-KT&)0JjsX0 zabVH+2%G9NWD0eAn#@O&1{`siYXo(;`j%+$N2iEF$zq~G%Ppq|>tZn*?7YK^%>irX z0CHzZUaL$VVk2#{S2Tm0NY$IZ&|tr$pN!M|6n;N(f`6(HzykM6%gcVIB|0#;%ARxm zm-yZ&&-^!gVe+yQeSvT21=$fJYFa!d^xI9 zQ`OuvZjueM`p8@~RlV`+k#dFW^W=cI@`}8?Xb6ts<1H-5RmLu24DE0P+^f&%4?r*mG0%-&Y4l@phPVoV`;s75L{@nYS{z=(s z>2=;iq4~A>Z373~gv7p&YLK_aE2gqwbE-W}p(sskFmmIZ)gtRcn6h;00o(4KP zBAz82Iric$YvZ1|3ZEPL^o`2ISa|Ji!$apTHs)WiDLgWv=ehh1=?(dS6EL>9op|Ip z7M2a&4lgx5VSk=`X=~EB@9i1;ow{axqv4{)Qr2f!+f_y0*>8PgUYIp|YRoQa@CR|( z_(;kV{u$oNn_ECtBuzbA?lvRv$>RXlwESsxK7v$I7#KL|THKs;9c{h@4#Fgy`kRMJ zCx+3yx$3PAVp4W$?%trq)vHGaA9we5x7b)uoTfjzdJgeo+HZ;%NvLrcZm^5AKeq1v zmT`20UzGoKY3%s#blBPe_|9$X4Td-|zE-neqtB0i)f|xxhJ{YYhcK+7O+Fgw>#vTL zSlo*6e4up`Py}Mkw+z_05EXr8!u`g#d*kSJ*j=cRx#I_e*{rIGaDx&Mta1ZA#Aj5H z2ITS7C==+lmJ;U!uGRf}%rbf03d{PjXmC{|m{qrcyX6CC%fFvn;8p|`;6X#j04L+G zk3C6`PX(?HVh^jvhCeuM5BUCGF{f=iXJVSV=&2% zo3X?YvHj&`3FABwN6j7DzM=0~EOF_H=*@0q`LI(QTspgkVMY|5ot*Us4ooq5Iq%-i z5HBZckRhd4moJ=r_T$rwdB63V9&JNux7b!~6<%`Jhdx3WLJOW7I$VtNk$cIlvKic`DrVZH)(i zY0(w;^b!)aS5E|qEi>3b#8X=}QtL{8>{Wz3@c=zkRjW?-2(cFl9sZQaIup3ML@gt! z>2o&HsBL)OhVa?>`kWn{#Mp9K$|%TmHQR!Xg9+=qEGz;{q zOdsrc6^JX_9}~A}pAGC6tySLsTl*7HWr!;a+;yN)Zco8@ZAh#=co9NIl-b7Wu_z^8 ze-+d?0AcgCsxoHDkb+0qa-GaD z;(jIdDR<8=e?B*KW5;U}bsMm@$!5e^nXa2t`X2>2OB~NPrlaCO#t7umqh`gfr)%!Q z#Qs?9C}j5M)faz%lbGTGvT?x%sxpa+lK^LBiuGYyjCNY4+a zg)|_W)vu%jN5pmZ+qO1m5wf3Fh}eO8@P0ESum2lkg#q6HO8T?{Eeo&^oMrTdJPT!- z%DLQ~@I-B1$qJw9RuU42ggF$g!y0Ls7xZymze`Y@{Wz?$+Ji3U$PPAU$JhqaM3mbZ{1+IMyVZ>!Tbol}>czsw7`2bho>~WM$wA0+%o#)+akTifkGF~rly-PJz{&vY zucu^%$LuiPHFkT=u5(fq_djWhnA(3Bo%|T!J4WBJov^Suwd8>d-=nRj%_pRa!C^GC zGb62${GD36@8SKisopQU&D643Kz3ERE$^=b|MyDR}43F{w&e%5&+4!c8 zaQFA!PTa>jJTfn6bc-BGr$OSoC79^4P8IVN&nfE4i+kO=EdO=uO;o0s8q`{4rj&?v z5;VHhp4po&%DBp^J`;0YeS5gvP~`Tyj8^q;Nq>rr5o6GuZ*Jt}Fg?YVEnJ6yoh|Vz zxTJs^@iz%nJ1x^0AA@`-fjF68HnN~g`(u6ZMeM%k)O`HUkfR8m@3}7|T2=5j1~Suh zk9P;UgL_{`GXdbzTKt@=rsF&9xdbE!1K=rN2Bf-3Uga8e6hKqB(y0EcA#PFPh3O}X zwXG3sfBmoXqK(E?Y%&6&#I+XIC7Ie)OK1Nj9RLF0J2A34FWaH25Y%k5gpbbl ziNhMUI%-Ys$Yzo73RE0b&m`pKnDUb8Lm)@*jmEcaMrw1e$yIpqCs`6&Yz6WcsQikYJg$J)@BP+d4;gfIM7`hbXAb29#c zIJgCXt5rfda-Gi&7~X2uvT{k~nSTmb9&yp=5qShc3hw+((dom{WDg!*5qC>g7r$8; zx1G$-$K8@ib^=PeClWq}nR%N%Dd5kjTPuFQLwUbLK&pzSrCLhEDYebz^!}lhQsyKv z&skKawcyTz+NIQuhLC&Li3nc9Fx8oWM0Xc8ZBM!TIYshZLqu<%!10TIFXpiZ?`L!@ zOD!9G0L8X6)rlt7>X3w-YEIC?YydaqWu{uWj37MIX=(Q@=&vFm7SP{I^_HFEE;*BE zvshRS^Di^5p(_`=^@Ek$ zTUF|Dp|x5goQXSRXE#VreNqQZ^X|AJ_CNJ3*_vv==YI-Hh_~gnYWfk)*+_X5a<`FRO&U|>WMIt^HVazztmWh8mS|LO zV)@$E9tm| zormQ@yiSUbMce4yQ3#@3@&~_;ih>DxZyIpIUJF9)fp+djjj%4m2e8xo=E(?mtSa6b z#YVLN{L>&cn_4VD%!*@oN`;+b7-jL##X0hv`#lB4EB6C|FSOic178KArP$*YLZ{29 z^(W~BwTf2Wi~7DMAGIhFWVNNHqNS&F$nY^W`K0Ak>L-V3kU;?BZp)6Duc2^Mxs%^p zVF21$z7h=u-EdH|N<)#~VJ---ymVl6Gxv5wNXvl2dJuzi>or@>nViF8HK%Z@f|c5} zHTEUH05@Xv$IGPK%3==7(ji*kCa)o$n{Pi|Y}d3*dNB%niT-i1u;-*y;NFII&;oL! z>lCzSIy1M!C|ITAja@E`c5^8`+1T<|8G5oOcNRB=8ZOf!4n*DVYsoX^M?9N|IKy;( zVbgq18_|6@Y$bP}gzz7|b4?^|>Wi2RgPD)~wZ*6hKrD^OH$5e zT6!lir8^($O+Jzh@_#9RF~dy!>=fAIvpge~M=#A^Eq_WK#P#$dwiJ zYOp9|CZ>W8d6uzfIw}qR{BgGVy`^goe}MNy+mPCBPk}Mu$E!KB33k}}NXKb+;ZkpO zKCO4AuwVF@IP|JujnQk4uA%%m%wW}MA*w+TR@|hX%?oI;%n76<`OEjQYfVk{NW+SG z4t`#gI+>j*vat-at$bruC0h0z;C_6R3WOhYv+wi0O7Y1B4ptY;{mH4mP_ax%jInM| z(~aY0V+j92M?bMwdPj--21!oiAygm&oE-3uLh{5OB_Sa8dbm0FU@MfAD8A7k*rdyw z#z(yDn6(v9Q6H-q)&DJR`ucpMB>NI`H~`%$#>_?k4W$ciVsgq{U5id<R;&h!Vo5zu?X@`*2Jy6K3k>sw!P1UrIIsNj=U&Lls4P=U-NaO5kayiQHyP=P0U8*4_j1|ydTFh2hp)!NMuc#BR-WB#Wpf6k8_ zcl*T5|LMKtXPhnUEbKubl3N1a8J75*GlqC&%zgfc5qc>eJX_b4$VBAv$K7OiA*~q8 z0933eRXkbTO6Xq?V>CNf=pf^qvR{^xn1lHLdIBP#j)~`PQ8L=WijBKce@k8S`(k${ zWrTi1-1iFUv)k*QO`4@dra&(Ti0gzPHio8s-*eG?F#S@KWq<;%loTOlQ~pR8m0rV( z)Q@ydd~MS1n?=OW8CR-oBiUZ(5Y0*c4%5xW&G$YU(&Ul^jcH~RJ^ttmg>sld#t78P zr`rqVC%#>kep~P;sRf?Vgn!wPbTD3Ev3>SWlDWK&5&ZyXv9=nr9JDjN`02^A)jAdm zJw8PC#b~rt+hQ7J@IcqeB`E#GABgclCor*`+H%y>$DC#hfQ(c z4BRwrbU%o$tTYt#6gVvJBI~PRUUb+5m>sWyNBeq#cG9=5 zo9A|uDHYYg3~}yyWO13Gv$bqee}NGDM=RYCRIT}SHrro^el~*)BlfTNd0~@+Phzh4 zL##c$mSsYArfH2{#Z3D!iIy6v7_5L<@)|z3#xC&p*(-2*?ikiQxChRf>ozO?v#s+I z88W+hb%dY*_~C!Tu5hQyob8Rni*TUgl9VS|106Z^^hhTTDuO=kDC~TCwXu7_(eZom zZnK|&xMdk%Fek2ds%E^Vmu6nI4mWpYpZbK8kvcMEGtg@+zUBDXt#rA2-QUpPi(W>M z`GVZl&V_7${%0N2Kci~Ps(|cbaXqcEtXmZ-5`{f2M~G_;0L0zukDm8{CyRF9ja4;O0e0I24MB zF_tm-=rYA!jxTGlwA*I$)oF2d4XS#S{I1+e^RRGMBfw`ecZ}$1p$QMv&S8?Y2So64 z7aPjC+g8v$vW(t!<<^naJt=fp6dAAEj4c?4!pl>c%0BwIOqNriTGlGLvM=o*MxR;# z=VwyYB2z#>+vsYi`QAnAHEKgO;>jYN`zdX>j6!!4lZ3+*Kee;p<-h=#!2UDfEW%** z?(+F1iYV5qHpHC|A4Rrp4>bV;4p6+K-BDenP4LD6e!(fwtf+$QLe95|e89#?>+!*F z^()Da#Ui%y4)y076!{-lGOOB&BVhup3-H_zT<=2qngo7`ZgkGt>g^wOlaQR={Go;; zNPq*gI-bl__^al1Jb7Yd<}ShjL87vu6XzcLipj*A!(UPQd=1%J+NbTjWM90V zr_XVXBUB8xlNTzFw3%1bFJj>*+v3>)xV?CJ0!}5>HXwp zM>B8PpZ^k1Ya*QJ{09=%iI?WPU&^|i0G;d^+=j$$S4TRNm=c4&r=_jLepy@1^Fuz% z5AVNue)0@;$QFL-dJ-D$Anx-!D6Sp9(+!B*u@K3!+Q0DYt-{F)kbD8&=7CvNX5qGH zksB@i>H_p7egxwtyXR$a%Qo_4F-Nc1$r6>IK}Lf{tf+>bJ+dau-o;jHCM!s`^`@d# zR2Dnuv!# z-KHxvm)vumY9H|I%=1y-v_2c?BCGfTO$ z-sEh`)a*I`sRS@?smA3pyjj>I;0JO`Nr!9$M4Ntx;2ww#pZR75XpQ*c_U#43X%-rj zV-$SV(1EqRB72h1Nn4_+Ra*gAQSqEK#oNpW*<7e}?awOb>J)wuii9`dPpf9~r=uv^^Cvm{*y$Tb2ITyG0dUG?ZSNHNh%6&9q8DTT>H7{q?l95)> zs6!g9JGvs%=Cx0yvr}p)Y%?tDr=f~Iib}annmJeNq|%CQpS=u}Zrn)9SU^BFOVr(@peSs??1^k2$L(?25Y*j+QCtWoaR zsBhn5K?Lh@XJg=>ZGQoObY+|kt3-Tyvd&XV4>xqE^|4K$lsE8e1^ctsF-3z+?^vvc ztX@3^{Vl(-k8;t+r(=fPHk;d!(XDa5FF?U7W_P^el3snxxaRk=nyYj7IUz=^PPys6 z>^Z(9zpqD%qiu72Z;)>o;I;E>^rjHjEWU0PVJIz+@vasZ*(Dqu(6MeZkG&ie;3nhe zUu=0}yOB=nzsvvR`4Z;gQ>Kme3D)WLb&zG2*Ao%UL@h+i1mD|J;@D)9OqwZmg#WgI zp|C+)GcPB$?hM&aB8<|l{ePK9z))fkt@iPkPv_a#9OoA@8_l{FO?guUHUA5xJ%%P& ziwOS9gXR5qJR>#cj}4Bq=zyOQoT%8;syCOu4k>dE?+iZ;7(6Z^mSd%R7-as7HNQTA_P0I~RbZ&MsL8O|Bo^Wo=fvdZXSONnv*G zxA)E#oDgoqPINnd)WH+noW~DP546Q`;=kul{@yu7n15IU$~F>ZHLM0fW0&VQk*gq} z?Eb&?s_MBtae&A1XXqOjk}swsxHScZK2e96z_Wuk7N5(dBCscmYVbj>^gOwbzA;{R^t$Gqo9`<}53|hJ4tb0iH)1Qm%4Lb%oS93cc@snoPT+|EKz}De zW#4$cJ=GUFiE+1K+Yxt|@t$HWYIj3$B;8xd6i5|0*PKmXra;&4`yT^X+J%2+5xkyr z7Piw@s(eJLwTeZR**eYQ;57RkWyF7r$H7!22ZD$O7)gWNc;4*(rC&=$N5zJyCK2nl z*8Ym*?dRJEZ_J+^)TTHY3rgQuOK*6dMDjK#Ud=`9efnW7<=-ax zBKXJbKP@(8yS-YPcCZa3@YNvqw!>WAxze@%8kp1Zf6KKyn+^WcWiR}HPpSRC7Ki#@ zppfq_^**u_>bST*GT&UoT`&J<7L9u=bO?}@(TydM7HtZAlG@HiE95Glj%FdOevj?8{7Hr}U=eFZ-kvLEy{;l1s74HsAN9^oTDv)lMnw?e~^c$2e z#Od%BLzoOQ)!pg%2ngBNyLDHBgF=l}gFAkhVM~`5TE?P`iET3Ql4w)_;6xUn%>C*;rpe^cmTzuqo|u zcSYXlW7dn()`V^<1FqyB5z-Qsn9xbB)#o*p5-*P7>+eeM+C5K^u4Egus8D4!IPoGvyu|b#%*W{8V3uC0A_u3oFBN0f&2snR*{eOCKA%>x4wfQ+Yr3 zHtX;y{LvlR`$!;MeW2@@EvY|HQs({PZp5|^>K7KK0uX|dpb3P&BR#fzr~4c{!;TT0gzWS)QfHV1R^qa@X~ z?RR*)+cQn)svRFrGfgSwjQVhgO#5+qg~PQ*6}}$18KfJxbXe9XWz&-KKUOwWtW0%1 z3FCnke|rWLbiI4H^CSE2iA4#WuImX^8BLG6Lxi8v6qV2bN5Z*cJyXzJ^IS-K`kMLs zN|sDN=1jQfv|7pX%5}_j`9tltp>hAkTkY(>JNWuyMyt+`Ds2}Gr3`Wko)#sL7kbbr zeu;`#-4z-J9xwD^Vb9ArTB=nuDvMcaH-z+CrT1ey9W}CL40=s%AKt0es)9`h891iO z7w|+yqPh$QV^p*CYRG8RO+@P?13h+RcI$bSIo)b>PTX#hEFOaeTo)ea$##yM#GLKY zLPz*{9cZ+L2fpRO&ss}rbop27e;*v+%OvicD55ZL|2hC;DlvNlbv)$qEV&#?yc%&j{PpWP>KxppQ!!Ou>MMC1i7>RLuR}mE}`_zA0^Vg zrBsY|Nn_8awcu!7_M&v9go$2S>8-RSOsTf?irXq|i!b5?xIyx|2Y1pf*dL4r>2!a# z3$O3<$*jnNxyNHtV1<6N^xJwcB8xB`V%Z=2lh3Xc2_Ku(ps_aEv{rp0l%bkeC}qu&2xe@>MOg9X&=Y)kF{q!F!U3vEzE0DW66mHD~AVFw_=-cH(bQ- zmL^l4=NDC}Y_*A6`y9`f1WBVb&5bUc`I+A5;H`S8PvS)Z^QwMh{0y{ z@MFykiSZ+wMI~+aC*iTUO0<+{jAEO9P!hHYXDNpfc)H)X!%S>gz`oYtP%YlYjS-+r zU7gZvzh$>0CliEr$)+YOKRjg|a%EBp=CA9!kNSRB%WKrmw_yjoeUOLb^! zqx+D#rF}{qbu{jX*r?d0H=2xHY9nrhY84B?PZEzAbw@29wD5m;HyFoI`5<60F7R#c zJvsZnVUDF+J)3z!1#+$VB5YD}UA^^Z zQ25aEuwR)F$Du0@2#CqoikV~MF&~9cdDTIceFC55d$$>^`f*@6`J_QBwR7$y(j?^Y z(7_fmaB?>G{B&6w)~a%RFt_e;9aU~4`a$x_$J3ur@q}dMQLY(9+{@ZEXlf^82y)&X zowlJn^S#ji!oUrgO^-ut0O@|OrXbg3TxE+SDz2M958M~)jS1sa$P&KI??U9utq{x& zv)wTAWzyluW9udQsdKyy<{@Qt@@=dgJk>{^>HGTr`q3A4Lv-AnAqd$mmN@WJ*E8Iq zvwZtz%q5G~@Y*J{1tyof3LbEk>ptrco(ZQEMzC}?-@P4n!4V>}T3km8%fj1Q9gg`ZQ@J5LlgPNrngDh&ugQ7~Q zj@RfkMn?;EdVft<`C^sQjw&*#@3dx_;xHcJI?R1Tj;S&xv^hRRX}>c4DIy_6sV)}s z5bD_;Y5iz-VaMVs z$Q8lPxqoF2occo}kP$*+1~q9&l!Ym?2}fq_i;M+RM7Z;&k4j;;O;p+PFK4n2@B*|P zrY`X{QH!gBk{G*$t$HQ7WR+HNKbTN^MX_qDeiB|MT6rGqr6>s#0h$vmAn zUdgutny6bq2UvtnA?NY|&hTLFrqgUOYIoj$k!SUHX$|&$4Wk2HO<^m+6QSIxlUYku8NJ8yv+c+tB2r_WA8c{*A-EV~qArq3 zmFr0eeXeQ8O$o}rqqZc1ZNB``;5IqzzNevSZ6Q>a%o)@0O-O+k8(Or;R>fPTRAu6C zNKaT3%!5&}knEvPe<=9NO2#xIdI!E{A=F4u9y%b#tLupwL0vn|TEx4PpkW;Ma5B5esJ(RK~z^XLlPVhSinXAzB;8U;V_iuhOtDnG*8Fwz-%P58-8P#FnV zQTXc^HcFG%llrzE%a}x4m921lJ$gKv#EY0b-Ln=IW0>Aw$WVgwm7WSG+TN;YupQl4 zbjjIU$Y4ExZ=Ga&HxWbZZw8T{+6GkCub93675Xx=sRq1a-rd4=KadpT_1S8o8eYdh z>?mCE+1FfM!DRbQ$MMkVp*ZPgo5K3abCrGjq%Dhqsg?ky`eIKcW*0Y^03LZc9_e27 zzBb&CRseL#;=4 zEXwwY47N%i)1Bp1O?dIlkzWim>@eR&rJY9}dY(smYuJmHtV|5{WhJdEaY= z`6EVOAoAx|#{18Gdc1Ae-l_iBLzgVXYaUS+PU{4*3;pu7XIC_$Kn{yUQ6}z zVlZ^zO@SH;Apn~H-PpojKpI!()oj9+P#9oPX+YMrT*CQ)vsclT_pwNE6sf_d$0)h) zaUW8i^6(1*Qtu;GM*g~TuM%GAeh{;K;So$QF&nndvC&1yF%yV)Aszv|ENr2H?N@=flq(f% z*G!g6Kg^|CF&KWUVi+<04!cH?982ifdf&o|menDaJoTTJdu6)p7Lac%QD*Fu=q_ed z`pdLHw42MBz+#$b0&WCm|SAKA5dMtIRFnJ z#k<4db7@6|@$OQ|3tsAkMdQs(EwYiGYg(qk-m zupyR#BMODv1lNb5t{VnMkGsOm6Z6?!2y=5Rm8leIvC~Y#YJ4|#7PYgClrR5T(g*?5 zNqSg)hFZ>YNwHd}^GCfd8Ucrw4!j~v_3pU$@8iSMN-;6|_{Yv$uk-}5EI}q)XtV_Z z(zppWy76vJr;aPfO`O)aQ;M$91^c8{@e3rKsxT|P;Jy>J`3yu#qkdW2JdtNODTII% zJ0K1$oYl`S|Kx&_2D{ur^oCOQF_TqUH`^X~>JxL)a$ijOTj4U^U62m=5G-KCh>CVI%L*JoMQujw^akeoq@Z4ldDqC z++i$NnVyJVI9$?GR<`2&0VD@Li6emwL_n>I#8lFEdN$%&0WGZT z>?>t<3s7Kb>r=80W5q_1mCAI`l7-oR6VvieWy|y9)1Ro`dK%E6clAJr6h4VP65m)b zi~K1SfUBSf2sAtbS|L$kR|yBsJz3 z(*zTi8xSEX14ol$I@QV|yL1}JNiyC9yHqr+TU(YOKa(yBz8<#M8HDN$qdXr`6OG{% zM+)Z9VjI$WHBdRmySV5uZf^{)DUdIeEWELU;~Gkzieo1L0ymB-Fa?H0vJ(3Sr|1wbGxthwZ* z(7CLy&3|Oh>^uLC@{@mwuBMb!A{$WbG6MToVg0nf4zxhC1^+{D{db6ef2q+6f0+df zZ|_`)iP4iMGhJH=@oXTFuLgCf1Vh2%kFR=;U709xwB}fXlnV&dmMQw{RKCJW=h}W5 z1u$z6_x6L7rlynWrcg&ppp8F2mxOG2mZ!zl6;B^)D6(p8{nmsorSj20NP{%@({oHmKincVsZ6 zaa{}fbk?H?45G3={7-$**DQEG5s~frf})lzTJG;BoIoeVZAp@rRf@YKL#}MnDvUR# z=4TrPWH1khGWO}ZfMTNyy7SgAd?YQKU7C%ybC?9H$10`(>7} zoo^sU_EO+X8%)pd9?mZT=WF)PDi|MIKQw))yW}^Oqqlgar;5%KSv?#Yy-%)pHRYfk4X5uaf?RJJ!DFvj2*iIY zw~A?XFcYht`;mf)S`vxG!qs=hs8h0-3p828)R-j%@FTUHKm7`vl60PR>L(KMI#;=d z{aIaa`f2k!2|-+xO@4|Le*Q=}uZxUYCbR%-WIBd)c8g%;P}-%Z4hw4n4F+#dH3`K? z9_5Ap+6K6`=vi#Fg;2T@|2M{f^7_(j0%K`iwX<1ri1Uv}3({VM_b*75J?F?4ypAuL zdiB&e;7DaFNQlMU>W8=*Cj47QvQ7gaL>H1C{*m~cO5;uPLT`@wHZrtCnH=eM12kFlB&=uk)rG5kznDbBBJg2*{?SDix;b_pdUhs{DUVW z+PR)R!2WUDtxCV4967XV)Mpy<2PXKXDrebzwRfv7!O_KEJ3|e2?0dXESC8i_a9MKY z7gnd@&8gZZw7=zp<>bw>fuuC^LBCT`q$5)tCT%I_?!f^yUhPdtvF((ZpP3;p4#PK+ zf^MPP#D>fS!dbxS^~eT$oKdy(M-3|Sn}Yg>#Q^Cna`KUa=m?ON>IDOxW+U-8)oyV| z)mv{aes!0ULs}%7F}AC7eposmIPO-DtXQ;7n8YZze z5*91r6AyR`Q}lEzj#Q>OV8y>DIwue|B;oFB#*d?XKj>%{IXNVT=?L3v`OmMkl0FfmXC1`#W_^`OcmM1Q2g?r%i z>uQ4;zQ;}qQl>e@4v(RRUW_DK@AIz|Tw`FP-^5sjjXLD}#ks+%7H04fdMTOW)?&Ht zfn>BvTs=Ai7DNe>bCQlau#$8g=r0`#hI$*?{iAxVKLHG`j>%uZGHI?sX?hITC0e{Z z<)s6Sa1<)(7f&7>4D*dJL&eR{Zt3iO;dvQ%IG8A=pgL_?vE=?1%WnsCRm0ov$5M6J zBVI1-VB&{%V4RZUz6yXW)IMwxVct(H#XQW3O4G?4Le$B`*7x3X81uugup}qY{ByKl z+JYS&inkpNd@;n&&tI&ety@Tvi>6c;d(vP-uh8N5t>QHmKWgu)`LnH8{Le9aX*zTl zK+1fp(5*T<)4TuGlR1BvArKuPgSo-G7DeS|7{kyJAlD-7t%a zy8@Lb-;v>Oq#apZBijDS{Z%8`61J#S0$ETh96s$R?)U?XhBq#@H1pvf`V=jiTsS&* zt^vU4`T03Ju;)yRM~8+WtJ*%)%}vYiAC-iK8*Dp(V~Y9$22ck?Wz+iKUh4lXw*S4p z9>&MJkYNOvyO=9~J=@T^KUVKN=fBUv{TJDRLRFuQm)o~+Rf;0M0I*N;D) z10D2czR|r{h-mE{{9`}9)146$a1;iCR05(F8DF@a2i@}uBLC;7ax>A&{mBNHf6-z; zCNA1^`N3{w%c1>BlsFdW0D#F1Qt^*!q9FRtPI*Kq4c++Yr(oU$3%2gRH6bzAoa!|# z`r{N_47x-=?)V(34JpAw<(|-2L8#bG8(_R)gh1 zO>Mdv?jJ6`OkZNumhhRub^@U4A%^X*zr2rVbx>**w^LXiQwO-mXUpRR;?h_`N1D}y zUA1Uf9$MH-vjN_UWlGD$yd2og%#a-mNhFAnXdRe$tO~`_p2X~&(Ni!f6fspxr3Jvb~!ptEPSSG3z}vSsw+=44ZT>q_Ie5o{rHar&dAZ6X5g2Wzv%AKIC4egxx6k9;A(PyM(vWq`hyLLH z=~eqf9q|@l^y+P+h0l>_*hO8KxYEPv%EFjm1udjFY%M^{IeDPWg(GhUhwPk2PjMw)8H3_DFoISuzKf4={& z@Tmo%f#lI3MoreTS1{0=9%$m-v0_0LWC2s3Xyd8rWkO%G(x!ZquH|Fc_`47#mI`m3 znfL0me1TYYBdpFlQM$H)4%16K8*9HQ0D!(EU)2yzBMl1G-Hq@0%1mzOm#Tidt`#(i zcnJ`B!Xq{vVXTa$Y(tri`W@Fn4pOckb5#YtL}owD!i*tEdb0-xVkE?pV=bpmVEw3X z*Qz+{^zoMF%b(<(Rf7GMUKJagH_|)rn3QrQqn8Kn_~%zC>sh|(A3|4Qz`DG#_2{P7 ztm(J+KrQ@J>U{o1G4W#LngEa=;{Ir3#pL0@i?#<&wEhC`>E#r>M@~h&<@d-K#i>;< zGX!qAoAJXnxgm6r^79uqvV|ZjstE~_yOT%Ai@sNFQ8s>nOG?&(Qc~|PSI6o-vecy) zjpZi^=t{p_bYXVvqR{n8#A~;m+F#${qQ8+$QB~m_v}aM z*t+8TA=$!>OUHqYiyC+~?ML_ha(e_%V#(9cwA-MFTsO(~%zLyE{JM?=5q`Gk1mz$v)@g?6cO|Ydz1icD}yQRHmk6p#*_I)T$~9 zIv~&`K@jKy_Uc7o1V?7>1N^(-uA?jmD(+)j2R>Y~k=2j|fl4E&@NX^ypDA2b4BbH> z_Mr3Eg^1-{D-cLLKvh9j_nqn1EJbpxRXSwn4dW#`I&Vw5M!rW$WPgzn{!g93T)WYa1Dn{_5@#}9twJ)dhW*Z#4h9VqDWql$~V`jVhRm ziJwiz-vGL<%NHl*h7Lm{`HrJkdi?C>snnru<(stA9vO6CNEsS;Oc*egbe?FvIKgg% z*jUrdi>}~MPksD=dMSx9M zST^LcH)}G$pAjW5b7pVAtq=Rk{-&Z4s~zBb{__}jIN|t~yJ=U3%FbDHd}@*pR&fRzd_a+Jc&9z z<7sl6q;{X{(5%QL_A;_hjE-=%vHSKYD__ekV12ar%cALom_BI;dhg*o)(|xw_i!`K z2W;%vWCzXHQ#Um_oKk0>@Sn3E=cUDU4y#lQ(^yERd%OMq<_>W`8@XKi#C4yHhH$`z z+p3z)?G0*qz|?K#TGG z8>K7}G$KrO^Ti9Ari_l~A~Mp6VM8&?huhNyr1x`#@e2c^aF%-@^U!+ z-M2%R4YSllZ_e5L>BZ4Zyk=iqu7VpM4yz0#e8_}%)h=owjV8FE@_@#YtcPW1w)aPcqQhEw0+j0_KJU}?OkSF+c$?7AER zEy3iPjW9_ba!M6yLGAi-8?RVqg%485SFI3N3P@hE{vm@~sp(Dl1RT+A5t~CiP0v9Z z8yKWI{0%gAs-9K82X`D&o~!aHpQe%VTDFO3I*V!>O7u1(wrDVu&h*7(B)mJjTyb#5yb^A4dyw5sqU?G(_(Q(WhZei&+GnHwS|zArjHSx8#T==WH0+>HxKf{0_t|r zNUyyM0XqB5?Wq0YY3Eepajl>g5>hYD~+Y%v%af(53dYUud_qwTQ(6t)%vE%)??ppL|tB61$-3+2!nrN|?7qmT>DQy<5B-%s>%|Lj} z@&&|G-h*Ki$+jUIEs%#!g^q-;W+sQHPck}FQAfs{(k@Voypyirp^m+$VuXe1RpMbO z(<-M3^XLY$;ZS)MhSky%L48$4g&h-yRBhPHjD>Dx3LJ&vB^$)LvZS94@PfHOb)GCX^^6DhSbCiN7b^o=6-H5ggah|H4Q4<=e z1U$`reGJOo?}+s(3+}$??1IzuNUzUYmOfMCftrPaU9{4MjhV0iU=DlDJk;39q-Ht6 zrd%^R4ZCfIpHo!+wp8Daz-0|19tq(p8BpV8qa`T(!Vu%oRnV-_u2Jz%a1Z+#l8{5@*yuR~JKTx#slg+s}Yv6xWdve&!f7ELe=T+-RV@SdUT;G0Bj&Z_Qn;|VhE>gP)1OhM9>a_nu*zG_&$#k~>aX_slzAS{>s@wf_*1AvJZC@{d zASQ4eb!!8|5B;-ue^i<)ea%52FmK{##|@@-zoCi!>0m0JPo9}kml4wYOC@NA3>9>5 zJM3V|f_4(MwjboO(^Ys2g>sv^qMYhAVQgpln;I>?E$PkJH1bQE9Eo2hiM!VSz~Wmp zATrp{O(Y*b?W2PoPW-|WZ0<}$2DVjA^V9{ps7|OlTgu~sRi3oHKINl@xVBS$f_T1X zybM~)_I=G_cNSaU!h;p^*;^`{kfCCJ=)1AL`lmmiv+^fy{szL>lv&5PosIPxwtOzl zt((G8_{S?~UU0UyCBCL{+zgd44{@p{b{zY^Tczeik+A)3kckribI9W!X1qVtz?mKm~!@H0Bfo-l^?=rJV^6-@1*+m_hfU}nKiour@%lim?? ze#4ch{kG}GV-t%Nt;V9aGgGXzjlw&>A}|eaj;8jjO%DnrkuLmOhgh4G{aq)uxx(Gq zsyUye-ZB=D2PDj4pMmm!4Ml+4+dYpRFUBPEzHVe@7lC z<6~(f9y+~ZzJ}c4H1oB=u-CYp5dyN`y;P6qM;{jCh(R2zmSnIqd~qvUwJ=})*mt&V zW-H8;pCItRpG7oCo_WZlX)~s}2hBG4g9ps)qcdy~*&8;m+zlHXc7jNRnoo(GqoVlt zf}F$;Cng*Xr0wda{h@IxR*frQQM>0xpl8+9!&44fS4_<7)JK)rRP{aNOKJ+B^B|x0G9hh)zK<>4RB<@6>1O z#pfooKUlRSR}Q9GE&3z15c@|lbL{<1%O6DC)vHb>1dFAu``1JBSMDlV{Qy1vROP0|NUKmn{ zdi~c6hnTN`n36uZhfnz}856imW<2`FW#Cg``(r&X%@#l4au}iY`O_XqlkVci`sD$U zPZ6m|Qc0n%`ONgOZLOV*$4rg1g*&{n=vb4FaMN=b`(5YzimBL!JoXh|@VCQX5NrfH zSf1wH@rfGl<;FH*=fgx}>FAtfC7a?$fuN#WGlxqd`(-+_6OHW=;aPVPQlyg*67hLA zK@;@Mo1VUdF&_Vj&E!t-rLmFx4rJ5I?;Zn>l`t}C_(Y>=RCWHo*q92FqMGng41Q&X zkK-Me8Nb8vA3-Tn@W6-W5P+}5V3c0uX0Z~L4M{2C`KSrGADTTyjGgtYt6xJy?T;|6Ik zCI?~R4}D+~>ag#vC9$>^5sro(1fHpaZm+fB!aM}dlz4}J=IfJl6oh1d5%%+VZ}jz! ztOcZV2|_sQMzW<)>-)i0uzjbqi={JbrKgIqltr&b#TOg%=3rg@aab{DJUKbDnz~CW zTiwuy zEg7qsHp65iVsmK0LzyEXaIsyeRqw1nN`;Gd{Q_p*Ne6R@|fQDZ-#QwkCE) zK%ecRw5G(zpnVMsW7%X`a-ZNG)=AElii+)#RbCe`?!U+v8nAc8dcL2H*%)|Ce?tLC zvFJN$&i1rSd?DX?Vqk10ZWCg;7+o^9puLwuzU{SkjDUBy^7uPrd&m1VM;nQl!tOpP z&jqfSl0>^5CQxK*lo4a?(FhG&o`_q-VW6Yww&0QEcD&fV0`Ym@J2|hasb4X9;mRZOf!` zrkc0xXdyMOpPbZ=4K1h?-CE^1LF+SJRCVxTef4(Jo0hmz6qe=re5T|%VZlep1+^TF z)=Y>JC}G<}L)%l2GZv3*z49J{)`)eRDn-g1Df>a2&R@;i`H!|O4gnTI>GM;6GNUVa zQF%)tDh(YzU6{b$3i;@5yWE@Ql;LgDSNEk6(<5#7b@atH zUSb{Y1%E5=v<8cEx@7M}fji;~CFt_P-^knJ3O(wP=INnG?OZ3N;y zNP6|O{KX|uT~MU_IoXPk5)~^hWQg=2nB0tG{T_sE#ai2-%LlgE`t*($30b8e|#K5 zckT@BQ(s7K(^(OOjmYA?S#wBiC#|4(tP5PF_kWQEtRI4&iCyDbuLp;#_ih5v=)Y5i?ag8CM^o5ruC{|x)CJJ2R{VFdA)CFWPQy}|sd1g-e6yl@{KJB?(%*k& zC;c+_`yqmS+a^fSbLU7rTjguQr8wkR^)96&r4BPcDKl?9gS_tfexaNwzL=%w=~-Y3Kj{~f z9&>4#U{@-x^laPHx1RM}Ry0e&PaDU(kn&XPizexR{*4VHy3YOyxc=zCB!ZS{CkhM41B+1!@9abZ7 z*@APTi=~mYP}JG4-j_CF*Vu);3g*dzk(B_0awZ-kW)ItffOr!qWc}H@HYY^F{F+u{#LzZmd8WfP>5k38AkXGLEDe9vVjUvguZKCq28on2g^Df?XjNC z#b^?K=Y)ttdicM4%~hkkw%lC~>8{PV7Nl=lEsMoVRlD}uYyVrRODdhAn`0wgJq;%z z$^?73i3yrWfEMSLuzHRpAWr1EW0Z_uz2tid!EG#RHS7_qCHT*1CLJfP7+y6wocgFw z$*!Dr{P4Ti?_G4A)wVHAmP~Zcydx38=h7sB*xfX&UGihxVxDx_S@|>GPrOwGCoD6^ zTcdu#Ewmc`V!+;2*-Ri0K0tEfxfFd}v962v4Zy@REwhz9Bj99yP7+n6w3#PYpJq-2 z$x93EX!B=pjI;FkD@5YBy%#_RCp9sBjXN#UqWxyZO((Udf>!N`_lE$gsVU{vJY{mj zsRAd7Hu;Vnys0=PjDQIcykwR>c54x5G(U|Clk^|@yzLD_a%QO1P;dx(x^4-TCSOTZI$$w{V;BO_Aubd%>U4Ll0JwcY{ICj&I0y03sQN zSDSl4OeadcX-5uV$bSBguHt2C)s^^IL)y8+Up>kk2||Qj#ez5i|2LgoC(UPnL}zVV zI$%dLKIr2n1U6-i<;zIJvexrjudZGM>i9R0sqbAc5na0u{2=wfM zU#b4m0$B1%n7_H}Rqk^!()ZfF5^tHWo_sqybwRl|ptf)*vgE0}sXw5R^w7Eh8UO={ zdGd9P%w2XCJ*hxPqe0)7fJWO3h&GdMIm9e>mQhL3S?k$Nl?#Bm!C|^fjml2qwg$*( z2JKi2WdF5Wb+Ju=p6h$Z!CudPIf?ouqV}ZLkdFx!>GW-o12*n3v%BL&PR)Va9x|B# zbkLxG#oo{nK*#>i6n_8XmFfTP1T)4l%Bz-&fS|6K>GJ}#U~1Cfk?*e(%u?ymoQ z`Tf89kpIDLga3u|&d`^amxmTcGxBYG%7-uk?UG#m64OS%V-9iGXV8*B`|POYZnQzA zy&e>BY+Z&7>`a$0M%O7b?mn=%q-AZ7g4z&JJLEs>7EB|+QYJ5e6 zg)LjF{^@pXC}{Qh9UV#Lh%u%5il*KYvTs=%1h<7w`Sz^Q?Op@&RQeTKj&HG3nVVTr z-{tqN59x;9#bN8UpyWWHEA^{^Uv4MEaVbJ&YKAwCVBP|kq5*2}fhEueG)o@MIED0z zh4I)x&RS*=((II+gq;iLU+SSKeLw7#+q#HVokHS9&9mtCuh!J8q8>B#$HB|^uF~ny z8K3qoHBB`zaIW3fbFhgu6Ykr+jPkZnmbVA1G<^|~(q+tJHH5xf^TmbH9ZK?I*XFsI z7H$E{Zi58|)*!bHI2pt^9(I*DMoiSwnYW2%RQG8zb}Cy|WyS*jFV_C zXw9ff_1~D}S*FKEl1D!d~t7Va$ zF+4Va zbEFr$EzvJ%Y~&O=H#9yQFNB`{9aS`xA_Jwx1>C2nVth!Sg#Anh4|J27yz5aZtg|&* zYTwc)>3lp$%NZ$HD&mzCRmu|XZ{**>_&BJ+qJMTze{t`(z~$)ckY<6?;XRWVfEle? z%hSehsi=uAv(9F*^qBC6jg0so3=E)%Z75Oct^?hQNsKb`i#GS?;03FCxnEyCESc@6 zezgg1y>DLn8uY%{iUd2(dldOiA&Sz*a6J5BoD%Qx(o2`hz7U%VZ|%1gqd>F@Ktr5_ zJycF^m8*TduB$)?T$UUCY-lt?W#ICV$~3f{ckV~#r@8_;V@S)VY-P!6HalLdquo)b zmk-cyit8eecD}Co@jOgcGW4Gq6hzm`=+Q064uk!Q$i7{p2x)IThA@~pNyzbgB>@4W zSjnJLr_4Z6Cx`A>qidZ711``weMWC8uzi!FZVkZ-0@<>t)M)@`v^7L6Y)9R`6dmUa zX+HIrt;jurnCdgfx7n|+4LAc~uk(O{d-h)NB@=MiH;;%*rSZIMT73>|^^6hMZ>akM zwJMGEJ_Wb7e#9NwaTW0IL1m5^;YeXGT@x=2I755Os~!QvEQc;hX=})t0zWXf;cu7z zeV7=fkJnWa?=`D=q(7qZ%^ zkU|ELe7yoDcOzT$ekNvz`?DVUVG+4CLENv-Bj&Ws2w2rF>C$Xdb+h2$OR#%dsmYAf z_N~EZg(DBzLgyriN9~~;k4tQAp;x)mACNj#ZycjtkT0&r2gI~8x4226H3bC?PBscc z$Z6OfxwXVi<}vY`)L~9f!)ndD1w^L-$^YGxISxum$7&6!7~@(uy#^V)KmIGvpU0M; ze($!u_#znKx2QgU)h1350Z!(J!>^lCLV}zs=I{Lx3%3Cp=^Xa<%t1r~&L&HA{hzWv z%`03}uCtZkwt6rs+How>FCPTREndK0PkWg-yg_wr5tKt^tvRh8eTQUnxEOQ6=Jk>{#i z%GG3{$Wu9QOLE*1CQhRt)9dntUAhS5(1S~(!FOa!0s{jJ4eoZwqv+tprj2zQT30}z z=r19sN1Nj%bun!PNMJJqh*!HZ3J4@n(H#JngX~m*Qt^xh=mvoz1A)dYD3j~|=HbDD z^mH!1s?njW?lOANGn3iBzdx1HKQlc0-@Xmx{|hcIf`GQa)VmkZAMU*gxDf$F0t?k{ zPnCso7`xCD2APB3u*F-s4*;LNuo_a~3E|?_x-F1!LOkx|9$^6jDEEn7rqHbaW=b`F zxwug0Lc-_7b6@M-3-d@sn!Y=gs8>jw^1|fa2$#H5@J#3b`JPqr^-UY=EK!ON+%3_C z7rz?3qynXFo~{SP+hkP*@6U1xz`&qqvFohsw#%!*j*?y@EyoeG0Z-jm1CYxl!j>Tw zz%H4zuBk{R_`$GQfAZlP#6~81baP{_3a5#b_80<~=8Z1Dup|bpIB#^tX4w$SIRxrL zq_TG_vk||RB=4LW^aUI@;=3T$v2m?_`yu_OB`z(r(1kTY7#JQ9twk@>)?*mKh|)gs znqR#O>6S4r`1bXVKvu|;>YF8sMiff+Tavpw?~->$J16t*jrqvFdw|gN%KwTq@wb9& zBq%GM#?F72*hcHZUT>gz3XRe>S#e`R(Loq%oQDXCur9wGuCacqcDh5(D}GptwxM*bX0FIa$z&c ze!m?An#!obE;!X=JzD0G_hlAN(<)cpTW_UtZz*RNDn8z!=*n87#wd?P&+;~@Z zm+VgzO22@iipj1i-eLiVW~Q1?jA?>fOD!ba4xhE>eKixPSDR);A3DOju2Zug$5*Zs z^{%(L-jOuSDLS09TOLx?W%V0qV;1z~l-qIyZT6J zwQ!6GC=Dj#XR9bAZ*-S4n=$$s|F>)L8^T=TdUt~_xg-50_(bTMl`ymq!uj6b@q2s0 zUad?xT8to1Z@cv@?>k@fjXh%UUerBAiM3$2)^?qHt?&>X9M+2c6Qu`wpWjukta9=6 zXD%nzs2!0zqmf506r(N0g@$-7GjW z`rVw0OcDM-s4pbIvn$B1)qXB#cL%K1B3Hh*9TolC=+uO3LU`JJh%Puog*y^7V3D$K zhVBT`4!Gy1_e8a(@!fYQKliOdMx7TNDj#?9rjV**4^|@YE6}NaGKzyU`N^0%q!@p^ zbSiSn7C}kw&^SsvJag?tEzmBY;hT#PeZ*djp3#tSu)_K5U#d{W<1rZjA3oQGRQ)ch z4xety0#lH^%6+U+|FB<9wu9S=wMLIksEdk%n@tSuYXdcl??PT1jg<+juy26QJ&rE1 z84dnz6ac!B8kzH@k28BzhvDlbdXR5nq$*$)aj6QPNa3xU6mq;@qS9i>9Td6VGTKD% z+>&@0*)nJtdu`z3(ojy+ZB8XUcmq^D#B8~dZ<*X-`NBOc$Jg>z`Kkxu!U9hZ{(e#m zAG7|xr_D{T0$S@dzt@?B;fidLD`2qs-q@zWE3?NoBx{j1mf#-j_o2B}r0kb|lhYlK zrbHDm*R{`WF#h;k#BVuY3W{sf-?iwbzUiVJqukT{zT>`8;b+d(FSi_kp*z0W8KL&% zd2#f8dI}(FTwDEEs?z-cr|Kz5k~`?_F$qw7%r0<$})eHW1HM0e$GZ&mra0pfqLPRI5Rw z(?>-EYc9SOHb0@SQu%B}6_`;6`Y&>ORqNI8PITR1m)P<6KKE`nB7Y(Mlg1 zB7RJ6DbKNF>rEW|T&FWLS$$np=x2Gf7~5|~4w6tQ@3sjL@-e!fdZPVxAqTen8PL@C zYB5eX@5Um&@9e5s!#*GPw#P2N0XHa?W8GTy##`lxZ;Z0)$O^6v-zj2I1E0Ptvc^5z zdt+3;JtH2_cz%!L*F_@klNOaR)weEyf&;8!wk=pag9A~H^jM_W=JbGkbVRy+-lsd4 zq77`PUl-v^A4e{6)}IJ5^W@fKy6ncb4(m^isqUrIZW}iREybZ`81)aSA>&V@Oxmy7 zjlN)^*n2Uko62cacMrRKA7W6jbOfvl69NuG!YuHq|C?##3ZyxF)TMzRi|k-- zePaL_GI#LCRpS=L3#^wL**0fX9wSuBv7^z~gNo}`0;4nh_b!0Cs08-FH2o`X3h8X& zu4UBPnZT+`2!uR3ZLkE4U;ST`aB5o$D&6;xkVnp`=p$ zkAUJ>kfk1PmDPojEG_lEqwvumd_>RV@9Bo2=q%~%XY<{WwK~&Ui1~C~s4Zez((?QD zn|t>D4?6nMKHWwstf%!1W=OM{!e|~c(C>eM3j6wsG1hTE{LYW7B6nng4XkxycA3K! z0+GqCGjy?qy_Zv-0fYI^S=KFMZKAKsIm*dtL@9yZ^TsGe-;Yt1yLwB~dI`W8oAl{p z05E(Os|vO&GMw`^{ld8$dR?wJ`rmWkQ;yD1q5#}T`@aw@9srwhJA$1mfvrV_00=(d z{u4yot>*OOAEhvZ5(egjjsUXH`?@-SUs&CJUv}_+3aI|qOwAQx&~vD^iAI@0?ZcJ< z;7vSB0=6iWOXy~MV`Tt2j77pj1)8J&kBuFiSSX%aPL?ejUY^Q#K{q{7jkm}I`p82+ z6x9{z^39jKV&{=Bq3I!j4E^3xZu)V>?Q+TrYPN2y(oW1js(Q zPCu@)w@3_{sFWFE$j)fOpK=#e>%CKXrwh$12pQG}$k5byo*g&#CIuIFcwc_-POj9b zu9cA#z>O$|4#KW&ptPa+(Y)5IpfvY`4Xd0B5(?NkSQ)*D;BOM+eGUUXr4mz5NsQPd zw)CHxFk{Gm<_$LQ1v}jH6Ay9t-hOxaOVBTt%@UL;^ke?UZ2iX-aAmp@>0aq*F@csy z+^L3Hz7Ut=(k*8;f;!BCxjyvxuMHYB?QLvs*KBSZTmjv2_&FpSNW&f-o9ja{q;fj( z^Y=ZN9R8;Fk`XCTP9*u7pw;0+ThwtQAHd!muCZ`OzOaJfj(XKRE{lwa4Y@okx&D*} zf2Pz+(@V+oM}7XItD%>@Q>CcRX1AHt!jAmC*1hfet(#P!XQcq!vzOFSoJYolM-^wi z^oB^SE|xd)|JoEah&6DTY=&YG!q_>nKxezWOQ5xTz=J#i!lDU=Got(|x;9$i-N7}F zjJ!X@II4hFQ2}S5AKzy1JuYUI$(}KLNffa-{g}f-@+w<9jSWc^q<-YI#(LV>FNhSu zmHOBDxSnvucuia3qU|{5%lJx~9s+>gshz4HQohvYIv$UDr@*i5J>z*ShJtAV?oNW^ zDuIpAb@gLMVE`U-D$1+$^_*3A-(W^fJco2rMU*#|L;O80LR z++3f(UHX1MxuOJMw7SJdLn^XBoOGL-5EgD69+T|W7rh0{8p|60bS75foFzHn9hvLZ zW~>n;nZ<7lttA}3C%c6s3N`$%W)9-~g_%L1pPC|xN3>$9+30*Q@v#zjw}rAoLW=3 zv;(AhfxKDDk)kAr|8iq;@!Ns5%_o3|vuCbmM_pIkJ9!J(cF*TFp!WWfNP)NcAf?X= zfX(MIqaUF8Uxl9lK1CbUNfhY5UJee-P715&(t^W%-ZGr-F-P2=d=2=T?OYAB9T1al zK4o!P4$?YVYOs-e(>LR@``m3_j0x_^1-3f8*L-fYtgeN`WN76iAgv~sp=Y1v zV%f%6LfDGF8;fZ;M=vey2ax9kp6F&4_84Iz279W%?`TJ&^hOA z|LJgcc6j)$#=}9RqY3Z*1CuEoCeNyHgIM<`J- zJNeJ#?$T#Q#TF#>)AQ*I&-lzQ)R*`c6$d=un<-@6--fw+)=MZRJ_c;}ma7oS;8bHe z_m(G>$%O(E!qX&{@|Omrd#A#zq-H7T^eyIbP=L_9e+Re7bS^u`W5E=F(tWDK?;wjTLu{QPI7MsIpa3b=8RprwLai(=Ax#>=GJm&AL#<-2H|R% zrN}d}F3*&PS~o*z{x9cxM`SD|jGarnWgRn_=h^A(<@3`3OKeU@Uqre(DS{L zTP_V}n65~9Q$!_Wxf*XN8aFrU2x*%Sdfufb;E+eQgz6V>UAh6v{UNS&U$pFjpmmi+ z#8ZA~NWjE(c#Qt5y+6>f`wmARVj;XoxoaG6QieiD?CpMz8L@1n!gqRG1$8AJZ36kc zT*vC66sczcL-$1K%Z*mpJ*&@rNppNamzt+0^U-GGCxi9NbsYRpLzJJR2vhG`wnqPG``@cC{_1Kt>{mWMb|0=QURDlz z#-}G!lN);Tn%tr|!pPRC-G{E1QuTHdO9`!5;3nU-E85FiSM>wqn=hxc3DS(ZmhG4; znukEV?&>Mxlehd|H_Seh?Aja=e&TzaUi#DRFqrpB^iFO=xfT8m*!%)$Z9^_Y3eP4~ zM@i}@RH29h!Uv0)`{L>{sV<@%Qctmyk<`s1r-wc&UziJD0(Z&-uS70{$UjXEUFFk0 zWJ2JRTldGO(^9I378(_iCWh(Z`>mXL z)C*g&%HqD+ni^o^tuoWMXvGeCAj|Le#&#P`YtcK0KILZfDN(u3K`fRp+hzu(QBj2L ziCf*_D5YS%DF61eZA3OZ|MK*<2J1qpdxl%A6qn|nbJZ+5pL+*b{pC6$Eva#Fq5>Z_ zHZVS5E`e{?vVAR8toLJEAKIr;%eQCTVtOC4q99 zP~bri<&bOb`2Zh7}q{XNQPbF5=!37F)0xFZE>(I|L5(A;q=!#paIVS z>rF-ntlz{9(f#m0754UUMa)e*Q4LvTl}M!@-&Lm&Z2oOuTpcUBeJ9-|l{zVnfSx}N%xScN~z}Lb>Tg8UzGuJxAijijgc${|KZ8G(8ScLn3X;A zxN&mVXf&ldMGbS&-VQc5Cb~Qg`6=L~w0<*PNEJY^0_V!dlf}x!s*(NmaTAqf)EuVW zSuf{>zow)&d*`3$l@dw|WQzy|+poawMsoe5CKs}Onk1mR&dcfZ(~LX`42bxJ)UX|x zacrTvi;^TRBwq$0E%P&r@z3pZILso_WE;`E(B{k5!dQKuV(Vl_NFnNRM)h_upX@UF zu73c2^D{Q7L;(7AB5ANsmE|!>_pRRY_wf9aXLWba#X1uoV^L>@n*nX!a|RI_JCXAF zm0IRJA?UmP+VjArjC~beHM)4G3ZEfFLuuXHhw%8qivs`l%>UK?FM(d@kE0N%LIufW zpkSoSa?;BM%u<~fj`Txxl`hjZHDo&SqtVb5tyV-90H*=lIU~D__ql>U8&3^LM{9|d zKp7}#L)pPUu5NMzsCp!Mn9BXYSY+tIQE-L*nIA(=(yGIi3NtpSek=J<7+_aW=jRb^ zDOpJHpJci8O6oHUD)$A8=)4)A0GtG?!wqI18|kqfC>~qSor{z!VY&}BC%!DaC@9n! zHDr5H{*O|a8P%nc;?TlpWr_quNcy#Qz_Iw1D{ gU&?-=e@wd2pTwEN(d(8Elw^>qqNYNz-0P434M8?VEdT%j diff --git a/docs/images/dcos-simpleweb1.png b/docs/images/dcos-simpleweb1.png deleted file mode 100644 index 5afa5c31a076cdebe2bc829deb921d595007cab2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41493 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%0DOy&9-IhKkRh1*E9ls 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 D#Vg32 diff --git a/docs/images/dcos-simpleweb4.png b/docs/images/dcos-simpleweb4.png deleted file mode 100644 index 484afaef8cb1f6e50c825b156f16a83139426ef3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37569 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

    az`yHPc+2 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 z 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 diff --git a/docs/images/dcos.png b/docs/images/dcos.png deleted file mode 100644 index f6a3dd724574dc6185eaab928ff6964fced1e3a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19317 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 diff --git a/docs/images/dcosdashboard.png b/docs/images/dcosdashboard.png deleted file mode 100644 index 4a68d4c6f93d790a1a96821b49ba5767592305a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47567 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 Na#G5YHR8sh{|^YsR`LJ< diff --git a/docs/images/dcosservices.png b/docs/images/dcosservices.png deleted file mode 100644 index c17cdc3480738bc3866f4ceae1221dfbaedcf4ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52271 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 diff --git a/docs/images/swarmbrowser.png b/docs/images/swarmbrowser.png deleted file mode 100644 index 1263a29d6fe91d7f36d4a60b464c46dcffdc1c67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22673 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 diff --git a/docs/images/swarmmode-hybrid-docker-node-inspect.png b/docs/images/swarmmode-hybrid-docker-node-inspect.png deleted file mode 100644 index 6d7787ec8b90f6b3921606bd317efe3538895502..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80331 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�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 diff --git a/docs/images/swarmmode-hybrid-docker-node-ls.png b/docs/images/swarmmode-hybrid-docker-node-ls.png deleted file mode 100644 index dc1a2e1f8f569a711b20659aa5ac2bf4ee0bacb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 118922 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

    eA1LH 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 Iv}w@)177CgH~;_u diff --git a/docs/images/swarmmode-hybrid-linux-agents.png b/docs/images/swarmmode-hybrid-linux-agents.png deleted file mode 100644 index 0c817fab46c1997457a999e3338847dff20ee0e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38185 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

    +DSE};MQXjW%fxCtYs|@e} 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

    w49zL9|K>V%}%)m&Bvt?e%p<4G(pMg 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 L7Aq9d{rtZG8#|ae diff --git a/docs/images/swarmmode-hybrid-service-ls.png b/docs/images/swarmmode-hybrid-service-ls.png deleted file mode 100644 index c2e922806e9612ed4f422acd4f39041462f94479..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57288 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 z 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 z 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 diff --git a/vendor/github.com/go-playground/universal-translator/.gitignore b/vendor/github.com/go-playground/universal-translator/.gitignore deleted file mode 100644 index 26617857ee..0000000000 --- a/vendor/github.com/go-playground/universal-translator/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof \ No newline at end of file diff --git a/vendor/github.com/go-playground/universal-translator/README.md b/vendor/github.com/go-playground/universal-translator/README.md deleted file mode 100644 index 24aef15859..0000000000 --- a/vendor/github.com/go-playground/universal-translator/README.md +++ /dev/null @@ -1,90 +0,0 @@ -## universal-translator - -![Project status](https://img.shields.io/badge/version-0.16.0-green.svg) -[![Build Status](https://semaphoreci.com/api/v1/joeybloggs/universal-translator/branches/master/badge.svg)](https://semaphoreci.com/joeybloggs/universal-translator) -[![Coverage Status](https://coveralls.io/repos/github/go-playground/universal-translator/badge.svg)](https://coveralls.io/github/go-playground/universal-translator) -[![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/universal-translator)](https://goreportcard.com/report/github.com/go-playground/universal-translator) -[![GoDoc](https://godoc.org/github.com/go-playground/universal-translator?status.svg)](https://godoc.org/github.com/go-playground/universal-translator) -![License](https://img.shields.io/dub/l/vibe-d.svg) -[![Gitter](https://badges.gitter.im/go-playground/universal-translator.svg)](https://gitter.im/go-playground/universal-translator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) - -Universal Translator is an i18n Translator for Go/Golang using CLDR data + pluralization rules - -Why another i18n library? --------------------------- -Because none of the plural rules seem to be correct out there, including the previous implementation of this package, -so I took it upon myself to create [locales](https://github.com/go-playground/locales) for everyone to use; this package -is a thin wrapper around [locales](https://github.com/go-playground/locales) in order to store and translate text for -use in your applications. - -Features --------- -- [x] Rules generated from the [CLDR](http://cldr.unicode.org/index/downloads) data, v30.0.3 -- [x] Contains Cardinal, Ordinal and Range Plural Rules -- [x] Contains Month, Weekday and Timezone translations built in -- [x] Contains Date & Time formatting functions -- [x] Contains Number, Currency, Accounting and Percent formatting functions -- [x] Supports the "Gregorian" calendar only ( my time isn't unlimited, had to draw the line somewhere ) -- [x] Support loading translations from files -- [x] Exporting translations to file(s), mainly for getting them professionally translated -- [ ] Code Generation for translation files -> Go code.. i.e. after it has been professionally translated -- [ ] Tests for all languages, I need help with this, please see [here](https://github.com/go-playground/locales/issues/1) - -Installation ------------ - -Use go get - -```shell -go get github.com/go-playground/universal-translator -``` - -Usage & Documentation -------- - -Please see https://godoc.org/github.com/go-playground/universal-translator for usage docs - -##### Examples: - -- [Basic](https://github.com/go-playground/universal-translator/tree/master/examples/basic) -- [Full - no files](https://github.com/go-playground/universal-translator/tree/master/examples/full-no-files) -- [Full - with files](https://github.com/go-playground/universal-translator/tree/master/examples/full-with-files) - -File formatting --------------- -All types, Plain substitution, Cardinal, Ordinal and Range translations can all be contained withing the same file(s); -they are only separated for easy viewing. - -##### Examples: - -- [Formats](https://github.com/go-playground/universal-translator/tree/master/examples/file-formats) - -##### Basic Makeup -NOTE: not all fields are needed for all translation types, see [examples](https://github.com/go-playground/universal-translator/tree/master/examples/file-formats) -```json -{ - "locale": "en", - "key": "days-left", - "trans": "You have {0} day left.", - "type": "Cardinal", - "rule": "One", - "override": false -} -``` -|Field|Description| -|---|---| -|locale|The locale for which the translation is for.| -|key|The translation key that will be used to store and lookup each translation; normally it is a string or integer.| -|trans|The actual translation text.| -|type|The type of translation Cardinal, Ordinal, Range or "" for a plain substitution(not required to be defined if plain used)| -|rule|The plural rule for which the translation is for eg. One, Two, Few, Many or Other.(not required to be defined if plain used)| -|override|If you wish to override an existing translation that has already been registered, set this to 'true'. 99% of the time there is no need to define it.| - -Help With Tests ---------------- -To anyone interesting in helping or contributing, I sure could use some help creating tests for each language. -Please see issue [here](https://github.com/go-playground/locales/issues/1) for details. - -License ------- -Distributed under MIT License, please see license file in code for more details. diff --git a/vendor/github.com/go-playground/universal-translator/logo.png b/vendor/github.com/go-playground/universal-translator/logo.png deleted file mode 100644 index a37aa8c0cd0f6e1b98e0be3eb2531ebc6ac6717b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16598 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 Z{{;$xH, -// "lastName": -// } -// -// If the embedded message type is well-known and has a custom JSON -// representation, that representation will be embedded adding a field -// `value` which holds the custom JSON in addition to the `@type` -// field. Example (for message [google.protobuf.Duration][]): -// -// { -// "@type": "type.googleapis.com/google.protobuf.Duration", -// "value": "1.212s" -// } -// -message Any { - // A URL/resource name whose content describes the type of the - // serialized protocol buffer message. - // - // For URLs which use the scheme `http`, `https`, or no scheme, the - // following restrictions and interpretations apply: - // - // * If no scheme is provided, `https` is assumed. - // * The last segment of the URL's path must represent the fully - // qualified name of the type (as in `path/google.protobuf.Duration`). - // The name should be in a canonical form (e.g., leading "." is - // not accepted). - // * An HTTP GET on the URL must yield a [google.protobuf.Type][] - // value in binary format, or produce an error. - // * Applications are allowed to cache lookup results based on the - // URL, or have them precompiled into a binary to avoid any - // lookup. Therefore, binary compatibility needs to be preserved - // on changes to types. (Use versioned type names to manage - // breaking changes.) - // - // Schemes other than `http`, `https` (or the empty scheme) might be - // used with implementation specific semantics. - // - string type_url = 1; - - // Must be a valid serialized protocol buffer of the above specified type. - bytes value = 2; -} diff --git a/vendor/github.com/golang/protobuf/ptypes/duration/duration.proto b/vendor/github.com/golang/protobuf/ptypes/duration/duration.proto deleted file mode 100644 index 975fce41aa..0000000000 --- a/vendor/github.com/golang/protobuf/ptypes/duration/duration.proto +++ /dev/null @@ -1,117 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -syntax = "proto3"; - -package google.protobuf; - -option csharp_namespace = "Google.Protobuf.WellKnownTypes"; -option cc_enable_arenas = true; -option go_package = "github.com/golang/protobuf/ptypes/duration"; -option java_package = "com.google.protobuf"; -option java_outer_classname = "DurationProto"; -option java_multiple_files = true; -option objc_class_prefix = "GPB"; - -// A Duration represents a signed, fixed-length span of time represented -// as a count of seconds and fractions of seconds at nanosecond -// resolution. It is independent of any calendar and concepts like "day" -// or "month". It is related to Timestamp in that the difference between -// two Timestamp values is a Duration and it can be added or subtracted -// from a Timestamp. Range is approximately +-10,000 years. -// -// # Examples -// -// Example 1: Compute Duration from two Timestamps in pseudo code. -// -// Timestamp start = ...; -// Timestamp end = ...; -// Duration duration = ...; -// -// duration.seconds = end.seconds - start.seconds; -// duration.nanos = end.nanos - start.nanos; -// -// if (duration.seconds < 0 && duration.nanos > 0) { -// duration.seconds += 1; -// duration.nanos -= 1000000000; -// } else if (durations.seconds > 0 && duration.nanos < 0) { -// duration.seconds -= 1; -// duration.nanos += 1000000000; -// } -// -// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. -// -// Timestamp start = ...; -// Duration duration = ...; -// Timestamp end = ...; -// -// end.seconds = start.seconds + duration.seconds; -// end.nanos = start.nanos + duration.nanos; -// -// if (end.nanos < 0) { -// end.seconds -= 1; -// end.nanos += 1000000000; -// } else if (end.nanos >= 1000000000) { -// end.seconds += 1; -// end.nanos -= 1000000000; -// } -// -// Example 3: Compute Duration from datetime.timedelta in Python. -// -// td = datetime.timedelta(days=3, minutes=10) -// duration = Duration() -// duration.FromTimedelta(td) -// -// # JSON Mapping -// -// In JSON format, the Duration type is encoded as a string rather than an -// object, where the string ends in the suffix "s" (indicating seconds) and -// is preceded by the number of seconds, with nanoseconds expressed as -// fractional seconds. For example, 3 seconds with 0 nanoseconds should be -// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should -// be expressed in JSON format as "3.000000001s", and 3 seconds and 1 -// microsecond should be expressed in JSON format as "3.000001s". -// -// -message Duration { - - // Signed seconds of the span of time. Must be from -315,576,000,000 - // to +315,576,000,000 inclusive. Note: these bounds are computed from: - // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years - int64 seconds = 1; - - // Signed fractions of a second at nanosecond resolution of the span - // of time. Durations less than one second are represented with a 0 - // `seconds` field and a positive or negative `nanos` field. For durations - // of one second or more, a non-zero value for the `nanos` field must be - // of the same sign as the `seconds` field. Must be from -999,999,999 - // to +999,999,999 inclusive. - int32 nanos = 2; -} diff --git a/vendor/github.com/golang/protobuf/ptypes/regen.sh b/vendor/github.com/golang/protobuf/ptypes/regen.sh deleted file mode 100755 index b50a9414ac..0000000000 --- a/vendor/github.com/golang/protobuf/ptypes/regen.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -e -# -# This script fetches and rebuilds the "well-known types" protocol buffers. -# To run this you will need protoc and goprotobuf installed; -# see https://github.com/golang/protobuf for instructions. -# You also need Go and Git installed. - -PKG=github.com/golang/protobuf/ptypes -UPSTREAM=https://github.com/google/protobuf -UPSTREAM_SUBDIR=src/google/protobuf -PROTO_FILES=(any duration empty struct timestamp wrappers) - -function die() { - echo 1>&2 $* - exit 1 -} - -# Sanity check that the right tools are accessible. -for tool in go git protoc protoc-gen-go; do - q=$(which $tool) || die "didn't find $tool" - echo 1>&2 "$tool: $q" -done - -tmpdir=$(mktemp -d -t regen-wkt.XXXXXX) -trap 'rm -rf $tmpdir' EXIT - -echo -n 1>&2 "finding package dir... " -pkgdir=$(go list -f '{{.Dir}}' $PKG) -echo 1>&2 $pkgdir -base=$(echo $pkgdir | sed "s,/$PKG\$,,") -echo 1>&2 "base: $base" -cd "$base" - -echo 1>&2 "fetching latest protos... " -git clone -q $UPSTREAM $tmpdir - -for file in ${PROTO_FILES[@]}; do - echo 1>&2 "* $file" - protoc --go_out=. -I$tmpdir/src $tmpdir/src/google/protobuf/$file.proto || die - cp $tmpdir/src/google/protobuf/$file.proto $PKG/$file -done - -echo 1>&2 "All OK" diff --git a/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto deleted file mode 100644 index b7cbd17502..0000000000 --- a/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto +++ /dev/null @@ -1,133 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -syntax = "proto3"; - -package google.protobuf; - -option csharp_namespace = "Google.Protobuf.WellKnownTypes"; -option cc_enable_arenas = true; -option go_package = "github.com/golang/protobuf/ptypes/timestamp"; -option java_package = "com.google.protobuf"; -option java_outer_classname = "TimestampProto"; -option java_multiple_files = true; -option objc_class_prefix = "GPB"; - -// A Timestamp represents a point in time independent of any time zone -// or calendar, represented as seconds and fractions of seconds at -// nanosecond resolution in UTC Epoch time. It is encoded using the -// Proleptic Gregorian Calendar which extends the Gregorian calendar -// backwards to year one. It is encoded assuming all minutes are 60 -// seconds long, i.e. leap seconds are "smeared" so that no leap second -// table is needed for interpretation. Range is from -// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. -// By restricting to that range, we ensure that we can convert to -// and from RFC 3339 date strings. -// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt). -// -// # Examples -// -// Example 1: Compute Timestamp from POSIX `time()`. -// -// Timestamp timestamp; -// timestamp.set_seconds(time(NULL)); -// timestamp.set_nanos(0); -// -// Example 2: Compute Timestamp from POSIX `gettimeofday()`. -// -// struct timeval tv; -// gettimeofday(&tv, NULL); -// -// Timestamp timestamp; -// timestamp.set_seconds(tv.tv_sec); -// timestamp.set_nanos(tv.tv_usec * 1000); -// -// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. -// -// FILETIME ft; -// GetSystemTimeAsFileTime(&ft); -// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; -// -// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z -// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. -// Timestamp timestamp; -// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); -// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); -// -// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. -// -// long millis = System.currentTimeMillis(); -// -// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) -// .setNanos((int) ((millis % 1000) * 1000000)).build(); -// -// -// Example 5: Compute Timestamp from current time in Python. -// -// timestamp = Timestamp() -// timestamp.GetCurrentTime() -// -// # JSON Mapping -// -// In JSON format, the Timestamp type is encoded as a string in the -// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the -// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" -// where {year} is always expressed using four digits while {month}, {day}, -// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional -// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), -// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone -// is required, though only UTC (as indicated by "Z") is presently supported. -// -// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past -// 01:30 UTC on January 15, 2017. -// -// In JavaScript, one can convert a Date object to this format using the -// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString] -// method. In Python, a standard `datetime.datetime` object can be converted -// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) -// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one -// can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( -// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime()) -// to obtain a formatter capable of generating timestamps in this format. -// -// -message Timestamp { - - // Represents seconds of UTC time since Unix epoch - // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to - // 9999-12-31T23:59:59Z inclusive. - int64 seconds = 1; - - // Non-negative fractions of a second at nanosecond resolution. Negative - // second values with fractions must still have non-negative nanos values - // that count forward in time. Must be from 0 to 999,999,999 - // inclusive. - int32 nanos = 2; -} diff --git a/vendor/github.com/google/btree/.travis.yml b/vendor/github.com/google/btree/.travis.yml deleted file mode 100644 index 4f2ee4d973..0000000000 --- a/vendor/github.com/google/btree/.travis.yml +++ /dev/null @@ -1 +0,0 @@ -language: go diff --git a/vendor/github.com/google/btree/README.md b/vendor/github.com/google/btree/README.md deleted file mode 100644 index 6062a4dacd..0000000000 --- a/vendor/github.com/google/btree/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# BTree implementation for Go - -![Travis CI Build Status](https://api.travis-ci.org/google/btree.svg?branch=master) - -This package provides an in-memory B-Tree implementation for Go, useful as -an ordered, mutable data structure. - -The API is based off of the wonderful -http://godoc.org/github.com/petar/GoLLRB/llrb, and is meant to allow btree to -act as a drop-in replacement for gollrb trees. - -See http://godoc.org/github.com/google/btree for documentation. diff --git a/vendor/github.com/google/gofuzz/.travis.yml b/vendor/github.com/google/gofuzz/.travis.yml deleted file mode 100644 index f8684d99fc..0000000000 --- a/vendor/github.com/google/gofuzz/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: go - -go: - - 1.4 - - 1.3 - - 1.2 - - tip - -install: - - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi - -script: - - go test -cover diff --git a/vendor/github.com/google/gofuzz/CONTRIBUTING.md b/vendor/github.com/google/gofuzz/CONTRIBUTING.md deleted file mode 100644 index 51cf5cd1ad..0000000000 --- a/vendor/github.com/google/gofuzz/CONTRIBUTING.md +++ /dev/null @@ -1,67 +0,0 @@ -# How to contribute # - -We'd love to accept your patches and contributions to this project. There are -a just a few small guidelines you need to follow. - - -## Contributor License Agreement ## - -Contributions to any Google project must be accompanied by a Contributor -License Agreement. This is not a copyright **assignment**, it simply gives -Google permission to use and redistribute your contributions as part of the -project. - - * If you are an individual writing original source code and you're sure you - own the intellectual property, then you'll need to sign an [individual - CLA][]. - - * If you work for a company that wants to allow you to contribute your work, - then you'll need to sign a [corporate CLA][]. - -You generally only need to submit a CLA once, so if you've already submitted -one (even if it was for a different project), you probably don't need to do it -again. - -[individual CLA]: https://developers.google.com/open-source/cla/individual -[corporate CLA]: https://developers.google.com/open-source/cla/corporate - - -## Submitting a patch ## - - 1. It's generally best to start by opening a new issue describing the bug or - feature you're intending to fix. Even if you think it's relatively minor, - it's helpful to know what people are working on. Mention in the initial - issue that you are planning to work on that bug or feature so that it can - be assigned to you. - - 1. Follow the normal process of [forking][] the project, and setup a new - branch to work in. It's important that each group of changes be done in - separate branches in order to ensure that a pull request only includes the - commits related to that bug or feature. - - 1. Go makes it very simple to ensure properly formatted code, so always run - `go fmt` on your code before committing it. You should also run - [golint][] over your code. As noted in the [golint readme][], it's not - strictly necessary that your code be completely "lint-free", but this will - help you find common style issues. - - 1. Any significant changes should almost always be accompanied by tests. The - project already has good test coverage, so look at some of the existing - tests if you're unsure how to go about it. [gocov][] and [gocov-html][] - are invaluable tools for seeing which parts of your code aren't being - exercised by your tests. - - 1. Do your best to have [well-formed commit messages][] for each change. - This provides consistency throughout the project, and ensures that commit - messages are able to be formatted properly by various git tools. - - 1. Finally, push the commits to your fork and submit a [pull request][]. - -[forking]: https://help.github.com/articles/fork-a-repo -[golint]: https://github.com/golang/lint -[golint readme]: https://github.com/golang/lint/blob/master/README -[gocov]: https://github.com/axw/gocov -[gocov-html]: https://github.com/matm/gocov-html -[well-formed commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html -[squash]: http://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits -[pull request]: https://help.github.com/articles/creating-a-pull-request diff --git a/vendor/github.com/google/gofuzz/README.md b/vendor/github.com/google/gofuzz/README.md deleted file mode 100644 index 64869af347..0000000000 --- a/vendor/github.com/google/gofuzz/README.md +++ /dev/null @@ -1,71 +0,0 @@ -gofuzz -====== - -gofuzz is a library for populating go objects with random values. - -[![GoDoc](https://godoc.org/github.com/google/gofuzz?status.png)](https://godoc.org/github.com/google/gofuzz) -[![Travis](https://travis-ci.org/google/gofuzz.svg?branch=master)](https://travis-ci.org/google/gofuzz) - -This is useful for testing: - -* Do your project's objects really serialize/unserialize correctly in all cases? -* Is there an incorrectly formatted object that will cause your project to panic? - -Import with ```import "github.com/google/gofuzz"``` - -You can use it on single variables: -```go -f := fuzz.New() -var myInt int -f.Fuzz(&myInt) // myInt gets a random value. -``` - -You can use it on maps: -```go -f := fuzz.New().NilChance(0).NumElements(1, 1) -var myMap map[ComplexKeyType]string -f.Fuzz(&myMap) // myMap will have exactly one element. -``` - -Customize the chance of getting a nil pointer: -```go -f := fuzz.New().NilChance(.5) -var fancyStruct struct { - A, B, C, D *string -} -f.Fuzz(&fancyStruct) // About half the pointers should be set. -``` - -You can even customize the randomization completely if needed: -```go -type MyEnum string -const ( - A MyEnum = "A" - B MyEnum = "B" -) -type MyInfo struct { - Type MyEnum - AInfo *string - BInfo *string -} - -f := fuzz.New().NilChance(0).Funcs( - func(e *MyInfo, c fuzz.Continue) { - switch c.Intn(2) { - case 0: - e.Type = A - c.Fuzz(&e.AInfo) - case 1: - e.Type = B - c.Fuzz(&e.BInfo) - } - }, -) - -var myObject MyInfo -f.Fuzz(&myObject) // Type will correspond to whether A or B info is set. -``` - -See more examples in ```example_test.go```. - -Happy testing! diff --git a/vendor/github.com/googleapis/gnostic/OpenAPIv2/OpenAPIv2.proto b/vendor/github.com/googleapis/gnostic/OpenAPIv2/OpenAPIv2.proto deleted file mode 100644 index 557c88072c..0000000000 --- a/vendor/github.com/googleapis/gnostic/OpenAPIv2/OpenAPIv2.proto +++ /dev/null @@ -1,663 +0,0 @@ -// Copyright 2017 Google Inc. 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. - -// THIS FILE IS AUTOMATICALLY GENERATED. - -syntax = "proto3"; - -package openapi.v2; - -import "google/protobuf/any.proto"; - -// This option lets the proto compiler generate Java code inside the package -// name (see below) instead of inside an outer class. It creates a simpler -// developer experience by reducing one-level of name nesting and be -// consistent with most programming languages that don't support outer classes. -option java_multiple_files = true; - -// The Java outer classname should be the filename in UpperCamelCase. This -// class is only used to hold proto descriptor, so developers don't need to -// work with it directly. -option java_outer_classname = "OpenAPIProto"; - -// The Java package name must be proto package name with proper prefix. -option java_package = "org.openapi_v2"; - -// A reasonable prefix for the Objective-C symbols generated from the package. -// It should at a minimum be 3 characters long, all uppercase, and convention -// is to use an abbreviation of the package name. Something short, but -// hopefully unique enough to not conflict with things that may come along in -// the future. 'GPB' is reserved for the protocol buffer implementation itself. -option objc_class_prefix = "OAS"; - -message AdditionalPropertiesItem { - oneof oneof { - Schema schema = 1; - bool boolean = 2; - } -} - -message Any { - google.protobuf.Any value = 1; - string yaml = 2; -} - -message ApiKeySecurity { - string type = 1; - string name = 2; - string in = 3; - string description = 4; - repeated NamedAny vendor_extension = 5; -} - -message BasicAuthenticationSecurity { - string type = 1; - string description = 2; - repeated NamedAny vendor_extension = 3; -} - -message BodyParameter { - // A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed. - string description = 1; - // The name of the parameter. - string name = 2; - // Determines the location of the parameter. - string in = 3; - // Determines whether or not this parameter is required or optional. - bool required = 4; - Schema schema = 5; - repeated NamedAny vendor_extension = 6; -} - -// Contact information for the owners of the API. -message Contact { - // The identifying name of the contact person/organization. - string name = 1; - // The URL pointing to the contact information. - string url = 2; - // The email address of the contact person/organization. - string email = 3; - repeated NamedAny vendor_extension = 4; -} - -message Default { - repeated NamedAny additional_properties = 1; -} - -// One or more JSON objects describing the schemas being consumed and produced by the API. -message Definitions { - repeated NamedSchema additional_properties = 1; -} - -message Document { - // The Swagger version of this document. - string swagger = 1; - Info info = 2; - // The host (name or ip) of the API. Example: 'swagger.io' - string host = 3; - // The base path to the API. Example: '/api'. - string base_path = 4; - // The transfer protocol of the API. - repeated string schemes = 5; - // A list of MIME types accepted by the API. - repeated string consumes = 6; - // A list of MIME types the API can produce. - repeated string produces = 7; - Paths paths = 8; - Definitions definitions = 9; - ParameterDefinitions parameters = 10; - ResponseDefinitions responses = 11; - repeated SecurityRequirement security = 12; - SecurityDefinitions security_definitions = 13; - repeated Tag tags = 14; - ExternalDocs external_docs = 15; - repeated NamedAny vendor_extension = 16; -} - -message Examples { - repeated NamedAny additional_properties = 1; -} - -// information about external documentation -message ExternalDocs { - string description = 1; - string url = 2; - repeated NamedAny vendor_extension = 3; -} - -// A deterministic version of a JSON Schema object. -message FileSchema { - string format = 1; - string title = 2; - string description = 3; - Any default = 4; - repeated string required = 5; - string type = 6; - bool read_only = 7; - ExternalDocs external_docs = 8; - Any example = 9; - repeated NamedAny vendor_extension = 10; -} - -message FormDataParameterSubSchema { - // Determines whether or not this parameter is required or optional. - bool required = 1; - // Determines the location of the parameter. - string in = 2; - // A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed. - string description = 3; - // The name of the parameter. - string name = 4; - // allows sending a parameter by name only or with an empty value. - bool allow_empty_value = 5; - string type = 6; - string format = 7; - PrimitivesItems items = 8; - string collection_format = 9; - Any default = 10; - double maximum = 11; - bool exclusive_maximum = 12; - double minimum = 13; - bool exclusive_minimum = 14; - int64 max_length = 15; - int64 min_length = 16; - string pattern = 17; - int64 max_items = 18; - int64 min_items = 19; - bool unique_items = 20; - repeated Any enum = 21; - double multiple_of = 22; - repeated NamedAny vendor_extension = 23; -} - -message Header { - string type = 1; - string format = 2; - PrimitivesItems items = 3; - string collection_format = 4; - Any default = 5; - double maximum = 6; - bool exclusive_maximum = 7; - double minimum = 8; - bool exclusive_minimum = 9; - int64 max_length = 10; - int64 min_length = 11; - string pattern = 12; - int64 max_items = 13; - int64 min_items = 14; - bool unique_items = 15; - repeated Any enum = 16; - double multiple_of = 17; - string description = 18; - repeated NamedAny vendor_extension = 19; -} - -message HeaderParameterSubSchema { - // Determines whether or not this parameter is required or optional. - bool required = 1; - // Determines the location of the parameter. - string in = 2; - // A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed. - string description = 3; - // The name of the parameter. - string name = 4; - string type = 5; - string format = 6; - PrimitivesItems items = 7; - string collection_format = 8; - Any default = 9; - double maximum = 10; - bool exclusive_maximum = 11; - double minimum = 12; - bool exclusive_minimum = 13; - int64 max_length = 14; - int64 min_length = 15; - string pattern = 16; - int64 max_items = 17; - int64 min_items = 18; - bool unique_items = 19; - repeated Any enum = 20; - double multiple_of = 21; - repeated NamedAny vendor_extension = 22; -} - -message Headers { - repeated NamedHeader additional_properties = 1; -} - -// General information about the API. -message Info { - // A unique and precise title of the API. - string title = 1; - // A semantic version number of the API. - string version = 2; - // A longer description of the API. Should be different from the title. GitHub Flavored Markdown is allowed. - string description = 3; - // The terms of service for the API. - string terms_of_service = 4; - Contact contact = 5; - License license = 6; - repeated NamedAny vendor_extension = 7; -} - -message ItemsItem { - repeated Schema schema = 1; -} - -message JsonReference { - string _ref = 1; - string description = 2; -} - -message License { - // The name of the license type. It's encouraged to use an OSI compatible license. - string name = 1; - // The URL pointing to the license. - string url = 2; - repeated NamedAny vendor_extension = 3; -} - -// Automatically-generated message used to represent maps of Any as ordered (name,value) pairs. -message NamedAny { - // Map key - string name = 1; - // Mapped value - Any value = 2; -} - -// Automatically-generated message used to represent maps of Header as ordered (name,value) pairs. -message NamedHeader { - // Map key - string name = 1; - // Mapped value - Header value = 2; -} - -// Automatically-generated message used to represent maps of Parameter as ordered (name,value) pairs. -message NamedParameter { - // Map key - string name = 1; - // Mapped value - Parameter value = 2; -} - -// Automatically-generated message used to represent maps of PathItem as ordered (name,value) pairs. -message NamedPathItem { - // Map key - string name = 1; - // Mapped value - PathItem value = 2; -} - -// Automatically-generated message used to represent maps of Response as ordered (name,value) pairs. -message NamedResponse { - // Map key - string name = 1; - // Mapped value - Response value = 2; -} - -// Automatically-generated message used to represent maps of ResponseValue as ordered (name,value) pairs. -message NamedResponseValue { - // Map key - string name = 1; - // Mapped value - ResponseValue value = 2; -} - -// Automatically-generated message used to represent maps of Schema as ordered (name,value) pairs. -message NamedSchema { - // Map key - string name = 1; - // Mapped value - Schema value = 2; -} - -// Automatically-generated message used to represent maps of SecurityDefinitionsItem as ordered (name,value) pairs. -message NamedSecurityDefinitionsItem { - // Map key - string name = 1; - // Mapped value - SecurityDefinitionsItem value = 2; -} - -// Automatically-generated message used to represent maps of string as ordered (name,value) pairs. -message NamedString { - // Map key - string name = 1; - // Mapped value - string value = 2; -} - -// Automatically-generated message used to represent maps of StringArray as ordered (name,value) pairs. -message NamedStringArray { - // Map key - string name = 1; - // Mapped value - StringArray value = 2; -} - -message NonBodyParameter { - oneof oneof { - HeaderParameterSubSchema header_parameter_sub_schema = 1; - FormDataParameterSubSchema form_data_parameter_sub_schema = 2; - QueryParameterSubSchema query_parameter_sub_schema = 3; - PathParameterSubSchema path_parameter_sub_schema = 4; - } -} - -message Oauth2AccessCodeSecurity { - string type = 1; - string flow = 2; - Oauth2Scopes scopes = 3; - string authorization_url = 4; - string token_url = 5; - string description = 6; - repeated NamedAny vendor_extension = 7; -} - -message Oauth2ApplicationSecurity { - string type = 1; - string flow = 2; - Oauth2Scopes scopes = 3; - string token_url = 4; - string description = 5; - repeated NamedAny vendor_extension = 6; -} - -message Oauth2ImplicitSecurity { - string type = 1; - string flow = 2; - Oauth2Scopes scopes = 3; - string authorization_url = 4; - string description = 5; - repeated NamedAny vendor_extension = 6; -} - -message Oauth2PasswordSecurity { - string type = 1; - string flow = 2; - Oauth2Scopes scopes = 3; - string token_url = 4; - string description = 5; - repeated NamedAny vendor_extension = 6; -} - -message Oauth2Scopes { - repeated NamedString additional_properties = 1; -} - -message Operation { - repeated string tags = 1; - // A brief summary of the operation. - string summary = 2; - // A longer description of the operation, GitHub Flavored Markdown is allowed. - string description = 3; - ExternalDocs external_docs = 4; - // A unique identifier of the operation. - string operation_id = 5; - // A list of MIME types the API can produce. - repeated string produces = 6; - // A list of MIME types the API can consume. - repeated string consumes = 7; - // The parameters needed to send a valid API call. - repeated ParametersItem parameters = 8; - Responses responses = 9; - // The transfer protocol of the API. - repeated string schemes = 10; - bool deprecated = 11; - repeated SecurityRequirement security = 12; - repeated NamedAny vendor_extension = 13; -} - -message Parameter { - oneof oneof { - BodyParameter body_parameter = 1; - NonBodyParameter non_body_parameter = 2; - } -} - -// One or more JSON representations for parameters -message ParameterDefinitions { - repeated NamedParameter additional_properties = 1; -} - -message ParametersItem { - oneof oneof { - Parameter parameter = 1; - JsonReference json_reference = 2; - } -} - -message PathItem { - string _ref = 1; - Operation get = 2; - Operation put = 3; - Operation post = 4; - Operation delete = 5; - Operation options = 6; - Operation head = 7; - Operation patch = 8; - // The parameters needed to send a valid API call. - repeated ParametersItem parameters = 9; - repeated NamedAny vendor_extension = 10; -} - -message PathParameterSubSchema { - // Determines whether or not this parameter is required or optional. - bool required = 1; - // Determines the location of the parameter. - string in = 2; - // A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed. - string description = 3; - // The name of the parameter. - string name = 4; - string type = 5; - string format = 6; - PrimitivesItems items = 7; - string collection_format = 8; - Any default = 9; - double maximum = 10; - bool exclusive_maximum = 11; - double minimum = 12; - bool exclusive_minimum = 13; - int64 max_length = 14; - int64 min_length = 15; - string pattern = 16; - int64 max_items = 17; - int64 min_items = 18; - bool unique_items = 19; - repeated Any enum = 20; - double multiple_of = 21; - repeated NamedAny vendor_extension = 22; -} - -// Relative paths to the individual endpoints. They must be relative to the 'basePath'. -message Paths { - repeated NamedAny vendor_extension = 1; - repeated NamedPathItem path = 2; -} - -message PrimitivesItems { - string type = 1; - string format = 2; - PrimitivesItems items = 3; - string collection_format = 4; - Any default = 5; - double maximum = 6; - bool exclusive_maximum = 7; - double minimum = 8; - bool exclusive_minimum = 9; - int64 max_length = 10; - int64 min_length = 11; - string pattern = 12; - int64 max_items = 13; - int64 min_items = 14; - bool unique_items = 15; - repeated Any enum = 16; - double multiple_of = 17; - repeated NamedAny vendor_extension = 18; -} - -message Properties { - repeated NamedSchema additional_properties = 1; -} - -message QueryParameterSubSchema { - // Determines whether or not this parameter is required or optional. - bool required = 1; - // Determines the location of the parameter. - string in = 2; - // A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed. - string description = 3; - // The name of the parameter. - string name = 4; - // allows sending a parameter by name only or with an empty value. - bool allow_empty_value = 5; - string type = 6; - string format = 7; - PrimitivesItems items = 8; - string collection_format = 9; - Any default = 10; - double maximum = 11; - bool exclusive_maximum = 12; - double minimum = 13; - bool exclusive_minimum = 14; - int64 max_length = 15; - int64 min_length = 16; - string pattern = 17; - int64 max_items = 18; - int64 min_items = 19; - bool unique_items = 20; - repeated Any enum = 21; - double multiple_of = 22; - repeated NamedAny vendor_extension = 23; -} - -message Response { - string description = 1; - SchemaItem schema = 2; - Headers headers = 3; - Examples examples = 4; - repeated NamedAny vendor_extension = 5; -} - -// One or more JSON representations for parameters -message ResponseDefinitions { - repeated NamedResponse additional_properties = 1; -} - -message ResponseValue { - oneof oneof { - Response response = 1; - JsonReference json_reference = 2; - } -} - -// Response objects names can either be any valid HTTP status code or 'default'. -message Responses { - repeated NamedResponseValue response_code = 1; - repeated NamedAny vendor_extension = 2; -} - -// A deterministic version of a JSON Schema object. -message Schema { - string _ref = 1; - string format = 2; - string title = 3; - string description = 4; - Any default = 5; - double multiple_of = 6; - double maximum = 7; - bool exclusive_maximum = 8; - double minimum = 9; - bool exclusive_minimum = 10; - int64 max_length = 11; - int64 min_length = 12; - string pattern = 13; - int64 max_items = 14; - int64 min_items = 15; - bool unique_items = 16; - int64 max_properties = 17; - int64 min_properties = 18; - repeated string required = 19; - repeated Any enum = 20; - AdditionalPropertiesItem additional_properties = 21; - TypeItem type = 22; - ItemsItem items = 23; - repeated Schema all_of = 24; - Properties properties = 25; - string discriminator = 26; - bool read_only = 27; - Xml xml = 28; - ExternalDocs external_docs = 29; - Any example = 30; - repeated NamedAny vendor_extension = 31; -} - -message SchemaItem { - oneof oneof { - Schema schema = 1; - FileSchema file_schema = 2; - } -} - -message SecurityDefinitions { - repeated NamedSecurityDefinitionsItem additional_properties = 1; -} - -message SecurityDefinitionsItem { - oneof oneof { - BasicAuthenticationSecurity basic_authentication_security = 1; - ApiKeySecurity api_key_security = 2; - Oauth2ImplicitSecurity oauth2_implicit_security = 3; - Oauth2PasswordSecurity oauth2_password_security = 4; - Oauth2ApplicationSecurity oauth2_application_security = 5; - Oauth2AccessCodeSecurity oauth2_access_code_security = 6; - } -} - -message SecurityRequirement { - repeated NamedStringArray additional_properties = 1; -} - -message StringArray { - repeated string value = 1; -} - -message Tag { - string name = 1; - string description = 2; - ExternalDocs external_docs = 3; - repeated NamedAny vendor_extension = 4; -} - -message TypeItem { - repeated string value = 1; -} - -// Any property starting with x- is valid. -message VendorExtension { - repeated NamedAny additional_properties = 1; -} - -message Xml { - string name = 1; - string namespace = 2; - string prefix = 3; - bool attribute = 4; - bool wrapped = 5; - repeated NamedAny vendor_extension = 6; -} - diff --git a/vendor/github.com/googleapis/gnostic/OpenAPIv2/README.md b/vendor/github.com/googleapis/gnostic/OpenAPIv2/README.md deleted file mode 100644 index 836fb32a7e..0000000000 --- a/vendor/github.com/googleapis/gnostic/OpenAPIv2/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# OpenAPI v2 Protocol Buffer Models - -This directory contains a Protocol Buffer-language model -and related code for supporting OpenAPI v2. - -Gnostic applications and plugins can use OpenAPIv2.proto -to generate Protocol Buffer support code for their preferred languages. - -OpenAPIv2.go is used by Gnostic to read JSON and YAML OpenAPI -descriptions into the Protocol Buffer-based datastructures -generated from OpenAPIv2.proto. - -OpenAPIv2.proto and OpenAPIv2.go are generated by the Gnostic -compiler generator, and OpenAPIv2.pb.go is generated by -protoc, the Protocol Buffer compiler, and protoc-gen-go, the -Protocol Buffer Go code generation plugin. diff --git a/vendor/github.com/googleapis/gnostic/OpenAPIv2/openapi-2.0.json b/vendor/github.com/googleapis/gnostic/OpenAPIv2/openapi-2.0.json deleted file mode 100644 index 2815a26ea7..0000000000 --- a/vendor/github.com/googleapis/gnostic/OpenAPIv2/openapi-2.0.json +++ /dev/null @@ -1,1610 +0,0 @@ -{ - "title": "A JSON Schema for Swagger 2.0 API.", - "id": "http://swagger.io/v2/schema.json#", - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": [ - "swagger", - "info", - "paths" - ], - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "properties": { - "swagger": { - "type": "string", - "enum": [ - "2.0" - ], - "description": "The Swagger version of this document." - }, - "info": { - "$ref": "#/definitions/info" - }, - "host": { - "type": "string", - "pattern": "^[^{}/ :\\\\]+(?::\\d+)?$", - "description": "The host (name or ip) of the API. Example: 'swagger.io'" - }, - "basePath": { - "type": "string", - "pattern": "^/", - "description": "The base path to the API. Example: '/api'." - }, - "schemes": { - "$ref": "#/definitions/schemesList" - }, - "consumes": { - "description": "A list of MIME types accepted by the API.", - "allOf": [ - { - "$ref": "#/definitions/mediaTypeList" - } - ] - }, - "produces": { - "description": "A list of MIME types the API can produce.", - "allOf": [ - { - "$ref": "#/definitions/mediaTypeList" - } - ] - }, - "paths": { - "$ref": "#/definitions/paths" - }, - "definitions": { - "$ref": "#/definitions/definitions" - }, - "parameters": { - "$ref": "#/definitions/parameterDefinitions" - }, - "responses": { - "$ref": "#/definitions/responseDefinitions" - }, - "security": { - "$ref": "#/definitions/security" - }, - "securityDefinitions": { - "$ref": "#/definitions/securityDefinitions" - }, - "tags": { - "type": "array", - "items": { - "$ref": "#/definitions/tag" - }, - "uniqueItems": true - }, - "externalDocs": { - "$ref": "#/definitions/externalDocs" - } - }, - "definitions": { - "info": { - "type": "object", - "description": "General information about the API.", - "required": [ - "version", - "title" - ], - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "properties": { - "title": { - "type": "string", - "description": "A unique and precise title of the API." - }, - "version": { - "type": "string", - "description": "A semantic version number of the API." - }, - "description": { - "type": "string", - "description": "A longer description of the API. Should be different from the title. GitHub Flavored Markdown is allowed." - }, - "termsOfService": { - "type": "string", - "description": "The terms of service for the API." - }, - "contact": { - "$ref": "#/definitions/contact" - }, - "license": { - "$ref": "#/definitions/license" - } - } - }, - "contact": { - "type": "object", - "description": "Contact information for the owners of the API.", - "additionalProperties": false, - "properties": { - "name": { - "type": "string", - "description": "The identifying name of the contact person/organization." - }, - "url": { - "type": "string", - "description": "The URL pointing to the contact information.", - "format": "uri" - }, - "email": { - "type": "string", - "description": "The email address of the contact person/organization.", - "format": "email" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "license": { - "type": "object", - "required": [ - "name" - ], - "additionalProperties": false, - "properties": { - "name": { - "type": "string", - "description": "The name of the license type. It's encouraged to use an OSI compatible license." - }, - "url": { - "type": "string", - "description": "The URL pointing to the license.", - "format": "uri" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "paths": { - "type": "object", - "description": "Relative paths to the individual endpoints. They must be relative to the 'basePath'.", - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - }, - "^/": { - "$ref": "#/definitions/pathItem" - } - }, - "additionalProperties": false - }, - "definitions": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/schema" - }, - "description": "One or more JSON objects describing the schemas being consumed and produced by the API." - }, - "parameterDefinitions": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/parameter" - }, - "description": "One or more JSON representations for parameters" - }, - "responseDefinitions": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/response" - }, - "description": "One or more JSON representations for parameters" - }, - "externalDocs": { - "type": "object", - "additionalProperties": false, - "description": "information about external documentation", - "required": [ - "url" - ], - "properties": { - "description": { - "type": "string" - }, - "url": { - "type": "string", - "format": "uri" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "examples": { - "type": "object", - "additionalProperties": true - }, - "mimeType": { - "type": "string", - "description": "The MIME type of the HTTP message." - }, - "operation": { - "type": "object", - "required": [ - "responses" - ], - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "properties": { - "tags": { - "type": "array", - "items": { - "type": "string" - }, - "uniqueItems": true - }, - "summary": { - "type": "string", - "description": "A brief summary of the operation." - }, - "description": { - "type": "string", - "description": "A longer description of the operation, GitHub Flavored Markdown is allowed." - }, - "externalDocs": { - "$ref": "#/definitions/externalDocs" - }, - "operationId": { - "type": "string", - "description": "A unique identifier of the operation." - }, - "produces": { - "description": "A list of MIME types the API can produce.", - "allOf": [ - { - "$ref": "#/definitions/mediaTypeList" - } - ] - }, - "consumes": { - "description": "A list of MIME types the API can consume.", - "allOf": [ - { - "$ref": "#/definitions/mediaTypeList" - } - ] - }, - "parameters": { - "$ref": "#/definitions/parametersList" - }, - "responses": { - "$ref": "#/definitions/responses" - }, - "schemes": { - "$ref": "#/definitions/schemesList" - }, - "deprecated": { - "type": "boolean", - "default": false - }, - "security": { - "$ref": "#/definitions/security" - } - } - }, - "pathItem": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "properties": { - "$ref": { - "type": "string" - }, - "get": { - "$ref": "#/definitions/operation" - }, - "put": { - "$ref": "#/definitions/operation" - }, - "post": { - "$ref": "#/definitions/operation" - }, - "delete": { - "$ref": "#/definitions/operation" - }, - "options": { - "$ref": "#/definitions/operation" - }, - "head": { - "$ref": "#/definitions/operation" - }, - "patch": { - "$ref": "#/definitions/operation" - }, - "parameters": { - "$ref": "#/definitions/parametersList" - } - } - }, - "responses": { - "type": "object", - "description": "Response objects names can either be any valid HTTP status code or 'default'.", - "minProperties": 1, - "additionalProperties": false, - "patternProperties": { - "^([0-9]{3})$|^(default)$": { - "$ref": "#/definitions/responseValue" - }, - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "not": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - } - }, - "responseValue": { - "oneOf": [ - { - "$ref": "#/definitions/response" - }, - { - "$ref": "#/definitions/jsonReference" - } - ] - }, - "response": { - "type": "object", - "required": [ - "description" - ], - "properties": { - "description": { - "type": "string" - }, - "schema": { - "oneOf": [ - { - "$ref": "#/definitions/schema" - }, - { - "$ref": "#/definitions/fileSchema" - } - ] - }, - "headers": { - "$ref": "#/definitions/headers" - }, - "examples": { - "$ref": "#/definitions/examples" - } - }, - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "headers": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/header" - } - }, - "header": { - "type": "object", - "additionalProperties": false, - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "string", - "number", - "integer", - "boolean", - "array" - ] - }, - "format": { - "type": "string" - }, - "items": { - "$ref": "#/definitions/primitivesItems" - }, - "collectionFormat": { - "$ref": "#/definitions/collectionFormat" - }, - "default": { - "$ref": "#/definitions/default" - }, - "maximum": { - "$ref": "#/definitions/maximum" - }, - "exclusiveMaximum": { - "$ref": "#/definitions/exclusiveMaximum" - }, - "minimum": { - "$ref": "#/definitions/minimum" - }, - "exclusiveMinimum": { - "$ref": "#/definitions/exclusiveMinimum" - }, - "maxLength": { - "$ref": "#/definitions/maxLength" - }, - "minLength": { - "$ref": "#/definitions/minLength" - }, - "pattern": { - "$ref": "#/definitions/pattern" - }, - "maxItems": { - "$ref": "#/definitions/maxItems" - }, - "minItems": { - "$ref": "#/definitions/minItems" - }, - "uniqueItems": { - "$ref": "#/definitions/uniqueItems" - }, - "enum": { - "$ref": "#/definitions/enum" - }, - "multipleOf": { - "$ref": "#/definitions/multipleOf" - }, - "description": { - "type": "string" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "vendorExtension": { - "description": "Any property starting with x- is valid.", - "additionalProperties": true, - "additionalItems": true - }, - "bodyParameter": { - "type": "object", - "required": [ - "name", - "in", - "schema" - ], - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "properties": { - "description": { - "type": "string", - "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." - }, - "name": { - "type": "string", - "description": "The name of the parameter." - }, - "in": { - "type": "string", - "description": "Determines the location of the parameter.", - "enum": [ - "body" - ] - }, - "required": { - "type": "boolean", - "description": "Determines whether or not this parameter is required or optional.", - "default": false - }, - "schema": { - "$ref": "#/definitions/schema" - } - }, - "additionalProperties": false - }, - "headerParameterSubSchema": { - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "properties": { - "required": { - "type": "boolean", - "description": "Determines whether or not this parameter is required or optional.", - "default": false - }, - "in": { - "type": "string", - "description": "Determines the location of the parameter.", - "enum": [ - "header" - ] - }, - "description": { - "type": "string", - "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." - }, - "name": { - "type": "string", - "description": "The name of the parameter." - }, - "type": { - "type": "string", - "enum": [ - "string", - "number", - "boolean", - "integer", - "array" - ] - }, - "format": { - "type": "string" - }, - "items": { - "$ref": "#/definitions/primitivesItems" - }, - "collectionFormat": { - "$ref": "#/definitions/collectionFormat" - }, - "default": { - "$ref": "#/definitions/default" - }, - "maximum": { - "$ref": "#/definitions/maximum" - }, - "exclusiveMaximum": { - "$ref": "#/definitions/exclusiveMaximum" - }, - "minimum": { - "$ref": "#/definitions/minimum" - }, - "exclusiveMinimum": { - "$ref": "#/definitions/exclusiveMinimum" - }, - "maxLength": { - "$ref": "#/definitions/maxLength" - }, - "minLength": { - "$ref": "#/definitions/minLength" - }, - "pattern": { - "$ref": "#/definitions/pattern" - }, - "maxItems": { - "$ref": "#/definitions/maxItems" - }, - "minItems": { - "$ref": "#/definitions/minItems" - }, - "uniqueItems": { - "$ref": "#/definitions/uniqueItems" - }, - "enum": { - "$ref": "#/definitions/enum" - }, - "multipleOf": { - "$ref": "#/definitions/multipleOf" - } - } - }, - "queryParameterSubSchema": { - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "properties": { - "required": { - "type": "boolean", - "description": "Determines whether or not this parameter is required or optional.", - "default": false - }, - "in": { - "type": "string", - "description": "Determines the location of the parameter.", - "enum": [ - "query" - ] - }, - "description": { - "type": "string", - "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." - }, - "name": { - "type": "string", - "description": "The name of the parameter." - }, - "allowEmptyValue": { - "type": "boolean", - "default": false, - "description": "allows sending a parameter by name only or with an empty value." - }, - "type": { - "type": "string", - "enum": [ - "string", - "number", - "boolean", - "integer", - "array" - ] - }, - "format": { - "type": "string" - }, - "items": { - "$ref": "#/definitions/primitivesItems" - }, - "collectionFormat": { - "$ref": "#/definitions/collectionFormatWithMulti" - }, - "default": { - "$ref": "#/definitions/default" - }, - "maximum": { - "$ref": "#/definitions/maximum" - }, - "exclusiveMaximum": { - "$ref": "#/definitions/exclusiveMaximum" - }, - "minimum": { - "$ref": "#/definitions/minimum" - }, - "exclusiveMinimum": { - "$ref": "#/definitions/exclusiveMinimum" - }, - "maxLength": { - "$ref": "#/definitions/maxLength" - }, - "minLength": { - "$ref": "#/definitions/minLength" - }, - "pattern": { - "$ref": "#/definitions/pattern" - }, - "maxItems": { - "$ref": "#/definitions/maxItems" - }, - "minItems": { - "$ref": "#/definitions/minItems" - }, - "uniqueItems": { - "$ref": "#/definitions/uniqueItems" - }, - "enum": { - "$ref": "#/definitions/enum" - }, - "multipleOf": { - "$ref": "#/definitions/multipleOf" - } - } - }, - "formDataParameterSubSchema": { - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "properties": { - "required": { - "type": "boolean", - "description": "Determines whether or not this parameter is required or optional.", - "default": false - }, - "in": { - "type": "string", - "description": "Determines the location of the parameter.", - "enum": [ - "formData" - ] - }, - "description": { - "type": "string", - "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." - }, - "name": { - "type": "string", - "description": "The name of the parameter." - }, - "allowEmptyValue": { - "type": "boolean", - "default": false, - "description": "allows sending a parameter by name only or with an empty value." - }, - "type": { - "type": "string", - "enum": [ - "string", - "number", - "boolean", - "integer", - "array", - "file" - ] - }, - "format": { - "type": "string" - }, - "items": { - "$ref": "#/definitions/primitivesItems" - }, - "collectionFormat": { - "$ref": "#/definitions/collectionFormatWithMulti" - }, - "default": { - "$ref": "#/definitions/default" - }, - "maximum": { - "$ref": "#/definitions/maximum" - }, - "exclusiveMaximum": { - "$ref": "#/definitions/exclusiveMaximum" - }, - "minimum": { - "$ref": "#/definitions/minimum" - }, - "exclusiveMinimum": { - "$ref": "#/definitions/exclusiveMinimum" - }, - "maxLength": { - "$ref": "#/definitions/maxLength" - }, - "minLength": { - "$ref": "#/definitions/minLength" - }, - "pattern": { - "$ref": "#/definitions/pattern" - }, - "maxItems": { - "$ref": "#/definitions/maxItems" - }, - "minItems": { - "$ref": "#/definitions/minItems" - }, - "uniqueItems": { - "$ref": "#/definitions/uniqueItems" - }, - "enum": { - "$ref": "#/definitions/enum" - }, - "multipleOf": { - "$ref": "#/definitions/multipleOf" - } - } - }, - "pathParameterSubSchema": { - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "required": [ - "required" - ], - "properties": { - "required": { - "type": "boolean", - "enum": [ - true - ], - "description": "Determines whether or not this parameter is required or optional." - }, - "in": { - "type": "string", - "description": "Determines the location of the parameter.", - "enum": [ - "path" - ] - }, - "description": { - "type": "string", - "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." - }, - "name": { - "type": "string", - "description": "The name of the parameter." - }, - "type": { - "type": "string", - "enum": [ - "string", - "number", - "boolean", - "integer", - "array" - ] - }, - "format": { - "type": "string" - }, - "items": { - "$ref": "#/definitions/primitivesItems" - }, - "collectionFormat": { - "$ref": "#/definitions/collectionFormat" - }, - "default": { - "$ref": "#/definitions/default" - }, - "maximum": { - "$ref": "#/definitions/maximum" - }, - "exclusiveMaximum": { - "$ref": "#/definitions/exclusiveMaximum" - }, - "minimum": { - "$ref": "#/definitions/minimum" - }, - "exclusiveMinimum": { - "$ref": "#/definitions/exclusiveMinimum" - }, - "maxLength": { - "$ref": "#/definitions/maxLength" - }, - "minLength": { - "$ref": "#/definitions/minLength" - }, - "pattern": { - "$ref": "#/definitions/pattern" - }, - "maxItems": { - "$ref": "#/definitions/maxItems" - }, - "minItems": { - "$ref": "#/definitions/minItems" - }, - "uniqueItems": { - "$ref": "#/definitions/uniqueItems" - }, - "enum": { - "$ref": "#/definitions/enum" - }, - "multipleOf": { - "$ref": "#/definitions/multipleOf" - } - } - }, - "nonBodyParameter": { - "type": "object", - "required": [ - "name", - "in", - "type" - ], - "oneOf": [ - { - "$ref": "#/definitions/headerParameterSubSchema" - }, - { - "$ref": "#/definitions/formDataParameterSubSchema" - }, - { - "$ref": "#/definitions/queryParameterSubSchema" - }, - { - "$ref": "#/definitions/pathParameterSubSchema" - } - ] - }, - "parameter": { - "oneOf": [ - { - "$ref": "#/definitions/bodyParameter" - }, - { - "$ref": "#/definitions/nonBodyParameter" - } - ] - }, - "schema": { - "type": "object", - "description": "A deterministic version of a JSON Schema object.", - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "properties": { - "$ref": { - "type": "string" - }, - "format": { - "type": "string" - }, - "title": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/title" - }, - "description": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/description" - }, - "default": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/default" - }, - "multipleOf": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/multipleOf" - }, - "maximum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/maximum" - }, - "exclusiveMaximum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMaximum" - }, - "minimum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/minimum" - }, - "exclusiveMinimum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMinimum" - }, - "maxLength": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" - }, - "minLength": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" - }, - "pattern": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/pattern" - }, - "maxItems": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" - }, - "minItems": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" - }, - "uniqueItems": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/uniqueItems" - }, - "maxProperties": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" - }, - "minProperties": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" - }, - "required": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/stringArray" - }, - "enum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/enum" - }, - "additionalProperties": { - "oneOf": [ - { - "$ref": "#/definitions/schema" - }, - { - "type": "boolean" - } - ], - "default": {} - }, - "type": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/type" - }, - "items": { - "anyOf": [ - { - "$ref": "#/definitions/schema" - }, - { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/definitions/schema" - } - } - ], - "default": {} - }, - "allOf": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/definitions/schema" - } - }, - "properties": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/schema" - }, - "default": {} - }, - "discriminator": { - "type": "string" - }, - "readOnly": { - "type": "boolean", - "default": false - }, - "xml": { - "$ref": "#/definitions/xml" - }, - "externalDocs": { - "$ref": "#/definitions/externalDocs" - }, - "example": {} - }, - "additionalProperties": false - }, - "fileSchema": { - "type": "object", - "description": "A deterministic version of a JSON Schema object.", - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "required": [ - "type" - ], - "properties": { - "format": { - "type": "string" - }, - "title": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/title" - }, - "description": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/description" - }, - "default": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/default" - }, - "required": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/stringArray" - }, - "type": { - "type": "string", - "enum": [ - "file" - ] - }, - "readOnly": { - "type": "boolean", - "default": false - }, - "externalDocs": { - "$ref": "#/definitions/externalDocs" - }, - "example": {} - }, - "additionalProperties": false - }, - "primitivesItems": { - "type": "object", - "additionalProperties": false, - "properties": { - "type": { - "type": "string", - "enum": [ - "string", - "number", - "integer", - "boolean", - "array" - ] - }, - "format": { - "type": "string" - }, - "items": { - "$ref": "#/definitions/primitivesItems" - }, - "collectionFormat": { - "$ref": "#/definitions/collectionFormat" - }, - "default": { - "$ref": "#/definitions/default" - }, - "maximum": { - "$ref": "#/definitions/maximum" - }, - "exclusiveMaximum": { - "$ref": "#/definitions/exclusiveMaximum" - }, - "minimum": { - "$ref": "#/definitions/minimum" - }, - "exclusiveMinimum": { - "$ref": "#/definitions/exclusiveMinimum" - }, - "maxLength": { - "$ref": "#/definitions/maxLength" - }, - "minLength": { - "$ref": "#/definitions/minLength" - }, - "pattern": { - "$ref": "#/definitions/pattern" - }, - "maxItems": { - "$ref": "#/definitions/maxItems" - }, - "minItems": { - "$ref": "#/definitions/minItems" - }, - "uniqueItems": { - "$ref": "#/definitions/uniqueItems" - }, - "enum": { - "$ref": "#/definitions/enum" - }, - "multipleOf": { - "$ref": "#/definitions/multipleOf" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "security": { - "type": "array", - "items": { - "$ref": "#/definitions/securityRequirement" - }, - "uniqueItems": true - }, - "securityRequirement": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - }, - "uniqueItems": true - } - }, - "xml": { - "type": "object", - "additionalProperties": false, - "properties": { - "name": { - "type": "string" - }, - "namespace": { - "type": "string" - }, - "prefix": { - "type": "string" - }, - "attribute": { - "type": "boolean", - "default": false - }, - "wrapped": { - "type": "boolean", - "default": false - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "tag": { - "type": "object", - "additionalProperties": false, - "required": [ - "name" - ], - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "externalDocs": { - "$ref": "#/definitions/externalDocs" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "securityDefinitions": { - "type": "object", - "additionalProperties": { - "oneOf": [ - { - "$ref": "#/definitions/basicAuthenticationSecurity" - }, - { - "$ref": "#/definitions/apiKeySecurity" - }, - { - "$ref": "#/definitions/oauth2ImplicitSecurity" - }, - { - "$ref": "#/definitions/oauth2PasswordSecurity" - }, - { - "$ref": "#/definitions/oauth2ApplicationSecurity" - }, - { - "$ref": "#/definitions/oauth2AccessCodeSecurity" - } - ] - } - }, - "basicAuthenticationSecurity": { - "type": "object", - "additionalProperties": false, - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "basic" - ] - }, - "description": { - "type": "string" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "apiKeySecurity": { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "name", - "in" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "apiKey" - ] - }, - "name": { - "type": "string" - }, - "in": { - "type": "string", - "enum": [ - "header", - "query" - ] - }, - "description": { - "type": "string" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "oauth2ImplicitSecurity": { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "flow", - "authorizationUrl" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "oauth2" - ] - }, - "flow": { - "type": "string", - "enum": [ - "implicit" - ] - }, - "scopes": { - "$ref": "#/definitions/oauth2Scopes" - }, - "authorizationUrl": { - "type": "string", - "format": "uri" - }, - "description": { - "type": "string" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "oauth2PasswordSecurity": { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "flow", - "tokenUrl" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "oauth2" - ] - }, - "flow": { - "type": "string", - "enum": [ - "password" - ] - }, - "scopes": { - "$ref": "#/definitions/oauth2Scopes" - }, - "tokenUrl": { - "type": "string", - "format": "uri" - }, - "description": { - "type": "string" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "oauth2ApplicationSecurity": { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "flow", - "tokenUrl" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "oauth2" - ] - }, - "flow": { - "type": "string", - "enum": [ - "application" - ] - }, - "scopes": { - "$ref": "#/definitions/oauth2Scopes" - }, - "tokenUrl": { - "type": "string", - "format": "uri" - }, - "description": { - "type": "string" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "oauth2AccessCodeSecurity": { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "flow", - "authorizationUrl", - "tokenUrl" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "oauth2" - ] - }, - "flow": { - "type": "string", - "enum": [ - "accessCode" - ] - }, - "scopes": { - "$ref": "#/definitions/oauth2Scopes" - }, - "authorizationUrl": { - "type": "string", - "format": "uri" - }, - "tokenUrl": { - "type": "string", - "format": "uri" - }, - "description": { - "type": "string" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "oauth2Scopes": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "mediaTypeList": { - "type": "array", - "items": { - "$ref": "#/definitions/mimeType" - }, - "uniqueItems": true - }, - "parametersList": { - "type": "array", - "description": "The parameters needed to send a valid API call.", - "additionalItems": false, - "items": { - "oneOf": [ - { - "$ref": "#/definitions/parameter" - }, - { - "$ref": "#/definitions/jsonReference" - } - ] - }, - "uniqueItems": true - }, - "schemesList": { - "type": "array", - "description": "The transfer protocol of the API.", - "items": { - "type": "string", - "enum": [ - "http", - "https", - "ws", - "wss" - ] - }, - "uniqueItems": true - }, - "collectionFormat": { - "type": "string", - "enum": [ - "csv", - "ssv", - "tsv", - "pipes" - ], - "default": "csv" - }, - "collectionFormatWithMulti": { - "type": "string", - "enum": [ - "csv", - "ssv", - "tsv", - "pipes", - "multi" - ], - "default": "csv" - }, - "title": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/title" - }, - "description": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/description" - }, - "default": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/default" - }, - "multipleOf": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/multipleOf" - }, - "maximum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/maximum" - }, - "exclusiveMaximum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMaximum" - }, - "minimum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/minimum" - }, - "exclusiveMinimum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMinimum" - }, - "maxLength": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" - }, - "minLength": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" - }, - "pattern": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/pattern" - }, - "maxItems": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" - }, - "minItems": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" - }, - "uniqueItems": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/uniqueItems" - }, - "enum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/enum" - }, - "jsonReference": { - "type": "object", - "required": [ - "$ref" - ], - "additionalProperties": false, - "properties": { - "$ref": { - "type": "string" - }, - "description": { - "type": "string" - } - } - } - } -} diff --git a/vendor/github.com/googleapis/gnostic/compiler/README.md b/vendor/github.com/googleapis/gnostic/compiler/README.md deleted file mode 100644 index 848b16c69b..0000000000 --- a/vendor/github.com/googleapis/gnostic/compiler/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Compiler support code - -This directory contains compiler support code used by Gnostic and Gnostic extensions. \ No newline at end of file diff --git a/vendor/github.com/googleapis/gnostic/extensions/COMPILE-EXTENSION.sh b/vendor/github.com/googleapis/gnostic/extensions/COMPILE-EXTENSION.sh deleted file mode 100755 index 68d02a02ac..0000000000 --- a/vendor/github.com/googleapis/gnostic/extensions/COMPILE-EXTENSION.sh +++ /dev/null @@ -1,5 +0,0 @@ -go get github.com/golang/protobuf/protoc-gen-go - -protoc \ ---go_out=Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. *.proto - diff --git a/vendor/github.com/googleapis/gnostic/extensions/README.md b/vendor/github.com/googleapis/gnostic/extensions/README.md deleted file mode 100644 index ff1c2eb1e3..0000000000 --- a/vendor/github.com/googleapis/gnostic/extensions/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Extensions - -This directory contains support code for building Gnostic extensions and associated examples. - -Extensions are used to compile vendor or specification extensions into protocol buffer structures. diff --git a/vendor/github.com/googleapis/gnostic/extensions/extension.proto b/vendor/github.com/googleapis/gnostic/extensions/extension.proto deleted file mode 100644 index 806760a132..0000000000 --- a/vendor/github.com/googleapis/gnostic/extensions/extension.proto +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2017 Google Inc. 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. - -syntax = "proto3"; - -import "google/protobuf/any.proto"; -package openapiextension.v1; - -// This option lets the proto compiler generate Java code inside the package -// name (see below) instead of inside an outer class. It creates a simpler -// developer experience by reducing one-level of name nesting and be -// consistent with most programming languages that don't support outer classes. -option java_multiple_files = true; - -// The Java outer classname should be the filename in UpperCamelCase. This -// class is only used to hold proto descriptor, so developers don't need to -// work with it directly. -option java_outer_classname = "OpenAPIExtensionV1"; - -// The Java package name must be proto package name with proper prefix. -option java_package = "org.openapic.v1"; - -// A reasonable prefix for the Objective-C symbols generated from the package. -// It should at a minimum be 3 characters long, all uppercase, and convention -// is to use an abbreviation of the package name. Something short, but -// hopefully unique enough to not conflict with things that may come along in -// the future. 'GPB' is reserved for the protocol buffer implementation itself. -// -option objc_class_prefix = "OAE"; // "OpenAPI Extension" - -// The version number of OpenAPI compiler. -message Version { - int32 major = 1; - int32 minor = 2; - int32 patch = 3; - // A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should - // be empty for mainline stable releases. - string suffix = 4; -} - -// An encoded Request is written to the ExtensionHandler's stdin. -message ExtensionHandlerRequest { - - // The OpenAPI descriptions that were explicitly listed on the command line. - // The specifications will appear in the order they are specified to openapic. - Wrapper wrapper = 1; - - // The version number of openapi compiler. - Version compiler_version = 3; -} - -// The extensions writes an encoded ExtensionHandlerResponse to stdout. -message ExtensionHandlerResponse { - - // true if the extension is handled by the extension handler; false otherwise - bool handled = 1; - - // Error message. If non-empty, the extension handling failed. - // The extension handler process should exit with status code zero - // even if it reports an error in this way. - // - // This should be used to indicate errors which prevent the extension from - // operating as intended. Errors which indicate a problem in gnostic - // itself -- such as the input Document being unparseable -- should be - // reported by writing a message to stderr and exiting with a non-zero - // status code. - repeated string error = 2; - - // text output - google.protobuf.Any value = 3; -} - -message Wrapper { - // version of the OpenAPI specification in which this extension was written. - string version = 1; - - // Name of the extension - string extension_name = 2; - - // Must be a valid yaml for the proto - string yaml = 3; -} diff --git a/vendor/github.com/gregjones/httpcache/.travis.yml b/vendor/github.com/gregjones/httpcache/.travis.yml deleted file mode 100644 index b5ffbe03d8..0000000000 --- a/vendor/github.com/gregjones/httpcache/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -sudo: false -language: go -go: - - 1.6.x - - 1.7.x - - 1.8.x - - 1.9.x - - master -matrix: - allow_failures: - - go: master - fast_finish: true -install: - - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step). -script: - - go get -t -v ./... - - diff -u <(echo -n) <(gofmt -d .) - - go tool vet . - - go test -v -race ./... diff --git a/vendor/github.com/gregjones/httpcache/README.md b/vendor/github.com/gregjones/httpcache/README.md deleted file mode 100644 index 09c9e7c173..0000000000 --- a/vendor/github.com/gregjones/httpcache/README.md +++ /dev/null @@ -1,25 +0,0 @@ -httpcache -========= - -[![Build Status](https://travis-ci.org/gregjones/httpcache.svg?branch=master)](https://travis-ci.org/gregjones/httpcache) [![GoDoc](https://godoc.org/github.com/gregjones/httpcache?status.svg)](https://godoc.org/github.com/gregjones/httpcache) - -Package httpcache provides a http.RoundTripper implementation that works as a mostly [RFC 7234](https://tools.ietf.org/html/rfc7234) compliant cache for http responses. - -It is only suitable for use as a 'private' cache (i.e. for a web-browser or an API-client and not for a shared proxy). - -Cache Backends --------------- - -- The built-in 'memory' cache stores responses in an in-memory map. -- [`github.com/gregjones/httpcache/diskcache`](https://github.com/gregjones/httpcache/tree/master/diskcache) provides a filesystem-backed cache using the [diskv](https://github.com/peterbourgon/diskv) library. -- [`github.com/gregjones/httpcache/memcache`](https://github.com/gregjones/httpcache/tree/master/memcache) provides memcache implementations, for both App Engine and 'normal' memcache servers. -- [`sourcegraph.com/sourcegraph/s3cache`](https://sourcegraph.com/github.com/sourcegraph/s3cache) uses Amazon S3 for storage. -- [`github.com/gregjones/httpcache/leveldbcache`](https://github.com/gregjones/httpcache/tree/master/leveldbcache) provides a filesystem-backed cache using [leveldb](https://github.com/syndtr/goleveldb/leveldb). -- [`github.com/die-net/lrucache`](https://github.com/die-net/lrucache) provides an in-memory cache that will evict least-recently used entries. -- [`github.com/die-net/lrucache/twotier`](https://github.com/die-net/lrucache/tree/master/twotier) allows caches to be combined, for example to use lrucache above with a persistent disk-cache. -- [`github.com/birkelund/boltdbcache`](https://github.com/birkelund/boltdbcache) provides a BoltDB implementation (based on the [bbolt](https://github.com/coreos/bbolt) fork). - -License -------- - -- [MIT License](LICENSE.txt) diff --git a/vendor/github.com/hpcloud/tail/.gitignore b/vendor/github.com/hpcloud/tail/.gitignore deleted file mode 100644 index 6d9953c3c6..0000000000 --- a/vendor/github.com/hpcloud/tail/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.test -.go - diff --git a/vendor/github.com/hpcloud/tail/.travis.yml b/vendor/github.com/hpcloud/tail/.travis.yml deleted file mode 100644 index 9cf8bb7fc5..0000000000 --- a/vendor/github.com/hpcloud/tail/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -language: go - -script: - - go test -race -v ./... - -go: - - 1.4 - - 1.5 - - 1.6 - - tip - -matrix: - allow_failures: - - go: tip - -install: - - go get gopkg.in/fsnotify.v1 - - go get gopkg.in/tomb.v1 diff --git a/vendor/github.com/hpcloud/tail/CHANGES.md b/vendor/github.com/hpcloud/tail/CHANGES.md deleted file mode 100644 index 422790c073..0000000000 --- a/vendor/github.com/hpcloud/tail/CHANGES.md +++ /dev/null @@ -1,63 +0,0 @@ -# API v1 (gopkg.in/hpcloud/tail.v1) - -## April, 2016 - -* Migrated to godep, as depman is not longer supported -* Introduced golang vendoring feature -* Fixed issue [#57](https://github.com/hpcloud/tail/issues/57) related to reopen deleted file - -## July, 2015 - -* Fix inotify watcher leak; remove `Cleanup` (#51) - -# API v0 (gopkg.in/hpcloud/tail.v0) - -## June, 2015 - -* Don't return partial lines (PR #40) -* Use stable version of fsnotify (#46) - -## July, 2014 - -* Fix tail for Windows (PR #36) - -## May, 2014 - -* Improved rate limiting using leaky bucket (PR #29) -* Fix odd line splitting (PR #30) - -## Apr, 2014 - -* LimitRate now discards read buffer (PR #28) -* allow reading of longer lines if MaxLineSize is unset (PR #24) -* updated deps.json to latest fsnotify (441bbc86b1) - -## Feb, 2014 - -* added `Config.Logger` to suppress library logging - -## Nov, 2013 - -* add Cleanup to remove leaky inotify watches (PR #20) - -## Aug, 2013 - -* redesigned Location field (PR #12) -* add tail.Tell (PR #14) - -## July, 2013 - -* Rate limiting (PR #10) - -## May, 2013 - -* Detect file deletions/renames in polling file watcher (PR #1) -* Detect file truncation -* Fix potential race condition when reopening the file (issue 5) -* Fix potential blocking of `tail.Stop` (issue 4) -* Fix uncleaned up ChangeEvents goroutines after calling tail.Stop -* Support Follow=false - -## Feb, 2013 - -* Initial open source release diff --git a/vendor/github.com/hpcloud/tail/Dockerfile b/vendor/github.com/hpcloud/tail/Dockerfile deleted file mode 100644 index cd297b940a..0000000000 --- a/vendor/github.com/hpcloud/tail/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM golang - -RUN mkdir -p $GOPATH/src/github.com/hpcloud/tail/ -ADD . $GOPATH/src/github.com/hpcloud/tail/ - -# expecting to fetch dependencies successfully. -RUN go get -v github.com/hpcloud/tail - -# expecting to run the test successfully. -RUN go test -v github.com/hpcloud/tail - -# expecting to install successfully -RUN go install -v github.com/hpcloud/tail -RUN go install -v github.com/hpcloud/tail/cmd/gotail - -RUN $GOPATH/bin/gotail -h || true - -ENV PATH $GOPATH/bin:$PATH -CMD ["gotail"] diff --git a/vendor/github.com/hpcloud/tail/Makefile b/vendor/github.com/hpcloud/tail/Makefile deleted file mode 100644 index 6591b24fc1..0000000000 --- a/vendor/github.com/hpcloud/tail/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -default: test - -test: *.go - go test -v -race ./... - -fmt: - gofmt -w . - -# Run the test in an isolated environment. -fulltest: - docker build -t hpcloud/tail . diff --git a/vendor/github.com/hpcloud/tail/README.md b/vendor/github.com/hpcloud/tail/README.md deleted file mode 100644 index fb7fbc26c6..0000000000 --- a/vendor/github.com/hpcloud/tail/README.md +++ /dev/null @@ -1,28 +0,0 @@ -[![Build Status](https://travis-ci.org/hpcloud/tail.svg)](https://travis-ci.org/hpcloud/tail) -[![Build status](https://ci.appveyor.com/api/projects/status/kohpsf3rvhjhrox6?svg=true)](https://ci.appveyor.com/project/HelionCloudFoundry/tail) - -# Go package for tail-ing files - -A Go package striving to emulate the features of the BSD `tail` program. - -```Go -t, err := tail.TailFile("/var/log/nginx.log", tail.Config{Follow: true}) -for line := range t.Lines { - fmt.Println(line.Text) -} -``` - -See [API documentation](http://godoc.org/github.com/hpcloud/tail). - -## Log rotation - -Tail comes with full support for truncation/move detection as it is -designed to work with log rotation tools. - -## Installing - - go get github.com/hpcloud/tail/... - -## Windows support - -This package [needs assistance](https://github.com/hpcloud/tail/labels/Windows) for full Windows support. diff --git a/vendor/github.com/hpcloud/tail/appveyor.yml b/vendor/github.com/hpcloud/tail/appveyor.yml deleted file mode 100644 index d370055b6f..0000000000 --- a/vendor/github.com/hpcloud/tail/appveyor.yml +++ /dev/null @@ -1,11 +0,0 @@ -version: 0.{build} -skip_tags: true -cache: C:\Users\appveyor\AppData\Local\NuGet\Cache -build_script: -- SET GOPATH=c:\workspace -- go test -v -race ./... -test: off -clone_folder: c:\workspace\src\github.com\hpcloud\tail -branches: - only: - - master diff --git a/vendor/github.com/imdario/mergo/.gitignore b/vendor/github.com/imdario/mergo/.gitignore deleted file mode 100644 index 529c3412ba..0000000000 --- a/vendor/github.com/imdario/mergo/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -#### joe made this: http://goel.io/joe - -#### go #### -# Binaries for programs and plugins -*.exe -*.dll -*.so -*.dylib - -# Test binary, build with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 -.glide/ - -#### vim #### -# Swap -[._]*.s[a-v][a-z] -[._]*.sw[a-p] -[._]s[a-v][a-z] -[._]sw[a-p] - -# Session -Session.vim - -# Temporary -.netrwhist -*~ -# Auto-generated tag files -tags diff --git a/vendor/github.com/imdario/mergo/.travis.yml b/vendor/github.com/imdario/mergo/.travis.yml deleted file mode 100644 index b13a50ed1f..0000000000 --- a/vendor/github.com/imdario/mergo/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: go -install: - - go get -t - - go get golang.org/x/tools/cmd/cover - - go get github.com/mattn/goveralls -script: - - $HOME/gopath/bin/goveralls -service=travis-ci -repotoken $COVERALLS_TOKEN diff --git a/vendor/github.com/imdario/mergo/CODE_OF_CONDUCT.md b/vendor/github.com/imdario/mergo/CODE_OF_CONDUCT.md deleted file mode 100644 index 469b44907a..0000000000 --- a/vendor/github.com/imdario/mergo/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,46 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at i@dario.im. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] - -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ diff --git a/vendor/github.com/imdario/mergo/README.md b/vendor/github.com/imdario/mergo/README.md deleted file mode 100644 index d1cefa8718..0000000000 --- a/vendor/github.com/imdario/mergo/README.md +++ /dev/null @@ -1,222 +0,0 @@ -# Mergo - -A helper to merge structs and maps in Golang. Useful for configuration default values, avoiding messy if-statements. - -Also a lovely [comune](http://en.wikipedia.org/wiki/Mergo) (municipality) in the Province of Ancona in the Italian region of Marche. - -## Status - -It is ready for production use. [It is used in several projects by Docker, Google, The Linux Foundation, VMWare, Shopify, etc](https://github.com/imdario/mergo#mergo-in-the-wild). - -[![GoDoc][3]][4] -[![GoCard][5]][6] -[![Build Status][1]][2] -[![Coverage Status][7]][8] -[![Sourcegraph][9]][10] - -[1]: https://travis-ci.org/imdario/mergo.png -[2]: https://travis-ci.org/imdario/mergo -[3]: https://godoc.org/github.com/imdario/mergo?status.svg -[4]: https://godoc.org/github.com/imdario/mergo -[5]: https://goreportcard.com/badge/imdario/mergo -[6]: https://goreportcard.com/report/github.com/imdario/mergo -[7]: https://coveralls.io/repos/github/imdario/mergo/badge.svg?branch=master -[8]: https://coveralls.io/github/imdario/mergo?branch=master -[9]: https://sourcegraph.com/github.com/imdario/mergo/-/badge.svg -[10]: https://sourcegraph.com/github.com/imdario/mergo?badge - -### Latest release - -[Release v0.3.4](https://github.com/imdario/mergo/releases/tag/v0.3.4). - -### Important note - -Please keep in mind that in [0.3.2](//github.com/imdario/mergo/releases/tag/0.3.2) Mergo changed `Merge()`and `Map()` signatures to support [transformers](#transformers). An optional/variadic argument has been added, so it won't break existing code. - -If you were using Mergo **before** April 6th 2015, please check your project works as intended after updating your local copy with ```go get -u github.com/imdario/mergo```. I apologize for any issue caused by its previous behavior and any future bug that Mergo could cause (I hope it won't!) in existing projects after the change (release 0.2.0). - -### Donations - -If Mergo is useful to you, consider buying me a coffee, a beer or making a monthly donation so I can keep building great free software. :heart_eyes: - -Buy Me a Coffee at ko-fi.com -[![Beerpay](https://beerpay.io/imdario/mergo/badge.svg)](https://beerpay.io/imdario/mergo) -[![Beerpay](https://beerpay.io/imdario/mergo/make-wish.svg)](https://beerpay.io/imdario/mergo) -Donate using Liberapay - -### Mergo in the wild - -- [moby/moby](https://github.com/moby/moby) -- [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes) -- [vmware/dispatch](https://github.com/vmware/dispatch) -- [Shopify/themekit](https://github.com/Shopify/themekit) -- [imdario/zas](https://github.com/imdario/zas) -- [matcornic/hermes](https://github.com/matcornic/hermes) -- [OpenBazaar/openbazaar-go](https://github.com/OpenBazaar/openbazaar-go) -- [kataras/iris](https://github.com/kataras/iris) -- [michaelsauter/crane](https://github.com/michaelsauter/crane) -- [go-task/task](https://github.com/go-task/task) -- [sensu/uchiwa](https://github.com/sensu/uchiwa) -- [ory/hydra](https://github.com/ory/hydra) -- [sisatech/vcli](https://github.com/sisatech/vcli) -- [dairycart/dairycart](https://github.com/dairycart/dairycart) -- [projectcalico/felix](https://github.com/projectcalico/felix) -- [resin-os/balena](https://github.com/resin-os/balena) -- [go-kivik/kivik](https://github.com/go-kivik/kivik) -- [Telefonica/govice](https://github.com/Telefonica/govice) -- [supergiant/supergiant](supergiant/supergiant) -- [SergeyTsalkov/brooce](https://github.com/SergeyTsalkov/brooce) -- [soniah/dnsmadeeasy](https://github.com/soniah/dnsmadeeasy) -- [ohsu-comp-bio/funnel](https://github.com/ohsu-comp-bio/funnel) -- [EagerIO/Stout](https://github.com/EagerIO/Stout) -- [lynndylanhurley/defsynth-api](https://github.com/lynndylanhurley/defsynth-api) -- [russross/canvasassignments](https://github.com/russross/canvasassignments) -- [rdegges/cryptly-api](https://github.com/rdegges/cryptly-api) -- [casualjim/exeggutor](https://github.com/casualjim/exeggutor) -- [divshot/gitling](https://github.com/divshot/gitling) -- [RWJMurphy/gorl](https://github.com/RWJMurphy/gorl) -- [andrerocker/deploy42](https://github.com/andrerocker/deploy42) -- [elwinar/rambler](https://github.com/elwinar/rambler) -- [tmaiaroto/gopartman](https://github.com/tmaiaroto/gopartman) -- [jfbus/impressionist](https://github.com/jfbus/impressionist) -- [Jmeyering/zealot](https://github.com/Jmeyering/zealot) -- [godep-migrator/rigger-host](https://github.com/godep-migrator/rigger-host) -- [Dronevery/MultiwaySwitch-Go](https://github.com/Dronevery/MultiwaySwitch-Go) -- [thoas/picfit](https://github.com/thoas/picfit) -- [mantasmatelis/whooplist-server](https://github.com/mantasmatelis/whooplist-server) -- [jnuthong/item_search](https://github.com/jnuthong/item_search) -- [bukalapak/snowboard](https://github.com/bukalapak/snowboard) - -## Installation - - go get github.com/imdario/mergo - - // use in your .go code - import ( - "github.com/imdario/mergo" - ) - -## Usage - -You can only merge same-type structs with exported fields initialized as zero value of their type and same-types maps. Mergo won't merge unexported (private) fields but will do recursively any exported one. It won't merge empty structs value as [they are not considered zero values](https://golang.org/ref/spec#The_zero_value) either. Also maps will be merged recursively except for structs inside maps (because they are not addressable using Go reflection). - -```go -if err := mergo.Merge(&dst, src); err != nil { - // ... -} -``` - -Also, you can merge overwriting values using the transformer `WithOverride`. - -```go -if err := mergo.Merge(&dst, src, mergo.WithOverride); err != nil { - // ... -} -``` - -Additionally, you can map a `map[string]interface{}` to a struct (and otherwise, from struct to map), following the same restrictions as in `Merge()`. Keys are capitalized to find each corresponding exported field. - -```go -if err := mergo.Map(&dst, srcMap); err != nil { - // ... -} -``` - -Warning: if you map a struct to map, it won't do it recursively. Don't expect Mergo to map struct members of your struct as `map[string]interface{}`. They will be just assigned as values. - -More information and examples in [godoc documentation](http://godoc.org/github.com/imdario/mergo). - -### Nice example - -```go -package main - -import ( - "fmt" - "github.com/imdario/mergo" -) - -type Foo struct { - A string - B int64 -} - -func main() { - src := Foo{ - A: "one", - B: 2, - } - dest := Foo{ - A: "two", - } - mergo.Merge(&dest, src) - fmt.Println(dest) - // Will print - // {two 2} -} -``` - -Note: if test are failing due missing package, please execute: - - go get gopkg.in/yaml.v2 - -### Transformers - -Transformers allow to merge specific types differently than in the default behavior. In other words, now you can customize how some types are merged. For example, `time.Time` is a struct; it doesn't have zero value but IsZero can return true because it has fields with zero value. How can we merge a non-zero `time.Time`? - -```go -package main - -import ( - "fmt" - "github.com/imdario/mergo" - "reflect" - "time" -) - -type timeTransfomer struct { -} - -func (t timeTransfomer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error { - if typ == reflect.TypeOf(time.Time{}) { - return func(dst, src reflect.Value) error { - if dst.CanSet() { - isZero := dst.MethodByName("IsZero") - result := isZero.Call([]reflect.Value{}) - if result[0].Bool() { - dst.Set(src) - } - } - return nil - } - } - return nil -} - -type Snapshot struct { - Time time.Time - // ... -} - -func main() { - src := Snapshot{time.Now()} - dest := Snapshot{} - mergo.Merge(&dest, src, mergo.WithTransformers(timeTransfomer{})) - fmt.Println(dest) - // Will print - // { 2018-01-12 01:15:00 +0000 UTC m=+0.000000001 } -} -``` - - -## Contact me - -If I can help you, you have an idea or you are using Mergo in your projects, don't hesitate to drop me a line (or a pull request): [@im_dario](https://twitter.com/im_dario) - -## About - -Written by [Dario Castañé](http://dario.im). - -## License - -[BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license, as [Go language](http://golang.org/LICENSE). diff --git a/vendor/github.com/inconshreveable/mousetrap/README.md b/vendor/github.com/inconshreveable/mousetrap/README.md deleted file mode 100644 index 7a950d1774..0000000000 --- a/vendor/github.com/inconshreveable/mousetrap/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# mousetrap - -mousetrap is a tiny library that answers a single question. - -On a Windows machine, was the process invoked by someone double clicking on -the executable file while browsing in explorer? - -### Motivation - -Windows developers unfamiliar with command line tools will often "double-click" -the executable for a tool. Because most CLI tools print the help and then exit -when invoked without arguments, this is often very frustrating for those users. - -mousetrap provides a way to detect these invocations so that you can provide -more helpful behavior and instructions on how to run the CLI tool. To see what -this looks like, both from an organizational and a technical perspective, see -https://inconshreveable.com/09-09-2014/sweat-the-small-stuff/ - -### The interface - -The library exposes a single interface: - - func StartedByExplorer() (bool) diff --git a/vendor/github.com/json-iterator/go/.codecov.yml b/vendor/github.com/json-iterator/go/.codecov.yml deleted file mode 100644 index 955dc0be5f..0000000000 --- a/vendor/github.com/json-iterator/go/.codecov.yml +++ /dev/null @@ -1,3 +0,0 @@ -ignore: - - "output_tests/.*" - diff --git a/vendor/github.com/json-iterator/go/.gitignore b/vendor/github.com/json-iterator/go/.gitignore deleted file mode 100644 index 15556530a8..0000000000 --- a/vendor/github.com/json-iterator/go/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/vendor -/bug_test.go -/coverage.txt -/.idea diff --git a/vendor/github.com/json-iterator/go/.travis.yml b/vendor/github.com/json-iterator/go/.travis.yml deleted file mode 100644 index 449e67cd01..0000000000 --- a/vendor/github.com/json-iterator/go/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: go - -go: - - 1.8.x - - 1.x - -before_install: - - go get -t -v ./... - -script: - - ./test.sh - -after_success: - - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/json-iterator/go/Gopkg.lock b/vendor/github.com/json-iterator/go/Gopkg.lock deleted file mode 100644 index c8a9fbb387..0000000000 --- a/vendor/github.com/json-iterator/go/Gopkg.lock +++ /dev/null @@ -1,21 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - name = "github.com/modern-go/concurrent" - packages = ["."] - revision = "e0a39a4cb4216ea8db28e22a69f4ec25610d513a" - version = "1.0.0" - -[[projects]] - name = "github.com/modern-go/reflect2" - packages = ["."] - revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd" - version = "1.0.1" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - inputs-digest = "ea54a775e5a354cb015502d2e7aa4b74230fc77e894f34a838b268c25ec8eeb8" - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/vendor/github.com/json-iterator/go/Gopkg.toml b/vendor/github.com/json-iterator/go/Gopkg.toml deleted file mode 100644 index 313a0f887b..0000000000 --- a/vendor/github.com/json-iterator/go/Gopkg.toml +++ /dev/null @@ -1,26 +0,0 @@ -# Gopkg.toml example -# -# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" - -ignored = ["github.com/davecgh/go-spew*","github.com/google/gofuzz*","github.com/stretchr/testify*"] - -[[constraint]] - name = "github.com/modern-go/reflect2" - version = "1.0.1" diff --git a/vendor/github.com/json-iterator/go/README.md b/vendor/github.com/json-iterator/go/README.md deleted file mode 100644 index 54d5afe957..0000000000 --- a/vendor/github.com/json-iterator/go/README.md +++ /dev/null @@ -1,91 +0,0 @@ -[![Sourcegraph](https://sourcegraph.com/github.com/json-iterator/go/-/badge.svg)](https://sourcegraph.com/github.com/json-iterator/go?badge) -[![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/json-iterator/go) -[![Build Status](https://travis-ci.org/json-iterator/go.svg?branch=master)](https://travis-ci.org/json-iterator/go) -[![codecov](https://codecov.io/gh/json-iterator/go/branch/master/graph/badge.svg)](https://codecov.io/gh/json-iterator/go) -[![rcard](https://goreportcard.com/badge/github.com/json-iterator/go)](https://goreportcard.com/report/github.com/json-iterator/go) -[![License](http://img.shields.io/badge/license-mit-blue.svg?style=flat-square)](https://raw.githubusercontent.com/json-iterator/go/master/LICENSE) -[![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/json-iterator/Lobby) - -A high-performance 100% compatible drop-in replacement of "encoding/json" - -You can also use thrift like JSON using [thrift-iterator](https://github.com/thrift-iterator/go) - -``` -Go开发者们请加入我们,滴滴出行平台技术部 taowen@didichuxing.com -``` - -# Benchmark - -![benchmark](http://jsoniter.com/benchmarks/go-benchmark.png) - -Source code: https://github.com/json-iterator/go-benchmark/blob/master/src/github.com/json-iterator/go-benchmark/benchmark_medium_payload_test.go - -Raw Result (easyjson requires static code generation) - -| | ns/op | allocation bytes | allocation times | -| --- | --- | --- | --- | -| std decode | 35510 ns/op | 1960 B/op | 99 allocs/op | -| easyjson decode | 8499 ns/op | 160 B/op | 4 allocs/op | -| jsoniter decode | 5623 ns/op | 160 B/op | 3 allocs/op | -| std encode | 2213 ns/op | 712 B/op | 5 allocs/op | -| easyjson encode | 883 ns/op | 576 B/op | 3 allocs/op | -| jsoniter encode | 837 ns/op | 384 B/op | 4 allocs/op | - -Always benchmark with your own workload. -The result depends heavily on the data input. - -# Usage - -100% compatibility with standard lib - -Replace - -```go -import "encoding/json" -json.Marshal(&data) -``` - -with - -```go -import "github.com/json-iterator/go" - -var json = jsoniter.ConfigCompatibleWithStandardLibrary -json.Marshal(&data) -``` - -Replace - -```go -import "encoding/json" -json.Unmarshal(input, &data) -``` - -with - -```go -import "github.com/json-iterator/go" - -var json = jsoniter.ConfigCompatibleWithStandardLibrary -json.Unmarshal(input, &data) -``` - -[More documentation](http://jsoniter.com/migrate-from-go-std.html) - -# How to get - -``` -go get github.com/json-iterator/go -``` - -# Contribution Welcomed ! - -Contributors - -* [thockin](https://github.com/thockin) -* [mattn](https://github.com/mattn) -* [cch123](https://github.com/cch123) -* [Oleg Shaldybin](https://github.com/olegshaldybin) -* [Jason Toffaletti](https://github.com/toffaletti) - -Report issue or pull request, or email taowen@gmail.com, or [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/json-iterator/Lobby) diff --git a/vendor/github.com/json-iterator/go/build.sh b/vendor/github.com/json-iterator/go/build.sh deleted file mode 100755 index b45ef68831..0000000000 --- a/vendor/github.com/json-iterator/go/build.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e -set -x - -if [ ! -d /tmp/build-golang/src/github.com/json-iterator ]; then - mkdir -p /tmp/build-golang/src/github.com/json-iterator - ln -s $PWD /tmp/build-golang/src/github.com/json-iterator/go -fi -export GOPATH=/tmp/build-golang -go get -u github.com/golang/dep/cmd/dep -cd /tmp/build-golang/src/github.com/json-iterator/go -exec $GOPATH/bin/dep ensure -update diff --git a/vendor/github.com/json-iterator/go/fuzzy_mode_convert_table.md b/vendor/github.com/json-iterator/go/fuzzy_mode_convert_table.md deleted file mode 100644 index 3095662b06..0000000000 --- a/vendor/github.com/json-iterator/go/fuzzy_mode_convert_table.md +++ /dev/null @@ -1,7 +0,0 @@ -| json type \ dest type | bool | int | uint | float |string| -| --- | --- | --- | --- |--|--| -| number | positive => true
    negative => true
    zero => false| 23.2 => 23
    -32.1 => -32| 12.1 => 12
    -12.1 => 0|as normal|same as origin| -| string | empty string => false
    string "0" => false
    other strings => true | "123.32" => 123
    "-123.4" => -123
    "123.23xxxw" => 123
    "abcde12" => 0
    "-32.1" => -32| 13.2 => 13
    -1.1 => 0 |12.1 => 12.1
    -12.3 => -12.3
    12.4xxa => 12.4
    +1.1e2 =>110 |same as origin| -| bool | true => true
    false => false| true => 1
    false => 0 | true => 1
    false => 0 |true => 1
    false => 0|true => "true"
    false => "false"| -| object | true | 0 | 0 |0|originnal json| -| array | empty array => false
    nonempty array => true| [] => 0
    [1,2] => 1 | [] => 0
    [1,2] => 1 |[] => 0
    [1,2] => 1|original json| \ No newline at end of file diff --git a/vendor/github.com/json-iterator/go/test.sh b/vendor/github.com/json-iterator/go/test.sh deleted file mode 100755 index f4e7c0b2c9..0000000000 --- a/vendor/github.com/json-iterator/go/test.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -set -e -echo "" > coverage.txt - -for d in $(go list ./... | grep -v vendor); do - go test -coverprofile=profile.out -coverpkg=github.com/json-iterator/go $d - if [ -f profile.out ]; then - cat profile.out >> coverage.txt - rm profile.out - fi -done diff --git a/vendor/github.com/kelseyhightower/envconfig/.travis.yml b/vendor/github.com/kelseyhightower/envconfig/.travis.yml deleted file mode 100644 index f6edc34839..0000000000 --- a/vendor/github.com/kelseyhightower/envconfig/.travis.yml +++ /dev/null @@ -1,10 +0,0 @@ -language: go - -go: - - 1.4.x - - 1.5.x - - 1.6.x - - 1.7.x - - 1.8.x - - 1.9.x - - tip diff --git a/vendor/github.com/kelseyhightower/envconfig/MAINTAINERS b/vendor/github.com/kelseyhightower/envconfig/MAINTAINERS deleted file mode 100644 index 6527a9f2cc..0000000000 --- a/vendor/github.com/kelseyhightower/envconfig/MAINTAINERS +++ /dev/null @@ -1,2 +0,0 @@ -Kelsey Hightower kelsey.hightower@gmail.com github.com/kelseyhightower -Travis Parker travis.parker@gmail.com github.com/teepark diff --git a/vendor/github.com/kelseyhightower/envconfig/README.md b/vendor/github.com/kelseyhightower/envconfig/README.md deleted file mode 100644 index 3e8fdc6938..0000000000 --- a/vendor/github.com/kelseyhightower/envconfig/README.md +++ /dev/null @@ -1,188 +0,0 @@ -# envconfig - -[![Build Status](https://travis-ci.org/kelseyhightower/envconfig.svg)](https://travis-ci.org/kelseyhightower/envconfig) - -```Go -import "github.com/kelseyhightower/envconfig" -``` - -## Documentation - -See [godoc](http://godoc.org/github.com/kelseyhightower/envconfig) - -## Usage - -Set some environment variables: - -```Bash -export MYAPP_DEBUG=false -export MYAPP_PORT=8080 -export MYAPP_USER=Kelsey -export MYAPP_RATE="0.5" -export MYAPP_TIMEOUT="3m" -export MYAPP_USERS="rob,ken,robert" -export MYAPP_COLORCODES="red:1,green:2,blue:3" -``` - -Write some code: - -```Go -package main - -import ( - "fmt" - "log" - "time" - - "github.com/kelseyhightower/envconfig" -) - -type Specification struct { - Debug bool - Port int - User string - Users []string - Rate float32 - Timeout time.Duration - ColorCodes map[string]int -} - -func main() { - var s Specification - err := envconfig.Process("myapp", &s) - if err != nil { - log.Fatal(err.Error()) - } - format := "Debug: %v\nPort: %d\nUser: %s\nRate: %f\nTimeout: %s\n" - _, err = fmt.Printf(format, s.Debug, s.Port, s.User, s.Rate, s.Timeout) - if err != nil { - log.Fatal(err.Error()) - } - - fmt.Println("Users:") - for _, u := range s.Users { - fmt.Printf(" %s\n", u) - } - - fmt.Println("Color codes:") - for k, v := range s.ColorCodes { - fmt.Printf(" %s: %d\n", k, v) - } -} -``` - -Results: - -```Bash -Debug: false -Port: 8080 -User: Kelsey -Rate: 0.500000 -Timeout: 3m0s -Users: - rob - ken - robert -Color codes: - red: 1 - green: 2 - blue: 3 -``` - -## Struct Tag Support - -Envconfig supports the use of struct tags to specify alternate, default, and required -environment variables. - -For example, consider the following struct: - -```Go -type Specification struct { - ManualOverride1 string `envconfig:"manual_override_1"` - DefaultVar string `default:"foobar"` - RequiredVar string `required:"true"` - IgnoredVar string `ignored:"true"` - AutoSplitVar string `split_words:"true"` -} -``` - -Envconfig has automatic support for CamelCased struct elements when the -`split_words:"true"` tag is supplied. Without this tag, `AutoSplitVar` above -would look for an environment variable called `MYAPP_AUTOSPLITVAR`. With the -setting applied it will look for `MYAPP_AUTO_SPLIT_VAR`. Note that numbers -will get globbed into the previous word. If the setting does not do the -right thing, you may use a manual override. - -Envconfig will process value for `ManualOverride1` by populating it with the -value for `MYAPP_MANUAL_OVERRIDE_1`. Without this struct tag, it would have -instead looked up `MYAPP_MANUALOVERRIDE1`. With the `split_words:"true"` tag -it would have looked up `MYAPP_MANUAL_OVERRIDE1`. - -```Bash -export MYAPP_MANUAL_OVERRIDE_1="this will be the value" - -# export MYAPP_MANUALOVERRIDE1="and this will not" -``` - -If envconfig can't find an environment variable value for `MYAPP_DEFAULTVAR`, -it will populate it with "foobar" as a default value. - -If envconfig can't find an environment variable value for `MYAPP_REQUIREDVAR`, -it will return an error when asked to process the struct. - -If envconfig can't find an environment variable in the form `PREFIX_MYVAR`, and there -is a struct tag defined, it will try to populate your variable with an environment -variable that directly matches the envconfig tag in your struct definition: - -```shell -export SERVICE_HOST=127.0.0.1 -export MYAPP_DEBUG=true -``` -```Go -type Specification struct { - ServiceHost string `envconfig:"SERVICE_HOST"` - Debug bool -} -``` - -Envconfig won't process a field with the "ignored" tag set to "true", even if a corresponding -environment variable is set. - -## Supported Struct Field Types - -envconfig supports supports these struct field types: - - * string - * int8, int16, int32, int64 - * bool - * float32, float64 - * slices of any supported type - * maps (keys and values of any supported type) - * [encoding.TextUnmarshaler](https://golang.org/pkg/encoding/#TextUnmarshaler) - -Embedded structs using these fields are also supported. - -## Custom Decoders - -Any field whose type (or pointer-to-type) implements `envconfig.Decoder` can -control its own deserialization: - -```Bash -export DNS_SERVER=8.8.8.8 -``` - -```Go -type IPDecoder net.IP - -func (ipd *IPDecoder) Decode(value string) error { - *ipd = IPDecoder(net.ParseIP(value)) - return nil -} - -type DNSConfig struct { - Address IPDecoder `envconfig:"DNS_SERVER"` -} -``` - -Also, envconfig will use a `Set(string) error` method like from the -[flag.Value](https://godoc.org/flag#Value) interface if implemented. diff --git a/vendor/github.com/leonelquinteros/gotext/.gitignore b/vendor/github.com/leonelquinteros/gotext/.gitignore deleted file mode 100644 index d537248563..0000000000 --- a/vendor/github.com/leonelquinteros/gotext/.gitignore +++ /dev/null @@ -1,29 +0,0 @@ -# Eclipse shit -.project -.settings -.buildpath - -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof diff --git a/vendor/github.com/leonelquinteros/gotext/.travis.yml b/vendor/github.com/leonelquinteros/gotext/.travis.yml deleted file mode 100644 index 28dedaba33..0000000000 --- a/vendor/github.com/leonelquinteros/gotext/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -language: go - -go: - - 1.6 - - 1.7 - - 1.8 - - tip - -before_install: - - go get -t -v ./... - -script: go test -v -race -coverprofile=coverage.txt -covermode=atomic . - -after_success: - - bash <(curl -s https://codecov.io/bash) - diff --git a/vendor/github.com/leonelquinteros/gotext/Gopkg.lock b/vendor/github.com/leonelquinteros/gotext/Gopkg.lock deleted file mode 100644 index b5dc577e0c..0000000000 --- a/vendor/github.com/leonelquinteros/gotext/Gopkg.lock +++ /dev/null @@ -1,15 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - branch = "master" - name = "github.com/mattn/kinako" - packages = ["ast","parser","vm"] - revision = "332c0a7e205a29536e672337a4bea6c7a96b04c1" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - inputs-digest = "d3069fabe2d6f79fe33ad88133e861db84aef0400f6b949c4e64395913b3ae97" - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/vendor/github.com/leonelquinteros/gotext/Gopkg.toml b/vendor/github.com/leonelquinteros/gotext/Gopkg.toml deleted file mode 100644 index 353e507a09..0000000000 --- a/vendor/github.com/leonelquinteros/gotext/Gopkg.toml +++ /dev/null @@ -1,26 +0,0 @@ - -# Gopkg.toml example -# -# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" - - -[[constraint]] - branch = "master" - name = "github.com/mattn/kinako" diff --git a/vendor/github.com/leonelquinteros/gotext/README.md b/vendor/github.com/leonelquinteros/gotext/README.md deleted file mode 100644 index c5cbedb868..0000000000 --- a/vendor/github.com/leonelquinteros/gotext/README.md +++ /dev/null @@ -1,290 +0,0 @@ -[![GitHub release](https://img.shields.io/github/release/leonelquinteros/gotext.svg)](https://github.com/leonelquinteros/gotext) -[![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) -[![GoDoc](https://godoc.org/github.com/leonelquinteros/gotext?status.svg)](https://godoc.org/github.com/leonelquinteros/gotext) -[![Build Status](https://travis-ci.org/leonelquinteros/gotext.svg?branch=master)](https://travis-ci.org/leonelquinteros/gotext) -[![codecov](https://codecov.io/gh/leonelquinteros/gotext/branch/master/graph/badge.svg)](https://codecov.io/gh/leonelquinteros/gotext) -[![Go Report Card](https://goreportcard.com/badge/github.com/leonelquinteros/gotext)](https://goreportcard.com/report/github.com/leonelquinteros/gotext) - -# Gotext - -[GNU gettext utilities](https://www.gnu.org/software/gettext) for Go. - - -# Features - -- Implements GNU gettext support in native Go. -- Complete support for [PO files](https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html) including: - - Support for multiline strings and headers. - - Support for variables inside translation strings using Go's [fmt syntax](https://golang.org/pkg/fmt/). - - Support for [pluralization rules](https://www.gnu.org/software/gettext/manual/html_node/Translating-plural-forms.html). - - Support for [message contexts](https://www.gnu.org/software/gettext/manual/html_node/Contexts.html). -- Thread-safe: This package is safe for concurrent use across multiple goroutines. -- It works with UTF-8 encoding as it's the default for Go language. -- Unit tests available. -- Language codes are automatically simplified from the form `en_UK` to `en` if the first isn't available. -- Ready to use inside Go templates. - - -# License - -[MIT license](LICENSE) - - -# Documentation - -Refer to the Godoc package documentation at (https://godoc.org/github.com/leonelquinteros/gotext) - - -# Installation - -``` -go get github.com/leonelquinteros/gotext -``` - -- There are no requirements or dependencies to use this package. -- No need to install GNU gettext utilities (unless specific needs of CLI tools). -- No need for environment variables. Some naming conventions are applied but not needed. - - -#### Version vendoring - -Stable releases use [semantic versioning](http://semver.org/spec/v2.0.0.html) tagging on this repository. - -You can rely on this to use your preferred vendoring tool or to manually retrieve the corresponding release tag from the GitHub repository. - - -##### Vendoring with [gopkg.in](http://labix.org/gopkg.in) - -[http://gopkg.in/leonelquinteros/gotext.v1](http://gopkg.in/leonelquinteros/gotext.v1) - -To get the latest v1 package stable release, execute: - -``` -go get gopkg.in/leonelquinteros/gotext.v1 -``` - -To import this package, add the following line to your code: - -```go -import "gopkg.in/leonelquinteros/gotext.v1" -``` - -Refer to it as gotext. - - -# Locales directories structure - -The package will assume a directories structure starting with a base path that will be provided to the package configuration -or to object constructors depending on the use, but either will use the same convention to lookup inside the base path. - -Inside the base directory where will be the language directories named using the language and country 2-letter codes (en_US, es_AR, ...). -All package functions can lookup after the simplified version for each language in case the full code isn't present but the more general language code exists. -So if the language set is `en_UK`, but there is no directory named after that code and there is a directory named `en`, -all package functions will be able to resolve this generalization and provide translations for the more general library. - -The language codes are assumed to be [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) codes (2-letter codes). -That said, most functions will work with any coding standard as long the directory name matches the language code set on the configuration. - -Then, there can be a `LC_MESSAGES` containing all PO files or the PO files themselves. -A library directory structure can look like: - -``` -/path/to/locales -/path/to/locales/en_US -/path/to/locales/en_US/LC_MESSAGES -/path/to/locales/en_US/LC_MESSAGES/default.po -/path/to/locales/en_US/LC_MESSAGES/extras.po -/path/to/locales/en_UK -/path/to/locales/en_UK/LC_MESSAGES -/path/to/locales/en_UK/LC_MESSAGES/default.po -/path/to/locales/en_UK/LC_MESSAGES/extras.po -/path/to/locales/en_AU -/path/to/locales/en_AU/LC_MESSAGES -/path/to/locales/en_AU/LC_MESSAGES/default.po -/path/to/locales/en_AU/LC_MESSAGES/extras.po -/path/to/locales/es -/path/to/locales/es/default.po -/path/to/locales/es/extras.po -/path/to/locales/es_ES -/path/to/locales/es_ES/default.po -/path/to/locales/es_ES/extras.po -/path/to/locales/fr -/path/to/locales/fr/default.po -/path/to/locales/fr/extras.po -``` - -And so on... - - -# Usage examples - -## Using package for single language/domain settings - -For quick/simple translations you can use the package level functions directly. - -```go -import ( - "fmt" - "github.com/leonelquinteros/gotext" -) - -func main() { - // Configure package - gotext.Configure("/path/to/locales/root/dir", "en_UK", "domain-name") - - // Translate text from default domain - fmt.Println(gotext.Get("My text on 'domain-name' domain")) - - // Translate text from a different domain without reconfigure - fmt.Println(gotext.GetD("domain2", "Another text on a different domain")) -} - -``` - -## Using dynamic variables on translations - -All translation strings support dynamic variables to be inserted without translate. -Use the fmt.Printf syntax (from Go's "fmt" package) to specify how to print the non-translated variable inside the translation string. - -```go -import ( - "fmt" - "github.com/leonelquinteros/gotext" -) - -func main() { - // Configure package - gotext.Configure("/path/to/locales/root/dir", "en_UK", "domain-name") - - // Set variables - name := "John" - - // Translate text with variables - fmt.Println(gotext.Get("Hi, my name is %s", name)) -} - -``` - - -## Using Locale object - -When having multiple languages/domains/libraries at the same time, you can create Locale objects for each variation -so you can handle each settings on their own. - -```go -import ( - "fmt" - "github.com/leonelquinteros/gotext" -) - -func main() { - // Create Locale with library path and language code - l := gotext.NewLocale("/path/to/locales/root/dir", "es_UY") - - // Load domain '/path/to/locales/root/dir/es_UY/default.po' - l.AddDomain("default") - - // Translate text from default domain - fmt.Println(l.Get("Translate this")) - - // Load different domain - l.AddDomain("translations") - - // Translate text from domain - fmt.Println(l.GetD("translations", "Translate this")) -} -``` - -This is also helpful for using inside templates (from the "text/template" package), where you can pass the Locale object to the template. -If you set the Locale object as "Loc" in the template, then the template code would look like: - -``` -{{ .Loc.Get "Translate this" }} -``` - - -## Using the Po object to handle .po files and PO-formatted strings - -For when you need to work with PO files and strings, -you can directly use the Po object to parse it and access the translations in there in the same way. - -```go -import ( - "fmt" - "github.com/leonelquinteros/gotext" -) - -func main() { - // Set PO content - str := ` -msgid "Translate this" -msgstr "Translated text" - -msgid "Another string" -msgstr "" - -msgid "One with var: %s" -msgstr "This one sets the var: %s" -` - - // Create Po object - po := new(gotext.Po) - po.Parse(str) - - fmt.Println(po.Get("Translate this")) -} -``` - - -## Use plural forms of translations - -PO format supports defining one or more plural forms for the same translation. -Relying on the PO file headers, a Plural-Forms formula can be set on the translation file -as defined in (https://www.gnu.org/savannah-checkouts/gnu/gettext/manual/html_node/Plural-forms.html) - -Plural formulas are parsed and evaluated using [Kinako](https://github.com/mattn/kinako) - -```go -import ( - "fmt" - "github.com/leonelquinteros/gotext" -) - -func main() { - // Set PO content - str := ` -msgid "" -msgstr "" - -# Header below -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgid "Translate this" -msgstr "Translated text" - -msgid "Another string" -msgstr "" - -msgid "One with var: %s" -msgid_plural "Several with vars: %s" -msgstr[0] "This one is the singular: %s" -msgstr[1] "This one is the plural: %s" -` - - // Create Po object - po := new(gotext.Po) - po.Parse(str) - - fmt.Println(po.GetN("One with var: %s", "Several with vars: %s", 54, v)) - // "This one is the plural: Variable" -} -``` - - -# Contribute - -- Please, contribute. -- Use the package on your projects. -- Report issues on Github. -- Send pull requests for bugfixes and improvements. -- Send proposals on Github issues. diff --git a/vendor/github.com/marstr/guid/.travis.yml b/vendor/github.com/marstr/guid/.travis.yml deleted file mode 100644 index 35158ec532..0000000000 --- a/vendor/github.com/marstr/guid/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -sudo: false - -language: go - -go: - - 1.7 - - 1.8 - -install: - - go get -u github.com/golang/lint/golint - - go get -u github.com/HewlettPackard/gas - -script: - - golint --set_exit_status - - go vet - - go test -v -cover -race - - go test -bench . - - gas ./... \ No newline at end of file diff --git a/vendor/github.com/marstr/guid/README.md b/vendor/github.com/marstr/guid/README.md deleted file mode 100644 index 355fad16d2..0000000000 --- a/vendor/github.com/marstr/guid/README.md +++ /dev/null @@ -1,27 +0,0 @@ -[![Build Status](https://travis-ci.org/marstr/guid.svg?branch=master)](https://travis-ci.org/marstr/guid) -[![GoDoc](https://godoc.org/github.com/marstr/guid?status.svg)](https://godoc.org/github.com/marstr/guid) -[![Go Report Card](https://goreportcard.com/badge/github.com/marstr/guid)](https://goreportcard.com/report/github.com/marstr/guid) - -# Guid -Globally unique identifiers offer a quick means of generating non-colliding values across a distributed system. For this implemenation, [RFC 4122](http://ietf.org/rfc/rfc4122.txt) governs the desired behavior. - -## What's in a name? -You have likely already noticed that RFC and some implementations refer to these structures as UUIDs (Universally Unique Identifiers), where as this project is annotated as GUIDs (Globally Unique Identifiers). The name Guid was selected to make clear this project's ties to the [.NET struct Guid.](https://msdn.microsoft.com/en-us/library/system.guid(v=vs.110).aspx) The most obvious relationship is the desire to have the same format specifiers available in this library's Format and Parse methods as .NET would have in its ToString and Parse methods. - -# Installation -- Ensure you have the [Go Programming Language](https://golang.org/) installed on your system. -- Run the command: `go get -u github.com/marstr/guid` - -# Contribution -Contributions are welcome! Feel free to send Pull Requests. Continuous Integration will ensure that you have conformed to Go conventions. Please remember to add tests for your changes. - -# Versioning -This library will adhere to the -[Semantic Versioning 2.0.0](http://semver.org/spec/v2.0.0.html) specification. It may be worth noting this should allow for tools like [glide](https://glide.readthedocs.io/en/latest/) to pull in this library with ease. - -The Release Notes portion of this file will be updated to reflect the most recent major/minor updates, with the option to tag particular bug-fixes as well. Updates to the Release Notes for patches should be addative, where as major/minor updates should replace the previous version. If one desires to see the release notes for an older version, checkout that version of code and open this file. - -# Release Notes 1.1.* - -## v1.1.0 -Adding support for JSON marshaling and unmarshaling. diff --git a/vendor/github.com/mattn/go-colorable/.travis.yml b/vendor/github.com/mattn/go-colorable/.travis.yml deleted file mode 100644 index 98db8f060b..0000000000 --- a/vendor/github.com/mattn/go-colorable/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: go -go: - - tip - -before_install: - - go get github.com/mattn/goveralls - - go get golang.org/x/tools/cmd/cover -script: - - $HOME/gopath/bin/goveralls -repotoken xnXqRGwgW3SXIguzxf90ZSK1GPYZPaGrw diff --git a/vendor/github.com/mattn/go-colorable/README.md b/vendor/github.com/mattn/go-colorable/README.md deleted file mode 100644 index 56729a92ca..0000000000 --- a/vendor/github.com/mattn/go-colorable/README.md +++ /dev/null @@ -1,48 +0,0 @@ -# go-colorable - -[![Godoc Reference](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable) -[![Build Status](https://travis-ci.org/mattn/go-colorable.svg?branch=master)](https://travis-ci.org/mattn/go-colorable) -[![Coverage Status](https://coveralls.io/repos/github/mattn/go-colorable/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-colorable?branch=master) -[![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable) - -Colorable writer for windows. - -For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.) -This package is possible to handle escape sequence for ansi color on windows. - -## Too Bad! - -![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/bad.png) - - -## So Good! - -![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/good.png) - -## Usage - -```go -logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true}) -logrus.SetOutput(colorable.NewColorableStdout()) - -logrus.Info("succeeded") -logrus.Warn("not correct") -logrus.Error("something error") -logrus.Fatal("panic") -``` - -You can compile above code on non-windows OSs. - -## Installation - -``` -$ go get github.com/mattn/go-colorable -``` - -# License - -MIT - -# Author - -Yasuhiro Matsumoto (a.k.a mattn) diff --git a/vendor/github.com/mattn/go-isatty/.travis.yml b/vendor/github.com/mattn/go-isatty/.travis.yml deleted file mode 100644 index 5597e026dd..0000000000 --- a/vendor/github.com/mattn/go-isatty/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: go -go: - - tip - -os: - - linux - - osx - -before_install: - - go get github.com/mattn/goveralls - - go get golang.org/x/tools/cmd/cover -script: - - $HOME/gopath/bin/goveralls -repotoken 3gHdORO5k5ziZcWMBxnd9LrMZaJs8m9x5 diff --git a/vendor/github.com/mattn/go-isatty/README.md b/vendor/github.com/mattn/go-isatty/README.md deleted file mode 100644 index 1e69004bb0..0000000000 --- a/vendor/github.com/mattn/go-isatty/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# go-isatty - -[![Godoc Reference](https://godoc.org/github.com/mattn/go-isatty?status.svg)](http://godoc.org/github.com/mattn/go-isatty) -[![Build Status](https://travis-ci.org/mattn/go-isatty.svg?branch=master)](https://travis-ci.org/mattn/go-isatty) -[![Coverage Status](https://coveralls.io/repos/github/mattn/go-isatty/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-isatty?branch=master) -[![Go Report Card](https://goreportcard.com/badge/mattn/go-isatty)](https://goreportcard.com/report/mattn/go-isatty) - -isatty for golang - -## Usage - -```go -package main - -import ( - "fmt" - "github.com/mattn/go-isatty" - "os" -) - -func main() { - if isatty.IsTerminal(os.Stdout.Fd()) { - fmt.Println("Is Terminal") - } else if isatty.IsCygwinTerminal(os.Stdout.Fd()) { - fmt.Println("Is Cygwin/MSYS2 Terminal") - } else { - fmt.Println("Is Not Terminal") - } -} -``` - -## Installation - -``` -$ go get github.com/mattn/go-isatty -``` - -## License - -MIT - -## Author - -Yasuhiro Matsumoto (a.k.a mattn) - -## Thanks - -* k-takata: base idea for IsCygwinTerminal - - https://github.com/k-takata/go-iscygpty diff --git a/vendor/github.com/mattn/kinako/parser/Makefile b/vendor/github.com/mattn/kinako/parser/Makefile deleted file mode 100644 index 88d6ad6f48..0000000000 --- a/vendor/github.com/mattn/kinako/parser/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -all : parser.go - -parser.go : parser.go.y - goyacc -o $@ parser.go.y diff --git a/vendor/github.com/mattn/kinako/parser/parser.go.y b/vendor/github.com/mattn/kinako/parser/parser.go.y deleted file mode 100644 index 84086ac9a6..0000000000 --- a/vendor/github.com/mattn/kinako/parser/parser.go.y +++ /dev/null @@ -1,214 +0,0 @@ -%{ -package parser - -import ( - "github.com/mattn/kinako/ast" -) - -%} - -%type compstmt -%type stmts -%type stmt -%type expr -%type exprs - -%union{ - compstmt []ast.Stmt - stmts []ast.Stmt - stmt ast.Stmt - expr ast.Expr - exprs []ast.Expr - tok ast.Token - term ast.Token - terms ast.Token - opt_terms ast.Token -} - -%token IDENT NUMBER STRING EQEQ NEQ GE LE OROR ANDAND POW - -%right '=' -%right '?' ':' -%left OROR -%left ANDAND -%left IDENT -%nonassoc EQEQ NEQ ',' -%left '>' GE '<' LE SHIFTLEFT SHIFTRIGHT - -%left '+' '-' PLUSPLUS MINUSMINUS -%left '*' '/' '%' -%right UNARY - -%% - -compstmt : opt_terms - { - $$ = nil - } - | stmts opt_terms - { - $$ = $1 - } - -stmts : - opt_terms stmt - { - $$ = []ast.Stmt{$2} - if l, ok := yylex.(*Lexer); ok { - l.stmts = $$ - } - } - | stmts terms stmt - { - if $3 != nil { - $$ = append($1, $3) - if l, ok := yylex.(*Lexer); ok { - l.stmts = $$ - } - } - } - -stmt : - expr '=' expr - { - $$ = &ast.LetStmt{Lhs: $1, Operator: "=", Rhs: $3} - } - | expr - { - $$ = &ast.ExprStmt{Expr: $1} - } - -expr : - IDENT - { - $$ = &ast.IdentExpr{Lit: $1.Lit} - } - | NUMBER - { - $$ = &ast.NumberExpr{Lit: $1.Lit} - } - | '-' expr %prec UNARY - { - $$ = &ast.UnaryExpr{Operator: "-", Expr: $2} - } - | '!' expr %prec UNARY - { - $$ = &ast.UnaryExpr{Operator: "!", Expr: $2} - } - | '^' expr %prec UNARY - { - $$ = &ast.UnaryExpr{Operator: "^", Expr: $2} - } - | STRING - { - $$ = &ast.StringExpr{Lit: $1.Lit} - } - | expr '?' expr ':' expr - { - $$ = &ast.TernaryOpExpr{Expr: $1, Lhs: $3, Rhs: $5} - } - | '(' expr ')' - { - $$ = &ast.ParenExpr{SubExpr: $2} - } - | expr '+' expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "+", Rhs: $3} - } - | expr '-' expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "-", Rhs: $3} - } - | expr '*' expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "*", Rhs: $3} - } - | expr '/' expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "/", Rhs: $3} - } - | expr '%' expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "%", Rhs: $3} - } - | expr EQEQ expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "==", Rhs: $3} - } - | expr NEQ expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "!=", Rhs: $3} - } - | expr '>' expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: ">", Rhs: $3} - } - | expr GE expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: ">=", Rhs: $3} - } - | expr '<' expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "<", Rhs: $3} - } - | expr LE expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "<=", Rhs: $3} - } - | expr '|' expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "|", Rhs: $3} - } - | expr OROR expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "||", Rhs: $3} - } - | expr '&' expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "&", Rhs: $3} - } - | expr ANDAND expr - { - $$ = &ast.BinOpExpr{Lhs: $1, Operator: "&&", Rhs: $3} - } - | IDENT '(' exprs ')' - { - $$ = &ast.CallExpr{Name: $1.Lit, SubExprs: $3} - } - -exprs : - { - $$ = nil - } - | expr - { - $$ = []ast.Expr{$1} - } - | exprs ',' expr - { - $$ = append($1, $3) - } - -opt_terms : /* none */ - | terms - ; - - -terms : term - { - } - | terms term - { - } - ; - -term : ';' - { - } - | '\n' - { - } - ; - -%% - diff --git a/vendor/github.com/mattn/kinako/parser/y.output b/vendor/github.com/mattn/kinako/parser/y.output deleted file mode 100644 index 1a0f45edf3..0000000000 --- a/vendor/github.com/mattn/kinako/parser/y.output +++ /dev/null @@ -1,1381 +0,0 @@ - -state 0 - $accept: .compstmt $end - opt_terms: . (34) - - ';' shift 6 - '\n' shift 7 - . reduce 34 (src line 192) - - compstmt goto 1 - stmts goto 3 - opt_terms goto 2 - terms goto 4 - term goto 5 - -state 1 - $accept: compstmt.$end - - $end accept - . error - - -state 2 - compstmt: opt_terms. (1) - stmts: opt_terms.stmt - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . reduce 1 (src line 44) - - stmt goto 8 - expr goto 9 - -state 3 - compstmt: stmts.opt_terms - stmts: stmts.terms stmt - opt_terms: . (34) - - ';' shift 6 - '\n' shift 7 - . reduce 34 (src line 192) - - opt_terms goto 17 - terms goto 18 - term goto 5 - -state 4 - opt_terms: terms. (35) - terms: terms.term - - ';' shift 6 - '\n' shift 7 - . reduce 35 (src line 193) - - term goto 19 - -state 5 - terms: term. (36) - - . reduce 36 (src line 197) - - -state 6 - term: ';'. (38) - - . reduce 38 (src line 205) - - -state 7 - term: '\n'. (39) - - . reduce 39 (src line 208) - - -state 8 - stmts: opt_terms stmt. (3) - - . reduce 3 (src line 53) - - -state 9 - stmt: expr.'=' expr - stmt: expr. (6) - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - OROR shift 34 - ANDAND shift 36 - '=' shift 20 - '?' shift 21 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 6 (src line 76) - - -state 10 - expr: IDENT. (7) - expr: IDENT.'(' exprs ')' - - '(' shift 37 - . reduce 7 (src line 81) - - -state 11 - expr: NUMBER. (8) - - . reduce 8 (src line 86) - - -state 12 - expr: '-'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 38 - -state 13 - expr: '!'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 39 - -state 14 - expr: '^'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 40 - -state 15 - expr: STRING. (12) - - . reduce 12 (src line 102) - - -state 16 - expr: '('.expr ')' - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 41 - -state 17 - compstmt: stmts opt_terms. (2) - - . reduce 2 (src line 48) - - -state 18 - stmts: stmts terms.stmt - opt_terms: terms. (35) - terms: terms.term - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - ';' shift 6 - '\n' shift 7 - . reduce 35 (src line 193) - - stmt goto 42 - expr goto 9 - term goto 19 - -state 19 - terms: terms term. (37) - - . reduce 37 (src line 200) - - -state 20 - stmt: expr '='.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 43 - -state 21 - expr: expr '?'.expr ':' expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 44 - -state 22 - expr: expr '+'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 45 - -state 23 - expr: expr '-'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 46 - -state 24 - expr: expr '*'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 47 - -state 25 - expr: expr '/'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 48 - -state 26 - expr: expr '%'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 49 - -state 27 - expr: expr EQEQ.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 50 - -state 28 - expr: expr NEQ.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 51 - -state 29 - expr: expr '>'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 52 - -state 30 - expr: expr GE.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 53 - -state 31 - expr: expr '<'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 54 - -state 32 - expr: expr LE.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 55 - -state 33 - expr: expr '|'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 56 - -state 34 - expr: expr OROR.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 57 - -state 35 - expr: expr '&'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 58 - -state 36 - expr: expr ANDAND.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 59 - -state 37 - expr: IDENT '('.exprs ')' - exprs: . (31) - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . reduce 31 (src line 179) - - expr goto 61 - exprs goto 60 - -38: shift/reduce conflict (shift 33(0), red'n 9(10)) on '|' -38: shift/reduce conflict (shift 35(0), red'n 9(10)) on '&' -state 38 - expr: '-' expr. (9) - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '|' shift 33 - '&' shift 35 - . reduce 9 (src line 90) - - -39: shift/reduce conflict (shift 33(0), red'n 10(10)) on '|' -39: shift/reduce conflict (shift 35(0), red'n 10(10)) on '&' -state 39 - expr: '!' expr. (10) - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '|' shift 33 - '&' shift 35 - . reduce 10 (src line 94) - - -40: shift/reduce conflict (shift 33(0), red'n 11(10)) on '|' -40: shift/reduce conflict (shift 35(0), red'n 11(10)) on '&' -state 40 - expr: '^' expr. (11) - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '|' shift 33 - '&' shift 35 - . reduce 11 (src line 98) - - -state 41 - expr: expr.'?' expr ':' expr - expr: '(' expr.')' - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - OROR shift 34 - ANDAND shift 36 - '?' shift 21 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - ')' shift 62 - '|' shift 33 - '&' shift 35 - . error - - -state 42 - stmts: stmts terms stmt. (4) - - . reduce 4 (src line 61) - - -state 43 - stmt: expr '=' expr. (5) - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - OROR shift 34 - ANDAND shift 36 - '?' shift 21 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 5 (src line 71) - - -state 44 - expr: expr.'?' expr ':' expr - expr: expr '?' expr.':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - OROR shift 34 - ANDAND shift 36 - '?' shift 21 - ':' shift 63 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . error - - -45: shift/reduce conflict (shift 33(0), red'n 15(8)) on '|' -45: shift/reduce conflict (shift 35(0), red'n 15(8)) on '&' -state 45 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr '+' expr. (15) - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 15 (src line 114) - - -46: shift/reduce conflict (shift 33(0), red'n 16(8)) on '|' -46: shift/reduce conflict (shift 35(0), red'n 16(8)) on '&' -state 46 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr '-' expr. (16) - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 16 (src line 118) - - -47: shift/reduce conflict (shift 33(0), red'n 17(9)) on '|' -47: shift/reduce conflict (shift 35(0), red'n 17(9)) on '&' -state 47 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr '*' expr. (17) - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '|' shift 33 - '&' shift 35 - . reduce 17 (src line 122) - - -48: shift/reduce conflict (shift 33(0), red'n 18(9)) on '|' -48: shift/reduce conflict (shift 35(0), red'n 18(9)) on '&' -state 48 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr '/' expr. (18) - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '|' shift 33 - '&' shift 35 - . reduce 18 (src line 126) - - -49: shift/reduce conflict (shift 33(0), red'n 19(9)) on '|' -49: shift/reduce conflict (shift 35(0), red'n 19(9)) on '&' -state 49 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr '%' expr. (19) - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '|' shift 33 - '&' shift 35 - . reduce 19 (src line 130) - - -50: shift/reduce conflict (shift 33(0), red'n 20(6)) on '|' -50: shift/reduce conflict (shift 35(0), red'n 20(6)) on '&' -state 50 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr EQEQ expr. (20) - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - EQEQ error - NEQ error - GE shift 30 - LE shift 32 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 20 (src line 134) - - -51: shift/reduce conflict (shift 33(0), red'n 21(6)) on '|' -51: shift/reduce conflict (shift 35(0), red'n 21(6)) on '&' -state 51 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr NEQ expr. (21) - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - EQEQ error - NEQ error - GE shift 30 - LE shift 32 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 21 (src line 138) - - -52: shift/reduce conflict (shift 33(0), red'n 22(7)) on '|' -52: shift/reduce conflict (shift 35(0), red'n 22(7)) on '&' -state 52 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr '>' expr. (22) - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 22 (src line 142) - - -53: shift/reduce conflict (shift 33(0), red'n 23(7)) on '|' -53: shift/reduce conflict (shift 35(0), red'n 23(7)) on '&' -state 53 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr GE expr. (23) - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 23 (src line 146) - - -54: shift/reduce conflict (shift 33(0), red'n 24(7)) on '|' -54: shift/reduce conflict (shift 35(0), red'n 24(7)) on '&' -state 54 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr '<' expr. (24) - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 24 (src line 150) - - -55: shift/reduce conflict (shift 33(0), red'n 25(7)) on '|' -55: shift/reduce conflict (shift 35(0), red'n 25(7)) on '&' -state 55 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr LE expr. (25) - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 25 (src line 154) - - -56: shift/reduce conflict (shift 27(6), red'n 26(0)) on EQEQ -56: shift/reduce conflict (shift 28(6), red'n 26(0)) on NEQ -56: shift/reduce conflict (shift 30(7), red'n 26(0)) on GE -56: shift/reduce conflict (shift 32(7), red'n 26(0)) on LE -56: shift/reduce conflict (shift 34(3), red'n 26(0)) on OROR -56: shift/reduce conflict (shift 36(4), red'n 26(0)) on ANDAND -56: shift/reduce conflict (shift 21(2), red'n 26(0)) on '?' -56: shift/reduce conflict (shift 29(7), red'n 26(0)) on '>' -56: shift/reduce conflict (shift 31(7), red'n 26(0)) on '<' -56: shift/reduce conflict (shift 22(8), red'n 26(0)) on '+' -56: shift/reduce conflict (shift 23(8), red'n 26(0)) on '-' -56: shift/reduce conflict (shift 24(9), red'n 26(0)) on '*' -56: shift/reduce conflict (shift 25(9), red'n 26(0)) on '/' -56: shift/reduce conflict (shift 26(9), red'n 26(0)) on '%' -56: shift/reduce conflict (shift 33(0), red'n 26(0)) on '|' -56: shift/reduce conflict (shift 35(0), red'n 26(0)) on '&' -state 56 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr '|' expr. (26) - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - OROR shift 34 - ANDAND shift 36 - '?' shift 21 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 26 (src line 158) - - -57: shift/reduce conflict (shift 33(0), red'n 27(3)) on '|' -57: shift/reduce conflict (shift 35(0), red'n 27(3)) on '&' -state 57 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr OROR expr. (27) - expr: expr.'&' expr - expr: expr.ANDAND expr - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - ANDAND shift 36 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 27 (src line 162) - - -58: shift/reduce conflict (shift 27(6), red'n 28(0)) on EQEQ -58: shift/reduce conflict (shift 28(6), red'n 28(0)) on NEQ -58: shift/reduce conflict (shift 30(7), red'n 28(0)) on GE -58: shift/reduce conflict (shift 32(7), red'n 28(0)) on LE -58: shift/reduce conflict (shift 34(3), red'n 28(0)) on OROR -58: shift/reduce conflict (shift 36(4), red'n 28(0)) on ANDAND -58: shift/reduce conflict (shift 21(2), red'n 28(0)) on '?' -58: shift/reduce conflict (shift 29(7), red'n 28(0)) on '>' -58: shift/reduce conflict (shift 31(7), red'n 28(0)) on '<' -58: shift/reduce conflict (shift 22(8), red'n 28(0)) on '+' -58: shift/reduce conflict (shift 23(8), red'n 28(0)) on '-' -58: shift/reduce conflict (shift 24(9), red'n 28(0)) on '*' -58: shift/reduce conflict (shift 25(9), red'n 28(0)) on '/' -58: shift/reduce conflict (shift 26(9), red'n 28(0)) on '%' -58: shift/reduce conflict (shift 33(0), red'n 28(0)) on '|' -58: shift/reduce conflict (shift 35(0), red'n 28(0)) on '&' -state 58 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr '&' expr. (28) - expr: expr.ANDAND expr - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - OROR shift 34 - ANDAND shift 36 - '?' shift 21 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 28 (src line 166) - - -59: shift/reduce conflict (shift 33(0), red'n 29(4)) on '|' -59: shift/reduce conflict (shift 35(0), red'n 29(4)) on '&' -state 59 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - expr: expr ANDAND expr. (29) - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 29 (src line 170) - - -state 60 - expr: IDENT '(' exprs.')' - exprs: exprs.',' expr - - ',' shift 65 - ')' shift 64 - . error - - -state 61 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - exprs: expr. (32) - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - OROR shift 34 - ANDAND shift 36 - '?' shift 21 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 32 (src line 183) - - -state 62 - expr: '(' expr ')'. (14) - - . reduce 14 (src line 110) - - -state 63 - expr: expr '?' expr ':'.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 66 - -state 64 - expr: IDENT '(' exprs ')'. (30) - - . reduce 30 (src line 174) - - -state 65 - exprs: exprs ','.expr - - IDENT shift 10 - NUMBER shift 11 - STRING shift 15 - '-' shift 12 - '!' shift 13 - '^' shift 14 - '(' shift 16 - . error - - expr goto 67 - -66: shift/reduce conflict (shift 33(0), red'n 13(2)) on '|' -66: shift/reduce conflict (shift 35(0), red'n 13(2)) on '&' -state 66 - expr: expr.'?' expr ':' expr - expr: expr '?' expr ':' expr. (13) - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - OROR shift 34 - ANDAND shift 36 - '?' shift 21 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 13 (src line 106) - - -state 67 - expr: expr.'?' expr ':' expr - expr: expr.'+' expr - expr: expr.'-' expr - expr: expr.'*' expr - expr: expr.'/' expr - expr: expr.'%' expr - expr: expr.EQEQ expr - expr: expr.NEQ expr - expr: expr.'>' expr - expr: expr.GE expr - expr: expr.'<' expr - expr: expr.LE expr - expr: expr.'|' expr - expr: expr.OROR expr - expr: expr.'&' expr - expr: expr.ANDAND expr - exprs: exprs ',' expr. (33) - - EQEQ shift 27 - NEQ shift 28 - GE shift 30 - LE shift 32 - OROR shift 34 - ANDAND shift 36 - '?' shift 21 - '>' shift 29 - '<' shift 31 - '+' shift 22 - '-' shift 23 - '*' shift 24 - '/' shift 25 - '%' shift 26 - '|' shift 33 - '&' shift 35 - . reduce 33 (src line 187) - - -37 terminals, 9 nonterminals -40 grammar rules, 68/2000 states -66 shift/reduce, 0 reduce/reduce conflicts reported -58 working sets used -memory: parser 38/30000 -49 extra closures -439 shift entries, 5 exceptions -37 goto entries -2 entries saved by goto default -Optimizer space used: output 251/30000 -251 table entries, 74 zero -maximum spread: 37, maximum offset: 65 diff --git a/vendor/github.com/mitchellh/go-homedir/README.md b/vendor/github.com/mitchellh/go-homedir/README.md deleted file mode 100644 index d70706d5b3..0000000000 --- a/vendor/github.com/mitchellh/go-homedir/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# go-homedir - -This is a Go library for detecting the user's home directory without -the use of cgo, so the library can be used in cross-compilation environments. - -Usage is incredibly simple, just call `homedir.Dir()` to get the home directory -for a user, and `homedir.Expand()` to expand the `~` in a path to the home -directory. - -**Why not just use `os/user`?** The built-in `os/user` package requires -cgo on Darwin systems. This means that any Go code that uses that package -cannot cross compile. But 99% of the time the use for `os/user` is just to -retrieve the home directory, which we can do for the current user without -cgo. This library does that, enabling cross-compilation. diff --git a/vendor/github.com/modern-go/concurrent/.gitignore b/vendor/github.com/modern-go/concurrent/.gitignore deleted file mode 100644 index 3f2bc47416..0000000000 --- a/vendor/github.com/modern-go/concurrent/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/coverage.txt diff --git a/vendor/github.com/modern-go/concurrent/.travis.yml b/vendor/github.com/modern-go/concurrent/.travis.yml deleted file mode 100644 index 449e67cd01..0000000000 --- a/vendor/github.com/modern-go/concurrent/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: go - -go: - - 1.8.x - - 1.x - -before_install: - - go get -t -v ./... - -script: - - ./test.sh - -after_success: - - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/modern-go/concurrent/README.md b/vendor/github.com/modern-go/concurrent/README.md deleted file mode 100644 index acab3200aa..0000000000 --- a/vendor/github.com/modern-go/concurrent/README.md +++ /dev/null @@ -1,49 +0,0 @@ -# concurrent - -[![Sourcegraph](https://sourcegraph.com/github.com/modern-go/concurrent/-/badge.svg)](https://sourcegraph.com/github.com/modern-go/concurrent?badge) -[![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/modern-go/concurrent) -[![Build Status](https://travis-ci.org/modern-go/concurrent.svg?branch=master)](https://travis-ci.org/modern-go/concurrent) -[![codecov](https://codecov.io/gh/modern-go/concurrent/branch/master/graph/badge.svg)](https://codecov.io/gh/modern-go/concurrent) -[![rcard](https://goreportcard.com/badge/github.com/modern-go/concurrent)](https://goreportcard.com/report/github.com/modern-go/concurrent) -[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://raw.githubusercontent.com/modern-go/concurrent/master/LICENSE) - -* concurrent.Map: backport sync.Map for go below 1.9 -* concurrent.Executor: goroutine with explicit ownership and cancellable - -# concurrent.Map - -because sync.Map is only available in go 1.9, we can use concurrent.Map to make code portable - -```go -m := concurrent.NewMap() -m.Store("hello", "world") -elem, found := m.Load("hello") -// elem will be "world" -// found will be true -``` - -# concurrent.Executor - -```go -executor := concurrent.NewUnboundedExecutor() -executor.Go(func(ctx context.Context) { - everyMillisecond := time.NewTicker(time.Millisecond) - for { - select { - case <-ctx.Done(): - fmt.Println("goroutine exited") - return - case <-everyMillisecond.C: - // do something - } - } -}) -time.Sleep(time.Second) -executor.StopAndWaitForever() -fmt.Println("executor stopped") -``` - -attach goroutine to executor instance, so that we can - -* cancel it by stop the executor with Stop/StopAndWait/StopAndWaitForever -* handle panic by callback: the default behavior will no longer crash your application \ No newline at end of file diff --git a/vendor/github.com/modern-go/concurrent/test.sh b/vendor/github.com/modern-go/concurrent/test.sh deleted file mode 100755 index d1e6b2ec55..0000000000 --- a/vendor/github.com/modern-go/concurrent/test.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -set -e -echo "" > coverage.txt - -for d in $(go list ./... | grep -v vendor); do - go test -coverprofile=profile.out -coverpkg=github.com/modern-go/concurrent $d - if [ -f profile.out ]; then - cat profile.out >> coverage.txt - rm profile.out - fi -done diff --git a/vendor/github.com/modern-go/reflect2/.gitignore b/vendor/github.com/modern-go/reflect2/.gitignore deleted file mode 100644 index 7b26c946dc..0000000000 --- a/vendor/github.com/modern-go/reflect2/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/vendor -/coverage.txt diff --git a/vendor/github.com/modern-go/reflect2/.travis.yml b/vendor/github.com/modern-go/reflect2/.travis.yml deleted file mode 100644 index fbb43744d9..0000000000 --- a/vendor/github.com/modern-go/reflect2/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: go - -go: - - 1.8.x - - 1.x - -before_install: - - go get -t -v ./... - - go get -t -v github.com/modern-go/reflect2-tests/... - -script: - - ./test.sh - -after_success: - - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/modern-go/reflect2/Gopkg.lock b/vendor/github.com/modern-go/reflect2/Gopkg.lock deleted file mode 100644 index 2a3a69893b..0000000000 --- a/vendor/github.com/modern-go/reflect2/Gopkg.lock +++ /dev/null @@ -1,15 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - name = "github.com/modern-go/concurrent" - packages = ["."] - revision = "e0a39a4cb4216ea8db28e22a69f4ec25610d513a" - version = "1.0.0" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - inputs-digest = "daee8a88b3498b61c5640056665b8b9eea062006f5e596bbb6a3ed9119a11ec7" - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/vendor/github.com/modern-go/reflect2/Gopkg.toml b/vendor/github.com/modern-go/reflect2/Gopkg.toml deleted file mode 100644 index 2f4f4dbdcc..0000000000 --- a/vendor/github.com/modern-go/reflect2/Gopkg.toml +++ /dev/null @@ -1,35 +0,0 @@ -# Gopkg.toml example -# -# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" -# -# [prune] -# non-go = false -# go-tests = true -# unused-packages = true - -ignored = [] - -[[constraint]] - name = "github.com/modern-go/concurrent" - version = "1.0.0" - -[prune] - go-tests = true - unused-packages = true diff --git a/vendor/github.com/modern-go/reflect2/README.md b/vendor/github.com/modern-go/reflect2/README.md deleted file mode 100644 index 6f968aab9e..0000000000 --- a/vendor/github.com/modern-go/reflect2/README.md +++ /dev/null @@ -1,71 +0,0 @@ -# reflect2 - -[![Sourcegraph](https://sourcegraph.com/github.com/modern-go/reflect2/-/badge.svg)](https://sourcegraph.com/github.com/modern-go/reflect2?badge) -[![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/modern-go/reflect2) -[![Build Status](https://travis-ci.org/modern-go/reflect2.svg?branch=master)](https://travis-ci.org/modern-go/reflect2) -[![codecov](https://codecov.io/gh/modern-go/reflect2/branch/master/graph/badge.svg)](https://codecov.io/gh/modern-go/reflect2) -[![rcard](https://goreportcard.com/badge/github.com/modern-go/reflect2)](https://goreportcard.com/report/github.com/modern-go/reflect2) -[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://raw.githubusercontent.com/modern-go/reflect2/master/LICENSE) - -reflect api that avoids runtime reflect.Value cost - -* reflect get/set interface{}, with type checking -* reflect get/set unsafe.Pointer, without type checking -* `reflect2.TypeByName` works like `Class.forName` found in java - -[json-iterator](https://github.com/json-iterator/go) use this package to save runtime dispatching cost. -This package is designed for low level libraries to optimize reflection performance. -General application should still use reflect standard library. - -# reflect2.TypeByName - -```go -// given package is github.com/your/awesome-package -type MyStruct struct { - // ... -} - -// will return the type -reflect2.TypeByName("awesome-package.MyStruct") -// however, if the type has not been used -// it will be eliminated by compiler, so we can not get it in runtime -``` - -# reflect2 get/set interface{} - -```go -valType := reflect2.TypeOf(1) -i := 1 -j := 10 -valType.Set(&i, &j) -// i will be 10 -``` - -to get set `type`, always use its pointer `*type` - -# reflect2 get/set unsafe.Pointer - -```go -valType := reflect2.TypeOf(1) -i := 1 -j := 10 -valType.UnsafeSet(unsafe.Pointer(&i), unsafe.Pointer(&j)) -// i will be 10 -``` - -to get set `type`, always use its pointer `*type` - -# benchmark - -Benchmark is not necessary for this package. It does nothing actually. -As it is just a thin wrapper to make go runtime public. -Both `reflect2` and `reflect` call same function -provided by `runtime` package exposed by go language. - -# unsafe safety - -Instead of casting `[]byte` to `sliceHeader` in your application using unsafe. -We can use reflect2 instead. This way, if `sliceHeader` changes in the future, -only reflect2 need to be upgraded. - -reflect2 tries its best to keep the implementation same as reflect (by testing). \ No newline at end of file diff --git a/vendor/github.com/modern-go/reflect2/test.sh b/vendor/github.com/modern-go/reflect2/test.sh deleted file mode 100755 index 3d2b9768ce..0000000000 --- a/vendor/github.com/modern-go/reflect2/test.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -set -e -echo "" > coverage.txt - -for d in $(go list github.com/modern-go/reflect2-tests/... | grep -v vendor); do - go test -coverprofile=profile.out -coverpkg=github.com/modern-go/reflect2 $d - if [ -f profile.out ]; then - cat profile.out >> coverage.txt - rm profile.out - fi -done diff --git a/vendor/github.com/onsi/ginkgo/.gitignore b/vendor/github.com/onsi/ginkgo/.gitignore deleted file mode 100644 index 18793c248a..0000000000 --- a/vendor/github.com/onsi/ginkgo/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -.DS_Store -TODO -tmp/**/* -*.coverprofile -.vscode -.idea/ -*.log \ No newline at end of file diff --git a/vendor/github.com/onsi/ginkgo/.travis.yml b/vendor/github.com/onsi/ginkgo/.travis.yml deleted file mode 100644 index 7ad39b78f6..0000000000 --- a/vendor/github.com/onsi/ginkgo/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -language: go -go: - - 1.6.x - - 1.7.x - - 1.8.x - - 1.9.x - - 1.10.x - -install: - - go get -v -t ./... - - go get golang.org/x/tools/cmd/cover - - go get github.com/onsi/gomega - - go install github.com/onsi/ginkgo/ginkgo - - export PATH=$PATH:$HOME/gopath/bin - -script: $HOME/gopath/bin/ginkgo -r --randomizeAllSpecs --randomizeSuites --race --trace && go vet diff --git a/vendor/github.com/onsi/ginkgo/CHANGELOG.md b/vendor/github.com/onsi/ginkgo/CHANGELOG.md deleted file mode 100644 index 32370206bf..0000000000 --- a/vendor/github.com/onsi/ginkgo/CHANGELOG.md +++ /dev/null @@ -1,198 +0,0 @@ -## 1.6.0 - -### New Features -- add --debug flag to emit node output to files (#499) [39febac] - -### Fixes -- fix: for `go vet` to pass [69338ec] -- docs: fix for contributing instructions [7004cb1] -- consolidate and streamline contribution docs (#494) [d848015] -- Make generated Junit file compatable with "Maven Surefire" (#488) [e51bee6] -- all: gofmt [000d317] -- Increase eventually timeout to 30s [c73579c] -- Clarify asynchronous test behaviour [294d8f4] -- Travis badge should only show master [26d2143] - -## 1.5.0 5/10/2018 - -### New Features -- Supports go v1.10 (#443, #446, #451) [e873237, 468e89e, e37dbfe, a37f4c0, c0b857d, bca5260, 4177ca8] -- Add a When() synonym for Context() (#386) [747514b, 7484dad, 7354a07, dd826c8] -- Re-add noisySkippings flag [652e15c] -- Allow coverage to be displayed for focused specs (#367) [11459a8] -- Handle -outputdir flag (#364) [228e3a8] -- Handle -coverprofile flag (#355) [43392d5] - -### Fixes -- When using custom reporters register the custom reporters *before* the default reporter. This allows users to see the output of any print statements in their customer reporters. (#365) [8382b23] -- When running a test and calculating the coverage using the `-coverprofile` and `-outputdir` flags, Ginkgo fails with an error if the directory does not exist. This is due to an [issue in go 1.10](https://github.com/golang/go/issues/24588) (#446) [b36a6e0] -- `unfocus` command ignores vendor folder (#459) [e5e551c, c556e43, a3b6351, 9a820dd] -- Ignore packages whose tests are all ignored by go (#456) [7430ca7, 6d8be98] -- Increase the threshold when checking time measuments (#455) [2f714bf, 68f622c] -- Fix race condition in coverage tests (#423) [a5a8ff7, ab9c08b] -- Add an extra new line after reporting spec run completion for test2json [874520d] -- added name name field to junit reported testsuite [ae61c63] -- Do not set the run time of a spec when the dryRun flag is used (#438) [457e2d9, ba8e856] -- Process FWhen and FSpecify when unfocusing (#434) [9008c7b, ee65bd, df87dfe] -- Synchronise the access to the state of specs to avoid race conditions (#430) [7d481bc, ae6829d] -- Added Duration on GinkgoTestDescription (#383) [5f49dad, 528417e, 0747408, 329d7ed] -- Fix Ginkgo stack trace on failure for Specify (#415) [b977ede, 65ca40e, 6c46eb8] -- Update README with Go 1.6+, Golang -> Go (#409) [17f6b97, bc14b66, 20d1598] -- Use fmt.Errorf instead of errors.New(fmt.Sprintf (#401) [a299f56, 44e2eaa] -- Imports in generated code should follow conventions (#398) [0bec0b0, e8536d8] -- Prevent data race error when Recording a benchmark value from multiple go routines (#390) [c0c4881, 7a241e9] -- Replace GOPATH in Environment [4b883f0] - - -## 1.4.0 7/16/2017 - -- `ginkgo` now provides a hint if you accidentally forget to run `ginkgo bootstrap` to generate a `*_suite_test.go` file that actually invokes the Ginkgo test runner. [#345](https://github.com/onsi/ginkgo/pull/345) -- thanks to improvements in `go test -c` `ginkgo` no longer needs to fix Go's compilation output to ensure compilation errors are expressed relative to the CWD. [#357] -- `ginkgo watch -watchRegExp=...` allows you to specify a custom regular expression to watch. Only files matching the regular expression are watched for changes (the default is `\.go$`) [#356] -- `ginkgo` now always emits compilation output. Previously, only failed compilation output was printed out. [#277] -- `ginkgo -requireSuite` now fails the test run if there are `*_test.go` files but `go test` fails to detect any tests. Typically this means you forgot to run `ginkgo bootstrap` to generate a suite file. [#344] -- `ginkgo -timeout=DURATION` allows you to adjust the timeout for the entire test suite (default is 24 hours) [#248] - -## 1.3.0 3/28/2017 - -Improvements: - -- Significantly improved parallel test distribution. Now instead of pre-sharding test cases across workers (which can result in idle workers and poor test performance) Ginkgo uses a shared queue to keep all workers busy until all tests are complete. This improves test-time performance and consistency. -- `Skip(message)` can be used to skip the current test. -- Added `extensions/table` - a Ginkgo DSL for [Table Driven Tests](http://onsi.github.io/ginkgo/#table-driven-tests) -- Add `GinkgoRandomSeed()` - shorthand for `config.GinkgoConfig.RandomSeed` -- Support for retrying flaky tests with `--flakeAttempts` -- `ginkgo ./...` now recurses as you'd expect -- Added `Specify` a synonym for `It` -- Support colorise on Windows -- Broader support for various go compilation flags in the `ginkgo` CLI - -Bug Fixes: - -- Ginkgo tests now fail when you `panic(nil)` (#167) - -## 1.2.0 5/31/2015 - -Improvements - -- `ginkgo -coverpkg` calls down to `go test -coverpkg` (#160) -- `ginkgo -afterSuiteHook COMMAND` invokes the passed-in `COMMAND` after a test suite completes (#152) -- Relaxed requirement for Go 1.4+. `ginkgo` now works with Go v1.3+ (#166) - -## 1.2.0-beta - -Ginkgo now requires Go 1.4+ - -Improvements: - -- Call reporters in reverse order when announcing spec completion -- allows custom reporters to emit output before the default reporter does. -- Improved focus behavior. Now, this: - - ```golang - FDescribe("Some describe", func() { - It("A", func() {}) - - FIt("B", func() {}) - }) - ``` - - will run `B` but *not* `A`. This tends to be a common usage pattern when in the thick of writing and debugging tests. -- When `SIGINT` is received, Ginkgo will emit the contents of the `GinkgoWriter` before running the `AfterSuite`. Useful for debugging stuck tests. -- When `--progress` is set, Ginkgo will write test progress (in particular, Ginkgo will say when it is about to run a BeforeEach, AfterEach, It, etc...) to the `GinkgoWriter`. This is useful for debugging stuck tests and tests that generate many logs. -- Improved output when an error occurs in a setup or teardown block. -- When `--dryRun` is set, Ginkgo will walk the spec tree and emit to its reporter *without* actually running anything. Best paired with `-v` to understand which specs will run in which order. -- Add `By` to help document long `It`s. `By` simply writes to the `GinkgoWriter`. -- Add support for precompiled tests: - - `ginkgo build ` will now compile the package, producing a file named `package.test` - - The compiled `package.test` file can be run directly. This runs the tests in series. - - To run precompiled tests in parallel, you can run: `ginkgo -p package.test` -- Support `bootstrap`ping and `generate`ing [Agouti](http://agouti.org) specs. -- `ginkgo generate` and `ginkgo bootstrap` now honor the package name already defined in a given directory -- The `ginkgo` CLI ignores `SIGQUIT`. Prevents its stack dump from interlacing with the underlying test suite's stack dump. -- The `ginkgo` CLI now compiles tests into a temporary directory instead of the package directory. This necessitates upgrading to Go v1.4+. -- `ginkgo -notify` now works on Linux - -Bug Fixes: - -- If --skipPackages is used and all packages are skipped, Ginkgo should exit 0. -- Fix tempfile leak when running in parallel -- Fix incorrect failure message when a panic occurs during a parallel test run -- Fixed an issue where a pending test within a focused context (or a focused test within a pending context) would skip all other tests. -- Be more consistent about handling SIGTERM as well as SIGINT -- When interupted while concurrently compiling test suites in the background, Ginkgo now cleans up the compiled artifacts. -- Fixed a long standing bug where `ginkgo -p` would hang if a process spawned by one of the Ginkgo parallel nodes does not exit. (Hooray!) - -## 1.1.0 (8/2/2014) - -No changes, just dropping the beta. - -## 1.1.0-beta (7/22/2014) -New Features: - -- `ginkgo watch` now monitors packages *and their dependencies* for changes. The depth of the dependency tree can be modified with the `-depth` flag. -- Test suites with a programmatic focus (`FIt`, `FDescribe`, etc...) exit with non-zero status code, even when they pass. This allows CI systems to detect accidental commits of focused test suites. -- `ginkgo -p` runs the testsuite in parallel with an auto-detected number of nodes. -- `ginkgo -tags=TAG_LIST` passes a list of tags down to the `go build` command. -- `ginkgo --failFast` aborts the test suite after the first failure. -- `ginkgo generate file_1 file_2` can take multiple file arguments. -- Ginkgo now summarizes any spec failures that occured at the end of the test run. -- `ginkgo --randomizeSuites` will run tests *suites* in random order using the generated/passed-in seed. - -Improvements: - -- `ginkgo -skipPackage` now takes a comma-separated list of strings. If the *relative path* to a package matches one of the entries in the comma-separated list, that package is skipped. -- `ginkgo --untilItFails` no longer recompiles between attempts. -- Ginkgo now panics when a runnable node (`It`, `BeforeEach`, `JustBeforeEach`, `AfterEach`, `Measure`) is nested within another runnable node. This is always a mistake. Any test suites that panic because of this change should be fixed. - -Bug Fixes: - -- `ginkgo boostrap` and `ginkgo generate` no longer fail when dealing with `hyphen-separated-packages`. -- parallel specs are now better distributed across nodes - fixed a crashing bug where (for example) distributing 11 tests across 7 nodes would panic - -## 1.0.0 (5/24/2014) -New Features: - -- Add `GinkgoParallelNode()` - shorthand for `config.GinkgoConfig.ParallelNode` - -Improvements: - -- When compilation fails, the compilation output is rewritten to present a correct *relative* path. Allows ⌘-clicking in iTerm open the file in your text editor. -- `--untilItFails` and `ginkgo watch` now generate new random seeds between test runs, unless a particular random seed is specified. - -Bug Fixes: - -- `-cover` now generates a correctly combined coverprofile when running with in parallel with multiple `-node`s. -- Print out the contents of the `GinkgoWriter` when `BeforeSuite` or `AfterSuite` fail. -- Fix all remaining race conditions in Ginkgo's test suite. - -## 1.0.0-beta (4/14/2014) -Breaking changes: - -- `thirdparty/gomocktestreporter` is gone. Use `GinkgoT()` instead -- Modified the Reporter interface -- `watch` is now a subcommand, not a flag. - -DSL changes: - -- `BeforeSuite` and `AfterSuite` for setting up and tearing down test suites. -- `AfterSuite` is triggered on interrupt (`^C`) as well as exit. -- `SynchronizedBeforeSuite` and `SynchronizedAfterSuite` for setting up and tearing down singleton resources across parallel nodes. - -CLI changes: - -- `watch` is now a subcommand, not a flag -- `--nodot` flag can be passed to `ginkgo generate` and `ginkgo bootstrap` to avoid dot imports. This explicitly imports all exported identifiers in Ginkgo and Gomega. Refreshing this list can be done by running `ginkgo nodot` -- Additional arguments can be passed to specs. Pass them after the `--` separator -- `--skipPackage` flag takes a regexp and ignores any packages with package names passing said regexp. -- `--trace` flag prints out full stack traces when errors occur, not just the line at which the error occurs. - -Misc: - -- Start using semantic versioning -- Start maintaining changelog - -Major refactor: - -- Pull out Ginkgo's internal to `internal` -- Rename `example` everywhere to `spec` -- Much more! diff --git a/vendor/github.com/onsi/ginkgo/CONTRIBUTING.md b/vendor/github.com/onsi/ginkgo/CONTRIBUTING.md deleted file mode 100644 index 908b95c2c1..0000000000 --- a/vendor/github.com/onsi/ginkgo/CONTRIBUTING.md +++ /dev/null @@ -1,33 +0,0 @@ -# Contributing to Ginkgo - -Your contributions to Ginkgo are essential for its long-term maintenance and improvement. - -- Please **open an issue first** - describe what problem you are trying to solve and give the community a forum for input and feedback ahead of investing time in writing code! -- Ensure adequate test coverage: - - When adding to the Ginkgo library, add unit and/or integration tests (under the `integration` folder). - - When adding to the Ginkgo CLI, note that there are very few unit tests. Please add an integration test. -- Update the documentation. Ginko uses `godoc` comments and documentation on the `gh-pages` branch. - If relevant, please submit a docs PR to that branch alongside your code PR. - -Thanks for supporting Ginkgo! - -## Setup - -Fork the repo, then: - -``` -go get github.com/onsi/ginkgo -go get github.com/onsi/gomega/... -cd $GOPATH/src/github.com/onsi/ginkgo -git remote add fork git@github.com:/ginkgo.git - -ginkgo -r -p # ensure tests are green -go vet ./... # ensure linter is happy -``` - -## Making the PR - - go to a new branch `git checkout -b my-feature` - - make your changes - - run tests and linter again (see above) - - `git push fork` - - open PR 🎉 diff --git a/vendor/github.com/onsi/ginkgo/README.md b/vendor/github.com/onsi/ginkgo/README.md deleted file mode 100644 index cdf8d054a1..0000000000 --- a/vendor/github.com/onsi/ginkgo/README.md +++ /dev/null @@ -1,121 +0,0 @@ -![Ginkgo: A Go BDD Testing Framework](http://onsi.github.io/ginkgo/images/ginkgo.png) - -[![Build Status](https://travis-ci.org/onsi/ginkgo.svg?branch=master)](https://travis-ci.org/onsi/ginkgo) - -Jump to the [docs](http://onsi.github.io/ginkgo/) to learn more. To start rolling your Ginkgo tests *now* [keep reading](#set-me-up)! - -If you have a question, comment, bug report, feature request, etc. please open a GitHub issue. - -## Feature List - -- Ginkgo uses Go's `testing` package and can live alongside your existing `testing` tests. It's easy to [bootstrap](http://onsi.github.io/ginkgo/#bootstrapping-a-suite) and start writing your [first tests](http://onsi.github.io/ginkgo/#adding-specs-to-a-suite) - -- Structure your BDD-style tests expressively: - - Nestable [`Describe`, `Context` and `When` container blocks](http://onsi.github.io/ginkgo/#organizing-specs-with-containers-describe-and-context) - - [`BeforeEach` and `AfterEach` blocks](http://onsi.github.io/ginkgo/#extracting-common-setup-beforeeach) for setup and teardown - - [`It` and `Specify` blocks](http://onsi.github.io/ginkgo/#individual-specs-) that hold your assertions - - [`JustBeforeEach` blocks](http://onsi.github.io/ginkgo/#separating-creation-and-configuration-justbeforeeach) that separate creation from configuration (also known as the subject action pattern). - - [`BeforeSuite` and `AfterSuite` blocks](http://onsi.github.io/ginkgo/#global-setup-and-teardown-beforesuite-and-aftersuite) to prep for and cleanup after a suite. - -- A comprehensive test runner that lets you: - - Mark specs as [pending](http://onsi.github.io/ginkgo/#pending-specs) - - [Focus](http://onsi.github.io/ginkgo/#focused-specs) individual specs, and groups of specs, either programmatically or on the command line - - Run your tests in [random order](http://onsi.github.io/ginkgo/#spec-permutation), and then reuse random seeds to replicate the same order. - - Break up your test suite into parallel processes for straightforward [test parallelization](http://onsi.github.io/ginkgo/#parallel-specs) - -- `ginkgo`: a command line interface with plenty of handy command line arguments for [running your tests](http://onsi.github.io/ginkgo/#running-tests) and [generating](http://onsi.github.io/ginkgo/#generators) test files. Here are a few choice examples: - - `ginkgo -nodes=N` runs your tests in `N` parallel processes and print out coherent output in realtime - - `ginkgo -cover` runs your tests using Go's code coverage tool - - `ginkgo convert` converts an XUnit-style `testing` package to a Ginkgo-style package - - `ginkgo -focus="REGEXP"` and `ginkgo -skip="REGEXP"` allow you to specify a subset of tests to run via regular expression - - `ginkgo -r` runs all tests suites under the current directory - - `ginkgo -v` prints out identifying information for each tests just before it runs - - And much more: run `ginkgo help` for details! - - The `ginkgo` CLI is convenient, but purely optional -- Ginkgo works just fine with `go test` - -- `ginkgo watch` [watches](https://onsi.github.io/ginkgo/#watching-for-changes) packages *and their dependencies* for changes, then reruns tests. Run tests immediately as you develop! - -- Built-in support for testing [asynchronicity](http://onsi.github.io/ginkgo/#asynchronous-tests) - -- Built-in support for [benchmarking](http://onsi.github.io/ginkgo/#benchmark-tests) your code. Control the number of benchmark samples as you gather runtimes and other, arbitrary, bits of numerical information about your code. - -- [Completions for Sublime Text](https://github.com/onsi/ginkgo-sublime-completions): just use [Package Control](https://sublime.wbond.net/) to install `Ginkgo Completions`. - -- [Completions for VSCode](https://github.com/onsi/vscode-ginkgo): just use VSCode's extension installer to install `vscode-ginkgo`. - -- Straightforward support for third-party testing libraries such as [Gomock](https://code.google.com/p/gomock/) and [Testify](https://github.com/stretchr/testify). Check out the [docs](http://onsi.github.io/ginkgo/#third-party-integrations) for details. - -- A modular architecture that lets you easily: - - Write [custom reporters](http://onsi.github.io/ginkgo/#writing-custom-reporters) (for example, Ginkgo comes with a [JUnit XML reporter](http://onsi.github.io/ginkgo/#generating-junit-xml-output) and a TeamCity reporter). - - [Adapt an existing matcher library (or write your own!)](http://onsi.github.io/ginkgo/#using-other-matcher-libraries) to work with Ginkgo - -## [Gomega](http://github.com/onsi/gomega): Ginkgo's Preferred Matcher Library - -Ginkgo is best paired with Gomega. Learn more about Gomega [here](http://onsi.github.io/gomega/) - -## [Agouti](http://github.com/sclevine/agouti): A Go Acceptance Testing Framework - -Agouti allows you run WebDriver integration tests. Learn more about Agouti [here](http://agouti.org) - -## Set Me Up! - -You'll need the Go command-line tools. Ginkgo is tested with Go 1.6+, but preferably you should get the latest. Follow the [installation instructions](https://golang.org/doc/install) if you don't have it installed. - -```bash - -go get -u github.com/onsi/ginkgo/ginkgo # installs the ginkgo CLI -go get -u github.com/onsi/gomega/... # fetches the matcher library - -cd path/to/package/you/want/to/test - -ginkgo bootstrap # set up a new ginkgo suite -ginkgo generate # will create a sample test file. edit this file and add your tests then... - -go test # to run your tests - -ginkgo # also runs your tests - -``` - -## I'm new to Go: What are my testing options? - -Of course, I heartily recommend [Ginkgo](https://github.com/onsi/ginkgo) and [Gomega](https://github.com/onsi/gomega). Both packages are seeing heavy, daily, production use on a number of projects and boast a mature and comprehensive feature-set. - -With that said, it's great to know what your options are :) - -### What Go gives you out of the box - -Testing is a first class citizen in Go, however Go's built-in testing primitives are somewhat limited: The [testing](http://golang.org/pkg/testing) package provides basic XUnit style tests and no assertion library. - -### Matcher libraries for Go's XUnit style tests - -A number of matcher libraries have been written to augment Go's built-in XUnit style tests. Here are two that have gained traction: - -- [testify](https://github.com/stretchr/testify) -- [gocheck](http://labix.org/gocheck) - -You can also use Ginkgo's matcher library [Gomega](https://github.com/onsi/gomega) in [XUnit style tests](http://onsi.github.io/gomega/#using-gomega-with-golangs-xunitstyle-tests) - -### BDD style testing frameworks - -There are a handful of BDD-style testing frameworks written for Go. Here are a few: - -- [Ginkgo](https://github.com/onsi/ginkgo) ;) -- [GoConvey](https://github.com/smartystreets/goconvey) -- [Goblin](https://github.com/franela/goblin) -- [Mao](https://github.com/azer/mao) -- [Zen](https://github.com/pranavraja/zen) - -Finally, @shageman has [put together](https://github.com/shageman/gotestit) a comprehensive comparison of Go testing libraries. - -Go explore! - -## License - -Ginkgo is MIT-Licensed - -## Contributing - -See [CONTRIBUTING.md](CONTRIBUTING.md) diff --git a/vendor/github.com/onsi/ginkgo/RELEASING.md b/vendor/github.com/onsi/ginkgo/RELEASING.md deleted file mode 100644 index 1e298c2da7..0000000000 --- a/vendor/github.com/onsi/ginkgo/RELEASING.md +++ /dev/null @@ -1,14 +0,0 @@ -A Ginkgo release is a tagged git sha and a GitHub release. To cut a release: - -1. Ensure CHANGELOG.md is up to date. - - Use `git log --pretty=format:'- %s [%h]' HEAD...vX.X.X` to list all the commits since the last release - - Categorize the changes into - - Breaking Changes (requires a major version) - - New Features (minor version) - - Fixes (fix version) - - Maintenance (which in general should not be mentioned in `CHANGELOG.md` as they have no user impact) -1. Update `VERSION` in `config/config.go` -1. Create a commit with the version number as the commit message (e.g. `v1.3.0`) -1. Tag the commit with the version number as the tag name (e.g. `v1.3.0`) -1. Push the commit and tag to GitHub -1. Create a new [GitHub release](https://help.github.com/articles/creating-releases/) with the version number as the tag (e.g. `v1.3.0`). List the key changes in the release notes. diff --git a/vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable/README.md b/vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable/README.md deleted file mode 100644 index e84226a735..0000000000 --- a/vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# go-colorable - -Colorable writer for windows. - -For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.) -This package is possible to handle escape sequence for ansi color on windows. - -## Too Bad! - -![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/bad.png) - - -## So Good! - -![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/good.png) - -## Usage - -```go -logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true}) -logrus.SetOutput(colorable.NewColorableStdout()) - -logrus.Info("succeeded") -logrus.Warn("not correct") -logrus.Error("something error") -logrus.Fatal("panic") -``` - -You can compile above code on non-windows OSs. - -## Installation - -``` -$ go get github.com/mattn/go-colorable -``` - -# License - -MIT - -# Author - -Yasuhiro Matsumoto (a.k.a mattn) diff --git a/vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/README.md b/vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/README.md deleted file mode 100644 index 74845de4a2..0000000000 --- a/vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# go-isatty - -isatty for golang - -## Usage - -```go -package main - -import ( - "fmt" - "github.com/mattn/go-isatty" - "os" -) - -func main() { - if isatty.IsTerminal(os.Stdout.Fd()) { - fmt.Println("Is Terminal") - } else { - fmt.Println("Is Not Terminal") - } -} -``` - -## Installation - -``` -$ go get github.com/mattn/go-isatty -``` - -# License - -MIT - -# Author - -Yasuhiro Matsumoto (a.k.a mattn) diff --git a/vendor/github.com/onsi/gomega/.gitignore b/vendor/github.com/onsi/gomega/.gitignore deleted file mode 100644 index 720c13cba8..0000000000 --- a/vendor/github.com/onsi/gomega/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -.DS_Store -*.test -. -.idea -gomega.iml diff --git a/vendor/github.com/onsi/gomega/.travis.yml b/vendor/github.com/onsi/gomega/.travis.yml deleted file mode 100644 index 61d0f41faf..0000000000 --- a/vendor/github.com/onsi/gomega/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -language: go -go: - - 1.6 - - 1.7 - - 1.8 - -install: - - go get -v ./... - - go get github.com/onsi/ginkgo - - go install github.com/onsi/ginkgo/ginkgo - -script: $HOME/gopath/bin/ginkgo -r --randomizeAllSpecs --failOnPending --randomizeSuites --race diff --git a/vendor/github.com/onsi/gomega/CHANGELOG.md b/vendor/github.com/onsi/gomega/CHANGELOG.md deleted file mode 100644 index a3e8ee4447..0000000000 --- a/vendor/github.com/onsi/gomega/CHANGELOG.md +++ /dev/null @@ -1,74 +0,0 @@ -## HEAD - -## 1.2.0 - -Improvements: - -- Added `BeSent` which attempts to send a value down a channel and fails if the attempt blocks. Can be paired with `Eventually` to safely send a value down a channel with a timeout. -- `Ω`, `Expect`, `Eventually`, and `Consistently` now immediately `panic` if there is no registered fail handler. This is always a mistake that can hide failing tests. -- `Receive()` no longer errors when passed a closed channel, it's perfectly fine to attempt to read from a closed channel so Ω(c).Should(Receive()) always fails and Ω(c).ShoudlNot(Receive()) always passes with a closed channel. -- Added `HavePrefix` and `HaveSuffix` matchers. -- `ghttp` can now handle concurrent requests. -- Added `Succeed` which allows one to write `Ω(MyFunction()).Should(Succeed())`. -- Improved `ghttp`'s behavior around failing assertions and panics: - - If a registered handler makes a failing assertion `ghttp` will return `500`. - - If a registered handler panics, `ghttp` will return `500` *and* fail the test. This is new behavior that may cause existing code to break. This code is almost certainly incorrect and creating a false positive. -- `ghttp` servers can take an `io.Writer`. `ghttp` will write a line to the writer when each request arrives. -- Added `WithTransform` matcher to allow munging input data before feeding into the relevant matcher -- Added boolean `And`, `Or`, and `Not` matchers to allow creating composite matchers -- Added `gbytes.TimeoutCloser`, `gbytes.TimeoutReader`, and `gbytes.TimeoutWriter` - these are convenience wrappers that timeout if the underlying Closer/Reader/Writer does not return within the alloted time. -- Added `gbytes.BufferReader` - this constructs a `gbytes.Buffer` that asynchronously reads the passed-in `io.Reader` into its buffer. - -Bug Fixes: -- gexec: `session.Wait` now uses `EventuallyWithOffset` to get the right line number in the failure. -- `ContainElement` no longer bails if a passed-in matcher errors. - -## 1.0 (8/2/2014) - -No changes. Dropping "beta" from the version number. - -## 1.0.0-beta (7/8/2014) -Breaking Changes: - -- Changed OmegaMatcher interface. Instead of having `Match` return failure messages, two new methods `FailureMessage` and `NegatedFailureMessage` are called instead. -- Moved and renamed OmegaFailHandler to types.GomegaFailHandler and OmegaMatcher to types.GomegaMatcher. Any references to OmegaMatcher in any custom matchers will need to be changed to point to types.GomegaMatcher - -New Test-Support Features: - -- `ghttp`: supports testing http clients - - Provides a flexible fake http server - - Provides a collection of chainable http handlers that perform assertions. -- `gbytes`: supports making ordered assertions against streams of data - - Provides a `gbytes.Buffer` - - Provides a `Say` matcher to perform ordered assertions against output data -- `gexec`: supports testing external processes - - Provides support for building Go binaries - - Wraps and starts `exec.Cmd` commands - - Makes it easy to assert against stdout and stderr - - Makes it easy to send signals and wait for processes to exit - - Provides an `Exit` matcher to assert against exit code. - -DSL Changes: - -- `Eventually` and `Consistently` can accept `time.Duration` interval and polling inputs. -- The default timeouts for `Eventually` and `Consistently` are now configurable. - -New Matchers: - -- `ConsistOf`: order-independent assertion against the elements of an array/slice or keys of a map. -- `BeTemporally`: like `BeNumerically` but for `time.Time` -- `HaveKeyWithValue`: asserts a map has a given key with the given value. - -Updated Matchers: - -- `Receive` matcher can take a matcher as an argument and passes only if the channel under test receives an objet that satisfies the passed-in matcher. -- Matchers that implement `MatchMayChangeInTheFuture(actual interface{}) bool` can inform `Eventually` and/or `Consistently` when a match has no chance of changing status in the future. For example, `Receive` returns `false` when a channel is closed. - -Misc: - -- Start using semantic versioning -- Start maintaining changelog - -Major refactor: - -- Pull out Gomega's internal to `internal` diff --git a/vendor/github.com/onsi/gomega/CONTRIBUTING.md b/vendor/github.com/onsi/gomega/CONTRIBUTING.md deleted file mode 100644 index 73d4020e6b..0000000000 --- a/vendor/github.com/onsi/gomega/CONTRIBUTING.md +++ /dev/null @@ -1,11 +0,0 @@ -# Contributing to Gomega - -Your contributions to Gomega are essential for its long-term maintenance and improvement. To make a contribution: - -- Please **open an issue first** - describe what problem you are trying to solve and give the community a forum for input and feedback ahead of investing time in writing code! -- Ensure adequate test coverage: - - Make sure to add appropriate unit tests - - Please run all tests locally (`ginkgo -r -p`) and make sure they go green before submitting the PR -- Update the documentation. In addition to standard `godoc` comments Gomega has extensive documentation on the `gh-pages` branch. If relevant, please submit a docs PR to that branch alongside your code PR. - -Thanks for supporting Gomega! \ No newline at end of file diff --git a/vendor/github.com/onsi/gomega/README.md b/vendor/github.com/onsi/gomega/README.md deleted file mode 100644 index 159be35907..0000000000 --- a/vendor/github.com/onsi/gomega/README.md +++ /dev/null @@ -1,21 +0,0 @@ -![Gomega: Ginkgo's Preferred Matcher Library](http://onsi.github.io/gomega/images/gomega.png) - -[![Build Status](https://travis-ci.org/onsi/gomega.svg)](https://travis-ci.org/onsi/gomega) - -Jump straight to the [docs](http://onsi.github.io/gomega/) to learn about Gomega, including a list of [all available matchers](http://onsi.github.io/gomega/#provided-matchers). - -If you have a question, comment, bug report, feature request, etc. please open a GitHub issue. - -## [Ginkgo](http://github.com/onsi/ginkgo): a BDD Testing Framework for Golang - -Learn more about Ginkgo [here](http://onsi.github.io/ginkgo/) - -## Community Matchers - -A collection of community matchers is available on the [wiki](https://github.com/onsi/gomega/wiki). - -## License - -Gomega is MIT-Licensed - -The `ConsistOf` matcher uses [goraph](https://github.com/amitkgupta/goraph) which is embedded in the source to simplify distribution. goraph has an MIT license. diff --git a/vendor/github.com/peterbourgon/diskv/README.md b/vendor/github.com/peterbourgon/diskv/README.md deleted file mode 100644 index 3474739edc..0000000000 --- a/vendor/github.com/peterbourgon/diskv/README.md +++ /dev/null @@ -1,141 +0,0 @@ -# What is diskv? - -Diskv (disk-vee) is a simple, persistent key-value store written in the Go -language. It starts with an incredibly simple API for storing arbitrary data on -a filesystem by key, and builds several layers of performance-enhancing -abstraction on top. The end result is a conceptually simple, but highly -performant, disk-backed storage system. - -[![Build Status][1]][2] - -[1]: https://drone.io/github.com/peterbourgon/diskv/status.png -[2]: https://drone.io/github.com/peterbourgon/diskv/latest - - -# Installing - -Install [Go 1][3], either [from source][4] or [with a prepackaged binary][5]. -Then, - -```bash -$ go get github.com/peterbourgon/diskv -``` - -[3]: http://golang.org -[4]: http://golang.org/doc/install/source -[5]: http://golang.org/doc/install - - -# Usage - -```go -package main - -import ( - "fmt" - "github.com/peterbourgon/diskv" -) - -func main() { - // Simplest transform function: put all the data files into the base dir. - flatTransform := func(s string) []string { return []string{} } - - // Initialize a new diskv store, rooted at "my-data-dir", with a 1MB cache. - d := diskv.New(diskv.Options{ - BasePath: "my-data-dir", - Transform: flatTransform, - CacheSizeMax: 1024 * 1024, - }) - - // Write three bytes to the key "alpha". - key := "alpha" - d.Write(key, []byte{'1', '2', '3'}) - - // Read the value back out of the store. - value, _ := d.Read(key) - fmt.Printf("%v\n", value) - - // Erase the key+value from the store (and the disk). - d.Erase(key) -} -``` - -More complex examples can be found in the "examples" subdirectory. - - -# Theory - -## Basic idea - -At its core, diskv is a map of a key (`string`) to arbitrary data (`[]byte`). -The data is written to a single file on disk, with the same name as the key. -The key determines where that file will be stored, via a user-provided -`TransformFunc`, which takes a key and returns a slice (`[]string`) -corresponding to a path list where the key file will be stored. The simplest -TransformFunc, - -```go -func SimpleTransform (key string) []string { - return []string{} -} -``` - -will place all keys in the same, base directory. The design is inspired by -[Redis diskstore][6]; a TransformFunc which emulates the default diskstore -behavior is available in the content-addressable-storage example. - -[6]: http://groups.google.com/group/redis-db/browse_thread/thread/d444bc786689bde9?pli=1 - -**Note** that your TransformFunc should ensure that one valid key doesn't -transform to a subset of another valid key. That is, it shouldn't be possible -to construct valid keys that resolve to directory names. As a concrete example, -if your TransformFunc splits on every 3 characters, then - -```go -d.Write("abcabc", val) // OK: written to /abc/abc/abcabc -d.Write("abc", val) // Error: attempted write to /abc/abc, but it's a directory -``` - -This will be addressed in an upcoming version of diskv. - -Probably the most important design principle behind diskv is that your data is -always flatly available on the disk. diskv will never do anything that would -prevent you from accessing, copying, backing up, or otherwise interacting with -your data via common UNIX commandline tools. - -## Adding a cache - -An in-memory caching layer is provided by combining the BasicStore -functionality with a simple map structure, and keeping it up-to-date as -appropriate. Since the map structure in Go is not threadsafe, it's combined -with a RWMutex to provide safe concurrent access. - -## Adding order - -diskv is a key-value store and therefore inherently unordered. An ordering -system can be injected into the store by passing something which satisfies the -diskv.Index interface. (A default implementation, using Google's -[btree][7] package, is provided.) Basically, diskv keeps an ordered (by a -user-provided Less function) index of the keys, which can be queried. - -[7]: https://github.com/google/btree - -## Adding compression - -Something which implements the diskv.Compression interface may be passed -during store creation, so that all Writes and Reads are filtered through -a compression/decompression pipeline. Several default implementations, -using stdlib compression algorithms, are provided. Note that data is cached -compressed; the cost of decompression is borne with each Read. - -## Streaming - -diskv also now provides ReadStream and WriteStream methods, to allow very large -data to be handled efficiently. - - -# Future plans - - * Needs plenty of robust testing: huge datasets, etc... - * More thorough benchmarking - * Your suggestions for use-cases I haven't thought of diff --git a/vendor/github.com/pkg/errors/.gitignore b/vendor/github.com/pkg/errors/.gitignore deleted file mode 100644 index daf913b1b3..0000000000 --- a/vendor/github.com/pkg/errors/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof diff --git a/vendor/github.com/pkg/errors/.travis.yml b/vendor/github.com/pkg/errors/.travis.yml deleted file mode 100644 index 588ceca183..0000000000 --- a/vendor/github.com/pkg/errors/.travis.yml +++ /dev/null @@ -1,11 +0,0 @@ -language: go -go_import_path: github.com/pkg/errors -go: - - 1.4.3 - - 1.5.4 - - 1.6.2 - - 1.7.1 - - tip - -script: - - go test -v ./... diff --git a/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md deleted file mode 100644 index 273db3c98a..0000000000 --- a/vendor/github.com/pkg/errors/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) - -Package errors provides simple error handling primitives. - -`go get github.com/pkg/errors` - -The traditional error handling idiom in Go is roughly akin to -```go -if err != nil { - return err -} -``` -which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. - -## Adding context to an error - -The errors.Wrap function returns a new error that adds context to the original error. For example -```go -_, err := ioutil.ReadAll(r) -if err != nil { - return errors.Wrap(err, "read failed") -} -``` -## Retrieving the cause of an error - -Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. -```go -type causer interface { - Cause() error -} -``` -`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: -```go -switch err := errors.Cause(err).(type) { -case *MyError: - // handle specifically -default: - // unknown error -} -``` - -[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). - -## Contributing - -We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high. - -Before proposing a change, please discuss your change by raising an issue. - -## Licence - -BSD-2-Clause diff --git a/vendor/github.com/pkg/errors/appveyor.yml b/vendor/github.com/pkg/errors/appveyor.yml deleted file mode 100644 index a932eade02..0000000000 --- a/vendor/github.com/pkg/errors/appveyor.yml +++ /dev/null @@ -1,32 +0,0 @@ -version: build-{build}.{branch} - -clone_folder: C:\gopath\src\github.com\pkg\errors -shallow_clone: true # for startup speed - -environment: - GOPATH: C:\gopath - -platform: - - x64 - -# http://www.appveyor.com/docs/installed-software -install: - # some helpful output for debugging builds - - go version - - go env - # pre-installed MinGW at C:\MinGW is 32bit only - # but MSYS2 at C:\msys64 has mingw64 - - set PATH=C:\msys64\mingw64\bin;%PATH% - - gcc --version - - g++ --version - -build_script: - - go install -v ./... - -test_script: - - set PATH=C:\gopath\bin;%PATH% - - go test -v ./... - -#artifacts: -# - path: '%GOPATH%\bin\*.exe' -deploy: off diff --git a/vendor/github.com/satori/go.uuid/.travis.yml b/vendor/github.com/satori/go.uuid/.travis.yml deleted file mode 100644 index 20dd53b8d3..0000000000 --- a/vendor/github.com/satori/go.uuid/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -language: go -sudo: false -go: - - 1.2 - - 1.3 - - 1.4 - - 1.5 - - 1.6 - - 1.7 - - 1.8 - - 1.9 - - tip -matrix: - allow_failures: - - go: tip - fast_finish: true -before_install: - - go get github.com/mattn/goveralls - - go get golang.org/x/tools/cmd/cover -script: - - $HOME/gopath/bin/goveralls -service=travis-ci -notifications: - email: false diff --git a/vendor/github.com/satori/go.uuid/README.md b/vendor/github.com/satori/go.uuid/README.md deleted file mode 100644 index 7b1a722dff..0000000000 --- a/vendor/github.com/satori/go.uuid/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# UUID package for Go language - -[![Build Status](https://travis-ci.org/satori/go.uuid.png?branch=master)](https://travis-ci.org/satori/go.uuid) -[![Coverage Status](https://coveralls.io/repos/github/satori/go.uuid/badge.svg?branch=master)](https://coveralls.io/github/satori/go.uuid) -[![GoDoc](http://godoc.org/github.com/satori/go.uuid?status.png)](http://godoc.org/github.com/satori/go.uuid) - -This package provides pure Go implementation of Universally Unique Identifier (UUID). Supported both creation and parsing of UUIDs. - -With 100% test coverage and benchmarks out of box. - -Supported versions: -* Version 1, based on timestamp and MAC address (RFC 4122) -* Version 2, based on timestamp, MAC address and POSIX UID/GID (DCE 1.1) -* Version 3, based on MD5 hashing (RFC 4122) -* Version 4, based on random numbers (RFC 4122) -* Version 5, based on SHA-1 hashing (RFC 4122) - -## Installation - -Use the `go` command: - - $ go get github.com/satori/go.uuid - -## Requirements - -UUID package requires Go >= 1.2. - -## Example - -```go -package main - -import ( - "fmt" - "github.com/satori/go.uuid" -) - -func main() { - // Creating UUID Version 4 - u1 := uuid.NewV4() - fmt.Printf("UUIDv4: %s\n", u1) - - // Parsing UUID from string input - u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - if err != nil { - fmt.Printf("Something gone wrong: %s", err) - } - fmt.Printf("Successfully parsed: %s", u2) -} -``` - -## Documentation - -[Documentation](http://godoc.org/github.com/satori/go.uuid) is hosted at GoDoc project. - -## Links -* [RFC 4122](http://tools.ietf.org/html/rfc4122) -* [DCE 1.1: Authentication and Security Services](http://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01) - -## Copyright - -Copyright (C) 2013-2018 by Maxim Bublis . - -UUID package released under MIT License. -See [LICENSE](https://github.com/satori/go.uuid/blob/master/LICENSE) for details. diff --git a/vendor/github.com/sirupsen/logrus/.gitignore b/vendor/github.com/sirupsen/logrus/.gitignore deleted file mode 100644 index 66be63a005..0000000000 --- a/vendor/github.com/sirupsen/logrus/.gitignore +++ /dev/null @@ -1 +0,0 @@ -logrus diff --git a/vendor/github.com/sirupsen/logrus/.travis.yml b/vendor/github.com/sirupsen/logrus/.travis.yml deleted file mode 100644 index a23296a53b..0000000000 --- a/vendor/github.com/sirupsen/logrus/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: go -go: - - 1.6.x - - 1.7.x - - 1.8.x - - tip -env: - - GOMAXPROCS=4 GORACE=halt_on_error=1 -install: - - go get github.com/stretchr/testify/assert - - go get gopkg.in/gemnasium/logrus-airbrake-hook.v2 - - go get golang.org/x/sys/unix - - go get golang.org/x/sys/windows -script: - - go test -race -v ./... diff --git a/vendor/github.com/sirupsen/logrus/CHANGELOG.md b/vendor/github.com/sirupsen/logrus/CHANGELOG.md deleted file mode 100644 index 8236d8b6ee..0000000000 --- a/vendor/github.com/sirupsen/logrus/CHANGELOG.md +++ /dev/null @@ -1,113 +0,0 @@ -# 1.0.3 - -* Replace example files with testable examples - -# 1.0.2 - -* bug: quote non-string values in text formatter (#583) -* Make (*Logger) SetLevel a public method - -# 1.0.1 - -* bug: fix escaping in text formatter (#575) - -# 1.0.0 - -* Officially changed name to lower-case -* bug: colors on Windows 10 (#541) -* bug: fix race in accessing level (#512) - -# 0.11.5 - -* feature: add writer and writerlevel to entry (#372) - -# 0.11.4 - -* bug: fix undefined variable on solaris (#493) - -# 0.11.3 - -* formatter: configure quoting of empty values (#484) -* formatter: configure quoting character (default is `"`) (#484) -* bug: fix not importing io correctly in non-linux environments (#481) - -# 0.11.2 - -* bug: fix windows terminal detection (#476) - -# 0.11.1 - -* bug: fix tty detection with custom out (#471) - -# 0.11.0 - -* performance: Use bufferpool to allocate (#370) -* terminal: terminal detection for app-engine (#343) -* feature: exit handler (#375) - -# 0.10.0 - -* feature: Add a test hook (#180) -* feature: `ParseLevel` is now case-insensitive (#326) -* feature: `FieldLogger` interface that generalizes `Logger` and `Entry` (#308) -* performance: avoid re-allocations on `WithFields` (#335) - -# 0.9.0 - -* logrus/text_formatter: don't emit empty msg -* logrus/hooks/airbrake: move out of main repository -* logrus/hooks/sentry: move out of main repository -* logrus/hooks/papertrail: move out of main repository -* logrus/hooks/bugsnag: move out of main repository -* logrus/core: run tests with `-race` -* logrus/core: detect TTY based on `stderr` -* logrus/core: support `WithError` on logger -* logrus/core: Solaris support - -# 0.8.7 - -* logrus/core: fix possible race (#216) -* logrus/doc: small typo fixes and doc improvements - - -# 0.8.6 - -* hooks/raven: allow passing an initialized client - -# 0.8.5 - -* logrus/core: revert #208 - -# 0.8.4 - -* formatter/text: fix data race (#218) - -# 0.8.3 - -* logrus/core: fix entry log level (#208) -* logrus/core: improve performance of text formatter by 40% -* logrus/core: expose `LevelHooks` type -* logrus/core: add support for DragonflyBSD and NetBSD -* formatter/text: print structs more verbosely - -# 0.8.2 - -* logrus: fix more Fatal family functions - -# 0.8.1 - -* logrus: fix not exiting on `Fatalf` and `Fatalln` - -# 0.8.0 - -* logrus: defaults to stderr instead of stdout -* hooks/sentry: add special field for `*http.Request` -* formatter/text: ignore Windows for colors - -# 0.7.3 - -* formatter/\*: allow configuration of timestamp layout - -# 0.7.2 - -* formatter/text: Add configuration option for time format (#158) diff --git a/vendor/github.com/sirupsen/logrus/README.md b/vendor/github.com/sirupsen/logrus/README.md deleted file mode 100644 index 4f5ce576dc..0000000000 --- a/vendor/github.com/sirupsen/logrus/README.md +++ /dev/null @@ -1,505 +0,0 @@ -# Logrus :walrus: [![Build Status](https://travis-ci.org/sirupsen/logrus.svg?branch=master)](https://travis-ci.org/sirupsen/logrus) [![GoDoc](https://godoc.org/github.com/sirupsen/logrus?status.svg)](https://godoc.org/github.com/sirupsen/logrus) - -Logrus is a structured logger for Go (golang), completely API compatible with -the standard library logger. - -**Seeing weird case-sensitive problems?** It's in the past been possible to -import Logrus as both upper- and lower-case. Due to the Go package environment, -this caused issues in the community and we needed a standard. Some environments -experienced problems with the upper-case variant, so the lower-case was decided. -Everything using `logrus` will need to use the lower-case: -`github.com/sirupsen/logrus`. Any package that isn't, should be changed. - -To fix Glide, see [these -comments](https://github.com/sirupsen/logrus/issues/553#issuecomment-306591437). -For an in-depth explanation of the casing issue, see [this -comment](https://github.com/sirupsen/logrus/issues/570#issuecomment-313933276). - -**Are you interested in assisting in maintaining Logrus?** Currently I have a -lot of obligations, and I am unable to provide Logrus with the maintainership it -needs. If you'd like to help, please reach out to me at `simon at author's -username dot com`. - -Nicely color-coded in development (when a TTY is attached, otherwise just -plain text): - -![Colored](http://i.imgur.com/PY7qMwd.png) - -With `log.SetFormatter(&log.JSONFormatter{})`, for easy parsing by logstash -or Splunk: - -```json -{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the -ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"} - -{"level":"warning","msg":"The group's number increased tremendously!", -"number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"} - -{"animal":"walrus","level":"info","msg":"A giant walrus appears!", -"size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"} - -{"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.", -"size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"} - -{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true, -"time":"2014-03-10 19:57:38.562543128 -0400 EDT"} -``` - -With the default `log.SetFormatter(&log.TextFormatter{})` when a TTY is not -attached, the output is compatible with the -[logfmt](http://godoc.org/github.com/kr/logfmt) format: - -```text -time="2015-03-26T01:27:38-04:00" level=debug msg="Started observing beach" animal=walrus number=8 -time="2015-03-26T01:27:38-04:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10 -time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true -time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4 -time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009 -time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} number=100 omg=true -exit status 1 -``` - -#### Case-sensitivity - -The organization's name was changed to lower-case--and this will not be changed -back. If you are getting import conflicts due to case sensitivity, please use -the lower-case import: `github.com/sirupsen/logrus`. - -#### Example - -The simplest way to use Logrus is simply the package-level exported logger: - -```go -package main - -import ( - log "github.com/sirupsen/logrus" -) - -func main() { - log.WithFields(log.Fields{ - "animal": "walrus", - }).Info("A walrus appears") -} -``` - -Note that it's completely api-compatible with the stdlib logger, so you can -replace your `log` imports everywhere with `log "github.com/sirupsen/logrus"` -and you'll now have the flexibility of Logrus. You can customize it all you -want: - -```go -package main - -import ( - "os" - log "github.com/sirupsen/logrus" -) - -func init() { - // Log as JSON instead of the default ASCII formatter. - log.SetFormatter(&log.JSONFormatter{}) - - // Output to stdout instead of the default stderr - // Can be any io.Writer, see below for File example - log.SetOutput(os.Stdout) - - // Only log the warning severity or above. - log.SetLevel(log.WarnLevel) -} - -func main() { - log.WithFields(log.Fields{ - "animal": "walrus", - "size": 10, - }).Info("A group of walrus emerges from the ocean") - - log.WithFields(log.Fields{ - "omg": true, - "number": 122, - }).Warn("The group's number increased tremendously!") - - log.WithFields(log.Fields{ - "omg": true, - "number": 100, - }).Fatal("The ice breaks!") - - // A common pattern is to re-use fields between logging statements by re-using - // the logrus.Entry returned from WithFields() - contextLogger := log.WithFields(log.Fields{ - "common": "this is a common field", - "other": "I also should be logged always", - }) - - contextLogger.Info("I'll be logged with common and other field") - contextLogger.Info("Me too") -} -``` - -For more advanced usage such as logging to multiple locations from the same -application, you can also create an instance of the `logrus` Logger: - -```go -package main - -import ( - "os" - "github.com/sirupsen/logrus" -) - -// Create a new instance of the logger. You can have any number of instances. -var log = logrus.New() - -func main() { - // The API for setting attributes is a little different than the package level - // exported logger. See Godoc. - log.Out = os.Stdout - - // You could set this to any `io.Writer` such as a file - // file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666) - // if err == nil { - // log.Out = file - // } else { - // log.Info("Failed to log to file, using default stderr") - // } - - log.WithFields(logrus.Fields{ - "animal": "walrus", - "size": 10, - }).Info("A group of walrus emerges from the ocean") -} -``` - -#### Fields - -Logrus encourages careful, structured logging through logging fields instead of -long, unparseable error messages. For example, instead of: `log.Fatalf("Failed -to send event %s to topic %s with key %d")`, you should log the much more -discoverable: - -```go -log.WithFields(log.Fields{ - "event": event, - "topic": topic, - "key": key, -}).Fatal("Failed to send event") -``` - -We've found this API forces you to think about logging in a way that produces -much more useful logging messages. We've been in countless situations where just -a single added field to a log statement that was already there would've saved us -hours. The `WithFields` call is optional. - -In general, with Logrus using any of the `printf`-family functions should be -seen as a hint you should add a field, however, you can still use the -`printf`-family functions with Logrus. - -#### Default Fields - -Often it's helpful to have fields _always_ attached to log statements in an -application or parts of one. For example, you may want to always log the -`request_id` and `user_ip` in the context of a request. Instead of writing -`log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})` on -every line, you can create a `logrus.Entry` to pass around instead: - -```go -requestLogger := log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip}) -requestLogger.Info("something happened on that request") # will log request_id and user_ip -requestLogger.Warn("something not great happened") -``` - -#### Hooks - -You can add hooks for logging levels. For example to send errors to an exception -tracking service on `Error`, `Fatal` and `Panic`, info to StatsD or log to -multiple places simultaneously, e.g. syslog. - -Logrus comes with [built-in hooks](hooks/). Add those, or your custom hook, in -`init`: - -```go -import ( - log "github.com/sirupsen/logrus" - "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "aibrake" - logrus_syslog "github.com/sirupsen/logrus/hooks/syslog" - "log/syslog" -) - -func init() { - - // Use the Airbrake hook to report errors that have Error severity or above to - // an exception tracker. You can create custom hooks, see the Hooks section. - log.AddHook(airbrake.NewHook(123, "xyz", "production")) - - hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "") - if err != nil { - log.Error("Unable to connect to local syslog daemon") - } else { - log.AddHook(hook) - } -} -``` -Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md). - -| Hook | Description | -| ----- | ----------- | -| [Airbrake "legacy"](https://github.com/gemnasium/logrus-airbrake-legacy-hook) | Send errors to an exception tracking service compatible with the Airbrake API V2. Uses [`airbrake-go`](https://github.com/tobi/airbrake-go) behind the scenes. | -| [Airbrake](https://github.com/gemnasium/logrus-airbrake-hook) | Send errors to the Airbrake API V3. Uses the official [`gobrake`](https://github.com/airbrake/gobrake) behind the scenes. | -| [Amazon Kinesis](https://github.com/evalphobia/logrus_kinesis) | Hook for logging to [Amazon Kinesis](https://aws.amazon.com/kinesis/) | -| [Amqp-Hook](https://github.com/vladoatanasov/logrus_amqp) | Hook for logging to Amqp broker (Like RabbitMQ) | -| [Bugsnag](https://github.com/Shopify/logrus-bugsnag/blob/master/bugsnag.go) | Send errors to the Bugsnag exception tracking service. | -| [DeferPanic](https://github.com/deferpanic/dp-logrus) | Hook for logging to DeferPanic | -| [Discordrus](https://github.com/kz/discordrus) | Hook for logging to [Discord](https://discordapp.com/) | -| [ElasticSearch](https://github.com/sohlich/elogrus) | Hook for logging to ElasticSearch| -| [Firehose](https://github.com/beaubrewer/logrus_firehose) | Hook for logging to [Amazon Firehose](https://aws.amazon.com/kinesis/firehose/) -| [Fluentd](https://github.com/evalphobia/logrus_fluent) | Hook for logging to fluentd | -| [Go-Slack](https://github.com/multiplay/go-slack) | Hook for logging to [Slack](https://slack.com) | -| [Graylog](https://github.com/gemnasium/logrus-graylog-hook) | Hook for logging to [Graylog](http://graylog2.org/) | -| [Hiprus](https://github.com/nubo/hiprus) | Send errors to a channel in hipchat. | -| [Honeybadger](https://github.com/agonzalezro/logrus_honeybadger) | Hook for sending exceptions to Honeybadger | -| [InfluxDB](https://github.com/Abramovic/logrus_influxdb) | Hook for logging to influxdb | -| [Influxus](http://github.com/vlad-doru/influxus) | Hook for concurrently logging to [InfluxDB](http://influxdata.com/) | -| [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` | -| [KafkaLogrus](https://github.com/goibibo/KafkaLogrus) | Hook for logging to kafka | -| [LFShook](https://github.com/rifflock/lfshook) | Hook for logging to the local filesystem | -| [Logentries](https://github.com/jcftang/logentriesrus) | Hook for logging to [Logentries](https://logentries.com/) | -| [Logentrus](https://github.com/puddingfactory/logentrus) | Hook for logging to [Logentries](https://logentries.com/) | -| [Logmatic.io](https://github.com/logmatic/logmatic-go) | Hook for logging to [Logmatic.io](http://logmatic.io/) | -| [Logrusly](https://github.com/sebest/logrusly) | Send logs to [Loggly](https://www.loggly.com/) | -| [Logstash](https://github.com/bshuster-repo/logrus-logstash-hook) | Hook for logging to [Logstash](https://www.elastic.co/products/logstash) | -| [Mail](https://github.com/zbindenren/logrus_mail) | Hook for sending exceptions via mail | -| [Mattermost](https://github.com/shuLhan/mattermost-integration/tree/master/hooks/logrus) | Hook for logging to [Mattermost](https://mattermost.com/) | -| [Mongodb](https://github.com/weekface/mgorus) | Hook for logging to mongodb | -| [NATS-Hook](https://github.com/rybit/nats_logrus_hook) | Hook for logging to [NATS](https://nats.io) | -| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit | -| [Papertrail](https://github.com/polds/logrus-papertrail-hook) | Send errors to the [Papertrail](https://papertrailapp.com) hosted logging service via UDP. | -| [PostgreSQL](https://github.com/gemnasium/logrus-postgresql-hook) | Send logs to [PostgreSQL](http://postgresql.org) | -| [Pushover](https://github.com/toorop/logrus_pushover) | Send error via [Pushover](https://pushover.net) | -| [Raygun](https://github.com/squirkle/logrus-raygun-hook) | Hook for logging to [Raygun.io](http://raygun.io/) | -| [Redis-Hook](https://github.com/rogierlommers/logrus-redis-hook) | Hook for logging to a ELK stack (through Redis) | -| [Rollrus](https://github.com/heroku/rollrus) | Hook for sending errors to rollbar | -| [Scribe](https://github.com/sagar8192/logrus-scribe-hook) | Hook for logging to [Scribe](https://github.com/facebookarchive/scribe)| -| [Sentry](https://github.com/evalphobia/logrus_sentry) | Send errors to the Sentry error logging and aggregation service. | -| [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. | -| [Stackdriver](https://github.com/knq/sdhook) | Hook for logging to [Google Stackdriver](https://cloud.google.com/logging/) | -| [Sumorus](https://github.com/doublefree/sumorus) | Hook for logging to [SumoLogic](https://www.sumologic.com/)| -| [Syslog](https://github.com/sirupsen/logrus/blob/master/hooks/syslog/syslog.go) | Send errors to remote syslog server. Uses standard library `log/syslog` behind the scenes. | -| [Syslog TLS](https://github.com/shinji62/logrus-syslog-ng) | Send errors to remote syslog server with TLS support. | -| [TraceView](https://github.com/evalphobia/logrus_appneta) | Hook for logging to [AppNeta TraceView](https://www.appneta.com/products/traceview/) | -| [Typetalk](https://github.com/dragon3/logrus-typetalk-hook) | Hook for logging to [Typetalk](https://www.typetalk.in/) | -| [logz.io](https://github.com/ripcurld00d/logrus-logzio-hook) | Hook for logging to [logz.io](https://logz.io), a Log as a Service using Logstash | -| [SQS-Hook](https://github.com/tsarpaul/logrus_sqs) | Hook for logging to [Amazon Simple Queue Service (SQS)](https://aws.amazon.com/sqs/) | - -#### Level logging - -Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic. - -```go -log.Debug("Useful debugging information.") -log.Info("Something noteworthy happened!") -log.Warn("You should probably take a look at this.") -log.Error("Something failed but I'm not quitting.") -// Calls os.Exit(1) after logging -log.Fatal("Bye.") -// Calls panic() after logging -log.Panic("I'm bailing.") -``` - -You can set the logging level on a `Logger`, then it will only log entries with -that severity or anything above it: - -```go -// Will log anything that is info or above (warn, error, fatal, panic). Default. -log.SetLevel(log.InfoLevel) -``` - -It may be useful to set `log.Level = logrus.DebugLevel` in a debug or verbose -environment if your application has that. - -#### Entries - -Besides the fields added with `WithField` or `WithFields` some fields are -automatically added to all logging events: - -1. `time`. The timestamp when the entry was created. -2. `msg`. The logging message passed to `{Info,Warn,Error,Fatal,Panic}` after - the `AddFields` call. E.g. `Failed to send event.` -3. `level`. The logging level. E.g. `info`. - -#### Environments - -Logrus has no notion of environment. - -If you wish for hooks and formatters to only be used in specific environments, -you should handle that yourself. For example, if your application has a global -variable `Environment`, which is a string representation of the environment you -could do: - -```go -import ( - log "github.com/sirupsen/logrus" -) - -init() { - // do something here to set environment depending on an environment variable - // or command-line flag - if Environment == "production" { - log.SetFormatter(&log.JSONFormatter{}) - } else { - // The TextFormatter is default, you don't actually have to do this. - log.SetFormatter(&log.TextFormatter{}) - } -} -``` - -This configuration is how `logrus` was intended to be used, but JSON in -production is mostly only useful if you do log aggregation with tools like -Splunk or Logstash. - -#### Formatters - -The built-in logging formatters are: - -* `logrus.TextFormatter`. Logs the event in colors if stdout is a tty, otherwise - without colors. - * *Note:* to force colored output when there is no TTY, set the `ForceColors` - field to `true`. To force no colored output even if there is a TTY set the - `DisableColors` field to `true`. For Windows, see - [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable). - * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#TextFormatter). -* `logrus.JSONFormatter`. Logs fields as JSON. - * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#JSONFormatter). - -Third party logging formatters: - -* [`FluentdFormatter`](https://github.com/joonix/log). Formats entries that can by parsed by Kubernetes and Google Container Engine. -* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events. -* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout. -* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦. - -You can define your formatter by implementing the `Formatter` interface, -requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a -`Fields` type (`map[string]interface{}`) with all your fields as well as the -default ones (see Entries section above): - -```go -type MyJSONFormatter struct { -} - -log.SetFormatter(new(MyJSONFormatter)) - -func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) { - // Note this doesn't include Time, Level and Message which are available on - // the Entry. Consult `godoc` on information about those fields or read the - // source of the official loggers. - serialized, err := json.Marshal(entry.Data) - if err != nil { - return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) - } - return append(serialized, '\n'), nil -} -``` - -#### Logger as an `io.Writer` - -Logrus can be transformed into an `io.Writer`. That writer is the end of an `io.Pipe` and it is your responsibility to close it. - -```go -w := logger.Writer() -defer w.Close() - -srv := http.Server{ - // create a stdlib log.Logger that writes to - // logrus.Logger. - ErrorLog: log.New(w, "", 0), -} -``` - -Each line written to that writer will be printed the usual way, using formatters -and hooks. The level for those entries is `info`. - -This means that we can override the standard library logger easily: - -```go -logger := logrus.New() -logger.Formatter = &logrus.JSONFormatter{} - -// Use logrus for standard log output -// Note that `log` here references stdlib's log -// Not logrus imported under the name `log`. -log.SetOutput(logger.Writer()) -``` - -#### Rotation - -Log rotation is not provided with Logrus. Log rotation should be done by an -external program (like `logrotate(8)`) that can compress and delete old log -entries. It should not be a feature of the application-level logger. - -#### Tools - -| Tool | Description | -| ---- | ----------- | -|[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will generated with different config at different environment.| -|[Logrus Viper Helper](https://github.com/heirko/go-contrib/tree/master/logrusHelper)|An Helper around Logrus to wrap with spf13/Viper to load configuration with fangs! And to simplify Logrus configuration use some behavior of [Logrus Mate](https://github.com/gogap/logrus_mate). [sample](https://github.com/heirko/iris-contrib/blob/master/middleware/logrus-logger/example) | - -#### Testing - -Logrus has a built in facility for asserting the presence of log messages. This is implemented through the `test` hook and provides: - -* decorators for existing logger (`test.NewLocal` and `test.NewGlobal`) which basically just add the `test` hook -* a test logger (`test.NewNullLogger`) that just records log messages (and does not output any): - -```go -import( - "github.com/sirupsen/logrus" - "github.com/sirupsen/logrus/hooks/test" - "github.com/stretchr/testify/assert" - "testing" -) - -func TestSomething(t*testing.T){ - logger, hook := test.NewNullLogger() - logger.Error("Helloerror") - - assert.Equal(t, 1, len(hook.Entries)) - assert.Equal(t, logrus.ErrorLevel, hook.LastEntry().Level) - assert.Equal(t, "Helloerror", hook.LastEntry().Message) - - hook.Reset() - assert.Nil(t, hook.LastEntry()) -} -``` - -#### Fatal handlers - -Logrus can register one or more functions that will be called when any `fatal` -level message is logged. The registered handlers will be executed before -logrus performs a `os.Exit(1)`. This behavior may be helpful if callers need -to gracefully shutdown. Unlike a `panic("Something went wrong...")` call which can be intercepted with a deferred `recover` a call to `os.Exit(1)` can not be intercepted. - -``` -... -handler := func() { - // gracefully shutdown something... -} -logrus.RegisterExitHandler(handler) -... -``` - -#### Thread safety - -By default Logger is protected by mutex for concurrent writes, this mutex is invoked when calling hooks and writing logs. -If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking. - -Situation when locking is not needed includes: - -* You have no hooks registered, or hooks calling is already thread-safe. - -* Writing to logger.Out is already thread-safe, for example: - - 1) logger.Out is protected by locks. - - 2) logger.Out is a os.File handler opened with `O_APPEND` flag, and every write is smaller than 4k. (This allow multi-thread/multi-process writing) - - (Refer to http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/) diff --git a/vendor/github.com/sirupsen/logrus/appveyor.yml b/vendor/github.com/sirupsen/logrus/appveyor.yml deleted file mode 100644 index 96c2ce15f8..0000000000 --- a/vendor/github.com/sirupsen/logrus/appveyor.yml +++ /dev/null @@ -1,14 +0,0 @@ -version: "{build}" -platform: x64 -clone_folder: c:\gopath\src\github.com\sirupsen\logrus -environment: - GOPATH: c:\gopath -branches: - only: - - master -install: - - set PATH=%GOPATH%\bin;c:\go\bin;%PATH% - - go version -build_script: - - go get -t - - go test diff --git a/vendor/github.com/spf13/cobra/.gitignore b/vendor/github.com/spf13/cobra/.gitignore deleted file mode 100644 index 1b8c7c2611..0000000000 --- a/vendor/github.com/spf13/cobra/.gitignore +++ /dev/null @@ -1,36 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -# Vim files https://github.com/github/gitignore/blob/master/Global/Vim.gitignore -# swap -[._]*.s[a-w][a-z] -[._]s[a-w][a-z] -# session -Session.vim -# temporary -.netrwhist -*~ -# auto-generated tag files -tags - -*.exe - -cobra.test diff --git a/vendor/github.com/spf13/cobra/.mailmap b/vendor/github.com/spf13/cobra/.mailmap deleted file mode 100644 index 94ec53068a..0000000000 --- a/vendor/github.com/spf13/cobra/.mailmap +++ /dev/null @@ -1,3 +0,0 @@ -Steve Francia -Bjørn Erik Pedersen -Fabiano Franz diff --git a/vendor/github.com/spf13/cobra/.travis.yml b/vendor/github.com/spf13/cobra/.travis.yml deleted file mode 100644 index cb2bf0d5c2..0000000000 --- a/vendor/github.com/spf13/cobra/.travis.yml +++ /dev/null @@ -1,21 +0,0 @@ -language: go - -matrix: - include: - - go: 1.7.5 - - go: 1.8.1 - - go: tip - allow_failures: - - go: tip - -before_install: - - mkdir -p bin - - curl -Lso bin/shellcheck https://github.com/caarlos0/shellcheck-docker/releases/download/v0.4.3/shellcheck - - chmod +x bin/shellcheck -script: - - PATH=$PATH:$PWD/bin go test -v ./... - - go build - - diff -u <(echo -n) <(gofmt -d -s .) - - if [ -z $NOVET ]; then - diff -u <(echo -n) <(go tool vet . 2>&1 | grep -vE 'ExampleCommand|bash_completions.*Fprint'); - fi diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md deleted file mode 100644 index 4563c211d0..0000000000 --- a/vendor/github.com/spf13/cobra/README.md +++ /dev/null @@ -1,887 +0,0 @@ -![cobra logo](https://cloud.githubusercontent.com/assets/173412/10886352/ad566232-814f-11e5-9cd0-aa101788c117.png) - -Cobra is both a library for creating powerful modern CLI applications as well as a program to generate applications and command files. - -Many of the most widely used Go projects are built using Cobra including: - -* [Kubernetes](http://kubernetes.io/) -* [Hugo](http://gohugo.io) -* [rkt](https://github.com/coreos/rkt) -* [etcd](https://github.com/coreos/etcd) -* [Moby (former Docker)](https://github.com/moby/moby) -* [Docker (distribution)](https://github.com/docker/distribution) -* [OpenShift](https://www.openshift.com/) -* [Delve](https://github.com/derekparker/delve) -* [GopherJS](http://www.gopherjs.org/) -* [CockroachDB](http://www.cockroachlabs.com/) -* [Bleve](http://www.blevesearch.com/) -* [ProjectAtomic (enterprise)](http://www.projectatomic.io/) -* [GiantSwarm's swarm](https://github.com/giantswarm/cli) -* [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack) -* [rclone](http://rclone.org/) - - -[![Build Status](https://travis-ci.org/spf13/cobra.svg "Travis CI status")](https://travis-ci.org/spf13/cobra) -[![CircleCI status](https://circleci.com/gh/spf13/cobra.png?circle-token=:circle-token "CircleCI status")](https://circleci.com/gh/spf13/cobra) -[![GoDoc](https://godoc.org/github.com/spf13/cobra?status.svg)](https://godoc.org/github.com/spf13/cobra) - -![cobra](https://cloud.githubusercontent.com/assets/173412/10911369/84832a8e-8212-11e5-9f82-cc96660a4794.gif) - -# Overview - -Cobra is a library providing a simple interface to create powerful modern CLI -interfaces similar to git & go tools. - -Cobra is also an application that will generate your application scaffolding to rapidly -develop a Cobra-based application. - -Cobra provides: -* Easy subcommand-based CLIs: `app server`, `app fetch`, etc. -* Fully POSIX-compliant flags (including short & long versions) -* Nested subcommands -* Global, local and cascading flags -* Easy generation of applications & commands with `cobra init appname` & `cobra add cmdname` -* Intelligent suggestions (`app srver`... did you mean `app server`?) -* Automatic help generation for commands and flags -* Automatic detailed help for `app help [command]` -* Automatic help flag recognition of `-h`, `--help`, etc. -* Automatically generated bash autocomplete for your application -* Automatically generated man pages for your application -* Command aliases so you can change things without breaking them -* The flexibility to define your own help, usage, etc. -* Optional tight integration with [viper](http://github.com/spf13/viper) for 12-factor apps - -Cobra has an exceptionally clean interface and simple design without needless -constructors or initialization methods. - -Applications built with Cobra commands are designed to be as user-friendly as -possible. Flags can be placed before or after the command (as long as a -confusing space isn’t provided). Both short and long flags can be used. A -command need not even be fully typed. Help is automatically generated and -available for the application or for a specific command using either the help -command or the `--help` flag. - -# Concepts - -Cobra is built on a structure of commands, arguments & flags. - -**Commands** represent actions, **Args** are things and **Flags** are modifiers for those actions. - -The best applications will read like sentences when used. Users will know how -to use the application because they will natively understand how to use it. - -The pattern to follow is -`APPNAME VERB NOUN --ADJECTIVE.` - or -`APPNAME COMMAND ARG --FLAG` - -A few good real world examples may better illustrate this point. - -In the following example, 'server' is a command, and 'port' is a flag: - - hugo server --port=1313 - -In this command we are telling Git to clone the url bare. - - git clone URL --bare - -## Commands - -Command is the central point of the application. Each interaction that -the application supports will be contained in a Command. A command can -have children commands and optionally run an action. - -In the example above, 'server' is the command. - -A Command has the following structure: - -```go -type Command struct { - Use string // The one-line usage message. - Short string // The short description shown in the 'help' output. - Long string // The long message shown in the 'help ' output. - Run func(cmd *Command, args []string) // Run runs the command. -} -``` - -## Flags - -A Flag is a way to modify the behavior of a command. Cobra supports -fully POSIX-compliant flags as well as the Go [flag package](https://golang.org/pkg/flag/). -A Cobra command can define flags that persist through to children commands -and flags that are only available to that command. - -In the example above, 'port' is the flag. - -Flag functionality is provided by the [pflag -library](https://github.com/spf13/pflag), a fork of the flag standard library -which maintains the same interface while adding POSIX compliance. - -## Usage - -Cobra works by creating a set of commands and then organizing them into a tree. -The tree defines the structure of the application. - -Once each command is defined with its corresponding flags, then the -tree is assigned to the commander which is finally executed. - -# Installing -Using Cobra is easy. First, use `go get` to install the latest version -of the library. This command will install the `cobra` generator executible -along with the library: - - go get -v github.com/spf13/cobra/cobra - -Next, include Cobra in your application: - -```go -import "github.com/spf13/cobra" -``` - -# Getting Started - -While you are welcome to provide your own organization, typically a Cobra based -application will follow the following organizational structure. - -``` - ▾ appName/ - ▾ cmd/ - add.go - your.go - commands.go - here.go - main.go -``` - -In a Cobra app, typically the main.go file is very bare. It serves, one purpose, to initialize Cobra. - -```go -package main - -import ( - "fmt" - "os" - - "{pathToYourApp}/cmd" -) - -func main() { - if err := cmd.RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } -} -``` - -## Using the Cobra Generator - -Cobra provides its own program that will create your application and add any -commands you want. It's the easiest way to incorporate Cobra into your application. - -In order to use the cobra command, compile it using the following command: - - go get github.com/spf13/cobra/cobra - -This will create the cobra executable under your `$GOPATH/bin` directory. - -### cobra init - -The `cobra init [yourApp]` command will create your initial application code -for you. It is a very powerful application that will populate your program with -the right structure so you can immediately enjoy all the benefits of Cobra. It -will also automatically apply the license you specify to your application. - -Cobra init is pretty smart. You can provide it a full path, or simply a path -similar to what is expected in the import. - -``` -cobra init github.com/spf13/newAppName -``` - -### cobra add - -Once an application is initialized Cobra can create additional commands for you. -Let's say you created an app and you wanted the following commands for it: - -* app serve -* app config -* app config create - -In your project directory (where your main.go file is) you would run the following: - -``` -cobra add serve -cobra add config -cobra add create -p 'configCmd' -``` - -*Note: Use camelCase (not snake_case/snake-case) for command names. -Otherwise, you will become unexpected errors. -For example, `cobra add add-user` is incorrect, but `cobra add addUser` is valid.* - -Once you have run these three commands you would have an app structure that would look like: - -``` - ▾ app/ - ▾ cmd/ - serve.go - config.go - create.go - main.go -``` - -at this point you can run `go run main.go` and it would run your app. `go run -main.go serve`, `go run main.go config`, `go run main.go config create` along -with `go run main.go help serve`, etc would all work. - -Obviously you haven't added your own code to these yet, the commands are ready -for you to give them their tasks. Have fun. - -### Configuring the cobra generator - -The cobra generator will be easier to use if you provide a simple configuration -file which will help you eliminate providing a bunch of repeated information in -flags over and over. - -An example ~/.cobra.yaml file: - -```yaml -author: Steve Francia -license: MIT -``` - -You can specify no license by setting `license` to `none` or you can specify -a custom license: - -```yaml -license: - header: This file is part of {{ .appName }}. - text: | - {{ .copyright }} - - This is my license. There are many like it, but this one is mine. - My license is my best friend. It is my life. I must master it as I must - master my life. -``` - -You can also use built-in licenses. For example, **GPLv2**, **GPLv3**, **LGPL**, -**AGPL**, **MIT**, **2-Clause BSD** or **3-Clause BSD**. - -## Manually implementing Cobra - -To manually implement cobra you need to create a bare main.go file and a RootCmd file. -You will optionally provide additional commands as you see fit. - -### Create the root command - -The root command represents your binary itself. - - -#### Manually create rootCmd - -Cobra doesn't require any special constructors. Simply create your commands. - -Ideally you place this in app/cmd/root.go: - -```go -var RootCmd = &cobra.Command{ - Use: "hugo", - Short: "Hugo is a very fast static site generator", - Long: `A Fast and Flexible Static Site Generator built with - love by spf13 and friends in Go. - Complete documentation is available at http://hugo.spf13.com`, - Run: func(cmd *cobra.Command, args []string) { - // Do Stuff Here - }, -} -``` - -You will additionally define flags and handle configuration in your init() function. - -for example cmd/root.go: - -```go -func init() { - cobra.OnInitialize(initConfig) - RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)") - RootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/") - RootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution") - RootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)") - RootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration") - viper.BindPFlag("author", RootCmd.PersistentFlags().Lookup("author")) - viper.BindPFlag("projectbase", RootCmd.PersistentFlags().Lookup("projectbase")) - viper.BindPFlag("useViper", RootCmd.PersistentFlags().Lookup("viper")) - viper.SetDefault("author", "NAME HERE ") - viper.SetDefault("license", "apache") -} -``` - -### Create your main.go - -With the root command you need to have your main function execute it. -Execute should be run on the root for clarity, though it can be called on any command. - -In a Cobra app, typically the main.go file is very bare. It serves, one purpose, to initialize Cobra. - -```go -package main - -import ( - "fmt" - "os" - - "{pathToYourApp}/cmd" -) - -func main() { - if err := cmd.RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } -} -``` - - -### Create additional commands - -Additional commands can be defined and typically are each given their own file -inside of the cmd/ directory. - -If you wanted to create a version command you would create cmd/version.go and -populate it with the following: - -```go -package cmd - -import ( - "github.com/spf13/cobra" - "fmt" -) - -func init() { - RootCmd.AddCommand(versionCmd) -} - -var versionCmd = &cobra.Command{ - Use: "version", - Short: "Print the version number of Hugo", - Long: `All software has versions. This is Hugo's`, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Hugo Static Site Generator v0.9 -- HEAD") - }, -} -``` - -### Attach command to its parent - - -If you notice in the above example we attach the command to its parent. In -this case the parent is the rootCmd. In this example we are attaching it to the -root, but commands can be attached at any level. - -```go -RootCmd.AddCommand(versionCmd) -``` - -### Remove a command from its parent - -Removing a command is not a common action in simple programs, but it allows 3rd -parties to customize an existing command tree. - -In this example, we remove the existing `VersionCmd` command of an existing -root command, and we replace it with our own version: - -```go -mainlib.RootCmd.RemoveCommand(mainlib.VersionCmd) -mainlib.RootCmd.AddCommand(versionCmd) -``` - -## Working with Flags - -Flags provide modifiers to control how the action command operates. - -### Assign flags to a command - -Since the flags are defined and used in different locations, we need to -define a variable outside with the correct scope to assign the flag to -work with. - -```go -var Verbose bool -var Source string -``` - -There are two different approaches to assign a flag. - -### Persistent Flags - -A flag can be 'persistent' meaning that this flag will be available to the -command it's assigned to as well as every command under that command. For -global flags, assign a flag as a persistent flag on the root. - -```go -RootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output") -``` - -### Local Flags - -A flag can also be assigned locally which will only apply to that specific command. - -```go -RootCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from") -``` - - -## Example - -In the example below, we have defined three commands. Two are at the top level -and one (cmdTimes) is a child of one of the top commands. In this case the root -is not executable meaning that a subcommand is required. This is accomplished -by not providing a 'Run' for the 'rootCmd'. - -We have only defined one flag for a single command. - -More documentation about flags is available at https://github.com/spf13/pflag - -```go -package main - -import ( - "fmt" - "strings" - - "github.com/spf13/cobra" -) - -func main() { - - var echoTimes int - - var cmdPrint = &cobra.Command{ - Use: "print [string to print]", - Short: "Print anything to the screen", - Long: `print is for printing anything back to the screen. - For many years people have printed back to the screen. - `, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Print: " + strings.Join(args, " ")) - }, - } - - var cmdEcho = &cobra.Command{ - Use: "echo [string to echo]", - Short: "Echo anything to the screen", - Long: `echo is for echoing anything back. - Echo works a lot like print, except it has a child command. - `, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Print: " + strings.Join(args, " ")) - }, - } - - var cmdTimes = &cobra.Command{ - Use: "times [# times] [string to echo]", - Short: "Echo anything to the screen more times", - Long: `echo things multiple times back to the user by providing - a count and a string.`, - Run: func(cmd *cobra.Command, args []string) { - for i := 0; i < echoTimes; i++ { - fmt.Println("Echo: " + strings.Join(args, " ")) - } - }, - } - - cmdTimes.Flags().IntVarP(&echoTimes, "times", "t", 1, "times to echo the input") - - var rootCmd = &cobra.Command{Use: "app"} - rootCmd.AddCommand(cmdPrint, cmdEcho) - cmdEcho.AddCommand(cmdTimes) - rootCmd.Execute() -} -``` - -For a more complete example of a larger application, please checkout [Hugo](http://gohugo.io/). - -## The Help Command - -Cobra automatically adds a help command to your application when you have subcommands. -This will be called when a user runs 'app help'. Additionally, help will also -support all other commands as input. Say, for instance, you have a command called -'create' without any additional configuration; Cobra will work when 'app help -create' is called. Every command will automatically have the '--help' flag added. - -### Example - -The following output is automatically generated by Cobra. Nothing beyond the -command and flag definitions are needed. - - > hugo help - - hugo is the main command, used to build your Hugo site. - - Hugo is a Fast and Flexible Static Site Generator - built with love by spf13 and friends in Go. - - Complete documentation is available at http://gohugo.io/. - - Usage: - hugo [flags] - hugo [command] - - Available Commands: - server Hugo runs its own webserver to render the files - version Print the version number of Hugo - config Print the site configuration - check Check content in the source directory - benchmark Benchmark hugo by building a site a number of times. - convert Convert your content to different formats - new Create new content for your site - list Listing out various types of content - undraft Undraft changes the content's draft status from 'True' to 'False' - genautocomplete Generate shell autocompletion script for Hugo - gendoc Generate Markdown documentation for the Hugo CLI. - genman Generate man page for Hugo - import Import your site from others. - - Flags: - -b, --baseURL="": hostname (and path) to the root, e.g. http://spf13.com/ - -D, --buildDrafts[=false]: include content marked as draft - -F, --buildFuture[=false]: include content with publishdate in the future - --cacheDir="": filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/ - --canonifyURLs[=false]: if true, all relative URLs will be canonicalized using baseURL - --config="": config file (default is path/config.yaml|json|toml) - -d, --destination="": filesystem path to write files to - --disableRSS[=false]: Do not build RSS files - --disableSitemap[=false]: Do not build Sitemap file - --editor="": edit new content with this editor, if provided - --ignoreCache[=false]: Ignores the cache directory for reading but still writes to it - --log[=false]: Enable Logging - --logFile="": Log File path (if set, logging enabled automatically) - --noTimes[=false]: Don't sync modification time of files - --pluralizeListTitles[=true]: Pluralize titles in lists using inflect - --preserveTaxonomyNames[=false]: Preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu") - -s, --source="": filesystem path to read files relative from - --stepAnalysis[=false]: display memory and timing of different steps of the program - -t, --theme="": theme to use (located in /themes/THEMENAME/) - --uglyURLs[=false]: if true, use /filename.html instead of /filename/ - -v, --verbose[=false]: verbose output - --verboseLog[=false]: verbose logging - -w, --watch[=false]: watch filesystem for changes and recreate as needed - - Use "hugo [command] --help" for more information about a command. - - -Help is just a command like any other. There is no special logic or behavior -around it. In fact, you can provide your own if you want. - -### Defining your own help - -You can provide your own Help command or your own template for the default command to use. - -The default help command is - -```go -func (c *Command) initHelp() { - if c.helpCommand == nil { - c.helpCommand = &Command{ - Use: "help [command]", - Short: "Help about any command", - Long: `Help provides help for any command in the application. - Simply type ` + c.Name() + ` help [path to command] for full details.`, - Run: c.HelpFunc(), - } - } - c.AddCommand(c.helpCommand) -} -``` - -You can provide your own command, function or template through the following methods: - -```go -command.SetHelpCommand(cmd *Command) - -command.SetHelpFunc(f func(*Command, []string)) - -command.SetHelpTemplate(s string) -``` - -The latter two will also apply to any children commands. - -## Usage - -When the user provides an invalid flag or invalid command, Cobra responds by -showing the user the 'usage'. - -### Example -You may recognize this from the help above. That's because the default help -embeds the usage as part of its output. - - Usage: - hugo [flags] - hugo [command] - - Available Commands: - server Hugo runs its own webserver to render the files - version Print the version number of Hugo - config Print the site configuration - check Check content in the source directory - benchmark Benchmark hugo by building a site a number of times. - convert Convert your content to different formats - new Create new content for your site - list Listing out various types of content - undraft Undraft changes the content's draft status from 'True' to 'False' - genautocomplete Generate shell autocompletion script for Hugo - gendoc Generate Markdown documentation for the Hugo CLI. - genman Generate man page for Hugo - import Import your site from others. - - Flags: - -b, --baseURL="": hostname (and path) to the root, e.g. http://spf13.com/ - -D, --buildDrafts[=false]: include content marked as draft - -F, --buildFuture[=false]: include content with publishdate in the future - --cacheDir="": filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/ - --canonifyURLs[=false]: if true, all relative URLs will be canonicalized using baseURL - --config="": config file (default is path/config.yaml|json|toml) - -d, --destination="": filesystem path to write files to - --disableRSS[=false]: Do not build RSS files - --disableSitemap[=false]: Do not build Sitemap file - --editor="": edit new content with this editor, if provided - --ignoreCache[=false]: Ignores the cache directory for reading but still writes to it - --log[=false]: Enable Logging - --logFile="": Log File path (if set, logging enabled automatically) - --noTimes[=false]: Don't sync modification time of files - --pluralizeListTitles[=true]: Pluralize titles in lists using inflect - --preserveTaxonomyNames[=false]: Preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu") - -s, --source="": filesystem path to read files relative from - --stepAnalysis[=false]: display memory and timing of different steps of the program - -t, --theme="": theme to use (located in /themes/THEMENAME/) - --uglyURLs[=false]: if true, use /filename.html instead of /filename/ - -v, --verbose[=false]: verbose output - --verboseLog[=false]: verbose logging - -w, --watch[=false]: watch filesystem for changes and recreate as needed - -### Defining your own usage -You can provide your own usage function or template for Cobra to use. - -The default usage function is: - -```go -return func(c *Command) error { - err := tmpl(c.Out(), c.UsageTemplate(), c) - return err -} -``` - -Like help, the function and template are overridable through public methods: - -```go -command.SetUsageFunc(f func(*Command) error) - -command.SetUsageTemplate(s string) -``` - -## PreRun or PostRun Hooks - -It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherited by children if they do not declare their own. These functions are run in the following order: - -- `PersistentPreRun` -- `PreRun` -- `Run` -- `PostRun` -- `PersistentPostRun` - -An example of two commands which use all of these features is below. When the subcommand is executed, it will run the root command's `PersistentPreRun` but not the root command's `PersistentPostRun`: - -```go -package main - -import ( - "fmt" - - "github.com/spf13/cobra" -) - -func main() { - - var rootCmd = &cobra.Command{ - Use: "root [sub]", - Short: "My root command", - PersistentPreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PersistentPreRun with args: %v\n", args) - }, - PreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PreRun with args: %v\n", args) - }, - Run: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd Run with args: %v\n", args) - }, - PostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PostRun with args: %v\n", args) - }, - PersistentPostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PersistentPostRun with args: %v\n", args) - }, - } - - var subCmd = &cobra.Command{ - Use: "sub [no options!]", - Short: "My subcommand", - PreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PreRun with args: %v\n", args) - }, - Run: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd Run with args: %v\n", args) - }, - PostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PostRun with args: %v\n", args) - }, - PersistentPostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PersistentPostRun with args: %v\n", args) - }, - } - - rootCmd.AddCommand(subCmd) - - rootCmd.SetArgs([]string{""}) - _ = rootCmd.Execute() - fmt.Print("\n") - rootCmd.SetArgs([]string{"sub", "arg1", "arg2"}) - _ = rootCmd.Execute() -} -``` - - -## Alternative Error Handling - -Cobra also has functions where the return signature is an error. This allows for errors to bubble up to the top, -providing a way to handle the errors in one location. The current list of functions that return an error is: - -* PersistentPreRunE -* PreRunE -* RunE -* PostRunE -* PersistentPostRunE - -If you would like to silence the default `error` and `usage` output in favor of your own, you can set `SilenceUsage` -and `SilenceErrors` to `true` on the command. A child command respects these flags if they are set on the parent -command. - -**Example Usage using RunE:** - -```go -package main - -import ( - "errors" - "log" - - "github.com/spf13/cobra" -) - -func main() { - var rootCmd = &cobra.Command{ - Use: "hugo", - Short: "Hugo is a very fast static site generator", - Long: `A Fast and Flexible Static Site Generator built with - love by spf13 and friends in Go. - Complete documentation is available at http://hugo.spf13.com`, - RunE: func(cmd *cobra.Command, args []string) error { - // Do Stuff Here - return errors.New("some random error") - }, - } - - if err := rootCmd.Execute(); err != nil { - log.Fatal(err) - } -} -``` - -## Suggestions when "unknown command" happens - -Cobra will print automatic suggestions when "unknown command" errors happen. This allows Cobra to behave similarly to the `git` command when a typo happens. For example: - -``` -$ hugo srever -Error: unknown command "srever" for "hugo" - -Did you mean this? - server - -Run 'hugo --help' for usage. -``` - -Suggestions are automatic based on every subcommand registered and use an implementation of [Levenshtein distance](http://en.wikipedia.org/wiki/Levenshtein_distance). Every registered command that matches a minimum distance of 2 (ignoring case) will be displayed as a suggestion. - -If you need to disable suggestions or tweak the string distance in your command, use: - -```go -command.DisableSuggestions = true -``` - -or - -```go -command.SuggestionsMinimumDistance = 1 -``` - -You can also explicitly set names for which a given command will be suggested using the `SuggestFor` attribute. This allows suggestions for strings that are not close in terms of string distance, but makes sense in your set of commands and for some which you don't want aliases. Example: - -``` -$ kubectl remove -Error: unknown command "remove" for "kubectl" - -Did you mean this? - delete - -Run 'kubectl help' for usage. -``` - -## Generating Markdown-formatted documentation for your command - -Cobra can generate a Markdown-formatted document based on the subcommands, flags, etc. A simple example of how to do this for your command can be found in [Markdown Docs](doc/md_docs.md). - -## Generating man pages for your command - -Cobra can generate a man page based on the subcommands, flags, etc. A simple example of how to do this for your command can be found in [Man Docs](doc/man_docs.md). - -## Generating bash completions for your command - -Cobra can generate a bash-completion file. If you add more information to your command, these completions can be amazingly powerful and flexible. Read more about it in [Bash Completions](bash_completions.md). - -## Debugging - -Cobra provides a ‘DebugFlags’ method on a command which, when called, will print -out everything Cobra knows about the flags for each command. - -### Example - -```go -command.DebugFlags() -``` - -## Extensions - -Libraries for extending Cobra: - -* [cmdns](https://github.com/gosuri/cmdns): Enables name spacing a command's immediate children. It provides an alternative way to structure subcommands, similar to `heroku apps:create` and `ovrclk clusters:launch`. - -## Contributing - -1. Fork it -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Commit your changes (`git commit -am 'Add some feature'`) -4. Push to the branch (`git push origin my-new-feature`) -5. Create new Pull Request - -## Contributors - -Names in no particular order: - -* [spf13](https://github.com/spf13), -[eparis](https://github.com/eparis), -[bep](https://github.com/bep), and many more! - -## License - -Cobra is released under the Apache 2.0 license. See [LICENSE.txt](https://github.com/spf13/cobra/blob/master/LICENSE.txt) diff --git a/vendor/github.com/spf13/cobra/bash_completions.md b/vendor/github.com/spf13/cobra/bash_completions.md deleted file mode 100644 index 52bd39ddb1..0000000000 --- a/vendor/github.com/spf13/cobra/bash_completions.md +++ /dev/null @@ -1,206 +0,0 @@ -# Generating Bash Completions For Your Own cobra.Command - -Generating bash completions from a cobra command is incredibly easy. An actual program which does so for the kubernetes kubectl binary is as follows: - -```go -package main - -import ( - "io/ioutil" - "os" - - "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd" -) - -func main() { - kubectl := cmd.NewFactory(nil).NewKubectlCommand(os.Stdin, ioutil.Discard, ioutil.Discard) - kubectl.GenBashCompletionFile("out.sh") -} -``` - -`out.sh` will get you completions of subcommands and flags. Copy it to `/etc/bash_completion.d/` as described [here](https://debian-administration.org/article/316/An_introduction_to_bash_completion_part_1) and reset your terminal to use autocompletion. If you make additional annotations to your code, you can get even more intelligent and flexible behavior. - -## Creating your own custom functions - -Some more actual code that works in kubernetes: - -```bash -const ( - bash_completion_func = `__kubectl_parse_get() -{ - local kubectl_output out - if kubectl_output=$(kubectl get --no-headers "$1" 2>/dev/null); then - out=($(echo "${kubectl_output}" | awk '{print $1}')) - COMPREPLY=( $( compgen -W "${out[*]}" -- "$cur" ) ) - fi -} - -__kubectl_get_resource() -{ - if [[ ${#nouns[@]} -eq 0 ]]; then - return 1 - fi - __kubectl_parse_get ${nouns[${#nouns[@]} -1]} - if [[ $? -eq 0 ]]; then - return 0 - fi -} - -__custom_func() { - case ${last_command} in - kubectl_get | kubectl_describe | kubectl_delete | kubectl_stop) - __kubectl_get_resource - return - ;; - *) - ;; - esac -} -`) -``` - -And then I set that in my command definition: - -```go -cmds := &cobra.Command{ - Use: "kubectl", - Short: "kubectl controls the Kubernetes cluster manager", - Long: `kubectl controls the Kubernetes cluster manager. - -Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`, - Run: runHelp, - BashCompletionFunction: bash_completion_func, -} -``` - -The `BashCompletionFunction` option is really only valid/useful on the root command. Doing the above will cause `__custom_func()` to be called when the built in processor was unable to find a solution. In the case of kubernetes a valid command might look something like `kubectl get pod [mypod]`. If you type `kubectl get pod [tab][tab]` the `__customc_func()` will run because the cobra.Command only understood "kubectl" and "get." `__custom_func()` will see that the cobra.Command is "kubectl_get" and will thus call another helper `__kubectl_get_resource()`. `__kubectl_get_resource` will look at the 'nouns' collected. In our example the only noun will be `pod`. So it will call `__kubectl_parse_get pod`. `__kubectl_parse_get` will actually call out to kubernetes and get any pods. It will then set `COMPREPLY` to valid pods! - -## Have the completions code complete your 'nouns' - -In the above example "pod" was assumed to already be typed. But if you want `kubectl get [tab][tab]` to show a list of valid "nouns" you have to set them. Simplified code from `kubectl get` looks like: - -```go -validArgs []string = { "pod", "node", "service", "replicationcontroller" } - -cmd := &cobra.Command{ - Use: "get [(-o|--output=)json|yaml|template|...] (RESOURCE [NAME] | RESOURCE/NAME ...)", - Short: "Display one or many resources", - Long: get_long, - Example: get_example, - Run: func(cmd *cobra.Command, args []string) { - err := RunGet(f, out, cmd, args) - util.CheckErr(err) - }, - ValidArgs: validArgs, -} -``` - -Notice we put the "ValidArgs" on the "get" subcommand. Doing so will give results like - -```bash -# kubectl get [tab][tab] -node pod replicationcontroller service -``` - -## Plural form and shortcuts for nouns - -If your nouns have a number of aliases, you can define them alongside `ValidArgs` using `ArgAliases`: - -```go -argAliases []string = { "pods", "nodes", "services", "svc", "replicationcontrollers", "rc" } - -cmd := &cobra.Command{ - ... - ValidArgs: validArgs, - ArgAliases: argAliases -} -``` - -The aliases are not shown to the user on tab completion, but they are accepted as valid nouns by -the completion algorithm if entered manually, e.g. in: - -```bash -# kubectl get rc [tab][tab] -backend frontend database -``` - -Note that without declaring `rc` as an alias, the completion algorithm would show the list of nouns -in this example again instead of the replication controllers. - -## Mark flags as required - -Most of the time completions will only show subcommands. But if a flag is required to make a subcommand work, you probably want it to show up when the user types [tab][tab]. Marking a flag as 'Required' is incredibly easy. - -```go -cmd.MarkFlagRequired("pod") -cmd.MarkFlagRequired("container") -``` - -and you'll get something like - -```bash -# kubectl exec [tab][tab][tab] --c --container= -p --pod= -``` - -# Specify valid filename extensions for flags that take a filename - -In this example we use --filename= and expect to get a json or yaml file as the argument. To make this easier we annotate the --filename flag with valid filename extensions. - -```go - annotations := []string{"json", "yaml", "yml"} - annotation := make(map[string][]string) - annotation[cobra.BashCompFilenameExt] = annotations - - flag := &pflag.Flag{ - Name: "filename", - Shorthand: "f", - Usage: usage, - Value: value, - DefValue: value.String(), - Annotations: annotation, - } - cmd.Flags().AddFlag(flag) -``` - -Now when you run a command with this filename flag you'll get something like - -```bash -# kubectl create -f -test/ example/ rpmbuild/ -hello.yml test.json -``` - -So while there are many other files in the CWD it only shows me subdirs and those with valid extensions. - -# Specifiy custom flag completion - -Similar to the filename completion and filtering using cobra.BashCompFilenameExt, you can specifiy -a custom flag completion function with cobra.BashCompCustom: - -```go - annotation := make(map[string][]string) - annotation[cobra.BashCompFilenameExt] = []string{"__kubectl_get_namespaces"} - - flag := &pflag.Flag{ - Name: "namespace", - Usage: usage, - Annotations: annotation, - } - cmd.Flags().AddFlag(flag) -``` - -In addition add the `__handle_namespace_flag` implementation in the `BashCompletionFunction` -value, e.g.: - -```bash -__kubectl_get_namespaces() -{ - local template - template="{{ range .items }}{{ .metadata.name }} {{ end }}" - local kubectl_out - if kubectl_out=$(kubectl get -o template --template="${template}" namespace 2>/dev/null); then - COMPREPLY=( $( compgen -W "${kubectl_out}[*]" -- "$cur" ) ) - fi -} -``` diff --git a/vendor/github.com/spf13/pflag/.gitignore b/vendor/github.com/spf13/pflag/.gitignore deleted file mode 100644 index c3da290134..0000000000 --- a/vendor/github.com/spf13/pflag/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.idea/* - diff --git a/vendor/github.com/spf13/pflag/.travis.yml b/vendor/github.com/spf13/pflag/.travis.yml deleted file mode 100644 index f8a63b308b..0000000000 --- a/vendor/github.com/spf13/pflag/.travis.yml +++ /dev/null @@ -1,21 +0,0 @@ -sudo: false - -language: go - -go: - - 1.7.3 - - 1.8.1 - - tip - -matrix: - allow_failures: - - go: tip - -install: - - go get github.com/golang/lint/golint - - export PATH=$GOPATH/bin:$PATH - - go install ./... - -script: - - verify/all.sh -v - - go test ./... diff --git a/vendor/github.com/spf13/pflag/README.md b/vendor/github.com/spf13/pflag/README.md deleted file mode 100644 index b052414d12..0000000000 --- a/vendor/github.com/spf13/pflag/README.md +++ /dev/null @@ -1,296 +0,0 @@ -[![Build Status](https://travis-ci.org/spf13/pflag.svg?branch=master)](https://travis-ci.org/spf13/pflag) -[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/pflag)](https://goreportcard.com/report/github.com/spf13/pflag) -[![GoDoc](https://godoc.org/github.com/spf13/pflag?status.svg)](https://godoc.org/github.com/spf13/pflag) - -## Description - -pflag is a drop-in replacement for Go's flag package, implementing -POSIX/GNU-style --flags. - -pflag is compatible with the [GNU extensions to the POSIX recommendations -for command-line options][1]. For a more precise description, see the -"Command-line flag syntax" section below. - -[1]: http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html - -pflag is available under the same style of BSD license as the Go language, -which can be found in the LICENSE file. - -## Installation - -pflag is available using the standard `go get` command. - -Install by running: - - go get github.com/spf13/pflag - -Run tests by running: - - go test github.com/spf13/pflag - -## Usage - -pflag is a drop-in replacement of Go's native flag package. If you import -pflag under the name "flag" then all code should continue to function -with no changes. - -``` go -import flag "github.com/spf13/pflag" -``` - -There is one exception to this: if you directly instantiate the Flag struct -there is one more field "Shorthand" that you will need to set. -Most code never instantiates this struct directly, and instead uses -functions such as String(), BoolVar(), and Var(), and is therefore -unaffected. - -Define flags using flag.String(), Bool(), Int(), etc. - -This declares an integer flag, -flagname, stored in the pointer ip, with type *int. - -``` go -var ip *int = flag.Int("flagname", 1234, "help message for flagname") -``` - -If you like, you can bind the flag to a variable using the Var() functions. - -``` go -var flagvar int -func init() { - flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname") -} -``` - -Or you can create custom flags that satisfy the Value interface (with -pointer receivers) and couple them to flag parsing by - -``` go -flag.Var(&flagVal, "name", "help message for flagname") -``` - -For such flags, the default value is just the initial value of the variable. - -After all flags are defined, call - -``` go -flag.Parse() -``` - -to parse the command line into the defined flags. - -Flags may then be used directly. If you're using the flags themselves, -they are all pointers; if you bind to variables, they're values. - -``` go -fmt.Println("ip has value ", *ip) -fmt.Println("flagvar has value ", flagvar) -``` - -There are helpers function to get values later if you have the FlagSet but -it was difficult to keep up with all of the flag pointers in your code. -If you have a pflag.FlagSet with a flag called 'flagname' of type int you -can use GetInt() to get the int value. But notice that 'flagname' must exist -and it must be an int. GetString("flagname") will fail. - -``` go -i, err := flagset.GetInt("flagname") -``` - -After parsing, the arguments after the flag are available as the -slice flag.Args() or individually as flag.Arg(i). -The arguments are indexed from 0 through flag.NArg()-1. - -The pflag package also defines some new functions that are not in flag, -that give one-letter shorthands for flags. You can use these by appending -'P' to the name of any function that defines a flag. - -``` go -var ip = flag.IntP("flagname", "f", 1234, "help message") -var flagvar bool -func init() { - flag.BoolVarP(&flagvar, "boolname", "b", true, "help message") -} -flag.VarP(&flagVal, "varname", "v", "help message") -``` - -Shorthand letters can be used with single dashes on the command line. -Boolean shorthand flags can be combined with other shorthand flags. - -The default set of command-line flags is controlled by -top-level functions. The FlagSet type allows one to define -independent sets of flags, such as to implement subcommands -in a command-line interface. The methods of FlagSet are -analogous to the top-level functions for the command-line -flag set. - -## Setting no option default values for flags - -After you create a flag it is possible to set the pflag.NoOptDefVal for -the given flag. Doing this changes the meaning of the flag slightly. If -a flag has a NoOptDefVal and the flag is set on the command line without -an option the flag will be set to the NoOptDefVal. For example given: - -``` go -var ip = flag.IntP("flagname", "f", 1234, "help message") -flag.Lookup("flagname").NoOptDefVal = "4321" -``` - -Would result in something like - -| Parsed Arguments | Resulting Value | -| ------------- | ------------- | -| --flagname=1357 | ip=1357 | -| --flagname | ip=4321 | -| [nothing] | ip=1234 | - -## Command line flag syntax - -``` ---flag // boolean flags, or flags with no option default values ---flag x // only on flags without a default value ---flag=x -``` - -Unlike the flag package, a single dash before an option means something -different than a double dash. Single dashes signify a series of shorthand -letters for flags. All but the last shorthand letter must be boolean flags -or a flag with a default value - -``` -// boolean or flags where the 'no option default value' is set --f --f=true --abc -but --b true is INVALID - -// non-boolean and flags without a 'no option default value' --n 1234 --n=1234 --n1234 - -// mixed --abcs "hello" --absd="hello" --abcs1234 -``` - -Flag parsing stops after the terminator "--". Unlike the flag package, -flags can be interspersed with arguments anywhere on the command line -before this terminator. - -Integer flags accept 1234, 0664, 0x1234 and may be negative. -Boolean flags (in their long form) accept 1, 0, t, f, true, false, -TRUE, FALSE, True, False. -Duration flags accept any input valid for time.ParseDuration. - -## Mutating or "Normalizing" Flag names - -It is possible to set a custom flag name 'normalization function.' It allows flag names to be mutated both when created in the code and when used on the command line to some 'normalized' form. The 'normalized' form is used for comparison. Two examples of using the custom normalization func follow. - -**Example #1**: You want -, _, and . in flags to compare the same. aka --my-flag == --my_flag == --my.flag - -``` go -func wordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName { - from := []string{"-", "_"} - to := "." - for _, sep := range from { - name = strings.Replace(name, sep, to, -1) - } - return pflag.NormalizedName(name) -} - -myFlagSet.SetNormalizeFunc(wordSepNormalizeFunc) -``` - -**Example #2**: You want to alias two flags. aka --old-flag-name == --new-flag-name - -``` go -func aliasNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName { - switch name { - case "old-flag-name": - name = "new-flag-name" - break - } - return pflag.NormalizedName(name) -} - -myFlagSet.SetNormalizeFunc(aliasNormalizeFunc) -``` - -## Deprecating a flag or its shorthand -It is possible to deprecate a flag, or just its shorthand. Deprecating a flag/shorthand hides it from help text and prints a usage message when the deprecated flag/shorthand is used. - -**Example #1**: You want to deprecate a flag named "badflag" as well as inform the users what flag they should use instead. -```go -// deprecate a flag by specifying its name and a usage message -flags.MarkDeprecated("badflag", "please use --good-flag instead") -``` -This hides "badflag" from help text, and prints `Flag --badflag has been deprecated, please use --good-flag instead` when "badflag" is used. - -**Example #2**: You want to keep a flag name "noshorthandflag" but deprecate its shortname "n". -```go -// deprecate a flag shorthand by specifying its flag name and a usage message -flags.MarkShorthandDeprecated("noshorthandflag", "please use --noshorthandflag only") -``` -This hides the shortname "n" from help text, and prints `Flag shorthand -n has been deprecated, please use --noshorthandflag only` when the shorthand "n" is used. - -Note that usage message is essential here, and it should not be empty. - -## Hidden flags -It is possible to mark a flag as hidden, meaning it will still function as normal, however will not show up in usage/help text. - -**Example**: You have a flag named "secretFlag" that you need for internal use only and don't want it showing up in help text, or for its usage text to be available. -```go -// hide a flag by specifying its name -flags.MarkHidden("secretFlag") -``` - -## Disable sorting of flags -`pflag` allows you to disable sorting of flags for help and usage message. - -**Example**: -```go -flags.BoolP("verbose", "v", false, "verbose output") -flags.String("coolflag", "yeaah", "it's really cool flag") -flags.Int("usefulflag", 777, "sometimes it's very useful") -flags.SortFlags = false -flags.PrintDefaults() -``` -**Output**: -``` - -v, --verbose verbose output - --coolflag string it's really cool flag (default "yeaah") - --usefulflag int sometimes it's very useful (default 777) -``` - - -## Supporting Go flags when using pflag -In order to support flags defined using Go's `flag` package, they must be added to the `pflag` flagset. This is usually necessary -to support flags defined by third-party dependencies (e.g. `golang/glog`). - -**Example**: You want to add the Go flags to the `CommandLine` flagset -```go -import ( - goflag "flag" - flag "github.com/spf13/pflag" -) - -var ip *int = flag.Int("flagname", 1234, "help message for flagname") - -func main() { - flag.CommandLine.AddGoFlagSet(goflag.CommandLine) - flag.Parse() -} -``` - -## More info - -You can see the full reference documentation of the pflag package -[at godoc.org][3], or through go's standard documentation system by -running `godoc -http=:6060` and browsing to -[http://localhost:6060/pkg/github.com/spf13/pflag][2] after -installation. - -[2]: http://localhost:6060/pkg/github.com/spf13/pflag -[3]: http://godoc.org/github.com/spf13/pflag diff --git a/vendor/golang.org/x/net/http2/.gitignore b/vendor/golang.org/x/net/http2/.gitignore deleted file mode 100644 index 190f12234a..0000000000 --- a/vendor/golang.org/x/net/http2/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*~ -h2i/h2i diff --git a/vendor/golang.org/x/net/http2/Dockerfile b/vendor/golang.org/x/net/http2/Dockerfile deleted file mode 100644 index 53fc525797..0000000000 --- a/vendor/golang.org/x/net/http2/Dockerfile +++ /dev/null @@ -1,51 +0,0 @@ -# -# This Dockerfile builds a recent curl with HTTP/2 client support, using -# a recent nghttp2 build. -# -# See the Makefile for how to tag it. If Docker and that image is found, the -# Go tests use this curl binary for integration tests. -# - -FROM ubuntu:trusty - -RUN apt-get update && \ - apt-get upgrade -y && \ - apt-get install -y git-core build-essential wget - -RUN apt-get install -y --no-install-recommends \ - autotools-dev libtool pkg-config zlib1g-dev \ - libcunit1-dev libssl-dev libxml2-dev libevent-dev \ - automake autoconf - -# The list of packages nghttp2 recommends for h2load: -RUN apt-get install -y --no-install-recommends make binutils \ - autoconf automake autotools-dev \ - libtool pkg-config zlib1g-dev libcunit1-dev libssl-dev libxml2-dev \ - libev-dev libevent-dev libjansson-dev libjemalloc-dev \ - cython python3.4-dev python-setuptools - -# Note: setting NGHTTP2_VER before the git clone, so an old git clone isn't cached: -ENV NGHTTP2_VER 895da9a -RUN cd /root && git clone https://github.com/tatsuhiro-t/nghttp2.git - -WORKDIR /root/nghttp2 -RUN git reset --hard $NGHTTP2_VER -RUN autoreconf -i -RUN automake -RUN autoconf -RUN ./configure -RUN make -RUN make install - -WORKDIR /root -RUN wget http://curl.haxx.se/download/curl-7.45.0.tar.gz -RUN tar -zxvf curl-7.45.0.tar.gz -WORKDIR /root/curl-7.45.0 -RUN ./configure --with-ssl --with-nghttp2=/usr/local -RUN make -RUN make install -RUN ldconfig - -CMD ["-h"] -ENTRYPOINT ["/usr/local/bin/curl"] - diff --git a/vendor/golang.org/x/net/http2/Makefile b/vendor/golang.org/x/net/http2/Makefile deleted file mode 100644 index 55fd826f77..0000000000 --- a/vendor/golang.org/x/net/http2/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -curlimage: - docker build -t gohttp2/curl . - diff --git a/vendor/golang.org/x/net/http2/README b/vendor/golang.org/x/net/http2/README deleted file mode 100644 index 360d5aa379..0000000000 --- a/vendor/golang.org/x/net/http2/README +++ /dev/null @@ -1,20 +0,0 @@ -This is a work-in-progress HTTP/2 implementation for Go. - -It will eventually live in the Go standard library and won't require -any changes to your code to use. It will just be automatic. - -Status: - -* The server support is pretty good. A few things are missing - but are being worked on. -* The client work has just started but shares a lot of code - is coming along much quicker. - -Docs are at https://godoc.org/golang.org/x/net/http2 - -Demo test server at https://http2.golang.org/ - -Help & bug reports welcome! - -Contributing: https://golang.org/doc/contribute.html -Bugs: https://golang.org/issue/new?title=x/net/http2:+ diff --git a/vendor/golang.org/x/oauth2/.travis.yml b/vendor/golang.org/x/oauth2/.travis.yml deleted file mode 100644 index fa139db225..0000000000 --- a/vendor/golang.org/x/oauth2/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: go - -go: - - tip - -install: - - export GOPATH="$HOME/gopath" - - mkdir -p "$GOPATH/src/golang.org/x" - - mv "$TRAVIS_BUILD_DIR" "$GOPATH/src/golang.org/x/oauth2" - - go get -v -t -d golang.org/x/oauth2/... - -script: - - go test -v golang.org/x/oauth2/... diff --git a/vendor/golang.org/x/oauth2/CONTRIBUTING.md b/vendor/golang.org/x/oauth2/CONTRIBUTING.md deleted file mode 100644 index dfbed62cf5..0000000000 --- a/vendor/golang.org/x/oauth2/CONTRIBUTING.md +++ /dev/null @@ -1,26 +0,0 @@ -# Contributing to Go - -Go is an open source project. - -It is the work of hundreds of contributors. We appreciate your help! - -## Filing issues - -When [filing an issue](https://github.com/golang/oauth2/issues), make sure to answer these five questions: - -1. What version of Go are you using (`go version`)? -2. What operating system and processor architecture are you using? -3. What did you do? -4. What did you expect to see? -5. What did you see instead? - -General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. -The gophers there will answer or ask you to file an issue if you've tripped over a bug. - -## Contributing code - -Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) -before sending patches. - -Unless otherwise noted, the Go source files are distributed under -the BSD-style license found in the LICENSE file. diff --git a/vendor/golang.org/x/oauth2/README.md b/vendor/golang.org/x/oauth2/README.md deleted file mode 100644 index eb8dcee179..0000000000 --- a/vendor/golang.org/x/oauth2/README.md +++ /dev/null @@ -1,77 +0,0 @@ -# OAuth2 for Go - -[![Build Status](https://travis-ci.org/golang/oauth2.svg?branch=master)](https://travis-ci.org/golang/oauth2) -[![GoDoc](https://godoc.org/golang.org/x/oauth2?status.svg)](https://godoc.org/golang.org/x/oauth2) - -oauth2 package contains a client implementation for OAuth 2.0 spec. - -## Installation - -~~~~ -go get golang.org/x/oauth2 -~~~~ - -Or you can manually git clone the repository to -`$(go env GOPATH)/src/golang.org/x/oauth2`. - -See godoc for further documentation and examples. - -* [godoc.org/golang.org/x/oauth2](http://godoc.org/golang.org/x/oauth2) -* [godoc.org/golang.org/x/oauth2/google](http://godoc.org/golang.org/x/oauth2/google) - - -## App Engine - -In change 96e89be (March 2015), we removed the `oauth2.Context2` type in favor -of the [`context.Context`](https://golang.org/x/net/context#Context) type from -the `golang.org/x/net/context` package - -This means it's no longer possible to use the "Classic App Engine" -`appengine.Context` type with the `oauth2` package. (You're using -Classic App Engine if you import the package `"appengine"`.) - -To work around this, you may use the new `"google.golang.org/appengine"` -package. This package has almost the same API as the `"appengine"` package, -but it can be fetched with `go get` and used on "Managed VMs" and well as -Classic App Engine. - -See the [new `appengine` package's readme](https://github.com/golang/appengine#updating-a-go-app-engine-app) -for information on updating your app. - -If you don't want to update your entire app to use the new App Engine packages, -you may use both sets of packages in parallel, using only the new packages -with the `oauth2` package. - -```go -import ( - "golang.org/x/net/context" - "golang.org/x/oauth2" - "golang.org/x/oauth2/google" - newappengine "google.golang.org/appengine" - newurlfetch "google.golang.org/appengine/urlfetch" - - "appengine" -) - -func handler(w http.ResponseWriter, r *http.Request) { - var c appengine.Context = appengine.NewContext(r) - c.Infof("Logging a message with the old package") - - var ctx context.Context = newappengine.NewContext(r) - client := &http.Client{ - Transport: &oauth2.Transport{ - Source: google.AppEngineTokenSource(ctx, "scope"), - Base: &newurlfetch.Transport{Context: ctx}, - }, - } - client.Get("...") -} -``` - -## Report Issues / Send Patches - -This repository uses Gerrit for code changes. To learn how to submit changes to -this repository, see https://golang.org/doc/contribute.html. - -The main issue tracker for the oauth2 repository is located at -https://github.com/golang/oauth2/issues. diff --git a/vendor/golang.org/x/sys/unix/.gitignore b/vendor/golang.org/x/sys/unix/.gitignore deleted file mode 100644 index e482715909..0000000000 --- a/vendor/golang.org/x/sys/unix/.gitignore +++ /dev/null @@ -1 +0,0 @@ -_obj/ diff --git a/vendor/golang.org/x/sys/unix/README.md b/vendor/golang.org/x/sys/unix/README.md deleted file mode 100644 index bc6f6031f1..0000000000 --- a/vendor/golang.org/x/sys/unix/README.md +++ /dev/null @@ -1,173 +0,0 @@ -# Building `sys/unix` - -The sys/unix package provides access to the raw system call interface of the -underlying operating system. See: https://godoc.org/golang.org/x/sys/unix - -Porting Go to a new architecture/OS combination or adding syscalls, types, or -constants to an existing architecture/OS pair requires some manual effort; -however, there are tools that automate much of the process. - -## Build Systems - -There are currently two ways we generate the necessary files. We are currently -migrating the build system to use containers so the builds are reproducible. -This is being done on an OS-by-OS basis. Please update this documentation as -components of the build system change. - -### Old Build System (currently for `GOOS != "Linux" || GOARCH == "sparc64"`) - -The old build system generates the Go files based on the C header files -present on your system. This means that files -for a given GOOS/GOARCH pair must be generated on a system with that OS and -architecture. This also means that the generated code can differ from system -to system, based on differences in the header files. - -To avoid this, if you are using the old build system, only generate the Go -files on an installation with unmodified header files. It is also important to -keep track of which version of the OS the files were generated from (ex. -Darwin 14 vs Darwin 15). This makes it easier to track the progress of changes -and have each OS upgrade correspond to a single change. - -To build the files for your current OS and architecture, make sure GOOS and -GOARCH are set correctly and run `mkall.sh`. This will generate the files for -your specific system. Running `mkall.sh -n` shows the commands that will be run. - -Requirements: bash, perl, go - -### New Build System (currently for `GOOS == "Linux" && GOARCH != "sparc64"`) - -The new build system uses a Docker container to generate the go files directly -from source checkouts of the kernel and various system libraries. This means -that on any platform that supports Docker, all the files using the new build -system can be generated at once, and generated files will not change based on -what the person running the scripts has installed on their computer. - -The OS specific files for the new build system are located in the `${GOOS}` -directory, and the build is coordinated by the `${GOOS}/mkall.go` program. When -the kernel or system library updates, modify the Dockerfile at -`${GOOS}/Dockerfile` to checkout the new release of the source. - -To build all the files under the new build system, you must be on an amd64/Linux -system and have your GOOS and GOARCH set accordingly. Running `mkall.sh` will -then generate all of the files for all of the GOOS/GOARCH pairs in the new build -system. Running `mkall.sh -n` shows the commands that will be run. - -Requirements: bash, perl, go, docker - -## Component files - -This section describes the various files used in the code generation process. -It also contains instructions on how to modify these files to add a new -architecture/OS or to add additional syscalls, types, or constants. Note that -if you are using the new build system, the scripts cannot be called normally. -They must be called from within the docker container. - -### asm files - -The hand-written assembly file at `asm_${GOOS}_${GOARCH}.s` implements system -call dispatch. There are three entry points: -``` - func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) - func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) - func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) -``` -The first and second are the standard ones; they differ only in how many -arguments can be passed to the kernel. The third is for low-level use by the -ForkExec wrapper. Unlike the first two, it does not call into the scheduler to -let it know that a system call is running. - -When porting Go to an new architecture/OS, this file must be implemented for -each GOOS/GOARCH pair. - -### mksysnum - -Mksysnum is a script located at `${GOOS}/mksysnum.pl` (or `mksysnum_${GOOS}.pl` -for the old system). This script takes in a list of header files containing the -syscall number declarations and parses them to produce the corresponding list of -Go numeric constants. See `zsysnum_${GOOS}_${GOARCH}.go` for the generated -constants. - -Adding new syscall numbers is mostly done by running the build on a sufficiently -new installation of the target OS (or updating the source checkouts for the -new build system). However, depending on the OS, you make need to update the -parsing in mksysnum. - -### mksyscall.pl - -The `syscall.go`, `syscall_${GOOS}.go`, `syscall_${GOOS}_${GOARCH}.go` are -hand-written Go files which implement system calls (for unix, the specific OS, -or the specific OS/Architecture pair respectively) that need special handling -and list `//sys` comments giving prototypes for ones that can be generated. - -The mksyscall.pl script takes the `//sys` and `//sysnb` comments and converts -them into syscalls. This requires the name of the prototype in the comment to -match a syscall number in the `zsysnum_${GOOS}_${GOARCH}.go` file. The function -prototype can be exported (capitalized) or not. - -Adding a new syscall often just requires adding a new `//sys` function prototype -with the desired arguments and a capitalized name so it is exported. However, if -you want the interface to the syscall to be different, often one will make an -unexported `//sys` prototype, an then write a custom wrapper in -`syscall_${GOOS}.go`. - -### types files - -For each OS, there is a hand-written Go file at `${GOOS}/types.go` (or -`types_${GOOS}.go` on the old system). This file includes standard C headers and -creates Go type aliases to the corresponding C types. The file is then fed -through godef to get the Go compatible definitions. Finally, the generated code -is fed though mkpost.go to format the code correctly and remove any hidden or -private identifiers. This cleaned-up code is written to -`ztypes_${GOOS}_${GOARCH}.go`. - -The hardest part about preparing this file is figuring out which headers to -include and which symbols need to be `#define`d to get the actual data -structures that pass through to the kernel system calls. Some C libraries -preset alternate versions for binary compatibility and translate them on the -way in and out of system calls, but there is almost always a `#define` that can -get the real ones. -See `types_darwin.go` and `linux/types.go` for examples. - -To add a new type, add in the necessary include statement at the top of the -file (if it is not already there) and add in a type alias line. Note that if -your type is significantly different on different architectures, you may need -some `#if/#elif` macros in your include statements. - -### mkerrors.sh - -This script is used to generate the system's various constants. This doesn't -just include the error numbers and error strings, but also the signal numbers -an a wide variety of miscellaneous constants. The constants come from the list -of include files in the `includes_${uname}` variable. A regex then picks out -the desired `#define` statements, and generates the corresponding Go constants. -The error numbers and strings are generated from `#include `, and the -signal numbers and strings are generated from `#include `. All of -these constants are written to `zerrors_${GOOS}_${GOARCH}.go` via a C program, -`_errors.c`, which prints out all the constants. - -To add a constant, add the header that includes it to the appropriate variable. -Then, edit the regex (if necessary) to match the desired constant. Avoid making -the regex too broad to avoid matching unintended constants. - - -## Generated files - -### `zerror_${GOOS}_${GOARCH}.go` - -A file containing all of the system's generated error numbers, error strings, -signal numbers, and constants. Generated by `mkerrors.sh` (see above). - -### `zsyscall_${GOOS}_${GOARCH}.go` - -A file containing all the generated syscalls for a specific GOOS and GOARCH. -Generated by `mksyscall.pl` (see above). - -### `zsysnum_${GOOS}_${GOARCH}.go` - -A list of numeric constants for all the syscall number of the specific GOOS -and GOARCH. Generated by mksysnum (see above). - -### `ztypes_${GOOS}_${GOARCH}.go` - -A file containing Go types for passing into (or returning from) syscalls. -Generated by godefs and the types file (see above). diff --git a/vendor/golang.org/x/sys/unix/mkall.sh b/vendor/golang.org/x/sys/unix/mkall.sh deleted file mode 100755 index 00b7ce7ac1..0000000000 --- a/vendor/golang.org/x/sys/unix/mkall.sh +++ /dev/null @@ -1,194 +0,0 @@ -#!/usr/bin/env bash -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -# This script runs or (given -n) prints suggested commands to generate files for -# the Architecture/OS specified by the GOARCH and GOOS environment variables. -# See README.md for more information about how the build system works. - -GOOSARCH="${GOOS}_${GOARCH}" - -# defaults -mksyscall="./mksyscall.pl" -mkerrors="./mkerrors.sh" -zerrors="zerrors_$GOOSARCH.go" -mksysctl="" -zsysctl="zsysctl_$GOOSARCH.go" -mksysnum= -mktypes= -run="sh" -cmd="" - -case "$1" in --syscalls) - for i in zsyscall*go - do - # Run the command line that appears in the first line - # of the generated file to regenerate it. - sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i - rm _$i - done - exit 0 - ;; --n) - run="cat" - cmd="echo" - shift -esac - -case "$#" in -0) - ;; -*) - echo 'usage: mkall.sh [-n]' 1>&2 - exit 2 -esac - -if [[ "$GOOS" = "linux" ]] && [[ "$GOARCH" != "sparc64" ]]; then - # Use then new build system - # Files generated through docker (use $cmd so you can Ctl-C the build or run) - $cmd docker build --tag generate:$GOOS $GOOS - $cmd docker run --interactive --tty --volume $(dirname "$(readlink -f "$0")"):/build generate:$GOOS - exit -fi - -GOOSARCH_in=syscall_$GOOSARCH.go -case "$GOOSARCH" in -_* | *_ | _) - echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2 - exit 1 - ;; -darwin_386) - mkerrors="$mkerrors -m32" - mksyscall="./mksyscall.pl -l32" - mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -darwin_amd64) - mkerrors="$mkerrors -m64" - mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -darwin_arm) - mkerrors="$mkerrors" - mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -darwin_arm64) - mkerrors="$mkerrors -m64" - mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -dragonfly_386) - mkerrors="$mkerrors -m32" - mksyscall="./mksyscall.pl -l32 -dragonfly" - mksysnum="curl -s 'http://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master' | ./mksysnum_dragonfly.pl" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -dragonfly_amd64) - mkerrors="$mkerrors -m64" - mksyscall="./mksyscall.pl -dragonfly" - mksysnum="curl -s 'http://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master' | ./mksysnum_dragonfly.pl" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -freebsd_386) - mkerrors="$mkerrors -m32" - mksyscall="./mksyscall.pl -l32" - mksysnum="curl -s 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -freebsd_amd64) - mkerrors="$mkerrors -m64" - mksysnum="curl -s 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -freebsd_arm) - mkerrors="$mkerrors" - mksyscall="./mksyscall.pl -l32 -arm" - mksysnum="curl -s 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master' | ./mksysnum_freebsd.pl" - # Let the type of C char be signed for making the bare syscall - # API consistent across platforms. - mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" - ;; -linux_sparc64) - GOOSARCH_in=syscall_linux_sparc64.go - unistd_h=/usr/include/sparc64-linux-gnu/asm/unistd.h - mkerrors="$mkerrors -m64" - mksysnum="./mksysnum_linux.pl $unistd_h" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -netbsd_386) - mkerrors="$mkerrors -m32" - mksyscall="./mksyscall.pl -l32 -netbsd" - mksysnum="curl -s 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_netbsd.pl" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -netbsd_amd64) - mkerrors="$mkerrors -m64" - mksyscall="./mksyscall.pl -netbsd" - mksysnum="curl -s 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_netbsd.pl" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -netbsd_arm) - mkerrors="$mkerrors" - mksyscall="./mksyscall.pl -l32 -netbsd -arm" - mksysnum="curl -s 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_netbsd.pl" - # Let the type of C char be signed for making the bare syscall - # API consistent across platforms. - mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" - ;; -openbsd_386) - mkerrors="$mkerrors -m32" - mksyscall="./mksyscall.pl -l32 -openbsd" - mksysctl="./mksysctl_openbsd.pl" - mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -openbsd_amd64) - mkerrors="$mkerrors -m64" - mksyscall="./mksyscall.pl -openbsd" - mksysctl="./mksysctl_openbsd.pl" - mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl" - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -openbsd_arm) - mkerrors="$mkerrors" - mksyscall="./mksyscall.pl -l32 -openbsd -arm" - mksysctl="./mksysctl_openbsd.pl" - mksysnum="curl -s 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master' | ./mksysnum_openbsd.pl" - # Let the type of C char be signed for making the bare syscall - # API consistent across platforms. - mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" - ;; -solaris_amd64) - mksyscall="./mksyscall_solaris.pl" - mkerrors="$mkerrors -m64" - mksysnum= - mktypes="GOARCH=$GOARCH go tool cgo -godefs" - ;; -*) - echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2 - exit 1 - ;; -esac - -( - if [ -n "$mkerrors" ]; then echo "$mkerrors |gofmt >$zerrors"; fi - case "$GOOS" in - *) - syscall_goos="syscall_$GOOS.go" - case "$GOOS" in - darwin | dragonfly | freebsd | netbsd | openbsd) - syscall_goos="syscall_bsd.go $syscall_goos" - ;; - esac - if [ -n "$mksyscall" ]; then echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; fi - ;; - esac - if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi - if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi - if [ -n "$mktypes" ]; then - echo "$mktypes types_$GOOS.go | go run mkpost.go > ztypes_$GOOSARCH.go"; - fi -) | $run diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh deleted file mode 100755 index 9a799b2f5b..0000000000 --- a/vendor/golang.org/x/sys/unix/mkerrors.sh +++ /dev/null @@ -1,569 +0,0 @@ -#!/usr/bin/env bash -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -# Generate Go code listing errors and other #defined constant -# values (ENAMETOOLONG etc.), by asking the preprocessor -# about the definitions. - -unset LANG -export LC_ALL=C -export LC_CTYPE=C - -if test -z "$GOARCH" -o -z "$GOOS"; then - echo 1>&2 "GOARCH or GOOS not defined in environment" - exit 1 -fi - -# Check that we are using the new build system if we should -if [[ "$GOOS" = "linux" ]] && [[ "$GOARCH" != "sparc64" ]]; then - if [[ "$GOLANG_SYS_BUILD" != "docker" ]]; then - echo 1>&2 "In the new build system, mkerrors should not be called directly." - echo 1>&2 "See README.md" - exit 1 - fi -fi - -CC=${CC:-cc} - -if [[ "$GOOS" = "solaris" ]]; then - # Assumes GNU versions of utilities in PATH. - export PATH=/usr/gnu/bin:$PATH -fi - -uname=$(uname) - -includes_Darwin=' -#define _DARWIN_C_SOURCE -#define KERNEL -#define _DARWIN_USE_64_BIT_INODE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -' - -includes_DragonFly=' -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -' - -includes_FreeBSD=' -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if __FreeBSD__ >= 10 -#define IFT_CARP 0xf8 // IFT_CARP is deprecated in FreeBSD 10 -#undef SIOCAIFADDR -#define SIOCAIFADDR _IOW(105, 26, struct oifaliasreq) // ifaliasreq contains if_data -#undef SIOCSIFPHYADDR -#define SIOCSIFPHYADDR _IOW(105, 70, struct oifaliasreq) // ifaliasreq contains if_data -#endif -' - -includes_Linux=' -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE -#ifndef __LP64__ -#define _FILE_OFFSET_BITS 64 -#endif -#define _GNU_SOURCE - -// is broken on powerpc64, as it fails to include definitions of -// these structures. We just include them copied from . -#if defined(__powerpc__) -struct sgttyb { - char sg_ispeed; - char sg_ospeed; - char sg_erase; - char sg_kill; - short sg_flags; -}; - -struct tchars { - char t_intrc; - char t_quitc; - char t_startc; - char t_stopc; - char t_eofc; - char t_brkc; -}; - -struct ltchars { - char t_suspc; - char t_dsuspc; - char t_rprntc; - char t_flushc; - char t_werasc; - char t_lnextc; -}; -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef MSG_FASTOPEN -#define MSG_FASTOPEN 0x20000000 -#endif - -#ifndef PTRACE_GETREGS -#define PTRACE_GETREGS 0xc -#endif - -#ifndef PTRACE_SETREGS -#define PTRACE_SETREGS 0xd -#endif - -#ifndef SOL_NETLINK -#define SOL_NETLINK 270 -#endif - -#ifdef SOL_BLUETOOTH -// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h -// but it is already in bluetooth_linux.go -#undef SOL_BLUETOOTH -#endif - -// Certain constants are missing from the fs/crypto UAPI -#define FS_KEY_DESC_PREFIX "fscrypt:" -#define FS_KEY_DESC_PREFIX_SIZE 8 -#define FS_MAX_KEY_SIZE 64 -' - -includes_NetBSD=' -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Needed since refers to it... -#define schedppq 1 -' - -includes_OpenBSD=' -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// We keep some constants not supported in OpenBSD 5.5 and beyond for -// the promise of compatibility. -#define EMUL_ENABLED 0x1 -#define EMUL_NATIVE 0x2 -#define IPV6_FAITH 0x1d -#define IPV6_OPTIONS 0x1 -#define IPV6_RTHDR_STRICT 0x1 -#define IPV6_SOCKOPT_RESERVED1 0x3 -#define SIOCGIFGENERIC 0xc020693a -#define SIOCSIFGENERIC 0x80206939 -#define WALTSIG 0x4 -' - -includes_SunOS=' -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -' - - -includes=' -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -' -ccflags="$@" - -# Write go tool cgo -godefs input. -( - echo package unix - echo - echo '/*' - indirect="includes_$(uname)" - echo "${!indirect} $includes" - echo '*/' - echo 'import "C"' - echo 'import "syscall"' - echo - echo 'const (' - - # The gcc command line prints all the #defines - # it encounters while processing the input - echo "${!indirect} $includes" | $CC -x c - -E -dM $ccflags | - awk ' - $1 != "#define" || $2 ~ /\(/ || $3 == "" {next} - - $2 ~ /^E([ABCD]X|[BIS]P|[SD]I|S|FL)$/ {next} # 386 registers - $2 ~ /^(SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))/ {next} - $2 ~ /^(SCM_SRCRT)$/ {next} - $2 ~ /^(MAP_FAILED)$/ {next} - $2 ~ /^ELF_.*$/ {next}# contains ELF_ARCH, etc. - - $2 ~ /^EXTATTR_NAMESPACE_NAMES/ || - $2 ~ /^EXTATTR_NAMESPACE_[A-Z]+_STRING/ {next} - - $2 !~ /^ETH_/ && - $2 !~ /^EPROC_/ && - $2 !~ /^EQUIV_/ && - $2 !~ /^EXPR_/ && - $2 ~ /^E[A-Z0-9_]+$/ || - $2 ~ /^B[0-9_]+$/ || - $2 ~ /^(OLD|NEW)DEV$/ || - $2 == "BOTHER" || - $2 ~ /^CI?BAUD(EX)?$/ || - $2 == "IBSHIFT" || - $2 ~ /^V[A-Z0-9]+$/ || - $2 ~ /^CS[A-Z0-9]/ || - $2 ~ /^I(SIG|CANON|CRNL|UCLC|EXTEN|MAXBEL|STRIP|UTF8)$/ || - $2 ~ /^IGN/ || - $2 ~ /^IX(ON|ANY|OFF)$/ || - $2 ~ /^IN(LCR|PCK)$/ || - $2 ~ /(^FLU?SH)|(FLU?SH$)/ || - $2 ~ /^C(LOCAL|READ|MSPAR|RTSCTS)$/ || - $2 == "BRKINT" || - $2 == "HUPCL" || - $2 == "PENDIN" || - $2 == "TOSTOP" || - $2 == "XCASE" || - $2 == "ALTWERASE" || - $2 == "NOKERNINFO" || - $2 ~ /^PAR/ || - $2 ~ /^SIG[^_]/ || - $2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ || - $2 ~ /^(NL|CR|TAB|BS|VT|FF)DLY$/ || - $2 ~ /^(NL|CR|TAB|BS|VT|FF)[0-9]$/ || - $2 ~ /^O?XTABS$/ || - $2 ~ /^TC[IO](ON|OFF)$/ || - $2 ~ /^IN_/ || - $2 ~ /^LOCK_(SH|EX|NB|UN)$/ || - $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ || - $2 ~ /^FALLOC_/ || - $2 == "ICMPV6_FILTER" || - $2 == "SOMAXCONN" || - $2 == "NAME_MAX" || - $2 == "IFNAMSIZ" || - $2 ~ /^CTL_(MAXNAME|NET|QUERY)$/ || - $2 ~ /^SYSCTL_VERS/ || - $2 ~ /^(MS|MNT|UMOUNT)_/ || - $2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ || - $2 ~ /^(O|F|E?FD|NAME|S|PTRACE|PT)_/ || - $2 ~ /^LINUX_REBOOT_CMD_/ || - $2 ~ /^LINUX_REBOOT_MAGIC[12]$/ || - $2 !~ "NLA_TYPE_MASK" && - $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/ || - $2 ~ /^SIOC/ || - $2 ~ /^TIOC/ || - $2 ~ /^TCGET/ || - $2 ~ /^TCSET/ || - $2 ~ /^TC(FLSH|SBRKP?|XONC)$/ || - $2 !~ "RTF_BITS" && - $2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ || - $2 ~ /^BIOC/ || - $2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ || - $2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ || - $2 ~ /^PRIO_(PROCESS|PGRP|USER)/ || - $2 ~ /^CLONE_[A-Z_]+/ || - $2 !~ /^(BPF_TIMEVAL)$/ && - $2 ~ /^(BPF|DLT)_/ || - $2 ~ /^CLOCK_/ || - $2 ~ /^CAN_/ || - $2 ~ /^CAP_/ || - $2 ~ /^ALG_/ || - $2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE|IOC_(GET|SET)_ENCRYPTION)/ || - $2 ~ /^GRND_/ || - $2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ || - $2 ~ /^KEYCTL_/ || - $2 ~ /^PERF_EVENT_IOC_/ || - $2 ~ /^SECCOMP_MODE_/ || - $2 ~ /^SPLICE_/ || - $2 ~ /^(VM|VMADDR)_/ || - $2 ~ /^(TASKSTATS|TS)_/ || - $2 ~ /^GENL_/ || - $2 ~ /^UTIME_/ || - $2 ~ /^XATTR_(CREATE|REPLACE)/ || - $2 ~ /^WDIOC_/ || - $2 !~ "WMESGLEN" && - $2 ~ /^W[A-Z0-9]+$/ || - $2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)} - $2 ~ /^__WCOREFLAG$/ {next} - $2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)} - - {next} - ' | sort - - echo ')' -) >_const.go - -# Pull out the error names for later. -errors=$( - echo '#include ' | $CC -x c - -E -dM $ccflags | - awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print $2 }' | - sort -) - -# Pull out the signal names for later. -signals=$( - echo '#include ' | $CC -x c - -E -dM $ccflags | - awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' | - egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' | - sort -) - -# Again, writing regexps to a file. -echo '#include ' | $CC -x c - -E -dM $ccflags | - awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print "^\t" $2 "[ \t]*=" }' | - sort >_error.grep -echo '#include ' | $CC -x c - -E -dM $ccflags | - awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' | - egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' | - sort >_signal.grep - -echo '// mkerrors.sh' "$@" -echo '// Code generated by the command above; see README.md. DO NOT EDIT.' -echo -echo "// +build ${GOARCH},${GOOS}" -echo -go tool cgo -godefs -- "$@" _const.go >_error.out -cat _error.out | grep -vf _error.grep | grep -vf _signal.grep -echo -echo '// Errors' -echo 'const (' -cat _error.out | grep -f _error.grep | sed 's/=\(.*\)/= syscall.Errno(\1)/' -echo ')' - -echo -echo '// Signals' -echo 'const (' -cat _error.out | grep -f _signal.grep | sed 's/=\(.*\)/= syscall.Signal(\1)/' -echo ')' - -# Run C program to print error and syscall strings. -( - echo -E " -#include -#include -#include -#include -#include -#include - -#define nelem(x) (sizeof(x)/sizeof((x)[0])) - -enum { A = 'A', Z = 'Z', a = 'a', z = 'z' }; // avoid need for single quotes below - -int errors[] = { -" - for i in $errors - do - echo -E ' '$i, - done - - echo -E " -}; - -int signals[] = { -" - for i in $signals - do - echo -E ' '$i, - done - - # Use -E because on some systems bash builtin interprets \n itself. - echo -E ' -}; - -static int -intcmp(const void *a, const void *b) -{ - return *(int*)a - *(int*)b; -} - -int -main(void) -{ - int i, e; - char buf[1024], *p; - - printf("\n\n// Error table\n"); - printf("var errors = [...]string {\n"); - qsort(errors, nelem(errors), sizeof errors[0], intcmp); - for(i=0; i 0 && errors[i-1] == e) - continue; - strcpy(buf, strerror(e)); - // lowercase first letter: Bad -> bad, but STREAM -> STREAM. - if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z) - buf[0] += a - A; - printf("\t%d: \"%s\",\n", e, buf); - } - printf("}\n\n"); - - printf("\n\n// Signal table\n"); - printf("var signals = [...]string {\n"); - qsort(signals, nelem(signals), sizeof signals[0], intcmp); - for(i=0; i 0 && signals[i-1] == e) - continue; - strcpy(buf, strsignal(e)); - // lowercase first letter: Bad -> bad, but STREAM -> STREAM. - if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z) - buf[0] += a - A; - // cut trailing : number. - p = strrchr(buf, ":"[0]); - if(p) - *p = '\0'; - printf("\t%d: \"%s\",\n", e, buf); - } - printf("}\n\n"); - - return 0; -} - -' -) >_errors.c - -$CC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.go _error.grep _signal.grep _error.out diff --git a/vendor/golang.org/x/sys/unix/mksyscall.pl b/vendor/golang.org/x/sys/unix/mksyscall.pl deleted file mode 100755 index fb929b4ce1..0000000000 --- a/vendor/golang.org/x/sys/unix/mksyscall.pl +++ /dev/null @@ -1,328 +0,0 @@ -#!/usr/bin/env perl -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -# This program reads a file containing function prototypes -# (like syscall_darwin.go) and generates system call bodies. -# The prototypes are marked by lines beginning with "//sys" -# and read like func declarations if //sys is replaced by func, but: -# * The parameter lists must give a name for each argument. -# This includes return parameters. -# * The parameter lists must give a type for each argument: -# the (x, y, z int) shorthand is not allowed. -# * If the return parameter is an error number, it must be named errno. - -# A line beginning with //sysnb is like //sys, except that the -# goroutine will not be suspended during the execution of the system -# call. This must only be used for system calls which can never -# block, as otherwise the system call could cause all goroutines to -# hang. - -use strict; - -my $cmdline = "mksyscall.pl " . join(' ', @ARGV); -my $errors = 0; -my $_32bit = ""; -my $plan9 = 0; -my $openbsd = 0; -my $netbsd = 0; -my $dragonfly = 0; -my $arm = 0; # 64-bit value should use (even, odd)-pair -my $tags = ""; # build tags - -if($ARGV[0] eq "-b32") { - $_32bit = "big-endian"; - shift; -} elsif($ARGV[0] eq "-l32") { - $_32bit = "little-endian"; - shift; -} -if($ARGV[0] eq "-plan9") { - $plan9 = 1; - shift; -} -if($ARGV[0] eq "-openbsd") { - $openbsd = 1; - shift; -} -if($ARGV[0] eq "-netbsd") { - $netbsd = 1; - shift; -} -if($ARGV[0] eq "-dragonfly") { - $dragonfly = 1; - shift; -} -if($ARGV[0] eq "-arm") { - $arm = 1; - shift; -} -if($ARGV[0] eq "-tags") { - shift; - $tags = $ARGV[0]; - shift; -} - -if($ARGV[0] =~ /^-/) { - print STDERR "usage: mksyscall.pl [-b32 | -l32] [-tags x,y] [file ...]\n"; - exit 1; -} - -# Check that we are using the new build system if we should -if($ENV{'GOOS'} eq "linux" && $ENV{'GOARCH'} ne "sparc64") { - if($ENV{'GOLANG_SYS_BUILD'} ne "docker") { - print STDERR "In the new build system, mksyscall should not be called directly.\n"; - print STDERR "See README.md\n"; - exit 1; - } -} - - -sub parseparamlist($) { - my ($list) = @_; - $list =~ s/^\s*//; - $list =~ s/\s*$//; - if($list eq "") { - return (); - } - return split(/\s*,\s*/, $list); -} - -sub parseparam($) { - my ($p) = @_; - if($p !~ /^(\S*) (\S*)$/) { - print STDERR "$ARGV:$.: malformed parameter: $p\n"; - $errors = 1; - return ("xx", "int"); - } - return ($1, $2); -} - -my $text = ""; -while(<>) { - chomp; - s/\s+/ /g; - s/^\s+//; - s/\s+$//; - my $nonblock = /^\/\/sysnb /; - next if !/^\/\/sys / && !$nonblock; - - # Line must be of the form - # func Open(path string, mode int, perm int) (fd int, errno error) - # Split into name, in params, out params. - if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*((?i)SYS_[A-Z0-9_]+))?$/) { - print STDERR "$ARGV:$.: malformed //sys declaration\n"; - $errors = 1; - next; - } - my ($func, $in, $out, $sysname) = ($2, $3, $4, $5); - - # Split argument lists on comma. - my @in = parseparamlist($in); - my @out = parseparamlist($out); - - # Try in vain to keep people from editing this file. - # The theory is that they jump into the middle of the file - # without reading the header. - $text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"; - - # Go function header. - my $out_decl = @out ? sprintf(" (%s)", join(', ', @out)) : ""; - $text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out_decl; - - # Check if err return available - my $errvar = ""; - foreach my $p (@out) { - my ($name, $type) = parseparam($p); - if($type eq "error") { - $errvar = $name; - last; - } - } - - # Prepare arguments to Syscall. - my @args = (); - my $n = 0; - foreach my $p (@in) { - my ($name, $type) = parseparam($p); - if($type =~ /^\*/) { - push @args, "uintptr(unsafe.Pointer($name))"; - } elsif($type eq "string" && $errvar ne "") { - $text .= "\tvar _p$n *byte\n"; - $text .= "\t_p$n, $errvar = BytePtrFromString($name)\n"; - $text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n"; - push @args, "uintptr(unsafe.Pointer(_p$n))"; - $n++; - } elsif($type eq "string") { - print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n"; - $text .= "\tvar _p$n *byte\n"; - $text .= "\t_p$n, _ = BytePtrFromString($name)\n"; - push @args, "uintptr(unsafe.Pointer(_p$n))"; - $n++; - } elsif($type =~ /^\[\](.*)/) { - # Convert slice into pointer, length. - # Have to be careful not to take address of &a[0] if len == 0: - # pass dummy pointer in that case. - # Used to pass nil, but some OSes or simulators reject write(fd, nil, 0). - $text .= "\tvar _p$n unsafe.Pointer\n"; - $text .= "\tif len($name) > 0 {\n\t\t_p$n = unsafe.Pointer(\&${name}[0])\n\t}"; - $text .= " else {\n\t\t_p$n = unsafe.Pointer(&_zero)\n\t}"; - $text .= "\n"; - push @args, "uintptr(_p$n)", "uintptr(len($name))"; - $n++; - } elsif($type eq "int64" && ($openbsd || $netbsd)) { - push @args, "0"; - if($_32bit eq "big-endian") { - push @args, "uintptr($name>>32)", "uintptr($name)"; - } elsif($_32bit eq "little-endian") { - push @args, "uintptr($name)", "uintptr($name>>32)"; - } else { - push @args, "uintptr($name)"; - } - } elsif($type eq "int64" && $dragonfly) { - if ($func !~ /^extp(read|write)/i) { - push @args, "0"; - } - if($_32bit eq "big-endian") { - push @args, "uintptr($name>>32)", "uintptr($name)"; - } elsif($_32bit eq "little-endian") { - push @args, "uintptr($name)", "uintptr($name>>32)"; - } else { - push @args, "uintptr($name)"; - } - } elsif($type eq "int64" && $_32bit ne "") { - if(@args % 2 && $arm) { - # arm abi specifies 64-bit argument uses - # (even, odd) pair - push @args, "0" - } - if($_32bit eq "big-endian") { - push @args, "uintptr($name>>32)", "uintptr($name)"; - } else { - push @args, "uintptr($name)", "uintptr($name>>32)"; - } - } else { - push @args, "uintptr($name)"; - } - } - - # Determine which form to use; pad args with zeros. - my $asm = "Syscall"; - if ($nonblock) { - $asm = "RawSyscall"; - } - if(@args <= 3) { - while(@args < 3) { - push @args, "0"; - } - } elsif(@args <= 6) { - $asm .= "6"; - while(@args < 6) { - push @args, "0"; - } - } elsif(@args <= 9) { - $asm .= "9"; - while(@args < 9) { - push @args, "0"; - } - } else { - print STDERR "$ARGV:$.: too many arguments to system call\n"; - } - - # System call number. - if($sysname eq "") { - $sysname = "SYS_$func"; - $sysname =~ s/([a-z])([A-Z])/${1}_$2/g; # turn FooBar into Foo_Bar - $sysname =~ y/a-z/A-Z/; - } - - # Actual call. - my $args = join(', ', @args); - my $call = "$asm($sysname, $args)"; - - # Assign return values. - my $body = ""; - my @ret = ("_", "_", "_"); - my $do_errno = 0; - for(my $i=0; $i<@out; $i++) { - my $p = $out[$i]; - my ($name, $type) = parseparam($p); - my $reg = ""; - if($name eq "err" && !$plan9) { - $reg = "e1"; - $ret[2] = $reg; - $do_errno = 1; - } elsif($name eq "err" && $plan9) { - $ret[0] = "r0"; - $ret[2] = "e1"; - next; - } else { - $reg = sprintf("r%d", $i); - $ret[$i] = $reg; - } - if($type eq "bool") { - $reg = "$reg != 0"; - } - if($type eq "int64" && $_32bit ne "") { - # 64-bit number in r1:r0 or r0:r1. - if($i+2 > @out) { - print STDERR "$ARGV:$.: not enough registers for int64 return\n"; - } - if($_32bit eq "big-endian") { - $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i, $i+1); - } else { - $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i+1, $i); - } - $ret[$i] = sprintf("r%d", $i); - $ret[$i+1] = sprintf("r%d", $i+1); - } - if($reg ne "e1" || $plan9) { - $body .= "\t$name = $type($reg)\n"; - } - } - if ($ret[0] eq "_" && $ret[1] eq "_" && $ret[2] eq "_") { - $text .= "\t$call\n"; - } else { - $text .= "\t$ret[0], $ret[1], $ret[2] := $call\n"; - } - $text .= $body; - - if ($plan9 && $ret[2] eq "e1") { - $text .= "\tif int32(r0) == -1 {\n"; - $text .= "\t\terr = e1\n"; - $text .= "\t}\n"; - } elsif ($do_errno) { - $text .= "\tif e1 != 0 {\n"; - $text .= "\t\terr = errnoErr(e1)\n"; - $text .= "\t}\n"; - } - $text .= "\treturn\n"; - $text .= "}\n\n"; -} - -chomp $text; -chomp $text; - -if($errors) { - exit 1; -} - -print <) { - chomp; - s/\s+/ /g; - s/^\s+//; - s/\s+$//; - $package = $1 if !$package && /^package (\S+)$/; - my $nonblock = /^\/\/sysnb /; - next if !/^\/\/sys / && !$nonblock; - - # Line must be of the form - # func Open(path string, mode int, perm int) (fd int, err error) - # Split into name, in params, out params. - if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) { - print STDERR "$ARGV:$.: malformed //sys declaration\n"; - $errors = 1; - next; - } - my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6); - - # Split argument lists on comma. - my @in = parseparamlist($in); - my @out = parseparamlist($out); - - # So file name. - if($modname eq "") { - $modname = "libc"; - } - - # System call name. - if($sysname eq "") { - $sysname = "$func"; - } - - # System call pointer variable name. - my $sysvarname = "proc$sysname"; - - my $strconvfunc = "BytePtrFromString"; - my $strconvtype = "*byte"; - - $sysname =~ y/A-Z/a-z/; # All libc functions are lowercase. - - # Runtime import of function to allow cross-platform builds. - $dynimports .= "//go:cgo_import_dynamic libc_${sysname} ${sysname} \"$modname.so\"\n"; - # Link symbol to proc address variable. - $linknames .= "//go:linkname ${sysvarname} libc_${sysname}\n"; - # Library proc address variable. - push @vars, $sysvarname; - - # Go function header. - $out = join(', ', @out); - if($out ne "") { - $out = " ($out)"; - } - if($text ne "") { - $text .= "\n" - } - $text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out; - - # Check if err return available - my $errvar = ""; - foreach my $p (@out) { - my ($name, $type) = parseparam($p); - if($type eq "error") { - $errvar = $name; - last; - } - } - - # Prepare arguments to Syscall. - my @args = (); - my $n = 0; - foreach my $p (@in) { - my ($name, $type) = parseparam($p); - if($type =~ /^\*/) { - push @args, "uintptr(unsafe.Pointer($name))"; - } elsif($type eq "string" && $errvar ne "") { - $text .= "\tvar _p$n $strconvtype\n"; - $text .= "\t_p$n, $errvar = $strconvfunc($name)\n"; - $text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n"; - push @args, "uintptr(unsafe.Pointer(_p$n))"; - $n++; - } elsif($type eq "string") { - print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n"; - $text .= "\tvar _p$n $strconvtype\n"; - $text .= "\t_p$n, _ = $strconvfunc($name)\n"; - push @args, "uintptr(unsafe.Pointer(_p$n))"; - $n++; - } elsif($type =~ /^\[\](.*)/) { - # Convert slice into pointer, length. - # Have to be careful not to take address of &a[0] if len == 0: - # pass nil in that case. - $text .= "\tvar _p$n *$1\n"; - $text .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n"; - push @args, "uintptr(unsafe.Pointer(_p$n))", "uintptr(len($name))"; - $n++; - } elsif($type eq "int64" && $_32bit ne "") { - if($_32bit eq "big-endian") { - push @args, "uintptr($name >> 32)", "uintptr($name)"; - } else { - push @args, "uintptr($name)", "uintptr($name >> 32)"; - } - } elsif($type eq "bool") { - $text .= "\tvar _p$n uint32\n"; - $text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n"; - push @args, "uintptr(_p$n)"; - $n++; - } else { - push @args, "uintptr($name)"; - } - } - my $nargs = @args; - - # Determine which form to use; pad args with zeros. - my $asm = "sysvicall6"; - if ($nonblock) { - $asm = "rawSysvicall6"; - } - if(@args <= 6) { - while(@args < 6) { - push @args, "0"; - } - } else { - print STDERR "$ARGV:$.: too many arguments to system call\n"; - } - - # Actual call. - my $args = join(', ', @args); - my $call = "$asm(uintptr(unsafe.Pointer(&$sysvarname)), $nargs, $args)"; - - # Assign return values. - my $body = ""; - my $failexpr = ""; - my @ret = ("_", "_", "_"); - my @pout= (); - my $do_errno = 0; - for(my $i=0; $i<@out; $i++) { - my $p = $out[$i]; - my ($name, $type) = parseparam($p); - my $reg = ""; - if($name eq "err") { - $reg = "e1"; - $ret[2] = $reg; - $do_errno = 1; - } else { - $reg = sprintf("r%d", $i); - $ret[$i] = $reg; - } - if($type eq "bool") { - $reg = "$reg != 0"; - } - if($type eq "int64" && $_32bit ne "") { - # 64-bit number in r1:r0 or r0:r1. - if($i+2 > @out) { - print STDERR "$ARGV:$.: not enough registers for int64 return\n"; - } - if($_32bit eq "big-endian") { - $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i, $i+1); - } else { - $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i+1, $i); - } - $ret[$i] = sprintf("r%d", $i); - $ret[$i+1] = sprintf("r%d", $i+1); - } - if($reg ne "e1") { - $body .= "\t$name = $type($reg)\n"; - } - } - if ($ret[0] eq "_" && $ret[1] eq "_" && $ret[2] eq "_") { - $text .= "\t$call\n"; - } else { - $text .= "\t$ret[0], $ret[1], $ret[2] := $call\n"; - } - $text .= $body; - - if ($do_errno) { - $text .= "\tif e1 != 0 {\n"; - $text .= "\t\terr = e1\n"; - $text .= "\t}\n"; - } - $text .= "\treturn\n"; - $text .= "}\n"; -} - -if($errors) { - exit 1; -} - -print < "net.inet", - "net.inet.ipproto" => "net.inet", - "net.inet6.ipv6proto" => "net.inet6", - "net.inet6.ipv6" => "net.inet6.ip6", - "net.inet.icmpv6" => "net.inet6.icmp6", - "net.inet6.divert6" => "net.inet6.divert", - "net.inet6.tcp6" => "net.inet.tcp", - "net.inet6.udp6" => "net.inet.udp", - "mpls" => "net.mpls", - "swpenc" => "vm.swapencrypt" -); - -# Node mappings -my %node_map = ( - "net.inet.ip.ifq" => "net.ifq", - "net.inet.pfsync" => "net.pfsync", - "net.mpls.ifq" => "net.ifq" -); - -my $ctlname; -my %mib = (); -my %sysctl = (); -my $node; - -sub debug() { - print STDERR "$_[0]\n" if $debug; -} - -# Walk the MIB and build a sysctl name to OID mapping. -sub build_sysctl() { - my ($node, $name, $oid) = @_; - my %node = %{$node}; - my @oid = @{$oid}; - - foreach my $key (sort keys %node) { - my @node = @{$node{$key}}; - my $nodename = $name.($name ne '' ? '.' : '').$key; - my @nodeoid = (@oid, $node[0]); - if ($node[1] eq 'CTLTYPE_NODE') { - if (exists $node_map{$nodename}) { - $node = \%mib; - $ctlname = $node_map{$nodename}; - foreach my $part (split /\./, $ctlname) { - $node = \%{@{$$node{$part}}[2]}; - } - } else { - $node = $node[2]; - } - &build_sysctl($node, $nodename, \@nodeoid); - } elsif ($node[1] ne '') { - $sysctl{$nodename} = \@nodeoid; - } - } -} - -foreach my $ctl (@ctls) { - $ctls{$ctl} = $ctl; -} - -# Build MIB -foreach my $header (@headers) { - &debug("Processing $header..."); - open HEADER, "/usr/include/$header" || - print STDERR "Failed to open $header\n"; - while (

    ) { - if ($_ =~ /^#define\s+(CTL_NAMES)\s+{/ || - $_ =~ /^#define\s+(CTL_(.*)_NAMES)\s+{/ || - $_ =~ /^#define\s+((.*)CTL_NAMES)\s+{/) { - if ($1 eq 'CTL_NAMES') { - # Top level. - $node = \%mib; - } else { - # Node. - my $nodename = lc($2); - if ($header =~ /^netinet\//) { - $ctlname = "net.inet.$nodename"; - } elsif ($header =~ /^netinet6\//) { - $ctlname = "net.inet6.$nodename"; - } elsif ($header =~ /^net\//) { - $ctlname = "net.$nodename"; - } else { - $ctlname = "$nodename"; - $ctlname =~ s/^(fs|net|kern)_/$1\./; - } - if (exists $ctl_map{$ctlname}) { - $ctlname = $ctl_map{$ctlname}; - } - if (not exists $ctls{$ctlname}) { - &debug("Ignoring $ctlname..."); - next; - } - - # Walk down from the top of the MIB. - $node = \%mib; - foreach my $part (split /\./, $ctlname) { - if (not exists $$node{$part}) { - &debug("Missing node $part"); - $$node{$part} = [ 0, '', {} ]; - } - $node = \%{@{$$node{$part}}[2]}; - } - } - - # Populate current node with entries. - my $i = -1; - while (defined($_) && $_ !~ /^}/) { - $_ =
    ; - $i++ if $_ =~ /{.*}/; - next if $_ !~ /{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}/; - $$node{$1} = [ $i, $2, {} ]; - } - } - } - close HEADER; -} - -&build_sysctl(\%mib, "", []); - -print <){ - if(/^#define\s+SYS_(\w+)\s+([0-9]+)/){ - my $name = $1; - my $num = $2; - $name =~ y/a-z/A-Z/; - print " SYS_$name = $num;" - } -} - -print <){ - if(/^([0-9]+)\s+STD\s+({ \S+\s+(\w+).*)$/){ - my $num = $1; - my $proto = $2; - my $name = "SYS_$3"; - $name =~ y/a-z/A-Z/; - - # There are multiple entries for enosys and nosys, so comment them out. - if($name =~ /^SYS_E?NOSYS$/){ - $name = "// $name"; - } - if($name eq 'SYS_SYS_EXIT'){ - $name = 'SYS_EXIT'; - } - - print " $name = $num; // $proto\n"; - } -} - -print <){ - if(/^([0-9]+)\s+\S+\s+STD\s+({ \S+\s+(\w+).*)$/){ - my $num = $1; - my $proto = $2; - my $name = "SYS_$3"; - $name =~ y/a-z/A-Z/; - - # There are multiple entries for enosys and nosys, so comment them out. - if($name =~ /^SYS_E?NOSYS$/){ - $name = "// $name"; - } - if($name eq 'SYS_SYS_EXIT'){ - $name = 'SYS_EXIT'; - } - - print " $name = $num; // $proto\n"; - } -} - -print <){ - if($line =~ /^(.*)\\$/) { - # Handle continuation - $line = $1; - $_ =~ s/^\s+//; - $line .= $_; - } else { - # New line - $line = $_; - } - next if $line =~ /\\$/; - if($line =~ /^([0-9]+)\s+((STD)|(NOERR))\s+(RUMP\s+)?({\s+\S+\s*\*?\s*\|(\S+)\|(\S*)\|(\w+).*\s+})(\s+(\S+))?$/) { - my $num = $1; - my $proto = $6; - my $compat = $8; - my $name = "$7_$9"; - - $name = "$7_$11" if $11 ne ''; - $name =~ y/a-z/A-Z/; - - if($compat eq '' || $compat eq '13' || $compat eq '30' || $compat eq '50') { - print " $name = $num; // $proto\n"; - } - } -} - -print <){ - if(/^([0-9]+)\s+STD\s+(NOLOCK\s+)?({ \S+\s+\*?(\w+).*)$/){ - my $num = $1; - my $proto = $3; - my $name = $4; - $name =~ y/a-z/A-Z/; - - # There are multiple entries for enosys and nosys, so comment them out. - if($name =~ /^SYS_E?NOSYS$/){ - $name = "// $name"; - } - if($name eq 'SYS_SYS_EXIT'){ - $name = 'SYS_EXIT'; - } - - print " $name = $num; // $proto\n"; - } -} - -print < tables.go - gofmt -w -s tables.go - -# Build (but do not run) maketables during testing, -# just to make sure it still compiles. -testshort: maketables diff --git a/vendor/google.golang.org/appengine/internal/base/api_base.proto b/vendor/google.golang.org/appengine/internal/base/api_base.proto deleted file mode 100644 index 56cd7a3cad..0000000000 --- a/vendor/google.golang.org/appengine/internal/base/api_base.proto +++ /dev/null @@ -1,33 +0,0 @@ -// Built-in base types for API calls. Primarily useful as return types. - -syntax = "proto2"; -option go_package = "base"; - -package appengine.base; - -message StringProto { - required string value = 1; -} - -message Integer32Proto { - required int32 value = 1; -} - -message Integer64Proto { - required int64 value = 1; -} - -message BoolProto { - required bool value = 1; -} - -message DoubleProto { - required double value = 1; -} - -message BytesProto { - required bytes value = 1 [ctype=CORD]; -} - -message VoidProto { -} diff --git a/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.proto b/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.proto deleted file mode 100755 index 497b4d9a9a..0000000000 --- a/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.proto +++ /dev/null @@ -1,551 +0,0 @@ -syntax = "proto2"; -option go_package = "datastore"; - -package appengine; - -message Action{} - -message PropertyValue { - optional int64 int64Value = 1; - optional bool booleanValue = 2; - optional string stringValue = 3; - optional double doubleValue = 4; - - optional group PointValue = 5 { - required double x = 6; - required double y = 7; - } - - optional group UserValue = 8 { - required string email = 9; - required string auth_domain = 10; - optional string nickname = 11; - optional string federated_identity = 21; - optional string federated_provider = 22; - } - - optional group ReferenceValue = 12 { - required string app = 13; - optional string name_space = 20; - repeated group PathElement = 14 { - required string type = 15; - optional int64 id = 16; - optional string name = 17; - } - } -} - -message Property { - enum Meaning { - NO_MEANING = 0; - BLOB = 14; - TEXT = 15; - BYTESTRING = 16; - - ATOM_CATEGORY = 1; - ATOM_LINK = 2; - ATOM_TITLE = 3; - ATOM_CONTENT = 4; - ATOM_SUMMARY = 5; - ATOM_AUTHOR = 6; - - GD_WHEN = 7; - GD_EMAIL = 8; - GEORSS_POINT = 9; - GD_IM = 10; - - GD_PHONENUMBER = 11; - GD_POSTALADDRESS = 12; - - GD_RATING = 13; - - BLOBKEY = 17; - ENTITY_PROTO = 19; - - INDEX_VALUE = 18; - }; - - optional Meaning meaning = 1 [default = NO_MEANING]; - optional string meaning_uri = 2; - - required string name = 3; - - required PropertyValue value = 5; - - required bool multiple = 4; - - optional bool searchable = 6 [default=false]; - - enum FtsTokenizationOption { - HTML = 1; - ATOM = 2; - } - - optional FtsTokenizationOption fts_tokenization_option = 8; - - optional string locale = 9 [default = "en"]; -} - -message Path { - repeated group Element = 1 { - required string type = 2; - optional int64 id = 3; - optional string name = 4; - } -} - -message Reference { - required string app = 13; - optional string name_space = 20; - required Path path = 14; -} - -message User { - required string email = 1; - required string auth_domain = 2; - optional string nickname = 3; - optional string federated_identity = 6; - optional string federated_provider = 7; -} - -message EntityProto { - required Reference key = 13; - required Path entity_group = 16; - optional User owner = 17; - - enum Kind { - GD_CONTACT = 1; - GD_EVENT = 2; - GD_MESSAGE = 3; - } - optional Kind kind = 4; - optional string kind_uri = 5; - - repeated Property property = 14; - repeated Property raw_property = 15; - - optional int32 rank = 18; -} - -message CompositeProperty { - required int64 index_id = 1; - repeated string value = 2; -} - -message Index { - required string entity_type = 1; - required bool ancestor = 5; - repeated group Property = 2 { - required string name = 3; - enum Direction { - ASCENDING = 1; - DESCENDING = 2; - } - optional Direction direction = 4 [default = ASCENDING]; - } -} - -message CompositeIndex { - required string app_id = 1; - required int64 id = 2; - required Index definition = 3; - - enum State { - WRITE_ONLY = 1; - READ_WRITE = 2; - DELETED = 3; - ERROR = 4; - } - required State state = 4; - - optional bool only_use_if_required = 6 [default = false]; -} - -message IndexPostfix { - message IndexValue { - required string property_name = 1; - required PropertyValue value = 2; - } - - repeated IndexValue index_value = 1; - - optional Reference key = 2; - - optional bool before = 3 [default=true]; -} - -message IndexPosition { - optional string key = 1; - - optional bool before = 2 [default=true]; -} - -message Snapshot { - enum Status { - INACTIVE = 0; - ACTIVE = 1; - } - - required int64 ts = 1; -} - -message InternalHeader { - optional string qos = 1; -} - -message Transaction { - optional InternalHeader header = 4; - required fixed64 handle = 1; - required string app = 2; - optional bool mark_changes = 3 [default = false]; -} - -message Query { - optional InternalHeader header = 39; - - required string app = 1; - optional string name_space = 29; - - optional string kind = 3; - optional Reference ancestor = 17; - - repeated group Filter = 4 { - enum Operator { - LESS_THAN = 1; - LESS_THAN_OR_EQUAL = 2; - GREATER_THAN = 3; - GREATER_THAN_OR_EQUAL = 4; - EQUAL = 5; - IN = 6; - EXISTS = 7; - } - - required Operator op = 6; - repeated Property property = 14; - } - - optional string search_query = 8; - - repeated group Order = 9 { - enum Direction { - ASCENDING = 1; - DESCENDING = 2; - } - - required string property = 10; - optional Direction direction = 11 [default = ASCENDING]; - } - - enum Hint { - ORDER_FIRST = 1; - ANCESTOR_FIRST = 2; - FILTER_FIRST = 3; - } - optional Hint hint = 18; - - optional int32 count = 23; - - optional int32 offset = 12 [default = 0]; - - optional int32 limit = 16; - - optional CompiledCursor compiled_cursor = 30; - optional CompiledCursor end_compiled_cursor = 31; - - repeated CompositeIndex composite_index = 19; - - optional bool require_perfect_plan = 20 [default = false]; - - optional bool keys_only = 21 [default = false]; - - optional Transaction transaction = 22; - - optional bool compile = 25 [default = false]; - - optional int64 failover_ms = 26; - - optional bool strong = 32; - - repeated string property_name = 33; - - repeated string group_by_property_name = 34; - - optional bool distinct = 24; - - optional int64 min_safe_time_seconds = 35; - - repeated string safe_replica_name = 36; - - optional bool persist_offset = 37 [default=false]; -} - -message CompiledQuery { - required group PrimaryScan = 1 { - optional string index_name = 2; - - optional string start_key = 3; - optional bool start_inclusive = 4; - optional string end_key = 5; - optional bool end_inclusive = 6; - - repeated string start_postfix_value = 22; - repeated string end_postfix_value = 23; - - optional int64 end_unapplied_log_timestamp_us = 19; - } - - repeated group MergeJoinScan = 7 { - required string index_name = 8; - - repeated string prefix_value = 9; - - optional bool value_prefix = 20 [default=false]; - } - - optional Index index_def = 21; - - optional int32 offset = 10 [default = 0]; - - optional int32 limit = 11; - - required bool keys_only = 12; - - repeated string property_name = 24; - - optional int32 distinct_infix_size = 25; - - optional group EntityFilter = 13 { - optional bool distinct = 14 [default=false]; - - optional string kind = 17; - optional Reference ancestor = 18; - } -} - -message CompiledCursor { - optional group Position = 2 { - optional string start_key = 27; - - repeated group IndexValue = 29 { - optional string property = 30; - required PropertyValue value = 31; - } - - optional Reference key = 32; - - optional bool start_inclusive = 28 [default=true]; - } -} - -message Cursor { - required fixed64 cursor = 1; - - optional string app = 2; -} - -message Error { - enum ErrorCode { - BAD_REQUEST = 1; - CONCURRENT_TRANSACTION = 2; - INTERNAL_ERROR = 3; - NEED_INDEX = 4; - TIMEOUT = 5; - PERMISSION_DENIED = 6; - BIGTABLE_ERROR = 7; - COMMITTED_BUT_STILL_APPLYING = 8; - CAPABILITY_DISABLED = 9; - TRY_ALTERNATE_BACKEND = 10; - SAFE_TIME_TOO_OLD = 11; - } -} - -message Cost { - optional int32 index_writes = 1; - optional int32 index_write_bytes = 2; - optional int32 entity_writes = 3; - optional int32 entity_write_bytes = 4; - optional group CommitCost = 5 { - optional int32 requested_entity_puts = 6; - optional int32 requested_entity_deletes = 7; - }; - optional int32 approximate_storage_delta = 8; - optional int32 id_sequence_updates = 9; -} - -message GetRequest { - optional InternalHeader header = 6; - - repeated Reference key = 1; - optional Transaction transaction = 2; - - optional int64 failover_ms = 3; - - optional bool strong = 4; - - optional bool allow_deferred = 5 [default=false]; -} - -message GetResponse { - repeated group Entity = 1 { - optional EntityProto entity = 2; - optional Reference key = 4; - - optional int64 version = 3; - } - - repeated Reference deferred = 5; - - optional bool in_order = 6 [default=true]; -} - -message PutRequest { - optional InternalHeader header = 11; - - repeated EntityProto entity = 1; - optional Transaction transaction = 2; - repeated CompositeIndex composite_index = 3; - - optional bool trusted = 4 [default = false]; - - optional bool force = 7 [default = false]; - - optional bool mark_changes = 8 [default = false]; - repeated Snapshot snapshot = 9; - - enum AutoIdPolicy { - CURRENT = 0; - SEQUENTIAL = 1; - } - optional AutoIdPolicy auto_id_policy = 10 [default = CURRENT]; -} - -message PutResponse { - repeated Reference key = 1; - optional Cost cost = 2; - repeated int64 version = 3; -} - -message TouchRequest { - optional InternalHeader header = 10; - - repeated Reference key = 1; - repeated CompositeIndex composite_index = 2; - optional bool force = 3 [default = false]; - repeated Snapshot snapshot = 9; -} - -message TouchResponse { - optional Cost cost = 1; -} - -message DeleteRequest { - optional InternalHeader header = 10; - - repeated Reference key = 6; - optional Transaction transaction = 5; - - optional bool trusted = 4 [default = false]; - - optional bool force = 7 [default = false]; - - optional bool mark_changes = 8 [default = false]; - repeated Snapshot snapshot = 9; -} - -message DeleteResponse { - optional Cost cost = 1; - repeated int64 version = 3; -} - -message NextRequest { - optional InternalHeader header = 5; - - required Cursor cursor = 1; - optional int32 count = 2; - - optional int32 offset = 4 [default = 0]; - - optional bool compile = 3 [default = false]; -} - -message QueryResult { - optional Cursor cursor = 1; - - repeated EntityProto result = 2; - - optional int32 skipped_results = 7; - - required bool more_results = 3; - - optional bool keys_only = 4; - - optional bool index_only = 9; - - optional bool small_ops = 10; - - optional CompiledQuery compiled_query = 5; - - optional CompiledCursor compiled_cursor = 6; - - repeated CompositeIndex index = 8; - - repeated int64 version = 11; -} - -message AllocateIdsRequest { - optional InternalHeader header = 4; - - optional Reference model_key = 1; - - optional int64 size = 2; - - optional int64 max = 3; - - repeated Reference reserve = 5; -} - -message AllocateIdsResponse { - required int64 start = 1; - required int64 end = 2; - optional Cost cost = 3; -} - -message CompositeIndices { - repeated CompositeIndex index = 1; -} - -message AddActionsRequest { - optional InternalHeader header = 3; - - required Transaction transaction = 1; - repeated Action action = 2; -} - -message AddActionsResponse { -} - -message BeginTransactionRequest { - optional InternalHeader header = 3; - - required string app = 1; - optional bool allow_multiple_eg = 2 [default = false]; - optional string database_id = 4; - - enum TransactionMode { - UNKNOWN = 0; - READ_ONLY = 1; - READ_WRITE = 2; - } - optional TransactionMode mode = 5 [default = UNKNOWN]; - - optional Transaction previous_transaction = 7; -} - -message CommitResponse { - optional Cost cost = 1; - - repeated group Version = 3 { - required Reference root_entity_key = 4; - required int64 version = 5; - } -} diff --git a/vendor/google.golang.org/appengine/internal/log/log_service.proto b/vendor/google.golang.org/appengine/internal/log/log_service.proto deleted file mode 100644 index 8981dc4757..0000000000 --- a/vendor/google.golang.org/appengine/internal/log/log_service.proto +++ /dev/null @@ -1,150 +0,0 @@ -syntax = "proto2"; -option go_package = "log"; - -package appengine; - -message LogServiceError { - enum ErrorCode { - OK = 0; - INVALID_REQUEST = 1; - STORAGE_ERROR = 2; - } -} - -message UserAppLogLine { - required int64 timestamp_usec = 1; - required int64 level = 2; - required string message = 3; -} - -message UserAppLogGroup { - repeated UserAppLogLine log_line = 2; -} - -message FlushRequest { - optional bytes logs = 1; -} - -message SetStatusRequest { - required string status = 1; -} - - -message LogOffset { - optional bytes request_id = 1; -} - -message LogLine { - required int64 time = 1; - required int32 level = 2; - required string log_message = 3; -} - -message RequestLog { - required string app_id = 1; - optional string module_id = 37 [default="default"]; - required string version_id = 2; - required bytes request_id = 3; - optional LogOffset offset = 35; - required string ip = 4; - optional string nickname = 5; - required int64 start_time = 6; - required int64 end_time = 7; - required int64 latency = 8; - required int64 mcycles = 9; - required string method = 10; - required string resource = 11; - required string http_version = 12; - required int32 status = 13; - required int64 response_size = 14; - optional string referrer = 15; - optional string user_agent = 16; - required string url_map_entry = 17; - required string combined = 18; - optional int64 api_mcycles = 19; - optional string host = 20; - optional double cost = 21; - - optional string task_queue_name = 22; - optional string task_name = 23; - - optional bool was_loading_request = 24; - optional int64 pending_time = 25; - optional int32 replica_index = 26 [default = -1]; - optional bool finished = 27 [default = true]; - optional bytes clone_key = 28; - - repeated LogLine line = 29; - - optional bool lines_incomplete = 36; - optional bytes app_engine_release = 38; - - optional int32 exit_reason = 30; - optional bool was_throttled_for_time = 31; - optional bool was_throttled_for_requests = 32; - optional int64 throttled_time = 33; - - optional bytes server_name = 34; -} - -message LogModuleVersion { - optional string module_id = 1 [default="default"]; - optional string version_id = 2; -} - -message LogReadRequest { - required string app_id = 1; - repeated string version_id = 2; - repeated LogModuleVersion module_version = 19; - - optional int64 start_time = 3; - optional int64 end_time = 4; - optional LogOffset offset = 5; - repeated bytes request_id = 6; - - optional int32 minimum_log_level = 7; - optional bool include_incomplete = 8; - optional int64 count = 9; - - optional string combined_log_regex = 14; - optional string host_regex = 15; - optional int32 replica_index = 16; - - optional bool include_app_logs = 10; - optional int32 app_logs_per_request = 17; - optional bool include_host = 11; - optional bool include_all = 12; - optional bool cache_iterator = 13; - optional int32 num_shards = 18; -} - -message LogReadResponse { - repeated RequestLog log = 1; - optional LogOffset offset = 2; - optional int64 last_end_time = 3; -} - -message LogUsageRecord { - optional string version_id = 1; - optional int32 start_time = 2; - optional int32 end_time = 3; - optional int64 count = 4; - optional int64 total_size = 5; - optional int32 records = 6; -} - -message LogUsageRequest { - required string app_id = 1; - repeated string version_id = 2; - optional int32 start_time = 3; - optional int32 end_time = 4; - optional uint32 resolution_hours = 5 [default = 1]; - optional bool combine_versions = 6; - optional int32 usage_version = 7; - optional bool versions_only = 8; -} - -message LogUsageResponse { - repeated LogUsageRecord usage = 1; - optional LogUsageRecord summary = 2; -} diff --git a/vendor/google.golang.org/appengine/internal/regen.sh b/vendor/google.golang.org/appengine/internal/regen.sh deleted file mode 100755 index 2fdb546a63..0000000000 --- a/vendor/google.golang.org/appengine/internal/regen.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash -e -# -# This script rebuilds the generated code for the protocol buffers. -# To run this you will need protoc and goprotobuf installed; -# see https://github.com/golang/protobuf for instructions. - -PKG=google.golang.org/appengine - -function die() { - echo 1>&2 $* - exit 1 -} - -# Sanity check that the right tools are accessible. -for tool in go protoc protoc-gen-go; do - q=$(which $tool) || die "didn't find $tool" - echo 1>&2 "$tool: $q" -done - -echo -n 1>&2 "finding package dir... " -pkgdir=$(go list -f '{{.Dir}}' $PKG) -echo 1>&2 $pkgdir -base=$(echo $pkgdir | sed "s,/$PKG\$,,") -echo 1>&2 "base: $base" -cd $base - -# Run protoc once per package. -for dir in $(find $PKG/internal -name '*.proto' | xargs dirname | sort | uniq); do - echo 1>&2 "* $dir" - protoc --go_out=. $dir/*.proto -done - -for f in $(find $PKG/internal -name '*.pb.go'); do - # Remove proto.RegisterEnum calls. - # These cause duplicate registration panics when these packages - # are used on classic App Engine. proto.RegisterEnum only affects - # parsing the text format; we don't care about that. - # https://code.google.com/p/googleappengine/issues/detail?id=11670#c17 - sed -i '/proto.RegisterEnum/d' $f -done diff --git a/vendor/google.golang.org/appengine/internal/remote_api/remote_api.proto b/vendor/google.golang.org/appengine/internal/remote_api/remote_api.proto deleted file mode 100644 index f21763a4e2..0000000000 --- a/vendor/google.golang.org/appengine/internal/remote_api/remote_api.proto +++ /dev/null @@ -1,44 +0,0 @@ -syntax = "proto2"; -option go_package = "remote_api"; - -package remote_api; - -message Request { - required string service_name = 2; - required string method = 3; - required bytes request = 4; - optional string request_id = 5; -} - -message ApplicationError { - required int32 code = 1; - required string detail = 2; -} - -message RpcError { - enum ErrorCode { - UNKNOWN = 0; - CALL_NOT_FOUND = 1; - PARSE_ERROR = 2; - SECURITY_VIOLATION = 3; - OVER_QUOTA = 4; - REQUEST_TOO_LARGE = 5; - CAPABILITY_DISABLED = 6; - FEATURE_DISABLED = 7; - BAD_REQUEST = 8; - RESPONSE_TOO_LARGE = 9; - CANCELLED = 10; - REPLAY_ERROR = 11; - DEADLINE_EXCEEDED = 12; - } - required int32 code = 1; - optional string detail = 2; -} - -message Response { - optional bytes response = 1; - optional bytes exception = 2; - optional ApplicationError application_error = 3; - optional bytes java_exception = 4; - optional RpcError rpc_error = 5; -} diff --git a/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto b/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto deleted file mode 100644 index f695edf6a9..0000000000 --- a/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto +++ /dev/null @@ -1,64 +0,0 @@ -syntax = "proto2"; -option go_package = "urlfetch"; - -package appengine; - -message URLFetchServiceError { - enum ErrorCode { - OK = 0; - INVALID_URL = 1; - FETCH_ERROR = 2; - UNSPECIFIED_ERROR = 3; - RESPONSE_TOO_LARGE = 4; - DEADLINE_EXCEEDED = 5; - SSL_CERTIFICATE_ERROR = 6; - DNS_ERROR = 7; - CLOSED = 8; - INTERNAL_TRANSIENT_ERROR = 9; - TOO_MANY_REDIRECTS = 10; - MALFORMED_REPLY = 11; - CONNECTION_ERROR = 12; - } -} - -message URLFetchRequest { - enum RequestMethod { - GET = 1; - POST = 2; - HEAD = 3; - PUT = 4; - DELETE = 5; - PATCH = 6; - } - required RequestMethod Method = 1; - required string Url = 2; - repeated group Header = 3 { - required string Key = 4; - required string Value = 5; - } - optional bytes Payload = 6 [ctype=CORD]; - - optional bool FollowRedirects = 7 [default=true]; - - optional double Deadline = 8; - - optional bool MustValidateServerCertificate = 9 [default=true]; -} - -message URLFetchResponse { - optional bytes Content = 1; - required int32 StatusCode = 2; - repeated group Header = 3 { - required string Key = 4; - required string Value = 5; - } - optional bool ContentWasTruncated = 6 [default=false]; - optional int64 ExternalBytesSent = 7; - optional int64 ExternalBytesReceived = 8; - - optional string FinalUrl = 9; - - optional int64 ApiCpuMilliseconds = 10 [default=0]; - optional int64 ApiBytesSent = 11 [default=0]; - optional int64 ApiBytesReceived = 12 [default=0]; -} diff --git a/vendor/gopkg.in/fsnotify.v1/.editorconfig b/vendor/gopkg.in/fsnotify.v1/.editorconfig deleted file mode 100644 index ba49e3c234..0000000000 --- a/vendor/gopkg.in/fsnotify.v1/.editorconfig +++ /dev/null @@ -1,5 +0,0 @@ -root = true - -[*] -indent_style = tab -indent_size = 4 diff --git a/vendor/gopkg.in/fsnotify.v1/.gitignore b/vendor/gopkg.in/fsnotify.v1/.gitignore deleted file mode 100644 index 4cd0cbaf43..0000000000 --- a/vendor/gopkg.in/fsnotify.v1/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -# Setup a Global .gitignore for OS and editor generated files: -# https://help.github.com/articles/ignoring-files -# git config --global core.excludesfile ~/.gitignore_global - -.vagrant -*.sublime-project diff --git a/vendor/gopkg.in/fsnotify.v1/.travis.yml b/vendor/gopkg.in/fsnotify.v1/.travis.yml deleted file mode 100644 index 981d1bb813..0000000000 --- a/vendor/gopkg.in/fsnotify.v1/.travis.yml +++ /dev/null @@ -1,30 +0,0 @@ -sudo: false -language: go - -go: - - 1.8.x - - 1.9.x - - tip - -matrix: - allow_failures: - - go: tip - fast_finish: true - -before_script: - - go get -u github.com/golang/lint/golint - -script: - - go test -v --race ./... - -after_script: - - test -z "$(gofmt -s -l -w . | tee /dev/stderr)" - - test -z "$(golint ./... | tee /dev/stderr)" - - go vet ./... - -os: - - linux - - osx - -notifications: - email: false diff --git a/vendor/gopkg.in/fsnotify.v1/CHANGELOG.md b/vendor/gopkg.in/fsnotify.v1/CHANGELOG.md deleted file mode 100644 index be4d7ea2c1..0000000000 --- a/vendor/gopkg.in/fsnotify.v1/CHANGELOG.md +++ /dev/null @@ -1,317 +0,0 @@ -# Changelog - -## v1.4.7 / 2018-01-09 - -* BSD/macOS: Fix possible deadlock on closing the watcher on kqueue (thanks @nhooyr and @glycerine) -* Tests: Fix missing verb on format string (thanks @rchiossi) -* Linux: Fix deadlock in Remove (thanks @aarondl) -* Linux: Watch.Add improvements (avoid race, fix consistency, reduce garbage) (thanks @twpayne) -* Docs: Moved FAQ into the README (thanks @vahe) -* Linux: Properly handle inotify's IN_Q_OVERFLOW event (thanks @zeldovich) -* Docs: replace references to OS X with macOS - -## v1.4.2 / 2016-10-10 - -* Linux: use InotifyInit1 with IN_CLOEXEC to stop leaking a file descriptor to a child process when using fork/exec [#178](https://github.com/fsnotify/fsnotify/pull/178) (thanks @pattyshack) - -## v1.4.1 / 2016-10-04 - -* Fix flaky inotify stress test on Linux [#177](https://github.com/fsnotify/fsnotify/pull/177) (thanks @pattyshack) - -## v1.4.0 / 2016-10-01 - -* add a String() method to Event.Op [#165](https://github.com/fsnotify/fsnotify/pull/165) (thanks @oozie) - -## v1.3.1 / 2016-06-28 - -* Windows: fix for double backslash when watching the root of a drive [#151](https://github.com/fsnotify/fsnotify/issues/151) (thanks @brunoqc) - -## v1.3.0 / 2016-04-19 - -* Support linux/arm64 by [patching](https://go-review.googlesource.com/#/c/21971/) x/sys/unix and switching to to it from syscall (thanks @suihkulokki) [#135](https://github.com/fsnotify/fsnotify/pull/135) - -## v1.2.10 / 2016-03-02 - -* Fix golint errors in windows.go [#121](https://github.com/fsnotify/fsnotify/pull/121) (thanks @tiffanyfj) - -## v1.2.9 / 2016-01-13 - -kqueue: Fix logic for CREATE after REMOVE [#111](https://github.com/fsnotify/fsnotify/pull/111) (thanks @bep) - -## v1.2.8 / 2015-12-17 - -* kqueue: fix race condition in Close [#105](https://github.com/fsnotify/fsnotify/pull/105) (thanks @djui for reporting the issue and @ppknap for writing a failing test) -* inotify: fix race in test -* enable race detection for continuous integration (Linux, Mac, Windows) - -## v1.2.5 / 2015-10-17 - -* inotify: use epoll_create1 for arm64 support (requires Linux 2.6.27 or later) [#100](https://github.com/fsnotify/fsnotify/pull/100) (thanks @suihkulokki) -* inotify: fix path leaks [#73](https://github.com/fsnotify/fsnotify/pull/73) (thanks @chamaken) -* kqueue: watch for rename events on subdirectories [#83](https://github.com/fsnotify/fsnotify/pull/83) (thanks @guotie) -* kqueue: avoid infinite loops from symlinks cycles [#101](https://github.com/fsnotify/fsnotify/pull/101) (thanks @illicitonion) - -## v1.2.1 / 2015-10-14 - -* kqueue: don't watch named pipes [#98](https://github.com/fsnotify/fsnotify/pull/98) (thanks @evanphx) - -## v1.2.0 / 2015-02-08 - -* inotify: use epoll to wake up readEvents [#66](https://github.com/fsnotify/fsnotify/pull/66) (thanks @PieterD) -* inotify: closing watcher should now always shut down goroutine [#63](https://github.com/fsnotify/fsnotify/pull/63) (thanks @PieterD) -* kqueue: close kqueue after removing watches, fixes [#59](https://github.com/fsnotify/fsnotify/issues/59) - -## v1.1.1 / 2015-02-05 - -* inotify: Retry read on EINTR [#61](https://github.com/fsnotify/fsnotify/issues/61) (thanks @PieterD) - -## v1.1.0 / 2014-12-12 - -* kqueue: rework internals [#43](https://github.com/fsnotify/fsnotify/pull/43) - * add low-level functions - * only need to store flags on directories - * less mutexes [#13](https://github.com/fsnotify/fsnotify/issues/13) - * done can be an unbuffered channel - * remove calls to os.NewSyscallError -* More efficient string concatenation for Event.String() [#52](https://github.com/fsnotify/fsnotify/pull/52) (thanks @mdlayher) -* kqueue: fix regression in rework causing subdirectories to be watched [#48](https://github.com/fsnotify/fsnotify/issues/48) -* kqueue: cleanup internal watch before sending remove event [#51](https://github.com/fsnotify/fsnotify/issues/51) - -## v1.0.4 / 2014-09-07 - -* kqueue: add dragonfly to the build tags. -* Rename source code files, rearrange code so exported APIs are at the top. -* Add done channel to example code. [#37](https://github.com/fsnotify/fsnotify/pull/37) (thanks @chenyukang) - -## v1.0.3 / 2014-08-19 - -* [Fix] Windows MOVED_TO now translates to Create like on BSD and Linux. [#36](https://github.com/fsnotify/fsnotify/issues/36) - -## v1.0.2 / 2014-08-17 - -* [Fix] Missing create events on macOS. [#14](https://github.com/fsnotify/fsnotify/issues/14) (thanks @zhsso) -* [Fix] Make ./path and path equivalent. (thanks @zhsso) - -## v1.0.0 / 2014-08-15 - -* [API] Remove AddWatch on Windows, use Add. -* Improve documentation for exported identifiers. [#30](https://github.com/fsnotify/fsnotify/issues/30) -* Minor updates based on feedback from golint. - -## dev / 2014-07-09 - -* Moved to [github.com/fsnotify/fsnotify](https://github.com/fsnotify/fsnotify). -* Use os.NewSyscallError instead of returning errno (thanks @hariharan-uno) - -## dev / 2014-07-04 - -* kqueue: fix incorrect mutex used in Close() -* Update example to demonstrate usage of Op. - -## dev / 2014-06-28 - -* [API] Don't set the Write Op for attribute notifications [#4](https://github.com/fsnotify/fsnotify/issues/4) -* Fix for String() method on Event (thanks Alex Brainman) -* Don't build on Plan 9 or Solaris (thanks @4ad) - -## dev / 2014-06-21 - -* Events channel of type Event rather than *Event. -* [internal] use syscall constants directly for inotify and kqueue. -* [internal] kqueue: rename events to kevents and fileEvent to event. - -## dev / 2014-06-19 - -* Go 1.3+ required on Windows (uses syscall.ERROR_MORE_DATA internally). -* [internal] remove cookie from Event struct (unused). -* [internal] Event struct has the same definition across every OS. -* [internal] remove internal watch and removeWatch methods. - -## dev / 2014-06-12 - -* [API] Renamed Watch() to Add() and RemoveWatch() to Remove(). -* [API] Pluralized channel names: Events and Errors. -* [API] Renamed FileEvent struct to Event. -* [API] Op constants replace methods like IsCreate(). - -## dev / 2014-06-12 - -* Fix data race on kevent buffer (thanks @tilaks) [#98](https://github.com/howeyc/fsnotify/pull/98) - -## dev / 2014-05-23 - -* [API] Remove current implementation of WatchFlags. - * current implementation doesn't take advantage of OS for efficiency - * provides little benefit over filtering events as they are received, but has extra bookkeeping and mutexes - * no tests for the current implementation - * not fully implemented on Windows [#93](https://github.com/howeyc/fsnotify/issues/93#issuecomment-39285195) - -## v0.9.3 / 2014-12-31 - -* kqueue: cleanup internal watch before sending remove event [#51](https://github.com/fsnotify/fsnotify/issues/51) - -## v0.9.2 / 2014-08-17 - -* [Backport] Fix missing create events on macOS. [#14](https://github.com/fsnotify/fsnotify/issues/14) (thanks @zhsso) - -## v0.9.1 / 2014-06-12 - -* Fix data race on kevent buffer (thanks @tilaks) [#98](https://github.com/howeyc/fsnotify/pull/98) - -## v0.9.0 / 2014-01-17 - -* IsAttrib() for events that only concern a file's metadata [#79][] (thanks @abustany) -* [Fix] kqueue: fix deadlock [#77][] (thanks @cespare) -* [NOTICE] Development has moved to `code.google.com/p/go.exp/fsnotify` in preparation for inclusion in the Go standard library. - -## v0.8.12 / 2013-11-13 - -* [API] Remove FD_SET and friends from Linux adapter - -## v0.8.11 / 2013-11-02 - -* [Doc] Add Changelog [#72][] (thanks @nathany) -* [Doc] Spotlight and double modify events on macOS [#62][] (reported by @paulhammond) - -## v0.8.10 / 2013-10-19 - -* [Fix] kqueue: remove file watches when parent directory is removed [#71][] (reported by @mdwhatcott) -* [Fix] kqueue: race between Close and readEvents [#70][] (reported by @bernerdschaefer) -* [Doc] specify OS-specific limits in README (thanks @debrando) - -## v0.8.9 / 2013-09-08 - -* [Doc] Contributing (thanks @nathany) -* [Doc] update package path in example code [#63][] (thanks @paulhammond) -* [Doc] GoCI badge in README (Linux only) [#60][] -* [Doc] Cross-platform testing with Vagrant [#59][] (thanks @nathany) - -## v0.8.8 / 2013-06-17 - -* [Fix] Windows: handle `ERROR_MORE_DATA` on Windows [#49][] (thanks @jbowtie) - -## v0.8.7 / 2013-06-03 - -* [API] Make syscall flags internal -* [Fix] inotify: ignore event changes -* [Fix] race in symlink test [#45][] (reported by @srid) -* [Fix] tests on Windows -* lower case error messages - -## v0.8.6 / 2013-05-23 - -* kqueue: Use EVT_ONLY flag on Darwin -* [Doc] Update README with full example - -## v0.8.5 / 2013-05-09 - -* [Fix] inotify: allow monitoring of "broken" symlinks (thanks @tsg) - -## v0.8.4 / 2013-04-07 - -* [Fix] kqueue: watch all file events [#40][] (thanks @ChrisBuchholz) - -## v0.8.3 / 2013-03-13 - -* [Fix] inoitfy/kqueue memory leak [#36][] (reported by @nbkolchin) -* [Fix] kqueue: use fsnFlags for watching a directory [#33][] (reported by @nbkolchin) - -## v0.8.2 / 2013-02-07 - -* [Doc] add Authors -* [Fix] fix data races for map access [#29][] (thanks @fsouza) - -## v0.8.1 / 2013-01-09 - -* [Fix] Windows path separators -* [Doc] BSD License - -## v0.8.0 / 2012-11-09 - -* kqueue: directory watching improvements (thanks @vmirage) -* inotify: add `IN_MOVED_TO` [#25][] (requested by @cpisto) -* [Fix] kqueue: deleting watched directory [#24][] (reported by @jakerr) - -## v0.7.4 / 2012-10-09 - -* [Fix] inotify: fixes from https://codereview.appspot.com/5418045/ (ugorji) -* [Fix] kqueue: preserve watch flags when watching for delete [#21][] (reported by @robfig) -* [Fix] kqueue: watch the directory even if it isn't a new watch (thanks @robfig) -* [Fix] kqueue: modify after recreation of file - -## v0.7.3 / 2012-09-27 - -* [Fix] kqueue: watch with an existing folder inside the watched folder (thanks @vmirage) -* [Fix] kqueue: no longer get duplicate CREATE events - -## v0.7.2 / 2012-09-01 - -* kqueue: events for created directories - -## v0.7.1 / 2012-07-14 - -* [Fix] for renaming files - -## v0.7.0 / 2012-07-02 - -* [Feature] FSNotify flags -* [Fix] inotify: Added file name back to event path - -## v0.6.0 / 2012-06-06 - -* kqueue: watch files after directory created (thanks @tmc) - -## v0.5.1 / 2012-05-22 - -* [Fix] inotify: remove all watches before Close() - -## v0.5.0 / 2012-05-03 - -* [API] kqueue: return errors during watch instead of sending over channel -* kqueue: match symlink behavior on Linux -* inotify: add `DELETE_SELF` (requested by @taralx) -* [Fix] kqueue: handle EINTR (reported by @robfig) -* [Doc] Godoc example [#1][] (thanks @davecheney) - -## v0.4.0 / 2012-03-30 - -* Go 1 released: build with go tool -* [Feature] Windows support using winfsnotify -* Windows does not have attribute change notifications -* Roll attribute notifications into IsModify - -## v0.3.0 / 2012-02-19 - -* kqueue: add files when watch directory - -## v0.2.0 / 2011-12-30 - -* update to latest Go weekly code - -## v0.1.0 / 2011-10-19 - -* kqueue: add watch on file creation to match inotify -* kqueue: create file event -* inotify: ignore `IN_IGNORED` events -* event String() -* linux: common FileEvent functions -* initial commit - -[#79]: https://github.com/howeyc/fsnotify/pull/79 -[#77]: https://github.com/howeyc/fsnotify/pull/77 -[#72]: https://github.com/howeyc/fsnotify/issues/72 -[#71]: https://github.com/howeyc/fsnotify/issues/71 -[#70]: https://github.com/howeyc/fsnotify/issues/70 -[#63]: https://github.com/howeyc/fsnotify/issues/63 -[#62]: https://github.com/howeyc/fsnotify/issues/62 -[#60]: https://github.com/howeyc/fsnotify/issues/60 -[#59]: https://github.com/howeyc/fsnotify/issues/59 -[#49]: https://github.com/howeyc/fsnotify/issues/49 -[#45]: https://github.com/howeyc/fsnotify/issues/45 -[#40]: https://github.com/howeyc/fsnotify/issues/40 -[#36]: https://github.com/howeyc/fsnotify/issues/36 -[#33]: https://github.com/howeyc/fsnotify/issues/33 -[#29]: https://github.com/howeyc/fsnotify/issues/29 -[#25]: https://github.com/howeyc/fsnotify/issues/25 -[#24]: https://github.com/howeyc/fsnotify/issues/24 -[#21]: https://github.com/howeyc/fsnotify/issues/21 diff --git a/vendor/gopkg.in/fsnotify.v1/CONTRIBUTING.md b/vendor/gopkg.in/fsnotify.v1/CONTRIBUTING.md deleted file mode 100644 index 828a60b24b..0000000000 --- a/vendor/gopkg.in/fsnotify.v1/CONTRIBUTING.md +++ /dev/null @@ -1,77 +0,0 @@ -# Contributing - -## Issues - -* Request features and report bugs using the [GitHub Issue Tracker](https://github.com/fsnotify/fsnotify/issues). -* Please indicate the platform you are using fsnotify on. -* A code example to reproduce the problem is appreciated. - -## Pull Requests - -### Contributor License Agreement - -fsnotify is derived from code in the [golang.org/x/exp](https://godoc.org/golang.org/x/exp) package and it may be included [in the standard library](https://github.com/fsnotify/fsnotify/issues/1) in the future. Therefore fsnotify carries the same [LICENSE](https://github.com/fsnotify/fsnotify/blob/master/LICENSE) as Go. Contributors retain their copyright, so you need to fill out a short form before we can accept your contribution: [Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual). - -Please indicate that you have signed the CLA in your pull request. - -### How fsnotify is Developed - -* Development is done on feature branches. -* Tests are run on BSD, Linux, macOS and Windows. -* Pull requests are reviewed and [applied to master][am] using [hub][]. - * Maintainers may modify or squash commits rather than asking contributors to. -* To issue a new release, the maintainers will: - * Update the CHANGELOG - * Tag a version, which will become available through gopkg.in. - -### How to Fork - -For smooth sailing, always use the original import path. Installing with `go get` makes this easy. - -1. Install from GitHub (`go get -u github.com/fsnotify/fsnotify`) -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Ensure everything works and the tests pass (see below) -4. Commit your changes (`git commit -am 'Add some feature'`) - -Contribute upstream: - -1. Fork fsnotify on GitHub -2. Add your remote (`git remote add fork git@github.com:mycompany/repo.git`) -3. Push to the branch (`git push fork my-new-feature`) -4. Create a new Pull Request on GitHub - -This workflow is [thoroughly explained by Katrina Owen](https://splice.com/blog/contributing-open-source-git-repositories-go/). - -### Testing - -fsnotify uses build tags to compile different code on Linux, BSD, macOS, and Windows. - -Before doing a pull request, please do your best to test your changes on multiple platforms, and list which platforms you were able/unable to test on. - -To aid in cross-platform testing there is a Vagrantfile for Linux and BSD. - -* Install [Vagrant](http://www.vagrantup.com/) and [VirtualBox](https://www.virtualbox.org/) -* Setup [Vagrant Gopher](https://github.com/nathany/vagrant-gopher) in your `src` folder. -* Run `vagrant up` from the project folder. You can also setup just one box with `vagrant up linux` or `vagrant up bsd` (note: the BSD box doesn't support Windows hosts at this time, and NFS may prompt for your host OS password) -* Once setup, you can run the test suite on a given OS with a single command `vagrant ssh linux -c 'cd fsnotify/fsnotify; go test'`. -* When you're done, you will want to halt or destroy the Vagrant boxes. - -Notice: fsnotify file system events won't trigger in shared folders. The tests get around this limitation by using the /tmp directory. - -Right now there is no equivalent solution for Windows and macOS, but there are Windows VMs [freely available from Microsoft](http://www.modern.ie/en-us/virtualization-tools#downloads). - -### Maintainers - -Help maintaining fsnotify is welcome. To be a maintainer: - -* Submit a pull request and sign the CLA as above. -* You must be able to run the test suite on Mac, Windows, Linux and BSD. - -To keep master clean, the fsnotify project uses the "apply mail" workflow outlined in Nathaniel Talbott's post ["Merge pull request" Considered Harmful][am]. This requires installing [hub][]. - -All code changes should be internal pull requests. - -Releases are tagged using [Semantic Versioning](http://semver.org/). - -[hub]: https://github.com/github/hub -[am]: http://blog.spreedly.com/2014/06/24/merge-pull-request-considered-harmful/#.VGa5yZPF_Zs diff --git a/vendor/gopkg.in/fsnotify.v1/README.md b/vendor/gopkg.in/fsnotify.v1/README.md deleted file mode 100644 index 3993207413..0000000000 --- a/vendor/gopkg.in/fsnotify.v1/README.md +++ /dev/null @@ -1,79 +0,0 @@ -# File system notifications for Go - -[![GoDoc](https://godoc.org/github.com/fsnotify/fsnotify?status.svg)](https://godoc.org/github.com/fsnotify/fsnotify) [![Go Report Card](https://goreportcard.com/badge/github.com/fsnotify/fsnotify)](https://goreportcard.com/report/github.com/fsnotify/fsnotify) - -fsnotify utilizes [golang.org/x/sys](https://godoc.org/golang.org/x/sys) rather than `syscall` from the standard library. Ensure you have the latest version installed by running: - -```console -go get -u golang.org/x/sys/... -``` - -Cross platform: Windows, Linux, BSD and macOS. - -|Adapter |OS |Status | -|----------|----------|----------| -|inotify |Linux 2.6.27 or later, Android\*|Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify)| -|kqueue |BSD, macOS, iOS\*|Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify)| -|ReadDirectoryChangesW|Windows|Supported [![Build status](https://ci.appveyor.com/api/projects/status/ivwjubaih4r0udeh/branch/master?svg=true)](https://ci.appveyor.com/project/NathanYoungman/fsnotify/branch/master)| -|FSEvents |macOS |[Planned](https://github.com/fsnotify/fsnotify/issues/11)| -|FEN |Solaris 11 |[In Progress](https://github.com/fsnotify/fsnotify/issues/12)| -|fanotify |Linux 2.6.37+ | | -|USN Journals |Windows |[Maybe](https://github.com/fsnotify/fsnotify/issues/53)| -|Polling |*All* |[Maybe](https://github.com/fsnotify/fsnotify/issues/9)| - -\* Android and iOS are untested. - -Please see [the documentation](https://godoc.org/github.com/fsnotify/fsnotify) and consult the [FAQ](#faq) for usage information. - -## API stability - -fsnotify is a fork of [howeyc/fsnotify](https://godoc.org/github.com/howeyc/fsnotify) with a new API as of v1.0. The API is based on [this design document](http://goo.gl/MrYxyA). - -All [releases](https://github.com/fsnotify/fsnotify/releases) are tagged based on [Semantic Versioning](http://semver.org/). Further API changes are [planned](https://github.com/fsnotify/fsnotify/milestones), and will be tagged with a new major revision number. - -Go 1.6 supports dependencies located in the `vendor/` folder. Unless you are creating a library, it is recommended that you copy fsnotify into `vendor/github.com/fsnotify/fsnotify` within your project, and likewise for `golang.org/x/sys`. - -## Contributing - -Please refer to [CONTRIBUTING][] before opening an issue or pull request. - -## Example - -See [example_test.go](https://github.com/fsnotify/fsnotify/blob/master/example_test.go). - -## FAQ - -**When a file is moved to another directory is it still being watched?** - -No (it shouldn't be, unless you are watching where it was moved to). - -**When I watch a directory, are all subdirectories watched as well?** - -No, you must add watches for any directory you want to watch (a recursive watcher is on the roadmap [#18][]). - -**Do I have to watch the Error and Event channels in a separate goroutine?** - -As of now, yes. Looking into making this single-thread friendly (see [howeyc #7][#7]) - -**Why am I receiving multiple events for the same file on OS X?** - -Spotlight indexing on OS X can result in multiple events (see [howeyc #62][#62]). A temporary workaround is to add your folder(s) to the *Spotlight Privacy settings* until we have a native FSEvents implementation (see [#11][]). - -**How many files can be watched at once?** - -There are OS-specific limits as to how many watches can be created: -* Linux: /proc/sys/fs/inotify/max_user_watches contains the limit, reaching this limit results in a "no space left on device" error. -* BSD / OSX: sysctl variables "kern.maxfiles" and "kern.maxfilesperproc", reaching these limits results in a "too many open files" error. - -[#62]: https://github.com/howeyc/fsnotify/issues/62 -[#18]: https://github.com/fsnotify/fsnotify/issues/18 -[#11]: https://github.com/fsnotify/fsnotify/issues/11 -[#7]: https://github.com/howeyc/fsnotify/issues/7 - -[contributing]: https://github.com/fsnotify/fsnotify/blob/master/CONTRIBUTING.md - -## Related Projects - -* [notify](https://github.com/rjeczalik/notify) -* [fsevents](https://github.com/fsnotify/fsevents) - diff --git a/vendor/gopkg.in/go-playground/validator.v9/.gitignore b/vendor/gopkg.in/go-playground/validator.v9/.gitignore deleted file mode 100644 index 792ca00d28..0000000000 --- a/vendor/gopkg.in/go-playground/validator.v9/.gitignore +++ /dev/null @@ -1,29 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof -*.test -*.out -*.txt -cover.html -README.html \ No newline at end of file diff --git a/vendor/gopkg.in/go-playground/validator.v9/README.md b/vendor/gopkg.in/go-playground/validator.v9/README.md deleted file mode 100644 index f5869664b3..0000000000 --- a/vendor/gopkg.in/go-playground/validator.v9/README.md +++ /dev/null @@ -1,139 +0,0 @@ -Package validator -================ -[![Join the chat at https://gitter.im/go-playground/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -![Project status](https://img.shields.io/badge/version-9.4.0-green.svg) -[![Build Status](https://semaphoreci.com/api/v1/joeybloggs/validator/branches/v9/badge.svg)](https://semaphoreci.com/joeybloggs/validator) -[![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=v9&service=github)](https://coveralls.io/github/go-playground/validator?branch=v9) -[![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/validator)](https://goreportcard.com/report/github.com/go-playground/validator) -[![GoDoc](https://godoc.org/gopkg.in/go-playground/validator.v9?status.svg)](https://godoc.org/gopkg.in/go-playground/validator.v9) -![License](https://img.shields.io/dub/l/vibe-d.svg) - -Package validator implements value validations for structs and individual fields based on tags. - -It has the following **unique** features: - -- Cross Field and Cross Struct validations by using validation tags or custom validators. -- Slice, Array and Map diving, which allows any or all levels of a multidimensional field to be validated. -- Handles type interface by determining it's underlying type prior to validation. -- Handles custom field types such as sql driver Valuer see [Valuer](https://golang.org/src/database/sql/driver/types.go?s=1210:1293#L29) -- Alias validation tags, which allows for mapping of several validations to a single tag for easier defining of validations on structs -- Extraction of custom defined Field Name e.g. can specify to extract the JSON name while validating and have it available in the resulting FieldError -- Customizable i18n aware error messages. -- Default validator for the [gin](https://github.com/gin-gonic/gin) web framework; upgrading from v8 to v9 in gin see [here](https://github.com/go-playground/validator/tree/v9/_examples/gin-upgrading-overriding) - -Installation ------------- - -Use go get. - - go get gopkg.in/go-playground/validator.v9 - -Then import the validator package into your own code. - - import "gopkg.in/go-playground/validator.v9" - -Error Return Value -------- - -Validation functions return type error - -They return type error to avoid the issue discussed in the following, where err is always != nil: - -* http://stackoverflow.com/a/29138676/3158232 -* https://github.com/go-playground/validator/issues/134 - -Validator only InvalidValidationError for bad validation input, nil or ValidationErrors as type error; so, in your code all you need to do is check if the error returned is not nil, and if it's not check if error is InvalidValidationError ( if necessary, most of the time it isn't ) type cast it to type ValidationErrors like so: - -```go -err := validate.Struct(mystruct) -validationErrors := err.(validator.ValidationErrors) - ``` - -Usage and documentation ------- - -Please see http://godoc.org/gopkg.in/go-playground/validator.v9 for detailed usage docs. - -##### Examples: - -- [Simple](https://github.com/go-playground/validator/blob/v9/_examples/simple/main.go) -- [Custom Field Types](https://github.com/go-playground/validator/blob/v9/_examples/custom/main.go) -- [Struct Level](https://github.com/go-playground/validator/blob/v9/_examples/struct-level/main.go) -- [Translations & Custom Errors](https://github.com/go-playground/validator/blob/v9/_examples/translations/main.go) -- [Gin upgrade and/or override validator](https://github.com/go-playground/validator/tree/v9/_examples/gin-upgrading-overriding) -- [wash - an example application putting it all together](https://github.com/bluesuncorp/wash) - -Benchmarks ------- -###### Run on i5-7600 16 GB DDR4-2400 using Go version go1.8 linux/amd64 -```go -BenchmarkFieldSuccess-4 20000000 74.3 ns/op 0 B/op 0 allocs/op -BenchmarkFieldSuccessParallel-4 50000000 31.5 ns/op 0 B/op 0 allocs/op -BenchmarkFieldFailure-4 3000000 556 ns/op 208 B/op 4 allocs/op -BenchmarkFieldFailureParallel-4 20000000 88.7 ns/op 208 B/op 4 allocs/op -BenchmarkFieldDiveSuccess-4 2000000 630 ns/op 201 B/op 11 allocs/op -BenchmarkFieldDiveSuccessParallel-4 10000000 173 ns/op 201 B/op 11 allocs/op -BenchmarkFieldDiveFailure-4 1000000 1350 ns/op 412 B/op 16 allocs/op -BenchmarkFieldDiveFailureParallel-4 5000000 250 ns/op 412 B/op 16 allocs/op -BenchmarkFieldCustomTypeSuccess-4 10000000 202 ns/op 32 B/op 2 allocs/op -BenchmarkFieldCustomTypeSuccessParallel-4 20000000 63.5 ns/op 32 B/op 2 allocs/op -BenchmarkFieldCustomTypeFailure-4 5000000 568 ns/op 208 B/op 4 allocs/op -BenchmarkFieldCustomTypeFailureParallel-4 20000000 87.5 ns/op 208 B/op 4 allocs/op -BenchmarkFieldOrTagSuccess-4 2000000 703 ns/op 16 B/op 1 allocs/op -BenchmarkFieldOrTagSuccessParallel-4 3000000 447 ns/op 16 B/op 1 allocs/op -BenchmarkFieldOrTagFailure-4 3000000 604 ns/op 224 B/op 5 allocs/op -BenchmarkFieldOrTagFailureParallel-4 5000000 353 ns/op 224 B/op 5 allocs/op -BenchmarkStructLevelValidationSuccess-4 10000000 190 ns/op 32 B/op 2 allocs/op -BenchmarkStructLevelValidationSuccessParallel-4 30000000 59.9 ns/op 32 B/op 2 allocs/op -BenchmarkStructLevelValidationFailure-4 2000000 705 ns/op 304 B/op 8 allocs/op -BenchmarkStructLevelValidationFailureParallel-4 10000000 146 ns/op 304 B/op 8 allocs/op -BenchmarkStructSimpleCustomTypeSuccess-4 5000000 361 ns/op 32 B/op 2 allocs/op -BenchmarkStructSimpleCustomTypeSuccessParallel-4 20000000 101 ns/op 32 B/op 2 allocs/op -BenchmarkStructSimpleCustomTypeFailure-4 1000000 1210 ns/op 424 B/op 9 allocs/op -BenchmarkStructSimpleCustomTypeFailureParallel-4 10000000 196 ns/op 440 B/op 10 allocs/op -BenchmarkStructFilteredSuccess-4 2000000 757 ns/op 288 B/op 9 allocs/op -BenchmarkStructFilteredSuccessParallel-4 10000000 167 ns/op 288 B/op 9 allocs/op -BenchmarkStructFilteredFailure-4 3000000 619 ns/op 256 B/op 7 allocs/op -BenchmarkStructFilteredFailureParallel-4 10000000 134 ns/op 256 B/op 7 allocs/op -BenchmarkStructPartialSuccess-4 2000000 687 ns/op 256 B/op 6 allocs/op -BenchmarkStructPartialSuccessParallel-4 10000000 159 ns/op 256 B/op 6 allocs/op -BenchmarkStructPartialFailure-4 1000000 1281 ns/op 480 B/op 11 allocs/op -BenchmarkStructPartialFailureParallel-4 10000000 218 ns/op 480 B/op 11 allocs/op -BenchmarkStructExceptSuccess-4 1000000 1041 ns/op 496 B/op 12 allocs/op -BenchmarkStructExceptSuccessParallel-4 10000000 140 ns/op 240 B/op 5 allocs/op -BenchmarkStructExceptFailure-4 1000000 1014 ns/op 464 B/op 10 allocs/op -BenchmarkStructExceptFailureParallel-4 10000000 201 ns/op 464 B/op 10 allocs/op -BenchmarkStructSimpleCrossFieldSuccess-4 5000000 364 ns/op 72 B/op 3 allocs/op -BenchmarkStructSimpleCrossFieldSuccessParallel-4 20000000 103 ns/op 72 B/op 3 allocs/op -BenchmarkStructSimpleCrossFieldFailure-4 2000000 789 ns/op 304 B/op 8 allocs/op -BenchmarkStructSimpleCrossFieldFailureParallel-4 10000000 174 ns/op 304 B/op 8 allocs/op -BenchmarkStructSimpleCrossStructCrossFieldSuccess-4 3000000 522 ns/op 80 B/op 4 allocs/op -BenchmarkStructSimpleCrossStructCrossFieldSuccessParallel-4 10000000 146 ns/op 80 B/op 4 allocs/op -BenchmarkStructSimpleCrossStructCrossFieldFailure-4 2000000 879 ns/op 320 B/op 9 allocs/op -BenchmarkStructSimpleCrossStructCrossFieldFailureParallel-4 10000000 225 ns/op 320 B/op 9 allocs/op -BenchmarkStructSimpleSuccess-4 10000000 223 ns/op 0 B/op 0 allocs/op -BenchmarkStructSimpleSuccessParallel-4 20000000 63.3 ns/op 0 B/op 0 allocs/op -BenchmarkStructSimpleFailure-4 2000000 1097 ns/op 424 B/op 9 allocs/op -BenchmarkStructSimpleFailureParallel-4 10000000 182 ns/op 424 B/op 9 allocs/op -BenchmarkStructComplexSuccess-4 1000000 1362 ns/op 128 B/op 8 allocs/op -BenchmarkStructComplexSuccessParallel-4 5000000 359 ns/op 128 B/op 8 allocs/op -BenchmarkStructComplexFailure-4 300000 6446 ns/op 3040 B/op 53 allocs/op -BenchmarkStructComplexFailureParallel-4 1000000 1203 ns/op 3040 B/op 53 allocs/op -``` - -Complementary Software ----------------------- - -Here is a list of software that complements using this library either pre or post validation. - -* [form](https://github.com/go-playground/form) - Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual Array and Full map support. -* [Conform](https://github.com/leebenson/conform) - Trims, sanitizes & scrubs data based on struct tags. - -How to Contribute ------- - -Make a pull request... - -License ------- -Distributed under MIT License, please see license file within the code for more details. diff --git a/vendor/gopkg.in/go-playground/validator.v9/logo.png b/vendor/gopkg.in/go-playground/validator.v9/logo.png deleted file mode 100644 index 355000f5247d50e979cf5db5de38188ef4649a34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13443 zcmbVz^LHiB^LK39wrv|5-`KWoTN~T9%?&s9Mte8f*xWeZ`~Lg^&kxU>)6-|>Om|IH zcUM=vsybFxSr!?A009gP3|U@IN*z>Z{#W2&KzAW<*L_e0I`lYd#@osT8GH952<>}$=#%H%txCM^!YLYIPG*~?*PoX}XfpXD#$r$vg% zUJ@M8Sa6}E0bs?J()q&Aj2!Xx^!*X7wf45!j09TZ!t8tmiZrhYa~rM!hkOgG3jNOL z$t%hsiEZp{`uZS=pUq3db%5@e>LpqUR%RzF4Fp&XYtszH3NMj(x&yBfN!B@dDe(i*$ zFaI9z`VK(*+SzZ3Km$V|gFS(NfPUS&ND}#zKM&MsZR;zy@SJwDwy5moK{eH84yz0`{Dhd+jynpps_Wzr*Rl)ctU%7jk!=>D(g}(sK zP}YV(B1|d_4NeR~4qlx?36qk5ng9u-wt+@fOTlvqhk>WQ%HxtjxBspSS(-6OpP;_x z73LX72W9oA=yUj&B*sjt0z}2U44ACNztdo!tbwR&pl8vCLjf!@HDwcP;p{h$JYsrk zE3Pp7L^A>!xwNPSX+2zrQgJ8|CCr11n`u|=C}{? zlHLN%{DxBD;+;&!6Se$BciUB@EQ~Y8_ZT-Q&4p}|A3l`R=AVR9Kt+V~a3a3V{l=)gHBK2op+X}BW7o(X1K2eRTZ^; ziO?#OmuWkXeCj2*{H(1C#qnQ>tz|Kq>*#cF7g)+?3G3(pVB@N37)9YHmYxa}CVb-% z@SHf5CnrEMiI6-&fkkOb9ema$%-Ld}qN54xNf|CDt?#e@Aec&IEcEEpu3Ak5Y z>0@s)b7yHEr~UCsek0JVuF%66MBgBxj-d!wQu4Evlx;p|pZG{&=4VV)*pIE{{f=SO z;V$)QC5ae=-6(Nc68{(S;2ymNVxIiwAs9}A@vA2?55kfV(qK>S6caF|bywd&p8ydL zB}xJ~6Di7u^Xl{s1E&b!{FXH0#>1$=MTNA7+vd;Pm*#B`iYRecX>5H7^iqDqQ{GQH zKNNh0?p}h?nEjh_Ft*^M`+(a;L*rKgPp=E!!}stvVxG|YKY=Yh25?+RloCoyT3T~2 zr1!?YL58}YTlyj1sTl_H(oBl48zJPwJFr9|r(>T7Npe$Hyl7Pm(dZ}|x;n!X(4wtZ zeNCCz4LTygy(gl;pV;dp+-Lpq=weiOW2Z_Lt@RNd_s43tZ>$@23^%6`T}rfexq!%# z)e|oR;kRY~2fW@V(in6QZzE*6TubN0<>|v2xiX)v6->d$no+&np8 z=DZPj>yPVL2Y2U^MJuW`R8R{2@Rg&}`S+$yEgsGihuW$3 z2y*A5Rm-TCh*xaY#R1q)HfzQS_%fPHCL7200}u=S#u`m zvW%z6F_UcmBq~g~s|d}v6$Q?noL`Z(X;@Q$i>kw^bF}I3A8QQyAE_nz-`H~a9o2}- ztPUs0q(DTZ^Yx3oA6C5I?{nHCX0qfW&C2r}h~~slhe!$_Hh1WB`w?_|D{JsF#zpgf z;F^yDTZs-$?`myzyDj@=x}@L4b~_KtUWzV+uiL${48Qh^ZdoywlRNR<*WLFY>v0fq zeWQS`g6{8q<#x){FrCbZlcTAh?+fw^gB-2LpRnlF^}`$D;(KxTOLn;dXs3Yl(uW$g6hyw3{wZdTVg|kdSet`n+SACG=!&%#r zl+Ha_MzD$G>iQb%tW~Uus7-zOMPI__Qo92dK3VKkGgR#;-!`uw++~l5J?MT+BUCv3 zcItfZO)uKXlipj1XD?F|>3frjQWA;$JV>TcHHrcrR=Ql;-B}Bb4;f|uVo(S7xL(QP zE%c8{bnchCJ%aG)3x8gx0`Hqq`eapfWqK`~Ec6Mea`v0{J?4~x(S2D#-7sMBR1X;{ zO-QlMUsyD!#jI^8v6y2J8TinHz_zsU@;3|?TfT0F2b2A7aX&aEQGc;IZ>UV*cToht z27rX9TA$h1ZMxk`KX|$6o$)=$PxIM3k^FhGmiJMaA3fBM6(M#efLJ9ucfbo2TkroP zxE4Dv?B_Nkef;0LYVj3nk|C9-MLv{y^-tY`SD(5phR2KMn}9@?I@SQ^#m* zu>9T8l>)311+yf)qc`Zp%3Cp9FS4PN18t5zZGy-!{f^5eJQA&Fb>Llf4kF^OZ}Tu z=jyadHyzlQLaf@_eAf{CFb}_v=Gj*BLc$VrMAe%hAL@6JaXkt^p&>`#SXjBAX!3#; zZ(sPdwtkoS08=HP@lruhHm*fIlu{y~LTu@+@;u*LBUU~nbQ7S{eH09xc5^_Xtu!q@ z6^P#P!A-(qwW30Th;TBWNp{b1+lP1D!2Y2In`HJ8=DTs8;1)Y~TE2Tco&agHaJGJRtE&{R2y^@Gnpny|$qxXc2=Ps$@$~9mxET{1Q$%i!i#frlzo0UOe_Y zMxNvLk98G99Jhl+-rMB_{OyQsE?70nTDUTZf%>P_;7WAz0a+FG*4EALUD*p3UWt_( z3yZrIM%L#2dleC=K}bD*)-@4195ctqtgM0iQACxJ?F&0O<{t?%^dK1pMJo*-dHj;E z%Vt=-^pa?Z(eb%_rx~$m@yuyvX^t!IvZZ&&LJtY`#;x+PXT-Gb~(3>gv;tf~4N37#aCX z-tW%A@AM^Cf&WBJl*|wp9s0RGq_rCL)=Klfe3e8BUY|7FGZM)#ZdT04zyZ#{*|<&8 z+dsxt9B+krqDfJbykPO==|6C|yAi)*jkV&C{Du7Y#drV0`{jGeFSFOANIz#B-ncz= zB?v}IR2j5eCJ`2>yNMN9<}h!(e$i><|KSPd(Ff^lC-7pg&G~QJ8T0JD-37gq1-K+V z;1?GW_CVrGX3V0m%yvW#+uGLl^01=9zyGrgZ5fJ6GeeULS25^4)YCL=-Z!w`r$tH= zj-ikdG|nI;y1wvvk2)h7^hL0Xvnxw)Y1u}&9Vv%k1};Z0IqW?AQ8)B@QOUa?ayt31 zX^`u?pa(0F6YpbrT;e2^auw#%0BX_ub?}_ieYF;4rGRd*1_vX-+Xv9I&yR@ zZF(3;`kXg0vHdTn$5Ie;gpS4@djPPJ60-Z_1?!DwQz9NO2jKDbkZ^oJbQVc?6v#&0 zAW|kWVx3>tw#eTFT> z$S^|&ZWo)7Lyes7r)@VL=2A|$JW1nr)ed9~F&(_uHC1f;YO_5oj&Afj!0(9M)7c*f z$rra8Ji?1Bc%e|v^CcS{(B7RRCc7Wrrs=I7)f#8IE{rDM)o~`?Y8!;pSaL!lLHCZ% z2RHV1+l?QSk}_AkH)`_s#(xKJ?jwKC`csy*aOGtV&`hmHIG<5hXtzm+=iQkb{pyZ< z%;RxAP~z<%lTo;vNWd4mn;*jW+1tVM*tJ0j)}5|LR4#M7r{PkXJaW;yHBr@9pIuiG z8V1M4Ci1&Z6T1I>(C@#6rJT=}4_MR%kp=0LFD)iInpDCFQ;rm ziA+yF-c%|NyQ8);!vM6)#xu8qylq9(nieBl!@e}S5}R@)8LEU)Q|o0z)Z3vP);l2n zvCG7gtlR2XtjF1}fhC?!r{BZ4#sNRJi-Kgt?Rd(rePR;wmE}rqM-z^#fA_=ptrRR~ zqS-A)prf=s19gdfPBn?#&j;!a+e1!wX7|RMt|@0KQ_^z7My)2imN}+? z&Ro$-#EC#FN(11}WJ|$X)eQ0hf7Xye3AhvowX$0|1+x+uY~g?ccTKswq+io;vFNd6 zr7#C9z4;>@b-tg$UzV@9U5hK{mDW{6%YjDa>FJu9Z8hZyN}pshPN=W>uI!^Q$kMqm z+}IiQA9sdYvoB1IiBfX#m0axM;6c8}N>K$tD8kW56>r1h5t8J!3X0YAj1|Aw&~l@A zxf2^V`F;A0W?i!7*yQ+#;?4!!1ZQrBEI$9+-N z6P_sTrV&}s7MX}77Nq}~KmQy&5T&0ZWX--y(<$MEOLGIm!7k)jQOWggN0!Rg^`Bj3z7;;PquhhFnoqJeAbUfHR~d2;C{_De_Ogp81i65*qU(X5fweyv+B#w>RW0 zm&_w7Zm z`YWfGxm^7MK^A>0nDITy;gz^Lzudv@BC>+^JOVExD%|?aa0W#9qe``&CHjF6vqV zB8&tSqdhz{r4(|w3!g-DZKg>^k=!a74kk`D{P(2>&R~8kXP)^Ns3jTlnM7|b=I@?W z*3YW^eW^H83@t)lUE4LAm#(ICbAZTgW?ohHU;Ok91QJvMGp6fHL|&TQb|ICaXi{OO zrD__`B5>e)a6orX^!P5CsJZqQhI9-E6v4*!cC1vUi2?G|44quG+rfLS+7ZX;meFoT zMa+fb0pH+x{|o<7L^;cM5J4}K*7m~l#N2_qa(YL%G9rt7(fo;z(CaJOODkCKPA9`Bop?dIYFl3wBU&l zdqN~tz4k#i1&+HT_N>0Qm%uxG;}xqfaciIXXK|67VNTu0yzMz6pt6)m~ z7y^EZ+(wMlK9yMiwkhp&>cmXQoRzGf`o{MmkrGaxJY*%s0Dza_WczOvC8IXtY4zGE zoAfaSy~MQoF^;l5RWb}DJq*S_&wp|_lkCAaR~iQkooeXo>yX+1hRw(?%#&k0 zm|IG1?>%mpBmLr(*DC>|Vr>bN;nKsdZLlS4*_h%G1n`;;6|sE0rg^T9KG)Swoz!z& zJra776~H1@daS@C;jzI*0~;x5(E1Fpo!nLAV=SmM;Q>*#bxdaC<;wO{!IV4ONwN}f z8NK=|T>UjQ5%%_C3KAVb1}wC~Feno-GH|l>&?HI*RX~t*0XtJ~S0R6Kst$kD*7mw& z{mR31-KopNO5bKJqku0*PjnBKFE_1y_|tmDtiN7SF!NZpwNb5#sV6w^bu9#1B5K7# z0N}))422cqc#^(uW?wJU*^KLe?VU&(*c6j;U6^LZcQoK4POU1{yKSH^?k2$VGLEWB zog!7!3_Kl%apr)=%d3Rpw_4BDLZf!1tIdN&D;Yg?X2&jp0vSBqbz)XX`Wu2%`IWJS1s3lhZ7H--?PJxQLg$XONw$8qE z@4G(S5}8yFwM`{Rdz9E__ZH{{Gusj%$t#w4+ac&G3wkM0n&qZPP}J9r*av-Zq- z%NdhH1sgs~Oq9{PLkkxDiK6MQo36OTZrr&F7k6+F*a}5hV<;1u+B`QQSF#ti5`pI3 z@gvRFovLjNAri8~54co-plD$yQSX*b95r9t@B%~eI2r9NqXw{mGRKtdG5*|wk~yO zW)?msL*Rlpy{X4OLKx;RTX5`t1RY4!(bJ`a7rJ?=xM7fwcCL;k7j%-*cj9NLfbojM= zsFk;>hWcz(m*MFBO66YXrs>D4!BqdqWy_oZ>c&}P@|L*1a zVk(-?<3wy?;t9XLM*dyTj^XbicaVIM%BJouomO8jaqzV51LbTf>Ywq=#cXFtO*-oC z$O(ezf}G*);p^d{5Cc9apUxWE7RHp-F$ne9h?~C!5ok6%glp3JFOLJd2A-Fm@I}Id-s z30mMGUBh}2LTd&+z4*b8fB8hNy+ke`kmJbFXYm9=Ud96znCvs;Xa*GB`{*jEPp($~+DX+RP*)$prD03Z~ zot>}r&YE}7>5Wkie5E(*NC^ihU`EdF6Ezw%Y_=C72{{2}2gipm z*Kp)Aa`c2J&xYYZ876z^z{Zt5pR2|?72(fT&g8MYt4OgJ8>+ZDr_oB=>9xhEw%27Y zdZWI$a9GrD@5Los+iFbyl507c-TMRH3x)MMT{uczOKy3!ra7;z>2})#CRqJW`Jr@s z)uA36KCgr8c)q);G>N2B3p4kyV4NWuoxzls;Xqq+eg~fI$A3otuea;KAQGd#L@`_H zA12vy0BVLhln8XMstlX5M43pjjcZzAO3GUc$zV-2^wq;7JE(EwPLoa!*2(XgxwSlx z2_J0xvN3`hnHWW^kuO7z`%AW8B~t4yhgSPHzS%y%$=}V7s+fZJ0#{k0^O+*L0|Zg4 zfX#xMrgl!s6Xo=iNk_&jq83fy!YAvDSuT8GO6%m58Pi*2YUR|;TQb;TdN=rqTpKIZ z-p&;$N{lIA6N##--%mV~CtEEa4=)@J`4YoT@$9}xH&qcX>lvW>wj*s%n1(JbS$r*d zK9ca~LMdTQ7v!Y34Q6Zh;50&tLX-E@$j3m@9%{iLEyrjeeM_lyMFuI6_pPMcUemdp z%6;iM!PP84B5GQ70B|+R^|BqipYC7_%BZRXP;eo#KZ6EBvBzlpn}@P3p}|8#I(4 zul0x<>TxI(s0g?8v|a89+n1)Jx##kH*g@FY*niUw?{Sqmm)Xi-;WBKlUieBT&& zR3bfdZ|yI{!e~+H2q@uF@=N3k*$H|RZpj@5hvmw~_Py+wV14-k8ynOVi-{@1gB;!g zop(C8F2W!)$gD|@VYtF3M2`gl44ny?45baF7yCBl4PB@{E_nNFz6{2b zr3nxXdd~S*FLLzzO#wytqw(3PI0_%D56fEkMQPca=JX$gqH9aJ{ZpKvk8&kz zVxpVpl56nj^P5R4Lm_KK_6WeFW0cD?IY zZu%H?$YfA5eBYF>2g^}+ig>LD^PgW_C#jRJ$|LNXlubK_b)pT9uqy)nlg?;4DG*(P@1w56aN4^TZM6bWUyCM1*1Czy}HIA#1w25=*y73 z^<0dmnQg(qFmL~t3lPYXx1H8~Zxg@d(x{4t40F=4{->PSRp{RzUszJHDlXejc7G)lY;8~fKsU-hk(590&9v& zFxr}ZKJqco?V2qb5bnkeLoQVbyu32=?$Kwh?;N0OiGN|7=6`RkdoJ(JT@djZ8dUCb za?z#~&v8Fm?V}L${Zr&aQ8JC0EF>X56u4pkjt-w^+1bG$r9f1OrJ$<6qE&iV7_}kN zQweT&?sbJOanV*#E0|bLjkCC(vOm|{V<5MsimhiSt-uxzjxz9SMUvMQK{`~RZ+v_m ztb%l8kCZHm@?oa?Mb$L;Bv2$(K*V=w5SD>$*ITQ!W*n%SOXJlQO>pLoRxLI#%aHpA zmYUE<8T)d$P6F=j$+`7W&dSV^FR;c5cvU=igm6$Q0Bz?EE|?msF@JEX89DoMOUuTr z`R{3)%|h-VtA7`wTgs8)s;PQ6$6IvQTsUzrO=Y6G!D)=Xx9w0$Gba6n1y?{dK@SoK ze54vzFH|9D2~QbpUTb_H)IYDfa|J}Lq9?%CFHbsIB8(vc1WUKbA`4uL=6b&iurle2 zi(4jg{2hA5K*7uKNnBA0KV4x*3NO0jb^QuEWV&39?%#Ve9aEQ)AWUUwycBSf_o%|` zTcm^fRU(B}U8I(N*#z&8fsGAkKpBAt5@UnRa>N{07@%qaw@bs$K2R5VP#c$2^Q%RQ zVuW0slT(*~U8kk?duR;_jOTpmwrrbx->n}JX^_|@zO|a)Ik@>X7HOQ(!z(#CF@`^7JGf2aEfn1S0v}oHKo%uVUMDjl3<>f#kD$hfw(^nW(aRB6AaG-TDAh%oHjEJ=J$;2s zNEtTUsuZa{ji(_8)1j8gUOb~B9fXBSc)M%Hfsu<`&aJGt{{#rePUQ zno1K;1#~H`?Rd#V$}MtvkS~UOgsP~@^u^u{ua{D3V=Fa{2IKwI7>|!cOUteP#X!Z_ z0=9Z(Y!#lhZpJ0TKxMl6%R?6~lt!EvNztb>dbADO5-ZkYS1f(TlqF6|c^Euh&Dojz z>7lTs0ClkTp5>|*~0 z_E{QdSna;}KOcu@*xbF3xyhffB&XIT`p{6hS*F))v#>=YEtJB9Cr*b2YtK$qd9@hS zP$+_%N43)URxgAF_fx!4#yRV$Y6W06mtQ<`6RwW>A*AaHVyEylR` z2)a@71;tKHeL9Ik*CB!~)Qw;=Fl6gGLG;?;LTeerep>@XsgVh4FN73z`?Z=yj9;v% zBxr{}l;h6)J_enD_Xs$w_!zAMpK(;B2{L7;9924=)DeQQG^=eR>S_sq&5Q6tF?!ZR z5Qknd!5HirCsnTIK}aSQLQ_)EQtb#JSG@QUVD}mpOr(idOXutsza|QP5K1WjdsWrs zkY855Sph`j8nzw^f)v# zwC?)Bwo9-}lWq~G9ow>)3->q?FnXQ<$)Y*Vq?hu8MmH8aL1yGrPXCBBQZxc2c}gM_ zazx&=nWtc(!DSU&y7M>VVWHK|f42Z4$ zgM>V`3TB$s+ZXAeFq65x>B{Mdc~^YySq_px;%mpmr2Huz$C}=8-KJN$50%RxgBJ`5 zP&~~O#I1B_1NXRe11=!ZG+8?m1fW)N1v3M~LuJCB_sLZ){E+CtNyJ{zEW!m2t6~4F z%H681*4phFkdH+Wb0LC&2rz`YF05QDpj#b^CS9c1iNN6yizQhsjIRb7ouDlN!>cKa zg7n0;K8z}XHxXi2Ecua32b&VylFo$*L~5$eud(~1>99o0y8R!-= zN_$<&9xytjEu>6segSMd2}6=@3VVB@GhvK>e5(3kr&=sV&}-F69b-m9?Ip^S&_1rK z)REQFT(LR2P6B9EqR$$Fjhw z@@PRbM9s{1I>jgtQ$A{Too_2xnL(GQD!IAjpSUUis4yB{sY$2}MT}d+!IfS_pu32*B z(%fM}`E)&K1vl5$L@*MaDwYf>96D4c;kb|PKTS;+YgrY9Ko@0Q)3$VlDZzF2D5qzp z3ooIC#iZNaZ8P4)aA|hlnC{a}TPrb~vTu2a+lFss)C;W1zZ926mndG{GXR|B)WfV} z(w*ugyn0Rs7_}^z1)X+M+)NXwrEUSMFwNFX_HD7RuV z!p-X54t?QhInx8)RxXg9Gk>_MaF-=XqAoa3dpy^>ZnMr+Cdt={MR4L zlI?2b=gsG3&Ijqpwy~pkv)Y=9n_|E|4ghMbhOV!U-CR;Kg+YdeFwVdfiyc*SZ33P= z$^Lo3LKgdGzEro#sbQm;1h}cbE=gD;VPV$RSAC(NX#P3$r*wNcQV1ac_8s?7<*v7Pd5{UE zcj<@b8s(}ugB+l6X(Y2RciZYZr@$lnh&EYVD&Q;@IV#m~)&N`>i%eC8QGg&uMXI=s zQLp~@6So9V;*{|ZngyWwRLWwzOCrXEh&`MazZ2wm)kNAKFDMMTX_jGA!oO_hJ-YRa z$^tLI^PHPVUu(o9eNPBKBkY8oY*JvIpawcN$Hq>rF`BD0kq%ngOwjI!^ei&^{U1>= z!^&Yoa|y-vSLjPKIP(7C?$zHcE6TomiB6zAM~x|S=v76w%>=hQ$rVordZSPGH_r!u za~NE4L)9W;Zi;ur8=N=;g2x`9ew-T?zd44CWDowkmcCKC2ZEkwyy{Cgf?DBwA)VTz zfJ;~J*q-_{>l2=#Z#w%BHa5yiZUb#89mRN|$!s*X41Sj}m@%Y%D8!j#oex}HpuLkT zi_70a875WHbj(&5q=Cb3*-Fn-b_=@DxVxh?M%~C#aO%I9A zfDhFlS)5h5m^sgc`qgo&LB;4CbJ+4Do$EQJL-i45cQ|%b4D${*iHS6$Z!lFja4{Z& zm_cQ;+$jmX_Ipjb?|qoQbz3TEQd@UgHO-t8i&2#uH*%Y+@t8HptKD;^>9mRb|w53r?9PIIfP$v|io_ z*cIdNpF96_?%r4O-CUdtgPsVgQ7~>`(Iv=~Vz&=N0I0@6UyQtkp156a;eRI#QPSg> zAcDjr+gD33>K!@@N;gSJr1%xowp?n{?=lK{fWo0V0xrMs(WD=)!hLrQ-FS z@!mYs_Wz~@&+paJijML41V^ce^;23KtbY_xNJKz@7&zTeFEoHm7;$(UI=YQFs#$@ptk!EQ42Y4FfxEf@TOsVt37 z}4AVbnC9Ri){mLjd@o@_vA;wzpV8G_ypN3Y=M08M6ZfM2Xtkpu^=A9}u!A?A z)0NYU%Y#TSSE#tnm?KTmo4 zd|UY(Tqjl;m?`7^R${$QG*ZIW=)p?(%lWYXyf8k9{rdP=)z$ty1cAPSJfgXTOPXN1 z^D-Pknjk$jWsP@0+o&sn#8=lA=)a-i-j|YE5DwZ9s#vk3w-c?}%C?C;Q@<(1;-i>L zl}SN#MAX*71GGR14&RiPaHe@3srrMMPYHjml+|aGSDU_fRi{h1_NlT;MHYR@D(IR3 zt6;N#m)Tdz?)V=$7s!&Z;ZdmJFd0m>InR~Umqz^)eM=coLx(q4tw%~Z0U73ho^=Mj zF)fREGIOlh6`*ARYk?K%ir!a_Yvw9snW){J#zyP<3!#qD8Q_2~d|so+(Xc54smil}_4kGqEK^l7mVKQmM+ zBR70H=a2QXGB!3jg`P(Kg~lE^KQr-y_EVJi%}cMMzb+f?)6-|yp{QzpZdk)-9EhXzQpEZ(ZuvkddnL`d4Y{JQ>J+Eg}}BSGkUqgbqYuem+;8++@MM(|;Eh?pTI_O&4Gy6PBOnIB)^cWfo! V^Rh-@K?jDw updatedAnnotations = 2; - - // The config of this deployment rollback. - optional RollbackConfig rollbackTo = 3; -} - -// DeploymentSpec is the specification of the desired behavior of the Deployment. -message DeploymentSpec { - // Number of desired pods. This is a pointer to distinguish between explicit - // zero and not specified. Defaults to 1. - // +optional - optional int32 replicas = 1; - - // Label selector for pods. Existing ReplicaSets whose pods are - // selected by this will be the ones affected by this deployment. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 2; - - // Template describes the pods that will be created. - optional k8s.io.api.core.v1.PodTemplateSpec template = 3; - - // The deployment strategy to use to replace existing pods with new ones. - // +optional - // +patchStrategy=retainKeys - optional DeploymentStrategy strategy = 4; - - // Minimum number of seconds for which a newly created pod should be ready - // without any of its container crashing, for it to be considered available. - // Defaults to 0 (pod will be considered available as soon as it is ready) - // +optional - optional int32 minReadySeconds = 5; - - // The number of old ReplicaSets to retain to allow rollback. - // This is a pointer to distinguish between explicit zero and not specified. - // Defaults to 2. - // +optional - optional int32 revisionHistoryLimit = 6; - - // Indicates that the deployment is paused. - // +optional - optional bool paused = 7; - - // DEPRECATED. - // The config this deployment is rolling back to. Will be cleared after rollback is done. - // +optional - optional RollbackConfig rollbackTo = 8; - - // The maximum time in seconds for a deployment to make progress before it - // is considered to be failed. The deployment controller will continue to - // process failed deployments and a condition with a ProgressDeadlineExceeded - // reason will be surfaced in the deployment status. Note that progress will - // not be estimated during the time a deployment is paused. Defaults to 600s. - // +optional - optional int32 progressDeadlineSeconds = 9; -} - -// DeploymentStatus is the most recently observed status of the Deployment. -message DeploymentStatus { - // The generation observed by the deployment controller. - // +optional - optional int64 observedGeneration = 1; - - // Total number of non-terminated pods targeted by this deployment (their labels match the selector). - // +optional - optional int32 replicas = 2; - - // Total number of non-terminated pods targeted by this deployment that have the desired template spec. - // +optional - optional int32 updatedReplicas = 3; - - // Total number of ready pods targeted by this deployment. - // +optional - optional int32 readyReplicas = 7; - - // Total number of available pods (ready for at least minReadySeconds) targeted by this deployment. - // +optional - optional int32 availableReplicas = 4; - - // Total number of unavailable pods targeted by this deployment. This is the total number of - // pods that are still required for the deployment to have 100% available capacity. They may - // either be pods that are running but not yet available or pods that still have not been created. - // +optional - optional int32 unavailableReplicas = 5; - - // Represents the latest available observations of a deployment's current state. - // +patchMergeKey=type - // +patchStrategy=merge - repeated DeploymentCondition conditions = 6; - - // Count of hash collisions for the Deployment. The Deployment controller uses this - // field as a collision avoidance mechanism when it needs to create the name for the - // newest ReplicaSet. - // +optional - optional int32 collisionCount = 8; -} - -// DeploymentStrategy describes how to replace existing pods with new ones. -message DeploymentStrategy { - // Type of deployment. Can be "Recreate" or "RollingUpdate". Default is RollingUpdate. - // +optional - optional string type = 1; - - // Rolling update config params. Present only if DeploymentStrategyType = - // RollingUpdate. - // --- - // TODO: Update this to follow our convention for oneOf, whatever we decide it - // to be. - // +optional - optional RollingUpdateDeployment rollingUpdate = 2; -} - -// DEPRECATED. -message RollbackConfig { - // The revision to rollback to. If set to 0, rollback to the last revision. - // +optional - optional int64 revision = 1; -} - -// Spec to control the desired behavior of rolling update. -message RollingUpdateDeployment { - // The maximum number of pods that can be unavailable during the update. - // Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - // Absolute number is calculated from percentage by rounding down. - // This can not be 0 if MaxSurge is 0. - // Defaults to 25%. - // Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods - // immediately when the rolling update starts. Once new pods are ready, old ReplicaSet - // can be scaled down further, followed by scaling up the new ReplicaSet, ensuring - // that the total number of pods available at all times during the update is at - // least 70% of desired pods. - // +optional - optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxUnavailable = 1; - - // The maximum number of pods that can be scheduled above the desired number of - // pods. - // Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - // This can not be 0 if MaxUnavailable is 0. - // Absolute number is calculated from percentage by rounding up. - // Defaults to 25%. - // Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when - // the rolling update starts, such that the total number of old and new pods do not exceed - // 130% of desired pods. Once old pods have been killed, - // new ReplicaSet can be scaled up further, ensuring that total number of pods running - // at any time during the update is atmost 130% of desired pods. - // +optional - optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxSurge = 2; -} - -// RollingUpdateStatefulSetStrategy is used to communicate parameter for RollingUpdateStatefulSetStrategyType. -message RollingUpdateStatefulSetStrategy { - // Partition indicates the ordinal at which the StatefulSet should be - // partitioned. - optional int32 partition = 1; -} - -// Scale represents a scaling request for a resource. -message Scale { - // Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // defines the behavior of the scale. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status. - // +optional - optional ScaleSpec spec = 2; - - // current status of the scale. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status. Read-only. - // +optional - optional ScaleStatus status = 3; -} - -// ScaleSpec describes the attributes of a scale subresource -message ScaleSpec { - // desired number of instances for the scaled object. - // +optional - optional int32 replicas = 1; -} - -// ScaleStatus represents the current status of a scale subresource. -message ScaleStatus { - // actual number of observed instances of the scaled object. - optional int32 replicas = 1; - - // label query over pods that should match the replicas count. More info: http://kubernetes.io/docs/user-guide/labels#label-selectors - // +optional - map selector = 2; - - // label selector for pods that should match the replicas count. This is a serializated - // version of both map-based and more expressive set-based selectors. This is done to - // avoid introspection in the clients. The string will be in the same format as the - // query-param syntax. If the target type only supports map-based selectors, both this - // field and map-based selector field are populated. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors - // +optional - optional string targetSelector = 3; -} - -// DEPRECATED - This group version of StatefulSet is deprecated by apps/v1beta2/StatefulSet. See the release notes for -// more information. -// StatefulSet represents a set of pods with consistent identities. -// Identities are defined as: -// - Network: A single stable DNS and hostname. -// - Storage: As many VolumeClaims as requested. -// The StatefulSet guarantees that a given network identity will always -// map to the same storage identity. -message StatefulSet { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec defines the desired identities of pods in this set. - // +optional - optional StatefulSetSpec spec = 2; - - // Status is the current status of Pods in this StatefulSet. This data - // may be out of date by some window of time. - // +optional - optional StatefulSetStatus status = 3; -} - -// StatefulSetCondition describes the state of a statefulset at a certain point. -message StatefulSetCondition { - // Type of statefulset condition. - optional string type = 1; - - // Status of the condition, one of True, False, Unknown. - optional string status = 2; - - // Last time the condition transitioned from one status to another. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 3; - - // The reason for the condition's last transition. - // +optional - optional string reason = 4; - - // A human readable message indicating details about the transition. - // +optional - optional string message = 5; -} - -// StatefulSetList is a collection of StatefulSets. -message StatefulSetList { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - repeated StatefulSet items = 2; -} - -// A StatefulSetSpec is the specification of a StatefulSet. -message StatefulSetSpec { - // replicas is the desired number of replicas of the given Template. - // These are replicas in the sense that they are instantiations of the - // same Template, but individual replicas also have a consistent identity. - // If unspecified, defaults to 1. - // TODO: Consider a rename of this field. - // +optional - optional int32 replicas = 1; - - // selector is a label query over pods that should match the replica count. - // If empty, defaulted to labels on the pod template. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 2; - - // template is the object that describes the pod that will be created if - // insufficient replicas are detected. Each pod stamped out by the StatefulSet - // will fulfill this Template, but have a unique identity from the rest - // of the StatefulSet. - optional k8s.io.api.core.v1.PodTemplateSpec template = 3; - - // volumeClaimTemplates is a list of claims that pods are allowed to reference. - // The StatefulSet controller is responsible for mapping network identities to - // claims in a way that maintains the identity of a pod. Every claim in - // this list must have at least one matching (by name) volumeMount in one - // container in the template. A claim in this list takes precedence over - // any volumes in the template, with the same name. - // TODO: Define the behavior if a claim already exists with the same name. - // +optional - repeated k8s.io.api.core.v1.PersistentVolumeClaim volumeClaimTemplates = 4; - - // serviceName is the name of the service that governs this StatefulSet. - // This service must exist before the StatefulSet, and is responsible for - // the network identity of the set. Pods get DNS/hostnames that follow the - // pattern: pod-specific-string.serviceName.default.svc.cluster.local - // where "pod-specific-string" is managed by the StatefulSet controller. - optional string serviceName = 5; - - // podManagementPolicy controls how pods are created during initial scale up, - // when replacing pods on nodes, or when scaling down. The default policy is - // `OrderedReady`, where pods are created in increasing order (pod-0, then - // pod-1, etc) and the controller will wait until each pod is ready before - // continuing. When scaling down, the pods are removed in the opposite order. - // The alternative policy is `Parallel` which will create pods in parallel - // to match the desired scale without waiting, and on scale down will delete - // all pods at once. - // +optional - optional string podManagementPolicy = 6; - - // updateStrategy indicates the StatefulSetUpdateStrategy that will be - // employed to update Pods in the StatefulSet when a revision is made to - // Template. - optional StatefulSetUpdateStrategy updateStrategy = 7; - - // revisionHistoryLimit is the maximum number of revisions that will - // be maintained in the StatefulSet's revision history. The revision history - // consists of all revisions not represented by a currently applied - // StatefulSetSpec version. The default value is 10. - optional int32 revisionHistoryLimit = 8; -} - -// StatefulSetStatus represents the current state of a StatefulSet. -message StatefulSetStatus { - // observedGeneration is the most recent generation observed for this StatefulSet. It corresponds to the - // StatefulSet's generation, which is updated on mutation by the API Server. - // +optional - optional int64 observedGeneration = 1; - - // replicas is the number of Pods created by the StatefulSet controller. - optional int32 replicas = 2; - - // readyReplicas is the number of Pods created by the StatefulSet controller that have a Ready Condition. - optional int32 readyReplicas = 3; - - // currentReplicas is the number of Pods created by the StatefulSet controller from the StatefulSet version - // indicated by currentRevision. - optional int32 currentReplicas = 4; - - // updatedReplicas is the number of Pods created by the StatefulSet controller from the StatefulSet version - // indicated by updateRevision. - optional int32 updatedReplicas = 5; - - // currentRevision, if not empty, indicates the version of the StatefulSet used to generate Pods in the - // sequence [0,currentReplicas). - optional string currentRevision = 6; - - // updateRevision, if not empty, indicates the version of the StatefulSet used to generate Pods in the sequence - // [replicas-updatedReplicas,replicas) - optional string updateRevision = 7; - - // collisionCount is the count of hash collisions for the StatefulSet. The StatefulSet controller - // uses this field as a collision avoidance mechanism when it needs to create the name for the - // newest ControllerRevision. - // +optional - optional int32 collisionCount = 9; - - // Represents the latest available observations of a statefulset's current state. - // +optional - // +patchMergeKey=type - // +patchStrategy=merge - repeated StatefulSetCondition conditions = 10; -} - -// StatefulSetUpdateStrategy indicates the strategy that the StatefulSet -// controller will use to perform updates. It includes any additional parameters -// necessary to perform the update for the indicated strategy. -message StatefulSetUpdateStrategy { - // Type indicates the type of the StatefulSetUpdateStrategy. - optional string type = 1; - - // RollingUpdate is used to communicate parameters when Type is RollingUpdateStatefulSetStrategyType. - optional RollingUpdateStatefulSetStrategy rollingUpdate = 2; -} - diff --git a/vendor/k8s.io/api/apps/v1beta2/generated.proto b/vendor/k8s.io/api/apps/v1beta2/generated.proto deleted file mode 100644 index 5d11cbe8d8..0000000000 --- a/vendor/k8s.io/api/apps/v1beta2/generated.proto +++ /dev/null @@ -1,752 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.apps.v1beta2; - -import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1beta2"; - -// DEPRECATED - This group version of ControllerRevision is deprecated by apps/v1/ControllerRevision. See the -// release notes for more information. -// ControllerRevision implements an immutable snapshot of state data. Clients -// are responsible for serializing and deserializing the objects that contain -// their internal state. -// Once a ControllerRevision has been successfully created, it can not be updated. -// The API Server will fail validation of all requests that attempt to mutate -// the Data field. ControllerRevisions may, however, be deleted. Note that, due to its use by both -// the DaemonSet and StatefulSet controllers for update and rollback, this object is beta. However, -// it may be subject to name and representation changes in future releases, and clients should not -// depend on its stability. It is primarily for internal use by controllers. -message ControllerRevision { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Data is the serialized representation of the state. - optional k8s.io.apimachinery.pkg.runtime.RawExtension data = 2; - - // Revision indicates the revision of the state represented by Data. - optional int64 revision = 3; -} - -// ControllerRevisionList is a resource containing a list of ControllerRevision objects. -message ControllerRevisionList { - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is the list of ControllerRevisions - repeated ControllerRevision items = 2; -} - -// DEPRECATED - This group version of DaemonSet is deprecated by apps/v1/DaemonSet. See the release notes for -// more information. -// DaemonSet represents the configuration of a daemon set. -message DaemonSet { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // The desired behavior of this daemon set. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional DaemonSetSpec spec = 2; - - // The current status of this daemon set. This data may be - // out of date by some window of time. - // Populated by the system. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional DaemonSetStatus status = 3; -} - -// DaemonSetCondition describes the state of a DaemonSet at a certain point. -message DaemonSetCondition { - // Type of DaemonSet condition. - optional string type = 1; - - // Status of the condition, one of True, False, Unknown. - optional string status = 2; - - // Last time the condition transitioned from one status to another. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 3; - - // The reason for the condition's last transition. - // +optional - optional string reason = 4; - - // A human readable message indicating details about the transition. - // +optional - optional string message = 5; -} - -// DaemonSetList is a collection of daemon sets. -message DaemonSetList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // A list of daemon sets. - repeated DaemonSet items = 2; -} - -// DaemonSetSpec is the specification of a daemon set. -message DaemonSetSpec { - // A label query over pods that are managed by the daemon set. - // Must match in order to be controlled. - // It must match the pod template's labels. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 1; - - // An object that describes the pod that will be created. - // The DaemonSet will create exactly one copy of this pod on every node - // that matches the template's node selector (or on every node if no node - // selector is specified). - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template - optional k8s.io.api.core.v1.PodTemplateSpec template = 2; - - // An update strategy to replace existing DaemonSet pods with new pods. - // +optional - optional DaemonSetUpdateStrategy updateStrategy = 3; - - // The minimum number of seconds for which a newly created DaemonSet pod should - // be ready without any of its container crashing, for it to be considered - // available. Defaults to 0 (pod will be considered available as soon as it - // is ready). - // +optional - optional int32 minReadySeconds = 4; - - // The number of old history to retain to allow rollback. - // This is a pointer to distinguish between explicit zero and not specified. - // Defaults to 10. - // +optional - optional int32 revisionHistoryLimit = 6; -} - -// DaemonSetStatus represents the current status of a daemon set. -message DaemonSetStatus { - // The number of nodes that are running at least 1 - // daemon pod and are supposed to run the daemon pod. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/ - optional int32 currentNumberScheduled = 1; - - // The number of nodes that are running the daemon pod, but are - // not supposed to run the daemon pod. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/ - optional int32 numberMisscheduled = 2; - - // The total number of nodes that should be running the daemon - // pod (including nodes correctly running the daemon pod). - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/ - optional int32 desiredNumberScheduled = 3; - - // The number of nodes that should be running the daemon pod and have one - // or more of the daemon pod running and ready. - optional int32 numberReady = 4; - - // The most recent generation observed by the daemon set controller. - // +optional - optional int64 observedGeneration = 5; - - // The total number of nodes that are running updated daemon pod - // +optional - optional int32 updatedNumberScheduled = 6; - - // The number of nodes that should be running the - // daemon pod and have one or more of the daemon pod running and - // available (ready for at least spec.minReadySeconds) - // +optional - optional int32 numberAvailable = 7; - - // The number of nodes that should be running the - // daemon pod and have none of the daemon pod running and available - // (ready for at least spec.minReadySeconds) - // +optional - optional int32 numberUnavailable = 8; - - // Count of hash collisions for the DaemonSet. The DaemonSet controller - // uses this field as a collision avoidance mechanism when it needs to - // create the name for the newest ControllerRevision. - // +optional - optional int32 collisionCount = 9; - - // Represents the latest available observations of a DaemonSet's current state. - // +optional - // +patchMergeKey=type - // +patchStrategy=merge - repeated DaemonSetCondition conditions = 10; -} - -// DaemonSetUpdateStrategy is a struct used to control the update strategy for a DaemonSet. -message DaemonSetUpdateStrategy { - // Type of daemon set update. Can be "RollingUpdate" or "OnDelete". Default is RollingUpdate. - // +optional - optional string type = 1; - - // Rolling update config params. Present only if type = "RollingUpdate". - // --- - // TODO: Update this to follow our convention for oneOf, whatever we decide it - // to be. Same as Deployment `strategy.rollingUpdate`. - // See https://github.com/kubernetes/kubernetes/issues/35345 - // +optional - optional RollingUpdateDaemonSet rollingUpdate = 2; -} - -// DEPRECATED - This group version of Deployment is deprecated by apps/v1/Deployment. See the release notes for -// more information. -// Deployment enables declarative updates for Pods and ReplicaSets. -message Deployment { - // Standard object metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Specification of the desired behavior of the Deployment. - // +optional - optional DeploymentSpec spec = 2; - - // Most recently observed status of the Deployment. - // +optional - optional DeploymentStatus status = 3; -} - -// DeploymentCondition describes the state of a deployment at a certain point. -message DeploymentCondition { - // Type of deployment condition. - optional string type = 1; - - // Status of the condition, one of True, False, Unknown. - optional string status = 2; - - // The last time this condition was updated. - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastUpdateTime = 6; - - // Last time the condition transitioned from one status to another. - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 7; - - // The reason for the condition's last transition. - optional string reason = 4; - - // A human readable message indicating details about the transition. - optional string message = 5; -} - -// DeploymentList is a list of Deployments. -message DeploymentList { - // Standard list metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is the list of Deployments. - repeated Deployment items = 2; -} - -// DeploymentSpec is the specification of the desired behavior of the Deployment. -message DeploymentSpec { - // Number of desired pods. This is a pointer to distinguish between explicit - // zero and not specified. Defaults to 1. - // +optional - optional int32 replicas = 1; - - // Label selector for pods. Existing ReplicaSets whose pods are - // selected by this will be the ones affected by this deployment. - // It must match the pod template's labels. - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 2; - - // Template describes the pods that will be created. - optional k8s.io.api.core.v1.PodTemplateSpec template = 3; - - // The deployment strategy to use to replace existing pods with new ones. - // +optional - // +patchStrategy=retainKeys - optional DeploymentStrategy strategy = 4; - - // Minimum number of seconds for which a newly created pod should be ready - // without any of its container crashing, for it to be considered available. - // Defaults to 0 (pod will be considered available as soon as it is ready) - // +optional - optional int32 minReadySeconds = 5; - - // The number of old ReplicaSets to retain to allow rollback. - // This is a pointer to distinguish between explicit zero and not specified. - // Defaults to 10. - // +optional - optional int32 revisionHistoryLimit = 6; - - // Indicates that the deployment is paused. - // +optional - optional bool paused = 7; - - // The maximum time in seconds for a deployment to make progress before it - // is considered to be failed. The deployment controller will continue to - // process failed deployments and a condition with a ProgressDeadlineExceeded - // reason will be surfaced in the deployment status. Note that progress will - // not be estimated during the time a deployment is paused. Defaults to 600s. - optional int32 progressDeadlineSeconds = 9; -} - -// DeploymentStatus is the most recently observed status of the Deployment. -message DeploymentStatus { - // The generation observed by the deployment controller. - // +optional - optional int64 observedGeneration = 1; - - // Total number of non-terminated pods targeted by this deployment (their labels match the selector). - // +optional - optional int32 replicas = 2; - - // Total number of non-terminated pods targeted by this deployment that have the desired template spec. - // +optional - optional int32 updatedReplicas = 3; - - // Total number of ready pods targeted by this deployment. - // +optional - optional int32 readyReplicas = 7; - - // Total number of available pods (ready for at least minReadySeconds) targeted by this deployment. - // +optional - optional int32 availableReplicas = 4; - - // Total number of unavailable pods targeted by this deployment. This is the total number of - // pods that are still required for the deployment to have 100% available capacity. They may - // either be pods that are running but not yet available or pods that still have not been created. - // +optional - optional int32 unavailableReplicas = 5; - - // Represents the latest available observations of a deployment's current state. - // +patchMergeKey=type - // +patchStrategy=merge - repeated DeploymentCondition conditions = 6; - - // Count of hash collisions for the Deployment. The Deployment controller uses this - // field as a collision avoidance mechanism when it needs to create the name for the - // newest ReplicaSet. - // +optional - optional int32 collisionCount = 8; -} - -// DeploymentStrategy describes how to replace existing pods with new ones. -message DeploymentStrategy { - // Type of deployment. Can be "Recreate" or "RollingUpdate". Default is RollingUpdate. - // +optional - optional string type = 1; - - // Rolling update config params. Present only if DeploymentStrategyType = - // RollingUpdate. - // --- - // TODO: Update this to follow our convention for oneOf, whatever we decide it - // to be. - // +optional - optional RollingUpdateDeployment rollingUpdate = 2; -} - -// DEPRECATED - This group version of ReplicaSet is deprecated by apps/v1/ReplicaSet. See the release notes for -// more information. -// ReplicaSet ensures that a specified number of pod replicas are running at any given time. -message ReplicaSet { - // If the Labels of a ReplicaSet are empty, they are defaulted to - // be the same as the Pod(s) that the ReplicaSet manages. - // Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec defines the specification of the desired behavior of the ReplicaSet. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional ReplicaSetSpec spec = 2; - - // Status is the most recently observed status of the ReplicaSet. - // This data may be out of date by some window of time. - // Populated by the system. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional ReplicaSetStatus status = 3; -} - -// ReplicaSetCondition describes the state of a replica set at a certain point. -message ReplicaSetCondition { - // Type of replica set condition. - optional string type = 1; - - // Status of the condition, one of True, False, Unknown. - optional string status = 2; - - // The last time the condition transitioned from one status to another. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 3; - - // The reason for the condition's last transition. - // +optional - optional string reason = 4; - - // A human readable message indicating details about the transition. - // +optional - optional string message = 5; -} - -// ReplicaSetList is a collection of ReplicaSets. -message ReplicaSetList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // List of ReplicaSets. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller - repeated ReplicaSet items = 2; -} - -// ReplicaSetSpec is the specification of a ReplicaSet. -message ReplicaSetSpec { - // Replicas is the number of desired replicas. - // This is a pointer to distinguish between explicit zero and unspecified. - // Defaults to 1. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller/#what-is-a-replicationcontroller - // +optional - optional int32 replicas = 1; - - // Minimum number of seconds for which a newly created pod should be ready - // without any of its container crashing, for it to be considered available. - // Defaults to 0 (pod will be considered available as soon as it is ready) - // +optional - optional int32 minReadySeconds = 4; - - // Selector is a label query over pods that should match the replica count. - // Label keys and values that must match in order to be controlled by this replica set. - // It must match the pod template's labels. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 2; - - // Template is the object that describes the pod that will be created if - // insufficient replicas are detected. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template - // +optional - optional k8s.io.api.core.v1.PodTemplateSpec template = 3; -} - -// ReplicaSetStatus represents the current status of a ReplicaSet. -message ReplicaSetStatus { - // Replicas is the most recently oberved number of replicas. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller/#what-is-a-replicationcontroller - optional int32 replicas = 1; - - // The number of pods that have labels matching the labels of the pod template of the replicaset. - // +optional - optional int32 fullyLabeledReplicas = 2; - - // The number of ready replicas for this replica set. - // +optional - optional int32 readyReplicas = 4; - - // The number of available replicas (ready for at least minReadySeconds) for this replica set. - // +optional - optional int32 availableReplicas = 5; - - // ObservedGeneration reflects the generation of the most recently observed ReplicaSet. - // +optional - optional int64 observedGeneration = 3; - - // Represents the latest available observations of a replica set's current state. - // +optional - // +patchMergeKey=type - // +patchStrategy=merge - repeated ReplicaSetCondition conditions = 6; -} - -// Spec to control the desired behavior of daemon set rolling update. -message RollingUpdateDaemonSet { - // The maximum number of DaemonSet pods that can be unavailable during the - // update. Value can be an absolute number (ex: 5) or a percentage of total - // number of DaemonSet pods at the start of the update (ex: 10%). Absolute - // number is calculated from percentage by rounding up. - // This cannot be 0. - // Default value is 1. - // Example: when this is set to 30%, at most 30% of the total number of nodes - // that should be running the daemon pod (i.e. status.desiredNumberScheduled) - // can have their pods stopped for an update at any given - // time. The update starts by stopping at most 30% of those DaemonSet pods - // and then brings up new DaemonSet pods in their place. Once the new pods - // are available, it then proceeds onto other DaemonSet pods, thus ensuring - // that at least 70% of original number of DaemonSet pods are available at - // all times during the update. - // +optional - optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxUnavailable = 1; -} - -// Spec to control the desired behavior of rolling update. -message RollingUpdateDeployment { - // The maximum number of pods that can be unavailable during the update. - // Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - // Absolute number is calculated from percentage by rounding down. - // This can not be 0 if MaxSurge is 0. - // Defaults to 25%. - // Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods - // immediately when the rolling update starts. Once new pods are ready, old ReplicaSet - // can be scaled down further, followed by scaling up the new ReplicaSet, ensuring - // that the total number of pods available at all times during the update is at - // least 70% of desired pods. - // +optional - optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxUnavailable = 1; - - // The maximum number of pods that can be scheduled above the desired number of - // pods. - // Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - // This can not be 0 if MaxUnavailable is 0. - // Absolute number is calculated from percentage by rounding up. - // Defaults to 25%. - // Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when - // the rolling update starts, such that the total number of old and new pods do not exceed - // 130% of desired pods. Once old pods have been killed, - // new ReplicaSet can be scaled up further, ensuring that total number of pods running - // at any time during the update is atmost 130% of desired pods. - // +optional - optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxSurge = 2; -} - -// RollingUpdateStatefulSetStrategy is used to communicate parameter for RollingUpdateStatefulSetStrategyType. -message RollingUpdateStatefulSetStrategy { - // Partition indicates the ordinal at which the StatefulSet should be - // partitioned. - // Default value is 0. - // +optional - optional int32 partition = 1; -} - -// Scale represents a scaling request for a resource. -message Scale { - // Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // defines the behavior of the scale. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status. - // +optional - optional ScaleSpec spec = 2; - - // current status of the scale. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status. Read-only. - // +optional - optional ScaleStatus status = 3; -} - -// ScaleSpec describes the attributes of a scale subresource -message ScaleSpec { - // desired number of instances for the scaled object. - // +optional - optional int32 replicas = 1; -} - -// ScaleStatus represents the current status of a scale subresource. -message ScaleStatus { - // actual number of observed instances of the scaled object. - optional int32 replicas = 1; - - // label query over pods that should match the replicas count. More info: http://kubernetes.io/docs/user-guide/labels#label-selectors - // +optional - map selector = 2; - - // label selector for pods that should match the replicas count. This is a serializated - // version of both map-based and more expressive set-based selectors. This is done to - // avoid introspection in the clients. The string will be in the same format as the - // query-param syntax. If the target type only supports map-based selectors, both this - // field and map-based selector field are populated. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors - // +optional - optional string targetSelector = 3; -} - -// DEPRECATED - This group version of StatefulSet is deprecated by apps/v1/StatefulSet. See the release notes for -// more information. -// StatefulSet represents a set of pods with consistent identities. -// Identities are defined as: -// - Network: A single stable DNS and hostname. -// - Storage: As many VolumeClaims as requested. -// The StatefulSet guarantees that a given network identity will always -// map to the same storage identity. -message StatefulSet { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec defines the desired identities of pods in this set. - // +optional - optional StatefulSetSpec spec = 2; - - // Status is the current status of Pods in this StatefulSet. This data - // may be out of date by some window of time. - // +optional - optional StatefulSetStatus status = 3; -} - -// StatefulSetCondition describes the state of a statefulset at a certain point. -message StatefulSetCondition { - // Type of statefulset condition. - optional string type = 1; - - // Status of the condition, one of True, False, Unknown. - optional string status = 2; - - // Last time the condition transitioned from one status to another. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 3; - - // The reason for the condition's last transition. - // +optional - optional string reason = 4; - - // A human readable message indicating details about the transition. - // +optional - optional string message = 5; -} - -// StatefulSetList is a collection of StatefulSets. -message StatefulSetList { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - repeated StatefulSet items = 2; -} - -// A StatefulSetSpec is the specification of a StatefulSet. -message StatefulSetSpec { - // replicas is the desired number of replicas of the given Template. - // These are replicas in the sense that they are instantiations of the - // same Template, but individual replicas also have a consistent identity. - // If unspecified, defaults to 1. - // TODO: Consider a rename of this field. - // +optional - optional int32 replicas = 1; - - // selector is a label query over pods that should match the replica count. - // It must match the pod template's labels. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 2; - - // template is the object that describes the pod that will be created if - // insufficient replicas are detected. Each pod stamped out by the StatefulSet - // will fulfill this Template, but have a unique identity from the rest - // of the StatefulSet. - optional k8s.io.api.core.v1.PodTemplateSpec template = 3; - - // volumeClaimTemplates is a list of claims that pods are allowed to reference. - // The StatefulSet controller is responsible for mapping network identities to - // claims in a way that maintains the identity of a pod. Every claim in - // this list must have at least one matching (by name) volumeMount in one - // container in the template. A claim in this list takes precedence over - // any volumes in the template, with the same name. - // TODO: Define the behavior if a claim already exists with the same name. - // +optional - repeated k8s.io.api.core.v1.PersistentVolumeClaim volumeClaimTemplates = 4; - - // serviceName is the name of the service that governs this StatefulSet. - // This service must exist before the StatefulSet, and is responsible for - // the network identity of the set. Pods get DNS/hostnames that follow the - // pattern: pod-specific-string.serviceName.default.svc.cluster.local - // where "pod-specific-string" is managed by the StatefulSet controller. - optional string serviceName = 5; - - // podManagementPolicy controls how pods are created during initial scale up, - // when replacing pods on nodes, or when scaling down. The default policy is - // `OrderedReady`, where pods are created in increasing order (pod-0, then - // pod-1, etc) and the controller will wait until each pod is ready before - // continuing. When scaling down, the pods are removed in the opposite order. - // The alternative policy is `Parallel` which will create pods in parallel - // to match the desired scale without waiting, and on scale down will delete - // all pods at once. - // +optional - optional string podManagementPolicy = 6; - - // updateStrategy indicates the StatefulSetUpdateStrategy that will be - // employed to update Pods in the StatefulSet when a revision is made to - // Template. - optional StatefulSetUpdateStrategy updateStrategy = 7; - - // revisionHistoryLimit is the maximum number of revisions that will - // be maintained in the StatefulSet's revision history. The revision history - // consists of all revisions not represented by a currently applied - // StatefulSetSpec version. The default value is 10. - optional int32 revisionHistoryLimit = 8; -} - -// StatefulSetStatus represents the current state of a StatefulSet. -message StatefulSetStatus { - // observedGeneration is the most recent generation observed for this StatefulSet. It corresponds to the - // StatefulSet's generation, which is updated on mutation by the API Server. - // +optional - optional int64 observedGeneration = 1; - - // replicas is the number of Pods created by the StatefulSet controller. - optional int32 replicas = 2; - - // readyReplicas is the number of Pods created by the StatefulSet controller that have a Ready Condition. - optional int32 readyReplicas = 3; - - // currentReplicas is the number of Pods created by the StatefulSet controller from the StatefulSet version - // indicated by currentRevision. - optional int32 currentReplicas = 4; - - // updatedReplicas is the number of Pods created by the StatefulSet controller from the StatefulSet version - // indicated by updateRevision. - optional int32 updatedReplicas = 5; - - // currentRevision, if not empty, indicates the version of the StatefulSet used to generate Pods in the - // sequence [0,currentReplicas). - optional string currentRevision = 6; - - // updateRevision, if not empty, indicates the version of the StatefulSet used to generate Pods in the sequence - // [replicas-updatedReplicas,replicas) - optional string updateRevision = 7; - - // collisionCount is the count of hash collisions for the StatefulSet. The StatefulSet controller - // uses this field as a collision avoidance mechanism when it needs to create the name for the - // newest ControllerRevision. - // +optional - optional int32 collisionCount = 9; - - // Represents the latest available observations of a statefulset's current state. - // +optional - // +patchMergeKey=type - // +patchStrategy=merge - repeated StatefulSetCondition conditions = 10; -} - -// StatefulSetUpdateStrategy indicates the strategy that the StatefulSet -// controller will use to perform updates. It includes any additional parameters -// necessary to perform the update for the indicated strategy. -message StatefulSetUpdateStrategy { - // Type indicates the type of the StatefulSetUpdateStrategy. - // Default is RollingUpdate. - // +optional - optional string type = 1; - - // RollingUpdate is used to communicate parameters when Type is RollingUpdateStatefulSetStrategyType. - // +optional - optional RollingUpdateStatefulSetStrategy rollingUpdate = 2; -} - diff --git a/vendor/k8s.io/api/authentication/v1/generated.proto b/vendor/k8s.io/api/authentication/v1/generated.proto deleted file mode 100644 index 10c792171d..0000000000 --- a/vendor/k8s.io/api/authentication/v1/generated.proto +++ /dev/null @@ -1,159 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.authentication.v1; - -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1"; - -// BoundObjectReference is a reference to an object that a token is bound to. -message BoundObjectReference { - // Kind of the referent. Valid kinds are 'Pod' and 'Secret'. - // +optional - optional string kind = 1; - - // API version of the referent. - // +optional - optional string aPIVersion = 2; - - // Name of the referent. - // +optional - optional string name = 3; - - // UID of the referent. - // +optional - optional string uID = 4; -} - -// ExtraValue masks the value so protobuf can generate -// +protobuf.nullable=true -// +protobuf.options.(gogoproto.goproto_stringer)=false -message ExtraValue { - // items, if empty, will result in an empty slice - - repeated string items = 1; -} - -// TokenRequest requests a token for a given service account. -message TokenRequest { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - optional TokenRequestSpec spec = 2; - - // +optional - optional TokenRequestStatus status = 3; -} - -// TokenRequestSpec contains client provided parameters of a token request. -message TokenRequestSpec { - // Audiences are the intendend audiences of the token. A recipient of a - // token must identitfy themself with an identifier in the list of - // audiences of the token, and otherwise should reject the token. A - // token issued for multiple audiences may be used to authenticate - // against any of the audiences listed but implies a high degree of - // trust between the target audiences. - repeated string audiences = 1; - - // ExpirationSeconds is the requested duration of validity of the request. The - // token issuer may return a token with a different validity duration so a - // client needs to check the 'expiration' field in a response. - // +optional - optional int64 expirationSeconds = 4; - - // BoundObjectRef is a reference to an object that the token will be bound to. - // The token will only be valid for as long as the bound objet exists. - // +optional - optional BoundObjectReference boundObjectRef = 3; -} - -// TokenRequestStatus is the result of a token request. -message TokenRequestStatus { - // Token is the opaque bearer token. - optional string token = 1; - - // ExpirationTimestamp is the time of expiration of the returned token. - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time expirationTimestamp = 2; -} - -// TokenReview attempts to authenticate a token to a known user. -// Note: TokenReview requests may be cached by the webhook token authenticator -// plugin in the kube-apiserver. -message TokenReview { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec holds information about the request being evaluated - optional TokenReviewSpec spec = 2; - - // Status is filled in by the server and indicates whether the request can be authenticated. - // +optional - optional TokenReviewStatus status = 3; -} - -// TokenReviewSpec is a description of the token authentication request. -message TokenReviewSpec { - // Token is the opaque bearer token. - // +optional - optional string token = 1; -} - -// TokenReviewStatus is the result of the token authentication request. -message TokenReviewStatus { - // Authenticated indicates that the token was associated with a known user. - // +optional - optional bool authenticated = 1; - - // User is the UserInfo associated with the provided token. - // +optional - optional UserInfo user = 2; - - // Error indicates that the token couldn't be checked - // +optional - optional string error = 3; -} - -// UserInfo holds the information about the user needed to implement the -// user.Info interface. -message UserInfo { - // The name that uniquely identifies this user among all active users. - // +optional - optional string username = 1; - - // A unique value that identifies this user across time. If this user is - // deleted and another user by the same name is added, they will have - // different UIDs. - // +optional - optional string uid = 2; - - // The names of groups this user is a part of. - // +optional - repeated string groups = 3; - - // Any additional information provided by the authenticator. - // +optional - map extra = 4; -} - diff --git a/vendor/k8s.io/api/authentication/v1beta1/generated.proto b/vendor/k8s.io/api/authentication/v1beta1/generated.proto deleted file mode 100644 index a057bc591c..0000000000 --- a/vendor/k8s.io/api/authentication/v1beta1/generated.proto +++ /dev/null @@ -1,98 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.authentication.v1beta1; - -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1beta1"; - -// ExtraValue masks the value so protobuf can generate -// +protobuf.nullable=true -// +protobuf.options.(gogoproto.goproto_stringer)=false -message ExtraValue { - // items, if empty, will result in an empty slice - - repeated string items = 1; -} - -// TokenReview attempts to authenticate a token to a known user. -// Note: TokenReview requests may be cached by the webhook token authenticator -// plugin in the kube-apiserver. -message TokenReview { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec holds information about the request being evaluated - optional TokenReviewSpec spec = 2; - - // Status is filled in by the server and indicates whether the request can be authenticated. - // +optional - optional TokenReviewStatus status = 3; -} - -// TokenReviewSpec is a description of the token authentication request. -message TokenReviewSpec { - // Token is the opaque bearer token. - // +optional - optional string token = 1; -} - -// TokenReviewStatus is the result of the token authentication request. -message TokenReviewStatus { - // Authenticated indicates that the token was associated with a known user. - // +optional - optional bool authenticated = 1; - - // User is the UserInfo associated with the provided token. - // +optional - optional UserInfo user = 2; - - // Error indicates that the token couldn't be checked - // +optional - optional string error = 3; -} - -// UserInfo holds the information about the user needed to implement the -// user.Info interface. -message UserInfo { - // The name that uniquely identifies this user among all active users. - // +optional - optional string username = 1; - - // A unique value that identifies this user across time. If this user is - // deleted and another user by the same name is added, they will have - // different UIDs. - // +optional - optional string uid = 2; - - // The names of groups this user is a part of. - // +optional - repeated string groups = 3; - - // Any additional information provided by the authenticator. - // +optional - map extra = 4; -} - diff --git a/vendor/k8s.io/api/authorization/v1/generated.proto b/vendor/k8s.io/api/authorization/v1/generated.proto deleted file mode 100644 index f68a04e49e..0000000000 --- a/vendor/k8s.io/api/authorization/v1/generated.proto +++ /dev/null @@ -1,272 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.authorization.v1; - -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1"; - -// ExtraValue masks the value so protobuf can generate -// +protobuf.nullable=true -// +protobuf.options.(gogoproto.goproto_stringer)=false -message ExtraValue { - // items, if empty, will result in an empty slice - - repeated string items = 1; -} - -// LocalSubjectAccessReview checks whether or not a user or group can perform an action in a given namespace. -// Having a namespace scoped resource makes it much easier to grant namespace scoped policy that includes permissions -// checking. -message LocalSubjectAccessReview { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec holds information about the request being evaluated. spec.namespace must be equal to the namespace - // you made the request against. If empty, it is defaulted. - optional SubjectAccessReviewSpec spec = 2; - - // Status is filled in by the server and indicates whether the request is allowed or not - // +optional - optional SubjectAccessReviewStatus status = 3; -} - -// NonResourceAttributes includes the authorization attributes available for non-resource requests to the Authorizer interface -message NonResourceAttributes { - // Path is the URL path of the request - // +optional - optional string path = 1; - - // Verb is the standard HTTP verb - // +optional - optional string verb = 2; -} - -// NonResourceRule holds information that describes a rule for the non-resource -message NonResourceRule { - // Verb is a list of kubernetes non-resource API verbs, like: get, post, put, delete, patch, head, options. "*" means all. - repeated string verbs = 1; - - // NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, - // final step in the path. "*" means all. - // +optional - repeated string nonResourceURLs = 2; -} - -// ResourceAttributes includes the authorization attributes available for resource requests to the Authorizer interface -message ResourceAttributes { - // Namespace is the namespace of the action being requested. Currently, there is no distinction between no namespace and all namespaces - // "" (empty) is defaulted for LocalSubjectAccessReviews - // "" (empty) is empty for cluster-scoped resources - // "" (empty) means "all" for namespace scoped resources from a SubjectAccessReview or SelfSubjectAccessReview - // +optional - optional string namespace = 1; - - // Verb is a kubernetes resource API verb, like: get, list, watch, create, update, delete, proxy. "*" means all. - // +optional - optional string verb = 2; - - // Group is the API Group of the Resource. "*" means all. - // +optional - optional string group = 3; - - // Version is the API Version of the Resource. "*" means all. - // +optional - optional string version = 4; - - // Resource is one of the existing resource types. "*" means all. - // +optional - optional string resource = 5; - - // Subresource is one of the existing resource types. "" means none. - // +optional - optional string subresource = 6; - - // Name is the name of the resource being requested for a "get" or deleted for a "delete". "" (empty) means all. - // +optional - optional string name = 7; -} - -// ResourceRule is the list of actions the subject is allowed to perform on resources. The list ordering isn't significant, -// may contain duplicates, and possibly be incomplete. -message ResourceRule { - // Verb is a list of kubernetes resource API verbs, like: get, list, watch, create, update, delete, proxy. "*" means all. - repeated string verbs = 1; - - // APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of - // the enumerated resources in any API group will be allowed. "*" means all. - // +optional - repeated string apiGroups = 2; - - // Resources is a list of resources this rule applies to. "*" means all in the specified apiGroups. - // "*/foo" represents the subresource 'foo' for all resources in the specified apiGroups. - // +optional - repeated string resources = 3; - - // ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. "*" means all. - // +optional - repeated string resourceNames = 4; -} - -// SelfSubjectAccessReview checks whether or the current user can perform an action. Not filling in a -// spec.namespace means "in all namespaces". Self is a special case, because users should always be able -// to check whether they can perform an action -message SelfSubjectAccessReview { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec holds information about the request being evaluated. user and groups must be empty - optional SelfSubjectAccessReviewSpec spec = 2; - - // Status is filled in by the server and indicates whether the request is allowed or not - // +optional - optional SubjectAccessReviewStatus status = 3; -} - -// SelfSubjectAccessReviewSpec is a description of the access request. Exactly one of ResourceAuthorizationAttributes -// and NonResourceAuthorizationAttributes must be set -message SelfSubjectAccessReviewSpec { - // ResourceAuthorizationAttributes describes information for a resource access request - // +optional - optional ResourceAttributes resourceAttributes = 1; - - // NonResourceAttributes describes information for a non-resource access request - // +optional - optional NonResourceAttributes nonResourceAttributes = 2; -} - -// SelfSubjectRulesReview enumerates the set of actions the current user can perform within a namespace. -// The returned list of actions may be incomplete depending on the server's authorization mode, -// and any errors experienced during the evaluation. SelfSubjectRulesReview should be used by UIs to show/hide actions, -// or to quickly let an end user reason about their permissions. It should NOT Be used by external systems to -// drive authorization decisions as this raises confused deputy, cache lifetime/revocation, and correctness concerns. -// SubjectAccessReview, and LocalAccessReview are the correct way to defer authorization decisions to the API server. -message SelfSubjectRulesReview { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec holds information about the request being evaluated. - optional SelfSubjectRulesReviewSpec spec = 2; - - // Status is filled in by the server and indicates the set of actions a user can perform. - // +optional - optional SubjectRulesReviewStatus status = 3; -} - -message SelfSubjectRulesReviewSpec { - // Namespace to evaluate rules for. Required. - optional string namespace = 1; -} - -// SubjectAccessReview checks whether or not a user or group can perform an action. -message SubjectAccessReview { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec holds information about the request being evaluated - optional SubjectAccessReviewSpec spec = 2; - - // Status is filled in by the server and indicates whether the request is allowed or not - // +optional - optional SubjectAccessReviewStatus status = 3; -} - -// SubjectAccessReviewSpec is a description of the access request. Exactly one of ResourceAuthorizationAttributes -// and NonResourceAuthorizationAttributes must be set -message SubjectAccessReviewSpec { - // ResourceAuthorizationAttributes describes information for a resource access request - // +optional - optional ResourceAttributes resourceAttributes = 1; - - // NonResourceAttributes describes information for a non-resource access request - // +optional - optional NonResourceAttributes nonResourceAttributes = 2; - - // User is the user you're testing for. - // If you specify "User" but not "Groups", then is it interpreted as "What if User were not a member of any groups - // +optional - optional string user = 3; - - // Groups is the groups you're testing for. - // +optional - repeated string groups = 4; - - // Extra corresponds to the user.Info.GetExtra() method from the authenticator. Since that is input to the authorizer - // it needs a reflection here. - // +optional - map extra = 5; - - // UID information about the requesting user. - // +optional - optional string uid = 6; -} - -// SubjectAccessReviewStatus -message SubjectAccessReviewStatus { - // Allowed is required. True if the action would be allowed, false otherwise. - optional bool allowed = 1; - - // Denied is optional. True if the action would be denied, otherwise - // false. If both allowed is false and denied is false, then the - // authorizer has no opinion on whether to authorize the action. Denied - // may not be true if Allowed is true. - // +optional - optional bool denied = 4; - - // Reason is optional. It indicates why a request was allowed or denied. - // +optional - optional string reason = 2; - - // EvaluationError is an indication that some error occurred during the authorization check. - // It is entirely possible to get an error and be able to continue determine authorization status in spite of it. - // For instance, RBAC can be missing a role, but enough roles are still present and bound to reason about the request. - // +optional - optional string evaluationError = 3; -} - -// SubjectRulesReviewStatus contains the result of a rules check. This check can be incomplete depending on -// the set of authorizers the server is configured with and any errors experienced during evaluation. -// Because authorization rules are additive, if a rule appears in a list it's safe to assume the subject has that permission, -// even if that list is incomplete. -message SubjectRulesReviewStatus { - // ResourceRules is the list of actions the subject is allowed to perform on resources. - // The list ordering isn't significant, may contain duplicates, and possibly be incomplete. - repeated ResourceRule resourceRules = 1; - - // NonResourceRules is the list of actions the subject is allowed to perform on non-resources. - // The list ordering isn't significant, may contain duplicates, and possibly be incomplete. - repeated NonResourceRule nonResourceRules = 2; - - // Incomplete is true when the rules returned by this call are incomplete. This is most commonly - // encountered when an authorizer, such as an external authorizer, doesn't support rules evaluation. - optional bool incomplete = 3; - - // EvaluationError can appear in combination with Rules. It indicates an error occurred during - // rule evaluation, such as an authorizer that doesn't support rule evaluation, and that - // ResourceRules and/or NonResourceRules may be incomplete. - // +optional - optional string evaluationError = 4; -} - diff --git a/vendor/k8s.io/api/authorization/v1beta1/generated.proto b/vendor/k8s.io/api/authorization/v1beta1/generated.proto deleted file mode 100644 index 3876a3eeb9..0000000000 --- a/vendor/k8s.io/api/authorization/v1beta1/generated.proto +++ /dev/null @@ -1,272 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.authorization.v1beta1; - -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1beta1"; - -// ExtraValue masks the value so protobuf can generate -// +protobuf.nullable=true -// +protobuf.options.(gogoproto.goproto_stringer)=false -message ExtraValue { - // items, if empty, will result in an empty slice - - repeated string items = 1; -} - -// LocalSubjectAccessReview checks whether or not a user or group can perform an action in a given namespace. -// Having a namespace scoped resource makes it much easier to grant namespace scoped policy that includes permissions -// checking. -message LocalSubjectAccessReview { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec holds information about the request being evaluated. spec.namespace must be equal to the namespace - // you made the request against. If empty, it is defaulted. - optional SubjectAccessReviewSpec spec = 2; - - // Status is filled in by the server and indicates whether the request is allowed or not - // +optional - optional SubjectAccessReviewStatus status = 3; -} - -// NonResourceAttributes includes the authorization attributes available for non-resource requests to the Authorizer interface -message NonResourceAttributes { - // Path is the URL path of the request - // +optional - optional string path = 1; - - // Verb is the standard HTTP verb - // +optional - optional string verb = 2; -} - -// NonResourceRule holds information that describes a rule for the non-resource -message NonResourceRule { - // Verb is a list of kubernetes non-resource API verbs, like: get, post, put, delete, patch, head, options. "*" means all. - repeated string verbs = 1; - - // NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, - // final step in the path. "*" means all. - // +optional - repeated string nonResourceURLs = 2; -} - -// ResourceAttributes includes the authorization attributes available for resource requests to the Authorizer interface -message ResourceAttributes { - // Namespace is the namespace of the action being requested. Currently, there is no distinction between no namespace and all namespaces - // "" (empty) is defaulted for LocalSubjectAccessReviews - // "" (empty) is empty for cluster-scoped resources - // "" (empty) means "all" for namespace scoped resources from a SubjectAccessReview or SelfSubjectAccessReview - // +optional - optional string namespace = 1; - - // Verb is a kubernetes resource API verb, like: get, list, watch, create, update, delete, proxy. "*" means all. - // +optional - optional string verb = 2; - - // Group is the API Group of the Resource. "*" means all. - // +optional - optional string group = 3; - - // Version is the API Version of the Resource. "*" means all. - // +optional - optional string version = 4; - - // Resource is one of the existing resource types. "*" means all. - // +optional - optional string resource = 5; - - // Subresource is one of the existing resource types. "" means none. - // +optional - optional string subresource = 6; - - // Name is the name of the resource being requested for a "get" or deleted for a "delete". "" (empty) means all. - // +optional - optional string name = 7; -} - -// ResourceRule is the list of actions the subject is allowed to perform on resources. The list ordering isn't significant, -// may contain duplicates, and possibly be incomplete. -message ResourceRule { - // Verb is a list of kubernetes resource API verbs, like: get, list, watch, create, update, delete, proxy. "*" means all. - repeated string verbs = 1; - - // APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of - // the enumerated resources in any API group will be allowed. "*" means all. - // +optional - repeated string apiGroups = 2; - - // Resources is a list of resources this rule applies to. "*" means all in the specified apiGroups. - // "*/foo" represents the subresource 'foo' for all resources in the specified apiGroups. - // +optional - repeated string resources = 3; - - // ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. "*" means all. - // +optional - repeated string resourceNames = 4; -} - -// SelfSubjectAccessReview checks whether or the current user can perform an action. Not filling in a -// spec.namespace means "in all namespaces". Self is a special case, because users should always be able -// to check whether they can perform an action -message SelfSubjectAccessReview { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec holds information about the request being evaluated. user and groups must be empty - optional SelfSubjectAccessReviewSpec spec = 2; - - // Status is filled in by the server and indicates whether the request is allowed or not - // +optional - optional SubjectAccessReviewStatus status = 3; -} - -// SelfSubjectAccessReviewSpec is a description of the access request. Exactly one of ResourceAuthorizationAttributes -// and NonResourceAuthorizationAttributes must be set -message SelfSubjectAccessReviewSpec { - // ResourceAuthorizationAttributes describes information for a resource access request - // +optional - optional ResourceAttributes resourceAttributes = 1; - - // NonResourceAttributes describes information for a non-resource access request - // +optional - optional NonResourceAttributes nonResourceAttributes = 2; -} - -// SelfSubjectRulesReview enumerates the set of actions the current user can perform within a namespace. -// The returned list of actions may be incomplete depending on the server's authorization mode, -// and any errors experienced during the evaluation. SelfSubjectRulesReview should be used by UIs to show/hide actions, -// or to quickly let an end user reason about their permissions. It should NOT Be used by external systems to -// drive authorization decisions as this raises confused deputy, cache lifetime/revocation, and correctness concerns. -// SubjectAccessReview, and LocalAccessReview are the correct way to defer authorization decisions to the API server. -message SelfSubjectRulesReview { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec holds information about the request being evaluated. - optional SelfSubjectRulesReviewSpec spec = 2; - - // Status is filled in by the server and indicates the set of actions a user can perform. - // +optional - optional SubjectRulesReviewStatus status = 3; -} - -message SelfSubjectRulesReviewSpec { - // Namespace to evaluate rules for. Required. - optional string namespace = 1; -} - -// SubjectAccessReview checks whether or not a user or group can perform an action. -message SubjectAccessReview { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec holds information about the request being evaluated - optional SubjectAccessReviewSpec spec = 2; - - // Status is filled in by the server and indicates whether the request is allowed or not - // +optional - optional SubjectAccessReviewStatus status = 3; -} - -// SubjectAccessReviewSpec is a description of the access request. Exactly one of ResourceAuthorizationAttributes -// and NonResourceAuthorizationAttributes must be set -message SubjectAccessReviewSpec { - // ResourceAuthorizationAttributes describes information for a resource access request - // +optional - optional ResourceAttributes resourceAttributes = 1; - - // NonResourceAttributes describes information for a non-resource access request - // +optional - optional NonResourceAttributes nonResourceAttributes = 2; - - // User is the user you're testing for. - // If you specify "User" but not "Group", then is it interpreted as "What if User were not a member of any groups - // +optional - optional string user = 3; - - // Groups is the groups you're testing for. - // +optional - repeated string group = 4; - - // Extra corresponds to the user.Info.GetExtra() method from the authenticator. Since that is input to the authorizer - // it needs a reflection here. - // +optional - map extra = 5; - - // UID information about the requesting user. - // +optional - optional string uid = 6; -} - -// SubjectAccessReviewStatus -message SubjectAccessReviewStatus { - // Allowed is required. True if the action would be allowed, false otherwise. - optional bool allowed = 1; - - // Denied is optional. True if the action would be denied, otherwise - // false. If both allowed is false and denied is false, then the - // authorizer has no opinion on whether to authorize the action. Denied - // may not be true if Allowed is true. - // +optional - optional bool denied = 4; - - // Reason is optional. It indicates why a request was allowed or denied. - // +optional - optional string reason = 2; - - // EvaluationError is an indication that some error occurred during the authorization check. - // It is entirely possible to get an error and be able to continue determine authorization status in spite of it. - // For instance, RBAC can be missing a role, but enough roles are still present and bound to reason about the request. - // +optional - optional string evaluationError = 3; -} - -// SubjectRulesReviewStatus contains the result of a rules check. This check can be incomplete depending on -// the set of authorizers the server is configured with and any errors experienced during evaluation. -// Because authorization rules are additive, if a rule appears in a list it's safe to assume the subject has that permission, -// even if that list is incomplete. -message SubjectRulesReviewStatus { - // ResourceRules is the list of actions the subject is allowed to perform on resources. - // The list ordering isn't significant, may contain duplicates, and possibly be incomplete. - repeated ResourceRule resourceRules = 1; - - // NonResourceRules is the list of actions the subject is allowed to perform on non-resources. - // The list ordering isn't significant, may contain duplicates, and possibly be incomplete. - repeated NonResourceRule nonResourceRules = 2; - - // Incomplete is true when the rules returned by this call are incomplete. This is most commonly - // encountered when an authorizer, such as an external authorizer, doesn't support rules evaluation. - optional bool incomplete = 3; - - // EvaluationError can appear in combination with Rules. It indicates an error occurred during - // rule evaluation, such as an authorizer that doesn't support rule evaluation, and that - // ResourceRules and/or NonResourceRules may be incomplete. - // +optional - optional string evaluationError = 4; -} - diff --git a/vendor/k8s.io/api/autoscaling/v1/generated.proto b/vendor/k8s.io/api/autoscaling/v1/generated.proto deleted file mode 100644 index 5b56b2ac83..0000000000 --- a/vendor/k8s.io/api/autoscaling/v1/generated.proto +++ /dev/null @@ -1,415 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.autoscaling.v1; - -import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/api/resource/generated.proto"; -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1"; - -// CrossVersionObjectReference contains enough information to let you identify the referred resource. -message CrossVersionObjectReference { - // Kind of the referent; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" - optional string kind = 1; - - // Name of the referent; More info: http://kubernetes.io/docs/user-guide/identifiers#names - optional string name = 2; - - // API version of the referent - // +optional - optional string apiVersion = 3; -} - -// ExternalMetricSource indicates how to scale on a metric not associated with -// any Kubernetes object (for example length of queue in cloud -// messaging service, or QPS from loadbalancer running outside of cluster). -message ExternalMetricSource { - // metricName is the name of the metric in question. - optional string metricName = 1; - - // metricSelector is used to identify a specific time series - // within a given metric. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector metricSelector = 2; - - // targetValue is the target value of the metric (as a quantity). - // Mutually exclusive with TargetAverageValue. - // +optional - optional k8s.io.apimachinery.pkg.api.resource.Quantity targetValue = 3; - - // targetAverageValue is the target per-pod value of global metric (as a quantity). - // Mutually exclusive with TargetValue. - // +optional - optional k8s.io.apimachinery.pkg.api.resource.Quantity targetAverageValue = 4; -} - -// ExternalMetricStatus indicates the current value of a global metric -// not associated with any Kubernetes object. -message ExternalMetricStatus { - // metricName is the name of a metric used for autoscaling in - // metric system. - optional string metricName = 1; - - // metricSelector is used to identify a specific time series - // within a given metric. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector metricSelector = 2; - - // currentValue is the current value of the metric (as a quantity) - optional k8s.io.apimachinery.pkg.api.resource.Quantity currentValue = 3; - - // currentAverageValue is the current value of metric averaged over autoscaled pods. - // +optional - optional k8s.io.apimachinery.pkg.api.resource.Quantity currentAverageValue = 4; -} - -// configuration of a horizontal pod autoscaler. -message HorizontalPodAutoscaler { - // Standard object metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // behaviour of autoscaler. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status. - // +optional - optional HorizontalPodAutoscalerSpec spec = 2; - - // current information about the autoscaler. - // +optional - optional HorizontalPodAutoscalerStatus status = 3; -} - -// HorizontalPodAutoscalerCondition describes the state of -// a HorizontalPodAutoscaler at a certain point. -message HorizontalPodAutoscalerCondition { - // type describes the current condition - optional string type = 1; - - // status is the status of the condition (True, False, Unknown) - optional string status = 2; - - // lastTransitionTime is the last time the condition transitioned from - // one status to another - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 3; - - // reason is the reason for the condition's last transition. - // +optional - optional string reason = 4; - - // message is a human-readable explanation containing details about - // the transition - // +optional - optional string message = 5; -} - -// list of horizontal pod autoscaler objects. -message HorizontalPodAutoscalerList { - // Standard list metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // list of horizontal pod autoscaler objects. - repeated HorizontalPodAutoscaler items = 2; -} - -// specification of a horizontal pod autoscaler. -message HorizontalPodAutoscalerSpec { - // reference to scaled resource; horizontal pod autoscaler will learn the current resource consumption - // and will set the desired number of pods by using its Scale subresource. - optional CrossVersionObjectReference scaleTargetRef = 1; - - // lower limit for the number of pods that can be set by the autoscaler, default 1. - // +optional - optional int32 minReplicas = 2; - - // upper limit for the number of pods that can be set by the autoscaler; cannot be smaller than MinReplicas. - optional int32 maxReplicas = 3; - - // target average CPU utilization (represented as a percentage of requested CPU) over all the pods; - // if not specified the default autoscaling policy will be used. - // +optional - optional int32 targetCPUUtilizationPercentage = 4; -} - -// current status of a horizontal pod autoscaler -message HorizontalPodAutoscalerStatus { - // most recent generation observed by this autoscaler. - // +optional - optional int64 observedGeneration = 1; - - // last time the HorizontalPodAutoscaler scaled the number of pods; - // used by the autoscaler to control how often the number of pods is changed. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastScaleTime = 2; - - // current number of replicas of pods managed by this autoscaler. - optional int32 currentReplicas = 3; - - // desired number of replicas of pods managed by this autoscaler. - optional int32 desiredReplicas = 4; - - // current average CPU utilization over all pods, represented as a percentage of requested CPU, - // e.g. 70 means that an average pod is using now 70% of its requested CPU. - // +optional - optional int32 currentCPUUtilizationPercentage = 5; -} - -// MetricSpec specifies how to scale based on a single metric -// (only `type` and one other matching field should be set at once). -message MetricSpec { - // type is the type of metric source. It should be one of "Object", - // "Pods" or "Resource", each mapping to a matching field in the object. - optional string type = 1; - - // object refers to a metric describing a single kubernetes object - // (for example, hits-per-second on an Ingress object). - // +optional - optional ObjectMetricSource object = 2; - - // pods refers to a metric describing each pod in the current scale target - // (for example, transactions-processed-per-second). The values will be - // averaged together before being compared to the target value. - // +optional - optional PodsMetricSource pods = 3; - - // resource refers to a resource metric (such as those specified in - // requests and limits) known to Kubernetes describing each pod in the - // current scale target (e.g. CPU or memory). Such metrics are built in to - // Kubernetes, and have special scaling options on top of those available - // to normal per-pod metrics using the "pods" source. - // +optional - optional ResourceMetricSource resource = 4; - - // external refers to a global metric that is not associated - // with any Kubernetes object. It allows autoscaling based on information - // coming from components running outside of cluster - // (for example length of queue in cloud messaging service, or - // QPS from loadbalancer running outside of cluster). - // +optional - optional ExternalMetricSource external = 5; -} - -// MetricStatus describes the last-read state of a single metric. -message MetricStatus { - // type is the type of metric source. It will be one of "Object", - // "Pods" or "Resource", each corresponds to a matching field in the object. - optional string type = 1; - - // object refers to a metric describing a single kubernetes object - // (for example, hits-per-second on an Ingress object). - // +optional - optional ObjectMetricStatus object = 2; - - // pods refers to a metric describing each pod in the current scale target - // (for example, transactions-processed-per-second). The values will be - // averaged together before being compared to the target value. - // +optional - optional PodsMetricStatus pods = 3; - - // resource refers to a resource metric (such as those specified in - // requests and limits) known to Kubernetes describing each pod in the - // current scale target (e.g. CPU or memory). Such metrics are built in to - // Kubernetes, and have special scaling options on top of those available - // to normal per-pod metrics using the "pods" source. - // +optional - optional ResourceMetricStatus resource = 4; - - // external refers to a global metric that is not associated - // with any Kubernetes object. It allows autoscaling based on information - // coming from components running outside of cluster - // (for example length of queue in cloud messaging service, or - // QPS from loadbalancer running outside of cluster). - // +optional - optional ExternalMetricStatus external = 5; -} - -// ObjectMetricSource indicates how to scale on a metric describing a -// kubernetes object (for example, hits-per-second on an Ingress object). -message ObjectMetricSource { - // target is the described Kubernetes object. - optional CrossVersionObjectReference target = 1; - - // metricName is the name of the metric in question. - optional string metricName = 2; - - // targetValue is the target value of the metric (as a quantity). - optional k8s.io.apimachinery.pkg.api.resource.Quantity targetValue = 3; - - // selector is the string-encoded form of a standard kubernetes label selector for the given metric. - // When set, it is passed as an additional parameter to the metrics server for more specific metrics scoping - // When unset, just the metricName will be used to gather metrics. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 4; - - // averageValue is the target value of the average of the - // metric across all relevant pods (as a quantity) - // +optional - optional k8s.io.apimachinery.pkg.api.resource.Quantity averageValue = 5; -} - -// ObjectMetricStatus indicates the current value of a metric describing a -// kubernetes object (for example, hits-per-second on an Ingress object). -message ObjectMetricStatus { - // target is the described Kubernetes object. - optional CrossVersionObjectReference target = 1; - - // metricName is the name of the metric in question. - optional string metricName = 2; - - // currentValue is the current value of the metric (as a quantity). - optional k8s.io.apimachinery.pkg.api.resource.Quantity currentValue = 3; - - // selector is the string-encoded form of a standard kubernetes label selector for the given metric - // When set in the ObjectMetricSource, it is passed as an additional parameter to the metrics server for more specific metrics scoping. - // When unset, just the metricName will be used to gather metrics. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 4; - - // averageValue is the current value of the average of the - // metric across all relevant pods (as a quantity) - // +optional - optional k8s.io.apimachinery.pkg.api.resource.Quantity averageValue = 5; -} - -// PodsMetricSource indicates how to scale on a metric describing each pod in -// the current scale target (for example, transactions-processed-per-second). -// The values will be averaged together before being compared to the target -// value. -message PodsMetricSource { - // metricName is the name of the metric in question - optional string metricName = 1; - - // targetAverageValue is the target value of the average of the - // metric across all relevant pods (as a quantity) - optional k8s.io.apimachinery.pkg.api.resource.Quantity targetAverageValue = 2; - - // selector is the string-encoded form of a standard kubernetes label selector for the given metric - // When set, it is passed as an additional parameter to the metrics server for more specific metrics scoping - // When unset, just the metricName will be used to gather metrics. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 3; -} - -// PodsMetricStatus indicates the current value of a metric describing each pod in -// the current scale target (for example, transactions-processed-per-second). -message PodsMetricStatus { - // metricName is the name of the metric in question - optional string metricName = 1; - - // currentAverageValue is the current value of the average of the - // metric across all relevant pods (as a quantity) - optional k8s.io.apimachinery.pkg.api.resource.Quantity currentAverageValue = 2; - - // selector is the string-encoded form of a standard kubernetes label selector for the given metric - // When set in the PodsMetricSource, it is passed as an additional parameter to the metrics server for more specific metrics scoping. - // When unset, just the metricName will be used to gather metrics. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 3; -} - -// ResourceMetricSource indicates how to scale on a resource metric known to -// Kubernetes, as specified in requests and limits, describing each pod in the -// current scale target (e.g. CPU or memory). The values will be averaged -// together before being compared to the target. Such metrics are built in to -// Kubernetes, and have special scaling options on top of those available to -// normal per-pod metrics using the "pods" source. Only one "target" type -// should be set. -message ResourceMetricSource { - // name is the name of the resource in question. - optional string name = 1; - - // targetAverageUtilization is the target value of the average of the - // resource metric across all relevant pods, represented as a percentage of - // the requested value of the resource for the pods. - // +optional - optional int32 targetAverageUtilization = 2; - - // targetAverageValue is the target value of the average of the - // resource metric across all relevant pods, as a raw value (instead of as - // a percentage of the request), similar to the "pods" metric source type. - // +optional - optional k8s.io.apimachinery.pkg.api.resource.Quantity targetAverageValue = 3; -} - -// ResourceMetricStatus indicates the current value of a resource metric known to -// Kubernetes, as specified in requests and limits, describing each pod in the -// current scale target (e.g. CPU or memory). Such metrics are built in to -// Kubernetes, and have special scaling options on top of those available to -// normal per-pod metrics using the "pods" source. -message ResourceMetricStatus { - // name is the name of the resource in question. - optional string name = 1; - - // currentAverageUtilization is the current value of the average of the - // resource metric across all relevant pods, represented as a percentage of - // the requested value of the resource for the pods. It will only be - // present if `targetAverageValue` was set in the corresponding metric - // specification. - // +optional - optional int32 currentAverageUtilization = 2; - - // currentAverageValue is the current value of the average of the - // resource metric across all relevant pods, as a raw value (instead of as - // a percentage of the request), similar to the "pods" metric source type. - // It will always be set, regardless of the corresponding metric specification. - optional k8s.io.apimachinery.pkg.api.resource.Quantity currentAverageValue = 3; -} - -// Scale represents a scaling request for a resource. -message Scale { - // Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // defines the behavior of the scale. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status. - // +optional - optional ScaleSpec spec = 2; - - // current status of the scale. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status. Read-only. - // +optional - optional ScaleStatus status = 3; -} - -// ScaleSpec describes the attributes of a scale subresource. -message ScaleSpec { - // desired number of instances for the scaled object. - // +optional - optional int32 replicas = 1; -} - -// ScaleStatus represents the current status of a scale subresource. -message ScaleStatus { - // actual number of observed instances of the scaled object. - optional int32 replicas = 1; - - // label query over pods that should match the replicas count. This is same - // as the label selector but in the string format to avoid introspection - // by clients. The string will be in the same format as the query-param syntax. - // More info about label selectors: http://kubernetes.io/docs/user-guide/labels#label-selectors - // +optional - optional string selector = 2; -} - diff --git a/vendor/k8s.io/api/autoscaling/v2beta1/generated.proto b/vendor/k8s.io/api/autoscaling/v2beta1/generated.proto deleted file mode 100644 index 04bc0ed601..0000000000 --- a/vendor/k8s.io/api/autoscaling/v2beta1/generated.proto +++ /dev/null @@ -1,397 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.autoscaling.v2beta1; - -import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/api/resource/generated.proto"; -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v2beta1"; - -// CrossVersionObjectReference contains enough information to let you identify the referred resource. -message CrossVersionObjectReference { - // Kind of the referent; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" - optional string kind = 1; - - // Name of the referent; More info: http://kubernetes.io/docs/user-guide/identifiers#names - optional string name = 2; - - // API version of the referent - // +optional - optional string apiVersion = 3; -} - -// ExternalMetricSource indicates how to scale on a metric not associated with -// any Kubernetes object (for example length of queue in cloud -// messaging service, or QPS from loadbalancer running outside of cluster). -// Exactly one "target" type should be set. -message ExternalMetricSource { - // metricName is the name of the metric in question. - optional string metricName = 1; - - // metricSelector is used to identify a specific time series - // within a given metric. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector metricSelector = 2; - - // targetValue is the target value of the metric (as a quantity). - // Mutually exclusive with TargetAverageValue. - // +optional - optional k8s.io.apimachinery.pkg.api.resource.Quantity targetValue = 3; - - // targetAverageValue is the target per-pod value of global metric (as a quantity). - // Mutually exclusive with TargetValue. - // +optional - optional k8s.io.apimachinery.pkg.api.resource.Quantity targetAverageValue = 4; -} - -// ExternalMetricStatus indicates the current value of a global metric -// not associated with any Kubernetes object. -message ExternalMetricStatus { - // metricName is the name of a metric used for autoscaling in - // metric system. - optional string metricName = 1; - - // metricSelector is used to identify a specific time series - // within a given metric. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector metricSelector = 2; - - // currentValue is the current value of the metric (as a quantity) - optional k8s.io.apimachinery.pkg.api.resource.Quantity currentValue = 3; - - // currentAverageValue is the current value of metric averaged over autoscaled pods. - // +optional - optional k8s.io.apimachinery.pkg.api.resource.Quantity currentAverageValue = 4; -} - -// HorizontalPodAutoscaler is the configuration for a horizontal pod -// autoscaler, which automatically manages the replica count of any resource -// implementing the scale subresource based on the metrics specified. -message HorizontalPodAutoscaler { - // metadata is the standard object metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // spec is the specification for the behaviour of the autoscaler. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status. - // +optional - optional HorizontalPodAutoscalerSpec spec = 2; - - // status is the current information about the autoscaler. - // +optional - optional HorizontalPodAutoscalerStatus status = 3; -} - -// HorizontalPodAutoscalerCondition describes the state of -// a HorizontalPodAutoscaler at a certain point. -message HorizontalPodAutoscalerCondition { - // type describes the current condition - optional string type = 1; - - // status is the status of the condition (True, False, Unknown) - optional string status = 2; - - // lastTransitionTime is the last time the condition transitioned from - // one status to another - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 3; - - // reason is the reason for the condition's last transition. - // +optional - optional string reason = 4; - - // message is a human-readable explanation containing details about - // the transition - // +optional - optional string message = 5; -} - -// HorizontalPodAutoscaler is a list of horizontal pod autoscaler objects. -message HorizontalPodAutoscalerList { - // metadata is the standard list metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // items is the list of horizontal pod autoscaler objects. - repeated HorizontalPodAutoscaler items = 2; -} - -// HorizontalPodAutoscalerSpec describes the desired functionality of the HorizontalPodAutoscaler. -message HorizontalPodAutoscalerSpec { - // scaleTargetRef points to the target resource to scale, and is used to the pods for which metrics - // should be collected, as well as to actually change the replica count. - optional CrossVersionObjectReference scaleTargetRef = 1; - - // minReplicas is the lower limit for the number of replicas to which the autoscaler can scale down. - // It defaults to 1 pod. - // +optional - optional int32 minReplicas = 2; - - // maxReplicas is the upper limit for the number of replicas to which the autoscaler can scale up. - // It cannot be less that minReplicas. - optional int32 maxReplicas = 3; - - // metrics contains the specifications for which to use to calculate the - // desired replica count (the maximum replica count across all metrics will - // be used). The desired replica count is calculated multiplying the - // ratio between the target value and the current value by the current - // number of pods. Ergo, metrics used must decrease as the pod count is - // increased, and vice-versa. See the individual metric source types for - // more information about how each type of metric must respond. - // +optional - repeated MetricSpec metrics = 4; -} - -// HorizontalPodAutoscalerStatus describes the current status of a horizontal pod autoscaler. -message HorizontalPodAutoscalerStatus { - // observedGeneration is the most recent generation observed by this autoscaler. - // +optional - optional int64 observedGeneration = 1; - - // lastScaleTime is the last time the HorizontalPodAutoscaler scaled the number of pods, - // used by the autoscaler to control how often the number of pods is changed. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastScaleTime = 2; - - // currentReplicas is current number of replicas of pods managed by this autoscaler, - // as last seen by the autoscaler. - optional int32 currentReplicas = 3; - - // desiredReplicas is the desired number of replicas of pods managed by this autoscaler, - // as last calculated by the autoscaler. - optional int32 desiredReplicas = 4; - - // currentMetrics is the last read state of the metrics used by this autoscaler. - // +optional - repeated MetricStatus currentMetrics = 5; - - // conditions is the set of conditions required for this autoscaler to scale its target, - // and indicates whether or not those conditions are met. - repeated HorizontalPodAutoscalerCondition conditions = 6; -} - -// MetricSpec specifies how to scale based on a single metric -// (only `type` and one other matching field should be set at once). -message MetricSpec { - // type is the type of metric source. It should be one of "Object", - // "Pods" or "Resource", each mapping to a matching field in the object. - optional string type = 1; - - // object refers to a metric describing a single kubernetes object - // (for example, hits-per-second on an Ingress object). - // +optional - optional ObjectMetricSource object = 2; - - // pods refers to a metric describing each pod in the current scale target - // (for example, transactions-processed-per-second). The values will be - // averaged together before being compared to the target value. - // +optional - optional PodsMetricSource pods = 3; - - // resource refers to a resource metric (such as those specified in - // requests and limits) known to Kubernetes describing each pod in the - // current scale target (e.g. CPU or memory). Such metrics are built in to - // Kubernetes, and have special scaling options on top of those available - // to normal per-pod metrics using the "pods" source. - // +optional - optional ResourceMetricSource resource = 4; - - // external refers to a global metric that is not associated - // with any Kubernetes object. It allows autoscaling based on information - // coming from components running outside of cluster - // (for example length of queue in cloud messaging service, or - // QPS from loadbalancer running outside of cluster). - // +optional - optional ExternalMetricSource external = 5; -} - -// MetricStatus describes the last-read state of a single metric. -message MetricStatus { - // type is the type of metric source. It will be one of "Object", - // "Pods" or "Resource", each corresponds to a matching field in the object. - optional string type = 1; - - // object refers to a metric describing a single kubernetes object - // (for example, hits-per-second on an Ingress object). - // +optional - optional ObjectMetricStatus object = 2; - - // pods refers to a metric describing each pod in the current scale target - // (for example, transactions-processed-per-second). The values will be - // averaged together before being compared to the target value. - // +optional - optional PodsMetricStatus pods = 3; - - // resource refers to a resource metric (such as those specified in - // requests and limits) known to Kubernetes describing each pod in the - // current scale target (e.g. CPU or memory). Such metrics are built in to - // Kubernetes, and have special scaling options on top of those available - // to normal per-pod metrics using the "pods" source. - // +optional - optional ResourceMetricStatus resource = 4; - - // external refers to a global metric that is not associated - // with any Kubernetes object. It allows autoscaling based on information - // coming from components running outside of cluster - // (for example length of queue in cloud messaging service, or - // QPS from loadbalancer running outside of cluster). - // +optional - optional ExternalMetricStatus external = 5; -} - -// ObjectMetricSource indicates how to scale on a metric describing a -// kubernetes object (for example, hits-per-second on an Ingress object). -message ObjectMetricSource { - // target is the described Kubernetes object. - optional CrossVersionObjectReference target = 1; - - // metricName is the name of the metric in question. - optional string metricName = 2; - - // targetValue is the target value of the metric (as a quantity). - optional k8s.io.apimachinery.pkg.api.resource.Quantity targetValue = 3; - - // selector is the string-encoded form of a standard kubernetes label selector for the given metric - // When set, it is passed as an additional parameter to the metrics server for more specific metrics scoping - // When unset, just the metricName will be used to gather metrics. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 4; - - // averageValue is the target value of the average of the - // metric across all relevant pods (as a quantity) - // +optional - optional k8s.io.apimachinery.pkg.api.resource.Quantity averageValue = 5; -} - -// ObjectMetricStatus indicates the current value of a metric describing a -// kubernetes object (for example, hits-per-second on an Ingress object). -message ObjectMetricStatus { - // target is the described Kubernetes object. - optional CrossVersionObjectReference target = 1; - - // metricName is the name of the metric in question. - optional string metricName = 2; - - // currentValue is the current value of the metric (as a quantity). - optional k8s.io.apimachinery.pkg.api.resource.Quantity currentValue = 3; - - // selector is the string-encoded form of a standard kubernetes label selector for the given metric - // When set in the ObjectMetricSource, it is passed as an additional parameter to the metrics server for more specific metrics scoping. - // When unset, just the metricName will be used to gather metrics. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 4; - - // averageValue is the current value of the average of the - // metric across all relevant pods (as a quantity) - // +optional - optional k8s.io.apimachinery.pkg.api.resource.Quantity averageValue = 5; -} - -// PodsMetricSource indicates how to scale on a metric describing each pod in -// the current scale target (for example, transactions-processed-per-second). -// The values will be averaged together before being compared to the target -// value. -message PodsMetricSource { - // metricName is the name of the metric in question - optional string metricName = 1; - - // targetAverageValue is the target value of the average of the - // metric across all relevant pods (as a quantity) - optional k8s.io.apimachinery.pkg.api.resource.Quantity targetAverageValue = 2; - - // selector is the string-encoded form of a standard kubernetes label selector for the given metric - // When set, it is passed as an additional parameter to the metrics server for more specific metrics scoping - // When unset, just the metricName will be used to gather metrics. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 3; -} - -// PodsMetricStatus indicates the current value of a metric describing each pod in -// the current scale target (for example, transactions-processed-per-second). -message PodsMetricStatus { - // metricName is the name of the metric in question - optional string metricName = 1; - - // currentAverageValue is the current value of the average of the - // metric across all relevant pods (as a quantity) - optional k8s.io.apimachinery.pkg.api.resource.Quantity currentAverageValue = 2; - - // selector is the string-encoded form of a standard kubernetes label selector for the given metric - // When set in the PodsMetricSource, it is passed as an additional parameter to the metrics server for more specific metrics scoping. - // When unset, just the metricName will be used to gather metrics. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 3; -} - -// ResourceMetricSource indicates how to scale on a resource metric known to -// Kubernetes, as specified in requests and limits, describing each pod in the -// current scale target (e.g. CPU or memory). The values will be averaged -// together before being compared to the target. Such metrics are built in to -// Kubernetes, and have special scaling options on top of those available to -// normal per-pod metrics using the "pods" source. Only one "target" type -// should be set. -message ResourceMetricSource { - // name is the name of the resource in question. - optional string name = 1; - - // targetAverageUtilization is the target value of the average of the - // resource metric across all relevant pods, represented as a percentage of - // the requested value of the resource for the pods. - // +optional - optional int32 targetAverageUtilization = 2; - - // targetAverageValue is the target value of the average of the - // resource metric across all relevant pods, as a raw value (instead of as - // a percentage of the request), similar to the "pods" metric source type. - // +optional - optional k8s.io.apimachinery.pkg.api.resource.Quantity targetAverageValue = 3; -} - -// ResourceMetricStatus indicates the current value of a resource metric known to -// Kubernetes, as specified in requests and limits, describing each pod in the -// current scale target (e.g. CPU or memory). Such metrics are built in to -// Kubernetes, and have special scaling options on top of those available to -// normal per-pod metrics using the "pods" source. -message ResourceMetricStatus { - // name is the name of the resource in question. - optional string name = 1; - - // currentAverageUtilization is the current value of the average of the - // resource metric across all relevant pods, represented as a percentage of - // the requested value of the resource for the pods. It will only be - // present if `targetAverageValue` was set in the corresponding metric - // specification. - // +optional - optional int32 currentAverageUtilization = 2; - - // currentAverageValue is the current value of the average of the - // resource metric across all relevant pods, as a raw value (instead of as - // a percentage of the request), similar to the "pods" metric source type. - // It will always be set, regardless of the corresponding metric specification. - optional k8s.io.apimachinery.pkg.api.resource.Quantity currentAverageValue = 3; -} - diff --git a/vendor/k8s.io/api/autoscaling/v2beta2/generated.proto b/vendor/k8s.io/api/autoscaling/v2beta2/generated.proto deleted file mode 100644 index b4e4c95a3b..0000000000 --- a/vendor/k8s.io/api/autoscaling/v2beta2/generated.proto +++ /dev/null @@ -1,369 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.autoscaling.v2beta2; - -import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/api/resource/generated.proto"; -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v2beta2"; - -// CrossVersionObjectReference contains enough information to let you identify the referred resource. -message CrossVersionObjectReference { - // Kind of the referent; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds" - optional string kind = 1; - - // Name of the referent; More info: http://kubernetes.io/docs/user-guide/identifiers#names - optional string name = 2; - - // API version of the referent - // +optional - optional string apiVersion = 3; -} - -// ExternalMetricSource indicates how to scale on a metric not associated with -// any Kubernetes object (for example length of queue in cloud -// messaging service, or QPS from loadbalancer running outside of cluster). -message ExternalMetricSource { - // metric identifies the target metric by name and selector - optional MetricIdentifier metric = 1; - - // target specifies the target value for the given metric - optional MetricTarget target = 2; -} - -// ExternalMetricStatus indicates the current value of a global metric -// not associated with any Kubernetes object. -message ExternalMetricStatus { - // metric identifies the target metric by name and selector - optional MetricIdentifier metric = 1; - - // current contains the current value for the given metric - optional MetricValueStatus current = 2; -} - -// HorizontalPodAutoscaler is the configuration for a horizontal pod -// autoscaler, which automatically manages the replica count of any resource -// implementing the scale subresource based on the metrics specified. -message HorizontalPodAutoscaler { - // metadata is the standard object metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // spec is the specification for the behaviour of the autoscaler. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status. - // +optional - optional HorizontalPodAutoscalerSpec spec = 2; - - // status is the current information about the autoscaler. - // +optional - optional HorizontalPodAutoscalerStatus status = 3; -} - -// HorizontalPodAutoscalerCondition describes the state of -// a HorizontalPodAutoscaler at a certain point. -message HorizontalPodAutoscalerCondition { - // type describes the current condition - optional string type = 1; - - // status is the status of the condition (True, False, Unknown) - optional string status = 2; - - // lastTransitionTime is the last time the condition transitioned from - // one status to another - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 3; - - // reason is the reason for the condition's last transition. - // +optional - optional string reason = 4; - - // message is a human-readable explanation containing details about - // the transition - // +optional - optional string message = 5; -} - -// HorizontalPodAutoscalerList is a list of horizontal pod autoscaler objects. -message HorizontalPodAutoscalerList { - // metadata is the standard list metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // items is the list of horizontal pod autoscaler objects. - repeated HorizontalPodAutoscaler items = 2; -} - -// HorizontalPodAutoscalerSpec describes the desired functionality of the HorizontalPodAutoscaler. -message HorizontalPodAutoscalerSpec { - // scaleTargetRef points to the target resource to scale, and is used to the pods for which metrics - // should be collected, as well as to actually change the replica count. - optional CrossVersionObjectReference scaleTargetRef = 1; - - // minReplicas is the lower limit for the number of replicas to which the autoscaler can scale down. - // It defaults to 1 pod. - // +optional - optional int32 minReplicas = 2; - - // maxReplicas is the upper limit for the number of replicas to which the autoscaler can scale up. - // It cannot be less that minReplicas. - optional int32 maxReplicas = 3; - - // metrics contains the specifications for which to use to calculate the - // desired replica count (the maximum replica count across all metrics will - // be used). The desired replica count is calculated multiplying the - // ratio between the target value and the current value by the current - // number of pods. Ergo, metrics used must decrease as the pod count is - // increased, and vice-versa. See the individual metric source types for - // more information about how each type of metric must respond. - // If not set, the default metric will be set to 80% average CPU utilization. - // +optional - repeated MetricSpec metrics = 4; -} - -// HorizontalPodAutoscalerStatus describes the current status of a horizontal pod autoscaler. -message HorizontalPodAutoscalerStatus { - // observedGeneration is the most recent generation observed by this autoscaler. - // +optional - optional int64 observedGeneration = 1; - - // lastScaleTime is the last time the HorizontalPodAutoscaler scaled the number of pods, - // used by the autoscaler to control how often the number of pods is changed. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastScaleTime = 2; - - // currentReplicas is current number of replicas of pods managed by this autoscaler, - // as last seen by the autoscaler. - optional int32 currentReplicas = 3; - - // desiredReplicas is the desired number of replicas of pods managed by this autoscaler, - // as last calculated by the autoscaler. - optional int32 desiredReplicas = 4; - - // currentMetrics is the last read state of the metrics used by this autoscaler. - // +optional - repeated MetricStatus currentMetrics = 5; - - // conditions is the set of conditions required for this autoscaler to scale its target, - // and indicates whether or not those conditions are met. - repeated HorizontalPodAutoscalerCondition conditions = 6; -} - -// MetricIdentifier defines the name and optionally selector for a metric -message MetricIdentifier { - // name is the name of the given metric - optional string name = 1; - - // selector is the string-encoded form of a standard kubernetes label selector for the given metric - // When set, it is passed as an additional parameter to the metrics server for more specific metrics scoping. - // When unset, just the metricName will be used to gather metrics. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 2; -} - -// MetricSpec specifies how to scale based on a single metric -// (only `type` and one other matching field should be set at once). -message MetricSpec { - // type is the type of metric source. It should be one of "Object", - // "Pods" or "Resource", each mapping to a matching field in the object. - optional string type = 1; - - // object refers to a metric describing a single kubernetes object - // (for example, hits-per-second on an Ingress object). - // +optional - optional ObjectMetricSource object = 2; - - // pods refers to a metric describing each pod in the current scale target - // (for example, transactions-processed-per-second). The values will be - // averaged together before being compared to the target value. - // +optional - optional PodsMetricSource pods = 3; - - // resource refers to a resource metric (such as those specified in - // requests and limits) known to Kubernetes describing each pod in the - // current scale target (e.g. CPU or memory). Such metrics are built in to - // Kubernetes, and have special scaling options on top of those available - // to normal per-pod metrics using the "pods" source. - // +optional - optional ResourceMetricSource resource = 4; - - // external refers to a global metric that is not associated - // with any Kubernetes object. It allows autoscaling based on information - // coming from components running outside of cluster - // (for example length of queue in cloud messaging service, or - // QPS from loadbalancer running outside of cluster). - // +optional - optional ExternalMetricSource external = 5; -} - -// MetricStatus describes the last-read state of a single metric. -message MetricStatus { - // type is the type of metric source. It will be one of "Object", - // "Pods" or "Resource", each corresponds to a matching field in the object. - optional string type = 1; - - // object refers to a metric describing a single kubernetes object - // (for example, hits-per-second on an Ingress object). - // +optional - optional ObjectMetricStatus object = 2; - - // pods refers to a metric describing each pod in the current scale target - // (for example, transactions-processed-per-second). The values will be - // averaged together before being compared to the target value. - // +optional - optional PodsMetricStatus pods = 3; - - // resource refers to a resource metric (such as those specified in - // requests and limits) known to Kubernetes describing each pod in the - // current scale target (e.g. CPU or memory). Such metrics are built in to - // Kubernetes, and have special scaling options on top of those available - // to normal per-pod metrics using the "pods" source. - // +optional - optional ResourceMetricStatus resource = 4; - - // external refers to a global metric that is not associated - // with any Kubernetes object. It allows autoscaling based on information - // coming from components running outside of cluster - // (for example length of queue in cloud messaging service, or - // QPS from loadbalancer running outside of cluster). - // +optional - optional ExternalMetricStatus external = 5; -} - -// MetricTarget defines the target value, average value, or average utilization of a specific metric -message MetricTarget { - // type represents whether the metric type is Utilization, Value, or AverageValue - optional string type = 1; - - // value is the target value of the metric (as a quantity). - // +optional - optional k8s.io.apimachinery.pkg.api.resource.Quantity value = 2; - - // averageValue is the target value of the average of the - // metric across all relevant pods (as a quantity) - // +optional - optional k8s.io.apimachinery.pkg.api.resource.Quantity averageValue = 3; - - // averageUtilization is the target value of the average of the - // resource metric across all relevant pods, represented as a percentage of - // the requested value of the resource for the pods. - // Currently only valid for Resource metric source type - // +optional - optional int32 averageUtilization = 4; -} - -// MetricValueStatus holds the current value for a metric -message MetricValueStatus { - // value is the current value of the metric (as a quantity). - // +optional - optional k8s.io.apimachinery.pkg.api.resource.Quantity value = 1; - - // averageValue is the current value of the average of the - // metric across all relevant pods (as a quantity) - // +optional - optional k8s.io.apimachinery.pkg.api.resource.Quantity averageValue = 2; - - // currentAverageUtilization is the current value of the average of the - // resource metric across all relevant pods, represented as a percentage of - // the requested value of the resource for the pods. - // +optional - optional int32 averageUtilization = 3; -} - -// ObjectMetricSource indicates how to scale on a metric describing a -// kubernetes object (for example, hits-per-second on an Ingress object). -message ObjectMetricSource { - optional CrossVersionObjectReference describedObject = 1; - - // target specifies the target value for the given metric - optional MetricTarget target = 2; - - // metric identifies the target metric by name and selector - optional MetricIdentifier metric = 3; -} - -// ObjectMetricStatus indicates the current value of a metric describing a -// kubernetes object (for example, hits-per-second on an Ingress object). -message ObjectMetricStatus { - // metric identifies the target metric by name and selector - optional MetricIdentifier metric = 1; - - // current contains the current value for the given metric - optional MetricValueStatus current = 2; - - optional CrossVersionObjectReference describedObject = 3; -} - -// PodsMetricSource indicates how to scale on a metric describing each pod in -// the current scale target (for example, transactions-processed-per-second). -// The values will be averaged together before being compared to the target -// value. -message PodsMetricSource { - // metric identifies the target metric by name and selector - optional MetricIdentifier metric = 1; - - // target specifies the target value for the given metric - optional MetricTarget target = 2; -} - -// PodsMetricStatus indicates the current value of a metric describing each pod in -// the current scale target (for example, transactions-processed-per-second). -message PodsMetricStatus { - // metric identifies the target metric by name and selector - optional MetricIdentifier metric = 1; - - // current contains the current value for the given metric - optional MetricValueStatus current = 2; -} - -// ResourceMetricSource indicates how to scale on a resource metric known to -// Kubernetes, as specified in requests and limits, describing each pod in the -// current scale target (e.g. CPU or memory). The values will be averaged -// together before being compared to the target. Such metrics are built in to -// Kubernetes, and have special scaling options on top of those available to -// normal per-pod metrics using the "pods" source. Only one "target" type -// should be set. -message ResourceMetricSource { - // name is the name of the resource in question. - optional string name = 1; - - // target specifies the target value for the given metric - optional MetricTarget target = 2; -} - -// ResourceMetricStatus indicates the current value of a resource metric known to -// Kubernetes, as specified in requests and limits, describing each pod in the -// current scale target (e.g. CPU or memory). Such metrics are built in to -// Kubernetes, and have special scaling options on top of those available to -// normal per-pod metrics using the "pods" source. -message ResourceMetricStatus { - // Name is the name of the resource in question. - optional string name = 1; - - // current contains the current value for the given metric - optional MetricValueStatus current = 2; -} - diff --git a/vendor/k8s.io/api/batch/v1/generated.proto b/vendor/k8s.io/api/batch/v1/generated.proto deleted file mode 100644 index 039149daba..0000000000 --- a/vendor/k8s.io/api/batch/v1/generated.proto +++ /dev/null @@ -1,184 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.batch.v1; - -import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1"; - -// Job represents the configuration of a single job. -message Job { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Specification of the desired behavior of a job. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional JobSpec spec = 2; - - // Current status of a job. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional JobStatus status = 3; -} - -// JobCondition describes current state of a job. -message JobCondition { - // Type of job condition, Complete or Failed. - optional string type = 1; - - // Status of the condition, one of True, False, Unknown. - optional string status = 2; - - // Last time the condition was checked. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastProbeTime = 3; - - // Last time the condition transit from one status to another. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 4; - - // (brief) reason for the condition's last transition. - // +optional - optional string reason = 5; - - // Human readable message indicating details about last transition. - // +optional - optional string message = 6; -} - -// JobList is a collection of jobs. -message JobList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // items is the list of Jobs. - repeated Job items = 2; -} - -// JobSpec describes how the job execution will look like. -message JobSpec { - // Specifies the maximum desired number of pods the job should - // run at any given time. The actual number of pods running in steady state will - // be less than this number when ((.spec.completions - .status.successful) < .spec.parallelism), - // i.e. when the work left to do is less than max parallelism. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/ - // +optional - optional int32 parallelism = 1; - - // Specifies the desired number of successfully finished pods the - // job should be run with. Setting to nil means that the success of any - // pod signals the success of all pods, and allows parallelism to have any positive - // value. Setting to 1 means that parallelism is limited to 1 and the success of that - // pod signals the success of the job. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/ - // +optional - optional int32 completions = 2; - - // Specifies the duration in seconds relative to the startTime that the job may be active - // before the system tries to terminate it; value must be positive integer - // +optional - optional int64 activeDeadlineSeconds = 3; - - // Specifies the number of retries before marking this job failed. - // Defaults to 6 - // +optional - optional int32 backoffLimit = 7; - - // A label query over pods that should match the pod count. - // Normally, the system sets this field for you. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 4; - - // manualSelector controls generation of pod labels and pod selectors. - // Leave `manualSelector` unset unless you are certain what you are doing. - // When false or unset, the system pick labels unique to this job - // and appends those labels to the pod template. When true, - // the user is responsible for picking unique labels and specifying - // the selector. Failure to pick a unique label may cause this - // and other jobs to not function correctly. However, You may see - // `manualSelector=true` in jobs that were created with the old `extensions/v1beta1` - // API. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/#specifying-your-own-pod-selector - // +optional - optional bool manualSelector = 5; - - // Describes the pod that will be created when executing a job. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/ - optional k8s.io.api.core.v1.PodTemplateSpec template = 6; - - // ttlSecondsAfterFinished limits the lifetime of a Job that has finished - // execution (either Complete or Failed). If this field is set, - // ttlSecondsAfterFinished after the Job finishes, it is eligible to be - // automatically deleted. When the Job is being deleted, its lifecycle - // guarantees (e.g. finalizers) will be honored. If this field is unset, - // the Job won't be automatically deleted. If this field is set to zero, - // the Job becomes eligible to be deleted immediately after it finishes. - // This field is alpha-level and is only honored by servers that enable the - // TTLAfterFinished feature. - // +optional - optional int32 ttlSecondsAfterFinished = 8; -} - -// JobStatus represents the current state of a Job. -message JobStatus { - // The latest available observations of an object's current state. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/ - // +optional - // +patchMergeKey=type - // +patchStrategy=merge - repeated JobCondition conditions = 1; - - // Represents time when the job was acknowledged by the job controller. - // It is not guaranteed to be set in happens-before order across separate operations. - // It is represented in RFC3339 form and is in UTC. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time startTime = 2; - - // Represents time when the job was completed. It is not guaranteed to - // be set in happens-before order across separate operations. - // It is represented in RFC3339 form and is in UTC. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time completionTime = 3; - - // The number of actively running pods. - // +optional - optional int32 active = 4; - - // The number of pods which reached phase Succeeded. - // +optional - optional int32 succeeded = 5; - - // The number of pods which reached phase Failed. - // +optional - optional int32 failed = 6; -} - diff --git a/vendor/k8s.io/api/batch/v1beta1/generated.proto b/vendor/k8s.io/api/batch/v1beta1/generated.proto deleted file mode 100644 index 043b3551b0..0000000000 --- a/vendor/k8s.io/api/batch/v1beta1/generated.proto +++ /dev/null @@ -1,137 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.batch.v1beta1; - -import "k8s.io/api/batch/v1/generated.proto"; -import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1beta1"; - -// CronJob represents the configuration of a single cron job. -message CronJob { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Specification of the desired behavior of a cron job, including the schedule. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional CronJobSpec spec = 2; - - // Current status of a cron job. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional CronJobStatus status = 3; -} - -// CronJobList is a collection of cron jobs. -message CronJobList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // items is the list of CronJobs. - repeated CronJob items = 2; -} - -// CronJobSpec describes how the job execution will look like and when it will actually run. -message CronJobSpec { - // The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. - optional string schedule = 1; - - // Optional deadline in seconds for starting the job if it misses scheduled - // time for any reason. Missed jobs executions will be counted as failed ones. - // +optional - optional int64 startingDeadlineSeconds = 2; - - // Specifies how to treat concurrent executions of a Job. - // Valid values are: - // - "Allow" (default): allows CronJobs to run concurrently; - // - "Forbid": forbids concurrent runs, skipping next run if previous run hasn't finished yet; - // - "Replace": cancels currently running job and replaces it with a new one - // +optional - optional string concurrencyPolicy = 3; - - // This flag tells the controller to suspend subsequent executions, it does - // not apply to already started executions. Defaults to false. - // +optional - optional bool suspend = 4; - - // Specifies the job that will be created when executing a CronJob. - optional JobTemplateSpec jobTemplate = 5; - - // The number of successful finished jobs to retain. - // This is a pointer to distinguish between explicit zero and not specified. - // Defaults to 3. - // +optional - optional int32 successfulJobsHistoryLimit = 6; - - // The number of failed finished jobs to retain. - // This is a pointer to distinguish between explicit zero and not specified. - // Defaults to 1. - // +optional - optional int32 failedJobsHistoryLimit = 7; -} - -// CronJobStatus represents the current state of a cron job. -message CronJobStatus { - // A list of pointers to currently running jobs. - // +optional - repeated k8s.io.api.core.v1.ObjectReference active = 1; - - // Information when was the last time the job was successfully scheduled. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastScheduleTime = 4; -} - -// JobTemplate describes a template for creating copies of a predefined pod. -message JobTemplate { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Defines jobs that will be created from this template. - // https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional JobTemplateSpec template = 2; -} - -// JobTemplateSpec describes the data a Job should have when created from a template -message JobTemplateSpec { - // Standard object's metadata of the jobs created from this template. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Specification of the desired behavior of the job. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional k8s.io.api.batch.v1.JobSpec spec = 2; -} - diff --git a/vendor/k8s.io/api/batch/v2alpha1/generated.proto b/vendor/k8s.io/api/batch/v2alpha1/generated.proto deleted file mode 100644 index 4321c3361e..0000000000 --- a/vendor/k8s.io/api/batch/v2alpha1/generated.proto +++ /dev/null @@ -1,135 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.batch.v2alpha1; - -import "k8s.io/api/batch/v1/generated.proto"; -import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v2alpha1"; - -// CronJob represents the configuration of a single cron job. -message CronJob { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Specification of the desired behavior of a cron job, including the schedule. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional CronJobSpec spec = 2; - - // Current status of a cron job. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional CronJobStatus status = 3; -} - -// CronJobList is a collection of cron jobs. -message CronJobList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // items is the list of CronJobs. - repeated CronJob items = 2; -} - -// CronJobSpec describes how the job execution will look like and when it will actually run. -message CronJobSpec { - // The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. - optional string schedule = 1; - - // Optional deadline in seconds for starting the job if it misses scheduled - // time for any reason. Missed jobs executions will be counted as failed ones. - // +optional - optional int64 startingDeadlineSeconds = 2; - - // Specifies how to treat concurrent executions of a Job. - // Valid values are: - // - "Allow" (default): allows CronJobs to run concurrently; - // - "Forbid": forbids concurrent runs, skipping next run if previous run hasn't finished yet; - // - "Replace": cancels currently running job and replaces it with a new one - // +optional - optional string concurrencyPolicy = 3; - - // This flag tells the controller to suspend subsequent executions, it does - // not apply to already started executions. Defaults to false. - // +optional - optional bool suspend = 4; - - // Specifies the job that will be created when executing a CronJob. - optional JobTemplateSpec jobTemplate = 5; - - // The number of successful finished jobs to retain. - // This is a pointer to distinguish between explicit zero and not specified. - // +optional - optional int32 successfulJobsHistoryLimit = 6; - - // The number of failed finished jobs to retain. - // This is a pointer to distinguish between explicit zero and not specified. - // +optional - optional int32 failedJobsHistoryLimit = 7; -} - -// CronJobStatus represents the current state of a cron job. -message CronJobStatus { - // A list of pointers to currently running jobs. - // +optional - repeated k8s.io.api.core.v1.ObjectReference active = 1; - - // Information when was the last time the job was successfully scheduled. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastScheduleTime = 4; -} - -// JobTemplate describes a template for creating copies of a predefined pod. -message JobTemplate { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Defines jobs that will be created from this template. - // https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional JobTemplateSpec template = 2; -} - -// JobTemplateSpec describes the data a Job should have when created from a template -message JobTemplateSpec { - // Standard object's metadata of the jobs created from this template. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Specification of the desired behavior of the job. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional k8s.io.api.batch.v1.JobSpec spec = 2; -} - diff --git a/vendor/k8s.io/api/certificates/v1beta1/generated.proto b/vendor/k8s.io/api/certificates/v1beta1/generated.proto deleted file mode 100644 index 5200224a2f..0000000000 --- a/vendor/k8s.io/api/certificates/v1beta1/generated.proto +++ /dev/null @@ -1,121 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.certificates.v1beta1; - -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1beta1"; - -// Describes a certificate signing request -message CertificateSigningRequest { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // The certificate request itself and any additional information. - // +optional - optional CertificateSigningRequestSpec spec = 2; - - // Derived information about the request. - // +optional - optional CertificateSigningRequestStatus status = 3; -} - -message CertificateSigningRequestCondition { - // request approval state, currently Approved or Denied. - optional string type = 1; - - // brief reason for the request state - // +optional - optional string reason = 2; - - // human readable message with details about the request state - // +optional - optional string message = 3; - - // timestamp for the last update to this condition - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastUpdateTime = 4; -} - -message CertificateSigningRequestList { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - repeated CertificateSigningRequest items = 2; -} - -// This information is immutable after the request is created. Only the Request -// and Usages fields can be set on creation, other fields are derived by -// Kubernetes and cannot be modified by users. -message CertificateSigningRequestSpec { - // Base64-encoded PKCS#10 CSR data - optional bytes request = 1; - - // allowedUsages specifies a set of usage contexts the key will be - // valid for. - // See: https://tools.ietf.org/html/rfc5280#section-4.2.1.3 - // https://tools.ietf.org/html/rfc5280#section-4.2.1.12 - repeated string usages = 5; - - // Information about the requesting user. - // See user.Info interface for details. - // +optional - optional string username = 2; - - // UID information about the requesting user. - // See user.Info interface for details. - // +optional - optional string uid = 3; - - // Group information about the requesting user. - // See user.Info interface for details. - // +optional - repeated string groups = 4; - - // Extra information about the requesting user. - // See user.Info interface for details. - // +optional - map extra = 6; -} - -message CertificateSigningRequestStatus { - // Conditions applied to the request, such as approval or denial. - // +optional - repeated CertificateSigningRequestCondition conditions = 1; - - // If request was approved, the controller will place the issued certificate here. - // +optional - optional bytes certificate = 2; -} - -// ExtraValue masks the value so protobuf can generate -// +protobuf.nullable=true -// +protobuf.options.(gogoproto.goproto_stringer)=false -message ExtraValue { - // items, if empty, will result in an empty slice - - repeated string items = 1; -} - diff --git a/vendor/k8s.io/api/coordination/v1beta1/generated.proto b/vendor/k8s.io/api/coordination/v1beta1/generated.proto deleted file mode 100644 index 918e0de1c7..0000000000 --- a/vendor/k8s.io/api/coordination/v1beta1/generated.proto +++ /dev/null @@ -1,80 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.coordination.v1beta1; - -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1beta1"; - -// Lease defines a lease concept. -message Lease { - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Specification of the Lease. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional LeaseSpec spec = 2; -} - -// LeaseList is a list of Lease objects. -message LeaseList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of schema objects. - repeated Lease items = 2; -} - -// LeaseSpec is a specification of a Lease. -message LeaseSpec { - // holderIdentity contains the identity of the holder of a current lease. - // +optional - optional string holderIdentity = 1; - - // leaseDurationSeconds is a duration that candidates for a lease need - // to wait to force acquire it. This is measure against time of last - // observed RenewTime. - // +optional - optional int32 leaseDurationSeconds = 2; - - // acquireTime is a time when the current lease was acquired. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.MicroTime acquireTime = 3; - - // renewTime is a time when the current holder of a lease has last - // updated the lease. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.MicroTime renewTime = 4; - - // leaseTransitions is the number of transitions of a lease between - // holders. - // +optional - optional int32 leaseTransitions = 5; -} - diff --git a/vendor/k8s.io/api/core/v1/generated.proto b/vendor/k8s.io/api/core/v1/generated.proto deleted file mode 100644 index c76482ffbd..0000000000 --- a/vendor/k8s.io/api/core/v1/generated.proto +++ /dev/null @@ -1,4765 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.core.v1; - -import "k8s.io/apimachinery/pkg/api/resource/generated.proto"; -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1"; - -// Represents a Persistent Disk resource in AWS. -// -// An AWS EBS disk must exist before mounting to a container. The disk -// must also be in the same AWS zone as the kubelet. An AWS EBS disk -// can only be mounted as read/write once. AWS EBS volumes support -// ownership management and SELinux relabeling. -message AWSElasticBlockStoreVolumeSource { - // Unique ID of the persistent disk resource in AWS (Amazon EBS volume). - // More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - optional string volumeID = 1; - - // Filesystem type of the volume that you want to mount. - // Tip: Ensure that the filesystem type is supported by the host operating system. - // Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - // TODO: how do we prevent errors in the filesystem from compromising the machine - // +optional - optional string fsType = 2; - - // The partition in the volume that you want to mount. - // If omitted, the default is to mount by volume name. - // Examples: For volume /dev/sda1, you specify the partition as "1". - // Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty). - // +optional - optional int32 partition = 3; - - // Specify "true" to force and set the ReadOnly property in VolumeMounts to "true". - // If omitted, the default is "false". - // More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - // +optional - optional bool readOnly = 4; -} - -// Affinity is a group of affinity scheduling rules. -message Affinity { - // Describes node affinity scheduling rules for the pod. - // +optional - optional NodeAffinity nodeAffinity = 1; - - // Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). - // +optional - optional PodAffinity podAffinity = 2; - - // Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). - // +optional - optional PodAntiAffinity podAntiAffinity = 3; -} - -// AttachedVolume describes a volume attached to a node -message AttachedVolume { - // Name of the attached volume - optional string name = 1; - - // DevicePath represents the device path where the volume should be available - optional string devicePath = 2; -} - -// AvoidPods describes pods that should avoid this node. This is the value for a -// Node annotation with key scheduler.alpha.kubernetes.io/preferAvoidPods and -// will eventually become a field of NodeStatus. -message AvoidPods { - // Bounded-sized list of signatures of pods that should avoid this node, sorted - // in timestamp order from oldest to newest. Size of the slice is unspecified. - // +optional - repeated PreferAvoidPodsEntry preferAvoidPods = 1; -} - -// AzureDisk represents an Azure Data Disk mount on the host and bind mount to the pod. -message AzureDiskVolumeSource { - // The Name of the data disk in the blob storage - optional string diskName = 1; - - // The URI the data disk in the blob storage - optional string diskURI = 2; - - // Host Caching mode: None, Read Only, Read Write. - // +optional - optional string cachingMode = 3; - - // Filesystem type to mount. - // Must be a filesystem type supported by the host operating system. - // Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - // +optional - optional string fsType = 4; - - // Defaults to false (read/write). ReadOnly here will force - // the ReadOnly setting in VolumeMounts. - // +optional - optional bool readOnly = 5; - - // Expected values Shared: multiple blob disks per storage account Dedicated: single blob disk per storage account Managed: azure managed data disk (only in managed availability set). defaults to shared - optional string kind = 6; -} - -// AzureFile represents an Azure File Service mount on the host and bind mount to the pod. -message AzureFilePersistentVolumeSource { - // the name of secret that contains Azure Storage Account Name and Key - optional string secretName = 1; - - // Share Name - optional string shareName = 2; - - // Defaults to false (read/write). ReadOnly here will force - // the ReadOnly setting in VolumeMounts. - // +optional - optional bool readOnly = 3; - - // the namespace of the secret that contains Azure Storage Account Name and Key - // default is the same as the Pod - // +optional - optional string secretNamespace = 4; -} - -// AzureFile represents an Azure File Service mount on the host and bind mount to the pod. -message AzureFileVolumeSource { - // the name of secret that contains Azure Storage Account Name and Key - optional string secretName = 1; - - // Share Name - optional string shareName = 2; - - // Defaults to false (read/write). ReadOnly here will force - // the ReadOnly setting in VolumeMounts. - // +optional - optional bool readOnly = 3; -} - -// Binding ties one object to another; for example, a pod is bound to a node by a scheduler. -// Deprecated in 1.7, please use the bindings subresource of pods instead. -message Binding { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // The target object that you want to bind to the standard object. - optional ObjectReference target = 2; -} - -// Represents storage that is managed by an external CSI volume driver (Beta feature) -message CSIPersistentVolumeSource { - // Driver is the name of the driver to use for this volume. - // Required. - optional string driver = 1; - - // VolumeHandle is the unique volume name returned by the CSI volume - // plugin’s CreateVolume to refer to the volume on all subsequent calls. - // Required. - optional string volumeHandle = 2; - - // Optional: The value to pass to ControllerPublishVolumeRequest. - // Defaults to false (read/write). - // +optional - optional bool readOnly = 3; - - // Filesystem type to mount. - // Must be a filesystem type supported by the host operating system. - // Ex. "ext4", "xfs", "ntfs". - // +optional - optional string fsType = 4; - - // Attributes of the volume to publish. - // +optional - map volumeAttributes = 5; - - // ControllerPublishSecretRef is a reference to the secret object containing - // sensitive information to pass to the CSI driver to complete the CSI - // ControllerPublishVolume and ControllerUnpublishVolume calls. - // This field is optional, and may be empty if no secret is required. If the - // secret object contains more than one secret, all secrets are passed. - // +optional - optional SecretReference controllerPublishSecretRef = 6; - - // NodeStageSecretRef is a reference to the secret object containing sensitive - // information to pass to the CSI driver to complete the CSI NodeStageVolume - // and NodeStageVolume and NodeUnstageVolume calls. - // This field is optional, and may be empty if no secret is required. If the - // secret object contains more than one secret, all secrets are passed. - // +optional - optional SecretReference nodeStageSecretRef = 7; - - // NodePublishSecretRef is a reference to the secret object containing - // sensitive information to pass to the CSI driver to complete the CSI - // NodePublishVolume and NodeUnpublishVolume calls. - // This field is optional, and may be empty if no secret is required. If the - // secret object contains more than one secret, all secrets are passed. - // +optional - optional SecretReference nodePublishSecretRef = 8; -} - -// Adds and removes POSIX capabilities from running containers. -message Capabilities { - // Added capabilities - // +optional - repeated string add = 1; - - // Removed capabilities - // +optional - repeated string drop = 2; -} - -// Represents a Ceph Filesystem mount that lasts the lifetime of a pod -// Cephfs volumes do not support ownership management or SELinux relabeling. -message CephFSPersistentVolumeSource { - // Required: Monitors is a collection of Ceph monitors - // More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it - repeated string monitors = 1; - - // Optional: Used as the mounted root, rather than the full Ceph tree, default is / - // +optional - optional string path = 2; - - // Optional: User is the rados user name, default is admin - // More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it - // +optional - optional string user = 3; - - // Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret - // More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it - // +optional - optional string secretFile = 4; - - // Optional: SecretRef is reference to the authentication secret for User, default is empty. - // More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it - // +optional - optional SecretReference secretRef = 5; - - // Optional: Defaults to false (read/write). ReadOnly here will force - // the ReadOnly setting in VolumeMounts. - // More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it - // +optional - optional bool readOnly = 6; -} - -// Represents a Ceph Filesystem mount that lasts the lifetime of a pod -// Cephfs volumes do not support ownership management or SELinux relabeling. -message CephFSVolumeSource { - // Required: Monitors is a collection of Ceph monitors - // More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it - repeated string monitors = 1; - - // Optional: Used as the mounted root, rather than the full Ceph tree, default is / - // +optional - optional string path = 2; - - // Optional: User is the rados user name, default is admin - // More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it - // +optional - optional string user = 3; - - // Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret - // More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it - // +optional - optional string secretFile = 4; - - // Optional: SecretRef is reference to the authentication secret for User, default is empty. - // More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it - // +optional - optional LocalObjectReference secretRef = 5; - - // Optional: Defaults to false (read/write). ReadOnly here will force - // the ReadOnly setting in VolumeMounts. - // More info: https://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it - // +optional - optional bool readOnly = 6; -} - -// Represents a cinder volume resource in Openstack. -// A Cinder volume must exist before mounting to a container. -// The volume must also be in the same region as the kubelet. -// Cinder volumes support ownership management and SELinux relabeling. -message CinderPersistentVolumeSource { - // volume id used to identify the volume in cinder - // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md - optional string volumeID = 1; - - // Filesystem type to mount. - // Must be a filesystem type supported by the host operating system. - // Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md - // +optional - optional string fsType = 2; - - // Optional: Defaults to false (read/write). ReadOnly here will force - // the ReadOnly setting in VolumeMounts. - // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md - // +optional - optional bool readOnly = 3; - - // Optional: points to a secret object containing parameters used to connect - // to OpenStack. - // +optional - optional SecretReference secretRef = 4; -} - -// Represents a cinder volume resource in Openstack. -// A Cinder volume must exist before mounting to a container. -// The volume must also be in the same region as the kubelet. -// Cinder volumes support ownership management and SELinux relabeling. -message CinderVolumeSource { - // volume id used to identify the volume in cinder - // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md - optional string volumeID = 1; - - // Filesystem type to mount. - // Must be a filesystem type supported by the host operating system. - // Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md - // +optional - optional string fsType = 2; - - // Optional: Defaults to false (read/write). ReadOnly here will force - // the ReadOnly setting in VolumeMounts. - // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md - // +optional - optional bool readOnly = 3; - - // Optional: points to a secret object containing parameters used to connect - // to OpenStack. - // +optional - optional LocalObjectReference secretRef = 4; -} - -// ClientIPConfig represents the configurations of Client IP based session affinity. -message ClientIPConfig { - // timeoutSeconds specifies the seconds of ClientIP type session sticky time. - // The value must be >0 && <=86400(for 1 day) if ServiceAffinity == "ClientIP". - // Default value is 10800(for 3 hours). - // +optional - optional int32 timeoutSeconds = 1; -} - -// Information about the condition of a component. -message ComponentCondition { - // Type of condition for a component. - // Valid value: "Healthy" - optional string type = 1; - - // Status of the condition for a component. - // Valid values for "Healthy": "True", "False", or "Unknown". - optional string status = 2; - - // Message about the condition for a component. - // For example, information about a health check. - // +optional - optional string message = 3; - - // Condition error code for a component. - // For example, a health check error code. - // +optional - optional string error = 4; -} - -// ComponentStatus (and ComponentStatusList) holds the cluster validation info. -message ComponentStatus { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // List of component conditions observed - // +optional - // +patchMergeKey=type - // +patchStrategy=merge - repeated ComponentCondition conditions = 2; -} - -// Status of all the conditions for the component as a list of ComponentStatus objects. -message ComponentStatusList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // List of ComponentStatus objects. - repeated ComponentStatus items = 2; -} - -// ConfigMap holds configuration data for pods to consume. -message ConfigMap { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Data contains the configuration data. - // Each key must consist of alphanumeric characters, '-', '_' or '.'. - // Values with non-UTF-8 byte sequences must use the BinaryData field. - // The keys stored in Data must not overlap with the keys in - // the BinaryData field, this is enforced during validation process. - // +optional - map data = 2; - - // BinaryData contains the binary data. - // Each key must consist of alphanumeric characters, '-', '_' or '.'. - // BinaryData can contain byte sequences that are not in the UTF-8 range. - // The keys stored in BinaryData must not overlap with the ones in - // the Data field, this is enforced during validation process. - // Using this field will require 1.10+ apiserver and - // kubelet. - // +optional - map binaryData = 3; -} - -// ConfigMapEnvSource selects a ConfigMap to populate the environment -// variables with. -// -// The contents of the target ConfigMap's Data field will represent the -// key-value pairs as environment variables. -message ConfigMapEnvSource { - // The ConfigMap to select from. - optional LocalObjectReference localObjectReference = 1; - - // Specify whether the ConfigMap must be defined - // +optional - optional bool optional = 2; -} - -// Selects a key from a ConfigMap. -message ConfigMapKeySelector { - // The ConfigMap to select from. - optional LocalObjectReference localObjectReference = 1; - - // The key to select. - optional string key = 2; - - // Specify whether the ConfigMap or it's key must be defined - // +optional - optional bool optional = 3; -} - -// ConfigMapList is a resource containing a list of ConfigMap objects. -message ConfigMapList { - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is the list of ConfigMaps. - repeated ConfigMap items = 2; -} - -// ConfigMapNodeConfigSource contains the information to reference a ConfigMap as a config source for the Node. -message ConfigMapNodeConfigSource { - // Namespace is the metadata.namespace of the referenced ConfigMap. - // This field is required in all cases. - optional string namespace = 1; - - // Name is the metadata.name of the referenced ConfigMap. - // This field is required in all cases. - optional string name = 2; - - // UID is the metadata.UID of the referenced ConfigMap. - // This field is forbidden in Node.Spec, and required in Node.Status. - // +optional - optional string uid = 3; - - // ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap. - // This field is forbidden in Node.Spec, and required in Node.Status. - // +optional - optional string resourceVersion = 4; - - // KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure - // This field is required in all cases. - optional string kubeletConfigKey = 5; -} - -// Adapts a ConfigMap into a projected volume. -// -// The contents of the target ConfigMap's Data field will be presented in a -// projected volume as files using the keys in the Data field as the file names, -// unless the items element is populated with specific mappings of keys to paths. -// Note that this is identical to a configmap volume source without the default -// mode. -message ConfigMapProjection { - optional LocalObjectReference localObjectReference = 1; - - // If unspecified, each key-value pair in the Data field of the referenced - // ConfigMap will be projected into the volume as a file whose name is the - // key and content is the value. If specified, the listed keys will be - // projected into the specified paths, and unlisted keys will not be - // present. If a key is specified which is not present in the ConfigMap, - // the volume setup will error unless it is marked optional. Paths must be - // relative and may not contain the '..' path or start with '..'. - // +optional - repeated KeyToPath items = 2; - - // Specify whether the ConfigMap or it's keys must be defined - // +optional - optional bool optional = 4; -} - -// Adapts a ConfigMap into a volume. -// -// The contents of the target ConfigMap's Data field will be presented in a -// volume as files using the keys in the Data field as the file names, unless -// the items element is populated with specific mappings of keys to paths. -// ConfigMap volumes support ownership management and SELinux relabeling. -message ConfigMapVolumeSource { - optional LocalObjectReference localObjectReference = 1; - - // If unspecified, each key-value pair in the Data field of the referenced - // ConfigMap will be projected into the volume as a file whose name is the - // key and content is the value. If specified, the listed keys will be - // projected into the specified paths, and unlisted keys will not be - // present. If a key is specified which is not present in the ConfigMap, - // the volume setup will error unless it is marked optional. Paths must be - // relative and may not contain the '..' path or start with '..'. - // +optional - repeated KeyToPath items = 2; - - // Optional: mode bits to use on created files by default. Must be a - // value between 0 and 0777. Defaults to 0644. - // Directories within the path are not affected by this setting. - // This might be in conflict with other options that affect the file - // mode, like fsGroup, and the result can be other mode bits set. - // +optional - optional int32 defaultMode = 3; - - // Specify whether the ConfigMap or it's keys must be defined - // +optional - optional bool optional = 4; -} - -// A single application container that you want to run within a pod. -message Container { - // Name of the container specified as a DNS_LABEL. - // Each container in a pod must have a unique name (DNS_LABEL). - // Cannot be updated. - optional string name = 1; - - // Docker image name. - // More info: https://kubernetes.io/docs/concepts/containers/images - // This field is optional to allow higher level config management to default or override - // container images in workload controllers like Deployments and StatefulSets. - // +optional - optional string image = 2; - - // Entrypoint array. Not executed within a shell. - // The docker image's ENTRYPOINT is used if this is not provided. - // Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - // cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax - // can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, - // regardless of whether the variable exists or not. - // Cannot be updated. - // More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - // +optional - repeated string command = 3; - - // Arguments to the entrypoint. - // The docker image's CMD is used if this is not provided. - // Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - // cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax - // can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, - // regardless of whether the variable exists or not. - // Cannot be updated. - // More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - // +optional - repeated string args = 4; - - // Container's working directory. - // If not specified, the container runtime's default will be used, which - // might be configured in the container image. - // Cannot be updated. - // +optional - optional string workingDir = 5; - - // List of ports to expose from the container. Exposing a port here gives - // the system additional information about the network connections a - // container uses, but is primarily informational. Not specifying a port here - // DOES NOT prevent that port from being exposed. Any port which is - // listening on the default "0.0.0.0" address inside a container will be - // accessible from the network. - // Cannot be updated. - // +optional - // +patchMergeKey=containerPort - // +patchStrategy=merge - // +listType=map - // +listMapKey=containerPort - // +listMapKey=protocol - repeated ContainerPort ports = 6; - - // List of sources to populate environment variables in the container. - // The keys defined within a source must be a C_IDENTIFIER. All invalid keys - // will be reported as an event when the container is starting. When a key exists in multiple - // sources, the value associated with the last source will take precedence. - // Values defined by an Env with a duplicate key will take precedence. - // Cannot be updated. - // +optional - repeated EnvFromSource envFrom = 19; - - // List of environment variables to set in the container. - // Cannot be updated. - // +optional - // +patchMergeKey=name - // +patchStrategy=merge - repeated EnvVar env = 7; - - // Compute Resources required by this container. - // Cannot be updated. - // More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ - // +optional - optional ResourceRequirements resources = 8; - - // Pod volumes to mount into the container's filesystem. - // Cannot be updated. - // +optional - // +patchMergeKey=mountPath - // +patchStrategy=merge - repeated VolumeMount volumeMounts = 9; - - // volumeDevices is the list of block devices to be used by the container. - // This is an alpha feature and may change in the future. - // +patchMergeKey=devicePath - // +patchStrategy=merge - // +optional - repeated VolumeDevice volumeDevices = 21; - - // Periodic probe of container liveness. - // Container will be restarted if the probe fails. - // Cannot be updated. - // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - // +optional - optional Probe livenessProbe = 10; - - // Periodic probe of container service readiness. - // Container will be removed from service endpoints if the probe fails. - // Cannot be updated. - // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - // +optional - optional Probe readinessProbe = 11; - - // Actions that the management system should take in response to container lifecycle events. - // Cannot be updated. - // +optional - optional Lifecycle lifecycle = 12; - - // Optional: Path at which the file to which the container's termination message - // will be written is mounted into the container's filesystem. - // Message written is intended to be brief final status, such as an assertion failure message. - // Will be truncated by the node if greater than 4096 bytes. The total message length across - // all containers will be limited to 12kb. - // Defaults to /dev/termination-log. - // Cannot be updated. - // +optional - optional string terminationMessagePath = 13; - - // Indicate how the termination message should be populated. File will use the contents of - // terminationMessagePath to populate the container status message on both success and failure. - // FallbackToLogsOnError will use the last chunk of container log output if the termination - // message file is empty and the container exited with an error. - // The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - // Defaults to File. - // Cannot be updated. - // +optional - optional string terminationMessagePolicy = 20; - - // Image pull policy. - // One of Always, Never, IfNotPresent. - // Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - // Cannot be updated. - // More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - // +optional - optional string imagePullPolicy = 14; - - // Security options the pod should run with. - // More info: https://kubernetes.io/docs/concepts/policy/security-context/ - // More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - // +optional - optional SecurityContext securityContext = 15; - - // Whether this container should allocate a buffer for stdin in the container runtime. If this - // is not set, reads from stdin in the container will always result in EOF. - // Default is false. - // +optional - optional bool stdin = 16; - - // Whether the container runtime should close the stdin channel after it has been opened by - // a single attach. When stdin is true the stdin stream will remain open across multiple attach - // sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - // first client attaches to stdin, and then remains open and accepts data until the client disconnects, - // at which time stdin is closed and remains closed until the container is restarted. If this - // flag is false, a container processes that reads from stdin will never receive an EOF. - // Default is false - // +optional - optional bool stdinOnce = 17; - - // Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - // Default is false. - // +optional - optional bool tty = 18; -} - -// Describe a container image -message ContainerImage { - // Names by which this image is known. - // e.g. ["k8s.gcr.io/hyperkube:v1.0.7", "dockerhub.io/google_containers/hyperkube:v1.0.7"] - repeated string names = 1; - - // The size of the image in bytes. - // +optional - optional int64 sizeBytes = 2; -} - -// ContainerPort represents a network port in a single container. -message ContainerPort { - // If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - // named port in a pod must have a unique name. Name for the port that can be - // referred to by services. - // +optional - optional string name = 1; - - // Number of port to expose on the host. - // If specified, this must be a valid port number, 0 < x < 65536. - // If HostNetwork is specified, this must match ContainerPort. - // Most containers do not need this. - // +optional - optional int32 hostPort = 2; - - // Number of port to expose on the pod's IP address. - // This must be a valid port number, 0 < x < 65536. - optional int32 containerPort = 3; - - // Protocol for port. Must be UDP, TCP, or SCTP. - // Defaults to "TCP". - // +optional - optional string protocol = 4; - - // What host IP to bind the external port to. - // +optional - optional string hostIP = 5; -} - -// ContainerState holds a possible state of container. -// Only one of its members may be specified. -// If none of them is specified, the default one is ContainerStateWaiting. -message ContainerState { - // Details about a waiting container - // +optional - optional ContainerStateWaiting waiting = 1; - - // Details about a running container - // +optional - optional ContainerStateRunning running = 2; - - // Details about a terminated container - // +optional - optional ContainerStateTerminated terminated = 3; -} - -// ContainerStateRunning is a running state of a container. -message ContainerStateRunning { - // Time at which the container was last (re-)started - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time startedAt = 1; -} - -// ContainerStateTerminated is a terminated state of a container. -message ContainerStateTerminated { - // Exit status from the last termination of the container - optional int32 exitCode = 1; - - // Signal from the last termination of the container - // +optional - optional int32 signal = 2; - - // (brief) reason from the last termination of the container - // +optional - optional string reason = 3; - - // Message regarding the last termination of the container - // +optional - optional string message = 4; - - // Time at which previous execution of the container started - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time startedAt = 5; - - // Time at which the container last terminated - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time finishedAt = 6; - - // Container's ID in the format 'docker://' - // +optional - optional string containerID = 7; -} - -// ContainerStateWaiting is a waiting state of a container. -message ContainerStateWaiting { - // (brief) reason the container is not yet running. - // +optional - optional string reason = 1; - - // Message regarding why the container is not yet running. - // +optional - optional string message = 2; -} - -// ContainerStatus contains details for the current status of this container. -message ContainerStatus { - // This must be a DNS_LABEL. Each container in a pod must have a unique name. - // Cannot be updated. - optional string name = 1; - - // Details about the container's current condition. - // +optional - optional ContainerState state = 2; - - // Details about the container's last termination condition. - // +optional - optional ContainerState lastState = 3; - - // Specifies whether the container has passed its readiness probe. - optional bool ready = 4; - - // The number of times the container has been restarted, currently based on - // the number of dead containers that have not yet been removed. - // Note that this is calculated from dead containers. But those containers are subject to - // garbage collection. This value will get capped at 5 by GC. - optional int32 restartCount = 5; - - // The image the container is running. - // More info: https://kubernetes.io/docs/concepts/containers/images - // TODO(dchen1107): Which image the container is running with? - optional string image = 6; - - // ImageID of the container's image. - optional string imageID = 7; - - // Container's ID in the format 'docker://'. - // +optional - optional string containerID = 8; -} - -// DaemonEndpoint contains information about a single Daemon endpoint. -message DaemonEndpoint { - // Port number of the given endpoint. - optional int32 Port = 1; -} - -// Represents downward API info for projecting into a projected volume. -// Note that this is identical to a downwardAPI volume source without the default -// mode. -message DownwardAPIProjection { - // Items is a list of DownwardAPIVolume file - // +optional - repeated DownwardAPIVolumeFile items = 1; -} - -// DownwardAPIVolumeFile represents information to create the file containing the pod field -message DownwardAPIVolumeFile { - // Required: Path is the relative path name of the file to be created. Must not be absolute or contain the '..' path. Must be utf-8 encoded. The first item of the relative path must not start with '..' - optional string path = 1; - - // Required: Selects a field of the pod: only annotations, labels, name and namespace are supported. - // +optional - optional ObjectFieldSelector fieldRef = 2; - - // Selects a resource of the container: only resources limits and requests - // (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported. - // +optional - optional ResourceFieldSelector resourceFieldRef = 3; - - // Optional: mode bits to use on this file, must be a value between 0 - // and 0777. If not specified, the volume defaultMode will be used. - // This might be in conflict with other options that affect the file - // mode, like fsGroup, and the result can be other mode bits set. - // +optional - optional int32 mode = 4; -} - -// DownwardAPIVolumeSource represents a volume containing downward API info. -// Downward API volumes support ownership management and SELinux relabeling. -message DownwardAPIVolumeSource { - // Items is a list of downward API volume file - // +optional - repeated DownwardAPIVolumeFile items = 1; - - // Optional: mode bits to use on created files by default. Must be a - // value between 0 and 0777. Defaults to 0644. - // Directories within the path are not affected by this setting. - // This might be in conflict with other options that affect the file - // mode, like fsGroup, and the result can be other mode bits set. - // +optional - optional int32 defaultMode = 2; -} - -// Represents an empty directory for a pod. -// Empty directory volumes support ownership management and SELinux relabeling. -message EmptyDirVolumeSource { - // What type of storage medium should back this directory. - // The default is "" which means to use the node's default medium. - // Must be an empty string (default) or Memory. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - // +optional - optional string medium = 1; - - // Total amount of local storage required for this EmptyDir volume. - // The size limit is also applicable for memory medium. - // The maximum usage on memory medium EmptyDir would be the minimum value between - // the SizeLimit specified here and the sum of memory limits of all containers in a pod. - // The default is nil which means that the limit is undefined. - // More info: http://kubernetes.io/docs/user-guide/volumes#emptydir - // +optional - optional k8s.io.apimachinery.pkg.api.resource.Quantity sizeLimit = 2; -} - -// EndpointAddress is a tuple that describes single IP address. -message EndpointAddress { - // The IP of this endpoint. - // May not be loopback (127.0.0.0/8), link-local (169.254.0.0/16), - // or link-local multicast ((224.0.0.0/24). - // IPv6 is also accepted but not fully supported on all platforms. Also, certain - // kubernetes components, like kube-proxy, are not IPv6 ready. - // TODO: This should allow hostname or IP, See #4447. - optional string ip = 1; - - // The Hostname of this endpoint - // +optional - optional string hostname = 3; - - // Optional: Node hosting this endpoint. This can be used to determine endpoints local to a node. - // +optional - optional string nodeName = 4; - - // Reference to object providing the endpoint. - // +optional - optional ObjectReference targetRef = 2; -} - -// EndpointPort is a tuple that describes a single port. -message EndpointPort { - // The name of this port (corresponds to ServicePort.Name). - // Must be a DNS_LABEL. - // Optional only if one port is defined. - // +optional - optional string name = 1; - - // The port number of the endpoint. - optional int32 port = 2; - - // The IP protocol for this port. - // Must be UDP, TCP, or SCTP. - // Default is TCP. - // +optional - optional string protocol = 3; -} - -// EndpointSubset is a group of addresses with a common set of ports. The -// expanded set of endpoints is the Cartesian product of Addresses x Ports. -// For example, given: -// { -// Addresses: [{"ip": "10.10.1.1"}, {"ip": "10.10.2.2"}], -// Ports: [{"name": "a", "port": 8675}, {"name": "b", "port": 309}] -// } -// The resulting set of endpoints can be viewed as: -// a: [ 10.10.1.1:8675, 10.10.2.2:8675 ], -// b: [ 10.10.1.1:309, 10.10.2.2:309 ] -message EndpointSubset { - // IP addresses which offer the related ports that are marked as ready. These endpoints - // should be considered safe for load balancers and clients to utilize. - // +optional - repeated EndpointAddress addresses = 1; - - // IP addresses which offer the related ports but are not currently marked as ready - // because they have not yet finished starting, have recently failed a readiness check, - // or have recently failed a liveness check. - // +optional - repeated EndpointAddress notReadyAddresses = 2; - - // Port numbers available on the related IP addresses. - // +optional - repeated EndpointPort ports = 3; -} - -// Endpoints is a collection of endpoints that implement the actual service. Example: -// Name: "mysvc", -// Subsets: [ -// { -// Addresses: [{"ip": "10.10.1.1"}, {"ip": "10.10.2.2"}], -// Ports: [{"name": "a", "port": 8675}, {"name": "b", "port": 309}] -// }, -// { -// Addresses: [{"ip": "10.10.3.3"}], -// Ports: [{"name": "a", "port": 93}, {"name": "b", "port": 76}] -// }, -// ] -message Endpoints { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // The set of all endpoints is the union of all subsets. Addresses are placed into - // subsets according to the IPs they share. A single address with multiple ports, - // some of which are ready and some of which are not (because they come from - // different containers) will result in the address being displayed in different - // subsets for the different ports. No address will appear in both Addresses and - // NotReadyAddresses in the same subset. - // Sets of addresses and ports that comprise a service. - // +optional - repeated EndpointSubset subsets = 2; -} - -// EndpointsList is a list of endpoints. -message EndpointsList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // List of endpoints. - repeated Endpoints items = 2; -} - -// EnvFromSource represents the source of a set of ConfigMaps -message EnvFromSource { - // An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER. - // +optional - optional string prefix = 1; - - // The ConfigMap to select from - // +optional - optional ConfigMapEnvSource configMapRef = 2; - - // The Secret to select from - // +optional - optional SecretEnvSource secretRef = 3; -} - -// EnvVar represents an environment variable present in a Container. -message EnvVar { - // Name of the environment variable. Must be a C_IDENTIFIER. - optional string name = 1; - - // Variable references $(VAR_NAME) are expanded - // using the previous defined environment variables in the container and - // any service environment variables. If a variable cannot be resolved, - // the reference in the input string will be unchanged. The $(VAR_NAME) - // syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped - // references will never be expanded, regardless of whether the variable - // exists or not. - // Defaults to "". - // +optional - optional string value = 2; - - // Source for the environment variable's value. Cannot be used if value is not empty. - // +optional - optional EnvVarSource valueFrom = 3; -} - -// EnvVarSource represents a source for the value of an EnvVar. -message EnvVarSource { - // Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, - // spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP. - // +optional - optional ObjectFieldSelector fieldRef = 1; - - // Selects a resource of the container: only resources limits and requests - // (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - // +optional - optional ResourceFieldSelector resourceFieldRef = 2; - - // Selects a key of a ConfigMap. - // +optional - optional ConfigMapKeySelector configMapKeyRef = 3; - - // Selects a key of a secret in the pod's namespace - // +optional - optional SecretKeySelector secretKeyRef = 4; -} - -// Event is a report of an event somewhere in the cluster. -message Event { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // The object that this event is about. - optional ObjectReference involvedObject = 2; - - // This should be a short, machine understandable string that gives the reason - // for the transition into the object's current status. - // TODO: provide exact specification for format. - // +optional - optional string reason = 3; - - // A human-readable description of the status of this operation. - // TODO: decide on maximum length. - // +optional - optional string message = 4; - - // The component reporting this event. Should be a short machine understandable string. - // +optional - optional EventSource source = 5; - - // The time at which the event was first recorded. (Time of server receipt is in TypeMeta.) - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time firstTimestamp = 6; - - // The time at which the most recent occurrence of this event was recorded. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTimestamp = 7; - - // The number of times this event has occurred. - // +optional - optional int32 count = 8; - - // Type of this event (Normal, Warning), new types could be added in the future - // +optional - optional string type = 9; - - // Time when this Event was first observed. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.MicroTime eventTime = 10; - - // Data about the Event series this event represents or nil if it's a singleton Event. - // +optional - optional EventSeries series = 11; - - // What action was taken/failed regarding to the Regarding object. - // +optional - optional string action = 12; - - // Optional secondary object for more complex actions. - // +optional - optional ObjectReference related = 13; - - // Name of the controller that emitted this Event, e.g. `kubernetes.io/kubelet`. - // +optional - optional string reportingComponent = 14; - - // ID of the controller instance, e.g. `kubelet-xyzf`. - // +optional - optional string reportingInstance = 15; -} - -// EventList is a list of events. -message EventList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // List of events - repeated Event items = 2; -} - -// EventSeries contain information on series of events, i.e. thing that was/is happening -// continuously for some time. -message EventSeries { - // Number of occurrences in this series up to the last heartbeat time - optional int32 count = 1; - - // Time of the last occurrence observed - optional k8s.io.apimachinery.pkg.apis.meta.v1.MicroTime lastObservedTime = 2; - - // State of this Series: Ongoing or Finished - optional string state = 3; -} - -// EventSource contains information for an event. -message EventSource { - // Component from which the event is generated. - // +optional - optional string component = 1; - - // Node name on which the event is generated. - // +optional - optional string host = 2; -} - -// ExecAction describes a "run in container" action. -message ExecAction { - // Command is the command line to execute inside the container, the working directory for the - // command is root ('/') in the container's filesystem. The command is simply exec'd, it is - // not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - // a shell, you need to explicitly call out to that shell. - // Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - // +optional - repeated string command = 1; -} - -// Represents a Fibre Channel volume. -// Fibre Channel volumes can only be mounted as read/write once. -// Fibre Channel volumes support ownership management and SELinux relabeling. -message FCVolumeSource { - // Optional: FC target worldwide names (WWNs) - // +optional - repeated string targetWWNs = 1; - - // Optional: FC target lun number - // +optional - optional int32 lun = 2; - - // Filesystem type to mount. - // Must be a filesystem type supported by the host operating system. - // Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - // TODO: how do we prevent errors in the filesystem from compromising the machine - // +optional - optional string fsType = 3; - - // Optional: Defaults to false (read/write). ReadOnly here will force - // the ReadOnly setting in VolumeMounts. - // +optional - optional bool readOnly = 4; - - // Optional: FC volume world wide identifiers (wwids) - // Either wwids or combination of targetWWNs and lun must be set, but not both simultaneously. - // +optional - repeated string wwids = 5; -} - -// FlexPersistentVolumeSource represents a generic persistent volume resource that is -// provisioned/attached using an exec based plugin. -message FlexPersistentVolumeSource { - // Driver is the name of the driver to use for this volume. - optional string driver = 1; - - // Filesystem type to mount. - // Must be a filesystem type supported by the host operating system. - // Ex. "ext4", "xfs", "ntfs". The default filesystem depends on FlexVolume script. - // +optional - optional string fsType = 2; - - // Optional: SecretRef is reference to the secret object containing - // sensitive information to pass to the plugin scripts. This may be - // empty if no secret object is specified. If the secret object - // contains more than one secret, all secrets are passed to the plugin - // scripts. - // +optional - optional SecretReference secretRef = 3; - - // Optional: Defaults to false (read/write). ReadOnly here will force - // the ReadOnly setting in VolumeMounts. - // +optional - optional bool readOnly = 4; - - // Optional: Extra command options if any. - // +optional - map options = 5; -} - -// FlexVolume represents a generic volume resource that is -// provisioned/attached using an exec based plugin. -message FlexVolumeSource { - // Driver is the name of the driver to use for this volume. - optional string driver = 1; - - // Filesystem type to mount. - // Must be a filesystem type supported by the host operating system. - // Ex. "ext4", "xfs", "ntfs". The default filesystem depends on FlexVolume script. - // +optional - optional string fsType = 2; - - // Optional: SecretRef is reference to the secret object containing - // sensitive information to pass to the plugin scripts. This may be - // empty if no secret object is specified. If the secret object - // contains more than one secret, all secrets are passed to the plugin - // scripts. - // +optional - optional LocalObjectReference secretRef = 3; - - // Optional: Defaults to false (read/write). ReadOnly here will force - // the ReadOnly setting in VolumeMounts. - // +optional - optional bool readOnly = 4; - - // Optional: Extra command options if any. - // +optional - map options = 5; -} - -// Represents a Flocker volume mounted by the Flocker agent. -// One and only one of datasetName and datasetUUID should be set. -// Flocker volumes do not support ownership management or SELinux relabeling. -message FlockerVolumeSource { - // Name of the dataset stored as metadata -> name on the dataset for Flocker - // should be considered as deprecated - // +optional - optional string datasetName = 1; - - // UUID of the dataset. This is unique identifier of a Flocker dataset - // +optional - optional string datasetUUID = 2; -} - -// Represents a Persistent Disk resource in Google Compute Engine. -// -// A GCE PD must exist before mounting to a container. The disk must -// also be in the same GCE project and zone as the kubelet. A GCE PD -// can only be mounted as read/write once or read-only many times. GCE -// PDs support ownership management and SELinux relabeling. -message GCEPersistentDiskVolumeSource { - // Unique name of the PD resource in GCE. Used to identify the disk in GCE. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - optional string pdName = 1; - - // Filesystem type of the volume that you want to mount. - // Tip: Ensure that the filesystem type is supported by the host operating system. - // Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - // TODO: how do we prevent errors in the filesystem from compromising the machine - // +optional - optional string fsType = 2; - - // The partition in the volume that you want to mount. - // If omitted, the default is to mount by volume name. - // Examples: For volume /dev/sda1, you specify the partition as "1". - // Similarly, the volume partition for /dev/sda is "0" (or you can leave the property empty). - // More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - // +optional - optional int32 partition = 3; - - // ReadOnly here will force the ReadOnly setting in VolumeMounts. - // Defaults to false. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - // +optional - optional bool readOnly = 4; -} - -// Represents a volume that is populated with the contents of a git repository. -// Git repo volumes do not support ownership management. -// Git repo volumes support SELinux relabeling. -// -// DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an -// EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir -// into the Pod's container. -message GitRepoVolumeSource { - // Repository URL - optional string repository = 1; - - // Commit hash for the specified revision. - // +optional - optional string revision = 2; - - // Target directory name. - // Must not contain or start with '..'. If '.' is supplied, the volume directory will be the - // git repository. Otherwise, if specified, the volume will contain the git repository in - // the subdirectory with the given name. - // +optional - optional string directory = 3; -} - -// Represents a Glusterfs mount that lasts the lifetime of a pod. -// Glusterfs volumes do not support ownership management or SELinux relabeling. -message GlusterfsVolumeSource { - // EndpointsName is the endpoint name that details Glusterfs topology. - // More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod - optional string endpoints = 1; - - // Path is the Glusterfs volume path. - // More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod - optional string path = 2; - - // ReadOnly here will force the Glusterfs volume to be mounted with read-only permissions. - // Defaults to false. - // More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod - // +optional - optional bool readOnly = 3; -} - -// HTTPGetAction describes an action based on HTTP Get requests. -message HTTPGetAction { - // Path to access on the HTTP server. - // +optional - optional string path = 1; - - // Name or number of the port to access on the container. - // Number must be in the range 1 to 65535. - // Name must be an IANA_SVC_NAME. - optional k8s.io.apimachinery.pkg.util.intstr.IntOrString port = 2; - - // Host name to connect to, defaults to the pod IP. You probably want to set - // "Host" in httpHeaders instead. - // +optional - optional string host = 3; - - // Scheme to use for connecting to the host. - // Defaults to HTTP. - // +optional - optional string scheme = 4; - - // Custom headers to set in the request. HTTP allows repeated headers. - // +optional - repeated HTTPHeader httpHeaders = 5; -} - -// HTTPHeader describes a custom header to be used in HTTP probes -message HTTPHeader { - // The header field name - optional string name = 1; - - // The header field value - optional string value = 2; -} - -// Handler defines a specific action that should be taken -// TODO: pass structured data to these actions, and document that data here. -message Handler { - // One and only one of the following should be specified. - // Exec specifies the action to take. - // +optional - optional ExecAction exec = 1; - - // HTTPGet specifies the http request to perform. - // +optional - optional HTTPGetAction httpGet = 2; - - // TCPSocket specifies an action involving a TCP port. - // TCP hooks not yet supported - // TODO: implement a realistic TCP lifecycle hook - // +optional - optional TCPSocketAction tcpSocket = 3; -} - -// HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the -// pod's hosts file. -message HostAlias { - // IP address of the host file entry. - optional string ip = 1; - - // Hostnames for the above IP address. - repeated string hostnames = 2; -} - -// Represents a host path mapped into a pod. -// Host path volumes do not support ownership management or SELinux relabeling. -message HostPathVolumeSource { - // Path of the directory on the host. - // If the path is a symlink, it will follow the link to the real path. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - optional string path = 1; - - // Type for HostPath Volume - // Defaults to "" - // More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - // +optional - optional string type = 2; -} - -// ISCSIPersistentVolumeSource represents an ISCSI disk. -// ISCSI volumes can only be mounted as read/write once. -// ISCSI volumes support ownership management and SELinux relabeling. -message ISCSIPersistentVolumeSource { - // iSCSI Target Portal. The Portal is either an IP or ip_addr:port if the port - // is other than default (typically TCP ports 860 and 3260). - optional string targetPortal = 1; - - // Target iSCSI Qualified Name. - optional string iqn = 2; - - // iSCSI Target Lun number. - optional int32 lun = 3; - - // iSCSI Interface Name that uses an iSCSI transport. - // Defaults to 'default' (tcp). - // +optional - optional string iscsiInterface = 4; - - // Filesystem type of the volume that you want to mount. - // Tip: Ensure that the filesystem type is supported by the host operating system. - // Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi - // TODO: how do we prevent errors in the filesystem from compromising the machine - // +optional - optional string fsType = 5; - - // ReadOnly here will force the ReadOnly setting in VolumeMounts. - // Defaults to false. - // +optional - optional bool readOnly = 6; - - // iSCSI Target Portal List. The Portal is either an IP or ip_addr:port if the port - // is other than default (typically TCP ports 860 and 3260). - // +optional - repeated string portals = 7; - - // whether support iSCSI Discovery CHAP authentication - // +optional - optional bool chapAuthDiscovery = 8; - - // whether support iSCSI Session CHAP authentication - // +optional - optional bool chapAuthSession = 11; - - // CHAP Secret for iSCSI target and initiator authentication - // +optional - optional SecretReference secretRef = 10; - - // Custom iSCSI Initiator Name. - // If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface - // : will be created for the connection. - // +optional - optional string initiatorName = 12; -} - -// Represents an ISCSI disk. -// ISCSI volumes can only be mounted as read/write once. -// ISCSI volumes support ownership management and SELinux relabeling. -message ISCSIVolumeSource { - // iSCSI Target Portal. The Portal is either an IP or ip_addr:port if the port - // is other than default (typically TCP ports 860 and 3260). - optional string targetPortal = 1; - - // Target iSCSI Qualified Name. - optional string iqn = 2; - - // iSCSI Target Lun number. - optional int32 lun = 3; - - // iSCSI Interface Name that uses an iSCSI transport. - // Defaults to 'default' (tcp). - // +optional - optional string iscsiInterface = 4; - - // Filesystem type of the volume that you want to mount. - // Tip: Ensure that the filesystem type is supported by the host operating system. - // Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi - // TODO: how do we prevent errors in the filesystem from compromising the machine - // +optional - optional string fsType = 5; - - // ReadOnly here will force the ReadOnly setting in VolumeMounts. - // Defaults to false. - // +optional - optional bool readOnly = 6; - - // iSCSI Target Portal List. The portal is either an IP or ip_addr:port if the port - // is other than default (typically TCP ports 860 and 3260). - // +optional - repeated string portals = 7; - - // whether support iSCSI Discovery CHAP authentication - // +optional - optional bool chapAuthDiscovery = 8; - - // whether support iSCSI Session CHAP authentication - // +optional - optional bool chapAuthSession = 11; - - // CHAP Secret for iSCSI target and initiator authentication - // +optional - optional LocalObjectReference secretRef = 10; - - // Custom iSCSI Initiator Name. - // If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface - // : will be created for the connection. - // +optional - optional string initiatorName = 12; -} - -// Maps a string key to a path within a volume. -message KeyToPath { - // The key to project. - optional string key = 1; - - // The relative path of the file to map the key to. - // May not be an absolute path. - // May not contain the path element '..'. - // May not start with the string '..'. - optional string path = 2; - - // Optional: mode bits to use on this file, must be a value between 0 - // and 0777. If not specified, the volume defaultMode will be used. - // This might be in conflict with other options that affect the file - // mode, like fsGroup, and the result can be other mode bits set. - // +optional - optional int32 mode = 3; -} - -// Lifecycle describes actions that the management system should take in response to container lifecycle -// events. For the PostStart and PreStop lifecycle handlers, management of the container blocks -// until the action is complete, unless the container process fails, in which case the handler is aborted. -message Lifecycle { - // PostStart is called immediately after a container is created. If the handler fails, - // the container is terminated and restarted according to its restart policy. - // Other management of the container blocks until the hook completes. - // More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - // +optional - optional Handler postStart = 1; - - // PreStop is called immediately before a container is terminated. - // The container is terminated after the handler completes. - // The reason for termination is passed to the handler. - // Regardless of the outcome of the handler, the container is eventually terminated. - // Other management of the container blocks until the hook completes. - // More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - // +optional - optional Handler preStop = 2; -} - -// LimitRange sets resource usage limits for each kind of resource in a Namespace. -message LimitRange { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec defines the limits enforced. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional LimitRangeSpec spec = 2; -} - -// LimitRangeItem defines a min/max usage limit for any resource that matches on kind. -message LimitRangeItem { - // Type of resource that this limit applies to. - // +optional - optional string type = 1; - - // Max usage constraints on this kind by resource name. - // +optional - map max = 2; - - // Min usage constraints on this kind by resource name. - // +optional - map min = 3; - - // Default resource requirement limit value by resource name if resource limit is omitted. - // +optional - map default = 4; - - // DefaultRequest is the default resource requirement request value by resource name if resource request is omitted. - // +optional - map defaultRequest = 5; - - // MaxLimitRequestRatio if specified, the named resource must have a request and limit that are both non-zero where limit divided by request is less than or equal to the enumerated value; this represents the max burst for the named resource. - // +optional - map maxLimitRequestRatio = 6; -} - -// LimitRangeList is a list of LimitRange items. -message LimitRangeList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of LimitRange objects. - // More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ - repeated LimitRange items = 2; -} - -// LimitRangeSpec defines a min/max usage limit for resources that match on kind. -message LimitRangeSpec { - // Limits is the list of LimitRangeItem objects that are enforced. - repeated LimitRangeItem limits = 1; -} - -// List holds a list of objects, which may not be known by the server. -message List { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // List of objects - repeated k8s.io.apimachinery.pkg.runtime.RawExtension items = 2; -} - -// LoadBalancerIngress represents the status of a load-balancer ingress point: -// traffic intended for the service should be sent to an ingress point. -message LoadBalancerIngress { - // IP is set for load-balancer ingress points that are IP based - // (typically GCE or OpenStack load-balancers) - // +optional - optional string ip = 1; - - // Hostname is set for load-balancer ingress points that are DNS based - // (typically AWS load-balancers) - // +optional - optional string hostname = 2; -} - -// LoadBalancerStatus represents the status of a load-balancer. -message LoadBalancerStatus { - // Ingress is a list containing ingress points for the load-balancer. - // Traffic intended for the service should be sent to these ingress points. - // +optional - repeated LoadBalancerIngress ingress = 1; -} - -// LocalObjectReference contains enough information to let you locate the -// referenced object inside the same namespace. -message LocalObjectReference { - // Name of the referent. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - // TODO: Add other useful fields. apiVersion, kind, uid? - // +optional - optional string name = 1; -} - -// Local represents directly-attached storage with node affinity (Beta feature) -message LocalVolumeSource { - // The full path to the volume on the node. - // It can be either a directory or block device (disk, partition, ...). - optional string path = 1; - - // Filesystem type to mount. - // It applies only when the Path is a block device. - // Must be a filesystem type supported by the host operating system. - // Ex. "ext4", "xfs", "ntfs". The default value is to auto-select a fileystem if unspecified. - // +optional - optional string fsType = 2; -} - -// Represents an NFS mount that lasts the lifetime of a pod. -// NFS volumes do not support ownership management or SELinux relabeling. -message NFSVolumeSource { - // Server is the hostname or IP address of the NFS server. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - optional string server = 1; - - // Path that is exported by the NFS server. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - optional string path = 2; - - // ReadOnly here will force - // the NFS export to be mounted with read-only permissions. - // Defaults to false. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - // +optional - optional bool readOnly = 3; -} - -// Namespace provides a scope for Names. -// Use of multiple namespaces is optional. -message Namespace { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec defines the behavior of the Namespace. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional NamespaceSpec spec = 2; - - // Status describes the current status of a Namespace. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional NamespaceStatus status = 3; -} - -// NamespaceList is a list of Namespaces. -message NamespaceList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is the list of Namespace objects in the list. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - repeated Namespace items = 2; -} - -// NamespaceSpec describes the attributes on a Namespace. -message NamespaceSpec { - // Finalizers is an opaque list of values that must be empty to permanently remove object from storage. - // More info: https://kubernetes.io/docs/tasks/administer-cluster/namespaces/ - // +optional - repeated string finalizers = 1; -} - -// NamespaceStatus is information about the current status of a Namespace. -message NamespaceStatus { - // Phase is the current lifecycle phase of the namespace. - // More info: https://kubernetes.io/docs/tasks/administer-cluster/namespaces/ - // +optional - optional string phase = 1; -} - -// Node is a worker node in Kubernetes. -// Each node will have a unique identifier in the cache (i.e. in etcd). -message Node { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec defines the behavior of a node. - // https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional NodeSpec spec = 2; - - // Most recently observed status of the node. - // Populated by the system. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional NodeStatus status = 3; -} - -// NodeAddress contains information for the node's address. -message NodeAddress { - // Node address type, one of Hostname, ExternalIP or InternalIP. - optional string type = 1; - - // The node address. - optional string address = 2; -} - -// Node affinity is a group of node affinity scheduling rules. -message NodeAffinity { - // If the affinity requirements specified by this field are not met at - // scheduling time, the pod will not be scheduled onto the node. - // If the affinity requirements specified by this field cease to be met - // at some point during pod execution (e.g. due to an update), the system - // may or may not try to eventually evict the pod from its node. - // +optional - optional NodeSelector requiredDuringSchedulingIgnoredDuringExecution = 1; - - // The scheduler will prefer to schedule pods to nodes that satisfy - // the affinity expressions specified by this field, but it may choose - // a node that violates one or more of the expressions. The node that is - // most preferred is the one with the greatest sum of weights, i.e. - // for each node that meets all of the scheduling requirements (resource - // request, requiredDuringScheduling affinity expressions, etc.), - // compute a sum by iterating through the elements of this field and adding - // "weight" to the sum if the node matches the corresponding matchExpressions; the - // node(s) with the highest sum are the most preferred. - // +optional - repeated PreferredSchedulingTerm preferredDuringSchedulingIgnoredDuringExecution = 2; -} - -// NodeCondition contains condition information for a node. -message NodeCondition { - // Type of node condition. - optional string type = 1; - - // Status of the condition, one of True, False, Unknown. - optional string status = 2; - - // Last time we got an update on a given condition. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastHeartbeatTime = 3; - - // Last time the condition transit from one status to another. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 4; - - // (brief) reason for the condition's last transition. - // +optional - optional string reason = 5; - - // Human readable message indicating details about last transition. - // +optional - optional string message = 6; -} - -// NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil. -message NodeConfigSource { - // ConfigMap is a reference to a Node's ConfigMap - optional ConfigMapNodeConfigSource configMap = 2; -} - -// NodeConfigStatus describes the status of the config assigned by Node.Spec.ConfigSource. -message NodeConfigStatus { - // Assigned reports the checkpointed config the node will try to use. - // When Node.Spec.ConfigSource is updated, the node checkpoints the associated - // config payload to local disk, along with a record indicating intended - // config. The node refers to this record to choose its config checkpoint, and - // reports this record in Assigned. Assigned only updates in the status after - // the record has been checkpointed to disk. When the Kubelet is restarted, - // it tries to make the Assigned config the Active config by loading and - // validating the checkpointed payload identified by Assigned. - // +optional - optional NodeConfigSource assigned = 1; - - // Active reports the checkpointed config the node is actively using. - // Active will represent either the current version of the Assigned config, - // or the current LastKnownGood config, depending on whether attempting to use the - // Assigned config results in an error. - // +optional - optional NodeConfigSource active = 2; - - // LastKnownGood reports the checkpointed config the node will fall back to - // when it encounters an error attempting to use the Assigned config. - // The Assigned config becomes the LastKnownGood config when the node determines - // that the Assigned config is stable and correct. - // This is currently implemented as a 10-minute soak period starting when the local - // record of Assigned config is updated. If the Assigned config is Active at the end - // of this period, it becomes the LastKnownGood. Note that if Spec.ConfigSource is - // reset to nil (use local defaults), the LastKnownGood is also immediately reset to nil, - // because the local default config is always assumed good. - // You should not make assumptions about the node's method of determining config stability - // and correctness, as this may change or become configurable in the future. - // +optional - optional NodeConfigSource lastKnownGood = 3; - - // Error describes any problems reconciling the Spec.ConfigSource to the Active config. - // Errors may occur, for example, attempting to checkpoint Spec.ConfigSource to the local Assigned - // record, attempting to checkpoint the payload associated with Spec.ConfigSource, attempting - // to load or validate the Assigned config, etc. - // Errors may occur at different points while syncing config. Earlier errors (e.g. download or - // checkpointing errors) will not result in a rollback to LastKnownGood, and may resolve across - // Kubelet retries. Later errors (e.g. loading or validating a checkpointed config) will result in - // a rollback to LastKnownGood. In the latter case, it is usually possible to resolve the error - // by fixing the config assigned in Spec.ConfigSource. - // You can find additional information for debugging by searching the error message in the Kubelet log. - // Error is a human-readable description of the error state; machines can check whether or not Error - // is empty, but should not rely on the stability of the Error text across Kubelet versions. - // +optional - optional string error = 4; -} - -// NodeDaemonEndpoints lists ports opened by daemons running on the Node. -message NodeDaemonEndpoints { - // Endpoint on which Kubelet is listening. - // +optional - optional DaemonEndpoint kubeletEndpoint = 1; -} - -// NodeList is the whole list of all Nodes which have been registered with master. -message NodeList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // List of nodes - repeated Node items = 2; -} - -// NodeProxyOptions is the query options to a Node's proxy call. -message NodeProxyOptions { - // Path is the URL path to use for the current proxy request to node. - // +optional - optional string path = 1; -} - -// NodeResources is an object for conveying resource information about a node. -// see http://releases.k8s.io/HEAD/docs/design/resources.md for more details. -message NodeResources { - // Capacity represents the available resources of a node - map capacity = 1; -} - -// A node selector represents the union of the results of one or more label queries -// over a set of nodes; that is, it represents the OR of the selectors represented -// by the node selector terms. -message NodeSelector { - // Required. A list of node selector terms. The terms are ORed. - repeated NodeSelectorTerm nodeSelectorTerms = 1; -} - -// A node selector requirement is a selector that contains values, a key, and an operator -// that relates the key and values. -message NodeSelectorRequirement { - // The label key that the selector applies to. - optional string key = 1; - - // Represents a key's relationship to a set of values. - // Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - optional string operator = 2; - - // An array of string values. If the operator is In or NotIn, - // the values array must be non-empty. If the operator is Exists or DoesNotExist, - // the values array must be empty. If the operator is Gt or Lt, the values - // array must have a single element, which will be interpreted as an integer. - // This array is replaced during a strategic merge patch. - // +optional - repeated string values = 3; -} - -// A null or empty node selector term matches no objects. The requirements of -// them are ANDed. -// The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. -message NodeSelectorTerm { - // A list of node selector requirements by node's labels. - // +optional - repeated NodeSelectorRequirement matchExpressions = 1; - - // A list of node selector requirements by node's fields. - // +optional - repeated NodeSelectorRequirement matchFields = 2; -} - -// NodeSpec describes the attributes that a node is created with. -message NodeSpec { - // PodCIDR represents the pod IP range assigned to the node. - // +optional - optional string podCIDR = 1; - - // ID of the node assigned by the cloud provider in the format: :// - // +optional - optional string providerID = 3; - - // Unschedulable controls node schedulability of new pods. By default, node is schedulable. - // More info: https://kubernetes.io/docs/concepts/nodes/node/#manual-node-administration - // +optional - optional bool unschedulable = 4; - - // If specified, the node's taints. - // +optional - repeated Taint taints = 5; - - // If specified, the source to get node configuration from - // The DynamicKubeletConfig feature gate must be enabled for the Kubelet to use this field - // +optional - optional NodeConfigSource configSource = 6; - - // Deprecated. Not all kubelets will set this field. Remove field after 1.13. - // see: https://issues.k8s.io/61966 - // +optional - optional string externalID = 2; -} - -// NodeStatus is information about the current status of a node. -message NodeStatus { - // Capacity represents the total resources of a node. - // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#capacity - // +optional - map capacity = 1; - - // Allocatable represents the resources of a node that are available for scheduling. - // Defaults to Capacity. - // +optional - map allocatable = 2; - - // NodePhase is the recently observed lifecycle phase of the node. - // More info: https://kubernetes.io/docs/concepts/nodes/node/#phase - // The field is never populated, and now is deprecated. - // +optional - optional string phase = 3; - - // Conditions is an array of current observed node conditions. - // More info: https://kubernetes.io/docs/concepts/nodes/node/#condition - // +optional - // +patchMergeKey=type - // +patchStrategy=merge - repeated NodeCondition conditions = 4; - - // List of addresses reachable to the node. - // Queried from cloud provider, if available. - // More info: https://kubernetes.io/docs/concepts/nodes/node/#addresses - // +optional - // +patchMergeKey=type - // +patchStrategy=merge - repeated NodeAddress addresses = 5; - - // Endpoints of daemons running on the Node. - // +optional - optional NodeDaemonEndpoints daemonEndpoints = 6; - - // Set of ids/uuids to uniquely identify the node. - // More info: https://kubernetes.io/docs/concepts/nodes/node/#info - // +optional - optional NodeSystemInfo nodeInfo = 7; - - // List of container images on this node - // +optional - repeated ContainerImage images = 8; - - // List of attachable volumes in use (mounted) by the node. - // +optional - repeated string volumesInUse = 9; - - // List of volumes that are attached to the node. - // +optional - repeated AttachedVolume volumesAttached = 10; - - // Status of the config assigned to the node via the dynamic Kubelet config feature. - // +optional - optional NodeConfigStatus config = 11; -} - -// NodeSystemInfo is a set of ids/uuids to uniquely identify the node. -message NodeSystemInfo { - // MachineID reported by the node. For unique machine identification - // in the cluster this field is preferred. Learn more from man(5) - // machine-id: http://man7.org/linux/man-pages/man5/machine-id.5.html - optional string machineID = 1; - - // SystemUUID reported by the node. For unique machine identification - // MachineID is preferred. This field is specific to Red Hat hosts - // https://access.redhat.com/documentation/en-US/Red_Hat_Subscription_Management/1/html/RHSM/getting-system-uuid.html - optional string systemUUID = 2; - - // Boot ID reported by the node. - optional string bootID = 3; - - // Kernel Version reported by the node from 'uname -r' (e.g. 3.16.0-0.bpo.4-amd64). - optional string kernelVersion = 4; - - // OS Image reported by the node from /etc/os-release (e.g. Debian GNU/Linux 7 (wheezy)). - optional string osImage = 5; - - // ContainerRuntime Version reported by the node through runtime remote API (e.g. docker://1.5.0). - optional string containerRuntimeVersion = 6; - - // Kubelet Version reported by the node. - optional string kubeletVersion = 7; - - // KubeProxy Version reported by the node. - optional string kubeProxyVersion = 8; - - // The Operating System reported by the node - optional string operatingSystem = 9; - - // The Architecture reported by the node - optional string architecture = 10; -} - -// ObjectFieldSelector selects an APIVersioned field of an object. -message ObjectFieldSelector { - // Version of the schema the FieldPath is written in terms of, defaults to "v1". - // +optional - optional string apiVersion = 1; - - // Path of the field to select in the specified API version. - optional string fieldPath = 2; -} - -// ObjectReference contains enough information to let you inspect or modify the referred object. -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -message ObjectReference { - // Kind of the referent. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional string kind = 1; - - // Namespace of the referent. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ - // +optional - optional string namespace = 2; - - // Name of the referent. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - // +optional - optional string name = 3; - - // UID of the referent. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids - // +optional - optional string uid = 4; - - // API version of the referent. - // +optional - optional string apiVersion = 5; - - // Specific resourceVersion to which this reference is made, if any. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency - // +optional - optional string resourceVersion = 6; - - // If referring to a piece of an object instead of an entire object, this string - // should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. - // For example, if the object reference is to a container within a pod, this would take on a value like: - // "spec.containers{name}" (where "name" refers to the name of the container that triggered - // the event) or if no container name is specified "spec.containers[2]" (container with - // index 2 in this pod). This syntax is chosen only to have some well-defined way of - // referencing a part of an object. - // TODO: this design is not final and this field is subject to change in the future. - // +optional - optional string fieldPath = 7; -} - -// PersistentVolume (PV) is a storage resource provisioned by an administrator. -// It is analogous to a node. -// More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes -message PersistentVolume { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec defines a specification of a persistent volume owned by the cluster. - // Provisioned by an administrator. - // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistent-volumes - // +optional - optional PersistentVolumeSpec spec = 2; - - // Status represents the current information/status for the persistent volume. - // Populated by the system. - // Read-only. - // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistent-volumes - // +optional - optional PersistentVolumeStatus status = 3; -} - -// PersistentVolumeClaim is a user's request for and claim to a persistent volume -message PersistentVolumeClaim { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec defines the desired characteristics of a volume requested by a pod author. - // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - // +optional - optional PersistentVolumeClaimSpec spec = 2; - - // Status represents the current information/status of a persistent volume claim. - // Read-only. - // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - // +optional - optional PersistentVolumeClaimStatus status = 3; -} - -// PersistentVolumeClaimCondition contails details about state of pvc -message PersistentVolumeClaimCondition { - optional string type = 1; - - optional string status = 2; - - // Last time we probed the condition. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastProbeTime = 3; - - // Last time the condition transitioned from one status to another. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 4; - - // Unique, this should be a short, machine understandable string that gives the reason - // for condition's last transition. If it reports "ResizeStarted" that means the underlying - // persistent volume is being resized. - // +optional - optional string reason = 5; - - // Human-readable message indicating details about last transition. - // +optional - optional string message = 6; -} - -// PersistentVolumeClaimList is a list of PersistentVolumeClaim items. -message PersistentVolumeClaimList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // A list of persistent volume claims. - // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - repeated PersistentVolumeClaim items = 2; -} - -// PersistentVolumeClaimSpec describes the common attributes of storage devices -// and allows a Source for provider-specific attributes -message PersistentVolumeClaimSpec { - // AccessModes contains the desired access modes the volume should have. - // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 - // +optional - repeated string accessModes = 1; - - // A label query over volumes to consider for binding. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 4; - - // Resources represents the minimum resources the volume should have. - // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources - // +optional - optional ResourceRequirements resources = 2; - - // VolumeName is the binding reference to the PersistentVolume backing this claim. - // +optional - optional string volumeName = 3; - - // Name of the StorageClass required by the claim. - // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 - // +optional - optional string storageClassName = 5; - - // volumeMode defines what type of volume is required by the claim. - // Value of Filesystem is implied when not included in claim spec. - // This is an alpha feature and may change in the future. - // +optional - optional string volumeMode = 6; - - // This field requires the VolumeSnapshotDataSource alpha feature gate to be - // enabled and currently VolumeSnapshot is the only supported data source. - // If the provisioner can support VolumeSnapshot data source, it will create - // a new volume and data will be restored to the volume at the same time. - // If the provisioner does not support VolumeSnapshot data source, volume will - // not be created and the failure will be reported as an event. - // In the future, we plan to support more data source types and the behavior - // of the provisioner may change. - // +optional - optional TypedLocalObjectReference dataSource = 7; -} - -// PersistentVolumeClaimStatus is the current status of a persistent volume claim. -message PersistentVolumeClaimStatus { - // Phase represents the current phase of PersistentVolumeClaim. - // +optional - optional string phase = 1; - - // AccessModes contains the actual access modes the volume backing the PVC has. - // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 - // +optional - repeated string accessModes = 2; - - // Represents the actual resources of the underlying volume. - // +optional - map capacity = 3; - - // Current Condition of persistent volume claim. If underlying persistent volume is being - // resized then the Condition will be set to 'ResizeStarted'. - // +optional - // +patchMergeKey=type - // +patchStrategy=merge - repeated PersistentVolumeClaimCondition conditions = 4; -} - -// PersistentVolumeClaimVolumeSource references the user's PVC in the same namespace. -// This volume finds the bound PV and mounts that volume for the pod. A -// PersistentVolumeClaimVolumeSource is, essentially, a wrapper around another -// type of volume that is owned by someone else (the system). -message PersistentVolumeClaimVolumeSource { - // ClaimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. - // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - optional string claimName = 1; - - // Will force the ReadOnly setting in VolumeMounts. - // Default false. - // +optional - optional bool readOnly = 2; -} - -// PersistentVolumeList is a list of PersistentVolume items. -message PersistentVolumeList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // List of persistent volumes. - // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes - repeated PersistentVolume items = 2; -} - -// PersistentVolumeSource is similar to VolumeSource but meant for the -// administrator who creates PVs. Exactly one of its members must be set. -message PersistentVolumeSource { - // GCEPersistentDisk represents a GCE Disk resource that is attached to a - // kubelet's host machine and then exposed to the pod. Provisioned by an admin. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - // +optional - optional GCEPersistentDiskVolumeSource gcePersistentDisk = 1; - - // AWSElasticBlockStore represents an AWS Disk resource that is attached to a - // kubelet's host machine and then exposed to the pod. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - // +optional - optional AWSElasticBlockStoreVolumeSource awsElasticBlockStore = 2; - - // HostPath represents a directory on the host. - // Provisioned by a developer or tester. - // This is useful for single-node development and testing only! - // On-host storage is not supported in any way and WILL NOT WORK in a multi-node cluster. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - // +optional - optional HostPathVolumeSource hostPath = 3; - - // Glusterfs represents a Glusterfs volume that is attached to a host and - // exposed to the pod. Provisioned by an admin. - // More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md - // +optional - optional GlusterfsVolumeSource glusterfs = 4; - - // NFS represents an NFS mount on the host. Provisioned by an admin. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - // +optional - optional NFSVolumeSource nfs = 5; - - // RBD represents a Rados Block Device mount on the host that shares a pod's lifetime. - // More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md - // +optional - optional RBDPersistentVolumeSource rbd = 6; - - // ISCSI represents an ISCSI Disk resource that is attached to a - // kubelet's host machine and then exposed to the pod. Provisioned by an admin. - // +optional - optional ISCSIPersistentVolumeSource iscsi = 7; - - // Cinder represents a cinder volume attached and mounted on kubelets host machine - // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md - // +optional - optional CinderPersistentVolumeSource cinder = 8; - - // CephFS represents a Ceph FS mount on the host that shares a pod's lifetime - // +optional - optional CephFSPersistentVolumeSource cephfs = 9; - - // FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod. - // +optional - optional FCVolumeSource fc = 10; - - // Flocker represents a Flocker volume attached to a kubelet's host machine and exposed to the pod for its usage. This depends on the Flocker control service being running - // +optional - optional FlockerVolumeSource flocker = 11; - - // FlexVolume represents a generic volume resource that is - // provisioned/attached using an exec based plugin. - // +optional - optional FlexPersistentVolumeSource flexVolume = 12; - - // AzureFile represents an Azure File Service mount on the host and bind mount to the pod. - // +optional - optional AzureFilePersistentVolumeSource azureFile = 13; - - // VsphereVolume represents a vSphere volume attached and mounted on kubelets host machine - // +optional - optional VsphereVirtualDiskVolumeSource vsphereVolume = 14; - - // Quobyte represents a Quobyte mount on the host that shares a pod's lifetime - // +optional - optional QuobyteVolumeSource quobyte = 15; - - // AzureDisk represents an Azure Data Disk mount on the host and bind mount to the pod. - // +optional - optional AzureDiskVolumeSource azureDisk = 16; - - // PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine - optional PhotonPersistentDiskVolumeSource photonPersistentDisk = 17; - - // PortworxVolume represents a portworx volume attached and mounted on kubelets host machine - // +optional - optional PortworxVolumeSource portworxVolume = 18; - - // ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes. - // +optional - optional ScaleIOPersistentVolumeSource scaleIO = 19; - - // Local represents directly-attached storage with node affinity - // +optional - optional LocalVolumeSource local = 20; - - // StorageOS represents a StorageOS volume that is attached to the kubelet's host machine and mounted into the pod - // More info: https://releases.k8s.io/HEAD/examples/volumes/storageos/README.md - // +optional - optional StorageOSPersistentVolumeSource storageos = 21; - - // CSI represents storage that handled by an external CSI driver (Beta feature). - // +optional - optional CSIPersistentVolumeSource csi = 22; -} - -// PersistentVolumeSpec is the specification of a persistent volume. -message PersistentVolumeSpec { - // A description of the persistent volume's resources and capacity. - // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#capacity - // +optional - map capacity = 1; - - // The actual volume backing the persistent volume. - optional PersistentVolumeSource persistentVolumeSource = 2; - - // AccessModes contains all ways the volume can be mounted. - // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes - // +optional - repeated string accessModes = 3; - - // ClaimRef is part of a bi-directional binding between PersistentVolume and PersistentVolumeClaim. - // Expected to be non-nil when bound. - // claim.VolumeName is the authoritative bind between PV and PVC. - // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#binding - // +optional - optional ObjectReference claimRef = 4; - - // What happens to a persistent volume when released from its claim. - // Valid options are Retain (default for manually created PersistentVolumes), Delete (default - // for dynamically provisioned PersistentVolumes), and Recycle (deprecated). - // Recycle must be supported by the volume plugin underlying this PersistentVolume. - // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#reclaiming - // +optional - optional string persistentVolumeReclaimPolicy = 5; - - // Name of StorageClass to which this persistent volume belongs. Empty value - // means that this volume does not belong to any StorageClass. - // +optional - optional string storageClassName = 6; - - // A list of mount options, e.g. ["ro", "soft"]. Not validated - mount will - // simply fail if one is invalid. - // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#mount-options - // +optional - repeated string mountOptions = 7; - - // volumeMode defines if a volume is intended to be used with a formatted filesystem - // or to remain in raw block state. Value of Filesystem is implied when not included in spec. - // This is an alpha feature and may change in the future. - // +optional - optional string volumeMode = 8; - - // NodeAffinity defines constraints that limit what nodes this volume can be accessed from. - // This field influences the scheduling of pods that use this volume. - // +optional - optional VolumeNodeAffinity nodeAffinity = 9; -} - -// PersistentVolumeStatus is the current status of a persistent volume. -message PersistentVolumeStatus { - // Phase indicates if a volume is available, bound to a claim, or released by a claim. - // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#phase - // +optional - optional string phase = 1; - - // A human-readable message indicating details about why the volume is in this state. - // +optional - optional string message = 2; - - // Reason is a brief CamelCase string that describes any failure and is meant - // for machine parsing and tidy display in the CLI. - // +optional - optional string reason = 3; -} - -// Represents a Photon Controller persistent disk resource. -message PhotonPersistentDiskVolumeSource { - // ID that identifies Photon Controller persistent disk - optional string pdID = 1; - - // Filesystem type to mount. - // Must be a filesystem type supported by the host operating system. - // Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - optional string fsType = 2; -} - -// Pod is a collection of containers that can run on a host. This resource is created -// by clients and scheduled onto hosts. -message Pod { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Specification of the desired behavior of the pod. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional PodSpec spec = 2; - - // Most recently observed status of the pod. - // This data may not be up to date. - // Populated by the system. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional PodStatus status = 3; -} - -// Pod affinity is a group of inter pod affinity scheduling rules. -message PodAffinity { - // If the affinity requirements specified by this field are not met at - // scheduling time, the pod will not be scheduled onto the node. - // If the affinity requirements specified by this field cease to be met - // at some point during pod execution (e.g. due to a pod label update), the - // system may or may not try to eventually evict the pod from its node. - // When there are multiple elements, the lists of nodes corresponding to each - // podAffinityTerm are intersected, i.e. all terms must be satisfied. - // +optional - repeated PodAffinityTerm requiredDuringSchedulingIgnoredDuringExecution = 1; - - // The scheduler will prefer to schedule pods to nodes that satisfy - // the affinity expressions specified by this field, but it may choose - // a node that violates one or more of the expressions. The node that is - // most preferred is the one with the greatest sum of weights, i.e. - // for each node that meets all of the scheduling requirements (resource - // request, requiredDuringScheduling affinity expressions, etc.), - // compute a sum by iterating through the elements of this field and adding - // "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - // node(s) with the highest sum are the most preferred. - // +optional - repeated WeightedPodAffinityTerm preferredDuringSchedulingIgnoredDuringExecution = 2; -} - -// Defines a set of pods (namely those matching the labelSelector -// relative to the given namespace(s)) that this pod should be -// co-located (affinity) or not co-located (anti-affinity) with, -// where co-located is defined as running on a node whose value of -// the label with key matches that of any node on which -// a pod of the set of pods is running -message PodAffinityTerm { - // A label query over a set of resources, in this case pods. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector labelSelector = 1; - - // namespaces specifies which namespaces the labelSelector applies to (matches against); - // null or empty list means "this pod's namespace" - // +optional - repeated string namespaces = 2; - - // This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - // the labelSelector in the specified namespaces, where co-located is defined as running on a node - // whose value of the label with key topologyKey matches that of any node on which any of the - // selected pods is running. - // Empty topologyKey is not allowed. - optional string topologyKey = 3; -} - -// Pod anti affinity is a group of inter pod anti affinity scheduling rules. -message PodAntiAffinity { - // If the anti-affinity requirements specified by this field are not met at - // scheduling time, the pod will not be scheduled onto the node. - // If the anti-affinity requirements specified by this field cease to be met - // at some point during pod execution (e.g. due to a pod label update), the - // system may or may not try to eventually evict the pod from its node. - // When there are multiple elements, the lists of nodes corresponding to each - // podAffinityTerm are intersected, i.e. all terms must be satisfied. - // +optional - repeated PodAffinityTerm requiredDuringSchedulingIgnoredDuringExecution = 1; - - // The scheduler will prefer to schedule pods to nodes that satisfy - // the anti-affinity expressions specified by this field, but it may choose - // a node that violates one or more of the expressions. The node that is - // most preferred is the one with the greatest sum of weights, i.e. - // for each node that meets all of the scheduling requirements (resource - // request, requiredDuringScheduling anti-affinity expressions, etc.), - // compute a sum by iterating through the elements of this field and adding - // "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - // node(s) with the highest sum are the most preferred. - // +optional - repeated WeightedPodAffinityTerm preferredDuringSchedulingIgnoredDuringExecution = 2; -} - -// PodAttachOptions is the query options to a Pod's remote attach call. -// --- -// TODO: merge w/ PodExecOptions below for stdin, stdout, etc -// and also when we cut V2, we should export a "StreamOptions" or somesuch that contains Stdin, Stdout, Stder and TTY -message PodAttachOptions { - // Stdin if true, redirects the standard input stream of the pod for this call. - // Defaults to false. - // +optional - optional bool stdin = 1; - - // Stdout if true indicates that stdout is to be redirected for the attach call. - // Defaults to true. - // +optional - optional bool stdout = 2; - - // Stderr if true indicates that stderr is to be redirected for the attach call. - // Defaults to true. - // +optional - optional bool stderr = 3; - - // TTY if true indicates that a tty will be allocated for the attach call. - // This is passed through the container runtime so the tty - // is allocated on the worker node by the container runtime. - // Defaults to false. - // +optional - optional bool tty = 4; - - // The container in which to execute the command. - // Defaults to only container if there is only one container in the pod. - // +optional - optional string container = 5; -} - -// PodCondition contains details for the current condition of this pod. -message PodCondition { - // Type is the type of the condition. - // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions - optional string type = 1; - - // Status is the status of the condition. - // Can be True, False, Unknown. - // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions - optional string status = 2; - - // Last time we probed the condition. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastProbeTime = 3; - - // Last time the condition transitioned from one status to another. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 4; - - // Unique, one-word, CamelCase reason for the condition's last transition. - // +optional - optional string reason = 5; - - // Human-readable message indicating details about last transition. - // +optional - optional string message = 6; -} - -// PodDNSConfig defines the DNS parameters of a pod in addition to -// those generated from DNSPolicy. -message PodDNSConfig { - // A list of DNS name server IP addresses. - // This will be appended to the base nameservers generated from DNSPolicy. - // Duplicated nameservers will be removed. - // +optional - repeated string nameservers = 1; - - // A list of DNS search domains for host-name lookup. - // This will be appended to the base search paths generated from DNSPolicy. - // Duplicated search paths will be removed. - // +optional - repeated string searches = 2; - - // A list of DNS resolver options. - // This will be merged with the base options generated from DNSPolicy. - // Duplicated entries will be removed. Resolution options given in Options - // will override those that appear in the base DNSPolicy. - // +optional - repeated PodDNSConfigOption options = 3; -} - -// PodDNSConfigOption defines DNS resolver options of a pod. -message PodDNSConfigOption { - // Required. - optional string name = 1; - - // +optional - optional string value = 2; -} - -// PodExecOptions is the query options to a Pod's remote exec call. -// --- -// TODO: This is largely identical to PodAttachOptions above, make sure they stay in sync and see about merging -// and also when we cut V2, we should export a "StreamOptions" or somesuch that contains Stdin, Stdout, Stder and TTY -message PodExecOptions { - // Redirect the standard input stream of the pod for this call. - // Defaults to false. - // +optional - optional bool stdin = 1; - - // Redirect the standard output stream of the pod for this call. - // Defaults to true. - // +optional - optional bool stdout = 2; - - // Redirect the standard error stream of the pod for this call. - // Defaults to true. - // +optional - optional bool stderr = 3; - - // TTY if true indicates that a tty will be allocated for the exec call. - // Defaults to false. - // +optional - optional bool tty = 4; - - // Container in which to execute the command. - // Defaults to only container if there is only one container in the pod. - // +optional - optional string container = 5; - - // Command is the remote command to execute. argv array. Not executed within a shell. - repeated string command = 6; -} - -// PodList is a list of Pods. -message PodList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // List of pods. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md - repeated Pod items = 2; -} - -// PodLogOptions is the query options for a Pod's logs REST call. -message PodLogOptions { - // The container for which to stream logs. Defaults to only container if there is one container in the pod. - // +optional - optional string container = 1; - - // Follow the log stream of the pod. Defaults to false. - // +optional - optional bool follow = 2; - - // Return previous terminated container logs. Defaults to false. - // +optional - optional bool previous = 3; - - // A relative time in seconds before the current time from which to show logs. If this value - // precedes the time a pod was started, only logs since the pod start will be returned. - // If this value is in the future, no logs will be returned. - // Only one of sinceSeconds or sinceTime may be specified. - // +optional - optional int64 sinceSeconds = 4; - - // An RFC3339 timestamp from which to show logs. If this value - // precedes the time a pod was started, only logs since the pod start will be returned. - // If this value is in the future, no logs will be returned. - // Only one of sinceSeconds or sinceTime may be specified. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time sinceTime = 5; - - // If true, add an RFC3339 or RFC3339Nano timestamp at the beginning of every line - // of log output. Defaults to false. - // +optional - optional bool timestamps = 6; - - // If set, the number of lines from the end of the logs to show. If not specified, - // logs are shown from the creation of the container or sinceSeconds or sinceTime - // +optional - optional int64 tailLines = 7; - - // If set, the number of bytes to read from the server before terminating the - // log output. This may not display a complete final line of logging, and may return - // slightly more or slightly less than the specified limit. - // +optional - optional int64 limitBytes = 8; -} - -// PodPortForwardOptions is the query options to a Pod's port forward call -// when using WebSockets. -// The `port` query parameter must specify the port or -// ports (comma separated) to forward over. -// Port forwarding over SPDY does not use these options. It requires the port -// to be passed in the `port` header as part of request. -message PodPortForwardOptions { - // List of ports to forward - // Required when using WebSockets - // +optional - repeated int32 ports = 1; -} - -// PodProxyOptions is the query options to a Pod's proxy call. -message PodProxyOptions { - // Path is the URL path to use for the current proxy request to pod. - // +optional - optional string path = 1; -} - -// PodReadinessGate contains the reference to a pod condition -message PodReadinessGate { - // ConditionType refers to a condition in the pod's condition list with matching type. - optional string conditionType = 1; -} - -// PodSecurityContext holds pod-level security attributes and common container settings. -// Some fields are also present in container.securityContext. Field values of -// container.securityContext take precedence over field values of PodSecurityContext. -message PodSecurityContext { - // The SELinux context to be applied to all containers. - // If unspecified, the container runtime will allocate a random SELinux context for each - // container. May also be set in SecurityContext. If set in - // both SecurityContext and PodSecurityContext, the value specified in SecurityContext - // takes precedence for that container. - // +optional - optional SELinuxOptions seLinuxOptions = 1; - - // The UID to run the entrypoint of the container process. - // Defaults to user specified in image metadata if unspecified. - // May also be set in SecurityContext. If set in both SecurityContext and - // PodSecurityContext, the value specified in SecurityContext takes precedence - // for that container. - // +optional - optional int64 runAsUser = 2; - - // The GID to run the entrypoint of the container process. - // Uses runtime default if unset. - // May also be set in SecurityContext. If set in both SecurityContext and - // PodSecurityContext, the value specified in SecurityContext takes precedence - // for that container. - // +optional - optional int64 runAsGroup = 6; - - // Indicates that the container must run as a non-root user. - // If true, the Kubelet will validate the image at runtime to ensure that it - // does not run as UID 0 (root) and fail to start the container if it does. - // If unset or false, no such validation will be performed. - // May also be set in SecurityContext. If set in both SecurityContext and - // PodSecurityContext, the value specified in SecurityContext takes precedence. - // +optional - optional bool runAsNonRoot = 3; - - // A list of groups applied to the first process run in each container, in addition - // to the container's primary GID. If unspecified, no groups will be added to - // any container. - // +optional - repeated int64 supplementalGroups = 4; - - // A special supplemental group that applies to all containers in a pod. - // Some volume types allow the Kubelet to change the ownership of that volume - // to be owned by the pod: - // - // 1. The owning GID will be the FSGroup - // 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) - // 3. The permission bits are OR'd with rw-rw---- - // - // If unset, the Kubelet will not modify the ownership and permissions of any volume. - // +optional - optional int64 fsGroup = 5; - - // Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported - // sysctls (by the container runtime) might fail to launch. - // +optional - repeated Sysctl sysctls = 7; -} - -// Describes the class of pods that should avoid this node. -// Exactly one field should be set. -message PodSignature { - // Reference to controller whose pods should avoid this node. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.OwnerReference podController = 1; -} - -// PodSpec is a description of a pod. -message PodSpec { - // List of volumes that can be mounted by containers belonging to the pod. - // More info: https://kubernetes.io/docs/concepts/storage/volumes - // +optional - // +patchMergeKey=name - // +patchStrategy=merge,retainKeys - repeated Volume volumes = 1; - - // List of initialization containers belonging to the pod. - // Init containers are executed in order prior to containers being started. If any - // init container fails, the pod is considered to have failed and is handled according - // to its restartPolicy. The name for an init container or normal container must be - // unique among all containers. - // Init containers may not have Lifecycle actions, Readiness probes, or Liveness probes. - // The resourceRequirements of an init container are taken into account during scheduling - // by finding the highest request/limit for each resource type, and then using the max of - // of that value or the sum of the normal containers. Limits are applied to init containers - // in a similar fashion. - // Init containers cannot currently be added or removed. - // Cannot be updated. - // More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ - // +patchMergeKey=name - // +patchStrategy=merge - repeated Container initContainers = 20; - - // List of containers belonging to the pod. - // Containers cannot currently be added or removed. - // There must be at least one container in a Pod. - // Cannot be updated. - // +patchMergeKey=name - // +patchStrategy=merge - repeated Container containers = 2; - - // Restart policy for all containers within the pod. - // One of Always, OnFailure, Never. - // Default to Always. - // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy - // +optional - optional string restartPolicy = 3; - - // Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. - // Value must be non-negative integer. The value zero indicates delete immediately. - // If this value is nil, the default grace period will be used instead. - // The grace period is the duration in seconds after the processes running in the pod are sent - // a termination signal and the time when the processes are forcibly halted with a kill signal. - // Set this value longer than the expected cleanup time for your process. - // Defaults to 30 seconds. - // +optional - optional int64 terminationGracePeriodSeconds = 4; - - // Optional duration in seconds the pod may be active on the node relative to - // StartTime before the system will actively try to mark it failed and kill associated containers. - // Value must be a positive integer. - // +optional - optional int64 activeDeadlineSeconds = 5; - - // Set DNS policy for the pod. - // Defaults to "ClusterFirst". - // Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. - // DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. - // To have DNS options set along with hostNetwork, you have to specify DNS policy - // explicitly to 'ClusterFirstWithHostNet'. - // +optional - optional string dnsPolicy = 6; - - // NodeSelector is a selector which must be true for the pod to fit on a node. - // Selector which must match a node's labels for the pod to be scheduled on that node. - // More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - // +optional - map nodeSelector = 7; - - // ServiceAccountName is the name of the ServiceAccount to use to run this pod. - // More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ - // +optional - optional string serviceAccountName = 8; - - // DeprecatedServiceAccount is a depreciated alias for ServiceAccountName. - // Deprecated: Use serviceAccountName instead. - // +k8s:conversion-gen=false - // +optional - optional string serviceAccount = 9; - - // AutomountServiceAccountToken indicates whether a service account token should be automatically mounted. - // +optional - optional bool automountServiceAccountToken = 21; - - // NodeName is a request to schedule this pod onto a specific node. If it is non-empty, - // the scheduler simply schedules this pod onto that node, assuming that it fits resource - // requirements. - // +optional - optional string nodeName = 10; - - // Host networking requested for this pod. Use the host's network namespace. - // If this option is set, the ports that will be used must be specified. - // Default to false. - // +k8s:conversion-gen=false - // +optional - optional bool hostNetwork = 11; - - // Use the host's pid namespace. - // Optional: Default to false. - // +k8s:conversion-gen=false - // +optional - optional bool hostPID = 12; - - // Use the host's ipc namespace. - // Optional: Default to false. - // +k8s:conversion-gen=false - // +optional - optional bool hostIPC = 13; - - // Share a single process namespace between all of the containers in a pod. - // When this is set containers will be able to view and signal processes from other containers - // in the same pod, and the first process in each container will not be assigned PID 1. - // HostPID and ShareProcessNamespace cannot both be set. - // Optional: Default to false. - // This field is beta-level and may be disabled with the PodShareProcessNamespace feature. - // +k8s:conversion-gen=false - // +optional - optional bool shareProcessNamespace = 27; - - // SecurityContext holds pod-level security attributes and common container settings. - // Optional: Defaults to empty. See type description for default values of each field. - // +optional - optional PodSecurityContext securityContext = 14; - - // ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. - // If specified, these secrets will be passed to individual puller implementations for them to use. For example, - // in the case of docker, only DockerConfig type secrets are honored. - // More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod - // +optional - // +patchMergeKey=name - // +patchStrategy=merge - repeated LocalObjectReference imagePullSecrets = 15; - - // Specifies the hostname of the Pod - // If not specified, the pod's hostname will be set to a system-defined value. - // +optional - optional string hostname = 16; - - // If specified, the fully qualified Pod hostname will be "...svc.". - // If not specified, the pod will not have a domainname at all. - // +optional - optional string subdomain = 17; - - // If specified, the pod's scheduling constraints - // +optional - optional Affinity affinity = 18; - - // If specified, the pod will be dispatched by specified scheduler. - // If not specified, the pod will be dispatched by default scheduler. - // +optional - optional string schedulerName = 19; - - // If specified, the pod's tolerations. - // +optional - repeated Toleration tolerations = 22; - - // HostAliases is an optional list of hosts and IPs that will be injected into the pod's hosts - // file if specified. This is only valid for non-hostNetwork pods. - // +optional - // +patchMergeKey=ip - // +patchStrategy=merge - repeated HostAlias hostAliases = 23; - - // If specified, indicates the pod's priority. "system-node-critical" and - // "system-cluster-critical" are two special keywords which indicate the - // highest priorities with the former being the highest priority. Any other - // name must be defined by creating a PriorityClass object with that name. - // If not specified, the pod priority will be default or zero if there is no - // default. - // +optional - optional string priorityClassName = 24; - - // The priority value. Various system components use this field to find the - // priority of the pod. When Priority Admission Controller is enabled, it - // prevents users from setting this field. The admission controller populates - // this field from PriorityClassName. - // The higher the value, the higher the priority. - // +optional - optional int32 priority = 25; - - // Specifies the DNS parameters of a pod. - // Parameters specified here will be merged to the generated DNS - // configuration based on DNSPolicy. - // +optional - optional PodDNSConfig dnsConfig = 26; - - // If specified, all readiness gates will be evaluated for pod readiness. - // A pod is ready when all its containers are ready AND - // all conditions specified in the readiness gates have status equal to "True" - // More info: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md - // +optional - repeated PodReadinessGate readinessGates = 28; - - // RuntimeClassName refers to a RuntimeClass object in the node.k8s.io group, which should be used - // to run this pod. If no RuntimeClass resource matches the named class, the pod will not be run. - // If unset or empty, the "legacy" RuntimeClass will be used, which is an implicit class with an - // empty definition that uses the default runtime handler. - // More info: https://github.com/kubernetes/community/blob/master/keps/sig-node/0014-runtime-class.md - // This is an alpha feature and may change in the future. - // +optional - optional string runtimeClassName = 29; - - // EnableServiceLinks indicates whether information about services should be injected into pod's - // environment variables, matching the syntax of Docker links. - // +optional - optional bool enableServiceLinks = 30; -} - -// PodStatus represents information about the status of a pod. Status may trail the actual -// state of a system, especially if the node that hosts the pod cannot contact the control -// plane. -message PodStatus { - // The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle. - // The conditions array, the reason and message fields, and the individual container status - // arrays contain more detail about the pod's status. - // There are five possible phase values: - // - // Pending: The pod has been accepted by the Kubernetes system, but one or more of the - // container images has not been created. This includes time before being scheduled as - // well as time spent downloading images over the network, which could take a while. - // Running: The pod has been bound to a node, and all of the containers have been created. - // At least one container is still running, or is in the process of starting or restarting. - // Succeeded: All containers in the pod have terminated in success, and will not be restarted. - // Failed: All containers in the pod have terminated, and at least one container has - // terminated in failure. The container either exited with non-zero status or was terminated - // by the system. - // Unknown: For some reason the state of the pod could not be obtained, typically due to an - // error in communicating with the host of the pod. - // - // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase - // +optional - optional string phase = 1; - - // Current service state of pod. - // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions - // +optional - // +patchMergeKey=type - // +patchStrategy=merge - repeated PodCondition conditions = 2; - - // A human readable message indicating details about why the pod is in this condition. - // +optional - optional string message = 3; - - // A brief CamelCase message indicating details about why the pod is in this state. - // e.g. 'Evicted' - // +optional - optional string reason = 4; - - // nominatedNodeName is set only when this pod preempts other pods on the node, but it cannot be - // scheduled right away as preemption victims receive their graceful termination periods. - // This field does not guarantee that the pod will be scheduled on this node. Scheduler may decide - // to place the pod elsewhere if other nodes become available sooner. Scheduler may also decide to - // give the resources on this node to a higher priority pod that is created after preemption. - // As a result, this field may be different than PodSpec.nodeName when the pod is - // scheduled. - // +optional - optional string nominatedNodeName = 11; - - // IP address of the host to which the pod is assigned. Empty if not yet scheduled. - // +optional - optional string hostIP = 5; - - // IP address allocated to the pod. Routable at least within the cluster. - // Empty if not yet allocated. - // +optional - optional string podIP = 6; - - // RFC 3339 date and time at which the object was acknowledged by the Kubelet. - // This is before the Kubelet pulled the container image(s) for the pod. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time startTime = 7; - - // The list has one entry per init container in the manifest. The most recent successful - // init container will have ready = true, the most recently started container will have - // startTime set. - // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status - repeated ContainerStatus initContainerStatuses = 10; - - // The list has one entry per container in the manifest. Each entry is currently the output - // of `docker inspect`. - // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status - // +optional - repeated ContainerStatus containerStatuses = 8; - - // The Quality of Service (QOS) classification assigned to the pod based on resource requirements - // See PodQOSClass type for available QOS classes - // More info: https://git.k8s.io/community/contributors/design-proposals/node/resource-qos.md - // +optional - optional string qosClass = 9; -} - -// PodStatusResult is a wrapper for PodStatus returned by kubelet that can be encode/decoded -message PodStatusResult { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Most recently observed status of the pod. - // This data may not be up to date. - // Populated by the system. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional PodStatus status = 2; -} - -// PodTemplate describes a template for creating copies of a predefined pod. -message PodTemplate { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Template defines the pods that will be created from this pod template. - // https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional PodTemplateSpec template = 2; -} - -// PodTemplateList is a list of PodTemplates. -message PodTemplateList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // List of pod templates - repeated PodTemplate items = 2; -} - -// PodTemplateSpec describes the data a pod should have when created from a template -message PodTemplateSpec { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Specification of the desired behavior of the pod. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional PodSpec spec = 2; -} - -// PortworxVolumeSource represents a Portworx volume resource. -message PortworxVolumeSource { - // VolumeID uniquely identifies a Portworx volume - optional string volumeID = 1; - - // FSType represents the filesystem type to mount - // Must be a filesystem type supported by the host operating system. - // Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified. - optional string fsType = 2; - - // Defaults to false (read/write). ReadOnly here will force - // the ReadOnly setting in VolumeMounts. - // +optional - optional bool readOnly = 3; -} - -// Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out. -// +k8s:openapi-gen=false -message Preconditions { - // Specifies the target UID. - // +optional - optional string uid = 1; -} - -// Describes a class of pods that should avoid this node. -message PreferAvoidPodsEntry { - // The class of pods. - optional PodSignature podSignature = 1; - - // Time at which this entry was added to the list. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time evictionTime = 2; - - // (brief) reason why this entry was added to the list. - // +optional - optional string reason = 3; - - // Human readable message indicating why this entry was added to the list. - // +optional - optional string message = 4; -} - -// An empty preferred scheduling term matches all objects with implicit weight 0 -// (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). -message PreferredSchedulingTerm { - // Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. - optional int32 weight = 1; - - // A node selector term, associated with the corresponding weight. - optional NodeSelectorTerm preference = 2; -} - -// Probe describes a health check to be performed against a container to determine whether it is -// alive or ready to receive traffic. -message Probe { - // The action taken to determine the health of a container - optional Handler handler = 1; - - // Number of seconds after the container has started before liveness probes are initiated. - // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - // +optional - optional int32 initialDelaySeconds = 2; - - // Number of seconds after which the probe times out. - // Defaults to 1 second. Minimum value is 1. - // More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - // +optional - optional int32 timeoutSeconds = 3; - - // How often (in seconds) to perform the probe. - // Default to 10 seconds. Minimum value is 1. - // +optional - optional int32 periodSeconds = 4; - - // Minimum consecutive successes for the probe to be considered successful after having failed. - // Defaults to 1. Must be 1 for liveness. Minimum value is 1. - // +optional - optional int32 successThreshold = 5; - - // Minimum consecutive failures for the probe to be considered failed after having succeeded. - // Defaults to 3. Minimum value is 1. - // +optional - optional int32 failureThreshold = 6; -} - -// Represents a projected volume source -message ProjectedVolumeSource { - // list of volume projections - repeated VolumeProjection sources = 1; - - // Mode bits to use on created files by default. Must be a value between - // 0 and 0777. - // Directories within the path are not affected by this setting. - // This might be in conflict with other options that affect the file - // mode, like fsGroup, and the result can be other mode bits set. - // +optional - optional int32 defaultMode = 2; -} - -// Represents a Quobyte mount that lasts the lifetime of a pod. -// Quobyte volumes do not support ownership management or SELinux relabeling. -message QuobyteVolumeSource { - // Registry represents a single or multiple Quobyte Registry services - // specified as a string as host:port pair (multiple entries are separated with commas) - // which acts as the central registry for volumes - optional string registry = 1; - - // Volume is a string that references an already created Quobyte volume by name. - optional string volume = 2; - - // ReadOnly here will force the Quobyte volume to be mounted with read-only permissions. - // Defaults to false. - // +optional - optional bool readOnly = 3; - - // User to map volume access to - // Defaults to serivceaccount user - // +optional - optional string user = 4; - - // Group to map volume access to - // Default is no group - // +optional - optional string group = 5; -} - -// Represents a Rados Block Device mount that lasts the lifetime of a pod. -// RBD volumes support ownership management and SELinux relabeling. -message RBDPersistentVolumeSource { - // A collection of Ceph monitors. - // More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it - repeated string monitors = 1; - - // The rados image name. - // More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it - optional string image = 2; - - // Filesystem type of the volume that you want to mount. - // Tip: Ensure that the filesystem type is supported by the host operating system. - // Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd - // TODO: how do we prevent errors in the filesystem from compromising the machine - // +optional - optional string fsType = 3; - - // The rados pool name. - // Default is rbd. - // More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it - // +optional - optional string pool = 4; - - // The rados user name. - // Default is admin. - // More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it - // +optional - optional string user = 5; - - // Keyring is the path to key ring for RBDUser. - // Default is /etc/ceph/keyring. - // More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it - // +optional - optional string keyring = 6; - - // SecretRef is name of the authentication secret for RBDUser. If provided - // overrides keyring. - // Default is nil. - // More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it - // +optional - optional SecretReference secretRef = 7; - - // ReadOnly here will force the ReadOnly setting in VolumeMounts. - // Defaults to false. - // More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it - // +optional - optional bool readOnly = 8; -} - -// Represents a Rados Block Device mount that lasts the lifetime of a pod. -// RBD volumes support ownership management and SELinux relabeling. -message RBDVolumeSource { - // A collection of Ceph monitors. - // More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it - repeated string monitors = 1; - - // The rados image name. - // More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it - optional string image = 2; - - // Filesystem type of the volume that you want to mount. - // Tip: Ensure that the filesystem type is supported by the host operating system. - // Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd - // TODO: how do we prevent errors in the filesystem from compromising the machine - // +optional - optional string fsType = 3; - - // The rados pool name. - // Default is rbd. - // More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it - // +optional - optional string pool = 4; - - // The rados user name. - // Default is admin. - // More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it - // +optional - optional string user = 5; - - // Keyring is the path to key ring for RBDUser. - // Default is /etc/ceph/keyring. - // More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it - // +optional - optional string keyring = 6; - - // SecretRef is name of the authentication secret for RBDUser. If provided - // overrides keyring. - // Default is nil. - // More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it - // +optional - optional LocalObjectReference secretRef = 7; - - // ReadOnly here will force the ReadOnly setting in VolumeMounts. - // Defaults to false. - // More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it - // +optional - optional bool readOnly = 8; -} - -// RangeAllocation is not a public type. -message RangeAllocation { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Range is string that identifies the range represented by 'data'. - optional string range = 2; - - // Data is a bit array containing all allocated addresses in the previous segment. - optional bytes data = 3; -} - -// ReplicationController represents the configuration of a replication controller. -message ReplicationController { - // If the Labels of a ReplicationController are empty, they are defaulted to - // be the same as the Pod(s) that the replication controller manages. - // Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec defines the specification of the desired behavior of the replication controller. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional ReplicationControllerSpec spec = 2; - - // Status is the most recently observed status of the replication controller. - // This data may be out of date by some window of time. - // Populated by the system. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional ReplicationControllerStatus status = 3; -} - -// ReplicationControllerCondition describes the state of a replication controller at a certain point. -message ReplicationControllerCondition { - // Type of replication controller condition. - optional string type = 1; - - // Status of the condition, one of True, False, Unknown. - optional string status = 2; - - // The last time the condition transitioned from one status to another. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 3; - - // The reason for the condition's last transition. - // +optional - optional string reason = 4; - - // A human readable message indicating details about the transition. - // +optional - optional string message = 5; -} - -// ReplicationControllerList is a collection of replication controllers. -message ReplicationControllerList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // List of replication controllers. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller - repeated ReplicationController items = 2; -} - -// ReplicationControllerSpec is the specification of a replication controller. -message ReplicationControllerSpec { - // Replicas is the number of desired replicas. - // This is a pointer to distinguish between explicit zero and unspecified. - // Defaults to 1. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#what-is-a-replicationcontroller - // +optional - optional int32 replicas = 1; - - // Minimum number of seconds for which a newly created pod should be ready - // without any of its container crashing, for it to be considered available. - // Defaults to 0 (pod will be considered available as soon as it is ready) - // +optional - optional int32 minReadySeconds = 4; - - // Selector is a label query over pods that should match the Replicas count. - // If Selector is empty, it is defaulted to the labels present on the Pod template. - // Label keys and values that must match in order to be controlled by this replication - // controller, if empty defaulted to labels on Pod template. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors - // +optional - map selector = 2; - - // Template is the object that describes the pod that will be created if - // insufficient replicas are detected. This takes precedence over a TemplateRef. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template - // +optional - optional PodTemplateSpec template = 3; -} - -// ReplicationControllerStatus represents the current status of a replication -// controller. -message ReplicationControllerStatus { - // Replicas is the most recently oberved number of replicas. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#what-is-a-replicationcontroller - optional int32 replicas = 1; - - // The number of pods that have labels matching the labels of the pod template of the replication controller. - // +optional - optional int32 fullyLabeledReplicas = 2; - - // The number of ready replicas for this replication controller. - // +optional - optional int32 readyReplicas = 4; - - // The number of available replicas (ready for at least minReadySeconds) for this replication controller. - // +optional - optional int32 availableReplicas = 5; - - // ObservedGeneration reflects the generation of the most recently observed replication controller. - // +optional - optional int64 observedGeneration = 3; - - // Represents the latest available observations of a replication controller's current state. - // +optional - // +patchMergeKey=type - // +patchStrategy=merge - repeated ReplicationControllerCondition conditions = 6; -} - -// ResourceFieldSelector represents container resources (cpu, memory) and their output format -message ResourceFieldSelector { - // Container name: required for volumes, optional for env vars - // +optional - optional string containerName = 1; - - // Required: resource to select - optional string resource = 2; - - // Specifies the output format of the exposed resources, defaults to "1" - // +optional - optional k8s.io.apimachinery.pkg.api.resource.Quantity divisor = 3; -} - -// ResourceQuota sets aggregate quota restrictions enforced per namespace -message ResourceQuota { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec defines the desired quota. - // https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional ResourceQuotaSpec spec = 2; - - // Status defines the actual enforced quota and its current usage. - // https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional ResourceQuotaStatus status = 3; -} - -// ResourceQuotaList is a list of ResourceQuota items. -message ResourceQuotaList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of ResourceQuota objects. - // More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/ - repeated ResourceQuota items = 2; -} - -// ResourceQuotaSpec defines the desired hard limits to enforce for Quota. -message ResourceQuotaSpec { - // hard is the set of desired hard limits for each named resource. - // More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/ - // +optional - map hard = 1; - - // A collection of filters that must match each object tracked by a quota. - // If not specified, the quota matches all objects. - // +optional - repeated string scopes = 2; - - // scopeSelector is also a collection of filters like scopes that must match each object tracked by a quota - // but expressed using ScopeSelectorOperator in combination with possible values. - // For a resource to match, both scopes AND scopeSelector (if specified in spec), must be matched. - // +optional - optional ScopeSelector scopeSelector = 3; -} - -// ResourceQuotaStatus defines the enforced hard limits and observed use. -message ResourceQuotaStatus { - // Hard is the set of enforced hard limits for each named resource. - // More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/ - // +optional - map hard = 1; - - // Used is the current observed total usage of the resource in the namespace. - // +optional - map used = 2; -} - -// ResourceRequirements describes the compute resource requirements. -message ResourceRequirements { - // Limits describes the maximum amount of compute resources allowed. - // More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ - // +optional - map limits = 1; - - // Requests describes the minimum amount of compute resources required. - // If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - // otherwise to an implementation-defined value. - // More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ - // +optional - map requests = 2; -} - -// SELinuxOptions are the labels to be applied to the container -message SELinuxOptions { - // User is a SELinux user label that applies to the container. - // +optional - optional string user = 1; - - // Role is a SELinux role label that applies to the container. - // +optional - optional string role = 2; - - // Type is a SELinux type label that applies to the container. - // +optional - optional string type = 3; - - // Level is SELinux level label that applies to the container. - // +optional - optional string level = 4; -} - -// ScaleIOPersistentVolumeSource represents a persistent ScaleIO volume -message ScaleIOPersistentVolumeSource { - // The host address of the ScaleIO API Gateway. - optional string gateway = 1; - - // The name of the storage system as configured in ScaleIO. - optional string system = 2; - - // SecretRef references to the secret for ScaleIO user and other - // sensitive information. If this is not provided, Login operation will fail. - optional SecretReference secretRef = 3; - - // Flag to enable/disable SSL communication with Gateway, default false - // +optional - optional bool sslEnabled = 4; - - // The name of the ScaleIO Protection Domain for the configured storage. - // +optional - optional string protectionDomain = 5; - - // The ScaleIO Storage Pool associated with the protection domain. - // +optional - optional string storagePool = 6; - - // Indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. - // Default is ThinProvisioned. - // +optional - optional string storageMode = 7; - - // The name of a volume already created in the ScaleIO system - // that is associated with this volume source. - optional string volumeName = 8; - - // Filesystem type to mount. - // Must be a filesystem type supported by the host operating system. - // Ex. "ext4", "xfs", "ntfs". - // Default is "xfs" - // +optional - optional string fsType = 9; - - // Defaults to false (read/write). ReadOnly here will force - // the ReadOnly setting in VolumeMounts. - // +optional - optional bool readOnly = 10; -} - -// ScaleIOVolumeSource represents a persistent ScaleIO volume -message ScaleIOVolumeSource { - // The host address of the ScaleIO API Gateway. - optional string gateway = 1; - - // The name of the storage system as configured in ScaleIO. - optional string system = 2; - - // SecretRef references to the secret for ScaleIO user and other - // sensitive information. If this is not provided, Login operation will fail. - optional LocalObjectReference secretRef = 3; - - // Flag to enable/disable SSL communication with Gateway, default false - // +optional - optional bool sslEnabled = 4; - - // The name of the ScaleIO Protection Domain for the configured storage. - // +optional - optional string protectionDomain = 5; - - // The ScaleIO Storage Pool associated with the protection domain. - // +optional - optional string storagePool = 6; - - // Indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. - // Default is ThinProvisioned. - // +optional - optional string storageMode = 7; - - // The name of a volume already created in the ScaleIO system - // that is associated with this volume source. - optional string volumeName = 8; - - // Filesystem type to mount. - // Must be a filesystem type supported by the host operating system. - // Ex. "ext4", "xfs", "ntfs". - // Default is "xfs". - // +optional - optional string fsType = 9; - - // Defaults to false (read/write). ReadOnly here will force - // the ReadOnly setting in VolumeMounts. - // +optional - optional bool readOnly = 10; -} - -// A scope selector represents the AND of the selectors represented -// by the scoped-resource selector requirements. -message ScopeSelector { - // A list of scope selector requirements by scope of the resources. - // +optional - repeated ScopedResourceSelectorRequirement matchExpressions = 1; -} - -// A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator -// that relates the scope name and values. -message ScopedResourceSelectorRequirement { - // The name of the scope that the selector applies to. - optional string scopeName = 1; - - // Represents a scope's relationship to a set of values. - // Valid operators are In, NotIn, Exists, DoesNotExist. - optional string operator = 2; - - // An array of string values. If the operator is In or NotIn, - // the values array must be non-empty. If the operator is Exists or DoesNotExist, - // the values array must be empty. - // This array is replaced during a strategic merge patch. - // +optional - repeated string values = 3; -} - -// Secret holds secret data of a certain type. The total bytes of the values in -// the Data field must be less than MaxSecretSize bytes. -message Secret { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Data contains the secret data. Each key must consist of alphanumeric - // characters, '-', '_' or '.'. The serialized form of the secret data is a - // base64 encoded string, representing the arbitrary (possibly non-string) - // data value here. Described in https://tools.ietf.org/html/rfc4648#section-4 - // +optional - map data = 2; - - // stringData allows specifying non-binary secret data in string form. - // It is provided as a write-only convenience method. - // All keys and values are merged into the data field on write, overwriting any existing values. - // It is never output when reading from the API. - // +k8s:conversion-gen=false - // +optional - map stringData = 4; - - // Used to facilitate programmatic handling of secret data. - // +optional - optional string type = 3; -} - -// SecretEnvSource selects a Secret to populate the environment -// variables with. -// -// The contents of the target Secret's Data field will represent the -// key-value pairs as environment variables. -message SecretEnvSource { - // The Secret to select from. - optional LocalObjectReference localObjectReference = 1; - - // Specify whether the Secret must be defined - // +optional - optional bool optional = 2; -} - -// SecretKeySelector selects a key of a Secret. -message SecretKeySelector { - // The name of the secret in the pod's namespace to select from. - optional LocalObjectReference localObjectReference = 1; - - // The key of the secret to select from. Must be a valid secret key. - optional string key = 2; - - // Specify whether the Secret or it's key must be defined - // +optional - optional bool optional = 3; -} - -// SecretList is a list of Secret. -message SecretList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of secret objects. - // More info: https://kubernetes.io/docs/concepts/configuration/secret - repeated Secret items = 2; -} - -// Adapts a secret into a projected volume. -// -// The contents of the target Secret's Data field will be presented in a -// projected volume as files using the keys in the Data field as the file names. -// Note that this is identical to a secret volume source without the default -// mode. -message SecretProjection { - optional LocalObjectReference localObjectReference = 1; - - // If unspecified, each key-value pair in the Data field of the referenced - // Secret will be projected into the volume as a file whose name is the - // key and content is the value. If specified, the listed keys will be - // projected into the specified paths, and unlisted keys will not be - // present. If a key is specified which is not present in the Secret, - // the volume setup will error unless it is marked optional. Paths must be - // relative and may not contain the '..' path or start with '..'. - // +optional - repeated KeyToPath items = 2; - - // Specify whether the Secret or its key must be defined - // +optional - optional bool optional = 4; -} - -// SecretReference represents a Secret Reference. It has enough information to retrieve secret -// in any namespace -message SecretReference { - // Name is unique within a namespace to reference a secret resource. - // +optional - optional string name = 1; - - // Namespace defines the space within which the secret name must be unique. - // +optional - optional string namespace = 2; -} - -// Adapts a Secret into a volume. -// -// The contents of the target Secret's Data field will be presented in a volume -// as files using the keys in the Data field as the file names. -// Secret volumes support ownership management and SELinux relabeling. -message SecretVolumeSource { - // Name of the secret in the pod's namespace to use. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#secret - // +optional - optional string secretName = 1; - - // If unspecified, each key-value pair in the Data field of the referenced - // Secret will be projected into the volume as a file whose name is the - // key and content is the value. If specified, the listed keys will be - // projected into the specified paths, and unlisted keys will not be - // present. If a key is specified which is not present in the Secret, - // the volume setup will error unless it is marked optional. Paths must be - // relative and may not contain the '..' path or start with '..'. - // +optional - repeated KeyToPath items = 2; - - // Optional: mode bits to use on created files by default. Must be a - // value between 0 and 0777. Defaults to 0644. - // Directories within the path are not affected by this setting. - // This might be in conflict with other options that affect the file - // mode, like fsGroup, and the result can be other mode bits set. - // +optional - optional int32 defaultMode = 3; - - // Specify whether the Secret or it's keys must be defined - // +optional - optional bool optional = 4; -} - -// SecurityContext holds security configuration that will be applied to a container. -// Some fields are present in both SecurityContext and PodSecurityContext. When both -// are set, the values in SecurityContext take precedence. -message SecurityContext { - // The capabilities to add/drop when running containers. - // Defaults to the default set of capabilities granted by the container runtime. - // +optional - optional Capabilities capabilities = 1; - - // Run container in privileged mode. - // Processes in privileged containers are essentially equivalent to root on the host. - // Defaults to false. - // +optional - optional bool privileged = 2; - - // The SELinux context to be applied to the container. - // If unspecified, the container runtime will allocate a random SELinux context for each - // container. May also be set in PodSecurityContext. If set in both SecurityContext and - // PodSecurityContext, the value specified in SecurityContext takes precedence. - // +optional - optional SELinuxOptions seLinuxOptions = 3; - - // The UID to run the entrypoint of the container process. - // Defaults to user specified in image metadata if unspecified. - // May also be set in PodSecurityContext. If set in both SecurityContext and - // PodSecurityContext, the value specified in SecurityContext takes precedence. - // +optional - optional int64 runAsUser = 4; - - // The GID to run the entrypoint of the container process. - // Uses runtime default if unset. - // May also be set in PodSecurityContext. If set in both SecurityContext and - // PodSecurityContext, the value specified in SecurityContext takes precedence. - // +optional - optional int64 runAsGroup = 8; - - // Indicates that the container must run as a non-root user. - // If true, the Kubelet will validate the image at runtime to ensure that it - // does not run as UID 0 (root) and fail to start the container if it does. - // If unset or false, no such validation will be performed. - // May also be set in PodSecurityContext. If set in both SecurityContext and - // PodSecurityContext, the value specified in SecurityContext takes precedence. - // +optional - optional bool runAsNonRoot = 5; - - // Whether this container has a read-only root filesystem. - // Default is false. - // +optional - optional bool readOnlyRootFilesystem = 6; - - // AllowPrivilegeEscalation controls whether a process can gain more - // privileges than its parent process. This bool directly controls if - // the no_new_privs flag will be set on the container process. - // AllowPrivilegeEscalation is true always when the container is: - // 1) run as Privileged - // 2) has CAP_SYS_ADMIN - // +optional - optional bool allowPrivilegeEscalation = 7; - - // procMount denotes the type of proc mount to use for the containers. - // The default is DefaultProcMount which uses the container runtime defaults for - // readonly paths and masked paths. - // This requires the ProcMountType feature flag to be enabled. - // +optional - optional string procMount = 9; -} - -// SerializedReference is a reference to serialized object. -message SerializedReference { - // The reference to an object in the system. - // +optional - optional ObjectReference reference = 1; -} - -// Service is a named abstraction of software service (for example, mysql) consisting of local port -// (for example 3306) that the proxy listens on, and the selector that determines which pods -// will answer requests sent through the proxy. -message Service { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec defines the behavior of a service. - // https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional ServiceSpec spec = 2; - - // Most recently observed status of the service. - // Populated by the system. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional ServiceStatus status = 3; -} - -// ServiceAccount binds together: -// * a name, understood by users, and perhaps by peripheral systems, for an identity -// * a principal that can be authenticated and authorized -// * a set of secrets -message ServiceAccount { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Secrets is the list of secrets allowed to be used by pods running using this ServiceAccount. - // More info: https://kubernetes.io/docs/concepts/configuration/secret - // +optional - // +patchMergeKey=name - // +patchStrategy=merge - repeated ObjectReference secrets = 2; - - // ImagePullSecrets is a list of references to secrets in the same namespace to use for pulling any images - // in pods that reference this ServiceAccount. ImagePullSecrets are distinct from Secrets because Secrets - // can be mounted in the pod, but ImagePullSecrets are only accessed by the kubelet. - // More info: https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod - // +optional - repeated LocalObjectReference imagePullSecrets = 3; - - // AutomountServiceAccountToken indicates whether pods running as this service account should have an API token automatically mounted. - // Can be overridden at the pod level. - // +optional - optional bool automountServiceAccountToken = 4; -} - -// ServiceAccountList is a list of ServiceAccount objects -message ServiceAccountList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // List of ServiceAccounts. - // More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ - repeated ServiceAccount items = 2; -} - -// ServiceAccountTokenProjection represents a projected service account token -// volume. This projection can be used to insert a service account token into -// the pods runtime filesystem for use against APIs (Kubernetes API Server or -// otherwise). -message ServiceAccountTokenProjection { - // Audience is the intended audience of the token. A recipient of a token - // must identify itself with an identifier specified in the audience of the - // token, and otherwise should reject the token. The audience defaults to the - // identifier of the apiserver. - // +optional - optional string audience = 1; - - // ExpirationSeconds is the requested duration of validity of the service - // account token. As the token approaches expiration, the kubelet volume - // plugin will proactively rotate the service account token. The kubelet will - // start trying to rotate the token if the token is older than 80 percent of - // its time to live or if the token is older than 24 hours.Defaults to 1 hour - // and must be at least 10 minutes. - // +optional - optional int64 expirationSeconds = 2; - - // Path is the path relative to the mount point of the file to project the - // token into. - optional string path = 3; -} - -// ServiceList holds a list of services. -message ServiceList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // List of services - repeated Service items = 2; -} - -// ServicePort contains information on service's port. -message ServicePort { - // The name of this port within the service. This must be a DNS_LABEL. - // All ports within a ServiceSpec must have unique names. This maps to - // the 'Name' field in EndpointPort objects. - // Optional if only one ServicePort is defined on this service. - // +optional - optional string name = 1; - - // The IP protocol for this port. Supports "TCP", "UDP", and "SCTP". - // Default is TCP. - // +optional - optional string protocol = 2; - - // The port that will be exposed by this service. - optional int32 port = 3; - - // Number or name of the port to access on the pods targeted by the service. - // Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME. - // If this is a string, it will be looked up as a named port in the - // target Pod's container ports. If this is not specified, the value - // of the 'port' field is used (an identity map). - // This field is ignored for services with clusterIP=None, and should be - // omitted or set equal to the 'port' field. - // More info: https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service - // +optional - optional k8s.io.apimachinery.pkg.util.intstr.IntOrString targetPort = 4; - - // The port on each node on which this service is exposed when type=NodePort or LoadBalancer. - // Usually assigned by the system. If specified, it will be allocated to the service - // if unused or else creation of the service will fail. - // Default is to auto-allocate a port if the ServiceType of this Service requires one. - // More info: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - // +optional - optional int32 nodePort = 5; -} - -// ServiceProxyOptions is the query options to a Service's proxy call. -message ServiceProxyOptions { - // Path is the part of URLs that include service endpoints, suffixes, - // and parameters to use for the current proxy request to service. - // For example, the whole request URL is - // http://localhost/api/v1/namespaces/kube-system/services/elasticsearch-logging/_search?q=user:kimchy. - // Path is _search?q=user:kimchy. - // +optional - optional string path = 1; -} - -// ServiceSpec describes the attributes that a user creates on a service. -message ServiceSpec { - // The list of ports that are exposed by this service. - // More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies - // +patchMergeKey=port - // +patchStrategy=merge - repeated ServicePort ports = 1; - - // Route service traffic to pods with label keys and values matching this - // selector. If empty or not present, the service is assumed to have an - // external process managing its endpoints, which Kubernetes will not - // modify. Only applies to types ClusterIP, NodePort, and LoadBalancer. - // Ignored if type is ExternalName. - // More info: https://kubernetes.io/docs/concepts/services-networking/service/ - // +optional - map selector = 2; - - // clusterIP is the IP address of the service and is usually assigned - // randomly by the master. If an address is specified manually and is not in - // use by others, it will be allocated to the service; otherwise, creation - // of the service will fail. This field can not be changed through updates. - // Valid values are "None", empty string (""), or a valid IP address. "None" - // can be specified for headless services when proxying is not required. - // Only applies to types ClusterIP, NodePort, and LoadBalancer. Ignored if - // type is ExternalName. - // More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies - // +optional - optional string clusterIP = 3; - - // type determines how the Service is exposed. Defaults to ClusterIP. Valid - // options are ExternalName, ClusterIP, NodePort, and LoadBalancer. - // "ExternalName" maps to the specified externalName. - // "ClusterIP" allocates a cluster-internal IP address for load-balancing to - // endpoints. Endpoints are determined by the selector or if that is not - // specified, by manual construction of an Endpoints object. If clusterIP is - // "None", no virtual IP is allocated and the endpoints are published as a - // set of endpoints rather than a stable IP. - // "NodePort" builds on ClusterIP and allocates a port on every node which - // routes to the clusterIP. - // "LoadBalancer" builds on NodePort and creates an - // external load-balancer (if supported in the current cloud) which routes - // to the clusterIP. - // More info: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services---service-types - // +optional - optional string type = 4; - - // externalIPs is a list of IP addresses for which nodes in the cluster - // will also accept traffic for this service. These IPs are not managed by - // Kubernetes. The user is responsible for ensuring that traffic arrives - // at a node with this IP. A common example is external load-balancers - // that are not part of the Kubernetes system. - // +optional - repeated string externalIPs = 5; - - // Supports "ClientIP" and "None". Used to maintain session affinity. - // Enable client IP based session affinity. - // Must be ClientIP or None. - // Defaults to None. - // More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies - // +optional - optional string sessionAffinity = 7; - - // Only applies to Service Type: LoadBalancer - // LoadBalancer will get created with the IP specified in this field. - // This feature depends on whether the underlying cloud-provider supports specifying - // the loadBalancerIP when a load balancer is created. - // This field will be ignored if the cloud-provider does not support the feature. - // +optional - optional string loadBalancerIP = 8; - - // If specified and supported by the platform, this will restrict traffic through the cloud-provider - // load-balancer will be restricted to the specified client IPs. This field will be ignored if the - // cloud-provider does not support the feature." - // More info: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/ - // +optional - repeated string loadBalancerSourceRanges = 9; - - // externalName is the external reference that kubedns or equivalent will - // return as a CNAME record for this service. No proxying will be involved. - // Must be a valid RFC-1123 hostname (https://tools.ietf.org/html/rfc1123) - // and requires Type to be ExternalName. - // +optional - optional string externalName = 10; - - // externalTrafficPolicy denotes if this Service desires to route external - // traffic to node-local or cluster-wide endpoints. "Local" preserves the - // client source IP and avoids a second hop for LoadBalancer and Nodeport - // type services, but risks potentially imbalanced traffic spreading. - // "Cluster" obscures the client source IP and may cause a second hop to - // another node, but should have good overall load-spreading. - // +optional - optional string externalTrafficPolicy = 11; - - // healthCheckNodePort specifies the healthcheck nodePort for the service. - // If not specified, HealthCheckNodePort is created by the service api - // backend with the allocated nodePort. Will use user-specified nodePort value - // if specified by the client. Only effects when Type is set to LoadBalancer - // and ExternalTrafficPolicy is set to Local. - // +optional - optional int32 healthCheckNodePort = 12; - - // publishNotReadyAddresses, when set to true, indicates that DNS implementations - // must publish the notReadyAddresses of subsets for the Endpoints associated with - // the Service. The default value is false. - // The primary use case for setting this field is to use a StatefulSet's Headless Service - // to propagate SRV records for its Pods without respect to their readiness for purpose - // of peer discovery. - // +optional - optional bool publishNotReadyAddresses = 13; - - // sessionAffinityConfig contains the configurations of session affinity. - // +optional - optional SessionAffinityConfig sessionAffinityConfig = 14; -} - -// ServiceStatus represents the current status of a service. -message ServiceStatus { - // LoadBalancer contains the current status of the load-balancer, - // if one is present. - // +optional - optional LoadBalancerStatus loadBalancer = 1; -} - -// SessionAffinityConfig represents the configurations of session affinity. -message SessionAffinityConfig { - // clientIP contains the configurations of Client IP based session affinity. - // +optional - optional ClientIPConfig clientIP = 1; -} - -// Represents a StorageOS persistent volume resource. -message StorageOSPersistentVolumeSource { - // VolumeName is the human-readable name of the StorageOS volume. Volume - // names are only unique within a namespace. - optional string volumeName = 1; - - // VolumeNamespace specifies the scope of the volume within StorageOS. If no - // namespace is specified then the Pod's namespace will be used. This allows the - // Kubernetes name scoping to be mirrored within StorageOS for tighter integration. - // Set VolumeName to any name to override the default behaviour. - // Set to "default" if you are not using namespaces within StorageOS. - // Namespaces that do not pre-exist within StorageOS will be created. - // +optional - optional string volumeNamespace = 2; - - // Filesystem type to mount. - // Must be a filesystem type supported by the host operating system. - // Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - // +optional - optional string fsType = 3; - - // Defaults to false (read/write). ReadOnly here will force - // the ReadOnly setting in VolumeMounts. - // +optional - optional bool readOnly = 4; - - // SecretRef specifies the secret to use for obtaining the StorageOS API - // credentials. If not specified, default values will be attempted. - // +optional - optional ObjectReference secretRef = 5; -} - -// Represents a StorageOS persistent volume resource. -message StorageOSVolumeSource { - // VolumeName is the human-readable name of the StorageOS volume. Volume - // names are only unique within a namespace. - optional string volumeName = 1; - - // VolumeNamespace specifies the scope of the volume within StorageOS. If no - // namespace is specified then the Pod's namespace will be used. This allows the - // Kubernetes name scoping to be mirrored within StorageOS for tighter integration. - // Set VolumeName to any name to override the default behaviour. - // Set to "default" if you are not using namespaces within StorageOS. - // Namespaces that do not pre-exist within StorageOS will be created. - // +optional - optional string volumeNamespace = 2; - - // Filesystem type to mount. - // Must be a filesystem type supported by the host operating system. - // Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - // +optional - optional string fsType = 3; - - // Defaults to false (read/write). ReadOnly here will force - // the ReadOnly setting in VolumeMounts. - // +optional - optional bool readOnly = 4; - - // SecretRef specifies the secret to use for obtaining the StorageOS API - // credentials. If not specified, default values will be attempted. - // +optional - optional LocalObjectReference secretRef = 5; -} - -// Sysctl defines a kernel parameter to be set -message Sysctl { - // Name of a property to set - optional string name = 1; - - // Value of a property to set - optional string value = 2; -} - -// TCPSocketAction describes an action based on opening a socket -message TCPSocketAction { - // Number or name of the port to access on the container. - // Number must be in the range 1 to 65535. - // Name must be an IANA_SVC_NAME. - optional k8s.io.apimachinery.pkg.util.intstr.IntOrString port = 1; - - // Optional: Host name to connect to, defaults to the pod IP. - // +optional - optional string host = 2; -} - -// The node this Taint is attached to has the "effect" on -// any pod that does not tolerate the Taint. -message Taint { - // Required. The taint key to be applied to a node. - optional string key = 1; - - // Required. The taint value corresponding to the taint key. - // +optional - optional string value = 2; - - // Required. The effect of the taint on pods - // that do not tolerate the taint. - // Valid effects are NoSchedule, PreferNoSchedule and NoExecute. - optional string effect = 3; - - // TimeAdded represents the time at which the taint was added. - // It is only written for NoExecute taints. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time timeAdded = 4; -} - -// The pod this Toleration is attached to tolerates any taint that matches -// the triple using the matching operator . -message Toleration { - // Key is the taint key that the toleration applies to. Empty means match all taint keys. - // If the key is empty, operator must be Exists; this combination means to match all values and all keys. - // +optional - optional string key = 1; - - // Operator represents a key's relationship to the value. - // Valid operators are Exists and Equal. Defaults to Equal. - // Exists is equivalent to wildcard for value, so that a pod can - // tolerate all taints of a particular category. - // +optional - optional string operator = 2; - - // Value is the taint value the toleration matches to. - // If the operator is Exists, the value should be empty, otherwise just a regular string. - // +optional - optional string value = 3; - - // Effect indicates the taint effect to match. Empty means match all taint effects. - // When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - // +optional - optional string effect = 4; - - // TolerationSeconds represents the period of time the toleration (which must be - // of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - // it is not set, which means tolerate the taint forever (do not evict). Zero and - // negative values will be treated as 0 (evict immediately) by the system. - // +optional - optional int64 tolerationSeconds = 5; -} - -// A topology selector requirement is a selector that matches given label. -// This is an alpha feature and may change in the future. -message TopologySelectorLabelRequirement { - // The label key that the selector applies to. - optional string key = 1; - - // An array of string values. One value must match the label to be selected. - // Each entry in Values is ORed. - repeated string values = 2; -} - -// A topology selector term represents the result of label queries. -// A null or empty topology selector term matches no objects. -// The requirements of them are ANDed. -// It provides a subset of functionality as NodeSelectorTerm. -// This is an alpha feature and may change in the future. -message TopologySelectorTerm { - // A list of topology selector requirements by labels. - // +optional - repeated TopologySelectorLabelRequirement matchLabelExpressions = 1; -} - -// TypedLocalObjectReference contains enough information to let you locate the -// typed referenced object inside the same namespace. -message TypedLocalObjectReference { - // APIGroup is the group for the resource being referenced. - // If APIGroup is not specified, the specified Kind must be in the core API group. - // For any other third-party types, APIGroup is required. - // +optional - optional string apiGroup = 1; - - // Kind is the type of resource being referenced - optional string kind = 2; - - // Name is the name of resource being referenced - optional string name = 3; -} - -// Volume represents a named volume in a pod that may be accessed by any container in the pod. -message Volume { - // Volume's name. - // Must be a DNS_LABEL and unique within the pod. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - optional string name = 1; - - // VolumeSource represents the location and type of the mounted volume. - // If not specified, the Volume is implied to be an EmptyDir. - // This implied behavior is deprecated and will be removed in a future version. - optional VolumeSource volumeSource = 2; -} - -// volumeDevice describes a mapping of a raw block device within a container. -message VolumeDevice { - // name must match the name of a persistentVolumeClaim in the pod - optional string name = 1; - - // devicePath is the path inside of the container that the device will be mapped to. - optional string devicePath = 2; -} - -// VolumeMount describes a mounting of a Volume within a container. -message VolumeMount { - // This must match the Name of a Volume. - optional string name = 1; - - // Mounted read-only if true, read-write otherwise (false or unspecified). - // Defaults to false. - // +optional - optional bool readOnly = 2; - - // Path within the container at which the volume should be mounted. Must - // not contain ':'. - optional string mountPath = 3; - - // Path within the volume from which the container's volume should be mounted. - // Defaults to "" (volume's root). - // +optional - optional string subPath = 4; - - // mountPropagation determines how mounts are propagated from the host - // to container and the other way around. - // When not set, MountPropagationNone is used. - // This field is beta in 1.10. - // +optional - optional string mountPropagation = 5; -} - -// VolumeNodeAffinity defines constraints that limit what nodes this volume can be accessed from. -message VolumeNodeAffinity { - // Required specifies hard node constraints that must be met. - optional NodeSelector required = 1; -} - -// Projection that may be projected along with other supported volume types -message VolumeProjection { - // information about the secret data to project - // +optional - optional SecretProjection secret = 1; - - // information about the downwardAPI data to project - // +optional - optional DownwardAPIProjection downwardAPI = 2; - - // information about the configMap data to project - // +optional - optional ConfigMapProjection configMap = 3; - - // information about the serviceAccountToken data to project - // +optional - optional ServiceAccountTokenProjection serviceAccountToken = 4; -} - -// Represents the source of a volume to mount. -// Only one of its members may be specified. -message VolumeSource { - // HostPath represents a pre-existing file or directory on the host - // machine that is directly exposed to the container. This is generally - // used for system agents or other privileged things that are allowed - // to see the host machine. Most containers will NOT need this. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - // --- - // TODO(jonesdl) We need to restrict who can use host directory mounts and who can/can not - // mount host directories as read/write. - // +optional - optional HostPathVolumeSource hostPath = 1; - - // EmptyDir represents a temporary directory that shares a pod's lifetime. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir - // +optional - optional EmptyDirVolumeSource emptyDir = 2; - - // GCEPersistentDisk represents a GCE Disk resource that is attached to a - // kubelet's host machine and then exposed to the pod. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - // +optional - optional GCEPersistentDiskVolumeSource gcePersistentDisk = 3; - - // AWSElasticBlockStore represents an AWS Disk resource that is attached to a - // kubelet's host machine and then exposed to the pod. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - // +optional - optional AWSElasticBlockStoreVolumeSource awsElasticBlockStore = 4; - - // GitRepo represents a git repository at a particular revision. - // DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an - // EmptyDir into an InitContainer that clones the repo using git, then mount the EmptyDir - // into the Pod's container. - // +optional - optional GitRepoVolumeSource gitRepo = 5; - - // Secret represents a secret that should populate this volume. - // More info: https://kubernetes.io/docs/concepts/storage/volumes#secret - // +optional - optional SecretVolumeSource secret = 6; - - // NFS represents an NFS mount on the host that shares a pod's lifetime - // More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - // +optional - optional NFSVolumeSource nfs = 7; - - // ISCSI represents an ISCSI Disk resource that is attached to a - // kubelet's host machine and then exposed to the pod. - // More info: https://releases.k8s.io/HEAD/examples/volumes/iscsi/README.md - // +optional - optional ISCSIVolumeSource iscsi = 8; - - // Glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. - // More info: https://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md - // +optional - optional GlusterfsVolumeSource glusterfs = 9; - - // PersistentVolumeClaimVolumeSource represents a reference to a - // PersistentVolumeClaim in the same namespace. - // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims - // +optional - optional PersistentVolumeClaimVolumeSource persistentVolumeClaim = 10; - - // RBD represents a Rados Block Device mount on the host that shares a pod's lifetime. - // More info: https://releases.k8s.io/HEAD/examples/volumes/rbd/README.md - // +optional - optional RBDVolumeSource rbd = 11; - - // FlexVolume represents a generic volume resource that is - // provisioned/attached using an exec based plugin. - // +optional - optional FlexVolumeSource flexVolume = 12; - - // Cinder represents a cinder volume attached and mounted on kubelets host machine - // More info: https://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md - // +optional - optional CinderVolumeSource cinder = 13; - - // CephFS represents a Ceph FS mount on the host that shares a pod's lifetime - // +optional - optional CephFSVolumeSource cephfs = 14; - - // Flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running - // +optional - optional FlockerVolumeSource flocker = 15; - - // DownwardAPI represents downward API about the pod that should populate this volume - // +optional - optional DownwardAPIVolumeSource downwardAPI = 16; - - // FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod. - // +optional - optional FCVolumeSource fc = 17; - - // AzureFile represents an Azure File Service mount on the host and bind mount to the pod. - // +optional - optional AzureFileVolumeSource azureFile = 18; - - // ConfigMap represents a configMap that should populate this volume - // +optional - optional ConfigMapVolumeSource configMap = 19; - - // VsphereVolume represents a vSphere volume attached and mounted on kubelets host machine - // +optional - optional VsphereVirtualDiskVolumeSource vsphereVolume = 20; - - // Quobyte represents a Quobyte mount on the host that shares a pod's lifetime - // +optional - optional QuobyteVolumeSource quobyte = 21; - - // AzureDisk represents an Azure Data Disk mount on the host and bind mount to the pod. - // +optional - optional AzureDiskVolumeSource azureDisk = 22; - - // PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine - optional PhotonPersistentDiskVolumeSource photonPersistentDisk = 23; - - // Items for all in one resources secrets, configmaps, and downward API - optional ProjectedVolumeSource projected = 26; - - // PortworxVolume represents a portworx volume attached and mounted on kubelets host machine - // +optional - optional PortworxVolumeSource portworxVolume = 24; - - // ScaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes. - // +optional - optional ScaleIOVolumeSource scaleIO = 25; - - // StorageOS represents a StorageOS volume attached and mounted on Kubernetes nodes. - // +optional - optional StorageOSVolumeSource storageos = 27; -} - -// Represents a vSphere volume resource. -message VsphereVirtualDiskVolumeSource { - // Path that identifies vSphere volume vmdk - optional string volumePath = 1; - - // Filesystem type to mount. - // Must be a filesystem type supported by the host operating system. - // Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - // +optional - optional string fsType = 2; - - // Storage Policy Based Management (SPBM) profile name. - // +optional - optional string storagePolicyName = 3; - - // Storage Policy Based Management (SPBM) profile ID associated with the StoragePolicyName. - // +optional - optional string storagePolicyID = 4; -} - -// The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) -message WeightedPodAffinityTerm { - // weight associated with matching the corresponding podAffinityTerm, - // in the range 1-100. - optional int32 weight = 1; - - // Required. A pod affinity term, associated with the corresponding weight. - optional PodAffinityTerm podAffinityTerm = 2; -} - diff --git a/vendor/k8s.io/api/events/v1beta1/generated.proto b/vendor/k8s.io/api/events/v1beta1/generated.proto deleted file mode 100644 index b3e565e674..0000000000 --- a/vendor/k8s.io/api/events/v1beta1/generated.proto +++ /dev/null @@ -1,121 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.events.v1beta1; - -import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1beta1"; - -// Event is a report of an event somewhere in the cluster. It generally denotes some state change in the system. -message Event { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Required. Time when this Event was first observed. - optional k8s.io.apimachinery.pkg.apis.meta.v1.MicroTime eventTime = 2; - - // Data about the Event series this event represents or nil if it's a singleton Event. - // +optional - optional EventSeries series = 3; - - // Name of the controller that emitted this Event, e.g. `kubernetes.io/kubelet`. - // +optional - optional string reportingController = 4; - - // ID of the controller instance, e.g. `kubelet-xyzf`. - // +optional - optional string reportingInstance = 5; - - // What action was taken/failed regarding to the regarding object. - // +optional - optional string action = 6; - - // Why the action was taken. - optional string reason = 7; - - // The object this Event is about. In most cases it's an Object reporting controller implements. - // E.g. ReplicaSetController implements ReplicaSets and this event is emitted because - // it acts on some changes in a ReplicaSet object. - // +optional - optional k8s.io.api.core.v1.ObjectReference regarding = 8; - - // Optional secondary object for more complex actions. E.g. when regarding object triggers - // a creation or deletion of related object. - // +optional - optional k8s.io.api.core.v1.ObjectReference related = 9; - - // Optional. A human-readable description of the status of this operation. - // Maximal length of the note is 1kB, but libraries should be prepared to - // handle values up to 64kB. - // +optional - optional string note = 10; - - // Type of this event (Normal, Warning), new types could be added in the - // future. - // +optional - optional string type = 11; - - // Deprecated field assuring backward compatibility with core.v1 Event type - // +optional - optional k8s.io.api.core.v1.EventSource deprecatedSource = 12; - - // Deprecated field assuring backward compatibility with core.v1 Event type - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time deprecatedFirstTimestamp = 13; - - // Deprecated field assuring backward compatibility with core.v1 Event type - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time deprecatedLastTimestamp = 14; - - // Deprecated field assuring backward compatibility with core.v1 Event type - // +optional - optional int32 deprecatedCount = 15; -} - -// EventList is a list of Event objects. -message EventList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of schema objects. - repeated Event items = 2; -} - -// EventSeries contain information on series of events, i.e. thing that was/is happening -// continuously for some time. -message EventSeries { - // Number of occurrences in this series up to the last heartbeat time - optional int32 count = 1; - - // Time when last Event from the series was seen before last heartbeat. - optional k8s.io.apimachinery.pkg.apis.meta.v1.MicroTime lastObservedTime = 2; - - // Information whether this series is ongoing or finished. - optional string state = 3; -} - diff --git a/vendor/k8s.io/api/extensions/v1beta1/generated.proto b/vendor/k8s.io/api/extensions/v1beta1/generated.proto deleted file mode 100644 index efcda7ebde..0000000000 --- a/vendor/k8s.io/api/extensions/v1beta1/generated.proto +++ /dev/null @@ -1,1160 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.extensions.v1beta1; - -import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1beta1"; - -// AllowedFlexVolume represents a single Flexvolume that is allowed to be used. -// Deprecated: use AllowedFlexVolume from policy API Group instead. -message AllowedFlexVolume { - // driver is the name of the Flexvolume driver. - optional string driver = 1; -} - -// AllowedHostPath defines the host volume conditions that will be enabled by a policy -// for pods to use. It requires the path prefix to be defined. -// Deprecated: use AllowedHostPath from policy API Group instead. -message AllowedHostPath { - // pathPrefix is the path prefix that the host volume must match. - // It does not support `*`. - // Trailing slashes are trimmed when validating the path prefix with a host path. - // - // Examples: - // `/foo` would allow `/foo`, `/foo/` and `/foo/bar` - // `/foo` would not allow `/food` or `/etc/foo` - optional string pathPrefix = 1; - - // when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly. - // +optional - optional bool readOnly = 2; -} - -// DEPRECATED - This group version of DaemonSet is deprecated by apps/v1beta2/DaemonSet. See the release notes for -// more information. -// DaemonSet represents the configuration of a daemon set. -message DaemonSet { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // The desired behavior of this daemon set. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional DaemonSetSpec spec = 2; - - // The current status of this daemon set. This data may be - // out of date by some window of time. - // Populated by the system. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional DaemonSetStatus status = 3; -} - -// DaemonSetCondition describes the state of a DaemonSet at a certain point. -message DaemonSetCondition { - // Type of DaemonSet condition. - optional string type = 1; - - // Status of the condition, one of True, False, Unknown. - optional string status = 2; - - // Last time the condition transitioned from one status to another. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 3; - - // The reason for the condition's last transition. - // +optional - optional string reason = 4; - - // A human readable message indicating details about the transition. - // +optional - optional string message = 5; -} - -// DaemonSetList is a collection of daemon sets. -message DaemonSetList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // A list of daemon sets. - repeated DaemonSet items = 2; -} - -// DaemonSetSpec is the specification of a daemon set. -message DaemonSetSpec { - // A label query over pods that are managed by the daemon set. - // Must match in order to be controlled. - // If empty, defaulted to labels on Pod template. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 1; - - // An object that describes the pod that will be created. - // The DaemonSet will create exactly one copy of this pod on every node - // that matches the template's node selector (or on every node if no node - // selector is specified). - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template - optional k8s.io.api.core.v1.PodTemplateSpec template = 2; - - // An update strategy to replace existing DaemonSet pods with new pods. - // +optional - optional DaemonSetUpdateStrategy updateStrategy = 3; - - // The minimum number of seconds for which a newly created DaemonSet pod should - // be ready without any of its container crashing, for it to be considered - // available. Defaults to 0 (pod will be considered available as soon as it - // is ready). - // +optional - optional int32 minReadySeconds = 4; - - // DEPRECATED. - // A sequence number representing a specific generation of the template. - // Populated by the system. It can be set only during the creation. - // +optional - optional int64 templateGeneration = 5; - - // The number of old history to retain to allow rollback. - // This is a pointer to distinguish between explicit zero and not specified. - // Defaults to 10. - // +optional - optional int32 revisionHistoryLimit = 6; -} - -// DaemonSetStatus represents the current status of a daemon set. -message DaemonSetStatus { - // The number of nodes that are running at least 1 - // daemon pod and are supposed to run the daemon pod. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/ - optional int32 currentNumberScheduled = 1; - - // The number of nodes that are running the daemon pod, but are - // not supposed to run the daemon pod. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/ - optional int32 numberMisscheduled = 2; - - // The total number of nodes that should be running the daemon - // pod (including nodes correctly running the daemon pod). - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/ - optional int32 desiredNumberScheduled = 3; - - // The number of nodes that should be running the daemon pod and have one - // or more of the daemon pod running and ready. - optional int32 numberReady = 4; - - // The most recent generation observed by the daemon set controller. - // +optional - optional int64 observedGeneration = 5; - - // The total number of nodes that are running updated daemon pod - // +optional - optional int32 updatedNumberScheduled = 6; - - // The number of nodes that should be running the - // daemon pod and have one or more of the daemon pod running and - // available (ready for at least spec.minReadySeconds) - // +optional - optional int32 numberAvailable = 7; - - // The number of nodes that should be running the - // daemon pod and have none of the daemon pod running and available - // (ready for at least spec.minReadySeconds) - // +optional - optional int32 numberUnavailable = 8; - - // Count of hash collisions for the DaemonSet. The DaemonSet controller - // uses this field as a collision avoidance mechanism when it needs to - // create the name for the newest ControllerRevision. - // +optional - optional int32 collisionCount = 9; - - // Represents the latest available observations of a DaemonSet's current state. - // +optional - // +patchMergeKey=type - // +patchStrategy=merge - repeated DaemonSetCondition conditions = 10; -} - -message DaemonSetUpdateStrategy { - // Type of daemon set update. Can be "RollingUpdate" or "OnDelete". - // Default is OnDelete. - // +optional - optional string type = 1; - - // Rolling update config params. Present only if type = "RollingUpdate". - // --- - // TODO: Update this to follow our convention for oneOf, whatever we decide it - // to be. Same as Deployment `strategy.rollingUpdate`. - // See https://github.com/kubernetes/kubernetes/issues/35345 - // +optional - optional RollingUpdateDaemonSet rollingUpdate = 2; -} - -// DEPRECATED - This group version of Deployment is deprecated by apps/v1beta2/Deployment. See the release notes for -// more information. -// Deployment enables declarative updates for Pods and ReplicaSets. -message Deployment { - // Standard object metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Specification of the desired behavior of the Deployment. - // +optional - optional DeploymentSpec spec = 2; - - // Most recently observed status of the Deployment. - // +optional - optional DeploymentStatus status = 3; -} - -// DeploymentCondition describes the state of a deployment at a certain point. -message DeploymentCondition { - // Type of deployment condition. - optional string type = 1; - - // Status of the condition, one of True, False, Unknown. - optional string status = 2; - - // The last time this condition was updated. - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastUpdateTime = 6; - - // Last time the condition transitioned from one status to another. - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 7; - - // The reason for the condition's last transition. - optional string reason = 4; - - // A human readable message indicating details about the transition. - optional string message = 5; -} - -// DeploymentList is a list of Deployments. -message DeploymentList { - // Standard list metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is the list of Deployments. - repeated Deployment items = 2; -} - -// DEPRECATED. -// DeploymentRollback stores the information required to rollback a deployment. -message DeploymentRollback { - // Required: This must match the Name of a deployment. - optional string name = 1; - - // The annotations to be updated to a deployment - // +optional - map updatedAnnotations = 2; - - // The config of this deployment rollback. - optional RollbackConfig rollbackTo = 3; -} - -// DeploymentSpec is the specification of the desired behavior of the Deployment. -message DeploymentSpec { - // Number of desired pods. This is a pointer to distinguish between explicit - // zero and not specified. Defaults to 1. - // +optional - optional int32 replicas = 1; - - // Label selector for pods. Existing ReplicaSets whose pods are - // selected by this will be the ones affected by this deployment. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 2; - - // Template describes the pods that will be created. - optional k8s.io.api.core.v1.PodTemplateSpec template = 3; - - // The deployment strategy to use to replace existing pods with new ones. - // +optional - // +patchStrategy=retainKeys - optional DeploymentStrategy strategy = 4; - - // Minimum number of seconds for which a newly created pod should be ready - // without any of its container crashing, for it to be considered available. - // Defaults to 0 (pod will be considered available as soon as it is ready) - // +optional - optional int32 minReadySeconds = 5; - - // The number of old ReplicaSets to retain to allow rollback. - // This is a pointer to distinguish between explicit zero and not specified. - // This is set to the max value of int32 (i.e. 2147483647) by default, which - // means "retaining all old RelicaSets". - // +optional - optional int32 revisionHistoryLimit = 6; - - // Indicates that the deployment is paused and will not be processed by the - // deployment controller. - // +optional - optional bool paused = 7; - - // DEPRECATED. - // The config this deployment is rolling back to. Will be cleared after rollback is done. - // +optional - optional RollbackConfig rollbackTo = 8; - - // The maximum time in seconds for a deployment to make progress before it - // is considered to be failed. The deployment controller will continue to - // process failed deployments and a condition with a ProgressDeadlineExceeded - // reason will be surfaced in the deployment status. Note that progress will - // not be estimated during the time a deployment is paused. This is set to - // the max value of int32 (i.e. 2147483647) by default, which means "no deadline". - // +optional - optional int32 progressDeadlineSeconds = 9; -} - -// DeploymentStatus is the most recently observed status of the Deployment. -message DeploymentStatus { - // The generation observed by the deployment controller. - // +optional - optional int64 observedGeneration = 1; - - // Total number of non-terminated pods targeted by this deployment (their labels match the selector). - // +optional - optional int32 replicas = 2; - - // Total number of non-terminated pods targeted by this deployment that have the desired template spec. - // +optional - optional int32 updatedReplicas = 3; - - // Total number of ready pods targeted by this deployment. - // +optional - optional int32 readyReplicas = 7; - - // Total number of available pods (ready for at least minReadySeconds) targeted by this deployment. - // +optional - optional int32 availableReplicas = 4; - - // Total number of unavailable pods targeted by this deployment. This is the total number of - // pods that are still required for the deployment to have 100% available capacity. They may - // either be pods that are running but not yet available or pods that still have not been created. - // +optional - optional int32 unavailableReplicas = 5; - - // Represents the latest available observations of a deployment's current state. - // +patchMergeKey=type - // +patchStrategy=merge - repeated DeploymentCondition conditions = 6; - - // Count of hash collisions for the Deployment. The Deployment controller uses this - // field as a collision avoidance mechanism when it needs to create the name for the - // newest ReplicaSet. - // +optional - optional int32 collisionCount = 8; -} - -// DeploymentStrategy describes how to replace existing pods with new ones. -message DeploymentStrategy { - // Type of deployment. Can be "Recreate" or "RollingUpdate". Default is RollingUpdate. - // +optional - optional string type = 1; - - // Rolling update config params. Present only if DeploymentStrategyType = - // RollingUpdate. - // --- - // TODO: Update this to follow our convention for oneOf, whatever we decide it - // to be. - // +optional - optional RollingUpdateDeployment rollingUpdate = 2; -} - -// FSGroupStrategyOptions defines the strategy type and options used to create the strategy. -// Deprecated: use FSGroupStrategyOptions from policy API Group instead. -message FSGroupStrategyOptions { - // rule is the strategy that will dictate what FSGroup is used in the SecurityContext. - // +optional - optional string rule = 1; - - // ranges are the allowed ranges of fs groups. If you would like to force a single - // fs group then supply a single range with the same start and end. Required for MustRunAs. - // +optional - repeated IDRange ranges = 2; -} - -// HTTPIngressPath associates a path regex with a backend. Incoming urls matching -// the path are forwarded to the backend. -message HTTPIngressPath { - // Path is an extended POSIX regex as defined by IEEE Std 1003.1, - // (i.e this follows the egrep/unix syntax, not the perl syntax) - // matched against the path of an incoming request. Currently it can - // contain characters disallowed from the conventional "path" - // part of a URL as defined by RFC 3986. Paths must begin with - // a '/'. If unspecified, the path defaults to a catch all sending - // traffic to the backend. - // +optional - optional string path = 1; - - // Backend defines the referenced service endpoint to which the traffic - // will be forwarded to. - optional IngressBackend backend = 2; -} - -// HTTPIngressRuleValue is a list of http selectors pointing to backends. -// In the example: http:///? -> backend where -// where parts of the url correspond to RFC 3986, this resource will be used -// to match against everything after the last '/' and before the first '?' -// or '#'. -message HTTPIngressRuleValue { - // A collection of paths that map requests to backends. - repeated HTTPIngressPath paths = 1; -} - -// HostPortRange defines a range of host ports that will be enabled by a policy -// for pods to use. It requires both the start and end to be defined. -// Deprecated: use HostPortRange from policy API Group instead. -message HostPortRange { - // min is the start of the range, inclusive. - optional int32 min = 1; - - // max is the end of the range, inclusive. - optional int32 max = 2; -} - -// IDRange provides a min/max of an allowed range of IDs. -// Deprecated: use IDRange from policy API Group instead. -message IDRange { - // min is the start of the range, inclusive. - optional int64 min = 1; - - // max is the end of the range, inclusive. - optional int64 max = 2; -} - -// DEPRECATED 1.9 - This group version of IPBlock is deprecated by networking/v1/IPBlock. -// IPBlock describes a particular CIDR (Ex. "192.168.1.1/24") that is allowed to the pods -// matched by a NetworkPolicySpec's podSelector. The except entry describes CIDRs that should -// not be included within this rule. -message IPBlock { - // CIDR is a string representing the IP Block - // Valid examples are "192.168.1.1/24" - optional string cidr = 1; - - // Except is a slice of CIDRs that should not be included within an IP Block - // Valid examples are "192.168.1.1/24" - // Except values will be rejected if they are outside the CIDR range - // +optional - repeated string except = 2; -} - -// Ingress is a collection of rules that allow inbound connections to reach the -// endpoints defined by a backend. An Ingress can be configured to give services -// externally-reachable urls, load balance traffic, terminate SSL, offer name -// based virtual hosting etc. -message Ingress { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec is the desired state of the Ingress. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional IngressSpec spec = 2; - - // Status is the current state of the Ingress. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional IngressStatus status = 3; -} - -// IngressBackend describes all endpoints for a given service and port. -message IngressBackend { - // Specifies the name of the referenced service. - optional string serviceName = 1; - - // Specifies the port of the referenced service. - optional k8s.io.apimachinery.pkg.util.intstr.IntOrString servicePort = 2; -} - -// IngressList is a collection of Ingress. -message IngressList { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is the list of Ingress. - repeated Ingress items = 2; -} - -// IngressRule represents the rules mapping the paths under a specified host to -// the related backend services. Incoming requests are first evaluated for a host -// match, then routed to the backend associated with the matching IngressRuleValue. -message IngressRule { - // Host is the fully qualified domain name of a network host, as defined - // by RFC 3986. Note the following deviations from the "host" part of the - // URI as defined in the RFC: - // 1. IPs are not allowed. Currently an IngressRuleValue can only apply to the - // IP in the Spec of the parent Ingress. - // 2. The `:` delimiter is not respected because ports are not allowed. - // Currently the port of an Ingress is implicitly :80 for http and - // :443 for https. - // Both these may change in the future. - // Incoming requests are matched against the host before the IngressRuleValue. - // If the host is unspecified, the Ingress routes all traffic based on the - // specified IngressRuleValue. - // +optional - optional string host = 1; - - // IngressRuleValue represents a rule to route requests for this IngressRule. - // If unspecified, the rule defaults to a http catch-all. Whether that sends - // just traffic matching the host to the default backend or all traffic to the - // default backend, is left to the controller fulfilling the Ingress. Http is - // currently the only supported IngressRuleValue. - // +optional - optional IngressRuleValue ingressRuleValue = 2; -} - -// IngressRuleValue represents a rule to apply against incoming requests. If the -// rule is satisfied, the request is routed to the specified backend. Currently -// mixing different types of rules in a single Ingress is disallowed, so exactly -// one of the following must be set. -message IngressRuleValue { - // +optional - optional HTTPIngressRuleValue http = 1; -} - -// IngressSpec describes the Ingress the user wishes to exist. -message IngressSpec { - // A default backend capable of servicing requests that don't match any - // rule. At least one of 'backend' or 'rules' must be specified. This field - // is optional to allow the loadbalancer controller or defaulting logic to - // specify a global default. - // +optional - optional IngressBackend backend = 1; - - // TLS configuration. Currently the Ingress only supports a single TLS - // port, 443. If multiple members of this list specify different hosts, they - // will be multiplexed on the same port according to the hostname specified - // through the SNI TLS extension, if the ingress controller fulfilling the - // ingress supports SNI. - // +optional - repeated IngressTLS tls = 2; - - // A list of host rules used to configure the Ingress. If unspecified, or - // no rule matches, all traffic is sent to the default backend. - // +optional - repeated IngressRule rules = 3; -} - -// IngressStatus describe the current state of the Ingress. -message IngressStatus { - // LoadBalancer contains the current status of the load-balancer. - // +optional - optional k8s.io.api.core.v1.LoadBalancerStatus loadBalancer = 1; -} - -// IngressTLS describes the transport layer security associated with an Ingress. -message IngressTLS { - // Hosts are a list of hosts included in the TLS certificate. The values in - // this list must match the name/s used in the tlsSecret. Defaults to the - // wildcard host setting for the loadbalancer controller fulfilling this - // Ingress, if left unspecified. - // +optional - repeated string hosts = 1; - - // SecretName is the name of the secret used to terminate SSL traffic on 443. - // Field is left optional to allow SSL routing based on SNI hostname alone. - // If the SNI host in a listener conflicts with the "Host" header field used - // by an IngressRule, the SNI host is used for termination and value of the - // Host header is used for routing. - // +optional - optional string secretName = 2; -} - -// DEPRECATED 1.9 - This group version of NetworkPolicy is deprecated by networking/v1/NetworkPolicy. -// NetworkPolicy describes what network traffic is allowed for a set of Pods -message NetworkPolicy { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Specification of the desired behavior for this NetworkPolicy. - // +optional - optional NetworkPolicySpec spec = 2; -} - -// DEPRECATED 1.9 - This group version of NetworkPolicyEgressRule is deprecated by networking/v1/NetworkPolicyEgressRule. -// NetworkPolicyEgressRule describes a particular set of traffic that is allowed out of pods -// matched by a NetworkPolicySpec's podSelector. The traffic must match both ports and to. -// This type is beta-level in 1.8 -message NetworkPolicyEgressRule { - // List of destination ports for outgoing traffic. - // Each item in this list is combined using a logical OR. If this field is - // empty or missing, this rule matches all ports (traffic not restricted by port). - // If this field is present and contains at least one item, then this rule allows - // traffic only if the traffic matches at least one port in the list. - // +optional - repeated NetworkPolicyPort ports = 1; - - // List of destinations for outgoing traffic of pods selected for this rule. - // Items in this list are combined using a logical OR operation. If this field is - // empty or missing, this rule matches all destinations (traffic not restricted by - // destination). If this field is present and contains at least one item, this rule - // allows traffic only if the traffic matches at least one item in the to list. - // +optional - repeated NetworkPolicyPeer to = 2; -} - -// DEPRECATED 1.9 - This group version of NetworkPolicyIngressRule is deprecated by networking/v1/NetworkPolicyIngressRule. -// This NetworkPolicyIngressRule matches traffic if and only if the traffic matches both ports AND from. -message NetworkPolicyIngressRule { - // List of ports which should be made accessible on the pods selected for this rule. - // Each item in this list is combined using a logical OR. - // If this field is empty or missing, this rule matches all ports (traffic not restricted by port). - // If this field is present and contains at least one item, then this rule allows traffic - // only if the traffic matches at least one port in the list. - // +optional - repeated NetworkPolicyPort ports = 1; - - // List of sources which should be able to access the pods selected for this rule. - // Items in this list are combined using a logical OR operation. - // If this field is empty or missing, this rule matches all sources (traffic not restricted by source). - // If this field is present and contains at least on item, this rule allows traffic only if the - // traffic matches at least one item in the from list. - // +optional - repeated NetworkPolicyPeer from = 2; -} - -// DEPRECATED 1.9 - This group version of NetworkPolicyList is deprecated by networking/v1/NetworkPolicyList. -// Network Policy List is a list of NetworkPolicy objects. -message NetworkPolicyList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of schema objects. - repeated NetworkPolicy items = 2; -} - -// DEPRECATED 1.9 - This group version of NetworkPolicyPeer is deprecated by networking/v1/NetworkPolicyPeer. -message NetworkPolicyPeer { - // This is a label selector which selects Pods. This field follows standard label - // selector semantics; if present but empty, it selects all pods. - // - // If NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects - // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. - // Otherwise it selects the Pods matching PodSelector in the policy's own Namespace. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector podSelector = 1; - - // Selects Namespaces using cluster-scoped labels. This field follows standard label - // selector semantics; if present but empty, it selects all namespaces. - // - // If PodSelector is also set, then the NetworkPolicyPeer as a whole selects - // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. - // Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector namespaceSelector = 2; - - // IPBlock defines policy on a particular IPBlock. If this field is set then - // neither of the other fields can be. - // +optional - optional IPBlock ipBlock = 3; -} - -// DEPRECATED 1.9 - This group version of NetworkPolicyPort is deprecated by networking/v1/NetworkPolicyPort. -message NetworkPolicyPort { - // Optional. The protocol (TCP, UDP, or SCTP) which traffic must match. - // If not specified, this field defaults to TCP. - // +optional - optional string protocol = 1; - - // If specified, the port on the given protocol. This can - // either be a numerical or named port on a pod. If this field is not provided, - // this matches all port names and numbers. - // If present, only traffic on the specified protocol AND port - // will be matched. - // +optional - optional k8s.io.apimachinery.pkg.util.intstr.IntOrString port = 2; -} - -// DEPRECATED 1.9 - This group version of NetworkPolicySpec is deprecated by networking/v1/NetworkPolicySpec. -message NetworkPolicySpec { - // Selects the pods to which this NetworkPolicy object applies. The array of ingress rules - // is applied to any pods selected by this field. Multiple network policies can select the - // same set of pods. In this case, the ingress rules for each are combined additively. - // This field is NOT optional and follows standard label selector semantics. - // An empty podSelector matches all pods in this namespace. - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector podSelector = 1; - - // List of ingress rules to be applied to the selected pods. - // Traffic is allowed to a pod if there are no NetworkPolicies selecting the pod - // OR if the traffic source is the pod's local node, - // OR if the traffic matches at least one ingress rule across all of the NetworkPolicy - // objects whose podSelector matches the pod. - // If this field is empty then this NetworkPolicy does not allow any traffic - // (and serves solely to ensure that the pods it selects are isolated by default). - // +optional - repeated NetworkPolicyIngressRule ingress = 2; - - // List of egress rules to be applied to the selected pods. Outgoing traffic is - // allowed if there are no NetworkPolicies selecting the pod (and cluster policy - // otherwise allows the traffic), OR if the traffic matches at least one egress rule - // across all of the NetworkPolicy objects whose podSelector matches the pod. If - // this field is empty then this NetworkPolicy limits all outgoing traffic (and serves - // solely to ensure that the pods it selects are isolated by default). - // This field is beta-level in 1.8 - // +optional - repeated NetworkPolicyEgressRule egress = 3; - - // List of rule types that the NetworkPolicy relates to. - // Valid options are Ingress, Egress, or Ingress,Egress. - // If this field is not specified, it will default based on the existence of Ingress or Egress rules; - // policies that contain an Egress section are assumed to affect Egress, and all policies - // (whether or not they contain an Ingress section) are assumed to affect Ingress. - // If you want to write an egress-only policy, you must explicitly specify policyTypes [ "Egress" ]. - // Likewise, if you want to write a policy that specifies that no egress is allowed, - // you must specify a policyTypes value that include "Egress" (since such a policy would not include - // an Egress section and would otherwise default to just [ "Ingress" ]). - // This field is beta-level in 1.8 - // +optional - repeated string policyTypes = 4; -} - -// PodSecurityPolicy governs the ability to make requests that affect the Security Context -// that will be applied to a pod and container. -// Deprecated: use PodSecurityPolicy from policy API Group instead. -message PodSecurityPolicy { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // spec defines the policy enforced. - // +optional - optional PodSecurityPolicySpec spec = 2; -} - -// PodSecurityPolicyList is a list of PodSecurityPolicy objects. -// Deprecated: use PodSecurityPolicyList from policy API Group instead. -message PodSecurityPolicyList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // items is a list of schema objects. - repeated PodSecurityPolicy items = 2; -} - -// PodSecurityPolicySpec defines the policy enforced. -// Deprecated: use PodSecurityPolicySpec from policy API Group instead. -message PodSecurityPolicySpec { - // privileged determines if a pod can request to be run as privileged. - // +optional - optional bool privileged = 1; - - // defaultAddCapabilities is the default set of capabilities that will be added to the container - // unless the pod spec specifically drops the capability. You may not list a capability in both - // defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly - // allowed, and need not be included in the allowedCapabilities list. - // +optional - repeated string defaultAddCapabilities = 2; - - // requiredDropCapabilities are the capabilities that will be dropped from the container. These - // are required to be dropped and cannot be added. - // +optional - repeated string requiredDropCapabilities = 3; - - // allowedCapabilities is a list of capabilities that can be requested to add to the container. - // Capabilities in this field may be added at the pod author's discretion. - // You must not list a capability in both allowedCapabilities and requiredDropCapabilities. - // +optional - repeated string allowedCapabilities = 4; - - // volumes is a white list of allowed volume plugins. Empty indicates that - // no volumes may be used. To allow all volumes you may use '*'. - // +optional - repeated string volumes = 5; - - // hostNetwork determines if the policy allows the use of HostNetwork in the pod spec. - // +optional - optional bool hostNetwork = 6; - - // hostPorts determines which host port ranges are allowed to be exposed. - // +optional - repeated HostPortRange hostPorts = 7; - - // hostPID determines if the policy allows the use of HostPID in the pod spec. - // +optional - optional bool hostPID = 8; - - // hostIPC determines if the policy allows the use of HostIPC in the pod spec. - // +optional - optional bool hostIPC = 9; - - // seLinux is the strategy that will dictate the allowable labels that may be set. - optional SELinuxStrategyOptions seLinux = 10; - - // runAsUser is the strategy that will dictate the allowable RunAsUser values that may be set. - optional RunAsUserStrategyOptions runAsUser = 11; - - // RunAsGroup is the strategy that will dictate the allowable RunAsGroup values that may be set. - // If this field is omitted, the pod's RunAsGroup can take any value. This field requires the - // RunAsGroup feature gate to be enabled. - // +optional - optional RunAsGroupStrategyOptions runAsGroup = 22; - - // supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. - optional SupplementalGroupsStrategyOptions supplementalGroups = 12; - - // fsGroup is the strategy that will dictate what fs group is used by the SecurityContext. - optional FSGroupStrategyOptions fsGroup = 13; - - // readOnlyRootFilesystem when set to true will force containers to run with a read only root file - // system. If the container specifically requests to run with a non-read only root file system - // the PSP should deny the pod. - // If set to false the container may run with a read only root file system if it wishes but it - // will not be forced to. - // +optional - optional bool readOnlyRootFilesystem = 14; - - // defaultAllowPrivilegeEscalation controls the default setting for whether a - // process can gain more privileges than its parent process. - // +optional - optional bool defaultAllowPrivilegeEscalation = 15; - - // allowPrivilegeEscalation determines if a pod can request to allow - // privilege escalation. If unspecified, defaults to true. - // +optional - optional bool allowPrivilegeEscalation = 16; - - // allowedHostPaths is a white list of allowed host paths. Empty indicates - // that all host paths may be used. - // +optional - repeated AllowedHostPath allowedHostPaths = 17; - - // allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all - // Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes - // is allowed in the "volumes" field. - // +optional - repeated AllowedFlexVolume allowedFlexVolumes = 18; - - // allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. - // Each entry is either a plain sysctl name or ends in "*" in which case it is considered - // as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. - // Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection. - // - // Examples: - // e.g. "foo/*" allows "foo/bar", "foo/baz", etc. - // e.g. "foo.*" allows "foo.bar", "foo.baz", etc. - // +optional - repeated string allowedUnsafeSysctls = 19; - - // forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. - // Each entry is either a plain sysctl name or ends in "*" in which case it is considered - // as a prefix of forbidden sysctls. Single * means all sysctls are forbidden. - // - // Examples: - // e.g. "foo/*" forbids "foo/bar", "foo/baz", etc. - // e.g. "foo.*" forbids "foo.bar", "foo.baz", etc. - // +optional - repeated string forbiddenSysctls = 20; - - // AllowedProcMountTypes is a whitelist of allowed ProcMountTypes. - // Empty or nil indicates that only the DefaultProcMountType may be used. - // This requires the ProcMountType feature flag to be enabled. - // +optional - repeated string allowedProcMountTypes = 21; -} - -// DEPRECATED - This group version of ReplicaSet is deprecated by apps/v1beta2/ReplicaSet. See the release notes for -// more information. -// ReplicaSet ensures that a specified number of pod replicas are running at any given time. -message ReplicaSet { - // If the Labels of a ReplicaSet are empty, they are defaulted to - // be the same as the Pod(s) that the ReplicaSet manages. - // Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Spec defines the specification of the desired behavior of the ReplicaSet. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional ReplicaSetSpec spec = 2; - - // Status is the most recently observed status of the ReplicaSet. - // This data may be out of date by some window of time. - // Populated by the system. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional ReplicaSetStatus status = 3; -} - -// ReplicaSetCondition describes the state of a replica set at a certain point. -message ReplicaSetCondition { - // Type of replica set condition. - optional string type = 1; - - // Status of the condition, one of True, False, Unknown. - optional string status = 2; - - // The last time the condition transitioned from one status to another. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 3; - - // The reason for the condition's last transition. - // +optional - optional string reason = 4; - - // A human readable message indicating details about the transition. - // +optional - optional string message = 5; -} - -// ReplicaSetList is a collection of ReplicaSets. -message ReplicaSetList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // List of ReplicaSets. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller - repeated ReplicaSet items = 2; -} - -// ReplicaSetSpec is the specification of a ReplicaSet. -message ReplicaSetSpec { - // Replicas is the number of desired replicas. - // This is a pointer to distinguish between explicit zero and unspecified. - // Defaults to 1. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller/#what-is-a-replicationcontroller - // +optional - optional int32 replicas = 1; - - // Minimum number of seconds for which a newly created pod should be ready - // without any of its container crashing, for it to be considered available. - // Defaults to 0 (pod will be considered available as soon as it is ready) - // +optional - optional int32 minReadySeconds = 4; - - // Selector is a label query over pods that should match the replica count. - // If the selector is empty, it is defaulted to the labels present on the pod template. - // Label keys and values that must match in order to be controlled by this replica set. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 2; - - // Template is the object that describes the pod that will be created if - // insufficient replicas are detected. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller#pod-template - // +optional - optional k8s.io.api.core.v1.PodTemplateSpec template = 3; -} - -// ReplicaSetStatus represents the current status of a ReplicaSet. -message ReplicaSetStatus { - // Replicas is the most recently oberved number of replicas. - // More info: https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller/#what-is-a-replicationcontroller - optional int32 replicas = 1; - - // The number of pods that have labels matching the labels of the pod template of the replicaset. - // +optional - optional int32 fullyLabeledReplicas = 2; - - // The number of ready replicas for this replica set. - // +optional - optional int32 readyReplicas = 4; - - // The number of available replicas (ready for at least minReadySeconds) for this replica set. - // +optional - optional int32 availableReplicas = 5; - - // ObservedGeneration reflects the generation of the most recently observed ReplicaSet. - // +optional - optional int64 observedGeneration = 3; - - // Represents the latest available observations of a replica set's current state. - // +optional - // +patchMergeKey=type - // +patchStrategy=merge - repeated ReplicaSetCondition conditions = 6; -} - -// Dummy definition -message ReplicationControllerDummy { -} - -// DEPRECATED. -message RollbackConfig { - // The revision to rollback to. If set to 0, rollback to the last revision. - // +optional - optional int64 revision = 1; -} - -// Spec to control the desired behavior of daemon set rolling update. -message RollingUpdateDaemonSet { - // The maximum number of DaemonSet pods that can be unavailable during the - // update. Value can be an absolute number (ex: 5) or a percentage of total - // number of DaemonSet pods at the start of the update (ex: 10%). Absolute - // number is calculated from percentage by rounding up. - // This cannot be 0. - // Default value is 1. - // Example: when this is set to 30%, at most 30% of the total number of nodes - // that should be running the daemon pod (i.e. status.desiredNumberScheduled) - // can have their pods stopped for an update at any given - // time. The update starts by stopping at most 30% of those DaemonSet pods - // and then brings up new DaemonSet pods in their place. Once the new pods - // are available, it then proceeds onto other DaemonSet pods, thus ensuring - // that at least 70% of original number of DaemonSet pods are available at - // all times during the update. - // +optional - optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxUnavailable = 1; -} - -// Spec to control the desired behavior of rolling update. -message RollingUpdateDeployment { - // The maximum number of pods that can be unavailable during the update. - // Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - // Absolute number is calculated from percentage by rounding down. - // This can not be 0 if MaxSurge is 0. - // By default, a fixed value of 1 is used. - // Example: when this is set to 30%, the old RC can be scaled down to 70% of desired pods - // immediately when the rolling update starts. Once new pods are ready, old RC - // can be scaled down further, followed by scaling up the new RC, ensuring - // that the total number of pods available at all times during the update is at - // least 70% of desired pods. - // +optional - optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxUnavailable = 1; - - // The maximum number of pods that can be scheduled above the desired number of - // pods. - // Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). - // This can not be 0 if MaxUnavailable is 0. - // Absolute number is calculated from percentage by rounding up. - // By default, a value of 1 is used. - // Example: when this is set to 30%, the new RC can be scaled up immediately when - // the rolling update starts, such that the total number of old and new pods do not exceed - // 130% of desired pods. Once old pods have been killed, - // new RC can be scaled up further, ensuring that total number of pods running - // at any time during the update is atmost 130% of desired pods. - // +optional - optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxSurge = 2; -} - -// RunAsGroupStrategyOptions defines the strategy type and any options used to create the strategy. -// Deprecated: use RunAsGroupStrategyOptions from policy API Group instead. -message RunAsGroupStrategyOptions { - // rule is the strategy that will dictate the allowable RunAsGroup values that may be set. - optional string rule = 1; - - // ranges are the allowed ranges of gids that may be used. If you would like to force a single gid - // then supply a single range with the same start and end. Required for MustRunAs. - // +optional - repeated IDRange ranges = 2; -} - -// RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. -// Deprecated: use RunAsUserStrategyOptions from policy API Group instead. -message RunAsUserStrategyOptions { - // rule is the strategy that will dictate the allowable RunAsUser values that may be set. - optional string rule = 1; - - // ranges are the allowed ranges of uids that may be used. If you would like to force a single uid - // then supply a single range with the same start and end. Required for MustRunAs. - // +optional - repeated IDRange ranges = 2; -} - -// SELinuxStrategyOptions defines the strategy type and any options used to create the strategy. -// Deprecated: use SELinuxStrategyOptions from policy API Group instead. -message SELinuxStrategyOptions { - // rule is the strategy that will dictate the allowable labels that may be set. - optional string rule = 1; - - // seLinuxOptions required to run as; required for MustRunAs - // More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - // +optional - optional k8s.io.api.core.v1.SELinuxOptions seLinuxOptions = 2; -} - -// represents a scaling request for a resource. -message Scale { - // Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // defines the behavior of the scale. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status. - // +optional - optional ScaleSpec spec = 2; - - // current status of the scale. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status. Read-only. - // +optional - optional ScaleStatus status = 3; -} - -// describes the attributes of a scale subresource -message ScaleSpec { - // desired number of instances for the scaled object. - // +optional - optional int32 replicas = 1; -} - -// represents the current status of a scale subresource. -message ScaleStatus { - // actual number of observed instances of the scaled object. - optional int32 replicas = 1; - - // label query over pods that should match the replicas count. More info: http://kubernetes.io/docs/user-guide/labels#label-selectors - // +optional - map selector = 2; - - // label selector for pods that should match the replicas count. This is a serializated - // version of both map-based and more expressive set-based selectors. This is done to - // avoid introspection in the clients. The string will be in the same format as the - // query-param syntax. If the target type only supports map-based selectors, both this - // field and map-based selector field are populated. - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors - // +optional - optional string targetSelector = 3; -} - -// SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy. -// Deprecated: use SupplementalGroupsStrategyOptions from policy API Group instead. -message SupplementalGroupsStrategyOptions { - // rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. - // +optional - optional string rule = 1; - - // ranges are the allowed ranges of supplemental groups. If you would like to force a single - // supplemental group then supply a single range with the same start and end. Required for MustRunAs. - // +optional - repeated IDRange ranges = 2; -} - diff --git a/vendor/k8s.io/api/networking/v1/generated.proto b/vendor/k8s.io/api/networking/v1/generated.proto deleted file mode 100644 index ab3731e9c3..0000000000 --- a/vendor/k8s.io/api/networking/v1/generated.proto +++ /dev/null @@ -1,195 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.networking.v1; - -import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1"; - -// IPBlock describes a particular CIDR (Ex. "192.168.1.1/24") that is allowed to the pods -// matched by a NetworkPolicySpec's podSelector. The except entry describes CIDRs that should -// not be included within this rule. -message IPBlock { - // CIDR is a string representing the IP Block - // Valid examples are "192.168.1.1/24" - optional string cidr = 1; - - // Except is a slice of CIDRs that should not be included within an IP Block - // Valid examples are "192.168.1.1/24" - // Except values will be rejected if they are outside the CIDR range - // +optional - repeated string except = 2; -} - -// NetworkPolicy describes what network traffic is allowed for a set of Pods -message NetworkPolicy { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Specification of the desired behavior for this NetworkPolicy. - // +optional - optional NetworkPolicySpec spec = 2; -} - -// NetworkPolicyEgressRule describes a particular set of traffic that is allowed out of pods -// matched by a NetworkPolicySpec's podSelector. The traffic must match both ports and to. -// This type is beta-level in 1.8 -message NetworkPolicyEgressRule { - // List of destination ports for outgoing traffic. - // Each item in this list is combined using a logical OR. If this field is - // empty or missing, this rule matches all ports (traffic not restricted by port). - // If this field is present and contains at least one item, then this rule allows - // traffic only if the traffic matches at least one port in the list. - // +optional - repeated NetworkPolicyPort ports = 1; - - // List of destinations for outgoing traffic of pods selected for this rule. - // Items in this list are combined using a logical OR operation. If this field is - // empty or missing, this rule matches all destinations (traffic not restricted by - // destination). If this field is present and contains at least one item, this rule - // allows traffic only if the traffic matches at least one item in the to list. - // +optional - repeated NetworkPolicyPeer to = 2; -} - -// NetworkPolicyIngressRule describes a particular set of traffic that is allowed to the pods -// matched by a NetworkPolicySpec's podSelector. The traffic must match both ports and from. -message NetworkPolicyIngressRule { - // List of ports which should be made accessible on the pods selected for this - // rule. Each item in this list is combined using a logical OR. If this field is - // empty or missing, this rule matches all ports (traffic not restricted by port). - // If this field is present and contains at least one item, then this rule allows - // traffic only if the traffic matches at least one port in the list. - // +optional - repeated NetworkPolicyPort ports = 1; - - // List of sources which should be able to access the pods selected for this rule. - // Items in this list are combined using a logical OR operation. If this field is - // empty or missing, this rule matches all sources (traffic not restricted by - // source). If this field is present and contains at least on item, this rule - // allows traffic only if the traffic matches at least one item in the from list. - // +optional - repeated NetworkPolicyPeer from = 2; -} - -// NetworkPolicyList is a list of NetworkPolicy objects. -message NetworkPolicyList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of schema objects. - repeated NetworkPolicy items = 2; -} - -// NetworkPolicyPeer describes a peer to allow traffic from. Only certain combinations of -// fields are allowed -message NetworkPolicyPeer { - // This is a label selector which selects Pods. This field follows standard label - // selector semantics; if present but empty, it selects all pods. - // - // If NamespaceSelector is also set, then the NetworkPolicyPeer as a whole selects - // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. - // Otherwise it selects the Pods matching PodSelector in the policy's own Namespace. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector podSelector = 1; - - // Selects Namespaces using cluster-scoped labels. This field follows standard label - // selector semantics; if present but empty, it selects all namespaces. - // - // If PodSelector is also set, then the NetworkPolicyPeer as a whole selects - // the Pods matching PodSelector in the Namespaces selected by NamespaceSelector. - // Otherwise it selects all Pods in the Namespaces selected by NamespaceSelector. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector namespaceSelector = 2; - - // IPBlock defines policy on a particular IPBlock. If this field is set then - // neither of the other fields can be. - // +optional - optional IPBlock ipBlock = 3; -} - -// NetworkPolicyPort describes a port to allow traffic on -message NetworkPolicyPort { - // The protocol (TCP, UDP, or SCTP) which traffic must match. If not specified, this - // field defaults to TCP. - // +optional - optional string protocol = 1; - - // The port on the given protocol. This can either be a numerical or named port on - // a pod. If this field is not provided, this matches all port names and numbers. - // +optional - optional k8s.io.apimachinery.pkg.util.intstr.IntOrString port = 2; -} - -// NetworkPolicySpec provides the specification of a NetworkPolicy -message NetworkPolicySpec { - // Selects the pods to which this NetworkPolicy object applies. The array of - // ingress rules is applied to any pods selected by this field. Multiple network - // policies can select the same set of pods. In this case, the ingress rules for - // each are combined additively. This field is NOT optional and follows standard - // label selector semantics. An empty podSelector matches all pods in this - // namespace. - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector podSelector = 1; - - // List of ingress rules to be applied to the selected pods. Traffic is allowed to - // a pod if there are no NetworkPolicies selecting the pod - // (and cluster policy otherwise allows the traffic), OR if the traffic source is - // the pod's local node, OR if the traffic matches at least one ingress rule - // across all of the NetworkPolicy objects whose podSelector matches the pod. If - // this field is empty then this NetworkPolicy does not allow any traffic (and serves - // solely to ensure that the pods it selects are isolated by default) - // +optional - repeated NetworkPolicyIngressRule ingress = 2; - - // List of egress rules to be applied to the selected pods. Outgoing traffic is - // allowed if there are no NetworkPolicies selecting the pod (and cluster policy - // otherwise allows the traffic), OR if the traffic matches at least one egress rule - // across all of the NetworkPolicy objects whose podSelector matches the pod. If - // this field is empty then this NetworkPolicy limits all outgoing traffic (and serves - // solely to ensure that the pods it selects are isolated by default). - // This field is beta-level in 1.8 - // +optional - repeated NetworkPolicyEgressRule egress = 3; - - // List of rule types that the NetworkPolicy relates to. - // Valid options are Ingress, Egress, or Ingress,Egress. - // If this field is not specified, it will default based on the existence of Ingress or Egress rules; - // policies that contain an Egress section are assumed to affect Egress, and all policies - // (whether or not they contain an Ingress section) are assumed to affect Ingress. - // If you want to write an egress-only policy, you must explicitly specify policyTypes [ "Egress" ]. - // Likewise, if you want to write a policy that specifies that no egress is allowed, - // you must specify a policyTypes value that include "Egress" (since such a policy would not include - // an Egress section and would otherwise default to just [ "Ingress" ]). - // This field is beta-level in 1.8 - // +optional - repeated string policyTypes = 4; -} - diff --git a/vendor/k8s.io/api/policy/v1beta1/generated.proto b/vendor/k8s.io/api/policy/v1beta1/generated.proto deleted file mode 100644 index e9df3c16fe..0000000000 --- a/vendor/k8s.io/api/policy/v1beta1/generated.proto +++ /dev/null @@ -1,367 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.policy.v1beta1; - -import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; -import "k8s.io/apimachinery/pkg/util/intstr/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1beta1"; - -// AllowedFlexVolume represents a single Flexvolume that is allowed to be used. -message AllowedFlexVolume { - // driver is the name of the Flexvolume driver. - optional string driver = 1; -} - -// AllowedHostPath defines the host volume conditions that will be enabled by a policy -// for pods to use. It requires the path prefix to be defined. -message AllowedHostPath { - // pathPrefix is the path prefix that the host volume must match. - // It does not support `*`. - // Trailing slashes are trimmed when validating the path prefix with a host path. - // - // Examples: - // `/foo` would allow `/foo`, `/foo/` and `/foo/bar` - // `/foo` would not allow `/food` or `/etc/foo` - optional string pathPrefix = 1; - - // when set to true, will allow host volumes matching the pathPrefix only if all volume mounts are readOnly. - // +optional - optional bool readOnly = 2; -} - -// Eviction evicts a pod from its node subject to certain policies and safety constraints. -// This is a subresource of Pod. A request to cause such an eviction is -// created by POSTing to .../pods//evictions. -message Eviction { - // ObjectMeta describes the pod that is being evicted. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // DeleteOptions may be provided - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.DeleteOptions deleteOptions = 2; -} - -// FSGroupStrategyOptions defines the strategy type and options used to create the strategy. -message FSGroupStrategyOptions { - // rule is the strategy that will dictate what FSGroup is used in the SecurityContext. - // +optional - optional string rule = 1; - - // ranges are the allowed ranges of fs groups. If you would like to force a single - // fs group then supply a single range with the same start and end. Required for MustRunAs. - // +optional - repeated IDRange ranges = 2; -} - -// HostPortRange defines a range of host ports that will be enabled by a policy -// for pods to use. It requires both the start and end to be defined. -message HostPortRange { - // min is the start of the range, inclusive. - optional int32 min = 1; - - // max is the end of the range, inclusive. - optional int32 max = 2; -} - -// IDRange provides a min/max of an allowed range of IDs. -message IDRange { - // min is the start of the range, inclusive. - optional int64 min = 1; - - // max is the end of the range, inclusive. - optional int64 max = 2; -} - -// PodDisruptionBudget is an object to define the max disruption that can be caused to a collection of pods -message PodDisruptionBudget { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Specification of the desired behavior of the PodDisruptionBudget. - // +optional - optional PodDisruptionBudgetSpec spec = 2; - - // Most recently observed status of the PodDisruptionBudget. - // +optional - optional PodDisruptionBudgetStatus status = 3; -} - -// PodDisruptionBudgetList is a collection of PodDisruptionBudgets. -message PodDisruptionBudgetList { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - repeated PodDisruptionBudget items = 2; -} - -// PodDisruptionBudgetSpec is a description of a PodDisruptionBudget. -message PodDisruptionBudgetSpec { - // An eviction is allowed if at least "minAvailable" pods selected by - // "selector" will still be available after the eviction, i.e. even in the - // absence of the evicted pod. So for example you can prevent all voluntary - // evictions by specifying "100%". - // +optional - optional k8s.io.apimachinery.pkg.util.intstr.IntOrString minAvailable = 1; - - // Label query over pods whose evictions are managed by the disruption - // budget. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 2; - - // An eviction is allowed if at most "maxUnavailable" pods selected by - // "selector" are unavailable after the eviction, i.e. even in absence of - // the evicted pod. For example, one can prevent all voluntary evictions - // by specifying 0. This is a mutually exclusive setting with "minAvailable". - // +optional - optional k8s.io.apimachinery.pkg.util.intstr.IntOrString maxUnavailable = 3; -} - -// PodDisruptionBudgetStatus represents information about the status of a -// PodDisruptionBudget. Status may trail the actual state of a system. -message PodDisruptionBudgetStatus { - // Most recent generation observed when updating this PDB status. PodDisruptionsAllowed and other - // status informatio is valid only if observedGeneration equals to PDB's object generation. - // +optional - optional int64 observedGeneration = 1; - - // DisruptedPods contains information about pods whose eviction was - // processed by the API server eviction subresource handler but has not - // yet been observed by the PodDisruptionBudget controller. - // A pod will be in this map from the time when the API server processed the - // eviction request to the time when the pod is seen by PDB controller - // as having been marked for deletion (or after a timeout). The key in the map is the name of the pod - // and the value is the time when the API server processed the eviction request. If - // the deletion didn't occur and a pod is still there it will be removed from - // the list automatically by PodDisruptionBudget controller after some time. - // If everything goes smooth this map should be empty for the most of the time. - // Large number of entries in the map may indicate problems with pod deletions. - // +optional - map disruptedPods = 2; - - // Number of pod disruptions that are currently allowed. - optional int32 disruptionsAllowed = 3; - - // current number of healthy pods - optional int32 currentHealthy = 4; - - // minimum desired number of healthy pods - optional int32 desiredHealthy = 5; - - // total number of pods counted by this disruption budget - optional int32 expectedPods = 6; -} - -// PodSecurityPolicy governs the ability to make requests that affect the Security Context -// that will be applied to a pod and container. -message PodSecurityPolicy { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // spec defines the policy enforced. - // +optional - optional PodSecurityPolicySpec spec = 2; -} - -// PodSecurityPolicyList is a list of PodSecurityPolicy objects. -message PodSecurityPolicyList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // items is a list of schema objects. - repeated PodSecurityPolicy items = 2; -} - -// PodSecurityPolicySpec defines the policy enforced. -message PodSecurityPolicySpec { - // privileged determines if a pod can request to be run as privileged. - // +optional - optional bool privileged = 1; - - // defaultAddCapabilities is the default set of capabilities that will be added to the container - // unless the pod spec specifically drops the capability. You may not list a capability in both - // defaultAddCapabilities and requiredDropCapabilities. Capabilities added here are implicitly - // allowed, and need not be included in the allowedCapabilities list. - // +optional - repeated string defaultAddCapabilities = 2; - - // requiredDropCapabilities are the capabilities that will be dropped from the container. These - // are required to be dropped and cannot be added. - // +optional - repeated string requiredDropCapabilities = 3; - - // allowedCapabilities is a list of capabilities that can be requested to add to the container. - // Capabilities in this field may be added at the pod author's discretion. - // You must not list a capability in both allowedCapabilities and requiredDropCapabilities. - // +optional - repeated string allowedCapabilities = 4; - - // volumes is a white list of allowed volume plugins. Empty indicates that - // no volumes may be used. To allow all volumes you may use '*'. - // +optional - repeated string volumes = 5; - - // hostNetwork determines if the policy allows the use of HostNetwork in the pod spec. - // +optional - optional bool hostNetwork = 6; - - // hostPorts determines which host port ranges are allowed to be exposed. - // +optional - repeated HostPortRange hostPorts = 7; - - // hostPID determines if the policy allows the use of HostPID in the pod spec. - // +optional - optional bool hostPID = 8; - - // hostIPC determines if the policy allows the use of HostIPC in the pod spec. - // +optional - optional bool hostIPC = 9; - - // seLinux is the strategy that will dictate the allowable labels that may be set. - optional SELinuxStrategyOptions seLinux = 10; - - // runAsUser is the strategy that will dictate the allowable RunAsUser values that may be set. - optional RunAsUserStrategyOptions runAsUser = 11; - - // RunAsGroup is the strategy that will dictate the allowable RunAsGroup values that may be set. - // If this field is omitted, the pod's RunAsGroup can take any value. This field requires the - // RunAsGroup feature gate to be enabled. - // +optional - optional RunAsGroupStrategyOptions runAsGroup = 22; - - // supplementalGroups is the strategy that will dictate what supplemental groups are used by the SecurityContext. - optional SupplementalGroupsStrategyOptions supplementalGroups = 12; - - // fsGroup is the strategy that will dictate what fs group is used by the SecurityContext. - optional FSGroupStrategyOptions fsGroup = 13; - - // readOnlyRootFilesystem when set to true will force containers to run with a read only root file - // system. If the container specifically requests to run with a non-read only root file system - // the PSP should deny the pod. - // If set to false the container may run with a read only root file system if it wishes but it - // will not be forced to. - // +optional - optional bool readOnlyRootFilesystem = 14; - - // defaultAllowPrivilegeEscalation controls the default setting for whether a - // process can gain more privileges than its parent process. - // +optional - optional bool defaultAllowPrivilegeEscalation = 15; - - // allowPrivilegeEscalation determines if a pod can request to allow - // privilege escalation. If unspecified, defaults to true. - // +optional - optional bool allowPrivilegeEscalation = 16; - - // allowedHostPaths is a white list of allowed host paths. Empty indicates - // that all host paths may be used. - // +optional - repeated AllowedHostPath allowedHostPaths = 17; - - // allowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all - // Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes - // is allowed in the "volumes" field. - // +optional - repeated AllowedFlexVolume allowedFlexVolumes = 18; - - // allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none. - // Each entry is either a plain sysctl name or ends in "*" in which case it is considered - // as a prefix of allowed sysctls. Single * means all unsafe sysctls are allowed. - // Kubelet has to whitelist all allowed unsafe sysctls explicitly to avoid rejection. - // - // Examples: - // e.g. "foo/*" allows "foo/bar", "foo/baz", etc. - // e.g. "foo.*" allows "foo.bar", "foo.baz", etc. - // +optional - repeated string allowedUnsafeSysctls = 19; - - // forbiddenSysctls is a list of explicitly forbidden sysctls, defaults to none. - // Each entry is either a plain sysctl name or ends in "*" in which case it is considered - // as a prefix of forbidden sysctls. Single * means all sysctls are forbidden. - // - // Examples: - // e.g. "foo/*" forbids "foo/bar", "foo/baz", etc. - // e.g. "foo.*" forbids "foo.bar", "foo.baz", etc. - // +optional - repeated string forbiddenSysctls = 20; - - // AllowedProcMountTypes is a whitelist of allowed ProcMountTypes. - // Empty or nil indicates that only the DefaultProcMountType may be used. - // This requires the ProcMountType feature flag to be enabled. - // +optional - repeated string allowedProcMountTypes = 21; -} - -// RunAsGroupStrategyOptions defines the strategy type and any options used to create the strategy. -message RunAsGroupStrategyOptions { - // rule is the strategy that will dictate the allowable RunAsGroup values that may be set. - optional string rule = 1; - - // ranges are the allowed ranges of gids that may be used. If you would like to force a single gid - // then supply a single range with the same start and end. Required for MustRunAs. - // +optional - repeated IDRange ranges = 2; -} - -// RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy. -message RunAsUserStrategyOptions { - // rule is the strategy that will dictate the allowable RunAsUser values that may be set. - optional string rule = 1; - - // ranges are the allowed ranges of uids that may be used. If you would like to force a single uid - // then supply a single range with the same start and end. Required for MustRunAs. - // +optional - repeated IDRange ranges = 2; -} - -// SELinuxStrategyOptions defines the strategy type and any options used to create the strategy. -message SELinuxStrategyOptions { - // rule is the strategy that will dictate the allowable labels that may be set. - optional string rule = 1; - - // seLinuxOptions required to run as; required for MustRunAs - // More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - // +optional - optional k8s.io.api.core.v1.SELinuxOptions seLinuxOptions = 2; -} - -// SupplementalGroupsStrategyOptions defines the strategy type and options used to create the strategy. -message SupplementalGroupsStrategyOptions { - // rule is the strategy that will dictate what supplemental groups is used in the SecurityContext. - // +optional - optional string rule = 1; - - // ranges are the allowed ranges of supplemental groups. If you would like to force a single - // supplemental group then supply a single range with the same start and end. Required for MustRunAs. - // +optional - repeated IDRange ranges = 2; -} - diff --git a/vendor/k8s.io/api/rbac/v1/generated.proto b/vendor/k8s.io/api/rbac/v1/generated.proto deleted file mode 100644 index 4b321a7c24..0000000000 --- a/vendor/k8s.io/api/rbac/v1/generated.proto +++ /dev/null @@ -1,197 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.rbac.v1; - -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1"; - -// AggregationRule describes how to locate ClusterRoles to aggregate into the ClusterRole -message AggregationRule { - // ClusterRoleSelectors holds a list of selectors which will be used to find ClusterRoles and create the rules. - // If any of the selectors match, then the ClusterRole's permissions will be added - // +optional - repeated k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector clusterRoleSelectors = 1; -} - -// ClusterRole is a cluster level, logical grouping of PolicyRules that can be referenced as a unit by a RoleBinding or ClusterRoleBinding. -message ClusterRole { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Rules holds all the PolicyRules for this ClusterRole - repeated PolicyRule rules = 2; - - // AggregationRule is an optional field that describes how to build the Rules for this ClusterRole. - // If AggregationRule is set, then the Rules are controller managed and direct changes to Rules will be - // stomped by the controller. - // +optional - optional AggregationRule aggregationRule = 3; -} - -// ClusterRoleBinding references a ClusterRole, but not contain it. It can reference a ClusterRole in the global namespace, -// and adds who information via Subject. -message ClusterRoleBinding { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Subjects holds references to the objects the role applies to. - // +optional - repeated Subject subjects = 2; - - // RoleRef can only reference a ClusterRole in the global namespace. - // If the RoleRef cannot be resolved, the Authorizer must return an error. - optional RoleRef roleRef = 3; -} - -// ClusterRoleBindingList is a collection of ClusterRoleBindings -message ClusterRoleBindingList { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of ClusterRoleBindings - repeated ClusterRoleBinding items = 2; -} - -// ClusterRoleList is a collection of ClusterRoles -message ClusterRoleList { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of ClusterRoles - repeated ClusterRole items = 2; -} - -// PolicyRule holds information that describes a policy rule, but does not contain information -// about who the rule applies to or which namespace the rule applies to. -message PolicyRule { - // Verbs is a list of Verbs that apply to ALL the ResourceKinds and AttributeRestrictions contained in this rule. VerbAll represents all kinds. - repeated string verbs = 1; - - // APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of - // the enumerated resources in any API group will be allowed. - // +optional - repeated string apiGroups = 2; - - // Resources is a list of resources this rule applies to. ResourceAll represents all resources. - // +optional - repeated string resources = 3; - - // ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. - // +optional - repeated string resourceNames = 4; - - // NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path - // Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding. - // Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"), but not both. - // +optional - repeated string nonResourceURLs = 5; -} - -// Role is a namespaced, logical grouping of PolicyRules that can be referenced as a unit by a RoleBinding. -message Role { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Rules holds all the PolicyRules for this Role - repeated PolicyRule rules = 2; -} - -// RoleBinding references a role, but does not contain it. It can reference a Role in the same namespace or a ClusterRole in the global namespace. -// It adds who information via Subjects and namespace information by which namespace it exists in. RoleBindings in a given -// namespace only have effect in that namespace. -message RoleBinding { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Subjects holds references to the objects the role applies to. - // +optional - repeated Subject subjects = 2; - - // RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. - // If the RoleRef cannot be resolved, the Authorizer must return an error. - optional RoleRef roleRef = 3; -} - -// RoleBindingList is a collection of RoleBindings -message RoleBindingList { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of RoleBindings - repeated RoleBinding items = 2; -} - -// RoleList is a collection of Roles -message RoleList { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of Roles - repeated Role items = 2; -} - -// RoleRef contains information that points to the role being used -message RoleRef { - // APIGroup is the group for the resource being referenced - optional string apiGroup = 1; - - // Kind is the type of resource being referenced - optional string kind = 2; - - // Name is the name of resource being referenced - optional string name = 3; -} - -// Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, -// or a value for non-objects such as user and group names. -message Subject { - // Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - // If the Authorizer does not recognized the kind value, the Authorizer should report an error. - optional string kind = 1; - - // APIGroup holds the API group of the referenced subject. - // Defaults to "" for ServiceAccount subjects. - // Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - // +optional - optional string apiGroup = 2; - - // Name of the object being referenced. - optional string name = 3; - - // Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - // the Authorizer should report an error. - // +optional - optional string namespace = 4; -} - diff --git a/vendor/k8s.io/api/rbac/v1alpha1/generated.proto b/vendor/k8s.io/api/rbac/v1alpha1/generated.proto deleted file mode 100644 index cde3aaac98..0000000000 --- a/vendor/k8s.io/api/rbac/v1alpha1/generated.proto +++ /dev/null @@ -1,199 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.rbac.v1alpha1; - -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1alpha1"; - -// AggregationRule describes how to locate ClusterRoles to aggregate into the ClusterRole -message AggregationRule { - // ClusterRoleSelectors holds a list of selectors which will be used to find ClusterRoles and create the rules. - // If any of the selectors match, then the ClusterRole's permissions will be added - // +optional - repeated k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector clusterRoleSelectors = 1; -} - -// ClusterRole is a cluster level, logical grouping of PolicyRules that can be referenced as a unit by a RoleBinding or ClusterRoleBinding. -message ClusterRole { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Rules holds all the PolicyRules for this ClusterRole - repeated PolicyRule rules = 2; - - // AggregationRule is an optional field that describes how to build the Rules for this ClusterRole. - // If AggregationRule is set, then the Rules are controller managed and direct changes to Rules will be - // stomped by the controller. - // +optional - optional AggregationRule aggregationRule = 3; -} - -// ClusterRoleBinding references a ClusterRole, but not contain it. It can reference a ClusterRole in the global namespace, -// and adds who information via Subject. -message ClusterRoleBinding { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Subjects holds references to the objects the role applies to. - // +optional - repeated Subject subjects = 2; - - // RoleRef can only reference a ClusterRole in the global namespace. - // If the RoleRef cannot be resolved, the Authorizer must return an error. - optional RoleRef roleRef = 3; -} - -// ClusterRoleBindingList is a collection of ClusterRoleBindings -message ClusterRoleBindingList { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of ClusterRoleBindings - repeated ClusterRoleBinding items = 2; -} - -// ClusterRoleList is a collection of ClusterRoles -message ClusterRoleList { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of ClusterRoles - repeated ClusterRole items = 2; -} - -// PolicyRule holds information that describes a policy rule, but does not contain information -// about who the rule applies to or which namespace the rule applies to. -message PolicyRule { - // Verbs is a list of Verbs that apply to ALL the ResourceKinds and AttributeRestrictions contained in this rule. VerbAll represents all kinds. - repeated string verbs = 1; - - // APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of - // the enumerated resources in any API group will be allowed. - // +optional - repeated string apiGroups = 3; - - // Resources is a list of resources this rule applies to. ResourceAll represents all resources. - // +optional - repeated string resources = 4; - - // ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. - // +optional - repeated string resourceNames = 5; - - // NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path - // This name is intentionally different than the internal type so that the DefaultConvert works nicely and because the ordering may be different. - // Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding. - // Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"), but not both. - // +optional - repeated string nonResourceURLs = 6; -} - -// Role is a namespaced, logical grouping of PolicyRules that can be referenced as a unit by a RoleBinding. -message Role { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Rules holds all the PolicyRules for this Role - repeated PolicyRule rules = 2; -} - -// RoleBinding references a role, but does not contain it. It can reference a Role in the same namespace or a ClusterRole in the global namespace. -// It adds who information via Subjects and namespace information by which namespace it exists in. RoleBindings in a given -// namespace only have effect in that namespace. -message RoleBinding { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Subjects holds references to the objects the role applies to. - // +optional - repeated Subject subjects = 2; - - // RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. - // If the RoleRef cannot be resolved, the Authorizer must return an error. - optional RoleRef roleRef = 3; -} - -// RoleBindingList is a collection of RoleBindings -message RoleBindingList { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of RoleBindings - repeated RoleBinding items = 2; -} - -// RoleList is a collection of Roles -message RoleList { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of Roles - repeated Role items = 2; -} - -// RoleRef contains information that points to the role being used -message RoleRef { - // APIGroup is the group for the resource being referenced - optional string apiGroup = 1; - - // Kind is the type of resource being referenced - optional string kind = 2; - - // Name is the name of resource being referenced - optional string name = 3; -} - -// Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, -// or a value for non-objects such as user and group names. -message Subject { - // Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - // If the Authorizer does not recognized the kind value, the Authorizer should report an error. - optional string kind = 1; - - // APIVersion holds the API group and version of the referenced subject. - // Defaults to "v1" for ServiceAccount subjects. - // Defaults to "rbac.authorization.k8s.io/v1alpha1" for User and Group subjects. - // +k8s:conversion-gen=false - // +optional - optional string apiVersion = 2; - - // Name of the object being referenced. - optional string name = 3; - - // Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - // the Authorizer should report an error. - // +optional - optional string namespace = 4; -} - diff --git a/vendor/k8s.io/api/rbac/v1beta1/generated.proto b/vendor/k8s.io/api/rbac/v1beta1/generated.proto deleted file mode 100644 index 27bd30ce9f..0000000000 --- a/vendor/k8s.io/api/rbac/v1beta1/generated.proto +++ /dev/null @@ -1,198 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.rbac.v1beta1; - -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1beta1"; - -// AggregationRule describes how to locate ClusterRoles to aggregate into the ClusterRole -message AggregationRule { - // ClusterRoleSelectors holds a list of selectors which will be used to find ClusterRoles and create the rules. - // If any of the selectors match, then the ClusterRole's permissions will be added - // +optional - repeated k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector clusterRoleSelectors = 1; -} - -// ClusterRole is a cluster level, logical grouping of PolicyRules that can be referenced as a unit by a RoleBinding or ClusterRoleBinding. -message ClusterRole { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Rules holds all the PolicyRules for this ClusterRole - repeated PolicyRule rules = 2; - - // AggregationRule is an optional field that describes how to build the Rules for this ClusterRole. - // If AggregationRule is set, then the Rules are controller managed and direct changes to Rules will be - // stomped by the controller. - // +optional - optional AggregationRule aggregationRule = 3; -} - -// ClusterRoleBinding references a ClusterRole, but not contain it. It can reference a ClusterRole in the global namespace, -// and adds who information via Subject. -message ClusterRoleBinding { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Subjects holds references to the objects the role applies to. - // +optional - repeated Subject subjects = 2; - - // RoleRef can only reference a ClusterRole in the global namespace. - // If the RoleRef cannot be resolved, the Authorizer must return an error. - optional RoleRef roleRef = 3; -} - -// ClusterRoleBindingList is a collection of ClusterRoleBindings -message ClusterRoleBindingList { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of ClusterRoleBindings - repeated ClusterRoleBinding items = 2; -} - -// ClusterRoleList is a collection of ClusterRoles -message ClusterRoleList { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of ClusterRoles - repeated ClusterRole items = 2; -} - -// PolicyRule holds information that describes a policy rule, but does not contain information -// about who the rule applies to or which namespace the rule applies to. -message PolicyRule { - // Verbs is a list of Verbs that apply to ALL the ResourceKinds and AttributeRestrictions contained in this rule. VerbAll represents all kinds. - repeated string verbs = 1; - - // APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of - // the enumerated resources in any API group will be allowed. - // +optional - repeated string apiGroups = 2; - - // Resources is a list of resources this rule applies to. '*' represents all resources in the specified apiGroups. - // '*/foo' represents the subresource 'foo' for all resources in the specified apiGroups. - // +optional - repeated string resources = 3; - - // ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. - // +optional - repeated string resourceNames = 4; - - // NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path - // Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding. - // Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"), but not both. - // +optional - repeated string nonResourceURLs = 5; -} - -// Role is a namespaced, logical grouping of PolicyRules that can be referenced as a unit by a RoleBinding. -message Role { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Rules holds all the PolicyRules for this Role - repeated PolicyRule rules = 2; -} - -// RoleBinding references a role, but does not contain it. It can reference a Role in the same namespace or a ClusterRole in the global namespace. -// It adds who information via Subjects and namespace information by which namespace it exists in. RoleBindings in a given -// namespace only have effect in that namespace. -message RoleBinding { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Subjects holds references to the objects the role applies to. - // +optional - repeated Subject subjects = 2; - - // RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. - // If the RoleRef cannot be resolved, the Authorizer must return an error. - optional RoleRef roleRef = 3; -} - -// RoleBindingList is a collection of RoleBindings -message RoleBindingList { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of RoleBindings - repeated RoleBinding items = 2; -} - -// RoleList is a collection of Roles -message RoleList { - // Standard object's metadata. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of Roles - repeated Role items = 2; -} - -// RoleRef contains information that points to the role being used -message RoleRef { - // APIGroup is the group for the resource being referenced - optional string apiGroup = 1; - - // Kind is the type of resource being referenced - optional string kind = 2; - - // Name is the name of resource being referenced - optional string name = 3; -} - -// Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, -// or a value for non-objects such as user and group names. -message Subject { - // Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". - // If the Authorizer does not recognized the kind value, the Authorizer should report an error. - optional string kind = 1; - - // APIGroup holds the API group of the referenced subject. - // Defaults to "" for ServiceAccount subjects. - // Defaults to "rbac.authorization.k8s.io" for User and Group subjects. - // +optional - optional string apiGroup = 2; - - // Name of the object being referenced. - optional string name = 3; - - // Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty - // the Authorizer should report an error. - // +optional - optional string namespace = 4; -} - diff --git a/vendor/k8s.io/api/scheduling/v1alpha1/generated.proto b/vendor/k8s.io/api/scheduling/v1alpha1/generated.proto deleted file mode 100644 index 5fb5472116..0000000000 --- a/vendor/k8s.io/api/scheduling/v1alpha1/generated.proto +++ /dev/null @@ -1,67 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.scheduling.v1alpha1; - -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1alpha1"; - -// PriorityClass defines mapping from a priority class name to the priority -// integer value. The value can be any valid integer. -message PriorityClass { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // The value of this priority class. This is the actual priority that pods - // receive when they have the name of this class in their pod spec. - optional int32 value = 2; - - // globalDefault specifies whether this PriorityClass should be considered as - // the default priority for pods that do not have any priority class. - // Only one PriorityClass can be marked as `globalDefault`. However, if more than - // one PriorityClasses exists with their `globalDefault` field set to true, - // the smallest value of such global default PriorityClasses will be used as the default priority. - // +optional - optional bool globalDefault = 3; - - // description is an arbitrary string that usually provides guidelines on - // when this priority class should be used. - // +optional - optional string description = 4; -} - -// PriorityClassList is a collection of priority classes. -message PriorityClassList { - // Standard list metadata - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // items is the list of PriorityClasses - repeated PriorityClass items = 2; -} - diff --git a/vendor/k8s.io/api/scheduling/v1beta1/generated.proto b/vendor/k8s.io/api/scheduling/v1beta1/generated.proto deleted file mode 100644 index 0a95755032..0000000000 --- a/vendor/k8s.io/api/scheduling/v1beta1/generated.proto +++ /dev/null @@ -1,67 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.scheduling.v1beta1; - -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1beta1"; - -// PriorityClass defines mapping from a priority class name to the priority -// integer value. The value can be any valid integer. -message PriorityClass { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // The value of this priority class. This is the actual priority that pods - // receive when they have the name of this class in their pod spec. - optional int32 value = 2; - - // globalDefault specifies whether this PriorityClass should be considered as - // the default priority for pods that do not have any priority class. - // Only one PriorityClass can be marked as `globalDefault`. However, if more than - // one PriorityClasses exists with their `globalDefault` field set to true, - // the smallest value of such global default PriorityClasses will be used as the default priority. - // +optional - optional bool globalDefault = 3; - - // description is an arbitrary string that usually provides guidelines on - // when this priority class should be used. - // +optional - optional string description = 4; -} - -// PriorityClassList is a collection of priority classes. -message PriorityClassList { - // Standard list metadata - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // items is the list of PriorityClasses - repeated PriorityClass items = 2; -} - diff --git a/vendor/k8s.io/api/settings/v1alpha1/generated.proto b/vendor/k8s.io/api/settings/v1alpha1/generated.proto deleted file mode 100644 index d5534c4de9..0000000000 --- a/vendor/k8s.io/api/settings/v1alpha1/generated.proto +++ /dev/null @@ -1,75 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.settings.v1alpha1; - -import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1alpha1"; - -// PodPreset is a policy resource that defines additional runtime -// requirements for a Pod. -message PodPreset { - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // +optional - optional PodPresetSpec spec = 2; -} - -// PodPresetList is a list of PodPreset objects. -message PodPresetList { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is a list of schema objects. - repeated PodPreset items = 2; -} - -// PodPresetSpec is a description of a pod preset. -message PodPresetSpec { - // Selector is a label query over a set of resources, in this case pods. - // Required. - optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 1; - - // Env defines the collection of EnvVar to inject into containers. - // +optional - repeated k8s.io.api.core.v1.EnvVar env = 2; - - // EnvFrom defines the collection of EnvFromSource to inject into containers. - // +optional - repeated k8s.io.api.core.v1.EnvFromSource envFrom = 3; - - // Volumes defines the collection of Volume to inject into the pod. - // +optional - repeated k8s.io.api.core.v1.Volume volumes = 4; - - // VolumeMounts defines the collection of VolumeMount to inject into containers. - // +optional - repeated k8s.io.api.core.v1.VolumeMount volumeMounts = 5; -} - diff --git a/vendor/k8s.io/api/storage/v1/generated.proto b/vendor/k8s.io/api/storage/v1/generated.proto deleted file mode 100644 index 1b8102c053..0000000000 --- a/vendor/k8s.io/api/storage/v1/generated.proto +++ /dev/null @@ -1,90 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.storage.v1; - -import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1"; - -// StorageClass describes the parameters for a class of storage for -// which PersistentVolumes can be dynamically provisioned. -// -// StorageClasses are non-namespaced; the name of the storage class -// according to etcd is in ObjectMeta.Name. -message StorageClass { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Provisioner indicates the type of the provisioner. - optional string provisioner = 2; - - // Parameters holds the parameters for the provisioner that should - // create volumes of this storage class. - // +optional - map parameters = 3; - - // Dynamically provisioned PersistentVolumes of this storage class are - // created with this reclaimPolicy. Defaults to Delete. - // +optional - optional string reclaimPolicy = 4; - - // Dynamically provisioned PersistentVolumes of this storage class are - // created with these mountOptions, e.g. ["ro", "soft"]. Not validated - - // mount of the PVs will simply fail if one is invalid. - // +optional - repeated string mountOptions = 5; - - // AllowVolumeExpansion shows whether the storage class allow volume expand - // +optional - optional bool allowVolumeExpansion = 6; - - // VolumeBindingMode indicates how PersistentVolumeClaims should be - // provisioned and bound. When unset, VolumeBindingImmediate is used. - // This field is only honored by servers that enable the VolumeScheduling feature. - // +optional - optional string volumeBindingMode = 7; - - // Restrict the node topologies where volumes can be dynamically provisioned. - // Each volume plugin defines its own supported topology specifications. - // An empty TopologySelectorTerm list means there is no topology restriction. - // This field is only honored by servers that enable the VolumeScheduling feature. - // +optional - repeated k8s.io.api.core.v1.TopologySelectorTerm allowedTopologies = 8; -} - -// StorageClassList is a collection of storage classes. -message StorageClassList { - // Standard list metadata - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is the list of StorageClasses - repeated StorageClass items = 2; -} - diff --git a/vendor/k8s.io/api/storage/v1alpha1/generated.proto b/vendor/k8s.io/api/storage/v1alpha1/generated.proto deleted file mode 100644 index fdc4ad257d..0000000000 --- a/vendor/k8s.io/api/storage/v1alpha1/generated.proto +++ /dev/null @@ -1,126 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.storage.v1alpha1; - -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1alpha1"; - -// VolumeAttachment captures the intent to attach or detach the specified volume -// to/from the specified node. -// -// VolumeAttachment objects are non-namespaced. -message VolumeAttachment { - // Standard object metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Specification of the desired attach/detach volume behavior. - // Populated by the Kubernetes system. - optional VolumeAttachmentSpec spec = 2; - - // Status of the VolumeAttachment request. - // Populated by the entity completing the attach or detach - // operation, i.e. the external-attacher. - // +optional - optional VolumeAttachmentStatus status = 3; -} - -// VolumeAttachmentList is a collection of VolumeAttachment objects. -message VolumeAttachmentList { - // Standard list metadata - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is the list of VolumeAttachments - repeated VolumeAttachment items = 2; -} - -// VolumeAttachmentSource represents a volume that should be attached. -// Right now only PersistenVolumes can be attached via external attacher, -// in future we may allow also inline volumes in pods. -// Exactly one member can be set. -message VolumeAttachmentSource { - // Name of the persistent volume to attach. - // +optional - optional string persistentVolumeName = 1; -} - -// VolumeAttachmentSpec is the specification of a VolumeAttachment request. -message VolumeAttachmentSpec { - // Attacher indicates the name of the volume driver that MUST handle this - // request. This is the name returned by GetPluginName(). - optional string attacher = 1; - - // Source represents the volume that should be attached. - optional VolumeAttachmentSource source = 2; - - // The node that the volume should be attached to. - optional string nodeName = 3; -} - -// VolumeAttachmentStatus is the status of a VolumeAttachment request. -message VolumeAttachmentStatus { - // Indicates the volume is successfully attached. - // This field must only be set by the entity completing the attach - // operation, i.e. the external-attacher. - optional bool attached = 1; - - // Upon successful attach, this field is populated with any - // information returned by the attach operation that must be passed - // into subsequent WaitForAttach or Mount calls. - // This field must only be set by the entity completing the attach - // operation, i.e. the external-attacher. - // +optional - map attachmentMetadata = 2; - - // The last error encountered during attach operation, if any. - // This field must only be set by the entity completing the attach - // operation, i.e. the external-attacher. - // +optional - optional VolumeError attachError = 3; - - // The last error encountered during detach operation, if any. - // This field must only be set by the entity completing the detach - // operation, i.e. the external-attacher. - // +optional - optional VolumeError detachError = 4; -} - -// VolumeError captures an error encountered during a volume operation. -message VolumeError { - // Time the error was encountered. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time time = 1; - - // String detailing the error encountered during Attach or Detach operation. - // This string maybe logged, so it should not contain sensitive - // information. - // +optional - optional string message = 2; -} - diff --git a/vendor/k8s.io/api/storage/v1beta1/generated.proto b/vendor/k8s.io/api/storage/v1beta1/generated.proto deleted file mode 100644 index db1f302a05..0000000000 --- a/vendor/k8s.io/api/storage/v1beta1/generated.proto +++ /dev/null @@ -1,186 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.api.storage.v1beta1; - -import "k8s.io/api/core/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1beta1"; - -// StorageClass describes the parameters for a class of storage for -// which PersistentVolumes can be dynamically provisioned. -// -// StorageClasses are non-namespaced; the name of the storage class -// according to etcd is in ObjectMeta.Name. -message StorageClass { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Provisioner indicates the type of the provisioner. - optional string provisioner = 2; - - // Parameters holds the parameters for the provisioner that should - // create volumes of this storage class. - // +optional - map parameters = 3; - - // Dynamically provisioned PersistentVolumes of this storage class are - // created with this reclaimPolicy. Defaults to Delete. - // +optional - optional string reclaimPolicy = 4; - - // Dynamically provisioned PersistentVolumes of this storage class are - // created with these mountOptions, e.g. ["ro", "soft"]. Not validated - - // mount of the PVs will simply fail if one is invalid. - // +optional - repeated string mountOptions = 5; - - // AllowVolumeExpansion shows whether the storage class allow volume expand - // +optional - optional bool allowVolumeExpansion = 6; - - // VolumeBindingMode indicates how PersistentVolumeClaims should be - // provisioned and bound. When unset, VolumeBindingImmediate is used. - // This field is only honored by servers that enable the VolumeScheduling feature. - // +optional - optional string volumeBindingMode = 7; - - // Restrict the node topologies where volumes can be dynamically provisioned. - // Each volume plugin defines its own supported topology specifications. - // An empty TopologySelectorTerm list means there is no topology restriction. - // This field is only honored by servers that enable the VolumeScheduling feature. - // +optional - repeated k8s.io.api.core.v1.TopologySelectorTerm allowedTopologies = 8; -} - -// StorageClassList is a collection of storage classes. -message StorageClassList { - // Standard list metadata - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is the list of StorageClasses - repeated StorageClass items = 2; -} - -// VolumeAttachment captures the intent to attach or detach the specified volume -// to/from the specified node. -// -// VolumeAttachment objects are non-namespaced. -message VolumeAttachment { - // Standard object metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; - - // Specification of the desired attach/detach volume behavior. - // Populated by the Kubernetes system. - optional VolumeAttachmentSpec spec = 2; - - // Status of the VolumeAttachment request. - // Populated by the entity completing the attach or detach - // operation, i.e. the external-attacher. - // +optional - optional VolumeAttachmentStatus status = 3; -} - -// VolumeAttachmentList is a collection of VolumeAttachment objects. -message VolumeAttachmentList { - // Standard list metadata - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; - - // Items is the list of VolumeAttachments - repeated VolumeAttachment items = 2; -} - -// VolumeAttachmentSource represents a volume that should be attached. -// Right now only PersistenVolumes can be attached via external attacher, -// in future we may allow also inline volumes in pods. -// Exactly one member can be set. -message VolumeAttachmentSource { - // Name of the persistent volume to attach. - // +optional - optional string persistentVolumeName = 1; -} - -// VolumeAttachmentSpec is the specification of a VolumeAttachment request. -message VolumeAttachmentSpec { - // Attacher indicates the name of the volume driver that MUST handle this - // request. This is the name returned by GetPluginName(). - optional string attacher = 1; - - // Source represents the volume that should be attached. - optional VolumeAttachmentSource source = 2; - - // The node that the volume should be attached to. - optional string nodeName = 3; -} - -// VolumeAttachmentStatus is the status of a VolumeAttachment request. -message VolumeAttachmentStatus { - // Indicates the volume is successfully attached. - // This field must only be set by the entity completing the attach - // operation, i.e. the external-attacher. - optional bool attached = 1; - - // Upon successful attach, this field is populated with any - // information returned by the attach operation that must be passed - // into subsequent WaitForAttach or Mount calls. - // This field must only be set by the entity completing the attach - // operation, i.e. the external-attacher. - // +optional - map attachmentMetadata = 2; - - // The last error encountered during attach operation, if any. - // This field must only be set by the entity completing the attach - // operation, i.e. the external-attacher. - // +optional - optional VolumeError attachError = 3; - - // The last error encountered during detach operation, if any. - // This field must only be set by the entity completing the detach - // operation, i.e. the external-attacher. - // +optional - optional VolumeError detachError = 4; -} - -// VolumeError captures an error encountered during a volume operation. -message VolumeError { - // Time the error was encountered. - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.Time time = 1; - - // String detailing the error encountered during Attach or Detach operation. - // This string maybe logged, so it should not contain sensitive - // information. - // +optional - optional string message = 2; -} - diff --git a/vendor/k8s.io/apimachinery/pkg/api/errors/OWNERS b/vendor/k8s.io/apimachinery/pkg/api/errors/OWNERS deleted file mode 100755 index dc6a4c7242..0000000000 --- a/vendor/k8s.io/apimachinery/pkg/api/errors/OWNERS +++ /dev/null @@ -1,24 +0,0 @@ -reviewers: -- thockin -- lavalamp -- smarterclayton -- wojtek-t -- deads2k -- brendandburns -- derekwaynecarr -- caesarxuchao -- mikedanese -- liggitt -- nikhiljindal -- gmarek -- erictune -- saad-ali -- janetkuo -- tallclair -- eparis -- dims -- hongchaodeng -- krousey -- cjcullen -- david-mcmahon -- goltermann diff --git a/vendor/k8s.io/apimachinery/pkg/api/meta/OWNERS b/vendor/k8s.io/apimachinery/pkg/api/meta/OWNERS deleted file mode 100755 index 5f729ffe63..0000000000 --- a/vendor/k8s.io/apimachinery/pkg/api/meta/OWNERS +++ /dev/null @@ -1,25 +0,0 @@ -reviewers: -- thockin -- smarterclayton -- wojtek-t -- deads2k -- brendandburns -- derekwaynecarr -- caesarxuchao -- mikedanese -- liggitt -- nikhiljindal -- gmarek -- janetkuo -- ncdc -- eparis -- dims -- krousey -- markturansky -- fabioy -- resouer -- david-mcmahon -- mfojtik -- jianhuiz -- feihujiang -- ghodss diff --git a/vendor/k8s.io/apimachinery/pkg/api/resource/OWNERS b/vendor/k8s.io/apimachinery/pkg/api/resource/OWNERS deleted file mode 100755 index c430067f35..0000000000 --- a/vendor/k8s.io/apimachinery/pkg/api/resource/OWNERS +++ /dev/null @@ -1,16 +0,0 @@ -reviewers: -- thockin -- lavalamp -- smarterclayton -- wojtek-t -- derekwaynecarr -- mikedanese -- saad-ali -- janetkuo -- tallclair -- eparis -- jbeda -- xiang90 -- mbohlool -- david-mcmahon -- goltermann diff --git a/vendor/k8s.io/apimachinery/pkg/api/resource/generated.proto b/vendor/k8s.io/apimachinery/pkg/api/resource/generated.proto deleted file mode 100644 index acc9044452..0000000000 --- a/vendor/k8s.io/apimachinery/pkg/api/resource/generated.proto +++ /dev/null @@ -1,88 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.apimachinery.pkg.api.resource; - -// Package-wide variables from generator "generated". -option go_package = "resource"; - -// Quantity is a fixed-point representation of a number. -// It provides convenient marshaling/unmarshaling in JSON and YAML, -// in addition to String() and Int64() accessors. -// -// The serialization format is: -// -// ::= -// (Note that may be empty, from the "" case in .) -// ::= 0 | 1 | ... | 9 -// ::= | -// ::= | . | . | . -// ::= "+" | "-" -// ::= | -// ::= | | -// ::= Ki | Mi | Gi | Ti | Pi | Ei -// (International System of units; See: http://physics.nist.gov/cuu/Units/binary.html) -// ::= m | "" | k | M | G | T | P | E -// (Note that 1024 = 1Ki but 1000 = 1k; I didn't choose the capitalization.) -// ::= "e" | "E" -// -// No matter which of the three exponent forms is used, no quantity may represent -// a number greater than 2^63-1 in magnitude, nor may it have more than 3 decimal -// places. Numbers larger or more precise will be capped or rounded up. -// (E.g.: 0.1m will rounded up to 1m.) -// This may be extended in the future if we require larger or smaller quantities. -// -// When a Quantity is parsed from a string, it will remember the type of suffix -// it had, and will use the same type again when it is serialized. -// -// Before serializing, Quantity will be put in "canonical form". -// This means that Exponent/suffix will be adjusted up or down (with a -// corresponding increase or decrease in Mantissa) such that: -// a. No precision is lost -// b. No fractional digits will be emitted -// c. The exponent (or suffix) is as large as possible. -// The sign will be omitted unless the number is negative. -// -// Examples: -// 1.5 will be serialized as "1500m" -// 1.5Gi will be serialized as "1536Mi" -// -// Note that the quantity will NEVER be internally represented by a -// floating point number. That is the whole point of this exercise. -// -// Non-canonical values will still parse as long as they are well formed, -// but will be re-emitted in their canonical form. (So always use canonical -// form, or don't diff.) -// -// This format is intended to make it difficult to use these numbers without -// writing some sort of special handling code in the hopes that that will -// cause implementors to also use a fixed point implementation. -// -// +protobuf=true -// +protobuf.embed=string -// +protobuf.options.marshal=false -// +protobuf.options.(gogoproto.goproto_stringer)=false -// +k8s:deepcopy-gen=true -// +k8s:openapi-gen=true -message Quantity { - optional string string = 1; -} - diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/OWNERS b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/OWNERS deleted file mode 100755 index cdb125a0dd..0000000000 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/OWNERS +++ /dev/null @@ -1,31 +0,0 @@ -reviewers: -- thockin -- smarterclayton -- wojtek-t -- deads2k -- brendandburns -- caesarxuchao -- liggitt -- nikhiljindal -- gmarek -- erictune -- davidopp -- sttts -- quinton-hoole -- luxas -- janetkuo -- justinsb -- ncdc -- soltysh -- dims -- madhusudancs -- hongchaodeng -- krousey -- mml -- mbohlool -- david-mcmahon -- therc -- mqliang -- kevin-wangzefeng -- jianhuiz -- feihujiang diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto deleted file mode 100644 index 989f076a10..0000000000 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto +++ /dev/null @@ -1,879 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.apimachinery.pkg.apis.meta.v1; - -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1"; - -// APIGroup contains the name, the supported versions, and the preferred version -// of a group. -message APIGroup { - // name is the name of the group. - optional string name = 1; - - // versions are the versions supported in this group. - repeated GroupVersionForDiscovery versions = 2; - - // preferredVersion is the version preferred by the API server, which - // probably is the storage version. - // +optional - optional GroupVersionForDiscovery preferredVersion = 3; - - // a map of client CIDR to server address that is serving this group. - // This is to help clients reach servers in the most network-efficient way possible. - // Clients can use the appropriate server address as per the CIDR that they match. - // In case of multiple matches, clients should use the longest matching CIDR. - // The server returns only those CIDRs that it thinks that the client can match. - // For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP. - // Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP. - // +optional - repeated ServerAddressByClientCIDR serverAddressByClientCIDRs = 4; -} - -// APIGroupList is a list of APIGroup, to allow clients to discover the API at -// /apis. -message APIGroupList { - // groups is a list of APIGroup. - repeated APIGroup groups = 1; -} - -// APIResource specifies the name of a resource and whether it is namespaced. -message APIResource { - // name is the plural name of the resource. - optional string name = 1; - - // singularName is the singular name of the resource. This allows clients to handle plural and singular opaquely. - // The singularName is more correct for reporting status on a single item and both singular and plural are allowed - // from the kubectl CLI interface. - optional string singularName = 6; - - // namespaced indicates if a resource is namespaced or not. - optional bool namespaced = 2; - - // group is the preferred group of the resource. Empty implies the group of the containing resource list. - // For subresources, this may have a different value, for example: Scale". - optional string group = 8; - - // version is the preferred version of the resource. Empty implies the version of the containing resource list - // For subresources, this may have a different value, for example: v1 (while inside a v1beta1 version of the core resource's group)". - optional string version = 9; - - // kind is the kind for the resource (e.g. 'Foo' is the kind for a resource 'foo') - optional string kind = 3; - - // verbs is a list of supported kube verbs (this includes get, list, watch, create, - // update, patch, delete, deletecollection, and proxy) - optional Verbs verbs = 4; - - // shortNames is a list of suggested short names of the resource. - repeated string shortNames = 5; - - // categories is a list of the grouped resources this resource belongs to (e.g. 'all') - repeated string categories = 7; -} - -// APIResourceList is a list of APIResource, it is used to expose the name of the -// resources supported in a specific group and version, and if the resource -// is namespaced. -message APIResourceList { - // groupVersion is the group and version this APIResourceList is for. - optional string groupVersion = 1; - - // resources contains the name of the resources and if they are namespaced. - repeated APIResource resources = 2; -} - -// APIVersions lists the versions that are available, to allow clients to -// discover the API at /api, which is the root path of the legacy v1 API. -// -// +protobuf.options.(gogoproto.goproto_stringer)=false -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -message APIVersions { - // versions are the api versions that are available. - repeated string versions = 1; - - // a map of client CIDR to server address that is serving this group. - // This is to help clients reach servers in the most network-efficient way possible. - // Clients can use the appropriate server address as per the CIDR that they match. - // In case of multiple matches, clients should use the longest matching CIDR. - // The server returns only those CIDRs that it thinks that the client can match. - // For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP. - // Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP. - repeated ServerAddressByClientCIDR serverAddressByClientCIDRs = 2; -} - -// CreateOptions may be provided when creating an API object. -message CreateOptions { - // When present, indicates that modifications should not be - // persisted. An invalid or unrecognized dryRun directive will - // result in an error response and no further processing of the - // request. Valid values are: - // - All: all dry run stages will be processed - // +optional - repeated string dryRun = 1; - - // If IncludeUninitialized is specified, the object may be - // returned without completing initialization. - optional bool includeUninitialized = 2; -} - -// DeleteOptions may be provided when deleting an API object. -message DeleteOptions { - // The duration in seconds before the object should be deleted. Value must be non-negative integer. - // The value zero indicates delete immediately. If this value is nil, the default grace period for the - // specified type will be used. - // Defaults to a per object value if not specified. zero means delete immediately. - // +optional - optional int64 gracePeriodSeconds = 1; - - // Must be fulfilled before a deletion is carried out. If not possible, a 409 Conflict status will be - // returned. - // +optional - optional Preconditions preconditions = 2; - - // Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. - // Should the dependent objects be orphaned. If true/false, the "orphan" - // finalizer will be added to/removed from the object's finalizers list. - // Either this field or PropagationPolicy may be set, but not both. - // +optional - optional bool orphanDependents = 3; - - // Whether and how garbage collection will be performed. - // Either this field or OrphanDependents may be set, but not both. - // The default policy is decided by the existing finalizer set in the - // metadata.finalizers and the resource-specific default policy. - // Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - - // allow the garbage collector to delete the dependents in the background; - // 'Foreground' - a cascading policy that deletes all dependents in the - // foreground. - // +optional - optional string propagationPolicy = 4; - - // When present, indicates that modifications should not be - // persisted. An invalid or unrecognized dryRun directive will - // result in an error response and no further processing of the - // request. Valid values are: - // - All: all dry run stages will be processed - // +optional - repeated string dryRun = 5; -} - -// Duration is a wrapper around time.Duration which supports correct -// marshaling to YAML and JSON. In particular, it marshals into strings, which -// can be used as map keys in json. -message Duration { - optional int64 duration = 1; -} - -// ExportOptions is the query options to the standard REST get call. -message ExportOptions { - // Should this value be exported. Export strips fields that a user can not specify. - optional bool export = 1; - - // Should the export be exact. Exact export maintains cluster-specific fields like 'Namespace'. - optional bool exact = 2; -} - -// GetOptions is the standard query options to the standard REST get call. -message GetOptions { - // When specified: - // - if unset, then the result is returned from remote storage based on quorum-read flag; - // - if it's 0, then we simply return what we currently have in cache, no guarantee; - // - if set to non zero, then the result is at least as fresh as given rv. - optional string resourceVersion = 1; - - // If true, partially initialized resources are included in the response. - // +optional - optional bool includeUninitialized = 2; -} - -// GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying -// concepts during lookup stages without having partially valid types -// -// +protobuf.options.(gogoproto.goproto_stringer)=false -message GroupKind { - optional string group = 1; - - optional string kind = 2; -} - -// GroupResource specifies a Group and a Resource, but does not force a version. This is useful for identifying -// concepts during lookup stages without having partially valid types -// -// +protobuf.options.(gogoproto.goproto_stringer)=false -message GroupResource { - optional string group = 1; - - optional string resource = 2; -} - -// GroupVersion contains the "group" and the "version", which uniquely identifies the API. -// -// +protobuf.options.(gogoproto.goproto_stringer)=false -message GroupVersion { - optional string group = 1; - - optional string version = 2; -} - -// GroupVersion contains the "group/version" and "version" string of a version. -// It is made a struct to keep extensibility. -message GroupVersionForDiscovery { - // groupVersion specifies the API group and version in the form "group/version" - optional string groupVersion = 1; - - // version specifies the version in the form of "version". This is to save - // the clients the trouble of splitting the GroupVersion. - optional string version = 2; -} - -// GroupVersionKind unambiguously identifies a kind. It doesn't anonymously include GroupVersion -// to avoid automatic coersion. It doesn't use a GroupVersion to avoid custom marshalling -// -// +protobuf.options.(gogoproto.goproto_stringer)=false -message GroupVersionKind { - optional string group = 1; - - optional string version = 2; - - optional string kind = 3; -} - -// GroupVersionResource unambiguously identifies a resource. It doesn't anonymously include GroupVersion -// to avoid automatic coersion. It doesn't use a GroupVersion to avoid custom marshalling -// -// +protobuf.options.(gogoproto.goproto_stringer)=false -message GroupVersionResource { - optional string group = 1; - - optional string version = 2; - - optional string resource = 3; -} - -// Initializer is information about an initializer that has not yet completed. -message Initializer { - // name of the process that is responsible for initializing this object. - optional string name = 1; -} - -// Initializers tracks the progress of initialization. -message Initializers { - // Pending is a list of initializers that must execute in order before this object is visible. - // When the last pending initializer is removed, and no failing result is set, the initializers - // struct will be set to nil and the object is considered as initialized and visible to all - // clients. - // +patchMergeKey=name - // +patchStrategy=merge - repeated Initializer pending = 1; - - // If result is set with the Failure field, the object will be persisted to storage and then deleted, - // ensuring that other clients can observe the deletion. - optional Status result = 2; -} - -// A label selector is a label query over a set of resources. The result of matchLabels and -// matchExpressions are ANDed. An empty label selector matches all objects. A null -// label selector matches no objects. -message LabelSelector { - // matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - // map is equivalent to an element of matchExpressions, whose key field is "key", the - // operator is "In", and the values array contains only "value". The requirements are ANDed. - // +optional - map matchLabels = 1; - - // matchExpressions is a list of label selector requirements. The requirements are ANDed. - // +optional - repeated LabelSelectorRequirement matchExpressions = 2; -} - -// A label selector requirement is a selector that contains values, a key, and an operator that -// relates the key and values. -message LabelSelectorRequirement { - // key is the label key that the selector applies to. - // +patchMergeKey=key - // +patchStrategy=merge - optional string key = 1; - - // operator represents a key's relationship to a set of values. - // Valid operators are In, NotIn, Exists and DoesNotExist. - optional string operator = 2; - - // values is an array of string values. If the operator is In or NotIn, - // the values array must be non-empty. If the operator is Exists or DoesNotExist, - // the values array must be empty. This array is replaced during a strategic - // merge patch. - // +optional - repeated string values = 3; -} - -// List holds a list of objects, which may not be known by the server. -message List { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional ListMeta metadata = 1; - - // List of objects - repeated k8s.io.apimachinery.pkg.runtime.RawExtension items = 2; -} - -// ListMeta describes metadata that synthetic resources must have, including lists and -// various status objects. A resource may have only one of {ObjectMeta, ListMeta}. -message ListMeta { - // selfLink is a URL representing this object. - // Populated by the system. - // Read-only. - // +optional - optional string selfLink = 1; - - // String that identifies the server's internal version of this object that - // can be used by clients to determine when objects have changed. - // Value must be treated as opaque by clients and passed unmodified back to the server. - // Populated by the system. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency - // +optional - optional string resourceVersion = 2; - - // continue may be set if the user set a limit on the number of items returned, and indicates that - // the server has more data available. The value is opaque and may be used to issue another request - // to the endpoint that served this list to retrieve the next set of available objects. Continuing a - // consistent list may not be possible if the server configuration has changed or more than a few - // minutes have passed. The resourceVersion field returned when using this continue value will be - // identical to the value in the first response, unless you have received this token from an error - // message. - optional string continue = 3; -} - -// ListOptions is the query options to a standard REST list call. -message ListOptions { - // A selector to restrict the list of returned objects by their labels. - // Defaults to everything. - // +optional - optional string labelSelector = 1; - - // A selector to restrict the list of returned objects by their fields. - // Defaults to everything. - // +optional - optional string fieldSelector = 2; - - // If true, partially initialized resources are included in the response. - // +optional - optional bool includeUninitialized = 6; - - // Watch for changes to the described resources and return them as a stream of - // add, update, and remove notifications. Specify resourceVersion. - // +optional - optional bool watch = 3; - - // When specified with a watch call, shows changes that occur after that particular version of a resource. - // Defaults to changes from the beginning of history. - // When specified for list: - // - if unset, then the result is returned from remote storage based on quorum-read flag; - // - if it's 0, then we simply return what we currently have in cache, no guarantee; - // - if set to non zero, then the result is at least as fresh as given rv. - // +optional - optional string resourceVersion = 4; - - // Timeout for the list/watch call. - // This limits the duration of the call, regardless of any activity or inactivity. - // +optional - optional int64 timeoutSeconds = 5; - - // limit is a maximum number of responses to return for a list call. If more items exist, the - // server will set the `continue` field on the list metadata to a value that can be used with the - // same initial query to retrieve the next set of results. Setting a limit may return fewer than - // the requested amount of items (up to zero items) in the event all requested objects are - // filtered out and clients should only use the presence of the continue field to determine whether - // more results are available. Servers may choose not to support the limit argument and will return - // all of the available results. If limit is specified and the continue field is empty, clients may - // assume that no more results are available. This field is not supported if watch is true. - // - // The server guarantees that the objects returned when using continue will be identical to issuing - // a single list call without a limit - that is, no objects created, modified, or deleted after the - // first request is issued will be included in any subsequent continued requests. This is sometimes - // referred to as a consistent snapshot, and ensures that a client that is using limit to receive - // smaller chunks of a very large result can ensure they see all possible objects. If objects are - // updated during a chunked list the version of the object that was present at the time the first list - // result was calculated is returned. - optional int64 limit = 7; - - // The continue option should be set when retrieving more results from the server. Since this value is - // server defined, clients may only use the continue value from a previous query result with identical - // query parameters (except for the value of continue) and the server may reject a continue value it - // does not recognize. If the specified continue value is no longer valid whether due to expiration - // (generally five to fifteen minutes) or a configuration change on the server, the server will - // respond with a 410 ResourceExpired error together with a continue token. If the client needs a - // consistent list, it must restart their list without the continue field. Otherwise, the client may - // send another list request with the token received with the 410 error, the server will respond with - // a list starting from the next key, but from the latest snapshot, which is inconsistent from the - // previous list results - objects that are created, modified, or deleted after the first list request - // will be included in the response, as long as their keys are after the "next key". - // - // This field is not supported when watch is true. Clients may start a watch from the last - // resourceVersion value returned by the server and not miss any modifications. - optional string continue = 8; -} - -// MicroTime is version of Time with microsecond level precision. -// -// +protobuf.options.marshal=false -// +protobuf.as=Timestamp -// +protobuf.options.(gogoproto.goproto_stringer)=false -message MicroTime { - // Represents seconds of UTC time since Unix epoch - // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to - // 9999-12-31T23:59:59Z inclusive. - optional int64 seconds = 1; - - // Non-negative fractions of a second at nanosecond resolution. Negative - // second values with fractions must still have non-negative nanos values - // that count forward in time. Must be from 0 to 999,999,999 - // inclusive. This field may be limited in precision depending on context. - optional int32 nanos = 2; -} - -// ObjectMeta is metadata that all persisted resources must have, which includes all objects -// users must create. -message ObjectMeta { - // Name must be unique within a namespace. Is required when creating resources, although - // some resources may allow a client to request the generation of an appropriate name - // automatically. Name is primarily intended for creation idempotence and configuration - // definition. - // Cannot be updated. - // More info: http://kubernetes.io/docs/user-guide/identifiers#names - // +optional - optional string name = 1; - - // GenerateName is an optional prefix, used by the server, to generate a unique - // name ONLY IF the Name field has not been provided. - // If this field is used, the name returned to the client will be different - // than the name passed. This value will also be combined with a unique suffix. - // The provided value has the same validation rules as the Name field, - // and may be truncated by the length of the suffix required to make the value - // unique on the server. - // - // If this field is specified and the generated name exists, the server will - // NOT return a 409 - instead, it will either return 201 Created or 500 with Reason - // ServerTimeout indicating a unique name could not be found in the time allotted, and the client - // should retry (optionally after the time indicated in the Retry-After header). - // - // Applied only if Name is not specified. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency - // +optional - optional string generateName = 2; - - // Namespace defines the space within each name must be unique. An empty namespace is - // equivalent to the "default" namespace, but "default" is the canonical representation. - // Not all objects are required to be scoped to a namespace - the value of this field for - // those objects will be empty. - // - // Must be a DNS_LABEL. - // Cannot be updated. - // More info: http://kubernetes.io/docs/user-guide/namespaces - // +optional - optional string namespace = 3; - - // SelfLink is a URL representing this object. - // Populated by the system. - // Read-only. - // +optional - optional string selfLink = 4; - - // UID is the unique in time and space value for this object. It is typically generated by - // the server on successful creation of a resource and is not allowed to change on PUT - // operations. - // - // Populated by the system. - // Read-only. - // More info: http://kubernetes.io/docs/user-guide/identifiers#uids - // +optional - optional string uid = 5; - - // An opaque value that represents the internal version of this object that can - // be used by clients to determine when objects have changed. May be used for optimistic - // concurrency, change detection, and the watch operation on a resource or set of resources. - // Clients must treat these values as opaque and passed unmodified back to the server. - // They may only be valid for a particular resource or set of resources. - // - // Populated by the system. - // Read-only. - // Value must be treated as opaque by clients and . - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency - // +optional - optional string resourceVersion = 6; - - // A sequence number representing a specific generation of the desired state. - // Populated by the system. Read-only. - // +optional - optional int64 generation = 7; - - // CreationTimestamp is a timestamp representing the server time when this object was - // created. It is not guaranteed to be set in happens-before order across separate operations. - // Clients may not set this value. It is represented in RFC3339 form and is in UTC. - // - // Populated by the system. - // Read-only. - // Null for lists. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional Time creationTimestamp = 8; - - // DeletionTimestamp is RFC 3339 date and time at which this resource will be deleted. This - // field is set by the server when a graceful deletion is requested by the user, and is not - // directly settable by a client. The resource is expected to be deleted (no longer visible - // from resource lists, and not reachable by name) after the time in this field, once the - // finalizers list is empty. As long as the finalizers list contains items, deletion is blocked. - // Once the deletionTimestamp is set, this value may not be unset or be set further into the - // future, although it may be shortened or the resource may be deleted prior to this time. - // For example, a user may request that a pod is deleted in 30 seconds. The Kubelet will react - // by sending a graceful termination signal to the containers in the pod. After that 30 seconds, - // the Kubelet will send a hard termination signal (SIGKILL) to the container and after cleanup, - // remove the pod from the API. In the presence of network partitions, this object may still - // exist after this timestamp, until an administrator or automated process can determine the - // resource is fully terminated. - // If not set, graceful deletion of the object has not been requested. - // - // Populated by the system when a graceful deletion is requested. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional Time deletionTimestamp = 9; - - // Number of seconds allowed for this object to gracefully terminate before - // it will be removed from the system. Only set when deletionTimestamp is also set. - // May only be shortened. - // Read-only. - // +optional - optional int64 deletionGracePeriodSeconds = 10; - - // Map of string keys and values that can be used to organize and categorize - // (scope and select) objects. May match selectors of replication controllers - // and services. - // More info: http://kubernetes.io/docs/user-guide/labels - // +optional - map labels = 11; - - // Annotations is an unstructured key value map stored with a resource that may be - // set by external tools to store and retrieve arbitrary metadata. They are not - // queryable and should be preserved when modifying objects. - // More info: http://kubernetes.io/docs/user-guide/annotations - // +optional - map annotations = 12; - - // List of objects depended by this object. If ALL objects in the list have - // been deleted, this object will be garbage collected. If this object is managed by a controller, - // then an entry in this list will point to this controller, with the controller field set to true. - // There cannot be more than one managing controller. - // +optional - // +patchMergeKey=uid - // +patchStrategy=merge - repeated OwnerReference ownerReferences = 13; - - // An initializer is a controller which enforces some system invariant at object creation time. - // This field is a list of initializers that have not yet acted on this object. If nil or empty, - // this object has been completely initialized. Otherwise, the object is considered uninitialized - // and is hidden (in list/watch and get calls) from clients that haven't explicitly asked to - // observe uninitialized objects. - // - // When an object is created, the system will populate this list with the current set of initializers. - // Only privileged users may set or modify this list. Once it is empty, it may not be modified further - // by any user. - optional Initializers initializers = 16; - - // Must be empty before the object is deleted from the registry. Each entry - // is an identifier for the responsible component that will remove the entry - // from the list. If the deletionTimestamp of the object is non-nil, entries - // in this list can only be removed. - // +optional - // +patchStrategy=merge - repeated string finalizers = 14; - - // The name of the cluster which the object belongs to. - // This is used to distinguish resources with same name and namespace in different clusters. - // This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request. - // +optional - optional string clusterName = 15; -} - -// OwnerReference contains enough information to let you identify an owning -// object. An owning object must be in the same namespace as the dependent, or -// be cluster-scoped, so there is no namespace field. -message OwnerReference { - // API version of the referent. - optional string apiVersion = 5; - - // Kind of the referent. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - optional string kind = 1; - - // Name of the referent. - // More info: http://kubernetes.io/docs/user-guide/identifiers#names - optional string name = 3; - - // UID of the referent. - // More info: http://kubernetes.io/docs/user-guide/identifiers#uids - optional string uid = 4; - - // If true, this reference points to the managing controller. - // +optional - optional bool controller = 6; - - // If true, AND if the owner has the "foregroundDeletion" finalizer, then - // the owner cannot be deleted from the key-value store until this - // reference is removed. - // Defaults to false. - // To set this field, a user needs "delete" permission of the owner, - // otherwise 422 (Unprocessable Entity) will be returned. - // +optional - optional bool blockOwnerDeletion = 7; -} - -// Patch is provided to give a concrete name and type to the Kubernetes PATCH request body. -message Patch { -} - -// Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out. -message Preconditions { - // Specifies the target UID. - // +optional - optional string uid = 1; -} - -// RootPaths lists the paths available at root. -// For example: "/healthz", "/apis". -message RootPaths { - // paths are the paths available at root. - repeated string paths = 1; -} - -// ServerAddressByClientCIDR helps the client to determine the server address that they should use, depending on the clientCIDR that they match. -message ServerAddressByClientCIDR { - // The CIDR with which clients can match their IP to figure out the server address that they should use. - optional string clientCIDR = 1; - - // Address of this server, suitable for a client that matches the above CIDR. - // This can be a hostname, hostname:port, IP or IP:port. - optional string serverAddress = 2; -} - -// Status is a return value for calls that don't return other objects. -message Status { - // Standard list metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional ListMeta metadata = 1; - - // Status of the operation. - // One of: "Success" or "Failure". - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status - // +optional - optional string status = 2; - - // A human-readable description of the status of this operation. - // +optional - optional string message = 3; - - // A machine-readable description of why this operation is in the - // "Failure" status. If this value is empty there - // is no information available. A Reason clarifies an HTTP status - // code but does not override it. - // +optional - optional string reason = 4; - - // Extended data associated with the reason. Each reason may define its - // own extended details. This field is optional and the data returned - // is not guaranteed to conform to any schema except that defined by - // the reason type. - // +optional - optional StatusDetails details = 5; - - // Suggested HTTP return code for this status, 0 if not set. - // +optional - optional int32 code = 6; -} - -// StatusCause provides more information about an api.Status failure, including -// cases when multiple errors are encountered. -message StatusCause { - // A machine-readable description of the cause of the error. If this value is - // empty there is no information available. - // +optional - optional string reason = 1; - - // A human-readable description of the cause of the error. This field may be - // presented as-is to a reader. - // +optional - optional string message = 2; - - // The field of the resource that has caused this error, as named by its JSON - // serialization. May include dot and postfix notation for nested attributes. - // Arrays are zero-indexed. Fields may appear more than once in an array of - // causes due to fields having multiple errors. - // Optional. - // - // Examples: - // "name" - the field "name" on the current resource - // "items[0].name" - the field "name" on the first array entry in "items" - // +optional - optional string field = 3; -} - -// StatusDetails is a set of additional properties that MAY be set by the -// server to provide additional information about a response. The Reason -// field of a Status object defines what attributes will be set. Clients -// must ignore fields that do not match the defined type of each attribute, -// and should assume that any attribute may be empty, invalid, or under -// defined. -message StatusDetails { - // The name attribute of the resource associated with the status StatusReason - // (when there is a single name which can be described). - // +optional - optional string name = 1; - - // The group attribute of the resource associated with the status StatusReason. - // +optional - optional string group = 2; - - // The kind attribute of the resource associated with the status StatusReason. - // On some operations may differ from the requested resource Kind. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional string kind = 3; - - // UID of the resource. - // (when there is a single resource which can be described). - // More info: http://kubernetes.io/docs/user-guide/identifiers#uids - // +optional - optional string uid = 6; - - // The Causes array includes more details associated with the StatusReason - // failure. Not all StatusReasons may provide detailed causes. - // +optional - repeated StatusCause causes = 4; - - // If specified, the time in seconds before the operation should be retried. Some errors may indicate - // the client must take an alternate action - for those errors this field may indicate how long to wait - // before taking the alternate action. - // +optional - optional int32 retryAfterSeconds = 5; -} - -// Time is a wrapper around time.Time which supports correct -// marshaling to YAML and JSON. Wrappers are provided for many -// of the factory methods that the time package offers. -// -// +protobuf.options.marshal=false -// +protobuf.as=Timestamp -// +protobuf.options.(gogoproto.goproto_stringer)=false -message Time { - // Represents seconds of UTC time since Unix epoch - // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to - // 9999-12-31T23:59:59Z inclusive. - optional int64 seconds = 1; - - // Non-negative fractions of a second at nanosecond resolution. Negative - // second values with fractions must still have non-negative nanos values - // that count forward in time. Must be from 0 to 999,999,999 - // inclusive. This field may be limited in precision depending on context. - optional int32 nanos = 2; -} - -// Timestamp is a struct that is equivalent to Time, but intended for -// protobuf marshalling/unmarshalling. It is generated into a serialization -// that matches Time. Do not use in Go structs. -message Timestamp { - // Represents seconds of UTC time since Unix epoch - // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to - // 9999-12-31T23:59:59Z inclusive. - optional int64 seconds = 1; - - // Non-negative fractions of a second at nanosecond resolution. Negative - // second values with fractions must still have non-negative nanos values - // that count forward in time. Must be from 0 to 999,999,999 - // inclusive. This field may be limited in precision depending on context. - optional int32 nanos = 2; -} - -// TypeMeta describes an individual object in an API response or request -// with strings representing the type of the object and its API schema version. -// Structures that are versioned or persisted should inline TypeMeta. -// -// +k8s:deepcopy-gen=false -message TypeMeta { - // Kind is a string value representing the REST resource this object represents. - // Servers may infer this from the endpoint the client submits requests to. - // Cannot be updated. - // In CamelCase. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds - // +optional - optional string kind = 1; - - // APIVersion defines the versioned schema of this representation of an object. - // Servers should convert recognized schemas to the latest internal value, and - // may reject unrecognized values. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources - // +optional - optional string apiVersion = 2; -} - -// UpdateOptions may be provided when updating an API object. -message UpdateOptions { - // When present, indicates that modifications should not be - // persisted. An invalid or unrecognized dryRun directive will - // result in an error response and no further processing of the - // request. Valid values are: - // - All: all dry run stages will be processed - // +optional - repeated string dryRun = 1; -} - -// Verbs masks the value so protobuf can generate -// -// +protobuf.nullable=true -// +protobuf.options.(gogoproto.goproto_stringer)=false -message Verbs { - // items, if empty, will result in an empty slice - - repeated string items = 1; -} - -// Event represents a single event to a watched resource. -// -// +protobuf=true -// +k8s:deepcopy-gen=true -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -message WatchEvent { - optional string type = 1; - - // Object is: - // * If Type is Added or Modified: the new state of the object. - // * If Type is Deleted: the state of the object immediately before deletion. - // * If Type is Error: *Status is recommended; other types may make sense - // depending on context. - optional k8s.io.apimachinery.pkg.runtime.RawExtension object = 2; -} - diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.proto b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.proto deleted file mode 100644 index 83be997904..0000000000 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.proto +++ /dev/null @@ -1,57 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.apimachinery.pkg.apis.meta.v1beta1; - -import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; - -// Package-wide variables from generator "generated". -option go_package = "v1beta1"; - -// PartialObjectMetadata is a generic representation of any object with ObjectMeta. It allows clients -// to get access to a particular ObjectMeta schema without knowing the details of the version. -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -message PartialObjectMetadata { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional - optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; -} - -// PartialObjectMetadataList contains a list of objects containing only their metadata -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -message PartialObjectMetadataList { - // items contains each of the included items. - repeated PartialObjectMetadata items = 1; -} - -// TableOptions are used when a Table is requested by the caller. -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -message TableOptions { - // includeObject decides whether to include each object along with its columnar information. - // Specifying "None" will return no object, specifying "Object" will return the full object contents, and - // specifying "Metadata" (the default) will return the object's metadata in the PartialObjectMetadata kind - // in version v1beta1 of the meta.k8s.io API group. - optional string includeObject = 1; -} - diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/generated.proto b/vendor/k8s.io/apimachinery/pkg/runtime/generated.proto deleted file mode 100644 index 0e212ec941..0000000000 --- a/vendor/k8s.io/apimachinery/pkg/runtime/generated.proto +++ /dev/null @@ -1,127 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.apimachinery.pkg.runtime; - -// Package-wide variables from generator "generated". -option go_package = "runtime"; - -// RawExtension is used to hold extensions in external versions. -// -// To use this, make a field which has RawExtension as its type in your external, versioned -// struct, and Object in your internal struct. You also need to register your -// various plugin types. -// -// // Internal package: -// type MyAPIObject struct { -// runtime.TypeMeta `json:",inline"` -// MyPlugin runtime.Object `json:"myPlugin"` -// } -// type PluginA struct { -// AOption string `json:"aOption"` -// } -// -// // External package: -// type MyAPIObject struct { -// runtime.TypeMeta `json:",inline"` -// MyPlugin runtime.RawExtension `json:"myPlugin"` -// } -// type PluginA struct { -// AOption string `json:"aOption"` -// } -// -// // On the wire, the JSON will look something like this: -// { -// "kind":"MyAPIObject", -// "apiVersion":"v1", -// "myPlugin": { -// "kind":"PluginA", -// "aOption":"foo", -// }, -// } -// -// So what happens? Decode first uses json or yaml to unmarshal the serialized data into -// your external MyAPIObject. That causes the raw JSON to be stored, but not unpacked. -// The next step is to copy (using pkg/conversion) into the internal struct. The runtime -// package's DefaultScheme has conversion functions installed which will unpack the -// JSON stored in RawExtension, turning it into the correct object type, and storing it -// in the Object. (TODO: In the case where the object is of an unknown type, a -// runtime.Unknown object will be created and stored.) -// -// +k8s:deepcopy-gen=true -// +protobuf=true -// +k8s:openapi-gen=true -message RawExtension { - // Raw is the underlying serialization of this object. - // - // TODO: Determine how to detect ContentType and ContentEncoding of 'Raw' data. - optional bytes raw = 1; -} - -// TypeMeta is shared by all top level objects. The proper way to use it is to inline it in your type, -// like this: -// type MyAwesomeAPIObject struct { -// runtime.TypeMeta `json:",inline"` -// ... // other fields -// } -// func (obj *MyAwesomeAPIObject) SetGroupVersionKind(gvk *metav1.GroupVersionKind) { metav1.UpdateTypeMeta(obj,gvk) }; GroupVersionKind() *GroupVersionKind -// -// TypeMeta is provided here for convenience. You may use it directly from this package or define -// your own with the same fields. -// -// +k8s:deepcopy-gen=false -// +protobuf=true -// +k8s:openapi-gen=true -message TypeMeta { - // +optional - optional string apiVersion = 1; - - // +optional - optional string kind = 2; -} - -// Unknown allows api objects with unknown types to be passed-through. This can be used -// to deal with the API objects from a plug-in. Unknown objects still have functioning -// TypeMeta features-- kind, version, etc. -// TODO: Make this object have easy access to field based accessors and settors for -// metadata and field mutatation. -// -// +k8s:deepcopy-gen=true -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// +protobuf=true -// +k8s:openapi-gen=true -message Unknown { - optional TypeMeta typeMeta = 1; - - // Raw will hold the complete serialized object which couldn't be matched - // with a registered type. Most likely, nothing should be done with this - // except for passing it through the system. - optional bytes raw = 2; - - // ContentEncoding is encoding used to encode 'Raw' data. - // Unspecified means no encoding. - optional string contentEncoding = 3; - - // ContentType is serialization method used to serialize 'Raw'. - // Unspecified means ContentTypeJSON. - optional string contentType = 4; -} - diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.proto b/vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.proto deleted file mode 100644 index 5aeeaa100a..0000000000 --- a/vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.proto +++ /dev/null @@ -1,26 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.apimachinery.pkg.runtime.schema; - -// Package-wide variables from generator "generated". -option go_package = "schema"; - diff --git a/vendor/k8s.io/apimachinery/pkg/util/intstr/generated.proto b/vendor/k8s.io/apimachinery/pkg/util/intstr/generated.proto deleted file mode 100644 index e79fb9e572..0000000000 --- a/vendor/k8s.io/apimachinery/pkg/util/intstr/generated.proto +++ /dev/null @@ -1,43 +0,0 @@ -/* -Copyright 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. -*/ - - -// This file was autogenerated by go-to-protobuf. Do not edit it manually! - -syntax = 'proto2'; - -package k8s.io.apimachinery.pkg.util.intstr; - -// Package-wide variables from generator "generated". -option go_package = "intstr"; - -// IntOrString is a type that can hold an int32 or a string. When used in -// JSON or YAML marshalling and unmarshalling, it produces or consumes the -// inner type. This allows you to have, for example, a JSON field that can -// accept a name or number. -// TODO: Rename to Int32OrString -// -// +protobuf=true -// +protobuf.options.(gogoproto.goproto_stringer)=false -// +k8s:openapi-gen=true -message IntOrString { - optional int64 type = 1; - - optional int32 intVal = 2; - - optional string strVal = 3; -} - diff --git a/vendor/k8s.io/client-go/pkg/version/.gitattributes b/vendor/k8s.io/client-go/pkg/version/.gitattributes deleted file mode 100644 index 7e349eff60..0000000000 --- a/vendor/k8s.io/client-go/pkg/version/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -base.go export-subst diff --git a/vendor/k8s.io/client-go/pkg/version/def.bzl b/vendor/k8s.io/client-go/pkg/version/def.bzl deleted file mode 100644 index 9c018a4ef7..0000000000 --- a/vendor/k8s.io/client-go/pkg/version/def.bzl +++ /dev/null @@ -1,38 +0,0 @@ -# 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. - -# Implements hack/lib/version.sh's kube::version::ldflags() for Bazel. -def version_x_defs(): - # This should match the list of packages in kube::version::ldflag - stamp_pkgs = [ - "k8s.io/kubernetes/pkg/version", - # In hack/lib/version.sh, this has a vendor/ prefix. That isn't needed here? - "k8s.io/client-go/pkg/version", - ] - # This should match the list of vars in kube::version::ldflags - # It should also match the list of vars set in hack/print-workspace-status.sh. - stamp_vars = [ - "buildDate", - "gitCommit", - "gitMajor", - "gitMinor", - "gitTreeState", - "gitVersion", - ] - # Generate the cross-product. - x_defs = {} - for pkg in stamp_pkgs: - for var in stamp_vars: - x_defs["%s.%s" % (pkg, var)] = "{%s}" % var - return x_defs diff --git a/vendor/k8s.io/client-go/rest/OWNERS b/vendor/k8s.io/client-go/rest/OWNERS deleted file mode 100755 index 8d97da007d..0000000000 --- a/vendor/k8s.io/client-go/rest/OWNERS +++ /dev/null @@ -1,24 +0,0 @@ -reviewers: -- thockin -- smarterclayton -- caesarxuchao -- wojtek-t -- deads2k -- brendandburns -- liggitt -- nikhiljindal -- gmarek -- erictune -- sttts -- luxas -- dims -- errordeveloper -- hongchaodeng -- krousey -- resouer -- cjcullen -- rmmh -- lixiaobing10051267 -- asalkeld -- juanvallejo -- lojies diff --git a/vendor/k8s.io/client-go/tools/metrics/OWNERS b/vendor/k8s.io/client-go/tools/metrics/OWNERS deleted file mode 100755 index ff51798071..0000000000 --- a/vendor/k8s.io/client-go/tools/metrics/OWNERS +++ /dev/null @@ -1,7 +0,0 @@ -reviewers: -- wojtek-t -- eparis -- krousey -- jayunit100 -- fgrzadkowski -- tmrts diff --git a/vendor/k8s.io/client-go/transport/OWNERS b/vendor/k8s.io/client-go/transport/OWNERS deleted file mode 100755 index bf0ba5b9f9..0000000000 --- a/vendor/k8s.io/client-go/transport/OWNERS +++ /dev/null @@ -1,7 +0,0 @@ -reviewers: -- smarterclayton -- wojtek-t -- deads2k -- liggitt -- krousey -- caesarxuchao From 1071ce17f798a05d46fd8c11ad95946a5e7d285c Mon Sep 17 00:00:00 2001 From: Cecile Robert-Michon Date: Tue, 20 Nov 2018 13:21:53 -0800 Subject: [PATCH 19/29] Fix outbound connection check for master VMSS (#44) --- parts/k8s/kubernetesmasterresourcesvmss.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parts/k8s/kubernetesmasterresourcesvmss.tmpl b/parts/k8s/kubernetesmasterresourcesvmss.tmpl index 3f610d2ef9..85941287af 100644 --- a/parts/k8s/kubernetesmasterresourcesvmss.tmpl +++ b/parts/k8s/kubernetesmasterresourcesvmss.tmpl @@ -461,7 +461,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $r); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not BlockOutboundInternet}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' ',variables('provisionScriptParametersMaster'), ' /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1\"')]" + "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $r); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not BlockOutboundInternet}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}gcr.azk8s.cn 80{{else}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' ',variables('provisionScriptParametersMaster'), ' /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1\"')]" } } } From b33dcae18d266361cf40bccc874f0cc1a39a68b5 Mon Sep 17 00:00:00 2001 From: Tariq Ibrahim Date: Tue, 20 Nov 2018 14:06:42 -0800 Subject: [PATCH 20/29] update azure_const unit test (#48) --- pkg/helpers/azureconst_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/helpers/azureconst_test.go b/pkg/helpers/azureconst_test.go index deca5b9700..d70a090b71 100644 --- a/pkg/helpers/azureconst_test.go +++ b/pkg/helpers/azureconst_test.go @@ -230,6 +230,9 @@ func TestKubernetesAllowedSizes(t *testing.T) { "Standard_NV24s_v2", "Standard_NV6", "Standard_NV6s_v2", + "Standard_PB12s", + "Standard_PB24s", + "Standard_PB6s", } for _, expectedSize := range expectedSizes { From f46924ae12664b08a3726e8e4913e14369ccaf1f Mon Sep 17 00:00:00 2001 From: Jack Francis Date: Tue, 20 Nov 2018 15:34:39 -0800 Subject: [PATCH 21/29] use mcr repos and disable smb flexvol addon (#45) --- pkg/api/addons.go | 4 +- pkg/api/const.go | 2 +- pkg/api/defaults_test.go | 4 +- pkg/api/types_test.go | 159 ++++++++++++++++++++++++++++++++++----- 4 files changed, 144 insertions(+), 25 deletions(-) diff --git a/pkg/api/addons.go b/pkg/api/addons.go index 8043b33986..a49580325c 100644 --- a/pkg/api/addons.go +++ b/pkg/api/addons.go @@ -83,7 +83,7 @@ func (cs *ContainerService) setAddonsConfig(isUpdate bool) { MemoryRequests: "10Mi", CPULimits: "50m", MemoryLimits: "10Mi", - Image: "andyzhangx/blobfuse-flexvol-installer", + Image: "mcr.microsoft.com/k8s/flexvolume/blobfuse-flexvolume", }, }, } @@ -98,7 +98,7 @@ func (cs *ContainerService) setAddonsConfig(isUpdate bool) { MemoryRequests: "10Mi", CPULimits: "50m", MemoryLimits: "10Mi", - Image: "andyzhangx/smb-flexvol-installer", + Image: "mcr.microsoft.com/k8s/flexvolume/smb-flexvolume", }, }, } diff --git a/pkg/api/const.go b/pkg/api/const.go index ee1fc3863c..f53483ad65 100644 --- a/pkg/api/const.go +++ b/pkg/api/const.go @@ -101,7 +101,7 @@ const ( // DefaultBlobfuseFlexVolumeAddonEnabled determines the aks-engine provided default for enabling blobfuse flexvolume addon DefaultBlobfuseFlexVolumeAddonEnabled = true // DefaultSMBFlexVolumeAddonEnabled determines the aks-engine provided default for enabling smb flexvolume addon - DefaultSMBFlexVolumeAddonEnabled = true + DefaultSMBFlexVolumeAddonEnabled = false // DefaultKeyVaultFlexVolumeAddonEnabled determines the aks-engine provided default for enabling key vault flexvolume addon DefaultKeyVaultFlexVolumeAddonEnabled = true // DefaultDashboardAddonEnabled determines the aks-engine provided default for enabling kubernetes-dashboard addon diff --git a/pkg/api/defaults_test.go b/pkg/api/defaults_test.go index e201056f98..0206b76060 100644 --- a/pkg/api/defaults_test.go +++ b/pkg/api/defaults_test.go @@ -189,8 +189,8 @@ func TestAssignDefaultAddonImages(t *testing.T) { DefaultTillerAddonName: "gcr.io/kubernetes-helm/tiller:v2.8.1", DefaultACIConnectorAddonName: "microsoft/virtual-kubelet:latest", DefaultClusterAutoscalerAddonName: "k8s.gcr.io/cluster-autoscaler:v1.2.2", - DefaultBlobfuseFlexVolumeAddonName: "andyzhangx/blobfuse-flexvol-installer", - DefaultSMBFlexVolumeAddonName: "andyzhangx/smb-flexvol-installer", + DefaultBlobfuseFlexVolumeAddonName: "mcr.microsoft.com/k8s/flexvolume/blobfuse-flexvolume", + DefaultSMBFlexVolumeAddonName: "mcr.microsoft.com/k8s/flexvolume/smb-flexvolume", DefaultKeyVaultFlexVolumeAddonName: "mcr.microsoft.com/k8s/flexvolume/keyvault-flexvolume:v0.0.5", DefaultDashboardAddonName: "k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.0", DefaultReschedulerAddonName: "k8s.gcr.io/rescheduler:v0.3.1", diff --git a/pkg/api/types_test.go b/pkg/api/types_test.go index f664c800fb..356e32b113 100644 --- a/pkg/api/types_test.go +++ b/pkg/api/types_test.go @@ -923,6 +923,7 @@ func TestKubernetesAddon(t *testing.T) { } func TestIsTillerEnabled(t *testing.T) { + // Default case c := KubernetesConfig{ Addons: []KubernetesAddon{ getMockAddon("addon"), @@ -933,12 +934,28 @@ func TestIsTillerEnabled(t *testing.T) { if enabled != enabledDefault { t.Fatalf("KubernetesConfig.IsTillerEnabled() should return %t when no tiller addon has been specified, instead returned %t", enabledDefault, enabled) } + // Addon present, but enabled not specified c.Addons = append(c.Addons, getMockAddon(DefaultTillerAddonName)) enabled = c.IsTillerEnabled() + if enabled != enabledDefault { + t.Fatalf("KubernetesConfig.IsTillerEnabled() should return default when a custom tiller addon has been specified w/ no enabled value, expected %t, instead returned %t", enabledDefault, enabled) + } + // Addon present and enabled + b := true + c = KubernetesConfig{ + Addons: []KubernetesAddon{ + { + Name: DefaultTillerAddonName, + Enabled: &b, + }, + }, + } + enabled = c.IsTillerEnabled() if !enabled { - t.Fatalf("KubernetesConfig.IsTillerEnabled() should return true when a custom tiller addon has been specified, instead returned %t", enabled) + t.Fatalf("KubernetesConfig.IsTillerEnabled() should return true when a custom tiller addon has been specified as enabled, instead returned %t", enabled) } - b := false + // Addon present and disabled + b = false c = KubernetesConfig{ Addons: []KubernetesAddon{ { @@ -954,6 +971,7 @@ func TestIsTillerEnabled(t *testing.T) { } func TestIsAADPodIdentityEnabled(t *testing.T) { + // Default case c := KubernetesConfig{ Addons: []KubernetesAddon{ getMockAddon("addon"), @@ -964,11 +982,13 @@ func TestIsAADPodIdentityEnabled(t *testing.T) { if enabled != enabledDefault { t.Fatalf("KubernetesConfig.IsAADPodIdentityEnabled() should return %t when no aad pod identity addon has been specified, instead returned %t", enabledDefault, enabled) } + // Addon present, but enabled not specified c.Addons = append(c.Addons, getMockAddon(DefaultAADPodIdentityAddonName)) enabled = c.IsAADPodIdentityEnabled() - if enabled { - t.Fatalf("KubernetesConfig.IsAADPodIdentityEnabled() should return true when aad pod identity addon has been specified, instead returned %t", enabled) + if enabled != enabledDefault { + t.Fatalf("KubernetesConfig.IsAADPodIdentityEnabled() should return default when aad pod identity addon has been specified w/ no enabled value, expected %t, instead returned %t", enabledDefault, enabled) } + // Addon present and enabled b := true c = KubernetesConfig{ Addons: []KubernetesAddon{ @@ -980,11 +1000,26 @@ func TestIsAADPodIdentityEnabled(t *testing.T) { } enabled = c.IsAADPodIdentityEnabled() if !enabled { + t.Fatalf("KubernetesConfig.IsAADPodIdentityEnabled() should return true when aad pod identity addon has been specified as enabled, instead returned %t", enabled) + } + // Addon present and disabled + b = false + c = KubernetesConfig{ + Addons: []KubernetesAddon{ + { + Name: DefaultAADPodIdentityAddonName, + Enabled: &b, + }, + }, + } + enabled = c.IsAADPodIdentityEnabled() + if enabled { t.Fatalf("KubernetesConfig.IsAADPodIdentityEnabled() should return false when aad pod identity addon has been specified as disabled, instead returned %t", enabled) } } func TestIsACIConnectorEnabled(t *testing.T) { + // Default case c := KubernetesConfig{ Addons: []KubernetesAddon{ getMockAddon("addon"), @@ -995,11 +1030,13 @@ func TestIsACIConnectorEnabled(t *testing.T) { if enabled != enabledDefault { t.Fatalf("KubernetesConfig.IsACIConnectorEnabled() should return %t when no ACI connector addon has been specified, instead returned %t", enabledDefault, enabled) } + // Addon present, but enabled not specified c.Addons = append(c.Addons, getMockAddon(DefaultACIConnectorAddonName)) enabled = c.IsACIConnectorEnabled() - if enabled { - t.Fatalf("KubernetesConfig.IsACIConnectorEnabled() should return true when ACI connector has been specified, instead returned %t", enabled) + if enabled != enabledDefault { + t.Fatalf("KubernetesConfig.IsACIConnectorEnabled() should return default when ACI connector has been specified w/ no enabled value, expected %t, instead returned %t", enabledDefault, enabled) } + // Addon present and enabled b := true c = KubernetesConfig{ Addons: []KubernetesAddon{ @@ -1011,11 +1048,26 @@ func TestIsACIConnectorEnabled(t *testing.T) { } enabled = c.IsACIConnectorEnabled() if !enabled { + t.Fatalf("KubernetesConfig.IsACIConnectorEnabled() should return true when ACI connector addon has been specified as enabled, instead returned %t", enabled) + } + // Addon present and disabled + b = false + c = KubernetesConfig{ + Addons: []KubernetesAddon{ + { + Name: DefaultACIConnectorAddonName, + Enabled: &b, + }, + }, + } + enabled = c.IsACIConnectorEnabled() + if enabled { t.Fatalf("KubernetesConfig.IsACIConnectorEnabled() should return false when ACI connector addon has been specified as disabled, instead returned %t", enabled) } } func TestIsClusterAutoscalerEnabled(t *testing.T) { + // Default case c := KubernetesConfig{ Addons: []KubernetesAddon{ getMockAddon("addon"), @@ -1026,11 +1078,13 @@ func TestIsClusterAutoscalerEnabled(t *testing.T) { if enabled != enabledDefault { t.Fatalf("KubernetesConfig.IsClusterAutoscalerEnabled() should return %t when no cluster autoscaler addon has been specified, instead returned %t", enabledDefault, enabled) } + // Addon present, but enabled not specified c.Addons = append(c.Addons, getMockAddon(DefaultClusterAutoscalerAddonName)) enabled = c.IsClusterAutoscalerEnabled() - if enabled { - t.Fatalf("KubernetesConfig.IsClusterAutoscalerEnabled() should return true when cluster autoscaler has been specified, instead returned %t", enabled) + if enabled != enabledDefault { + t.Fatalf("KubernetesConfig.IsClusterAutoscalerEnabled() should return default when cluster autoscaler has been specified w/ no enabled value, expected %t, instead returned %t", enabledDefault, enabled) } + // Addon present and enabled b := true c = KubernetesConfig{ Addons: []KubernetesAddon{ @@ -1042,11 +1096,26 @@ func TestIsClusterAutoscalerEnabled(t *testing.T) { } enabled = c.IsClusterAutoscalerEnabled() if !enabled { + t.Fatalf("KubernetesConfig.IsClusterAutoscalerEnabled() should return true when cluster autoscaler addon has been specified as enabled, instead returned %t", enabled) + } + // Addon present and disabled + b = false + c = KubernetesConfig{ + Addons: []KubernetesAddon{ + { + Name: DefaultClusterAutoscalerAddonName, + Enabled: &b, + }, + }, + } + enabled = c.IsClusterAutoscalerEnabled() + if enabled { t.Fatalf("KubernetesConfig.IsClusterAutoscalerEnabled() should return false when cluster autoscaler addon has been specified as disabled, instead returned %t", enabled) } } func TestIsBlobfuseFlexVolumeEnabled(t *testing.T) { + // Default case c := KubernetesConfig{ Addons: []KubernetesAddon{ getMockAddon("addon"), @@ -1055,13 +1124,15 @@ func TestIsBlobfuseFlexVolumeEnabled(t *testing.T) { enabled := c.IsBlobfuseFlexVolumeEnabled() enabledDefault := DefaultBlobfuseFlexVolumeAddonEnabled if enabled != enabledDefault { - t.Fatalf("KubernetesConfig.IsBlobfuseFlexVolumeEnabled() should return %t when no blob fuse flex volume addon has been specified, instead returned %t", enabledDefault, enabled) + t.Fatalf("KubernetesConfig.IsBlobfuseFlexVolumeEnabled() should return %t when no blobfuse flexvolume addon has been specified, instead returned %t", enabledDefault, enabled) } + // Addon present, but enabled not specified c.Addons = append(c.Addons, getMockAddon(DefaultBlobfuseFlexVolumeAddonName)) enabled = c.IsBlobfuseFlexVolumeEnabled() - if !enabled { - t.Fatalf("KubernetesConfig.IsBlobfuseFlexVolumeEnabled() should return true when blob fuse flex volume has been specified, instead returned %t", enabled) + if enabled != enabledDefault { + t.Fatalf("KubernetesConfig.IsBlobfuseFlexVolumeEnabled() should return default when blobfuse flexvolume has been specified w/ no enabled value, expected %t, instead returned %t", enabledDefault, enabled) } + // Addon present and enabled b := true c = KubernetesConfig{ Addons: []KubernetesAddon{ @@ -1073,11 +1144,26 @@ func TestIsBlobfuseFlexVolumeEnabled(t *testing.T) { } enabled = c.IsBlobfuseFlexVolumeEnabled() if !enabled { - t.Fatalf("KubernetesConfig.IsBlobfuseFlexVolumeEnabled() should return false when blob fuse flex volume addon has been specified as disabled, instead returned %t", enabled) + t.Fatalf("KubernetesConfig.IsBlobfuseFlexVolumeEnabled() should return true when blobfuse flexvolume addon has been specified as enabled, instead returned %t", enabled) + } + // Addon present and disabled + b = false + c = KubernetesConfig{ + Addons: []KubernetesAddon{ + { + Name: DefaultBlobfuseFlexVolumeAddonName, + Enabled: &b, + }, + }, + } + enabled = c.IsBlobfuseFlexVolumeEnabled() + if enabled { + t.Fatalf("KubernetesConfig.IsBlobfuseFlexVolumeEnabled() should return false when blobfuse flexvolume addon has been specified as disabled, instead returned %t", enabled) } } func TestIsSMBFlexVolumeEnabled(t *testing.T) { + // Default case c := KubernetesConfig{ Addons: []KubernetesAddon{ getMockAddon("addon"), @@ -1086,13 +1172,15 @@ func TestIsSMBFlexVolumeEnabled(t *testing.T) { enabled := c.IsSMBFlexVolumeEnabled() enabledDefault := DefaultSMBFlexVolumeAddonEnabled if enabled != enabledDefault { - t.Fatalf("KubernetesConfig.IsSMBFlexVolumeEnabled() should return %t when no SMB flex volume addon has been specified, instead returned %t", enabledDefault, enabled) + t.Fatalf("KubernetesConfig.IsSMBFlexVolumeEnabled() should return %t when no SMB flexvolume addon has been specified, instead returned %t", enabledDefault, enabled) } + // Addon present, but enabled not specified c.Addons = append(c.Addons, getMockAddon(DefaultSMBFlexVolumeAddonName)) enabled = c.IsSMBFlexVolumeEnabled() - if !enabled { - t.Fatalf("KubernetesConfig.IsSMBFlexVolumeEnabled() should return true when SMB flex volume has been specified, instead returned %t", enabled) + if enabled != enabledDefault { + t.Fatalf("KubernetesConfig.IsSMBFlexVolumeEnabled() should return default when SMB flexvolume has been specified w/ no enabled value, expected %t, instead returned %t", enabledDefault, enabled) } + // Addon present and enabled b := true c = KubernetesConfig{ Addons: []KubernetesAddon{ @@ -1104,11 +1192,26 @@ func TestIsSMBFlexVolumeEnabled(t *testing.T) { } enabled = c.IsSMBFlexVolumeEnabled() if !enabled { - t.Fatalf("KubernetesConfig.IsSMBFlexVolumeEnabled() should return false when SMB flex volume addon has been specified as disabled, instead returned %t", enabled) + t.Fatalf("KubernetesConfig.IsSMBFlexVolumeEnabled() should return true when SMB flexvolume addon has been specified as enabled, instead returned %t", enabled) + } + // Addon present and disabled + b = false + c = KubernetesConfig{ + Addons: []KubernetesAddon{ + { + Name: DefaultSMBFlexVolumeAddonName, + Enabled: &b, + }, + }, + } + enabled = c.IsSMBFlexVolumeEnabled() + if enabled { + t.Fatalf("KubernetesConfig.IsSMBFlexVolumeEnabled() should return true when SMB flexvolume addon has been specified as enabled, instead returned %t", enabled) } } func TestIsKeyVaultFlexVolumeEnabled(t *testing.T) { + // Default case c := KubernetesConfig{ Addons: []KubernetesAddon{ getMockAddon("addon"), @@ -1117,14 +1220,30 @@ func TestIsKeyVaultFlexVolumeEnabled(t *testing.T) { enabled := c.IsKeyVaultFlexVolumeEnabled() enabledDefault := DefaultKeyVaultFlexVolumeAddonEnabled if enabled != enabledDefault { - t.Fatalf("KubernetesConfig.IsKeyVaultFlexVolumeEnabled() should return %t when no key vault flex volume addon has been specified, instead returned %t", enabledDefault, enabled) + t.Fatalf("KubernetesConfig.IsKeyVaultFlexVolumeEnabled() should return %t when no key vault flexvolume addon has been specified, instead returned %t", enabledDefault, enabled) } + // Addon present, but enabled not specified c.Addons = append(c.Addons, getMockAddon(DefaultKeyVaultFlexVolumeAddonName)) enabled = c.IsKeyVaultFlexVolumeEnabled() + if enabled != enabledDefault { + t.Fatalf("KubernetesConfig.IsKeyVaultFlexVolumeEnabled() should return default when no keyvault flexvolume has been specified w/ no enabled value, expected %t, instead returned %t", enabledDefault, enabled) + } + // Addon present and enabled + b := true + c = KubernetesConfig{ + Addons: []KubernetesAddon{ + { + Name: DefaultKeyVaultFlexVolumeAddonName, + Enabled: &b, + }, + }, + } + enabled = c.IsKeyVaultFlexVolumeEnabled() if !enabled { - t.Fatalf("KubernetesConfig.IsKeyVaultFlexVolumeEnabled() should return true when no keyvault flex volume has been specified, instead returned %t", enabled) + t.Fatalf("KubernetesConfig.IsKeyVaultFlexVolumeEnabled() should return true when keyvault flexvolume addon has been specified as enabled, instead returned %t", enabled) } - b := false + // Addon present and disabled + b = false c = KubernetesConfig{ Addons: []KubernetesAddon{ { @@ -1135,7 +1254,7 @@ func TestIsKeyVaultFlexVolumeEnabled(t *testing.T) { } enabled = c.IsKeyVaultFlexVolumeEnabled() if enabled { - t.Fatalf("KubernetesConfig.IsKeyVaultFlexVolumeEnabled() should return false when keyvault flex volume addon has been specified as disabled, instead returned %t", enabled) + t.Fatalf("KubernetesConfig.IsKeyVaultFlexVolumeEnabled() should return false when keyvault flexvolume addon has been specified as disabled, instead returned %t", enabled) } } From 76ca14fe43e483e23e7176d33f1ef1bdb37da258 Mon Sep 17 00:00:00 2001 From: Jack Francis Date: Tue, 20 Nov 2018 15:37:45 -0800 Subject: [PATCH 22/29] fix docker-health monitor syntax (#46) --- parts/k8s/health-monitor.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parts/k8s/health-monitor.sh b/parts/k8s/health-monitor.sh index 56315bcb2f..752f29254b 100755 --- a/parts/k8s/health-monitor.sh +++ b/parts/k8s/health-monitor.sh @@ -6,7 +6,7 @@ set -o nounset set -o pipefail -container_runtime_monitoring { +container_runtime_monitoring() { local -r max_attempts=5 local attempt=1 local -r crictl="${KUBE_HOME}/bin/crictl" @@ -38,7 +38,7 @@ container_runtime_monitoring { done } -kubelet_monitoring { +kubelet_monitoring() { echo "Wait for 2 minutes for kubelet to be functional" sleep 120 local -r max_seconds=10 From 9fa1c237323b6bf6276e77bde62b7ef25c42250f Mon Sep 17 00:00:00 2001 From: Cecile Robert-Michon Date: Wed, 21 Nov 2018 08:09:21 -0800 Subject: [PATCH 23/29] Add docker-engine feature flag for docker-engine w/ Ubuntu distro (#47) --- docs/clusterdefinition.md | 4 +- docs/kubernetes/gpu.md | 16 ++++++ packer/feature-flagged.sh | 18 ------ packer/install-dependencies.sh | 1 - packer/vhd-image-builder.json | 5 -- parts/k8s/kubernetesagentresourcesvmas.tmpl | 2 +- parts/k8s/kubernetesagentresourcesvmss.tmpl | 2 +- parts/k8s/kubernetesinstalls.sh | 24 +++++++- parts/k8s/kubernetesmasterresources.tmpl | 4 +- parts/k8s/kubernetesmasterresourcesvmss.tmpl | 4 +- parts/k8s/kubernetesmastervars.tmpl | 6 +- parts/k8s/kubernetesprovisionsource.sh | 3 +- pkg/api/converterfromapi.go | 1 + pkg/api/convertertoapi.go | 1 + pkg/api/types.go | 18 ++++++ pkg/api/types_test.go | 59 ++++++++++++++++++++ pkg/api/vlabs/types.go | 1 + pkg/engine/template_generator.go | 13 +---- 18 files changed, 133 insertions(+), 49 deletions(-) delete mode 100644 packer/feature-flagged.sh diff --git a/docs/clusterdefinition.md b/docs/clusterdefinition.md index 41d3ef1199..0e71cee73c 100644 --- a/docs/clusterdefinition.md +++ b/docs/clusterdefinition.md @@ -524,7 +524,7 @@ We consider `kubeletConfig`, `controllerManagerConfig`, `apiServerConfig`, and ` | vnetCidr | no | Specifies the VNET cidr when using a custom VNET ([bring your own VNET examples](../examples/vnet)). This VNET cidr should include both the master and the agent subnets. | | imageReference.name | no | The name of the Linux OS image. Needs to be used in conjunction with resourceGroup, below | | imageReference.resourceGroup | no | Resource group that contains the Linux OS image. Needs to be used in conjunction with name, above | -| distro | no | Select Master(s) Operating System (Linux only). Currently supported values are: `ubuntu`, `aks` and `coreos` (CoreOS support is currently experimental). Defaults to `aks` if undefined. `aks` is a custom image based on `ubuntu` that comes with pre-installed software necessary for Kubernetes deployments (Azure Public Cloud only for now). Currently supported OS and orchestrator configurations -- `ubuntu` and `aks`: Kubernetes; `coreos`: Kubernetes. [Example of CoreOS Master with CoreOS Agents](../examples/coreos/kubernetes-coreos.json) | +| distro | no | Specifies the masters' Linux distribution. Currently supported values are: `ubuntu`, `aks`, `aks-docker-engine` and `coreos` (CoreOS support is currently experimental - [Example of CoreOS Master with CoreOS Agents](../examples/coreos/kubernetes-coreos.json)). For Azure Public Cloud, defaults to `aks` if undefined, unless GPU nodes are present, in which case it will default to `aks-docker-engine`. For Sovereign Clouds, the default is `ubuntu`. `aks` is a custom image based on `ubuntu` that comes with pre-installed software necessary for Kubernetes deployments (Azure Public Cloud only for now). **NOTE**: GPU nodes are currently incompatible with the default Moby container runtime provided in the `aks` image. Clusters containing GPU nodes will be set to use the `aks-docker-engine` distro which is functionally equivalent to `aks` with the exception of the docker distribution (see [GPU support Walkthrough](kubernetes/gpu.md) for details). | | customFiles | no | The custom files to be provisioned to the master nodes. Defined as an array of json objects with each defined as `"source":"absolute-local-path", "dest":"absolute-path-on-masternodes"`.[See examples](../examples/customfiles) | | availabilityProfile | no | Supported values are `AvailabilitySet` (default) and `VirtualMachineScaleSets` (still under development: upgrade not supported; requires Kubernetes clusters version 1.10+ and agent pool availabilityProfile must also be `VirtualMachineScaleSets`). When MasterProfile is using `VirtualMachineScaleSets`, to SSH into a master node, you need to use `ssh -p 50001` instead of port 22. | | agentVnetSubnetId | only required when using custom VNET and when MasterProfile is using `VirtualMachineScaleSets` | Specifies the Id of an alternate VNET subnet for all the agent pool nodes. The subnet id must specify a valid VNET ID owned by the same subscription. ([bring your own VNET examples](../examples/vnet)). When MasterProfile is using `VirtualMachineScaleSets`, this value should be the subnetId of the subnet for all agent pool nodes. | @@ -553,7 +553,7 @@ A cluster can have 0 to 12 agent pool profiles. Agent Pool Profiles are used for | imageReference.name | no | The name of a a Linux OS image. Needs to be used in conjunction with resourceGroup, below | | imageReference.resourceGroup | no | Resource group that contains the Linux OS image. Needs to be used in conjunction with name, above | | osType | no | Specifies the agent pool's Operating System. Supported values are `Windows` and `Linux`. Defaults to `Linux` | -| distro | no | Specifies the agent pool's Linux distribution. Supported values are `ubuntu`, `aks` and `coreos` (CoreOS support is currently experimental). Defaults to `aks` if undefined, unless `osType` is defined as `Windows` (in which case `distro` is unused). `aks` is a custom image based on `ubuntu` that comes with pre-installed software necessary for Kubernetes deployments (Azure Public Cloud only for now). Currently supported OS and orchestrator configurations -- `ubuntu`: Kubernetes; `coreos`: Kubernetes. [Example of CoreOS Master with Windows and Linux (CoreOS and Ubuntu) Agents](../examples/coreos/kubernetes-coreos-hybrid.json) | +| distro | no | Specifies the agent pool's Linux distribution. Currently supported values are: `ubuntu`, `aks`, `aks-docker-engine` and `coreos` (CoreOS support is currently experimental - [Example of CoreOS Master with CoreOS Agents](../examples/coreos/kubernetes-coreos.json)). For Azure Public Cloud, defaults to `aks` if undefined, unless GPU nodes are present, in which case it will default to `aks-docker-engine`. For Sovereign Clouds, the default is `ubuntu`. `aks` is a custom image based on `ubuntu` that comes with pre-installed software necessary for Kubernetes deployments (Azure Public Cloud only for now). **NOTE**: GPU nodes are currently incompatible with the default Moby container runtime provided in the `aks` image. Clusters containing GPU nodes will be set to use the `aks-docker-engine` distro which is functionally equivalent to `aks` with the exception of the docker distribution (see [GPU support Walkthrough](kubernetes/gpu.md) for details). | | acceleratedNetworkingEnabled | no | Use [Azure Accelerated Networking](https://azure.microsoft.com/en-us/blog/maximize-your-vm-s-performance-with-accelerated-networking-now-generally-available-for-both-windows-and-linux/) feature for Linux agents (You must select a VM SKU that supports Accelerated Networking). Defaults to `true` if the VM SKU selected supports Accelerated Networking | | acceleratedNetworkingEnabledWindows | no | Use [Azure Accelerated Networking](https://azure.microsoft.com/en-us/blog/maximize-your-vm-s-performance-with-accelerated-networking-now-generally-available-for-both-windows-and-linux/) feature for Windows agents (You must select a VM SKU that supports Accelerated Networking). Defaults to `false` | diff --git a/docs/kubernetes/gpu.md b/docs/kubernetes/gpu.md index d36d941117..09621e6d35 100644 --- a/docs/kubernetes/gpu.md +++ b/docs/kubernetes/gpu.md @@ -94,3 +94,19 @@ spec: ``` We specify `nvidia.com/gpu: 1` or `alpha.kubernetes.io/nvidia-gpu: 1` in the resources limits. For v1.6 to v1.9 clusters, we need to mount the drivers from the host into the container. + +## Known incompatibilty with Moby + + GPU nodes are currently incompatible with the default Moby container runtime provided in the default `aks` image. Clusters containing GPU nodes will be set to use the `aks-docker-engine` distro by default which is functionally equivalent to `aks` with the exception of the docker distribution. + For users unable to use the `aks` OS image (eg. Sovereign Clouds), a workaround is provided to install Docker Engine instead of Moby. To use it, simply enable Docker Engine in your apimodel as follows: + + ```json +{ + "apiVersion": "vlabs", + "properties": { + "featureFlags": { + "dockerEngine": true + } + } +} + ``` \ No newline at end of file diff --git a/packer/feature-flagged.sh b/packer/feature-flagged.sh deleted file mode 100644 index bd1f991263..0000000000 --- a/packer/feature-flagged.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT license. - -function installDockerEngine() { - DOCKER_REPO="https://apt.dockerproject.org/repo" - DOCKER_ENGINE_VERSION="1.13.*" - dockerd --version - if [ $? -eq 0 ]; then - echo "dockerd is already installed, skipping download" - else - retrycmd_if_failure_no_stats 20 1 5 curl -fsSL https://aptdocker.azureedge.net/gpg > /tmp/aptdocker.gpg || exit $ERR_DOCKER_KEY_DOWNLOAD_TIMEOUT - retrycmd_if_failure 10 5 10 apt-key add /tmp/aptdocker.gpg || exit $ERR_DOCKER_APT_KEY_TIMEOUT - echo "deb ${DOCKER_REPO} ubuntu-xenial main" | sudo tee /etc/apt/sources.list.d/docker.list - printf "Package: docker-engine\nPin: version ${DOCKER_ENGINE_VERSION}\nPin-Priority: 550\n" > /etc/apt/preferences.d/docker.pref - fi -} \ No newline at end of file diff --git a/packer/install-dependencies.sh b/packer/install-dependencies.sh index 432f79e1d6..1922c11800 100644 --- a/packer/install-dependencies.sh +++ b/packer/install-dependencies.sh @@ -5,7 +5,6 @@ source /home/packer/provision_installs.sh source /home/packer/provision_source.sh -source /home/packer/feature-flagged.sh echo "Starting build on " `date` > /var/log/azure/golden-image-install.complete echo "Using kernel:" >> /var/log/azure/golden-image-install.complete diff --git a/packer/vhd-image-builder.json b/packer/vhd-image-builder.json index cb74e6db53..a063763e6a 100644 --- a/packer/vhd-image-builder.json +++ b/packer/vhd-image-builder.json @@ -63,11 +63,6 @@ "source": "packer/install-dependencies.sh", "destination": "/home/packer/install-dependencies.sh" }, - { - "type": "file", - "source": "packer/feature-flagged.sh", - "destination": "/home/packer/feature-flagged.sh" - }, { "type": "shell", "inline": [ diff --git a/parts/k8s/kubernetesagentresourcesvmas.tmpl b/parts/k8s/kubernetesagentresourcesvmas.tmpl index 843d0da877..0282987a09 100644 --- a/parts/k8s/kubernetesagentresourcesvmas.tmpl +++ b/parts/k8s/kubernetesagentresourcesvmas.tmpl @@ -295,7 +295,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $r); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not BlockOutboundInternet}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}gcr.azk8s.cn 80{{else}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' GPU_NODE={{IsNSeriesSKU .}} /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1{{if CSERunInBackground }} &{{end}}\"')]" + "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $r); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not (IsFeatureEnabled "BlockOutboundInternet")}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}gcr.azk8s.cn 80{{else}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' GPU_NODE={{IsNSeriesSKU .}} /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1{{if IsFeatureEnabled "CSERunInBackground" }} &{{end}}\"')]" } } } diff --git a/parts/k8s/kubernetesagentresourcesvmss.tmpl b/parts/k8s/kubernetesagentresourcesvmss.tmpl index 42c422373c..a22f855f3d 100644 --- a/parts/k8s/kubernetesagentresourcesvmss.tmpl +++ b/parts/k8s/kubernetesagentresourcesvmss.tmpl @@ -155,7 +155,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $r); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not BlockOutboundInternet}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}gcr.azk8s.cn 80{{else}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' GPU_NODE={{IsNSeriesSKU .}} /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1{{if CSERunInBackground }} &{{end}}\"')]" + "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $r); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not (IsFeatureEnabled "BlockOutboundInternet")}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}gcr.azk8s.cn 80{{else}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' GPU_NODE={{IsNSeriesSKU .}} /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1{{if IsFeatureEnabled "CSERunInBackground" }} &{{end}}\"')]" } } } diff --git a/parts/k8s/kubernetesinstalls.sh b/parts/k8s/kubernetesinstalls.sh index 14bb42b02f..0a8a663d4e 100755 --- a/parts/k8s/kubernetesinstalls.sh +++ b/parts/k8s/kubernetesinstalls.sh @@ -51,7 +51,11 @@ installGPUDrivers() { installContainerRuntime() { if [[ "$CONTAINER_RUNTIME" == "docker" ]]; then - installMoby + if [[ "$DOCKER_ENGINE" == "true" ]]; then + installDockerEngine + else + installMoby + fi elif [[ "$CONTAINER_RUNTIME" == "clear-containers" ]]; then # Ensure we can nest virtualization if grep -q vmx /proc/cpuinfo; then @@ -74,6 +78,22 @@ installMoby() { fi } +installDockerEngine() { + DOCKER_REPO="https://apt.dockerproject.org/repo" + DOCKER_ENGINE_VERSION="1.13.*" + dockerd --version + if [ $? -eq 0 ]; then + echo "dockerd is already installed, skipping download" + else + retrycmd_if_failure_no_stats 20 1 5 curl -fsSL https://aptdocker.azureedge.net/gpg > /tmp/aptdocker.gpg || exit $ERR_DOCKER_KEY_DOWNLOAD_TIMEOUT + retrycmd_if_failure 10 5 10 apt-key add /tmp/aptdocker.gpg || exit $ERR_DOCKER_APT_KEY_TIMEOUT + echo "deb ${DOCKER_REPO} ubuntu-xenial main" | sudo tee /etc/apt/sources.list.d/docker.list + printf "Package: docker-engine\nPin: version ${DOCKER_ENGINE_VERSION}\nPin-Priority: 550\n" > /etc/apt/preferences.d/docker.pref + apt_get_update || exit $ERR_APT_UPDATE_TIMEOUT + apt_get_install 20 30 120 docker-engine || exit $ERR_DOCKER_INSTALL_TIMEOUT + fi +} + installKataContainersRuntime() { # TODO incorporate this into packer CI so that it is pre-baked into the VHD image echo "Adding Kata Containers repository key..." @@ -214,7 +234,7 @@ installKubeletAndKubectl() { pullContainerImage() { CLI_TOOL=$1 DOCKER_IMAGE_URL=$2 - retrycmd_if_failure 60 1 1200 $CLI_TOOL pull $DOCKER_IMAGE_URL || exit $ERR_IMG_DOWNLOAD_TIMEOUT + retrycmd_if_failure 60 1 1200 $CLI_TOOL pull $DOCKER_IMAGE_URL || exit $ERR_CONTAINER_IMG_PULL_TIMEOUT } cleanUpContainerImages() { diff --git a/parts/k8s/kubernetesmasterresources.tmpl b/parts/k8s/kubernetesmasterresources.tmpl index 4d49925a9b..15657ae389 100644 --- a/parts/k8s/kubernetesmasterresources.tmpl +++ b/parts/k8s/kubernetesmasterresources.tmpl @@ -125,7 +125,7 @@ "sourcePortRange": "*" } } - {{if BlockOutboundInternet}} + {{if IsFeatureEnabled "BlockOutboundInternet"}} ,{ "name": "allow_vnet", "properties": { @@ -929,7 +929,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $r); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not BlockOutboundInternet}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}gcr.azk8s.cn 80{{else}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' ',variables('provisionScriptParametersMaster'), ' /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1\"')]" + "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $r); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not (IsFeatureEnabled "BlockOutboundInternet")}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}gcr.azk8s.cn 80{{else}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' ',variables('provisionScriptParametersMaster'), ' /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1\"')]" } } } diff --git a/parts/k8s/kubernetesmasterresourcesvmss.tmpl b/parts/k8s/kubernetesmasterresourcesvmss.tmpl index 85941287af..986fa2bf5a 100644 --- a/parts/k8s/kubernetesmasterresourcesvmss.tmpl +++ b/parts/k8s/kubernetesmasterresourcesvmss.tmpl @@ -100,7 +100,7 @@ "sourcePortRange": "*" } } - {{if BlockOutboundInternet}} + {{if IsFeatureEnabled "BlockOutboundInternet"}} ,{ "name": "allow_vnet", "properties": { @@ -461,7 +461,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $r); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not BlockOutboundInternet}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}gcr.azk8s.cn 80{{else}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' ',variables('provisionScriptParametersMaster'), ' /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1\"')]" + "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $r); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not (IsFeatureEnabled "BlockOutboundInternet")}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}gcr.azk8s.cn 80{{else}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' ',variables('provisionScriptParametersMaster'), ' /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1\"')]" } } } diff --git a/parts/k8s/kubernetesmastervars.tmpl b/parts/k8s/kubernetesmastervars.tmpl index 149d1129d7..6217f5b19e 100644 --- a/parts/k8s/kubernetesmastervars.tmpl +++ b/parts/k8s/kubernetesmastervars.tmpl @@ -131,12 +131,12 @@ "customSearchDomainsScript": "{{GetKubernetesB64CustomSearchDomainsScript}}", "sshdConfig": "{{GetB64sshdConfig}}", "systemConf": "{{GetB64systemConf}}", - "provisionScriptParametersCommon": "[concat('ADMINUSER=',parameters('linuxAdminUsername'),' ETCD_DOWNLOAD_URL=',parameters('etcdDownloadURLBase'),' ETCD_VERSION=',parameters('etcdVersion'),' TENANT_ID=',variables('tenantID'),' KUBERNETES_VERSION={{.OrchestratorProfile.OrchestratorVersion}} HYPERKUBE_URL=',parameters('kubernetesHyperkubeSpec'),' APISERVER_PUBLIC_KEY=',parameters('apiserverCertificate'),' SUBSCRIPTION_ID=',variables('subscriptionId'),' RESOURCE_GROUP=',variables('resourceGroup'),' LOCATION=',variables('location'),' VM_TYPE=',variables('vmType'),' SUBNET=',variables('subnetName'),' NETWORK_SECURITY_GROUP=',variables('nsgName'),' VIRTUAL_NETWORK=',variables('virtualNetworkName'),' VIRTUAL_NETWORK_RESOURCE_GROUP=',variables('virtualNetworkResourceGroupName'),' ROUTE_TABLE=',variables('routeTableName'),' PRIMARY_AVAILABILITY_SET=',variables('primaryAvailabilitySetName'),' PRIMARY_SCALE_SET=',variables('primaryScaleSetName'),' SERVICE_PRINCIPAL_CLIENT_ID=',variables('servicePrincipalClientId'),' SERVICE_PRINCIPAL_CLIENT_SECRET=',variables('singleQuote'),variables('servicePrincipalClientSecret'),variables('singleQuote'),' KUBELET_PRIVATE_KEY=',parameters('clientPrivateKey'),' TARGET_ENVIRONMENT=',parameters('targetEnvironment'),' NETWORK_PLUGIN=',parameters('networkPlugin'),' NETWORK_POLICY=',parameters('networkPolicy'),' VNET_CNI_PLUGINS_URL=',parameters('vnetCniLinuxPluginsURL'),' CNI_PLUGINS_URL=',parameters('cniPluginsURL'),' CLOUDPROVIDER_BACKOFF=',toLower(string(parameters('cloudproviderConfig').cloudProviderBackoff)),' CLOUDPROVIDER_BACKOFF_RETRIES=',parameters('cloudproviderConfig').cloudProviderBackoffRetries,' CLOUDPROVIDER_BACKOFF_EXPONENT=',parameters('cloudproviderConfig').cloudProviderBackoffExponent,' CLOUDPROVIDER_BACKOFF_DURATION=',parameters('cloudproviderConfig').cloudProviderBackoffDuration,' CLOUDPROVIDER_BACKOFF_JITTER=',parameters('cloudproviderConfig').cloudProviderBackoffJitter,' CLOUDPROVIDER_RATELIMIT=',toLower(string(parameters('cloudproviderConfig').cloudProviderRatelimit)),' CLOUDPROVIDER_RATELIMIT_QPS=',parameters('cloudproviderConfig').cloudProviderRatelimitQPS,' CLOUDPROVIDER_RATELIMIT_BUCKET=',parameters('cloudproviderConfig').cloudProviderRatelimitBucket,' USE_MANAGED_IDENTITY_EXTENSION=',variables('useManagedIdentityExtension'),' USER_ASSIGNED_IDENTITY_ID=',variables('userAssignedClientID'),' USE_INSTANCE_METADATA=',variables('useInstanceMetadata'),' LOAD_BALANCER_SKU=',variables('loadBalancerSku'),' EXCLUDE_MASTER_FROM_STANDARD_LB=',variables('excludeMasterFromStandardLB'),' CONTAINER_RUNTIME=',parameters('containerRuntime'),' CONTAINERD_DOWNLOAD_URL_BASE=',parameters('containerdDownloadURLBase'),' POD_INFRA_CONTAINER_SPEC=',parameters('kubernetesPodInfraContainerSpec'),' KMS_PROVIDER_VAULT_NAME=',variables('clusterKeyVaultName'),' IS_HOSTED_MASTER={{IsHostedMaster}}')]", + "provisionScriptParametersCommon": "[concat('ADMINUSER=',parameters('linuxAdminUsername'),' ETCD_DOWNLOAD_URL=',parameters('etcdDownloadURLBase'),' ETCD_VERSION=',parameters('etcdVersion'),' TENANT_ID=',variables('tenantID'),' KUBERNETES_VERSION={{.OrchestratorProfile.OrchestratorVersion}} HYPERKUBE_URL=',parameters('kubernetesHyperkubeSpec'),' APISERVER_PUBLIC_KEY=',parameters('apiserverCertificate'),' SUBSCRIPTION_ID=',variables('subscriptionId'),' RESOURCE_GROUP=',variables('resourceGroup'),' LOCATION=',variables('location'),' VM_TYPE=',variables('vmType'),' SUBNET=',variables('subnetName'),' NETWORK_SECURITY_GROUP=',variables('nsgName'),' VIRTUAL_NETWORK=',variables('virtualNetworkName'),' VIRTUAL_NETWORK_RESOURCE_GROUP=',variables('virtualNetworkResourceGroupName'),' ROUTE_TABLE=',variables('routeTableName'),' PRIMARY_AVAILABILITY_SET=',variables('primaryAvailabilitySetName'),' PRIMARY_SCALE_SET=',variables('primaryScaleSetName'),' SERVICE_PRINCIPAL_CLIENT_ID=',variables('servicePrincipalClientId'),' SERVICE_PRINCIPAL_CLIENT_SECRET=',variables('singleQuote'),variables('servicePrincipalClientSecret'),variables('singleQuote'),' KUBELET_PRIVATE_KEY=',parameters('clientPrivateKey'),' TARGET_ENVIRONMENT=',parameters('targetEnvironment'),' NETWORK_PLUGIN=',parameters('networkPlugin'),' NETWORK_POLICY=',parameters('networkPolicy'),' VNET_CNI_PLUGINS_URL=',parameters('vnetCniLinuxPluginsURL'),' CNI_PLUGINS_URL=',parameters('cniPluginsURL'),' CLOUDPROVIDER_BACKOFF=',toLower(string(parameters('cloudproviderConfig').cloudProviderBackoff)),' CLOUDPROVIDER_BACKOFF_RETRIES=',parameters('cloudproviderConfig').cloudProviderBackoffRetries,' CLOUDPROVIDER_BACKOFF_EXPONENT=',parameters('cloudproviderConfig').cloudProviderBackoffExponent,' CLOUDPROVIDER_BACKOFF_DURATION=',parameters('cloudproviderConfig').cloudProviderBackoffDuration,' CLOUDPROVIDER_BACKOFF_JITTER=',parameters('cloudproviderConfig').cloudProviderBackoffJitter,' CLOUDPROVIDER_RATELIMIT=',toLower(string(parameters('cloudproviderConfig').cloudProviderRatelimit)),' CLOUDPROVIDER_RATELIMIT_QPS=',parameters('cloudproviderConfig').cloudProviderRatelimitQPS,' CLOUDPROVIDER_RATELIMIT_BUCKET=',parameters('cloudproviderConfig').cloudProviderRatelimitBucket,' USE_MANAGED_IDENTITY_EXTENSION=',variables('useManagedIdentityExtension'),' USER_ASSIGNED_IDENTITY_ID=',variables('userAssignedClientID'),' USE_INSTANCE_METADATA=',variables('useInstanceMetadata'),' LOAD_BALANCER_SKU=',variables('loadBalancerSku'),' EXCLUDE_MASTER_FROM_STANDARD_LB=',variables('excludeMasterFromStandardLB'),' CONTAINER_RUNTIME=',parameters('containerRuntime'),' CONTAINERD_DOWNLOAD_URL_BASE=',parameters('containerdDownloadURLBase'),' POD_INFRA_CONTAINER_SPEC=',parameters('kubernetesPodInfraContainerSpec'),' KMS_PROVIDER_VAULT_NAME=',variables('clusterKeyVaultName'),' IS_HOSTED_MASTER={{IsHostedMaster}}',' DOCKER_ENGINE={{IsFeatureEnabled "DockerEngine"}}')]", {{if not IsHostedMaster}} {{if IsMasterVirtualMachineScaleSets}} - "provisionScriptParametersMaster": "[concat('MASTER_NODE=true NO_OUTBOUND={{BlockOutboundInternet}} CLUSTER_AUTOSCALER_ADDON=',parameters('kubernetesClusterAutoscalerEnabled'),' ACI_CONNECTOR_ADDON=',parameters('kubernetesACIConnectorEnabled'),' APISERVER_PRIVATE_KEY=',parameters('apiServerPrivateKey'),' CA_CERTIFICATE=',parameters('caCertificate'),' CA_PRIVATE_KEY=',parameters('caPrivateKey'),' MASTER_FQDN=',variables('masterFqdnPrefix'),' KUBECONFIG_CERTIFICATE=',parameters('kubeConfigCertificate'),' KUBECONFIG_KEY=',parameters('kubeConfigPrivateKey'),' ETCD_SERVER_CERTIFICATE=',parameters('etcdServerCertificate'),' ETCD_CLIENT_CERTIFICATE=',parameters('etcdClientCertificate'),' ETCD_SERVER_PRIVATE_KEY=',parameters('etcdServerPrivateKey'),' ETCD_CLIENT_PRIVATE_KEY=',parameters('etcdClientPrivateKey'),' ETCD_PEER_CERTIFICATES=',string(variables('etcdPeerCertificates')),' ETCD_PEER_PRIVATE_KEYS=',string(variables('etcdPeerPrivateKeys')),' ENABLE_AGGREGATED_APIS=',string(parameters('enableAggregatedAPIs')),' KUBECONFIG_SERVER=',variables('kubeconfigServer'))]", + "provisionScriptParametersMaster": "[concat('MASTER_NODE=true NO_OUTBOUND={{IsFeatureEnabled "BlockOutboundInternet"}} CLUSTER_AUTOSCALER_ADDON=',parameters('kubernetesClusterAutoscalerEnabled'),' ACI_CONNECTOR_ADDON=',parameters('kubernetesACIConnectorEnabled'),' APISERVER_PRIVATE_KEY=',parameters('apiServerPrivateKey'),' CA_CERTIFICATE=',parameters('caCertificate'),' CA_PRIVATE_KEY=',parameters('caPrivateKey'),' MASTER_FQDN=',variables('masterFqdnPrefix'),' KUBECONFIG_CERTIFICATE=',parameters('kubeConfigCertificate'),' KUBECONFIG_KEY=',parameters('kubeConfigPrivateKey'),' ETCD_SERVER_CERTIFICATE=',parameters('etcdServerCertificate'),' ETCD_CLIENT_CERTIFICATE=',parameters('etcdClientCertificate'),' ETCD_SERVER_PRIVATE_KEY=',parameters('etcdServerPrivateKey'),' ETCD_CLIENT_PRIVATE_KEY=',parameters('etcdClientPrivateKey'),' ETCD_PEER_CERTIFICATES=',string(variables('etcdPeerCertificates')),' ETCD_PEER_PRIVATE_KEYS=',string(variables('etcdPeerPrivateKeys')),' ENABLE_AGGREGATED_APIS=',string(parameters('enableAggregatedAPIs')),' KUBECONFIG_SERVER=',variables('kubeconfigServer'))]", {{else}} - "provisionScriptParametersMaster": "[concat('MASTER_VM_NAME=',variables('masterVMNames')[variables('masterOffset')],' ETCD_PEER_URL=',variables('masterEtcdPeerURLs')[variables('masterOffset')],' ETCD_CLIENT_URL=',variables('masterEtcdClientURLs')[variables('masterOffset')],' MASTER_NODE=true NO_OUTBOUND={{BlockOutboundInternet}} CLUSTER_AUTOSCALER_ADDON=',parameters('kubernetesClusterAutoscalerEnabled'),' ACI_CONNECTOR_ADDON=',parameters('kubernetesACIConnectorEnabled'),' APISERVER_PRIVATE_KEY=',parameters('apiServerPrivateKey'),' CA_CERTIFICATE=',parameters('caCertificate'),' CA_PRIVATE_KEY=',parameters('caPrivateKey'),' MASTER_FQDN=',variables('masterFqdnPrefix'),' KUBECONFIG_CERTIFICATE=',parameters('kubeConfigCertificate'),' KUBECONFIG_KEY=',parameters('kubeConfigPrivateKey'),' ETCD_SERVER_CERTIFICATE=',parameters('etcdServerCertificate'),' ETCD_CLIENT_CERTIFICATE=',parameters('etcdClientCertificate'),' ETCD_SERVER_PRIVATE_KEY=',parameters('etcdServerPrivateKey'),' ETCD_CLIENT_PRIVATE_KEY=',parameters('etcdClientPrivateKey'),' ETCD_PEER_CERTIFICATES=',string(variables('etcdPeerCertificates')),' ETCD_PEER_PRIVATE_KEYS=',string(variables('etcdPeerPrivateKeys')),' ENABLE_AGGREGATED_APIS=',string(parameters('enableAggregatedAPIs')),' KUBECONFIG_SERVER=',variables('kubeconfigServer'))]", + "provisionScriptParametersMaster": "[concat('MASTER_VM_NAME=',variables('masterVMNames')[variables('masterOffset')],' ETCD_PEER_URL=',variables('masterEtcdPeerURLs')[variables('masterOffset')],' ETCD_CLIENT_URL=',variables('masterEtcdClientURLs')[variables('masterOffset')],' MASTER_NODE=true NO_OUTBOUND={{IsFeatureEnabled "BlockOutboundInternet"}} CLUSTER_AUTOSCALER_ADDON=',parameters('kubernetesClusterAutoscalerEnabled'),' ACI_CONNECTOR_ADDON=',parameters('kubernetesACIConnectorEnabled'),' APISERVER_PRIVATE_KEY=',parameters('apiServerPrivateKey'),' CA_CERTIFICATE=',parameters('caCertificate'),' CA_PRIVATE_KEY=',parameters('caPrivateKey'),' MASTER_FQDN=',variables('masterFqdnPrefix'),' KUBECONFIG_CERTIFICATE=',parameters('kubeConfigCertificate'),' KUBECONFIG_KEY=',parameters('kubeConfigPrivateKey'),' ETCD_SERVER_CERTIFICATE=',parameters('etcdServerCertificate'),' ETCD_CLIENT_CERTIFICATE=',parameters('etcdClientCertificate'),' ETCD_SERVER_PRIVATE_KEY=',parameters('etcdServerPrivateKey'),' ETCD_CLIENT_PRIVATE_KEY=',parameters('etcdClientPrivateKey'),' ETCD_PEER_CERTIFICATES=',string(variables('etcdPeerCertificates')),' ETCD_PEER_PRIVATE_KEYS=',string(variables('etcdPeerPrivateKeys')),' ENABLE_AGGREGATED_APIS=',string(parameters('enableAggregatedAPIs')),' KUBECONFIG_SERVER=',variables('kubeconfigServer'))]", {{end}} {{end}} "generateProxyCertsScript": "{{GetKubernetesB64GenerateProxyCerts}}", diff --git a/parts/k8s/kubernetesprovisionsource.sh b/parts/k8s/kubernetesprovisionsource.sh index 48d3fa71c5..eaaaf3ee29 100755 --- a/parts/k8s/kubernetesprovisionsource.sh +++ b/parts/k8s/kubernetesprovisionsource.sh @@ -24,8 +24,9 @@ ERR_MOBY_INSTALL_TIMEOUT=27 # Timeout waiting for moby install ERR_K8S_RUNNING_TIMEOUT=30 # Timeout waiting for k8s cluster to be healthy ERR_K8S_DOWNLOAD_TIMEOUT=31 # Timeout waiting for Kubernetes download(s) ERR_KUBECTL_NOT_FOUND=32 # kubectl client binary not found on local disk -ERR_KUBELET_START_FAIL=34 # kubelet could not be started by systemctl ERR_IMG_DOWNLOAD_TIMEOUT=33 # Timeout waiting for img download +ERR_KUBELET_START_FAIL=34 # kubelet could not be started by systemctl +ERR_CONTAINER_IMG_PULL_TIMEOUT=35 # Timeout trying to pull a container image ERR_CNI_DOWNLOAD_TIMEOUT=41 # Timeout waiting for CNI download(s) ERR_MS_PROD_DEB_DOWNLOAD_TIMEOUT=42 # Timeout waiting for https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb ERR_MS_PROD_DEB_PKG_ADD_FAIL=43 # Failed to add repo pkg file diff --git a/pkg/api/converterfromapi.go b/pkg/api/converterfromapi.go index 9158e352cc..a3dfa62be9 100644 --- a/pkg/api/converterfromapi.go +++ b/pkg/api/converterfromapi.go @@ -923,4 +923,5 @@ func convertAzProfileToVLabs(api *AzProfile, vlabs *vlabs.AzProfile) { func convertFeatureFlagsToVLabs(api *FeatureFlags, vlabs *vlabs.FeatureFlags) { vlabs.EnableCSERunInBackground = api.EnableCSERunInBackground vlabs.BlockOutboundInternet = api.BlockOutboundInternet + vlabs.DockerEngine = api.DockerEngine } diff --git a/pkg/api/convertertoapi.go b/pkg/api/convertertoapi.go index d19de23a98..577bedf1b3 100644 --- a/pkg/api/convertertoapi.go +++ b/pkg/api/convertertoapi.go @@ -346,6 +346,7 @@ func convertVLabsAZProfile(vlabs *vlabs.AzProfile, api *AzProfile) { func convertVLabsFeatureFlags(vlabs *vlabs.FeatureFlags, api *FeatureFlags) { api.EnableCSERunInBackground = vlabs.EnableCSERunInBackground api.BlockOutboundInternet = vlabs.BlockOutboundInternet + api.DockerEngine = vlabs.DockerEngine } func convertV20160930LinuxProfile(obj *v20160930.LinuxProfile, api *LinuxProfile) { diff --git a/pkg/api/types.go b/pkg/api/types.go index 6e5be74783..4268d61af2 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -104,6 +104,7 @@ type AzProfile struct { type FeatureFlags struct { EnableCSERunInBackground bool `json:"enableCSERunInBackground,omitempty"` BlockOutboundInternet bool `json:"blockOutboundInternet,omitempty"` + DockerEngine bool `json:"dockerEngine,omitempty"` } // ServicePrincipalProfile contains the client and secret used by the cluster for Azure Resource CRUD @@ -1313,6 +1314,23 @@ func (k *KubernetesConfig) GetAzureCNIURLWindows(cloudSpecConfig AzureEnvironmen return cloudSpecConfig.KubernetesSpecConfig.VnetCNIWindowsPluginsDownloadURL } +// IsFeatureEnabled returns true if a feature flag is on for the provided feature +func (f *FeatureFlags) IsFeatureEnabled(feature string) bool { + if f != nil { + switch feature { + case "CSERunInBackground": + return f.EnableCSERunInBackground + case "BlockOutboundInternet": + return f.BlockOutboundInternet + case "DockerEngine": + return f.DockerEngine + default: + return false + } + } + return false +} + //GetCloudSpecConfig returns the Kubernetes container images URL configurations based on the deploy target environment. //for example: if the target is the public azure, then the default container image url should be k8s.gcr.io/... //if the target is azure china, then the default container image should be mirror.azure.cn:5000/google_container/... diff --git a/pkg/api/types_test.go b/pkg/api/types_test.go index 356e32b113..11f422e2fc 100644 --- a/pkg/api/types_test.go +++ b/pkg/api/types_test.go @@ -2626,3 +2626,62 @@ func TestProperties_GetMasterVMPrefix(t *testing.T) { t.Errorf("expected master VM prefix %s, but got %s", expected, actual) } } + +func TestIsFeatureEnabled(t *testing.T) { + tests := []struct { + name string + feature string + flags *FeatureFlags + expected bool + }{ + { + name: "nil flags", + feature: "DockerEngine", + flags: nil, + expected: false, + }, + { + name: "empty flags", + feature: "DockerEngine", + flags: &FeatureFlags{}, + expected: false, + }, + { + name: "Enabled feature", + feature: "CSERunInBackground", + flags: &FeatureFlags{ + EnableCSERunInBackground: true, + DockerEngine: false, + }, + expected: true, + }, + { + name: "Disabled feature", + feature: "DockerEngine", + flags: &FeatureFlags{ + EnableCSERunInBackground: true, + DockerEngine: false, + }, + expected: false, + }, + { + name: "Non-existent feature", + feature: "Foo", + flags: &FeatureFlags{ + EnableCSERunInBackground: true, + DockerEngine: true, + }, + expected: false, + }, + } + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + t.Parallel() + actual := test.flags.IsFeatureEnabled(test.feature) + if actual != test.expected { + t.Errorf("expected feature %s to be enabled:%v, but got %v", test.feature, test.expected, actual) + } + }) + } +} diff --git a/pkg/api/vlabs/types.go b/pkg/api/vlabs/types.go index 63ddc0ec39..df5bc45810 100644 --- a/pkg/api/vlabs/types.go +++ b/pkg/api/vlabs/types.go @@ -61,6 +61,7 @@ type AzProfile struct { type FeatureFlags struct { EnableCSERunInBackground bool `json:"enableCSERunInBackground,omitempty"` BlockOutboundInternet bool `json:"blockOutboundInternet,omitempty"` + DockerEngine bool `json:"dockerEngine,omitempty"` } // ServicePrincipalProfile contains the client and secret used by the cluster for Azure Resource CRUD diff --git a/pkg/engine/template_generator.go b/pkg/engine/template_generator.go index 3bb07d55dc..b5742de97b 100644 --- a/pkg/engine/template_generator.go +++ b/pkg/engine/template_generator.go @@ -385,17 +385,8 @@ func (t *TemplateGenerator) getTemplateFuncMap(cs *api.ContainerService) templat "IsHostedBootstrap": func() bool { return false }, - "CSERunInBackground": func() bool { - if cs.Properties.FeatureFlags != nil { - return cs.Properties.FeatureFlags.EnableCSERunInBackground - } - return false - }, - "BlockOutboundInternet": func() bool { - if cs.Properties.FeatureFlags != nil { - return cs.Properties.FeatureFlags.BlockOutboundInternet - } - return false + "IsFeatureEnabled": func(feature string) bool { + return cs.Properties.FeatureFlags.IsFeatureEnabled(feature) }, "GetMasterAllowedSizes": func() string { return helpers.GetKubernetesAllowedSizes() From 994fcd0921e73656a93fd602e14b547646d79036 Mon Sep 17 00:00:00 2001 From: Jack Francis Date: Wed, 21 Nov 2018 08:41:42 -0800 Subject: [PATCH 24/29] E2E: rationalize node check + kube-system check, no kms (#33) --- .circleci/config.yml | 8 ++++---- test/e2e/engine/template.go | 3 +++ test/e2e/kubernetes/kubernetes_test.go | 26 ++++++++------------------ test/e2e/kubernetes/node/node.go | 12 ++++++++++-- test/e2e/runner/cli_provisioner.go | 3 +++ 5 files changed, 28 insertions(+), 24 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4db9d3116d..6cfbf4521d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -69,7 +69,7 @@ jobs: echo 'export ORCHESTRATOR_RELEASE=1.10' >> $BASH_ENV echo 'export CLUSTER_DEFINITION=examples/e2e-tests/kubernetes/release/default/definition.json' >> $BASH_ENV echo 'export CREATE_VNET=true' >> $BASH_ENV - echo 'export ENABLE_KMS_ENCRYPTION=true' >> $BASH_ENV + echo 'export ENABLE_KMS_ENCRYPTION=false' >> $BASH_ENV echo 'export CLEANUP_ON_EXIT=${CLEANUP_ON_EXIT}' >> $BASH_ENV echo 'export CLEANUP_IF_FAIL=${CLEANUP_IF_FAIL_LINUX}' >> $BASH_ENV echo 'export RETAIN_SSH=false' >> $BASH_ENV @@ -95,7 +95,7 @@ jobs: echo 'export ORCHESTRATOR_RELEASE=1.11' >> $BASH_ENV echo 'export CLUSTER_DEFINITION=examples/e2e-tests/kubernetes/release/default/definition.json' >> $BASH_ENV echo 'export CREATE_VNET=true' >> $BASH_ENV - echo 'export ENABLE_KMS_ENCRYPTION=true' >> $BASH_ENV + echo 'export ENABLE_KMS_ENCRYPTION=false' >> $BASH_ENV echo 'export CLEANUP_ON_EXIT=${CLEANUP_ON_EXIT}' >> $BASH_ENV echo 'export CLEANUP_IF_FAIL=${CLEANUP_IF_FAIL_LINUX}' >> $BASH_ENV echo 'export RETAIN_SSH=false' >> $BASH_ENV @@ -121,7 +121,7 @@ jobs: echo 'export ORCHESTRATOR_RELEASE=1.12' >> $BASH_ENV echo 'export CLUSTER_DEFINITION=examples/e2e-tests/kubernetes/release/default/definition.json' >> $BASH_ENV echo 'export CREATE_VNET=true' >> $BASH_ENV - echo 'export ENABLE_KMS_ENCRYPTION=true' >> $BASH_ENV + echo 'export ENABLE_KMS_ENCRYPTION=false' >> $BASH_ENV echo 'export CLEANUP_ON_EXIT=${CLEANUP_ON_EXIT}' >> $BASH_ENV echo 'export CLEANUP_IF_FAIL=${CLEANUP_IF_FAIL_LINUX}' >> $BASH_ENV echo 'export RETAIN_SSH=false' >> $BASH_ENV @@ -147,7 +147,7 @@ jobs: echo 'export ORCHESTRATOR_RELEASE=1.13' >> $BASH_ENV echo 'export CLUSTER_DEFINITION=examples/e2e-tests/kubernetes/release/default/definition.json' >> $BASH_ENV echo 'export CREATE_VNET=true' >> $BASH_ENV - echo 'export ENABLE_KMS_ENCRYPTION=true' >> $BASH_ENV + echo 'export ENABLE_KMS_ENCRYPTION=false' >> $BASH_ENV echo 'export CLEANUP_ON_EXIT=${CLEANUP_ON_EXIT}' >> $BASH_ENV echo 'export CLEANUP_IF_FAIL=${CLEANUP_IF_FAIL_LINUX}' >> $BASH_ENV echo 'export RETAIN_SSH=false' >> $BASH_ENV diff --git a/test/e2e/engine/template.go b/test/e2e/engine/template.go index 2f87017235..562dcb1359 100644 --- a/test/e2e/engine/template.go +++ b/test/e2e/engine/template.go @@ -150,6 +150,9 @@ func Build(cfg *config.Config, masterSubnetID string, agentSubnetID string, isVM } if config.EnableKMSEncryption && config.ClientObjectID != "" { + if prop.OrchestratorProfile.KubernetesConfig == nil { + prop.OrchestratorProfile.KubernetesConfig = &vlabs.KubernetesConfig{} + } prop.OrchestratorProfile.KubernetesConfig.EnableEncryptionWithExternalKms = &config.EnableKMSEncryption prop.ServicePrincipalProfile.ObjectID = config.ClientObjectID } diff --git a/test/e2e/kubernetes/kubernetes_test.go b/test/e2e/kubernetes/kubernetes_test.go index 347d100987..f15da757f6 100644 --- a/test/e2e/kubernetes/kubernetes_test.go +++ b/test/e2e/kubernetes/kubernetes_test.go @@ -142,25 +142,15 @@ var _ = Describe("Azure Container Cluster using the Kubernetes Orchestrator", fu } }) - It("should have have the appropriate node count", func() { - var nodeList *node.List - var err error - // Allow ten mins for node count to converge, in the case where we're running this test immediately after a scale operation - for i := 0; i < 60; i++ { - nodeList, err = node.Get() - if err != nil { - log.Printf("Error while getting nodes: %s\n", err) - } - if nodeList != nil && len(nodeList.Nodes) == eng.NodeCount() { - break - } else { - log.Printf("Got %d nodes, expected %d\n", len(nodeList.Nodes), eng.NodeCount()) - } - // Wait a minute before proceeding to create a new job w/ the same name - time.Sleep(10 * time.Second) + It("should report all nodes in a Ready state", func() { + ready := node.WaitOnReady(eng.NodeCount(), 10*time.Second, cfg.Timeout) + cmd := exec.Command("kubectl", "get", "nodes", "-o", "wide") + out, _ := cmd.CombinedOutput() + log.Printf("%s\n", out) + if !ready { + log.Printf("Error: Not all nodes in a healthy state\n") } - Expect(nodeList).NotTo(BeNil()) - Expect(len(nodeList.Nodes)).To(Equal(eng.NodeCount())) + Expect(ready).To(Equal(true)) }) It("should have DNS pod running", func() { diff --git a/test/e2e/kubernetes/node/node.go b/test/e2e/kubernetes/node/node.go index d9616dc10c..e619d92be6 100644 --- a/test/e2e/kubernetes/node/node.go +++ b/test/e2e/kubernetes/node/node.go @@ -74,14 +74,22 @@ type List struct { // AreAllReady returns a bool depending on cluster state func AreAllReady(nodeCount int) bool { list, _ := Get() + var ready int if list != nil && len(list.Nodes) == nodeCount { for _, node := range list.Nodes { + nodeReady := false for _, condition := range node.Status.Conditions { - if condition.Type == "KubeletReady" && condition.Status == "false" { - return false + if condition.Type == "Ready" && condition.Status == "True" { + ready++ + nodeReady = true } } + if !nodeReady { + return false + } } + } + if ready == nodeCount { return true } return false diff --git a/test/e2e/runner/cli_provisioner.go b/test/e2e/runner/cli_provisioner.go index ea85d7e3d5..bc0a9674c8 100644 --- a/test/e2e/runner/cli_provisioner.go +++ b/test/e2e/runner/cli_provisioner.go @@ -255,6 +255,9 @@ func (cli *CLIProvisioner) waitForNodes() error { if !cli.IsPrivate() { log.Println("Waiting on nodes to go into ready state...") ready := node.WaitOnReady(cli.Engine.NodeCount(), 10*time.Second, cli.Config.Timeout) + cmd := exec.Command("kubectl", "get", "nodes", "-o", "wide") + out, _ := cmd.CombinedOutput() + log.Printf("%s\n", out) if !ready { return errors.New("Error: Not all nodes in a healthy state") } From 0c22bba7658f2d700fe4d59d2c87d245f13b697b Mon Sep 17 00:00:00 2001 From: Tariq Ibrahim Date: Wed, 21 Nov 2018 10:22:16 -0800 Subject: [PATCH 25/29] update tiller versions in the recent versions of kubernetes (#50) --- pkg/api/defaults_test.go | 2 +- pkg/api/k8s_versions.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/api/defaults_test.go b/pkg/api/defaults_test.go index 0206b76060..a2b32d81e0 100644 --- a/pkg/api/defaults_test.go +++ b/pkg/api/defaults_test.go @@ -186,7 +186,7 @@ func TestAddonsIndexByName(t *testing.T) { func TestAssignDefaultAddonImages(t *testing.T) { addonNameMap := map[string]string{ - DefaultTillerAddonName: "gcr.io/kubernetes-helm/tiller:v2.8.1", + DefaultTillerAddonName: "gcr.io/kubernetes-helm/tiller:v2.11.0", DefaultACIConnectorAddonName: "microsoft/virtual-kubelet:latest", DefaultClusterAutoscalerAddonName: "k8s.gcr.io/cluster-autoscaler:v1.2.2", DefaultBlobfuseFlexVolumeAddonName: "mcr.microsoft.com/k8s/flexvolume/blobfuse-flexvolume", diff --git a/pkg/api/k8s_versions.go b/pkg/api/k8s_versions.go index 61b6022a1a..6d906575fe 100644 --- a/pkg/api/k8s_versions.go +++ b/pkg/api/k8s_versions.go @@ -25,7 +25,7 @@ var k8sComponentVersions = map[string]map[string]string{ "addon-manager": "kube-addon-manager-amd64:v8.8", "dnsmasq": "k8s-dns-dnsmasq-nanny-amd64:1.14.10", "pause": "pause-amd64:3.1", - "tiller": "tiller:v2.8.1", + "tiller": "tiller:v2.11.0", "rescheduler": "rescheduler:v0.4.0", "aci-connector": "virtual-kubelet:latest", ContainerMonitoringAddonName: "oms:ciprod10162018-2", @@ -58,7 +58,7 @@ var k8sComponentVersions = map[string]map[string]string{ "addon-manager": "kube-addon-manager-amd64:v8.7", "dnsmasq": "k8s-dns-dnsmasq-nanny-amd64:1.14.10", "pause": "pause-amd64:3.1", - "tiller": "tiller:v2.8.1", + "tiller": "tiller:v2.11.0", "rescheduler": "rescheduler:v0.4.0", "aci-connector": "virtual-kubelet:latest", ContainerMonitoringAddonName: "oms:ciprod10162018-2", @@ -90,7 +90,7 @@ var k8sComponentVersions = map[string]map[string]string{ "addon-manager": "kube-addon-manager-amd64:v8.6", "dnsmasq": "k8s-dns-dnsmasq-nanny-amd64:1.14.10", "pause": "pause-amd64:3.1", - "tiller": "tiller:v2.8.1", + "tiller": "tiller:v2.11.0", "rescheduler": "rescheduler:v0.4.0", "aci-connector": "virtual-kubelet:latest", ContainerMonitoringAddonName: "oms:ciprod10162018-2", @@ -122,7 +122,7 @@ var k8sComponentVersions = map[string]map[string]string{ "addon-manager": "kube-addon-manager-amd64:v8.6", "dnsmasq": "k8s-dns-dnsmasq-nanny-amd64:1.14.8", "pause": "pause-amd64:3.1", - "tiller": "tiller:v2.8.1", + "tiller": "tiller:v2.11.0", "rescheduler": "rescheduler:v0.3.1", "aci-connector": "virtual-kubelet:latest", ContainerMonitoringAddonName: "oms:ciprod10162018-2", From c00deb2b72da06e8d7ef75a511442ef8a87d1677 Mon Sep 17 00:00:00 2001 From: Jack Francis Date: Wed, 21 Nov 2018 11:10:28 -0800 Subject: [PATCH 26/29] Replace docker engine feature flag by existing cloud spec (#51) --- parts/k8s/kubernetescustomscript.sh | 13 ++++++------- parts/k8s/kubernetesinstalls.sh | 5 ++--- parts/k8s/kubernetesmastervars.tmpl | 2 +- parts/k8s/kubernetesparams.tmpl | 7 +++++++ pkg/api/converterfromapi.go | 1 - pkg/api/convertertoapi.go | 1 - pkg/api/types.go | 3 --- pkg/api/types_test.go | 9 ++------- pkg/api/vlabs/types.go | 1 - pkg/engine/params_k8s.go | 7 +++++++ 10 files changed, 25 insertions(+), 24 deletions(-) diff --git a/parts/k8s/kubernetescustomscript.sh b/parts/k8s/kubernetescustomscript.sh index efa97c100a..4ec1cd0697 100755 --- a/parts/k8s/kubernetescustomscript.sh +++ b/parts/k8s/kubernetescustomscript.sh @@ -73,6 +73,12 @@ fi installContainerRuntime installNetworkPlugin installContainerd +if [[ "${GPU_NODE}" = true ]]; then + if $FULL_INSTALL_REQUIRED; then + installGPUDrivers + fi + ensureGPUDrivers +fi installKubeletAndKubectl ensureRPC createKubeManifestDir @@ -122,13 +128,6 @@ if [[ ! -z "${MASTER_NODE}" ]]; then ensurePodSecurityPolicy fi -if [[ "${GPU_NODE}" = true ]]; then - if $FULL_INSTALL_REQUIRED; then - installGPUDrivers - fi - ensureGPUDrivers -fi - if $FULL_INSTALL_REQUIRED; then if [[ $OS == $UBUNTU_OS_NAME ]]; then # mitigation for bug https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1676635 diff --git a/parts/k8s/kubernetesinstalls.sh b/parts/k8s/kubernetesinstalls.sh index 0a8a663d4e..8cb76ff2b0 100755 --- a/parts/k8s/kubernetesinstalls.sh +++ b/parts/k8s/kubernetesinstalls.sh @@ -51,7 +51,7 @@ installGPUDrivers() { installContainerRuntime() { if [[ "$CONTAINER_RUNTIME" == "docker" ]]; then - if [[ "$DOCKER_ENGINE" == "true" ]]; then + if [[ "$DOCKER_ENGINE_REPO" != "" ]]; then installDockerEngine else installMoby @@ -79,7 +79,6 @@ installMoby() { } installDockerEngine() { - DOCKER_REPO="https://apt.dockerproject.org/repo" DOCKER_ENGINE_VERSION="1.13.*" dockerd --version if [ $? -eq 0 ]; then @@ -87,7 +86,7 @@ installDockerEngine() { else retrycmd_if_failure_no_stats 20 1 5 curl -fsSL https://aptdocker.azureedge.net/gpg > /tmp/aptdocker.gpg || exit $ERR_DOCKER_KEY_DOWNLOAD_TIMEOUT retrycmd_if_failure 10 5 10 apt-key add /tmp/aptdocker.gpg || exit $ERR_DOCKER_APT_KEY_TIMEOUT - echo "deb ${DOCKER_REPO} ubuntu-xenial main" | sudo tee /etc/apt/sources.list.d/docker.list + echo "deb ${DOCKER_ENGINE_REPO} ubuntu-xenial main" | sudo tee /etc/apt/sources.list.d/docker.list printf "Package: docker-engine\nPin: version ${DOCKER_ENGINE_VERSION}\nPin-Priority: 550\n" > /etc/apt/preferences.d/docker.pref apt_get_update || exit $ERR_APT_UPDATE_TIMEOUT apt_get_install 20 30 120 docker-engine || exit $ERR_DOCKER_INSTALL_TIMEOUT diff --git a/parts/k8s/kubernetesmastervars.tmpl b/parts/k8s/kubernetesmastervars.tmpl index 6217f5b19e..2c67468965 100644 --- a/parts/k8s/kubernetesmastervars.tmpl +++ b/parts/k8s/kubernetesmastervars.tmpl @@ -131,7 +131,7 @@ "customSearchDomainsScript": "{{GetKubernetesB64CustomSearchDomainsScript}}", "sshdConfig": "{{GetB64sshdConfig}}", "systemConf": "{{GetB64systemConf}}", - "provisionScriptParametersCommon": "[concat('ADMINUSER=',parameters('linuxAdminUsername'),' ETCD_DOWNLOAD_URL=',parameters('etcdDownloadURLBase'),' ETCD_VERSION=',parameters('etcdVersion'),' TENANT_ID=',variables('tenantID'),' KUBERNETES_VERSION={{.OrchestratorProfile.OrchestratorVersion}} HYPERKUBE_URL=',parameters('kubernetesHyperkubeSpec'),' APISERVER_PUBLIC_KEY=',parameters('apiserverCertificate'),' SUBSCRIPTION_ID=',variables('subscriptionId'),' RESOURCE_GROUP=',variables('resourceGroup'),' LOCATION=',variables('location'),' VM_TYPE=',variables('vmType'),' SUBNET=',variables('subnetName'),' NETWORK_SECURITY_GROUP=',variables('nsgName'),' VIRTUAL_NETWORK=',variables('virtualNetworkName'),' VIRTUAL_NETWORK_RESOURCE_GROUP=',variables('virtualNetworkResourceGroupName'),' ROUTE_TABLE=',variables('routeTableName'),' PRIMARY_AVAILABILITY_SET=',variables('primaryAvailabilitySetName'),' PRIMARY_SCALE_SET=',variables('primaryScaleSetName'),' SERVICE_PRINCIPAL_CLIENT_ID=',variables('servicePrincipalClientId'),' SERVICE_PRINCIPAL_CLIENT_SECRET=',variables('singleQuote'),variables('servicePrincipalClientSecret'),variables('singleQuote'),' KUBELET_PRIVATE_KEY=',parameters('clientPrivateKey'),' TARGET_ENVIRONMENT=',parameters('targetEnvironment'),' NETWORK_PLUGIN=',parameters('networkPlugin'),' NETWORK_POLICY=',parameters('networkPolicy'),' VNET_CNI_PLUGINS_URL=',parameters('vnetCniLinuxPluginsURL'),' CNI_PLUGINS_URL=',parameters('cniPluginsURL'),' CLOUDPROVIDER_BACKOFF=',toLower(string(parameters('cloudproviderConfig').cloudProviderBackoff)),' CLOUDPROVIDER_BACKOFF_RETRIES=',parameters('cloudproviderConfig').cloudProviderBackoffRetries,' CLOUDPROVIDER_BACKOFF_EXPONENT=',parameters('cloudproviderConfig').cloudProviderBackoffExponent,' CLOUDPROVIDER_BACKOFF_DURATION=',parameters('cloudproviderConfig').cloudProviderBackoffDuration,' CLOUDPROVIDER_BACKOFF_JITTER=',parameters('cloudproviderConfig').cloudProviderBackoffJitter,' CLOUDPROVIDER_RATELIMIT=',toLower(string(parameters('cloudproviderConfig').cloudProviderRatelimit)),' CLOUDPROVIDER_RATELIMIT_QPS=',parameters('cloudproviderConfig').cloudProviderRatelimitQPS,' CLOUDPROVIDER_RATELIMIT_BUCKET=',parameters('cloudproviderConfig').cloudProviderRatelimitBucket,' USE_MANAGED_IDENTITY_EXTENSION=',variables('useManagedIdentityExtension'),' USER_ASSIGNED_IDENTITY_ID=',variables('userAssignedClientID'),' USE_INSTANCE_METADATA=',variables('useInstanceMetadata'),' LOAD_BALANCER_SKU=',variables('loadBalancerSku'),' EXCLUDE_MASTER_FROM_STANDARD_LB=',variables('excludeMasterFromStandardLB'),' CONTAINER_RUNTIME=',parameters('containerRuntime'),' CONTAINERD_DOWNLOAD_URL_BASE=',parameters('containerdDownloadURLBase'),' POD_INFRA_CONTAINER_SPEC=',parameters('kubernetesPodInfraContainerSpec'),' KMS_PROVIDER_VAULT_NAME=',variables('clusterKeyVaultName'),' IS_HOSTED_MASTER={{IsHostedMaster}}',' DOCKER_ENGINE={{IsFeatureEnabled "DockerEngine"}}')]", + "provisionScriptParametersCommon": "[concat('ADMINUSER=',parameters('linuxAdminUsername'),' ETCD_DOWNLOAD_URL=',parameters('etcdDownloadURLBase'),' ETCD_VERSION=',parameters('etcdVersion'),' DOCKER_ENGINE_REPO=',parameters('dockerEngineDownloadRepo'),' TENANT_ID=',variables('tenantID'),' KUBERNETES_VERSION={{.OrchestratorProfile.OrchestratorVersion}} HYPERKUBE_URL=',parameters('kubernetesHyperkubeSpec'),' APISERVER_PUBLIC_KEY=',parameters('apiserverCertificate'),' SUBSCRIPTION_ID=',variables('subscriptionId'),' RESOURCE_GROUP=',variables('resourceGroup'),' LOCATION=',variables('location'),' VM_TYPE=',variables('vmType'),' SUBNET=',variables('subnetName'),' NETWORK_SECURITY_GROUP=',variables('nsgName'),' VIRTUAL_NETWORK=',variables('virtualNetworkName'),' VIRTUAL_NETWORK_RESOURCE_GROUP=',variables('virtualNetworkResourceGroupName'),' ROUTE_TABLE=',variables('routeTableName'),' PRIMARY_AVAILABILITY_SET=',variables('primaryAvailabilitySetName'),' PRIMARY_SCALE_SET=',variables('primaryScaleSetName'),' SERVICE_PRINCIPAL_CLIENT_ID=',variables('servicePrincipalClientId'),' SERVICE_PRINCIPAL_CLIENT_SECRET=',variables('singleQuote'),variables('servicePrincipalClientSecret'),variables('singleQuote'),' KUBELET_PRIVATE_KEY=',parameters('clientPrivateKey'),' TARGET_ENVIRONMENT=',parameters('targetEnvironment'),' NETWORK_PLUGIN=',parameters('networkPlugin'),' NETWORK_POLICY=',parameters('networkPolicy'),' VNET_CNI_PLUGINS_URL=',parameters('vnetCniLinuxPluginsURL'),' CNI_PLUGINS_URL=',parameters('cniPluginsURL'),' CLOUDPROVIDER_BACKOFF=',toLower(string(parameters('cloudproviderConfig').cloudProviderBackoff)),' CLOUDPROVIDER_BACKOFF_RETRIES=',parameters('cloudproviderConfig').cloudProviderBackoffRetries,' CLOUDPROVIDER_BACKOFF_EXPONENT=',parameters('cloudproviderConfig').cloudProviderBackoffExponent,' CLOUDPROVIDER_BACKOFF_DURATION=',parameters('cloudproviderConfig').cloudProviderBackoffDuration,' CLOUDPROVIDER_BACKOFF_JITTER=',parameters('cloudproviderConfig').cloudProviderBackoffJitter,' CLOUDPROVIDER_RATELIMIT=',toLower(string(parameters('cloudproviderConfig').cloudProviderRatelimit)),' CLOUDPROVIDER_RATELIMIT_QPS=',parameters('cloudproviderConfig').cloudProviderRatelimitQPS,' CLOUDPROVIDER_RATELIMIT_BUCKET=',parameters('cloudproviderConfig').cloudProviderRatelimitBucket,' USE_MANAGED_IDENTITY_EXTENSION=',variables('useManagedIdentityExtension'),' USER_ASSIGNED_IDENTITY_ID=',variables('userAssignedClientID'),' USE_INSTANCE_METADATA=',variables('useInstanceMetadata'),' LOAD_BALANCER_SKU=',variables('loadBalancerSku'),' EXCLUDE_MASTER_FROM_STANDARD_LB=',variables('excludeMasterFromStandardLB'),' CONTAINER_RUNTIME=',parameters('containerRuntime'),' CONTAINERD_DOWNLOAD_URL_BASE=',parameters('containerdDownloadURLBase'),' POD_INFRA_CONTAINER_SPEC=',parameters('kubernetesPodInfraContainerSpec'),' KMS_PROVIDER_VAULT_NAME=',variables('clusterKeyVaultName'),' IS_HOSTED_MASTER={{IsHostedMaster}}')]", {{if not IsHostedMaster}} {{if IsMasterVirtualMachineScaleSets}} "provisionScriptParametersMaster": "[concat('MASTER_NODE=true NO_OUTBOUND={{IsFeatureEnabled "BlockOutboundInternet"}} CLUSTER_AUTOSCALER_ADDON=',parameters('kubernetesClusterAutoscalerEnabled'),' ACI_CONNECTOR_ADDON=',parameters('kubernetesACIConnectorEnabled'),' APISERVER_PRIVATE_KEY=',parameters('apiServerPrivateKey'),' CA_CERTIFICATE=',parameters('caCertificate'),' CA_PRIVATE_KEY=',parameters('caPrivateKey'),' MASTER_FQDN=',variables('masterFqdnPrefix'),' KUBECONFIG_CERTIFICATE=',parameters('kubeConfigCertificate'),' KUBECONFIG_KEY=',parameters('kubeConfigPrivateKey'),' ETCD_SERVER_CERTIFICATE=',parameters('etcdServerCertificate'),' ETCD_CLIENT_CERTIFICATE=',parameters('etcdClientCertificate'),' ETCD_SERVER_PRIVATE_KEY=',parameters('etcdServerPrivateKey'),' ETCD_CLIENT_PRIVATE_KEY=',parameters('etcdClientPrivateKey'),' ETCD_PEER_CERTIFICATES=',string(variables('etcdPeerCertificates')),' ETCD_PEER_PRIVATE_KEYS=',string(variables('etcdPeerPrivateKeys')),' ENABLE_AGGREGATED_APIS=',string(parameters('enableAggregatedAPIs')),' KUBECONFIG_SERVER=',variables('kubeconfigServer'))]", diff --git a/parts/k8s/kubernetesparams.tmpl b/parts/k8s/kubernetesparams.tmpl index dd51dc0ee6..d3cefa6331 100644 --- a/parts/k8s/kubernetesparams.tmpl +++ b/parts/k8s/kubernetesparams.tmpl @@ -324,6 +324,13 @@ "type": "string" }, {{end}} + "dockerEngineDownloadRepo": { + "defaultValue": "https://aptdocker.azureedge.net/repo", + "metadata": { + "description": "The Docker Engine download URL for Kubernetes." + }, + "type": "string" + }, "networkPolicy": { "defaultValue": "{{.OrchestratorProfile.KubernetesConfig.NetworkPolicy}}", "metadata": { diff --git a/pkg/api/converterfromapi.go b/pkg/api/converterfromapi.go index a3dfa62be9..9158e352cc 100644 --- a/pkg/api/converterfromapi.go +++ b/pkg/api/converterfromapi.go @@ -923,5 +923,4 @@ func convertAzProfileToVLabs(api *AzProfile, vlabs *vlabs.AzProfile) { func convertFeatureFlagsToVLabs(api *FeatureFlags, vlabs *vlabs.FeatureFlags) { vlabs.EnableCSERunInBackground = api.EnableCSERunInBackground vlabs.BlockOutboundInternet = api.BlockOutboundInternet - vlabs.DockerEngine = api.DockerEngine } diff --git a/pkg/api/convertertoapi.go b/pkg/api/convertertoapi.go index 577bedf1b3..d19de23a98 100644 --- a/pkg/api/convertertoapi.go +++ b/pkg/api/convertertoapi.go @@ -346,7 +346,6 @@ func convertVLabsAZProfile(vlabs *vlabs.AzProfile, api *AzProfile) { func convertVLabsFeatureFlags(vlabs *vlabs.FeatureFlags, api *FeatureFlags) { api.EnableCSERunInBackground = vlabs.EnableCSERunInBackground api.BlockOutboundInternet = vlabs.BlockOutboundInternet - api.DockerEngine = vlabs.DockerEngine } func convertV20160930LinuxProfile(obj *v20160930.LinuxProfile, api *LinuxProfile) { diff --git a/pkg/api/types.go b/pkg/api/types.go index 4268d61af2..6666a43464 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -104,7 +104,6 @@ type AzProfile struct { type FeatureFlags struct { EnableCSERunInBackground bool `json:"enableCSERunInBackground,omitempty"` BlockOutboundInternet bool `json:"blockOutboundInternet,omitempty"` - DockerEngine bool `json:"dockerEngine,omitempty"` } // ServicePrincipalProfile contains the client and secret used by the cluster for Azure Resource CRUD @@ -1322,8 +1321,6 @@ func (f *FeatureFlags) IsFeatureEnabled(feature string) bool { return f.EnableCSERunInBackground case "BlockOutboundInternet": return f.BlockOutboundInternet - case "DockerEngine": - return f.DockerEngine default: return false } diff --git a/pkg/api/types_test.go b/pkg/api/types_test.go index 11f422e2fc..8b03306e15 100644 --- a/pkg/api/types_test.go +++ b/pkg/api/types_test.go @@ -2636,13 +2636,11 @@ func TestIsFeatureEnabled(t *testing.T) { }{ { name: "nil flags", - feature: "DockerEngine", flags: nil, expected: false, }, { name: "empty flags", - feature: "DockerEngine", flags: &FeatureFlags{}, expected: false, }, @@ -2651,16 +2649,14 @@ func TestIsFeatureEnabled(t *testing.T) { feature: "CSERunInBackground", flags: &FeatureFlags{ EnableCSERunInBackground: true, - DockerEngine: false, }, expected: true, }, { name: "Disabled feature", - feature: "DockerEngine", + feature: "CSERunInBackground", flags: &FeatureFlags{ - EnableCSERunInBackground: true, - DockerEngine: false, + EnableCSERunInBackground: false, }, expected: false, }, @@ -2669,7 +2665,6 @@ func TestIsFeatureEnabled(t *testing.T) { feature: "Foo", flags: &FeatureFlags{ EnableCSERunInBackground: true, - DockerEngine: true, }, expected: false, }, diff --git a/pkg/api/vlabs/types.go b/pkg/api/vlabs/types.go index df5bc45810..63ddc0ec39 100644 --- a/pkg/api/vlabs/types.go +++ b/pkg/api/vlabs/types.go @@ -61,7 +61,6 @@ type AzProfile struct { type FeatureFlags struct { EnableCSERunInBackground bool `json:"enableCSERunInBackground,omitempty"` BlockOutboundInternet bool `json:"blockOutboundInternet,omitempty"` - DockerEngine bool `json:"dockerEngine,omitempty"` } // ServicePrincipalProfile contains the client and secret used by the cluster for Azure Resource CRUD diff --git a/pkg/engine/params_k8s.go b/pkg/engine/params_k8s.go index 7cc8292e2e..3234b99f98 100644 --- a/pkg/engine/params_k8s.go +++ b/pkg/engine/params_k8s.go @@ -228,6 +228,13 @@ func assignKubernetesParameters(properties *api.Properties, parametersMap params addValue(parametersMap, "kubernetesEndpoint", properties.HostedMasterProfile.FQDN) } + // GPU nodes need docker-engine as the container runtime + if properties.HasNSeriesSKU() { + addValue(parametersMap, "dockerEngineDownloadRepo", cloudSpecConfig.DockerSpecConfig.DockerEngineRepo) + } else { + addValue(parametersMap, "dockerEngineDownloadRepo", "") + } + if properties.AADProfile != nil { addValue(parametersMap, "aadTenantId", properties.AADProfile.TenantID) if properties.AADProfile.AdminGroupID != "" { From e08f7ee818aa71f74d29e0858f0c9900ec0d03e9 Mon Sep 17 00:00:00 2001 From: Cecile Robert-Michon Date: Wed, 21 Nov 2018 11:11:17 -0800 Subject: [PATCH 27/29] [docs] Remove docker-engine feature flag docs (#52) --- docs/kubernetes/gpu.md | 14 +------------- pkg/engine/params_k8s_test.go | 2 +- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/docs/kubernetes/gpu.md b/docs/kubernetes/gpu.md index 09621e6d35..4dbc233077 100644 --- a/docs/kubernetes/gpu.md +++ b/docs/kubernetes/gpu.md @@ -97,16 +97,4 @@ We specify `nvidia.com/gpu: 1` or `alpha.kubernetes.io/nvidia-gpu: 1` in the res ## Known incompatibilty with Moby - GPU nodes are currently incompatible with the default Moby container runtime provided in the default `aks` image. Clusters containing GPU nodes will be set to use the `aks-docker-engine` distro by default which is functionally equivalent to `aks` with the exception of the docker distribution. - For users unable to use the `aks` OS image (eg. Sovereign Clouds), a workaround is provided to install Docker Engine instead of Moby. To use it, simply enable Docker Engine in your apimodel as follows: - - ```json -{ - "apiVersion": "vlabs", - "properties": { - "featureFlags": { - "dockerEngine": true - } - } -} - ``` \ No newline at end of file + GPU nodes are currently incompatible with the default Moby container runtime provided in the default `aks` image. Clusters containing GPU nodes will be set to use Docker Engine instead of Moby. \ No newline at end of file diff --git a/pkg/engine/params_k8s_test.go b/pkg/engine/params_k8s_test.go index e7b23ac3cf..1c65db9b43 100644 --- a/pkg/engine/params_k8s_test.go +++ b/pkg/engine/params_k8s_test.go @@ -37,7 +37,7 @@ func TestAssignKubernetesParameters(t *testing.T) { } parametersMap := paramsMap{} - containerService.Location = "eatsus" + containerService.Location = "eastus" cloudSpecConfig := containerService.GetCloudSpecConfig() containerService.SetPropertiesDefaults(false, false) assignKubernetesParameters(containerService.Properties, parametersMap, cloudSpecConfig, DefaultGeneratorCode) From 849178a350376c23001522255b1c0b32aae9d523 Mon Sep 17 00:00:00 2001 From: Jack Francis Date: Wed, 21 Nov 2018 12:00:33 -0800 Subject: [PATCH 28/29] enable iis scaling test --- test/e2e/kubernetes/deployment/deployment.go | 11 ++++ test/e2e/kubernetes/kubernetes_test.go | 67 ++++++++++++++++++-- 2 files changed, 73 insertions(+), 5 deletions(-) diff --git a/test/e2e/kubernetes/deployment/deployment.go b/test/e2e/kubernetes/deployment/deployment.go index a126637dff..6a52b00936 100644 --- a/test/e2e/kubernetes/deployment/deployment.go +++ b/test/e2e/kubernetes/deployment/deployment.go @@ -190,6 +190,17 @@ func (d *Deployment) Expose(svcType string, targetPort, exposedPort int) error { return nil } +// ScaleDeployment scales a deployment to n instancees +func (d *Deployment) ScaleDeployment(n int) error { + cmd := exec.Command("kubectl", "scale", fmt.Sprintf("--replicas=%d", n), "deployment", d.Metadata.Name) + out, err := util.RunAndLogCommand(cmd) + if err != nil { + log.Printf("Error while scaling deployment %s to %d pods:%s\n", d.Metadata.Name, n, string(out)) + return err + } + return nil +} + // CreateDeploymentHPA applies autoscale characteristics to deployment func (d *Deployment) CreateDeploymentHPA(cpuPercent, min, max int) error { cmd := exec.Command("kubectl", "autoscale", "deployment", d.Metadata.Name, fmt.Sprintf("--cpu-percent=%d", cpuPercent), diff --git a/test/e2e/kubernetes/kubernetes_test.go b/test/e2e/kubernetes/kubernetes_test.go index f15da757f6..13d645109f 100644 --- a/test/e2e/kubernetes/kubernetes_test.go +++ b/test/e2e/kubernetes/kubernetes_test.go @@ -971,8 +971,7 @@ var _ = Describe("Azure Container Cluster using the Kubernetes Orchestrator", fu }) }) - Describe("with a windows agent pool", func() { - It("should be able to deploy an iis webserver", func() { + It("should be able to deploy and scale an iis webserver", func() { if eng.HasWindowsAgents() { iisImage := "microsoft/iis:windowsservercore-1803" // BUG: This should be set based on the host OS version @@ -990,11 +989,11 @@ var _ = Describe("Azure Container Cluster using the Kubernetes Orchestrator", fu By("Exposing a LoadBalancer for the pod") err = iisDeploy.Expose("LoadBalancer", 80, 80) Expect(err).NotTo(HaveOccurred()) - s, err := service.Get(deploymentName, "default") + iisService, err := service.Get(deploymentName, "default") Expect(err).NotTo(HaveOccurred()) By("Verifying that the service is reachable and returns the default IIS start page") - valid := s.Validate("(IIS Windows Server)", 10, 10*time.Second, cfg.Timeout) + valid := iisService.Validate("(IIS Windows Server)", 10, 10*time.Second, cfg.Timeout) Expect(valid).To(BeTrue()) By("Checking that each pod can reach http://www.bing.com") @@ -1007,10 +1006,68 @@ var _ = Describe("Azure Container Cluster using the Kubernetes Orchestrator", fu Expect(pass).To(BeTrue()) } + By("Scaling deployment to 5 pods") + err = iisDeploy.ScaleDeployment(5) + Expect(err).NotTo(HaveOccurred()) + _, err = iisDeploy.WaitForReplicas(5, 5, 2*time.Second, cfg.Timeout) + Expect(err).NotTo(HaveOccurred()) + + By("Waiting on 5 pods to be Ready") + running, err = pod.WaitOnReady(deploymentName, "default", 3, 30*time.Second, cfg.Timeout) + Expect(err).NotTo(HaveOccurred()) + Expect(running).To(Equal(true)) + iisPods, err = iisDeploy.Pods() + Expect(err).NotTo(HaveOccurred()) + Expect(len(iisPods)).To(Equal(5)) + + By("Verifying that the service is reachable and returns the default IIS start page") + valid = iisService.Validate("(IIS Windows Server)", 10, 10*time.Second, cfg.Timeout) + Expect(valid).To(BeTrue()) + + By("Checking that each pod can reach http://www.bing.com") + iisPods, err = iisDeploy.Pods() + Expect(err).NotTo(HaveOccurred()) + Expect(len(iisPods)).ToNot(BeZero()) + for _, iisPod := range iisPods { + pass, err := iisPod.CheckWindowsOutboundConnection("www.bing.com", 10*time.Second, cfg.Timeout) + Expect(err).NotTo(HaveOccurred()) + Expect(pass).To(BeTrue()) + } + + By("Checking that no pods restart") + for _, iisPod := range iisPods { + log.Printf("Checking %s", iisPod.Metadata.Name) + Expect(iisPod.Status.ContainerStatuses[0].Ready).To(BeTrue()) + Expect(iisPod.Status.ContainerStatuses[0].RestartCount).To(Equal(0)) + } + + By("Scaling deployment to 2 pods") + err = iisDeploy.ScaleDeployment(2) + Expect(err).NotTo(HaveOccurred()) + _, err = iisDeploy.WaitForReplicas(2, 2, 2*time.Second, cfg.Timeout) + Expect(err).NotTo(HaveOccurred()) + iisPods, err = iisDeploy.Pods() + Expect(err).NotTo(HaveOccurred()) + Expect(len(iisPods)).To(Equal(2)) + + By("Verifying that the service is reachable and returns the default IIS start page") + valid = iisService.Validate("(IIS Windows Server)", 10, 10*time.Second, cfg.Timeout) + Expect(valid).To(BeTrue()) + + By("Checking that each pod can reach http://www.bing.com") + iisPods, err = iisDeploy.Pods() + Expect(err).NotTo(HaveOccurred()) + Expect(len(iisPods)).ToNot(BeZero()) + for _, iisPod := range iisPods { + pass, err := iisPod.CheckWindowsOutboundConnection("www.bing.com", 10*time.Second, cfg.Timeout) + Expect(err).NotTo(HaveOccurred()) + Expect(pass).To(BeTrue()) + } + By("Verifying pods & services can be deleted") err = iisDeploy.Delete(deleteResourceRetries) Expect(err).NotTo(HaveOccurred()) - err = s.Delete(deleteResourceRetries) + err = iisService.Delete(deleteResourceRetries) Expect(err).NotTo(HaveOccurred()) } else { Skip("No windows agent was provisioned for this Cluster Definition") From 5fd05aeae7968aa8c129f7af6dca1222ae7f500e Mon Sep 17 00:00:00 2001 From: Jack Francis Date: Wed, 21 Nov 2018 12:03:58 -0800 Subject: [PATCH 29/29] copy pasta --- test/e2e/kubernetes/kubernetes_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/test/e2e/kubernetes/kubernetes_test.go b/test/e2e/kubernetes/kubernetes_test.go index 13d645109f..446e2d3249 100644 --- a/test/e2e/kubernetes/kubernetes_test.go +++ b/test/e2e/kubernetes/kubernetes_test.go @@ -971,6 +971,7 @@ var _ = Describe("Azure Container Cluster using the Kubernetes Orchestrator", fu }) }) + Describe("with a windows agent pool", func() { It("should be able to deploy and scale an iis webserver", func() { if eng.HasWindowsAgents() { iisImage := "microsoft/iis:windowsservercore-1803" // BUG: This should be set based on the host OS version

    D?H3j&3VEz5cR+wIU}Mul&#hWSU>1OJKW1Hc}3 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 z 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 folder -* Run `acs-engine generate --api-model _output//apimodel.json`. This wil update the `azuredeploy*` files needed for the new ARM deployment. These files are also located in the `_output` folder. +* Run `aks-engine generate --api-model _output//apimodel.json`. This wil update the `azuredeploy*` files needed for the new ARM deployment. These files are also located in the `_output` folder. * Apply the changes by manually starting an ARM deployment. From within the `_output/` run az group deployment create --template-file azuredeploy.json --parameters azuredeploy.parameters.json --resource-group "" To use the `az` CLI tools you have to login. More info can be found here: https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli?view=azure-cli-latest - _Note: I use `az group deployment` instead of `acs-engine deploy` because the latter seems to assume you are deploying a new cluster and as a result overwriting you private ssh keys located in the _ouput folder_ + _Note: I use `az group deployment` instead of `aks-engine deploy` because the latter seems to assume you are deploying a new cluster and as a result overwriting you private ssh keys located in the _ouput folder_ * Grab a coffee * Profit! @@ -34,9 +34,9 @@ Add (or copy) an entry in the `agentPoolProfiles` array. ### Resizing a node pool -Use the `acs-engine scale` command +Use the `aks-engine scale` command - acs-engine scale --location westeurope --subscription-id "xxx" --resource-group " --node-pool --new-node-count --master-FQDN **Remember to also update your original api-model.json file (used for 1st deployment) or else you would end up with the original number of VM's after using the `generate` command described above** diff --git a/docs/kubernetes-large-clusters.md b/docs/kubernetes-large-clusters.md index 9cb9d10473..8b99799e86 100644 --- a/docs/kubernetes-large-clusters.md +++ b/docs/kubernetes-large-clusters.md @@ -1,11 +1,11 @@ -# Large Kubernetes Clusters with acs-engine +# Large Kubernetes Clusters with aks-engine ## Background -Starting from acs-engine v0.3.0, acs-engine supports using exponential cloud backoff that is a feature of Kubernetes v1.6.6 and newer. Cloud backoff allows Kubernetes nodes to backoff on HTTP 429 errors that are usually caused by exceeding Azure API limits. +Starting from aks-engine v0.3.0, aks-engine supports using exponential cloud backoff that is a feature of Kubernetes v1.6.6 and newer. Cloud backoff allows Kubernetes nodes to backoff on HTTP 429 errors that are usually caused by exceeding Azure API limits. ## To Use Declare your kubernetes cluster API model config as you normally would, with the following requirements: -- You must be using at minimum the `v1.6.6` version of Kubernetes to have access to the `kubernetesConfig` configuration vectors exemplified in [examples/largeclusters/kubernetes.json](https://github.com/Azure/acs-engine/blob/master/examples/largeclusters/kubernetes.json). As long as you are using a version of acs-engine `v0.3.0` or newer, your kubernetes cluster specification will fulfill this minimum version requirement. +- You must be using at minimum the `v1.6.6` version of Kubernetes to have access to the `kubernetesConfig` configuration vectors exemplified in [examples/largeclusters/kubernetes.json](https://github.com/Azure/aks-engine/blob/master/examples/largeclusters/kubernetes.json). As long as you are using a version of aks-engine `v0.3.0` or newer, your kubernetes cluster specification will fulfill this minimum version requirement. - We recommend the use of smaller pools (e.g., count of 20) over larger pools (e.g., count of 100); produce your desired total node count with lots of pools, as opposed to as few as possible. - We also recommend using large vmSize configurations to reduce node counts, where appropriate. Make sure you have a defensible infrastructure justification for more nodes in terms of node count (for example as of kubernetes 1.7 there is a 100 pods per node limit), instead of opting to use more powerful nodes. Doing so reduces cluster complexity, and azure resource administrative overhead. As Kubernetes excels in binpacking pods onto available instances, vertically scaling VM sizes (more CPU/RAM) is a better approach for expanding cluster capacity, if you are not approaching the pod-per-node limit. @@ -46,4 +46,4 @@ The following configuration parameters are available in the `properties.orchestr "--route-reconciliation-period": "1m" // how often to reconcile cloudprovider-originating node routes } ``` -The [examples/largeclusters/kubernetes.json](https://github.com/Azure/acs-engine/blob/master/examples/largeclusters/kubernetes.json) api model example suggests how you might opt into these large cluster features following the guidelines above. \ No newline at end of file +The [examples/largeclusters/kubernetes.json](https://github.com/Azure/aks-engine/blob/master/examples/largeclusters/kubernetes.json) api model example suggests how you might opt into these large cluster features following the guidelines above. \ No newline at end of file diff --git a/docs/kubernetes.md b/docs/kubernetes.md index 7224c99394..e7d102035d 100644 --- a/docs/kubernetes.md +++ b/docs/kubernetes.md @@ -1,12 +1,12 @@ -# Microsoft Azure Container Service Engine - Kubernetes +# Microsoft Azure Kubernetes Service Engine - Kubernetes * Create a Kubernetes Cluster * [Linux](kubernetes/deploy.md) - Create your first Linux Kubernetes cluster * [Windows](kubernetes/windows.md) - Create your first Windows Kubernetes cluster * [Kubernetes Next Steps](kubernetes/walkthrough.md) - You have successfully deployed a Kubernetes cluster, now what? * [Troubleshooting](kubernetes/troubleshooting.md) - Running into issues? Start here to troubleshoot Kubernetes. -* [Features](kubernetes/features.md) - Guide to alpha, beta, and stable functionality in acs-engine. -* [For Kubernetes Developers](kubernetes/k8s-developers.md) - Info for devs working on Kubernetes upstream and wanting to test using acs-engine. +* [Features](kubernetes/features.md) - Guide to alpha, beta, and stable functionality in aks-engine. +* [For Kubernetes Developers](kubernetes/k8s-developers.md) - Info for devs working on Kubernetes upstream and wanting to test using aks-engine. ## Known Issues @@ -15,7 +15,7 @@ Nodes might appear in the "NotReady" state for approx. 15 minutes if master stops receiving updates from agents. This is a known upstream kubernetes [issue #41916](https://github.com/kubernetes/kubernetes/issues/41916#issuecomment-312428731). This fixing PR is currently under review. -ACS-Engine partially mitigates this issue on Linux by detecting dead TCP connections more quickly via **net.ipv4.tcp_retries2=8**. +AKS Engine partially mitigates this issue on Linux by detecting dead TCP connections more quickly via **net.ipv4.tcp_retries2=8**. ## Additional Kubernetes Resources diff --git a/docs/kubernetes/aad.md b/docs/kubernetes/aad.md index 894d9d67db..e8b06ae6e7 100644 --- a/docs/kubernetes/aad.md +++ b/docs/kubernetes/aad.md @@ -1,6 +1,6 @@ -# Microsoft Azure Container Service Engine - Kubernetes AAD integration Walkthrough +# Microsoft Azure Kubernetes Service Engine - Kubernetes AAD integration Walkthrough -This is walkthrough is to help you get start with Azure Active Directory(AAD) integeration with an ACS-Engine Kubernetes cluster. +This is walkthrough is to help you get start with Azure Active Directory(AAD) integeration with an AKS Engine Kubernetes cluster. [OpenID Connect](http://openid.net/connect/) is a simple identity layer built on top of the OAuth 2.0 protocol, and it is supported by both AAD and Kubernetes. Here we're going to use OpenID Connect as the communication protocol. @@ -45,7 +45,7 @@ To sign in, use a web browser to open the page https://aka.ms/devicelogin and en You can now authenticate to the Kubernetes cluster, but you need to set up authorization as well. #### Authentication -With ACS-Engine, the cluster is locked down by default. +With AKS Engine, the cluster is locked down by default. This means that when you try to use your AAD account you will see something like: diff --git a/docs/kubernetes/deploy.md b/docs/kubernetes/deploy.md index 0887ede028..4edcbc7bdc 100644 --- a/docs/kubernetes/deploy.md +++ b/docs/kubernetes/deploy.md @@ -2,24 +2,24 @@ ## Install Prerequisites -All the commands in this guide require both the Azure CLI and `acs-engine`. Follow the [installation instructions to download acs-engine before continuing](../acsengine.md#install-acs-engine) or [compile from source](../acsengine.md#build-from-source). +All the commands in this guide require both the Azure CLI and `aks-engine`. Follow the [installation instructions to download aks-engine before continuing](../aksengine.md#install-aks-engine) or [compile from source](../aksengine.md#build-from-source). For installation instructions see [the Azure CLI GitHub repository](https://github.com/Azure/azure-cli#installation) for the latest release. ## Overview -`acs-engine` reads a cluster definition which describes the size, shape, and configuration of your cluster. This guide takes the default configuration of one master and two Linux agents. If you would like to change the configuration, edit `examples/kubernetes.json` before continuing. +`aks-engine` reads a cluster definition which describes the size, shape, and configuration of your cluster. This guide takes the default configuration of one master and two Linux agents. If you would like to change the configuration, edit `examples/kubernetes.json` before continuing. -The `acs-engine deploy` command automates creation of a Service Principal, Resource Group and SSH key for your cluster. If operators need more control or are interested in the individual steps see the ["Long Way" section below](#acs-engine-the-long-way). +The `aks-engine deploy` command automates creation of a Service Principal, Resource Group and SSH key for your cluster. If operators need more control or are interested in the individual steps see the ["Long Way" section below](#aks-engine-the-long-way). -**NOTE:** ACS Engine creates a _cluster_; it _doesn't_ create an Azure Container Service resource. So clusters that you create using the `acs-engine` command (or ARM templates generated by the `acs-engine` command) won't show up as ACS resources, for example when you run `az acs list`. Think of `acs-engine` as the, er, engine which ACS uses to create clusters: you can use the same engine yourself, but ACS won't know about the results. +**NOTE:** AKS Engine creates a _cluster_; it _doesn't_ create an Azure Container Service resource. So clusters that you create using the `aks-engine` command (or ARM templates generated by the `aks-engine` command) won't show up as ACS resources, for example when you run `az acs list`. Think of `aks-engine` as the, er, engine which ACS uses to create clusters: you can use the same engine yourself, but ACS won't know about the results. After the cluster is deployed the upgrade and [scale](scale.md) commands can be used to make updates to your cluster. ## Gather Information * The subscription in which you would like to provision the cluster. This is a uuid which can be found with `az account list -o table`. -* Proper access rights within the subscription. Especially the right to create and assign service principals to applications ( see ACS Engine the Long Way, Step #2) +* Proper access rights within the subscription. Especially the right to create and assign service principals to applications ( see AKS Engine the Long Way, Step #2) * A `dnsPrefix` which forms part of the the hostname for your cluster (e.g. staging, prodwest, blueberry). The DNS prefix must be unique so pick a random name. * A location to provision the cluster e.g. `westus2`. @@ -34,10 +34,10 @@ Contoso Subscription AzureCloud 51ac25de-afdg-9201 For this example, the subscription id is `51ac25de-afdg-9201-d923-8d8e8e8e8e8e`, the DNS prefix is `contoso-apple`, and location is `westus2`. -Run `acs-engine deploy` with the appropriate arguments: +Run `aks-engine deploy` with the appropriate arguments: ```sh -$ acs-engine deploy --subscription-id 51ac25de-afdg-9201-d923-8d8e8e8e8e8e \ +$ aks-engine deploy --subscription-id 51ac25de-afdg-9201-d923-8d8e8e8e8e8e \ --dns-prefix contoso-apple --location westus2 \ --api-model examples/kubernetes.json @@ -50,12 +50,12 @@ INFO[0034] Starting ARM Deployment (contoso-apple-1423145182). This will take so INFO[0393] Finished ARM Deployment (contoso-apple-1423145182). ``` -`acs-engine` will output Azure Resource Manager (ARM) templates, SSH keys, and a kubeconfig file in `_output/contoso-apple-59769a59` directory: +`aks-engine` will output Azure Resource Manager (ARM) templates, SSH keys, and a kubeconfig file in `_output/contoso-apple-59769a59` directory: * `_output/contoso-apple-59769a59/azureuser_rsa` * `_output/contoso-apple-59769a59/kubeconfig/kubeconfig.westus2.json` -acs-engine generates kubeconfig files for each possible region. Access the new cluster by using the kubeconfig generated for the cluster's location. This example used `westus2`, so the kubeconfig is `_output//kubeconfig/kubeconfig.westus2.json`: +aks-engine generates kubeconfig files for each possible region. Access the new cluster by using the kubeconfig generated for the cluster's location. This example used `westus2`, so the kubeconfig is `_output//kubeconfig/kubeconfig.westus2.json`: ```sh $ KUBECONFIG=_output/contoso-apple-59769a59/kubeconfig/kubeconfig.westus2.json kubectl cluster-info @@ -67,14 +67,14 @@ kubernetes-dashboard is running at https://contoso-apple-59769a59.westus2.clouda To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. ``` -Administrative note: By default, the directory where acs-engine stores cluster configuration (`_output/contoso-apple` above) won't be overwritten as a result of subsequent attempts to deploy a cluster using the same `--dns-prefix`) To re-use the same resource group name repeatedly, include the `--force-overwrite` command line option with your `acs-engine deploy` command. On a related note, include an `--auto-suffix` option to append a randomly generated suffix to the dns-prefix to form the resource group name, for example if your workflow requires a common prefix across multiple cluster deployments. Using the `--auto-suffix` pattern appends a compressed timestamp to ensure a unique cluster name (and thus ensure that each deployment's configuration artifacts will be stored locally under a discrete `_output//` directory). +Administrative note: By default, the directory where aks-engine stores cluster configuration (`_output/contoso-apple` above) won't be overwritten as a result of subsequent attempts to deploy a cluster using the same `--dns-prefix`) To re-use the same resource group name repeatedly, include the `--force-overwrite` command line option with your `aks-engine deploy` command. On a related note, include an `--auto-suffix` option to append a randomly generated suffix to the dns-prefix to form the resource group name, for example if your workflow requires a common prefix across multiple cluster deployments. Using the `--auto-suffix` pattern appends a compressed timestamp to ensure a unique cluster name (and thus ensure that each deployment's configuration artifacts will be stored locally under a discrete `_output//` directory). **Note**: If the cluster is using an existing VNET please see the [Custom VNET](features.md#feat-custom-vnet) feature documentation for additional steps that must be completed after cluster provisioning. The deploy command lets you override any values under the properties tag (even in arrays) from the cluster definition file without having to update the file. You can use the `--set` flag to do that. For example: ```bash -acs-engine deploy --resource-group "your-resource-group" \ +aks-engine deploy --resource-group "your-resource-group" \ --location "westeurope" \ --subscription-id "your-subscription-id" \ --api-model "./apimodel.json" \ @@ -88,7 +88,7 @@ acs-engine deploy --resource-group "your-resource-group" \ -## ACS Engine the Long Way +## AKS Engine the Long Way ### Step 1: Generate an SSH Key @@ -98,11 +98,11 @@ If you don't have an SSH key [cluster operators may generate a new one](../ssh.m ### Step 2: Create a Service Principal -Kubernetes clusters have integrated support for various cloud providers as core functionality. On Azure, acs-engine uses a Service Principal to interact with Azure Resource Manager (ARM). Follow the [instructions](../serviceprincipal.md) to create a new service principal and grant it the necessary IAM role to create Azure resources. +Kubernetes clusters have integrated support for various cloud providers as core functionality. On Azure, aks-engine uses a Service Principal to interact with Azure Resource Manager (ARM). Follow the [instructions](../serviceprincipal.md) to create a new service principal and grant it the necessary IAM role to create Azure resources. ### Step 3: Edit your Cluster Definition -ACS Engine consumes a cluster definition which outlines the desired shape, size, and configuration of Kubernetes. There are a number of features that can be enabled through the cluster definition: check the `examples` directory for a number of... examples. +AKS Engine consumes a cluster definition which outlines the desired shape, size, and configuration of Kubernetes. There are a number of features that can be enabled through the cluster definition: check the `examples` directory for a number of... examples. Edit the [simple Kubernetes cluster definition](/examples/kubernetes.json) and fill out the required values: @@ -119,23 +119,23 @@ Note: you can then use the `--set` option of the generate command to override va The generate command takes a cluster definition and outputs a number of templates which describe your Kubernetes cluster. By default, `generate` will create a new directory named after your cluster nested in the `_output` directory. If my dnsPrefix was `larry` my cluster templates would be found in `_output/larry-`. -Run `acs-engine generate examples/kubernetes.json` +Run `aks-engine generate examples/kubernetes.json` The generate command lets you override values from the cluster definition file without having to update the file. You can use the `--set` flag to do that: ```sh -acs-engine generate --set linuxProfile.adminUsername=myNewUsername,masterProfile.count=3 clusterdefinition.json +aks-engine generate --set linuxProfile.adminUsername=myNewUsername,masterProfile.count=3 clusterdefinition.json ``` The `--set` flag only supports JSON properties under `properties`. You can also work with array, like the following: ```sh -acs-engine generate --set agentPoolProfiles[0].count=5,agentPoolProfiles[1].name=myPoolName clusterdefinition.json +aks-engine generate --set agentPoolProfiles[0].count=5,agentPoolProfiles[1].name=myPoolName clusterdefinition.json ``` ### Step 5: Submit your Templates to Azure Resource Manager (ARM) -[Deploy the output azuredeploy.json and azuredeploy.parameters.json](../acsengine.md#deployment-usage) +[Deploy the output azuredeploy.json and azuredeploy.parameters.json](../aksengine.md#deployment-usage) * To enable the optional network policy enforcement using calico, you have to set the parameter during this step according to this [guide](../kubernetes.md#optional-enable-network-policy-enforcement-using-calico) * To enable the optional network policy enforcement using cilium, you have to set the parameter during this step according to this [guide](../kubernetes.md#optional-enable-network-policy-enforcement-using-cilium) @@ -160,12 +160,12 @@ k8s-master-22116803-0 XXXXXXXXXXXX southeastasia az vm show -g -n --query tags ``` - Sample JSON out of this command is shown below. This command can also be used to check the acs-engine version which was used to create the cluster + Sample JSON out of this command is shown below. This command can also be used to check the aks-engine version which was used to create the cluster ```json { - "acsengineVersion": "v0.15.0", - "creationSource": "acsengine-k8s-master-22116803-0", + "aksengineVersion": "v0.15.0", + "creationSource": "aksengine-k8s-master-22116803-0", "orchestrator": "Kubernetes:1.9.5", "poolName": "master", "resourceNameSuffix": "22116803" diff --git a/docs/kubernetes/features.md b/docs/kubernetes/features.md index d44cc2aa31..d600e8ffc4 100644 --- a/docs/kubernetes/features.md +++ b/docs/kubernetes/features.md @@ -15,7 +15,7 @@ ## Managed Identity -Enabling Managed Identity configures acs-engine to include and use MSI identities for all interactions with the Azure Resource Manager (ARM) API. +Enabling Managed Identity configures aks-engine to include and use MSI identities for all interactions with the Azure Resource Manager (ARM) API. Instead of using a static servic principal written to `/etc/kubernetes/azure.json`, Kubernetes will use a dynamic, time-limited token fetched from the MSI extension running on master and agent nodes. This support is currently alpha and requires Kubernetes v1.9.1 or newer. @@ -39,7 +39,7 @@ By default, the cluster will be provisioned with [Role-Based Access Control](htt } ``` -See [cluster definition](https://github.com/Azure/acs-engine/blob/master/docs/clusterdefinition.md#kubernetesconfig) for further detail. +See [cluster definition](https://github.com/Azure/aks-engine/blob/master/docs/clusterdefinition.md#kubernetesconfig) for further detail. ## Managed Disks @@ -49,7 +49,7 @@ Related [upstream PR](https://github.com/kubernetes/kubernetes/pull/46360) for d ### Using Kubernetes Persistent Volumes -By default, each ACS-Engine cluster is bootstrapped with several StorageClass resources. This bootstrapping is handled by the addon-manager pod that creates resources defined under /etc/kubernetes/addons directory on master VMs. +By default, each AKS Engine cluster is bootstrapped with several StorageClass resources. This bootstrapping is handled by the addon-manager pod that creates resources defined under /etc/kubernetes/addons directory on master VMs. #### Non-managed Disks @@ -105,7 +105,7 @@ spec: ## Using Azure integrated networking (CNI) -Kubernetes clusters are configured by default to use the [Azure CNI plugin](https://github.com/Azure/azure-container-networking) which provides an Azure native networking experience. Pods will receive IP addresses directly from the vnet subnet on which they're hosted. If the api model doesn't specify explicitly, acs-engine will automatically provide the following `networkPlugin` configuration in `kubernetesConfig`: +Kubernetes clusters are configured by default to use the [Azure CNI plugin](https://github.com/Azure/azure-container-networking) which provides an Azure native networking experience. Pods will receive IP addresses directly from the vnet subnet on which they're hosted. If the api model doesn't specify explicitly, aks-engine will automatically provide the following `networkPlugin` configuration in `kubernetesConfig`: ``` "kubernetesConfig": { @@ -148,7 +148,7 @@ When using Azure integrated networking the maxPods setting will be set to 30 by Using the default configuration, Kubernetes allows communication between all Pods within a cluster. To ensure that Pods can only be accessed by authorized -Pods, a policy enforcement is needed. To enable policy enforcement using Calico refer to the [cluster definition](https://github.com/Azure/acs-engine/blob/master/docs/clusterdefinition.md#kubernetesconfig) document under networkPolicy. There is also a reference cluster definition available [here](https://github.com/Azure/acs-engine/blob/master/examples/networkpolicy/kubernetes-calico.json). +Pods, a policy enforcement is needed. To enable policy enforcement using Calico refer to the [cluster definition](https://github.com/Azure/aks-engine/blob/master/docs/clusterdefinition.md#kubernetesconfig) document under networkPolicy. There is also a reference cluster definition available [here](https://github.com/Azure/aks-engine/blob/master/examples/networkpolicy/kubernetes-calico.json). This will deploy a Calico node controller to every instance of the cluster using a Kubernetes DaemonSet. After a successful deployment you should be able @@ -166,7 +166,7 @@ Per default Calico still allows all communication within the cluster. Using Kube * [NetworkPolicy User Guide](https://kubernetes.io/docs/user-guide/networkpolicies/) * [NetworkPolicy Example Walkthrough](https://kubernetes.io/docs/getting-started-guides/network-policy/walkthrough/) -* [Calico Kubernetes](https://github.com/Azure/acs-engine/blob/master/examples/networkpolicy) +* [Calico Kubernetes](https://github.com/Azure/aks-engine/blob/master/examples/networkpolicy) @@ -175,9 +175,9 @@ Per default Calico still allows all communication within the cluster. Using Kube Using the default configuration, Kubernetes allows communication between all Pods within a cluster. To ensure that Pods can only be accessed by authorized Pods, a policy enforcement is needed. To enable policy enforcement using Cilium refer to the -[cluster definition](https://github.com/Azure/acs-engine/blob/master/docs/clusterdefinition.md#kubernetesconfig) +[cluster definition](https://github.com/Azure/aks-engine/blob/master/docs/clusterdefinition.md#kubernetesconfig) document under networkPolicy. There is also a reference cluster definition available -[here](https://github.com/Azure/acs-engine/blob/master/examples/networkpolicy/kubernetes-cilium.json). +[here](https://github.com/Azure/aks-engine/blob/master/examples/networkpolicy/kubernetes-cilium.json). This will deploy a Cilium agent to every instance of the cluster using a Kubernetes DaemonSet. After a successful deployment you should be able @@ -197,22 +197,22 @@ you can define stricter policies. Good resources to get information about that a * [Cilum Network Policy Docs](https://cilium.readthedocs.io/en/latest/kubernetes/policy/#k8s-policy) * [NetworkPolicy User Guide](https://kubernetes.io/docs/user-guide/networkpolicies/) * [NetworkPolicy Example Walkthrough](https://kubernetes.io/docs/getting-started-guides/network-policy/walkthrough/) -* [Cilium Kubernetes](https://github.com/Azure/acs-engine/blob/master/examples/networkpolicy) +* [Cilium Kubernetes](https://github.com/Azure/aks-engine/blob/master/examples/networkpolicy) ## Custom VNET -*Note: Custom VNET for Kubernetes Windows cluster has a [known issue](https://github.com/Azure/acs-engine/issues/1767).* +*Note: Custom VNET for Kubernetes Windows cluster has a [known issue](https://github.com/Azure/aks-engine/issues/1767).* -ACS Engine supports deploying into an existing VNET. Operators must specify the ARM path/id of Subnets for the `masterProfile` and any `agentPoolProfiles`, as well as the first IP address to use for static IP allocation in `firstConsecutiveStaticIP`. Please note that in any azure subnet, the first four and the last ip address is reserved and can not be used. Additionally, each pod now gets the IP address from the Subnet. As a result, enough IP addresses (equal to `ipAddressCount` for each node) should be available beyond `firstConsecutiveStaticIP`. By default, the `ipAddressCount` has a value of 31, 1 for the node and 30 for pods, (note that the number of pods can be changed via `KubeletConfig["--max-pods"]`). `ipAddressCount` can be changed if desired. Furthermore, to prevent source address NAT'ing within the VNET, we assign to the `vnetCidr` property in `masterProfile` the CIDR block that represents the usable address space in the existing VNET. Therefore, it is recommended to use a large subnet size such as `/16`. +AKS Engine supports deploying into an existing VNET. Operators must specify the ARM path/id of Subnets for the `masterProfile` and any `agentPoolProfiles`, as well as the first IP address to use for static IP allocation in `firstConsecutiveStaticIP`. Please note that in any azure subnet, the first four and the last ip address is reserved and can not be used. Additionally, each pod now gets the IP address from the Subnet. As a result, enough IP addresses (equal to `ipAddressCount` for each node) should be available beyond `firstConsecutiveStaticIP`. By default, the `ipAddressCount` has a value of 31, 1 for the node and 30 for pods, (note that the number of pods can be changed via `KubeletConfig["--max-pods"]`). `ipAddressCount` can be changed if desired. Furthermore, to prevent source address NAT'ing within the VNET, we assign to the `vnetCidr` property in `masterProfile` the CIDR block that represents the usable address space in the existing VNET. Therefore, it is recommended to use a large subnet size such as `/16`. Depending upon the size of the VNET address space, during deployment, it is possible to experience IP address assignment collision between the required Kubernetes static IPs (one each per master and one for the API server load balancer, if more than one masters) and Azure CNI-assigned dynamic IPs (one for each NIC on the agent nodes). In practice, the larger the VNET the less likely this is to happen; some detail, and then a guideline. First, the detail: * Azure CNI assigns dynamic IP addresses from the "beginning" of the subnet IP address space (specifically, it looks for available addresses starting at ".4" ["10.0.0.4" in a "10.0.0.0/24" network]) -* acs-engine will require a range of up to 16 unused IP addresses in multi-master scenarios (1 per master for up to 5 masters, and then the next 10 IP addresses immediately following the "last" master for headroom reservation, and finally 1 more for the load balancer immediately adjacent to the afore-described _n_ masters+10 sequence) to successfully scaffold the network stack for your cluster +* aks-engine will require a range of up to 16 unused IP addresses in multi-master scenarios (1 per master for up to 5 masters, and then the next 10 IP addresses immediately following the "last" master for headroom reservation, and finally 1 more for the load balancer immediately adjacent to the afore-described _n_ masters+10 sequence) to successfully scaffold the network stack for your cluster A guideline that will remove the danger of IP address allocation collision during deployment: @@ -378,7 +378,7 @@ You can build a private Kubernetes cluster with no public IP addresses assigned } ``` -In order to access this cluster using kubectl commands, you will need a jumpbox in the same VNET (or onto a peer VNET that routes to the VNET). If you do not already have a jumpbox, you can use acs-engine to provision your jumpbox (see below) or create it manually. You can create a new jumpbox manually in the Azure Portal under "Create a resource > Compute > Ubuntu Server 16.04 LTS VM" or using the [az cli](https://docs.microsoft.com/en-us/cli/azure/vm?view=azure-cli-latest#az_vm_create). You will then be able to: +In order to access this cluster using kubectl commands, you will need a jumpbox in the same VNET (or onto a peer VNET that routes to the VNET). If you do not already have a jumpbox, you can use aks-engine to provision your jumpbox (see below) or create it manually. You can create a new jumpbox manually in the Azure Portal under "Create a resource > Compute > Ubuntu Server 16.04 LTS VM" or using the [az cli](https://docs.microsoft.com/en-us/cli/azure/vm?view=azure-cli-latest#az_vm_create). You will then be able to: - install [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) on the jumpbox - copy the kubeconfig artifact for the right region from the deployment directory to the jumpbox - run `export KUBECONFIG=` @@ -386,7 +386,7 @@ In order to access this cluster using kubectl commands, you will need a jumpbox Alternatively, you may also ssh into your nodes (given that your ssh key is on the jumpbox) and use the admin user kubeconfig on the cluster to run `kubectl` commands directly on the cluster. However, in the case of a multi-master private cluster, the connection will be refused when running commands on a master every time that master gets picked by the load balancer as it will be routing to itself (1 in 3 times for a 3 master cluster, 1 in 5 for 5 masters). This is expected behavior and therefore the method aforementioned of accessing nodes on the jumpbox using the `_output` directory kubeconfig is preferred. -To auto-provision a jumpbox with your acs-engine deployment use: +To auto-provision a jumpbox with your aks-engine deployment use: ``` "kubernetesConfig": { @@ -406,7 +406,7 @@ To auto-provision a jumpbox with your acs-engine deployment use: ## Azure Key Vault Data Encryption -Enabling Azure Key Vault Encryption configures acs-engine to create an Azure Key Vault in the same resource group as the Kubernetes cluster and configures Kubernetes to use a key from this Key Vault to encrypt and decrypt etcd data for the Kubernetes cluster. +Enabling Azure Key Vault Encryption configures aks-engine to create an Azure Key Vault in the same resource group as the Kubernetes cluster and configures Kubernetes to use a key from this Key Vault to encrypt and decrypt etcd data for the Kubernetes cluster. To enable this feature, add `encryptionWithExternalKms` in `kubernetesConfig` and `objectId` in `servicePrincipalProfile`: diff --git a/docs/kubernetes/gpu.md b/docs/kubernetes/gpu.md index 003e0701bb..d36d941117 100644 --- a/docs/kubernetes/gpu.md +++ b/docs/kubernetes/gpu.md @@ -1,4 +1,4 @@ -# Microsoft Azure Container Service Engine - Using GPUs with Kubernetes +# Microsoft Azure Kubernetes Service Engine - Using GPUs with Kubernetes If you created a Kubernetes cluster with one or multiple agent pool(s) whose VM size is `Standard_NC*` or `Standard_NV*` you can schedule GPU workload on your cluster. The NVIDIA drivers are automatically installed on every GPU agent in your cluster, so you don't need to do that manually, unless you require a specific version of the drivers. Currently, the installed driver is version 396.26. diff --git a/docs/kubernetes/hybrid-environment.md b/docs/kubernetes/hybrid-environment.md index 27f1dfa242..102e6f83d3 100644 --- a/docs/kubernetes/hybrid-environment.md +++ b/docs/kubernetes/hybrid-environment.md @@ -14,7 +14,7 @@ As illustrated on the figure above, we recommand to deploy the Kubernetes cluste This document assumes that you are familiar with: -- Deploying Kubernetes cluster in a [custom VNET using ACS-Engine](../../examples/vnet/README.md) +- Deploying Kubernetes cluster in a [custom VNET using AKS Engine](../../examples/vnet/README.md) - Azure [VPN Gateway](https://azure.microsoft.com/en-us/services/vpn-gateway/) and/or [Azure Express Route](https://azure.microsoft.com/en-us/services/expressroute/) - Azure [Virtual Network Peering](https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-peering-overview) @@ -27,15 +27,15 @@ The network topology must be well defined beforehand to enable peering between t ### DNS In a hybrid environment, you usually want to integrate with your on-premises DNS. There is two aspects to this. The first one is to register the VMs forming the cluster, and using your local search domain when resolving other services. The second is getting the services running on Kubernetes to use the external DNS. -To benefit the scaling capabilities of the cluster and to ensure resiliency to machine failure, every node configuration needs to be scripted and part of the initial template that acs-engine will deploy. To register the nodes in your DNS at startup, you need to define [an acs-engine extension](../extensions.md) that will run your [DNS registration script](https://github.com/tesharp/acs-engine/blob/register-dns-extension/extensions/register-dns/v1/register-dns.sh). +To benefit the scaling capabilities of the cluster and to ensure resiliency to machine failure, every node configuration needs to be scripted and part of the initial template that aks-engine will deploy. To register the nodes in your DNS at startup, you need to define [an aks-engine extension](../extensions.md) that will run your [DNS registration script](https://github.com/tesharp/aks-engine/blob/register-dns-extension/extensions/register-dns/v1/register-dns.sh). In addition, you might want cluster services to address URLs outside the cluster using your on-premise DNS. To achieve this you need to configure KubeDNS to use your existing nameservice as upstream. [This setup is well documented on kubernetes blog](https://kubernetes.io/blog/2017/04/configuring-private-dns-zones-upstream-nameservers-kubernetes) -Note : There is some ongoing work to make this easier. See [acs-engine#2590](https://github.com/Azure/acs-engine/pull/2590) +Note : There is some ongoing work to make this easier. See [aks-engine#2590](https://github.com/Azure/aks-engine/pull/2590) ### Private Cluster -By default, Kubernetes deployment with acs-engine expose the the admin api publicly (and securely). This can be avoided. Using peering with private/on-premise virtual network with ACS-Engine also allows you to create cloud-hosted [private cluster](features.md#private-cluster), with no endpoint exposed over the Internet. +By default, Kubernetes deployment with aks-engine expose the the admin api publicly (and securely). This can be avoided. Using peering with private/on-premise virtual network with AKS Engine also allows you to create cloud-hosted [private cluster](features.md#private-cluster), with no endpoint exposed over the Internet. ## Kubernetes Network @@ -43,12 +43,12 @@ For your kubernetes cluster to communicate with your on-premise network, you wil ### Network -Deploying ACS-Engine on Azure, you have 3 options of network policy. Azure CNI, Kubenet, or Calico. +Deploying AKS Engine on Azure, you have 3 options of network policy. Azure CNI, Kubenet, or Calico. #### Azure CNI -By default, ACS-Engine is using the [**azure cni** network policy](../../examples/networkpolicy/README.md#azure-container-networking-default) plugin. This has some advantages and some consequences that must be considered when defining the network where we deploy the cluster. CNI provides an integration with azure subnet IP addressing so that every pod created by kubernetes is assigned an IP address from the corresponding subnet. -All IP addresses are pre-allocated at provisionning time. By default, [acs-engine will pre-allocate 128 IPs per node](https://github.com/Azure/azure-container-networking/blob/master/docs/acs.md#enabling-azure-vnet-plugins-for-an-acs-kubernetes-cluster) on the subnet. +By default, AKS Engine is using the [**azure cni** network policy](../../examples/networkpolicy/README.md#azure-container-networking-default) plugin. This has some advantages and some consequences that must be considered when defining the network where we deploy the cluster. CNI provides an integration with azure subnet IP addressing so that every pod created by kubernetes is assigned an IP address from the corresponding subnet. +All IP addresses are pre-allocated at provisionning time. By default, [aks-engine will pre-allocate 128 IPs per node](https://github.com/Azure/azure-container-networking/blob/master/docs/acs.md#enabling-azure-vnet-plugins-for-an-acs-kubernetes-cluster) on the subnet. While this can be configured, new addresses will not be allocated dynamically. That means that you need to anticipate and plan for the maximum number of IP addresses you will need for the maximum scale. Consequences: @@ -155,7 +155,7 @@ Note: when using service without selector, you can't have any Kubernetes readine ## Cluster upgrades -As you may know, ACS-Engine proposes an [upgrade command](../../examples/k8s-upgrade/README.md). It is really important to understand that this uprade process is *not* fail-safe. Therefore in most cases, and especially with production clusters, a good practice consists of creating another Kubernetes cluster running the targeted version in another VNET and move the workloads into this new cluster. Once everything is tested and works as desired, set up the network redirection to this new environment. +As you may know, AKS Engine proposes an [upgrade command](../../examples/k8s-upgrade/README.md). It is really important to understand that this uprade process is *not* fail-safe. Therefore in most cases, and especially with production clusters, a good practice consists of creating another Kubernetes cluster running the targeted version in another VNET and move the workloads into this new cluster. Once everything is tested and works as desired, set up the network redirection to this new environment. If you plan everything correctly following the documentation above and use Kubernetes Services properly to address both in-cluster and outside services, everything should work fine. diff --git a/docs/kubernetes/k8s-developers.md b/docs/kubernetes/k8s-developers.md index 82afde6280..7c9364e276 100644 --- a/docs/kubernetes/k8s-developers.md +++ b/docs/kubernetes/k8s-developers.md @@ -1,8 +1,8 @@ # For Kubernetes Developers -If you're working on Kubernetes upstream, you can use ACS Engine to test your build of Kubernetes in the Azure environment. The option that allows you to do this is `orchestratorProfile/kubernetesConfig/customHyperkubeImage`, which you should set to point to a Docker image containing your build of hyperkube. +If you're working on Kubernetes upstream, you can use AKS Engine to test your build of Kubernetes in the Azure environment. The option that allows you to do this is `orchestratorProfile/kubernetesConfig/customHyperkubeImage`, which you should set to point to a Docker image containing your build of hyperkube. -The following instructions describe in more detail how to create the required Docker image and deploy it using ACS Engine (replace `dockerhubid` and `sometag` with your Docker Hub ID and a unique tag for your build): +The following instructions describe in more detail how to create the required Docker image and deploy it using AKS Engine (replace `dockerhubid` and `sometag` with your Docker Hub ID and a unique tag for your build): ## In the Kubernetes repo @@ -31,7 +31,7 @@ docker push dockerhubid/hyperkube-amd64:sometag ## In the ACS repo -* Open the ACS Engine input JSON (e.g. a file from the examples directory) and add the following to the `orchestratorProfile` section: +* Open the AKS Engine input JSON (e.g. a file from the examples directory) and add the following to the `orchestratorProfile` section: ``` "kubernetesConfig": { @@ -39,4 +39,4 @@ docker push dockerhubid/hyperkube-amd64:sometag } ``` -* Run `./bin/acs-engine deploy --api-model the_json_file_you_just_edited.json ...` [as normal](deploy.md). +* Run `./bin/aks-engine deploy --api-model the_json_file_you_just_edited.json ...` [as normal](deploy.md). diff --git a/docs/kubernetes/monitoring.md b/docs/kubernetes/monitoring.md index 3d1b3ef910..6040ca43ab 100644 --- a/docs/kubernetes/monitoring.md +++ b/docs/kubernetes/monitoring.md @@ -14,7 +14,7 @@ There are five main options to monitor your cluster: ## Intro to Heapster -Monitoring your cluster in Kubernetes is powered by a component called [Heapster](https://github.com/kubernetes/Heapster/). Heapster is a pod that is responsible for aggregating monitoring data from across all the nodes and pods in your cluster. Heapster is necessary for viewing monitoring data in the Kubernetes dashboard as well as in Grafana. Heapster comes preinstalled on `acs-engine` deployments. To ensure that Heapster is set up in your cluster and is running: +Monitoring your cluster in Kubernetes is powered by a component called [Heapster](https://github.com/kubernetes/Heapster/). Heapster is a pod that is responsible for aggregating monitoring data from across all the nodes and pods in your cluster. Heapster is necessary for viewing monitoring data in the Kubernetes dashboard as well as in Grafana. Heapster comes preinstalled on `aks-engine` deployments. To ensure that Heapster is set up in your cluster and is running: 1. Ensure you have set up a [working kubernetes cluster](../kubernetes.md) and are able to use kubectl 2. Run `kubectl get pods --namespace=kube-system` @@ -68,7 +68,7 @@ Once you have opened the UI, you can explore node stats (CPU, Memory, etc...) un ## Monitoring extension -A quick way to scaffold out cloud-native and open source monitoring components is to use the [acs-engine monitoring extension](https://github.com/Azure/acs-engine/tree/master/extensions/prometheus-grafana-k8s). For details on how to use the monitoring extension, please refer to the [extension documentation](https://github.com/Azure/acs-engine/tree/master/extensions/prometheus-grafana-k8s). By embedding the extension in your apimodel, the extension will do much of the work to create a monitoring solution in your cluster, which includes the following: +A quick way to scaffold out cloud-native and open source monitoring components is to use the [aks-engine monitoring extension](https://github.com/Azure/aks-engine/tree/master/extensions/prometheus-grafana-k8s). For details on how to use the monitoring extension, please refer to the [extension documentation](https://github.com/Azure/aks-engine/tree/master/extensions/prometheus-grafana-k8s). By embedding the extension in your apimodel, the extension will do much of the work to create a monitoring solution in your cluster, which includes the following: - [cAdvisor](https://github.com/google/cadvisor) daemon set to publish container metrics - [Prometheus](https://prometheus.io/) for metrics collection and storage diff --git a/docs/kubernetes/scale.md b/docs/kubernetes/scale.md index 6ab5031b39..f42e1e7a5c 100644 --- a/docs/kubernetes/scale.md +++ b/docs/kubernetes/scale.md @@ -2,21 +2,21 @@ ## Install Pre-requisites -All the commands in this guide require both the Azure CLI and `acs-engine`. Follow the [installation instructions to download acs-engine before continuing](../acsengine.md#install-acs-engine) or [compile from source](../acsengine.md#build-from-source). +All the commands in this guide require both the Azure CLI and `aks-engine`. Follow the [installation instructions to download aks-engine before continuing](../aksengine.md#install-aks-engine) or [compile from source](../aksengine.md#build-from-source). For installation instructions see [the Azure CLI GitHub repository](https://github.com/Azure/azure-cli#installation) for the latest release. -This guide assumes you already have deployed a cluster using acs engine. For more details on how to do that see [deploy](./deploy.md). +This guide assumes you already have deployed a cluster using AKS Engine. For more details on how to do that see [deploy](./deploy.md). ## Scale -After a cluster has been deployed using acs engine the cluster can be interacted further by using the scale command. The scale command can add more nodes to an existing node pool or remove them. Nodes will always be added or removed from the end of the agent pool. Nodes will be cordoned and drained before deletion. +After a cluster has been deployed using AKS Engine the cluster can be interacted further by using the scale command. The scale command can add more nodes to an existing node pool or remove them. Nodes will always be added or removed from the end of the agent pool. Nodes will be cordoned and drained before deletion. -This guide will assume you have a cluster deployed and the output for the deployed cluster is stored at _output/mycluster. It will also assume there is a node pool named "agentpool1" in your cluster. ACS engine will default to storing the output at ./_output/dns-prefix from where the acs-engine command was ran. +This guide will assume you have a cluster deployed and the output for the deployed cluster is stored at _output/mycluster. It will also assume there is a node pool named "agentpool1" in your cluster. AKS Engine will default to storing the output at ./_output/dns-prefix from where the aks-engine command was ran. To scale the cluster you will run a command like: ``` -$ acs-engine scale --subscription-id 51ac25de-afdg-9201-d923-8d8e8e8e8e8e \ +$ aks-engine scale --subscription-id 51ac25de-afdg-9201-d923-8d8e8e8e8e8e \ --resource-group mycluster --location westus2 \ --deployment-dir _output/mycluster --new-node-count 5 \ --node-pool agentpool1 --master-FQDN mycluster.westus2.cloudapp.azure.com @@ -30,7 +30,7 @@ This command will look the the deployment directory to find info about the clust |subscription-id|yes|The subscription id the cluster is deployed in.| |resource-group|yes|The resource group the cluster is deployed in.| |location|yes|The location the resource group is in.| -|deployment-dir|yes|Relative path to the folder location for the output from the acs-engine deploy/generate command.| +|deployment-dir|yes|Relative path to the folder location for the output from the aks-engine deploy/generate command.| |node-pool|depends|Required if there is more than one node pool. Which node pool should be scaled.| |new-node-count|yes|Desired number of nodes in the node pool.| |master-FQDN|depends|When scaling down a kuberentes cluster this is required. The master FDQN so that the nodes can be cordoned and drained before removal. This should be output as part of the create template or it can be found by looking at the public ip addresses in the resource group.| \ No newline at end of file diff --git a/docs/kubernetes/troubleshooting.md b/docs/kubernetes/troubleshooting.md index 31a7042cbd..58fb0a3047 100644 --- a/docs/kubernetes/troubleshooting.md +++ b/docs/kubernetes/troubleshooting.md @@ -2,7 +2,7 @@ ## VMExtensionProvisioningError or VMExtensionProvisioningTimeout -The two above VMExtensionProvisioning— errors tell us that a vm in the cluster failed installing required application prerequisites after CRP provisioned the VM into the resource group. When acs-engine creates a new Kubernetes cluster, a series of shell scripts runs to install prereq's like docker, etcd, Kubernetes runtime, and various other host OS packages that support the Kubernetes application layer. *Usually* this indicates one of the following: +The two above VMExtensionProvisioning— errors tell us that a vm in the cluster failed installing required application prerequisites after CRP provisioned the VM into the resource group. When aks-engine creates a new Kubernetes cluster, a series of shell scripts runs to install prereq's like docker, etcd, Kubernetes runtime, and various other host OS packages that support the Kubernetes application layer. *Usually* this indicates one of the following: 1. Something about the cluster configuration is pathological. For example, perhaps the cluster config includes a custom version of a particular software dependency that doesn't exist. Or, another example, for a cluster created inside a custom VNET (i.e., a user-provided, pre-existing VNET), perhaps that custom VNET does not have general outbound internet access, and so apt, docker pull, etc is not able to execute successfully. 2. A transient Azure environmental error caused the shell script operation to timeout, or exceed its retry count. For example, the shell script may attempt to download a required package (e.g., etcd), and if the Azure networking environment for the newly provisioned vm is flaky for a period of time, then the shell script may retry several times, but eventually timeout and fail. @@ -15,7 +15,7 @@ For classification #2 above, the appropriate strategic response is to retry a fe CSE stands for CustomScriptExtension, and is just a way of expressing: "a script that executes as part of the VM provisioning process, and that must exit 0 (i.e., successfully) in order for that VM provisioning process to succeed". Basically it's another way of expressing the VMExtensionProvisioning— concept above. -To summarize, the way that acs-engine implements Kubernetes on Azure is a collection of (1) Azure VM configuration + (2) shell script execution. Both are implemented as a single operational unit, and when #2 fails, we consider the entire VM provisioning operation to be a failure; more importantly, if only one VM in the cluster deployment fails, we consider the entire cluster operation to be a failure. +To summarize, the way that aks-engine implements Kubernetes on Azure is a collection of (1) Azure VM configuration + (2) shell script execution. Both are implemented as a single operational unit, and when #2 fails, we consider the entire VM provisioning operation to be a failure; more importantly, if only one VM in the cluster deployment fails, we consider the entire cluster operation to be a failure. ### How To Debug CSE errors (Linux) @@ -152,4 +152,4 @@ read and **write** permissions to the target Subscription. `Nov 10 16:35:22 k8s-master-43D6F832-0 docker[3177]: E1110 16:35:22.840688 3201 kubelet_node_status.go:69] Unable to construct api.Node object for kubelet: failed to get external ID from cloud provider: autorest#WithErrorUnlessStatusCode: POST https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47/oauth2/token?api-version=1.0 failed with 400 Bad Request: StatusCode=400` -[This documentation](../serviceprincipal.md) explains how to create/configure a service principal for an ACS-Engine Kubernetes cluster. +[This documentation](../serviceprincipal.md) explains how to create/configure a service principal for an AKS Engine Kubernetes cluster. diff --git a/docs/kubernetes/windows-details.md b/docs/kubernetes/windows-details.md index e69248268a..7f5d39c994 100644 --- a/docs/kubernetes/windows-details.md +++ b/docs/kubernetes/windows-details.md @@ -4,7 +4,7 @@ If you're trying to deploy Kubernetes with Windows the first time, be sure to ch ## Customizing Windows deployments -ACS-Engine allows a lot more customizations available in the [docs](../), but here are a few important ones you should know for Windows deployments. Each of these are extra parameters you can add into the ACS-Engine apimodel file (such as `kubernetes-windows.json` from the quick start) before running `acs-engine generate`. +AKS Engine allows a lot more customizations available in the [docs](../), but here are a few important ones you should know for Windows deployments. Each of these are extra parameters you can add into the AKS Engine apimodel file (such as `kubernetes-windows.json` from the quick start) before running `aks-engine generate`. ### Changing the OS disk size @@ -232,12 +232,12 @@ Get the Azure CNI build by running `C:\k\azurecni\bin\azure-vnet.exe --help`. It ### Known Issues per Version -ACS-Engine | Windows Server | Kubernetes | Azure CNI | Notes +AKS Engine | Windows Server | Kubernetes | Azure CNI | Notes -----------|----------------|------------|-----------|---------- V0.16.2 | Windows Server version 1709 (10.0.16299.____) | V1.9.7 | ? | DNS resolution is not configured -V0.17.0 | Windows Server version 1709 | V1.10.2 | v1.0.4 | Acs-engine version 0.17 defaults to Windows Server version 1803. You can override it to use 1709 instead [here](#choosing-the-windows-server-version). Manual workarounds needed on Windows for DNS Server list, DNS search suffix +V0.17.0 | Windows Server version 1709 | V1.10.2 | v1.0.4 | AKS Engine version 0.17 defaults to Windows Server version 1803. You can override it to use 1709 instead [here](#choosing-the-windows-server-version). Manual workarounds needed on Windows for DNS Server list, DNS search suffix V0.17.0 | Windows Server version 1803 (10.0.17134.1) | V1.10.2 | v1.0.4 | Manual workarounds needed on Windows for DNS Server list, DNS search suffix, and dropped packets -v0.17.1 | Windows Server version 1709 | v1.10.3 | v1.0.4-1-gf0f090e | Manual workarounds needed on Windows for DNS Server list and DNS search suffix. This ACS-Engine version defaults to Windows Server version 1803, but you can override it to use 1709 instead [here](#choosing-the-windows-server-version) +v0.17.1 | Windows Server version 1709 | v1.10.3 | v1.0.4-1-gf0f090e | Manual workarounds needed on Windows for DNS Server list and DNS search suffix. This AKS Engine version defaults to Windows Server version 1803, but you can override it to use 1709 instead [here](#choosing-the-windows-server-version) v0.18.3 | Windows Server version 1803 | v1.10.3 | v1.0.6 | Pods cannot resolve cluster DNS names v0.20.9 | Windows Server version 1803 | v1.10.6 | v1.0.11 | Pods cannot resolve cluster DNS names @@ -247,12 +247,12 @@ v0.20.9 | Windows Server version 1803 | v1.10.6 | v1.0.11 | Pods cannot resolve Affects: Windows Server version 1803 (10.0.17134.1) -Issues: https://github.com/Azure/acs-engine/issues/3037 +Issues: https://github.com/Azure/aks-engine/issues/3037 There is a problem with the “L2Tunnel” networking mode not forwarding packets correctly specific to Windows Server version 1803. Windows Server version 1709 is not affected. Workarounds: -**Fixes are still in development.** A Windows hotfix is needed, and will be deployed by ACS-Engine once it's ready. The hotfix will be removed later when it's in a future cumulative rollup. +**Fixes are still in development.** A Windows hotfix is needed, and will be deployed by AKS Engine once it's ready. The hotfix will be removed later when it's in a future cumulative rollup. #### Pods cannot resolve public DNS names @@ -310,7 +310,7 @@ Workaround: #### Pods cannot ping default route or internet IPs -Affects: All clusters deployed by acs-engine +Affects: All clusters deployed by aks-engine ICMP traffic is not routed between private Azure vNETs or to the internet. diff --git a/docs/kubernetes/windows.md b/docs/kubernetes/windows.md index a485cbcae4..39ed606f8d 100644 --- a/docs/kubernetes/windows.md +++ b/docs/kubernetes/windows.md @@ -1,4 +1,4 @@ -# Microsoft ACS-Engine - Kubernetes Windows Walkthrough +# Microsoft AKS Engine - Kubernetes Windows Walkthrough @@ -10,7 +10,7 @@ - [Create a Resource Group and Service Principal](#create-a-resource-group-and-service-principal) - [Create a Resource Group and Service Principal (Windows)](#create-a-resource-group-and-service-principal-windows) - [Create a Resource Group and Service Principal (Mac+Linux)](#create-a-resource-group-and-service-principal-maclinux) - - [Create an acs-engine apimodel](#create-an-acs-engine-apimodel) + - [Create an aks-engine apimodel](#create-an-aks-engine-apimodel) - [Filling out apimodel (Windows)](#filling-out-apimodel-windows) - [Filling out apimodel (Mac & Linux)](#filling-out-apimodel-mac--linux) - [Generate Azure Resource Manager template](#generate-azure-resource-manager-template) @@ -27,21 +27,21 @@ This guide will step through everything needed to build your first Kubernetes cluster and deploy a Windows web server on it. The steps include: - Getting the right tools -- Completing an ACS-Engine apimodel which describes what you want to deploy -- Running ACS-Engine to generate Azure Resource Model templates +- Completing an AKS Engine apimodel which describes what you want to deploy +- Running AKS Engine to generate Azure Resource Model templates - Deploying your first Kubernetes cluster with Windows Server nodes - Managing the cluster from your Windows machine - Deploying your first app on the cluster All of these steps can be done from any OS platform, so some sections are split out by Windows, Mac or Linux to provide the most relevant samples and scripts. If you have a Windows machine but want to use the Linux tools - no problem! Set up the [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/about) and you can follow the Linux instructions on this page. -> Note: Windows support for Kubernetes is still in beta and under **active development**. If you run into problems, please be sure to check the [Troubleshooting](windows-details.md#troubleshooting) page and [active Windows issues](https://github.com/azure/acs-engine/issues?&q=is:issue+is:open+label:windows) in this repo, then help us by filing new issues for things that aren't already covered. +> Note: Windows support for Kubernetes is still in beta and under **active development**. If you run into problems, please be sure to check the [Troubleshooting](windows-details.md#troubleshooting) page and [active Windows issues](https://github.com/Azure/aks-engine/issues?&q=is:issue+is:open+label:windows) in this repo, then help us by filing new issues for things that aren't already covered. ### Install Needed Tools This guide needs a few important tools, which are available on Windows, Mac, and Linux: -- ACS-Engine - used to generate the Azure Resource Manager (ARM) template to automatically deploy a Kubernetes cluster +- AKS Engine - used to generate the Azure Resource Manager (ARM) template to automatically deploy a Kubernetes cluster - Azure CLI - used to log into Azure, create resource groups, and deploy a Kubernetes cluster from a template - Kubectl - "Kube control" tool used to manage Kubernetes clusters - SSH - A SSH public key is needed when you deploy a cluster. It's used to connect to the Linux VMs running the cluster if you need to do more management or troubleshooting later. @@ -56,20 +56,20 @@ Once it's installed, make sure you can connect to Azure with it. Open a new Powe > If you want other versions, check out the [official instructions](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest). For more help, check out the Azure CLI [getting started](https://docs.microsoft.com/en-us/cli/azure/get-started-with-azure-cli?view=azure-cli-latest) page. -##### ACS-Engine (Windows) +##### AKS Engine (Windows) -Windows support is evolving rapidly, so be sure to use the latest ACS-Engine version (v0.20 or later). +Windows support is evolving rapidly, so be sure to use the latest AKS Engine version (v0.20 or later). -1. Browse to the ACS-Engine [releases page](https://github.com/Azure/acs-engine/releases) on GitHub. +1. Browse to the AKS Engine [releases page](https://github.com/Azure/aks-engine/releases) on GitHub. 2. Find the latest version, and download the file ending in `-windows-amd64.zip`. -3. Extract the `acs-engine...-windows-amd64.zip` file to a working folder such as `c:\tools` +3. Extract the `aks-engine...-windows-amd64.zip` file to a working folder such as `c:\tools` -4. Check that it runs with `.\acs-engine.exe version` +4. Check that it runs with `.\aks-engine.exe version` ```none -PS C:\Users\patrick\acs-engine> .\acs-engine.exe version +PS C:\Users\patrick\aks-engine> .\aks-engine.exe version Version: v0.20.6 GitCommit: 293adfda GitTreeState: clean @@ -88,7 +88,7 @@ $oldPath = [Environment]::GetEnvironmentVariable('Path', [EnvironmentVariableTar The latest release of Kubernetes Control (kubectl) is available on the [Kubernetes release page](https://kubernetes.io/docs/imported/release/notes/). Look for `kubernetes-client-windows-amd64.tar.gz` and download it. -Windows 10 version 1803 already includes `tar`, so extract the archive and move `kubectl.exe` to the same folder (such as `c:\tools`) that you put `acs-engine.exe`. If you don't already have `tar`, then [busybox-w32](https://frippery.org/busybox/) is a good alternative. Download [busybox.exe](https://frippery.org/files/busybox/busybox.exe), then copy it to `c:\tools\tar.exe`. It must be named to `tar.exe` for the next step to work. +Windows 10 version 1803 already includes `tar`, so extract the archive and move `kubectl.exe` to the same folder (such as `c:\tools`) that you put `aks-engine.exe`. If you don't already have `tar`, then [busybox-w32](https://frippery.org/busybox/) is a good alternative. Download [busybox.exe](https://frippery.org/files/busybox/busybox.exe), then copy it to `c:\tools\tar.exe`. It must be named to `tar.exe` for the next step to work. ```powershell tar xvzf C:\Users\patrick\Downloads\kubernetes-client-windows-amd64.tar.gz @@ -116,7 +116,7 @@ If the file already exists, then you can skip forward to [Create a Resource Grou If it does not exist, then run `ssh-keygen.exe`. Use the default file, and enter a passphrase if you wish to protect it. Be sure not to use a SSH key with blank passphrase in production. ```powershell -PS C:\Users\patrick\acs-engine> ssh-keygen.exe +PS C:\Users\patrick\aks-engine> ssh-keygen.exe Generating public/private rsa key pair. Enter file in which to save the key (C:\Users\patrick/.ssh/id_rsa): Created directory 'C:\Users\patrick/.ssh'. @@ -142,20 +142,20 @@ Most of the needed tools are available with [Homebrew](https://brew.sh/). Use it Once you have those installed, make sure you can log into Azure. Open a new Terminal window, then run `az login`. It will have you log in to Azure in your web browser, then return back to the command line and show "You have logged in. Now let us find all the subscriptions to which you have access..." along with the list of subscriptions. -##### ACS-Engine (Mac) +##### AKS Engine (Mac) -Windows support is evolving rapidly, so be sure to use the latest ACS-Engine version (v0.20 or later). +Windows support is evolving rapidly, so be sure to use the latest AKS Engine version (v0.20 or later). -1. Browse to the ACS-Engine [releases page](https://github.com/Azure/acs-engine/releases) on GitHub. +1. Browse to the AKS Engine [releases page](https://github.com/Azure/aks-engine/releases) on GitHub. 2. Find the latest version, and download the file ending in `-darwin-amd64.zip`. -3. Extract the `acs-engine...-darwin-amd64.zip` file to a folder in your path such as `/usr/local/bin` +3. Extract the `aks-engine...-darwin-amd64.zip` file to a folder in your path such as `/usr/local/bin` -4. Check that it runs with `acs-engine version` +4. Check that it runs with `aks-engine version` ```bash -$ acs-engine.exe version +$ aks-engine.exe version Version: v0.20.6 GitCommit: 293adfda GitTreeState: clean @@ -194,20 +194,20 @@ Packages for the `az` cli are available for most distributions. Please follow th Now, make sure you can log into Azure. Open a new Terminal window, then run `az login`. It will have you log in to Azure in your web browser, then return back to the command line and show "You have logged in. Now let us find all the subscriptions to which you have access..." along with the list of subscriptions. -##### ACS-Engine (Linux) +##### AKS Engine (Linux) -Windows support is evolving rapidly, so be sure to use the latest ACS-Engine version (v0.20 or later). +Windows support is evolving rapidly, so be sure to use the latest AKS Engine version (v0.20 or later). -1. Browse to the ACS-Engine [releases page](https://github.com/Azure/acs-engine/releases) on GitHub. +1. Browse to the AKS Engine [releases page](https://github.com/Azure/aks-engine/releases) on GitHub. 2. Find the latest version, and download the file ending in `-linux-amd64.zip`. -3. Extract the `acs-engine...-linux-amd64.zip` file to a folder in your path such as `/usr/local/bin` +3. Extract the `aks-engine...-linux-amd64.zip` file to a folder in your path such as `/usr/local/bin` -4. Check that it runs with `acs-engine version` +4. Check that it runs with `aks-engine version` ```bash -$ acs-engine.exe version +$ aks-engine.exe version Version: v0.20.6 GitCommit: 293adfda GitTreeState: clean @@ -251,14 +251,14 @@ If the file doesn't exist, run `ssh-keygen` to create one. Now that we have the Azure CLI configured and a SSH key generated, it's time to create a resource group to hold the deployment. -ACS-Engine and Kubernetes also need access to deploy resources inside that resource group to build the cluster, as well as configure more resources such as Azure Load Balancers once the cluster is running. This is done using an Azure Service Principal. It's safest to create one with access just to the resource group so that once your deployment is deleted, the service principal can't be used to make other changes in your subscription. +AKS Engine and Kubernetes also need access to deploy resources inside that resource group to build the cluster, as well as configure more resources such as Azure Load Balancers once the cluster is running. This is done using an Azure Service Principal. It's safest to create one with access just to the resource group so that once your deployment is deleted, the service principal can't be used to make other changes in your subscription. #### Create a Resource Group and Service Principal (Windows) `az group create --location --name ` will create a group for you. Be sure to use a unique name for each cluster. If you need a list of available locations, run `az account list-locations -o table`. ```powershell -PS C:\Users\patrick\acs-engine> az group create --location westus2 --name k8s-win1 +PS C:\Users\patrick\aks-engine> az group create --location westus2 --name k8s-win1 { "id": "/subscriptions/df392461-0000-1111-2222-cd3aa2d911a6/resourceGroups/k8s-win1", "location": "westus2", @@ -302,7 +302,7 @@ export SERVICEPRINCIPAL=$(az ad sp create-for-rbac --role="Contributor" --scopes ``` -### Create an acs-engine apimodel +### Create an aks-engine apimodel Multiple samples are available in this repo under [examples/windows](../../examples/windows/). This guide will use the [windows/kubernetes.json](../../examples/windows/kubernetes.json) sample to deploy 1 Linux VM to run Kubernetes services, and 2 Windows nodes to run your Windows containers. @@ -324,7 +324,7 @@ $windowsUser = "winuser" $windowsPassword = "Cr4shOverride!" # Download template -Invoke-WebRequest -UseBasicParsing https://raw.githubusercontent.com/Azure/acs-engine/master/examples/windows/kubernetes.json -OutFile kubernetes-windows.json +Invoke-WebRequest -UseBasicParsing https://raw.githubusercontent.com/Azure/aks-engine/master/examples/windows/kubernetes.json -OutFile kubernetes-windows.json # Load template $inJson = Get-Content .\kubernetes-windows.json | ConvertFrom-Json @@ -356,7 +356,7 @@ export DNSPREFIX="wink8s1" export WINDOWSUSER="winuser" export WINDOWSPASSWORD="Cr4shOverride!" -curl -L https://raw.githubusercontent.com/Azure/acs-engine/master/examples/windows/kubernetes.json -o kubernetes.json +curl -L https://raw.githubusercontent.com/Azure/aks-engine/master/examples/windows/kubernetes.json -o kubernetes.json cat kubernetes.json | \ jq ".properties.masterProfile.dnsPrefix = \"$DNSPREFIX\"" | \ @@ -369,10 +369,10 @@ jq ".properties.windowsProfile.adminUsername = \"$WINDOWSUSER\"" > kubernetes-wi ### Generate Azure Resource Manager template -Now that the ACS-Engine cluster definition is complete, generate the Azure templates with `acs-engine generate kubernetes-windows-complete.json` +Now that the AKS Engine cluster definition is complete, generate the Azure templates with `aks-engine generate kubernetes-windows-complete.json` ```none -acs-engine.exe generate kubernetes-windows-complete.json +aks-engine.exe generate kubernetes-windows-complete.json INFO[0000] Generating assets into _output/plangk8swin1... ``` @@ -399,7 +399,7 @@ After several minutes, it will return the list of resources created in JSON. Loo #### Check that the cluster is up -As mentioned earlier, `acs-engine generate` also creates Kubernetes configuration files under `_output//kubeconfig`. There will be one per possible region, so find the one matching the region you deployed in. +As mentioned earlier, `aks-engine generate` also creates Kubernetes configuration files under `_output//kubeconfig`. There will be one per possible region, so find the one matching the region you deployed in. In the example above with `dnsprefix`=`plangk8swin1` and the `westus2` region, the filename would be `_output/plangk8swin1/kubeconfig/kubeconfig.westus2.json`. @@ -530,7 +530,7 @@ Once your Kubernetes cluster has been created you will have a resource group con ![Image of Kubernetes cluster on azure with Windows](../images/kubernetes-windows.png) -These parts were all automatically created using the Azure Resource Manager template created by ACS-Engine: +These parts were all automatically created using the Azure Resource Manager template created by AKS Engine: 1. **Master Components** - The master runs the Kubernetes scheduler, api server, and controller manager. Port 443 is exposed for remote management with the kubectl cli. 2. **Linux Nodes** - the Kubernetes nodes run in an availability set. Azure load balancers are dynamically added to the cluster depending on exposed services. @@ -540,7 +540,7 @@ These parts were all automatically created using the Azure Resource Manager temp ## Next Steps -For more resources on Windows and ACS-Engine, continue reading: +For more resources on Windows and AKS Engine, continue reading: - [Customizing Windows Deployments](windows-details.md#customizing-windows-deployments) - [More Examples](windows-details.md#more-examples) diff --git a/docs/openshift.md b/docs/openshift.md deleted file mode 100644 index 7afb3705bd..0000000000 --- a/docs/openshift.md +++ /dev/null @@ -1,11 +0,0 @@ -# Microsoft Azure Container Service Engine - OpenShift - -[OpenShift](https://www.openshift.com/) is a distribution of [Kubernetes](https://kubernetes.io/) optimized for continuous application development and multi-tenant deployment. OpenShift adds developer and operations-centric tools on top of Kubernetes to enable rapid application development, easy deployment and scaling, and long-term lifecycle maintenance for small and large teams. - -* [OpenShift Origin Documentation](https://docs.openshift.org/latest/welcome/) -* [OpenShift Container Platform Documentation](https://docs.openshift.com/container-platform/latest/welcome/index.html) -* [OpenShift GitHub repository](https://github.com/openshift/origin) - -To deploy OpenShift cluster on Azure, follow this documentation: - -* [Create an OpenShift Cluster on Azure](openshift/deploy.md) - Create your first OpenShift cluster on Azure. Start here! diff --git a/docs/openshift/OWNERS b/docs/openshift/OWNERS deleted file mode 100644 index 4e1cf8514f..0000000000 --- a/docs/openshift/OWNERS +++ /dev/null @@ -1,4 +0,0 @@ -approvers: -- jim-minter -- kargakis -- pweil- diff --git a/docs/openshift/deploy.md b/docs/openshift/deploy.md deleted file mode 100644 index f66eb0b5c4..0000000000 --- a/docs/openshift/deploy.md +++ /dev/null @@ -1,161 +0,0 @@ -# Deploy an OpenShift Cluster - -## Install Pre-requisites - -All the commands in this guide require both the Azure CLI and `acs-engine`. Follow the [installation instructions to download acs-engine before continuing](../acsengine.md#install-acs-engine) or [compile it from source](../acsengine.md#build-from-source). - -To install the Azure CLI, follow [the official documentation](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) for your operating system. - -## Overview - -[acs-engine](https://github.com/Azure/acs-engine/blob/master/docs/acsengine.md) reads a cluster definition (or api model) which describes the size, shape, and configuration of your cluster. This guide follows the default configuration of one master and two Linux nodes, where one node is used by the OpenShift internal infrastructure, and the other one is for end-user workloads (compute node). At least one of each node type is required for a working OpenShift cluster. In the openshift.json file, one agent pool specifies the number of infrastructure node(s); another is used to specify the number of compute node(s). If you would like to change these numbers, edit [examples/openshift.json](/examples/openshift.json) before continuing. - -The `acs-engine deploy` command automates creation of a Service Principal, Resource Group and SSH key for your cluster. If operators need more control or are interested in the individual steps see the ["Long Way" section below](#acs-engine-the-long-way). - -## Preparing for the Deployment - -In order to deploy OpenShift, you will need the following: - -* The subscription and tenant ID in which you would like to provision the cluster. Both uuids can be found with `az account list -o json`, under the `id` and `tenantId` fields. -* Proper access rights within the subscription. Especially the right to create and assign service principals to applications (see ACS Engine the Long Way, Step #2). -* A `dnsPrefix` which forms part of the the hostname for your cluster (e.g. staging, prodwest, blueberry). The DNS prefix must be unique in the given geographical location, so pick a random name. -* A location to provision the cluster e.g. `eastus`. - -``` -$ az account list -o json -[ - { - "cloudName": "AzureCloud", - "id": "5eca53b6-18b4-4d9b-a4d4-a45a1ff367c8", - "isDefault": true, - "name": "Acme Corp", - "state": "Enabled", - "tenantId": "5a27b61b-1b6e-4be5-aa9d-0d5696076bb9", - "user": { - "name": "a2ada0c0-1a4d-4923-848f-c04b8b301c13", - "type": "servicePrincipal" - } - } -] -``` - -## Deploy - -For this example, the subscription id is `5eca53b6-18b4-4d9b-a4d4-a45a1ff367c8`, the tenant id is `5a27b61b-1b6e-4be5-aa9d-0d5696076bb9`, the DNS prefix and a resource group is `openshift-red`, and location is `eastus`. - -Before running the `acs-engine deploy` command, you must fill in all missing fields in the `examples/openshift.json` file. See the ["Long Way" section below](#acs-engine-the-long-way) for the description of required values. - -Now you can run `acs-engine deploy` with the appropriate arguments: - -``` -$ acs-engine deploy --subscription-id 5eca53b6-18b4-4d9b-a4d4-a45a1ff367c8 \ - --resource-group openshift-red --location eastus \ - --api-model examples/openshift.json - -INFO[0034] Starting ARM Deployment (openshift-red-1843927849). This will take some time... -INFO[0393] Finished ARM Deployment (openshift-red-1843927849). -``` - -As well as deploying the cluster, `acs-engine` will output Azure Resource Manager (ARM) templates, SSH keys (only if generated by `acs-engine`) and a node configuration in `_output/openshift-red` directory: - - * `_output/openshift-red/apimodel.json` - * `_output/openshift-red/azuredeploy.json` - * `_output/openshift-red/azuredeploy.parameters.json` - * `_output/openshift-red/master.tar.gz` - * `_output/openshift-red/node.tar.gz` - -Administrative note: By default, the directory where acs-engine stores cluster configuration (`_output/openshift-red` above) won't be overwritten as a result of subsequent attempts to deploy a cluster using the same `--dns-prefix`) To re-use the same resource group name repeatedly, include the `--force-overwrite` command line option with your `acs-engine deploy` command. - -Bonus tip: include an `--auto-suffix` option to append a randomly generated suffix to the dns-prefix to form the resource group name, for example if your workflow requires a common prefix across multiple cluster deployments. Using the `--auto-suffix` pattern appends a compressed timestamp to ensure a unique cluster name (and thus ensure that each deployment's configuration artifacts will be stored locally under a discrete `_output//` directory). - -After couple of minutes, your OpenShift web console should be accessible at `https://${dnsprefix}.${location}.cloudapp.azure.com:8443/`. You can log in with `clusterUsername` and `clusterPassword` values you set in the `openshift.json` file or with your Azure account if you've used AAD integration. - -For next steps, see [getting started documentation](https://docs.openshift.org/latest/getting_started/index.html) on OpenShift website. - -## ACS Engine the Long Way - -### Step 1: Generate an SSH Key - -In addition to using OpenShift web console, CLI and API to interact with the clusters, cluster operators may access the master machine using SSH. - -If you don't have an SSH key [cluster operators may generate a new one](../ssh.md#ssh-key-generation). - -### Step 2: Create a Service Principal - -The OpenShift cluster needs a Service Principal to interact with Azure Resource Manager (ARM), for example to dynamically create Azure persistent storage volumes. Follow the instructions to [create a new service principal](../serviceprincipal.md). - -### Step 3: Edit your Cluster Definition - -ACS Engine consumes a cluster definition which outlines the desired shape, size, and configuration of OpenShift. There are a number of features that can be enabled through the cluster definition: check the `examples` directory for a number of examples. - -Edit the [simple OpenShift cluster definition](/examples/openshift.json) and fill out the required values (every value with empty default `""` must be filled in): - -* `openShiftConfig`: contains authentication info for OpenShift. You must provide `clusterUsername` and `clusterPassword` for htpasswd authentication. Optionally you can set the `enableAADAuthentication` to `true` to enable AAD integration between OpenShift and Azure. AAD Authentication is preferred and more secure option, but requires more prerequisites and privileges to enable -* `azProfile`: Azure account information. `subscriptionId` and `tenantId` can be obtained from `$ az account list -o json` command. `resourceGroup` and `location` should be filled in based on your preference -* `masterProfile`: - * `count`: currently only one master is supported - * `dnsPrefix`: must be a region-unique name and will form part of the hostname (e.g. myprod1, staging, leapingllama) - * `vmSize`: must be at least `Standard_D4s_v3` -* `agentPoolProfiles`: contains specification for infrastructure and compute nodes - * `vmSize`: must be at least `Standard_D4s_v3` -* `linuxProfile`: `keyData` must contain the public portion of an SSH key - this will be associated with the `adminUsername` system user (e.g. 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABA....') -* `clientId`: this is the service principal's appId uuid or name from step 2. Leave blank if using AAD integration -* `secret`: this is the service principal's password or randomly-generated password from step 2. Leave blank if using AAD integration - -### Step 4: Generate the Templates - -The generate command takes a cluster definition and outputs a template and parameters file which describes your OpenShift cluster. By default, `generate` will create a new directory named after your cluster nested in the `_output` directory. If my dnsPrefix was `openshift-red` my cluster templates would be found in `_output/openshift-red-`. - -Run `acs-engine generate examples/openshift.json` - -### Step 5: Submit your Templates to Azure Resource Manager (ARM) - -[Deploy the output azuredeploy.json and azuredeploy.parameters.json](../acsengine.md#deployment-usage) - -### Step 6: Check the OpenShift cluster - -After couple of minutes, your OpenShift web console should be accessible at `https://${dnsprefix}.${location}.cloudapp.azure.com:8443/`. You can log in with `clusterUsername` and `clusterPassword` values you set in the `openshift.json` file or with your Azure account if you've used AAD integration. - -For next steps, see [getting started documentation](https://docs.openshift.org/latest/getting_started/index.html) on OpenShift website. - -## Custom VNET - -ACS Engine supports deploying into an existing VNET. Operators must specify the ARM path/id of Subnets for the `masterProfile` and any `agentPoolProfiles`, as well as the master IP address in `firstConsecutiveStaticIP`. Note: Currently OpenShift clusters cannot be set up in the 172.30.0.0/16 range. - -To create a vnet and a subnet, for example: - -```bash -az network vnet create -g $RESOURCE_GROUP -n $VNET_NAME --address-prefixes 10.239.0.0/16 --subnet-name $SUBNET_NAME --subnet-prefix 10.239.0.0/24 -``` -To get the `vnetSubnetId`: - -```bash -az network vnet subnet show -n $SUBNET_NAME -g $RESOURCE_GROUP --vnet-name $VNET_NAME --query id -``` - -Edit the [OpenShift with custom vnet cluster definition](/examples/vnet/openshift-vnet.json) and fill out the required values (every value with empty default `""` must be filled in). - -Before provisioning, modify the `masterProfile` and `agentPoolProfiles` to match the above requirements, with the below being a representative example: - -```json -"masterProfile": { - ... - "vnetSubnetId": "/subscriptions/SUB_ID/resourceGroups/RG_NAME/providers/Microsoft.Network/virtualNetworks/VNET_NAME/subnets/SUBNET_NAME", - "firstConsecutiveStaticIP": "10.239.0.239", - ... -}, -... -"agentPoolProfiles": [ - { - ... - "name": "compute", - "vnetSubnetId": "/subscriptions/SUB_ID/resourceGroups/RG_NAME/providers/Microsoft.Network/virtualNetworks/VNET_NAME/subnets/SUBNET_NAME", - ... - }, - { - ... - "name": "infra", - "vnetSubnetId": "/subscriptions/SUB_ID/resourceGroups/RG_NAME/providers/Microsoft.Network/virtualNetworks/VNET_NAME/subnets/SUBNET_NAME", - ... - }, -``` diff --git a/docs/roadmap/planning-process.md b/docs/roadmap/planning-process.md index 23590329ba..021ea47bc9 100644 --- a/docs/roadmap/planning-process.md +++ b/docs/roadmap/planning-process.md @@ -1,14 +1,14 @@ # Planning Process -acs-engine features a lightweight process that emphasizes openness and ensures every community member can see project goals for the future. +aks-engine features a lightweight process that emphasizes openness and ensures every community member can see project goals for the future. ## The Role of Maintainers -[Maintainers][] lead the acs-engine project. Their duties include proposing the Roadmap, reviewing and integrating contributions and maintaining the vision of the project. +[Maintainers][] lead the aks-engine project. Their duties include proposing the Roadmap, reviewing and integrating contributions and maintaining the vision of the project. ## Open Roadmap -The [acs-engine Roadmap](roadmap.md) is a community document. While Maintainers propose the Roadmap, it gets discussed and refined in Release Planning Meetings. +The [aks-engine Roadmap](roadmap.md) is a community document. While Maintainers propose the Roadmap, it gets discussed and refined in Release Planning Meetings. ## Contributing to the Roadmap @@ -24,5 +24,5 @@ Major decisions affecting the Roadmap are discussed during Release Planning Meet Release Planning Meetings are not currently open to non-Microsoft contributors, but we may change this in the future. -[Maintainers]: https://github.com/Azure/acs-engine/blob/master/OWNERS +[Maintainers]: https://github.com/Azure/aks-engine/blob/master/OWNERS [Release Schedule]: releases.md diff --git a/docs/roadmap/releases.md b/docs/roadmap/releases.md index 4ba15ffd69..8c6bcb3148 100644 --- a/docs/roadmap/releases.md +++ b/docs/roadmap/releases.md @@ -1,6 +1,6 @@ # Releases -acs-engine uses a [continuous delivery][] approach for creating releases. Every merged commit that passes +aks-engine uses a [continuous delivery][] approach for creating releases. Every merged commit that passes testing results in a deliverable that can be given a [semantic version][] tag and shipped. ## Release as Needed @@ -8,33 +8,33 @@ testing results in a deliverable that can be given a [semantic version][] tag an The master `git` branch of a project should always work. Only changes considered ready to be released publicly are merged. -acs-engine depends on components that release new versions as often as needed. Fixing +aks-engine depends on components that release new versions as often as needed. Fixing a high priority bug requires the project maintainer to create a new patch release. Merging a backward-compatible feature implies a minor release. By releasing often, each component release becomes a safe and routine event. This makes it faster and easier for users to obtain specific fixes. Continuous delivery also reduces the work -necessary to release a product such as acs-engine, which depends on several external projects. +necessary to release a product such as aks-engine, which depends on several external projects. "Components" applies not just to ACS projects, but also to development and release -tools, orchestrator versions (Kubernetes, DC/OS, Swarm),to Docker base images, and to other Azure +tools, Kubernetes orchestrator versions, to Docker base images, and to other Azure projects that do [semantic version][] releases. -## acs-engine Releases Each Month +## aks-engine Releases Each Month -acs-engine has a regular, public release cadence. From v0.1.0 onward, new acs-engine feature +aks-engine has a regular, public release cadence. From v0.1.0 onward, new aks-engine feature releases arrive on the first Thursday of each month. Patch releases are created at any time, as needed. GitHub milestones are used to communicate the content and timing of major and minor releases, and longer-term planning is visible at [the Roadmap](roadmap.md). -acs-engine release timing is not linked to specific features. If a feature is merged before the +aks-engine release timing is not linked to specific features. If a feature is merged before the release date, it is included in the next release. -See "[How to Release acs-engine](#how-to-release-acs-engine)" for more detail. +See "[How to Release aks-engine](#how-to-release-aks-engine)" for more detail. ## Semantic Versioning -acs-engine releases comply with [semantic versioning][semantic version], with the "public API" broadly +aks-engine releases comply with [semantic versioning][semantic version], with the "public API" broadly defined as: - REST, gRPC, or other API that is network-accessible @@ -44,16 +44,16 @@ defined as: - Integration with Azure public APIs such as ARM In general, changes to anything a user might reasonably link to, customize, or integrate with should -be backward-compatible, or else require a major release. acs-engine users can be confident that upgrading +be backward-compatible, or else require a major release. aks-engine users can be confident that upgrading to a patch or to a minor release will not break anything. -## How to Release acs-engine +## How to Release aks-engine -This section leads a maintainer through creating an acs-engine release. +This section leads a maintainer through creating an aks-engine release. ### Step 1: Assemble Master Changelog A change log is a file which contains a curated, chronologically ordered list of changes -for each version of acs-engine, which helps users and contributors see what notable changes +for each version of aks-engine, which helps users and contributors see what notable changes have been made between each version of the project. The CHANGELOG should be driven by release milestones defined on Github, which track specific deliverables and @@ -88,13 +88,13 @@ TBD ### Step 5: Let Everyone Know -Let the rest of the team know they can start blogging and tweeting about the new acs-engine release. +Let the rest of the team know they can start blogging and tweeting about the new aks-engine release. Post a message to the #company channel on Slack. Include a link to the released chart and to the master CHANGELOG: ``` -@here acs-engine 0.1.0 is here! -Master CHANGELOG: https://github.com/Azure/acs-engine/CHANGELOG.md +@here aks-engine 0.1.0 is here! +Master CHANGELOG: https://github.com/Azure/aks-engine/CHANGELOG.md ``` You're done with the release. Nice job! diff --git a/docs/serviceprincipal.md b/docs/serviceprincipal.md index 9453b1760b..0c64358d17 100644 --- a/docs/serviceprincipal.md +++ b/docs/serviceprincipal.md @@ -1,4 +1,4 @@ -# Microsoft Azure Container Service Engine +# Microsoft Azure Kubernetes Service Engine ## Service Principals diff --git a/docs/ssh.md b/docs/ssh.md index 939a26e37c..7e5dbfbda3 100644 --- a/docs/ssh.md +++ b/docs/ssh.md @@ -1,4 +1,4 @@ -# Microsoft Azure Container Service Engine - SSH +# Microsoft Azure Kubernetes Service Engine - SSH # SSH Key Management diff --git a/docs/swarm.md b/docs/swarm.md deleted file mode 100644 index a6bdecfdd4..0000000000 --- a/docs/swarm.md +++ /dev/null @@ -1,85 +0,0 @@ -# Microsoft Azure Container Service Engine - Swarm Walkthrough - -## Deployment - -Here are the steps to deploy a simple Swarm cluster: - -1. [Install acs-engine](acsengine.md#downloading-and-building-acs-engine) -2. [Generate your SSH key](ssh.md#ssh-key-generation) -3. [Edit the Swarm example](../examples/swarm.json) and fill in the blank strings -4. [Generate the template](acsengine.md#generate-templates) -5. [Deploy the output azuredeploy.json and azuredeploy.parameters.json](../docs/acsengine.md#deploy-templates) - -## Walkthrough - -Once your Swarm cluster has been deployed you will have a resource group containing: - -1. a set of 1,3, or 5 masters in a master availability set. Each master's SSH can be accessed via the public dns address at ports 2200..2204. First master's SSH can also be accessed via public dns address on port 22. - -2. a set of agents in a VM scale set (VMSS). The agent VMs can be accessed through a master. See [agent forwarding](ssh.md#key-management-and-agent-forwarding-with-windows-pageant) for an example of how to do this. - -The following image shows the architecture of a container service cluster with 3 masters, and 3 agents: - - ![Image of Swarm container service on azure](images/swarm.png) - - All VMs are in the same VNET where the masters are on private subnet 172.16.0.0/24 and the agents are on the private subnet, 10.0.0.0/16, and fully accessible to each other. - -## Create your First Two Swarm Docker Applications: hello-world, and Docker web app - -After completing this walkthrough you will know how to: - * display information from Swarm, - * deploy a simple Docker hello-world app using docker-compose, - * and deploy a simple Docker web app publically available to the world. - - - 1. After successfully deploying the template write down the two output master and agent FQDNs (Fully Qualified Domain Name). - 1. If using Powershell or CLI, the output parameters are the last values printed. - 2. If using Portal, to get the output you need to: - 1. navigate to "resource group" - 2. click on the resource group you just created - 3. then click on "Succeeded" under *last deployment* - 4. then click on the "Microsoft.Template" - 5. now you can copy the output FQDNs and sample SSH commands - - ![Image of docker scaling](images/findingoutputs.png) - - 2. SSH to port 2200 of the master FQDN. See [agent forwarding](ssh.md#key-management-and-agent-forwarding-with-windows-pageant) for an example of how to do this. - - 3. Set the DOCKER_HOST environment variable to `:2375`: e.g. ```export DOCKER_HOST=:2375``` - - 4. Type `docker info` to see the status of the agent nodes. - ![Image of docker info](images/dockerinfo.png) - - 5. Type `docker run -it hello-world` to see the hello-world test app run on one of the agents (the '-it' switches ensure output is displayed on your client) - - 6. Now let's create a simple web app and expose to the world. Start by using your favorite linux file editor to create a file named `docker-compose.yml` with the following contents: - ``` - web: - image: "yeasy/simple-web" - ports: - - "80:80" - restart: "always" - ``` - 7. type `docker-compose up -d` to create the simple web server. This will take a few minutes to pull the image - - 8. once completed, type `docker ps` to see the running image. - - ![Image of docker ps](images/dockerps.png) - - 9. in your web browser hit the AGENTFQDN endpoint (**not the master FQDN**) you recorded in step #1 and you should see the following page, with a counter that increases on each refresh. - - ![Image of the web page](images/swarmbrowser.png) - - 10. You can now scale the web application. For example, if you have 3 agents, you can type `docker-compose scale web=3`, and this will scale to the rest of your agents. Note that in this example you can only scale up to the number of agents that you have since each container requires port 80, so if you deployed a single agent, you won't be able to scale up. The Azure load balancer will automatically pick up the new containers. - - ![Image of docker scaling](images/dockercomposescale.png) - -# Learning More - -Here are recommended links to learn more about Swarm, Docker, and Docker Compose: - -1. [Docker](https://docs.docker.com/) - learn more through Docker documentation. - -2. [Docker Swarm](https://docs.docker.com/swarm/overview/) - learn more about Docker Swarm. - -3. [Docker Compose](https://docs.docker.com/compose/overview/) - Learn more about Docker Compose. diff --git a/docs/swarmmode-hybrid.md b/docs/swarmmode-hybrid.md deleted file mode 100644 index 6c17b9bc07..0000000000 --- a/docs/swarmmode-hybrid.md +++ /dev/null @@ -1,89 +0,0 @@ -# Microsoft Azure Container Service Engine - Hybrid Swarm Mode Walkthrough - -## Deployment - -Here are the steps to deploy a Hybrid Swarm Mode cluster: - -1. [Install acs-engine](acsengine.md#downloading-and-building-acs-engine) -2. [Generate your ssh key](ssh.md#ssh-key-generation) -3. [Edit the Hybrid Swarm Mode example](../examples/windows/swarmmode-hybrid.json) and fill in the blank strings -4. [Generate the template](acsengine.md#generate-templates) -5. [Deploy the output azuredeploy.json and azuredeploy.parameters.json](../README.md#deploy-templates) - -## Walkthrough - -After you edit the template with your values and deploy, you should have: -- 3 Linux masters -- 3 Linux agents -- 3 Windows agents (with Windows Server 2016 with Containers), -all in the same Swarm. - -SSH into one of the masters (`ssh yourlinuxuser@masterfqdn.yourregion.cloudapp.azure.com -p 220x`, where x is the number of your master instance - 0,1,2 in the default case) and list all nodes: `docker node ls`. The output should be similar to this: - -![](images/swarmmode-hybrid-docker-node-ls.png) - -> NOTE - if you only see the Linux masters and agents, a working solution is to reimage the Windows agents scale set - that is restoring the VMs to the initial state and restart them. This will reapply all the steps in the installation, [mainly this one that installs the container host and joins the Swarm](https://github.com/Azure/acs-engine/blob/master/parts/swarm/Install-ContainerHost-And-Join-Swarm.ps1). - -Now you can inspect one of the Windows agents with `docker node inspect `: - -![](images/swarmmode-hybrid-docker-node-inspect.png) - - -##Limitations - -As the [Windows Server Containers documentation](https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/swarm-mode#limitations) states, at the moment there are a few limitations to Swarm Mode with Windows hosts. - -The most important is that the routing mesh is not available for Windows Server at the moment, but you can publish ports on the host (`docker service create --publish mode=host`) - - -## Create your first hybrid deployment on the Swarm - -Now that you have a functional Hybrid Swarm Mode cluster in Azure, it is time to deploy a hybrid application: a Python front-end that will run on Linux, with a Redis data store on Windows. Here is the stack file for our services: - -``` -version: "3" -services: - - redis: - image: redis:3.2.100-nanoserver - deploy: - placement: - constraints: [node.platform.os == windows] - - python-web: - image: radumatei/python-web - ports: - - "80:80" -``` - -> [The Python application can be found here](https://github.com/microsoft-dx/docker-lab/tree/master/apps/python-redis) and is very similar to the [Docker Compose one from the Official Docker Docs](https://docs.docker.com/compose/gettingstarted/) - -On one of the masters create the file above and name it `hybrid-stack.yml`. In order to deploy it, execute: `docker stack deploy --compose-file hybrid-stack.yml python-redis`: - - -![](images/swarmmode-hybrid-stack-deploy.png) - -Now if you execute `docker service ls` you should see the two services: - -![](images/swarmmode-hybrid-service-ls.png) - -[Since the Nanoserver Redis image](https://hub.docker.com/r/library/redis/) is around 340 MB, it will take a little to pull it, then start a container. -After the container started, we can go to the Linux agents FQDN (the one you setup when editing the `swarmmode-hybrid.json` file) and access it from a browser: - -> Note that on the first run it might take a little while - -![](images/swarmmode-hybrid-linux-agents.png) - -## Learning more - -Here are recommended links to learn more about Swarm Mode, Docker, and Docker Compose: - -1. [Docker](https://docs.docker.com/) - learn more through Docker documentation. - -2. [Docker Swarm Mode](https://docs.docker.com/engine/swarm/) - learn more about Docker Swarm Mode. - -For hybrid swarms, you can check the following resources: - -3. Use Docker Swarm to run a Windows+Linux containerized application - [Part 1](https://www.youtube.com/watch?v=ZfMV5JmkWCY&t=170s), [Part 2](https://www.youtube.com/watch?v=VbzwKbcC_Mg&t=406s), [Part 3](https://www.youtube.com/watch?v=I9oDD78E_1E&t=354s) - -4. [The Hybrid Swarm: Running Windows and Linux Apps in one Docker Cluster - Talk by Elton Stoneman, Docker Captain](https://channel9.msdn.com/Events/DXPortugal/OSCAMP-Open-Source-Software-powered-by-Bright-Pixel/The-Hybrid-Swarm-Running-Windows-and-Linux-Apps-in-one-Docker-Cluster) diff --git a/docs/swarmmode.md b/docs/swarmmode.md deleted file mode 100644 index 71d5d32074..0000000000 --- a/docs/swarmmode.md +++ /dev/null @@ -1,73 +0,0 @@ -# Microsoft Azure Container Service Engine - Swarm Mode Walkthrough - -## Deployment - -Here are the steps to deploy a simple Swarm Mode cluster: - -1. [Install acs-engine](acsengine.md#downloading-and-building-acs-engine) -2. [Generate your ssh key](ssh.md#ssh-key-generation) -3. [Edit the Swarm Mode example](../examples/swarmmode.json) and fill in the blank strings -4. [Generate the template](acsengine.md#generate-templates) -5. [Deploy the output azuredeploy.json and azuredeploy.parameters.json](../docs/acsengine.md#deploy-templates) - -## Walkthrough - -Once your Swarm Mode cluster has been deployed you will have a resource group containing: - -1. a set of 1,3, or 5 masters in a master availability set. Each master's SSH can be accessed via the public dns address at ports 2200..2204. First master's SSH can also be accessed via public dns address on port 22. - -2. a set of agents in a VM scale set (VMSS). The agent VMs can be accessed through a master. See [agent forwarding](ssh.md#key-management-and-agent-forwarding-with-windows-pageant) for an example of how to do this. - -The following image shows the architecture of a container service cluster with 3 masters, and 3 agents: - - ![Image of Swarm container service on azure](images/swarm.png) - - All VMs are in the same VNET where the masters are on private subnet 172.16.0.0/24 and the agents are on the private subnet, 10.0.0.0/16, and fully accessible to each other. - -## Create your First Two Swarm Mode Docker services: hello-world, and Docker web app - -After completing this walkthrough you will know how to: - * display information from Swarm Mode, - * deploy a simple Docker hello-world app using docker-compose, - * and deploy a simple Docker web app publically available to the world. - - - 1. After successfully deploying the template write down the two output master and agent FQDNs (Fully Qualified Domain Name). - 1. If using Powershell or CLI, the output parameters are the last values printed. - 2. If using Portal, to get the output you need to: - 1. navigate to "resource group" - 2. click on the resource group you just created - 3. then click on "Succeeded" under *last deployment* - 4. then click on the "Microsoft.Template" - 5. now you can copy the output FQDNs and sample SSH commands - - ![Image of docker scaling](images/findingoutputs.png) - - 2. SSH to port 2200 of the master FQDN (or first master's SSH can also be accessed via public dns address on port 22.). See [agent forwarding](ssh.md#key-management-and-agent-forwarding-with-windows-pageant) for an example of how to do this. - - 3. Type `docker node ls` to view the list of nodes (and their status) in the Swarm. - ![Image of docker node ls](images/dockernodels.png) - - 4. Type `docker run -it hello-world` to see the hello-world test app run on one of the agents (the '-it' switches ensure output is displayed on your client) - - 5. Now let's create a simple service in a swarm and expose it to the world. Type `docker service create --name fe --publish 80:80 yeasy/simple-web` - - 6. Once completed, type `docker service ps fe` to see the running service. - - ![Image of docker service ps](images/dockerserviceps.png) - - 7. In your web browser hit the AGENTFQDN endpoint (**not the master FQDN**) you recorded in step #1 and you should see the following page, with a counter that increases on each refresh. - - ![Image of the web page](images/swarmbrowser.png) - - 8. You can now scale the service. You can type `docker service scale fe=5`, and this will scale up the service to the desired number of replicas. - - ![Image of service scaling](images/dockerservicescale.png) - -# Learning More - -Here are recommended links to learn more about Swarm Mode, Docker, and Docker Compose: - -1. [Docker](https://docs.docker.com/) - learn more through Docker documentation. - -2. [Docker Swarm Mode](https://docs.docker.com/engine/swarm/) - learn more about Docker Swarm Mode. \ No newline at end of file diff --git a/examples/README.md b/examples/README.md index 9bcb95a64a..d71b27f79d 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,19 +1,16 @@ -# Microsoft Azure Container Service Engine - Builds Docker Enabled Clusters +# Microsoft Azure Kubernetes Service Engine - Builds Kubernetes Clusters ## Overview -These cluster definition examples demonstrate how to create a customized Docker Enabled Cluster on Microsoft Azure. +These cluster definition examples demonstrate how to create a customized Kubernetes Cluster on Microsoft Azure. ## Walkthroughs -* [ACS Engine](../docs/acsengine.md) - shows you how to use the ACS engine to generate custom Docker enabled container clusters +* [AKS Engine](../docs/aksengine.md) - shows you how to use the AKS Engine to generate custom Kubernetes container clusters * [Cluster Definition](../docs/clusterdefinition.md) - describes the components of the cluster definition file -* [DC/OS Walkthrough](../docs/dcos.md) - shows how to create a DC/OS enabled Docker cluster on Azure -* [Kubernetes Walkthrough](../docs/kubernetes.md) - shows how to create a Kubernetes enabled Docker cluster on Azure -* [Swarm Walkthrough](../docs/swarm.md) - shows how to create a Swarm enabled Docker cluster on Azure -* [Swarm Mode Walkthrough](../docs/swarmmode.md) - shows how to create a Swarm Mode cluster on Azure -* [Custom VNET](vnet) - shows how to use a custom VNET +* [Kubernetes Walkthrough](../docs/kubernetes.md) - shows how to create a Kubernetes cluster on Azure +* [Custom VNET](vnet) - shows how to use a custom VNET * [Attached Disks](disks-storageaccount) - shows how to attach up to 4 disks per node -* [Managed Disks](disks-managed) (under private preview) - shows how to use managed disks +* [Managed Disks](disks-managed) (under private preview) - shows how to use managed disks * [Large Clusters](largeclusters) - shows how to create cluster sizes of up to 1200 nodes * [Windows Clusters](windows) - shows how to create mixed Microsoft Windows and Linux Docker clusters on Microsoft Azure diff --git a/examples/azure-cni/k8s-scale.sh b/examples/azure-cni/k8s-scale.sh index fe772108a4..caf8b74ed6 100755 --- a/examples/azure-cni/k8s-scale.sh +++ b/examples/azure-cni/k8s-scale.sh @@ -15,7 +15,7 @@ OUTPUT="_output/${INSTANCE_NAME}" # allow nodes to run for a while before scaling sleep 180 -./bin/acs-engine scale \ +./bin/aks-engine scale \ --subscription-id ${SUBSCRIPTION_ID} \ --deployment-dir ${OUTPUT} \ --location ${LOCATION} \ diff --git a/examples/azure-cni/k8s-scaledown.json.env b/examples/azure-cni/k8s-scaledown.json.env index edf562b01d..58ac8babf0 100644 --- a/examples/azure-cni/k8s-scaledown.json.env +++ b/examples/azure-cni/k8s-scaledown.json.env @@ -1,4 +1,4 @@ -ACSE_POSTDEPLOY=examples/azure-cni/k8s-scale.sh +AKSE_POSTDEPLOY=examples/azure-cni/k8s-scale.sh NEW_AGENT_NODE_COUNT=2 EXPECTED_NODE_COUNT=3 diff --git a/examples/azure-cni/k8s-scaleup.json.env b/examples/azure-cni/k8s-scaleup.json.env index b89b76f2ca..b77dcf9c8a 100644 --- a/examples/azure-cni/k8s-scaleup.json.env +++ b/examples/azure-cni/k8s-scaleup.json.env @@ -1,4 +1,4 @@ -ACSE_POSTDEPLOY=examples/azure-cni/k8s-scale.sh +AKSE_POSTDEPLOY=examples/azure-cni/k8s-scale.sh NEW_AGENT_NODE_COUNT=3 EXPECTED_NODE_COUNT=4 diff --git a/examples/azure-cni/k8s-vnet-scaledown.json.env b/examples/azure-cni/k8s-vnet-scaledown.json.env index 9413e165cc..0ce4b07009 100644 --- a/examples/azure-cni/k8s-vnet-scaledown.json.env +++ b/examples/azure-cni/k8s-vnet-scaledown.json.env @@ -1,5 +1,5 @@ -ACSE_PREDEPLOY=examples/vnet/k8s-vnet-azure-cni-predeploy.sh -ACSE_POSTDEPLOY=examples/azure-cni/k8s-scale.sh +AKSE_PREDEPLOY=examples/vnet/k8s-vnet-azure-cni-predeploy.sh +AKSE_POSTDEPLOY=examples/azure-cni/k8s-scale.sh NEW_AGENT_NODE_COUNT=2 EXPECTED_NODE_COUNT=3 diff --git a/examples/azure-cni/k8s-vnet-scaleup.json.env b/examples/azure-cni/k8s-vnet-scaleup.json.env index f0675dd449..b495b5aeb7 100644 --- a/examples/azure-cni/k8s-vnet-scaleup.json.env +++ b/examples/azure-cni/k8s-vnet-scaleup.json.env @@ -1,5 +1,5 @@ -ACSE_PREDEPLOY=examples/vnet/k8s-vnet-azure-cni-predeploy.sh -ACSE_POSTDEPLOY=examples/azure-cni/k8s-scale.sh +AKSE_PREDEPLOY=examples/vnet/k8s-vnet-azure-cni-predeploy.sh +AKSE_POSTDEPLOY=examples/azure-cni/k8s-scale.sh NEW_AGENT_NODE_COUNT=3 EXPECTED_NODE_COUNT=4 diff --git a/examples/customfiles/README.md b/examples/customfiles/README.md index 3cd85160aa..dff5413e30 100644 --- a/examples/customfiles/README.md +++ b/examples/customfiles/README.md @@ -1,8 +1,8 @@ -# Microsoft Azure Container Service Engine - Provisioning of master node custom files +# Microsoft Azure Kubernetes Service Engine - Provisioning of master node custom files ## Overview -ACS-Engine enables you to provision custom files to your master nodes. This can be used to put whichever files you want on your master nodes to whichever path you want (and have permission to). For example, the use case is when you want additional configurations to native kubernetes features, such as in +AKS Engine enables you to provision custom files to your master nodes. This can be used to put whichever files you want on your master nodes to whichever path you want (and have permission to). For example, the use case is when you want additional configurations to native kubernetes features, such as in the [given example](../examples/customfiles/kubernetes-customfiles-podnodeselector.yaml) ## Examples diff --git a/examples/dcos-D2.json b/examples/dcos-D2.json deleted file mode 100644 index 84eae3280c..0000000000 --- a/examples/dcos-D2.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 1, - "vmSize": "Standard_D2" - }, - { - "name": "agentpublic", - "count": 1, - "vmSize": "Standard_D2", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} diff --git a/examples/dcos-attributes/README.md b/examples/dcos-attributes/README.md deleted file mode 100644 index 185c268e03..0000000000 --- a/examples/dcos-attributes/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# DCOS Agent Node Attributes - -Attributes can be defined for each agent node type. -The attributes can then be used with Marathon deployments as [placement contraints](https://mesosphere.github.io/marathon/docs/constraints.html). - -Attributes can easily be defined in AgentPoolProfile property of the API Model - -The definition below adds 2 attributes `"foo"` and `"att1"` to all nodes in the `agentprivate` pool. - -``` - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2", - "customNodeLabels" : { - "foo" : "bar", - "att1" : "value1" - } - } - ] -``` - -You can confirm the attributes on the Node Details: - -![Node UI Details](images/dcosattributes.png) \ No newline at end of file diff --git a/examples/dcos-attributes/dcos.json b/examples/dcos-attributes/dcos.json deleted file mode 100644 index 1ef14c6cff..0000000000 --- a/examples/dcos-attributes/dcos.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "xtentprivate", - "count": 3, - "vmSize": "Standard_D2_v2", - "customNodeLabels" : { - "foo" : "bar", - "attribute1" : "value1" - } - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} diff --git a/examples/dcos-attributes/images/dcosattributes.png b/examples/dcos-attributes/images/dcosattributes.png deleted file mode 100644 index efedd16f09df6d60c1e9f09fa729db3d8bbc4f22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8450 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 Um%%*ne+!^%m#r>QE}$R&7n4bE{r~^~ diff --git a/examples/dcos-private-registry/README.md b/examples/dcos-private-registry/README.md deleted file mode 100644 index 348b3f06f6..0000000000 --- a/examples/dcos-private-registry/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# Private Registry Support - -ACS can deploy credentials to private registries to agent nodes DC/OS clusters. - -The credentials are specified in the orchestrator profile in the apimodel: -``` - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS", - "dcosConfig" : { - "Registry" : "", - "RegistryUser" : "", - "RegistryPassword" : "" - } - }, -``` - -The agent provisioning process will then create a tar archive containing a docker config as documented at: [Using a Private Docker Registry](https://docs.mesosphere.com/1.9/deploying-services/private-docker-registry/) - -## Example -Let's provision a DC/OS cluster with credentials to an [Azure Container Registry](https://azure.microsoft.com/en-us/services/container-registry/) deployed to every agent node. - -- First, [provision an Azure Container Registry](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-managed-get-started-portal). - -- Enable Admin Access and note the registry credentials -ACR Blade with Admin Access enabled - -- Clone [acs-engine](http://github.com/azure/acs-engine) and [start the container with the dev environment](https://github.com/Azure/acs-engine/blob/master/docs/acsengine.md). - -- Edit the API model to include the credentials -``` - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS", - "registry" : "xtophregistry.azurecr.io", - "registryUser" : "xtophregistry", - "registryPassword" : "aN//=+l==Z+/A=3hXhA+mSX=rXwB/UgW" - }, -``` - -- Run acs-engine to create ARM templates -``` -./acs-engine generate examples/dcos-private-registry/dcos.json -``` - -- Deploy the cluster -``` -az group create -l eastus -n cluster-rg -az group deployment create -g cluster-rg --template-file _output/dcoscluster/azuredeploy.json --parameters @_output/dcoscluster/azuredeploy.parameters.json -``` - -- Create a Service to deploy a container from the ACR -Service Creation from Registry - -- Add the credential path on the agent using the JSON editor -JSON editor with credential path - -- See the Service running -Running Service - -- Check the credential deployment -Running Service - -## Limitations -- The API model currenlty only supports credentials to a single registry. -- Not tested with Kubernetes clusters -- Credentials have to be updated on each node \ No newline at end of file diff --git a/examples/dcos-private-registry/dcos.json b/examples/dcos-private-registry/dcos.json deleted file mode 100644 index c58e5503c5..0000000000 --- a/examples/dcos-private-registry/dcos.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS", - "dcosConfig" : { - "registry" : "", - "registryUser" : "", - "registryPassword" : "" - } - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 1, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpublic", - "count": 1, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} diff --git a/examples/dcos-releases/README.md b/examples/dcos-releases/README.md deleted file mode 100644 index f067072489..0000000000 --- a/examples/dcos-releases/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Microsoft Azure Container Service Engine - DC/OS Versions - -## Overview - -This section provides example templates enable creation of Docker enabled cluster with older version of the DC/OS orchestrator. - -Here are the release channels acs-engine is able to deploy: - -1. DC/OS `1.8`. Access by specifying `"orchestratorVersion": "1.8.8"`. -2. DC/OS `1.9`. Access by specifying `"orchestratorVersion": "1.9.0"`. -3. DC/OS `1.10`. Access by specifying `"orchestratorVersion": "1.10.0"`. - -Deploying and using [DC/OS](../../docs/dcos.md) diff --git a/examples/dcos-releases/dcos1.10.json b/examples/dcos-releases/dcos1.10.json deleted file mode 100644 index ade44c559e..0000000000 --- a/examples/dcos-releases/dcos1.10.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS", - "orchestratorRelease": "1.10" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "", - "vmSize": "Standard_D2s_v3" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 2, - "vmSize": "Standard_D2s_v3" - }, - { - "name": "agentpublic", - "count": 2, - "vmSize": "Standard_D2s_v3", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} diff --git a/examples/dcos-releases/dcos1.8.json b/examples/dcos-releases/dcos1.8.json deleted file mode 100644 index 0d42ff171c..0000000000 --- a/examples/dcos-releases/dcos1.8.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS", - "orchestratorRelease": "1.8" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "", - "vmSize": "Standard_D2s_v3" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2s_v3" - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2s_v3", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} diff --git a/examples/dcos-releases/dcos1.9.json b/examples/dcos-releases/dcos1.9.json deleted file mode 100644 index 3936799ce3..0000000000 --- a/examples/dcos-releases/dcos1.9.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS", - "orchestratorRelease": "1.9" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "", - "vmSize": "Standard_D2s_v3" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2s_v3" - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2s_v3", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} diff --git a/examples/dcos.json b/examples/dcos.json deleted file mode 100644 index 125dccbf5c..0000000000 --- a/examples/dcos.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2s_v3" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 2, - "vmSize": "Standard_D2s_v3" - }, - { - "name": "agentpublic", - "count": 2, - "vmSize": "Standard_D2s_v3", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} diff --git a/examples/disks-managed/README.md b/examples/disks-managed/README.md index 6f2fd06ec1..9cf0f60db4 100644 --- a/examples/disks-managed/README.md +++ b/examples/disks-managed/README.md @@ -1,7 +1,7 @@ -# Microsoft Azure Container Service Engine - Managed Disks +# Microsoft Azure Kubernetes Service Engine - Managed Disks ## Overview -ACS-Engine enables you to create customized Docker enabled cluster on Microsoft Azure with [managed disks](https://docs.microsoft.com/en-us/azure/storage/storage-managed-disks-overview). +AKS Engine enables you to create customized Kubernetes clusters on Microsoft Azure with [managed disks](https://docs.microsoft.com/en-us/azure/storage/storage-managed-disks-overview). These examples are provided as a reference, note that managed disks is the default storage account type if none is specified. diff --git a/examples/disks-managed/dcos-preAttachedDisks-vmas.json b/examples/disks-managed/dcos-preAttachedDisks-vmas.json deleted file mode 100644 index e544e61eb3..0000000000 --- a/examples/disks-managed/dcos-preAttachedDisks-vmas.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2s_v3" - }, - "agentPoolProfiles": [ - { - "name": "agentpublic", - "count": 6, - "vmSize": "Standard_D2s_v3", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "ManagedDisks", - "diskSizesGB": [128, 128, 128, 128], - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/disks-managed/dcos-preAttachedDisks-vmas.json.env b/examples/disks-managed/dcos-preAttachedDisks-vmas.json.env deleted file mode 100644 index 7404e4a54f..0000000000 --- a/examples/disks-managed/dcos-preAttachedDisks-vmas.json.env +++ /dev/null @@ -1 +0,0 @@ -MARATHON_JSON=marathon-slave-public.json diff --git a/examples/disks-managed/dcos-preAttachedDisks-vmss.json b/examples/disks-managed/dcos-preAttachedDisks-vmss.json deleted file mode 100644 index 5b8b22dc3c..0000000000 --- a/examples/disks-managed/dcos-preAttachedDisks-vmss.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agent128", - "count": 3, - "vmSize": "Standard_D2_v2", - "AvailabilityProfile": "VirtualMachineScaleSets", - "storageProfile": "ManagedDisks", - "diskSizesGB": [128, 128, 128, 128] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/disks-managed/dcos-vmas.json b/examples/disks-managed/dcos-vmas.json deleted file mode 100644 index 12fccad1a4..0000000000 --- a/examples/disks-managed/dcos-vmas.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2", - "OSDiskSizeGB": 200 - }, - "agentPoolProfiles": [ - { - "name": "agent128", - "count": 3, - "vmSize": "Standard_D2_v2", - "OSDiskSizeGB": 200, - "availabilityProfile": "AvailabilitySet", - "storageProfile": "ManagedDisks" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/disks-managed/dcos-vmss.json b/examples/disks-managed/dcos-vmss.json deleted file mode 100644 index 440e4b0849..0000000000 --- a/examples/disks-managed/dcos-vmss.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2s_v3", - "OSDiskSizeGB": 200 - }, - "agentPoolProfiles": [ - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2s_v3", - "OSDiskSizeGB": 200, - "AvailabilityProfile": "VirtualMachineScaleSets", - "storageProfile": "ManagedDisks", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/disks-managed/dcos-vmss.json.env b/examples/disks-managed/dcos-vmss.json.env deleted file mode 100644 index 7404e4a54f..0000000000 --- a/examples/disks-managed/dcos-vmss.json.env +++ /dev/null @@ -1 +0,0 @@ -MARATHON_JSON=marathon-slave-public.json diff --git a/examples/disks-managed/swarm-preAttachedDisks-vmas.json b/examples/disks-managed/swarm-preAttachedDisks-vmas.json deleted file mode 100644 index 0fe76bd112..0000000000 --- a/examples/disks-managed/swarm-preAttachedDisks-vmas.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpool1", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "ManagedDisks", - "diskSizesGB": [128, 128, 128, 128] - }, - { - "name": "agentpublic", - "count": 3, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "ManagedDisks", - "diskSizesGB": [128, 128, 128, 128], - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/disks-managed/swarm-preAttachedDisks-vmss.json b/examples/disks-managed/swarm-preAttachedDisks-vmss.json deleted file mode 100644 index 5563335ffd..0000000000 --- a/examples/disks-managed/swarm-preAttachedDisks-vmss.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpool1", - "count": 1, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "VirtualMachineScaleSets", - "storageProfile": "ManagedDisks", - "diskSizesGB": [128, 128, 128, 128] - }, - { - "name": "agentpublic", - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2", - "availabilityProfile": "VirtualMachineScaleSets", - "storageProfile": "ManagedDisks", - "diskSizesGB": [128, 128, 128, 128], - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/disks-managed/swarm-vmas.json b/examples/disks-managed/swarm-vmas.json deleted file mode 100644 index c20f44e597..0000000000 --- a/examples/disks-managed/swarm-vmas.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpool1", - "count": 3, - "vmSize": "Standard_D2_v2", - "OSDiskSizeGB": 200, - "availabilityProfile": "AvailabilitySet", - "storageProfile": "ManagedDisks" - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "OSDiskSizeGB": 200, - "availabilityProfile": "AvailabilitySet", - "storageProfile": "ManagedDisks", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/disks-managed/swarm-vmss.json b/examples/disks-managed/swarm-vmss.json deleted file mode 100644 index b9cd60e946..0000000000 --- a/examples/disks-managed/swarm-vmss.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpool1", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "VirtualMachineScaleSets", - "storageProfile": "ManagedDisks" - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "VirtualMachineScaleSets", - "storageProfile": "ManagedDisks", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/disks-managed/swarmmode-vmas.json b/examples/disks-managed/swarmmode-vmas.json deleted file mode 100644 index 085db0785a..0000000000 --- a/examples/disks-managed/swarmmode-vmas.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpool1", - "count": 1, - "vmSize": "Standard_D2_v2", - "OSDiskSizeGB": 200, - "availabilityProfile": "AvailabilitySet", - "storageProfile": "ManagedDisks" - }, - { - "name": "agentpublic", - "count": 1, - "vmSize": "Standard_D2_v2", - "OSDiskSizeGB": 200, - "availabilityProfile": "AvailabilitySet", - "storageProfile": "ManagedDisks", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/disks-managed/swarmmode-vmss.json b/examples/disks-managed/swarmmode-vmss.json deleted file mode 100644 index ea4b223069..0000000000 --- a/examples/disks-managed/swarmmode-vmss.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpool1", - "count": 1, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "VirtualMachineScaleSets", - "storageProfile": "ManagedDisks" - }, - { - "name": "agentpublic", - "count": 1, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "VirtualMachineScaleSets", - "storageProfile": "ManagedDisks", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/disks-storageaccount/README.md b/examples/disks-storageaccount/README.md index 2ccb135058..9be3e68412 100644 --- a/examples/disks-storageaccount/README.md +++ b/examples/disks-storageaccount/README.md @@ -1,12 +1,9 @@ -# Microsoft Azure Container Service Engine - Attached Disks +# Microsoft Azure Kubernetes Service Engine - Attached Disks ## Overview -ACS-Engine enables you to create customized Docker enabled cluster on Microsoft Azure with attached disks. +AKS Engine enables you to create a customized Kuberntes cluster on Microsoft Azure with attached disks. The examples show you how to configure up to 4 attached disks. The disks can range from 1 to 1024 GB in size: -1. **dcos.json** - deploying and using [DC/OS](../../docs/dcos.md) -2. **kubernetes.json** - deploying and using [Kubernetes](../../docs/kubernetes.md) -3. **swarm.json** - deploying and using [Swarm](../../docs/swarm.md) -4. **swarmmode.json** - deploying and using [Swarm Mode](../../docs/swarmmode.md) \ No newline at end of file +1. **kubernetes.json** - deploying and using [Kubernetes](../../docs/kubernetes.md) diff --git a/examples/disks-storageaccount/dcos-master-sa.json b/examples/disks-storageaccount/dcos-master-sa.json deleted file mode 100644 index 36c6526453..0000000000 --- a/examples/disks-storageaccount/dcos-master-sa.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2", - "storageProfile": "StorageAccount" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 1, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpublic", - "count": 1, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} diff --git a/examples/disks-storageaccount/dcos.json b/examples/disks-storageaccount/dcos.json deleted file mode 100644 index 5fb442d0a4..0000000000 --- a/examples/disks-storageaccount/dcos.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "", - "vmSize": "Standard_D2s_v3", - "OSDiskSizeGB": 200 - }, - "agentPoolProfiles": [ - { - "name": "agent128", - "count": 3, - "vmSize": "Standard_D2s_v3", - "OSDiskSizeGB": 200, - "availabilityProfile": "AvailabilitySet", - "storageProfile": "StorageAccount", - "diskSizesGB": [128, 128, 128, 128] - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2s_v3", - "dnsPrefix": "", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "StorageAccount", - "diskSizesGB": [1], - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/disks-storageaccount/swarm.json b/examples/disks-storageaccount/swarm.json deleted file mode 100644 index e052b57df6..0000000000 --- a/examples/disks-storageaccount/swarm.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2", - "OSDiskSizeGB": 200 - }, - "agentPoolProfiles": [ - { - "name": "agent128", - "count": 3, - "vmSize": "Standard_D2_v2", - "OSDiskSizeGB": 200, - "availabilityProfile": "AvailabilitySet", - "storageProfile": "StorageAccount", - "diskSizesGB": [128, 128, 128, 128] - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "StorageAccount", - "diskSizesGB": [1], - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/disks-storageaccount/swarmmode-master-sa.json b/examples/disks-storageaccount/swarmmode-master-sa.json deleted file mode 100644 index 460df95b7c..0000000000 --- a/examples/disks-storageaccount/swarmmode-master-sa.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2", - "storageProfile": "StorageAccount" - }, - "agentPoolProfiles": [ - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} diff --git a/examples/disks-storageaccount/swarmmode.json b/examples/disks-storageaccount/swarmmode.json deleted file mode 100644 index 3992adf8f9..0000000000 --- a/examples/disks-storageaccount/swarmmode.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2", - "OSDiskSizeGB": 200 - }, - "agentPoolProfiles": [ - { - "name": "agent128", - "count": 1, - "vmSize": "Standard_D2_v2", - "OSDiskSizeGB": 200, - "availabilityProfile": "AvailabilitySet", - "storageProfile": "StorageAccount", - "diskSizesGB": [128, 128, 128, 128] - }, - { - "name": "agentpublic", - "count": 1, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "StorageAccount", - "diskSizesGB": [1], - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/e2e-tests/openshift/definition.json b/examples/e2e-tests/openshift/definition.json deleted file mode 100644 index 86b3a57150..0000000000 --- a/examples/e2e-tests/openshift/definition.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "OpenShift", - "openShiftConfig": { - "clusterUsername": "", - "clusterPassword": "", - "enableAADAuthentication": false - } - }, - "azProfile": { - "tenantId": "", - "subscriptionId": "", - "resourceGroup": "", - "location": "" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "imageReference": { - "name": "", - "resourceGroup": "" - }, - "storageProfile": "ManagedDisks", - "vmSize": "Standard_D4s_v3", - "vnetSubnetId": "/subscriptions/SUB_ID/resourceGroups/RG_NAME/providers/Microsoft.Network/virtualNetworks/VNET_NAME/subnets/SUBNET_NAME", - "firstConsecutiveStaticIP": "10.239.0.239" - }, - "agentPoolProfiles": [ - { - "availabilityProfile": "AvailabilitySet", - "count": 1, - "imageReference": { - "name": "", - "resourceGroup": "" - }, - "name": "compute", - "storageProfile": "ManagedDisks", - "vmSize": "Standard_D4s_v3", - "vnetSubnetId": "/subscriptions/SUB_ID/resourceGroups/RG_NAME/providers/Microsoft.Network/virtualNetworks/VNET_NAME/subnets/SUBNET_NAME" - }, - { - "availabilityProfile": "AvailabilitySet", - "count": 1, - "imageReference": { - "name": "", - "resourceGroup": "" - }, - "role": "infra", - "name": "infra", - "storageProfile": "ManagedDisks", - "vmSize": "Standard_D4s_v3", - "vnetSubnetId": "/subscriptions/SUB_ID/resourceGroups/RG_NAME/providers/Microsoft.Network/virtualNetworks/VNET_NAME/subnets/SUBNET_NAME" - } - ], - "linuxProfile": { - "adminUsername": "cloud-user", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - }, - "servicePrincipalProfile": { - "clientId": "", - "secret": "" - } - } -} \ No newline at end of file diff --git a/examples/e2e-tests/userassignedidentity/vmas/kubernetes-vmas-multimaster.json b/examples/e2e-tests/userassignedidentity/vmas/kubernetes-vmas-multimaster.json index dddc78e118..08390d2c10 100644 --- a/examples/e2e-tests/userassignedidentity/vmas/kubernetes-vmas-multimaster.json +++ b/examples/e2e-tests/userassignedidentity/vmas/kubernetes-vmas-multimaster.json @@ -6,7 +6,7 @@ "orchestratorRelease" : "1.12", "kubernetesConfig": { "useManagedIdentity": true, - "userAssignedID": "acsenginetestid" + "userAssignedID": "aksenginetestid" } }, "masterProfile": { diff --git a/examples/e2e-tests/userassignedidentity/vmas/kubernetes-vmas.json b/examples/e2e-tests/userassignedidentity/vmas/kubernetes-vmas.json index 4f10af0bd1..2931894f22 100644 --- a/examples/e2e-tests/userassignedidentity/vmas/kubernetes-vmas.json +++ b/examples/e2e-tests/userassignedidentity/vmas/kubernetes-vmas.json @@ -6,7 +6,7 @@ "orchestratorRelease" : "1.12", "kubernetesConfig": { "useManagedIdentity": true, - "userAssignedID": "acsenginetestid" + "userAssignedID": "aksenginetestid" } }, "masterProfile": { diff --git a/examples/e2e-tests/userassignedidentity/vmss/kubernetes-vmss.json b/examples/e2e-tests/userassignedidentity/vmss/kubernetes-vmss.json index 9723e18371..fc3438558d 100644 --- a/examples/e2e-tests/userassignedidentity/vmss/kubernetes-vmss.json +++ b/examples/e2e-tests/userassignedidentity/vmss/kubernetes-vmss.json @@ -6,7 +6,7 @@ "orchestratorRelease" : "1.12", "kubernetesConfig": { "useManagedIdentity": true, - "userAssignedID": "acsenginetestid" + "userAssignedID": "aksenginetestid" } }, "masterProfile": { diff --git a/examples/extensions/dcos.json b/examples/extensions/dcos.json deleted file mode 100644 index a7672f64a4..0000000000 --- a/examples/extensions/dcos.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2", - "extensions": [ - { - "name": "hello-world-dcos", - "singleOrAll": "single" - } - ] - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpublic", - "count": 1, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - }, - "extensionProfiles": [ - { - "name": "hello-world-dcos", - "version": "v1" - } - ] - } -} diff --git a/examples/extensions/dcos.preprovision.json b/examples/extensions/dcos.preprovision.json deleted file mode 100644 index fb2462c6c1..0000000000 --- a/examples/extensions/dcos.preprovision.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2", - "preProvisionExtension": { - "name": "hello-world", - "singleOrAll": "All" - } - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2", - "preProvisionExtension": { - "name": "hello-world", - "singleOrAll": "All" - } - }, - { - "name": "agentpublic", - "count": 1, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - }, - "extensionProfiles": [ - { - "name": "hello-world", - "version": "v1", - "script": "hello.sh" - } - ] - } -} diff --git a/examples/extensions/prometheus-grafana-k8s.json b/examples/extensions/prometheus-grafana-k8s.json index e68adb1993..33a27105b5 100644 --- a/examples/extensions/prometheus-grafana-k8s.json +++ b/examples/extensions/prometheus-grafana-k8s.json @@ -36,7 +36,7 @@ { "name": "prometheus-grafana-k8s", "version": "v1", - "rootURL": "https://raw.githubusercontent.com/Azure/acs-engine/master/" + "rootURL": "https://raw.githubusercontent.com/Azure/aks-engine/master/" } ], "servicePrincipalProfile": { diff --git a/examples/extensions/swarmmode.preprovision.json b/examples/extensions/swarmmode.preprovision.json deleted file mode 100644 index aac74b1253..0000000000 --- a/examples/extensions/swarmmode.preprovision.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2", - "preProvisionExtension": { - "name": "hello-world", - "singleOrAll": "All" - } - }, - "agentPoolProfiles": [ - { - "name": "agentpublic", - "count": 1, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ], - "preProvisionExtension": { - "name": "hello-world", - "singleOrAll": "All" - } - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - }, - "extensionProfiles": [ - { - "name": "hello-world", - "version": "v1", - "script": "hello.sh" - } - ] - } -} diff --git a/examples/k8s-upgrade/README.md b/examples/k8s-upgrade/README.md index 10a60aeaa8..1ee08256dc 100644 --- a/examples/k8s-upgrade/README.md +++ b/examples/k8s-upgrade/README.md @@ -1,23 +1,23 @@ -# Microsoft Azure Container Service Engine - Kubernetes Upgrade +# Microsoft Azure Kubernetes Service Engine - Kubernetes Upgrade ## Overview This document describes how to upgrade kubernetes version for an existing cluster. -*acs-engine* supports Kubernetes version upgrades starting from ``1.5`` release. -During the upgrade, *acs-engine* successively visits virtual machines that constitute the cluster (first the master nodes, then the agent nodes) and performs the following operations: +*aks-engine* supports Kubernetes version upgrades starting from ``1.5`` release. +During the upgrade, *aks-engine* successively visits virtual machines that constitute the cluster (first the master nodes, then the agent nodes) and performs the following operations: - cordon the node and drain existing workload - delete the VM - create new VM and install desired orchestrator version - add the new VM to the cluster -*acs-engine* allows one subsequent minor version upgrade at a time, for example, from ``1.6.x`` to ``1.7.y``. +*aks-engine* allows one subsequent minor version upgrade at a time, for example, from ``1.6.x`` to ``1.7.y``. For upgrade that spans over more than a single minor version, this operation should be called several times, each time advancing the minor version by one. For example, to upgrade from ``1.6.x`` to ``1.8.z`` one should first upgrade the cluster to ``1.7.y``, followed by upgrading it to ``1.8.z`` To get the list of all available Kubernetes versions and upgrades, run the *orchestrators* command and specify Kubernetes orchestrator type. The output is a JSON object: ```bash -./bin/acs-engine orchestrators --orchestrator Kubernetes +./bin/aks-engine orchestrators --orchestrator Kubernetes ``` ```json @@ -75,7 +75,7 @@ To get the list of all available Kubernetes versions and upgrades, run the *orch To get the information specific to the cluster, provide its current orchestrator version: ```bash -./bin/acs-engine orchestrators --orchestrator Kubernetes --version 1.7.8 +./bin/aks-engine orchestrators --orchestrator Kubernetes --version 1.7.8 ``` ```json @@ -132,9 +132,9 @@ To get the information specific to the cluster, provide its current orchestrator Once the desired Kubernetes version is finalized, call the *upgrade* command: ```bash -./bin/acs-engine upgrade \ +./bin/aks-engine upgrade \ --subscription-id \ - --deployment-dir \ + --deployment-dir \ --location \ --resource-group \ --upgrade-version \ @@ -144,7 +144,7 @@ Once the desired Kubernetes version is finalized, call the *upgrade* command: ``` For example, ```bash -./bin/acs-engine upgrade \ +./bin/aks-engine upgrade \ --subscription-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \ --deployment-dir ./_output/test \ --location westus \ @@ -157,7 +157,7 @@ For example, By its nature, the upgrade operation is long running and potentially could fail for various reasons, such as temporary lack of resources, etc. In this case, rerun the command. The *upgrade* command is idempotent, and will pick up execution from the point it failed on. -[This directory](https://github.com/Azure/acs-engine/tree/master/examples/k8s-upgrade) contains the following files: +[This directory](https://github.com/Azure/aks-engine/tree/master/examples/k8s-upgrade) contains the following files: - **README.md** - this file - **k8s-upgrade.sh** - script invoking upgrade operation - **\*.json** - cluster definition examples for various orchestrator versions and configurations: Linux clusters, Windows clusters, hybrid clusters. diff --git a/examples/k8s-upgrade/k8s-upgrade.sh b/examples/k8s-upgrade/k8s-upgrade.sh index f66eefccbc..6fc56abdc2 100755 --- a/examples/k8s-upgrade/k8s-upgrade.sh +++ b/examples/k8s-upgrade/k8s-upgrade.sh @@ -12,7 +12,7 @@ fi OUTPUT="_output/${INSTANCE_NAME}" -./bin/acs-engine upgrade \ +./bin/aks-engine upgrade \ --subscription-id ${SUBSCRIPTION_ID} \ --deployment-dir ${OUTPUT} \ --location ${LOCATION} \ diff --git a/examples/k8s-upgrade/v1.7.7.json.env b/examples/k8s-upgrade/v1.7.7.json.env index 6dc67f58b4..3579b2090f 100644 --- a/examples/k8s-upgrade/v1.7.7.json.env +++ b/examples/k8s-upgrade/v1.7.7.json.env @@ -1,2 +1,2 @@ -ACSE_POSTDEPLOY=examples/k8s-upgrade/k8s-upgrade.sh +AKSE_POSTDEPLOY=examples/k8s-upgrade/k8s-upgrade.sh EXPECTED_ORCHESTRATOR_VERSION=1.8.1 \ No newline at end of file diff --git a/examples/k8s-upgrade/v1.7.9-hybrid.json.env b/examples/k8s-upgrade/v1.7.9-hybrid.json.env index 7ec290ed25..4e9db1a33a 100644 --- a/examples/k8s-upgrade/v1.7.9-hybrid.json.env +++ b/examples/k8s-upgrade/v1.7.9-hybrid.json.env @@ -1,2 +1,2 @@ -ACSE_POSTDEPLOY=examples/k8s-upgrade/k8s-upgrade.sh +AKSE_POSTDEPLOY=examples/k8s-upgrade/k8s-upgrade.sh EXPECTED_ORCHESTRATOR_VERSION=1.8.9 \ No newline at end of file diff --git a/examples/k8s-upgrade/v1.7.9-win.json.env b/examples/k8s-upgrade/v1.7.9-win.json.env index 45f41d2632..12fd2c25d1 100644 --- a/examples/k8s-upgrade/v1.7.9-win.json.env +++ b/examples/k8s-upgrade/v1.7.9-win.json.env @@ -1,2 +1,2 @@ -ACSE_POSTDEPLOY=examples/k8s-upgrade/k8s-upgrade.sh +AKSE_POSTDEPLOY=examples/k8s-upgrade/k8s-upgrade.sh EXPECTED_ORCHESTRATOR_VERSION=1.8.9 diff --git a/examples/k8s-upgrade/v1.7.9.json.env b/examples/k8s-upgrade/v1.7.9.json.env index 45f41d2632..12fd2c25d1 100644 --- a/examples/k8s-upgrade/v1.7.9.json.env +++ b/examples/k8s-upgrade/v1.7.9.json.env @@ -1,2 +1,2 @@ -ACSE_POSTDEPLOY=examples/k8s-upgrade/k8s-upgrade.sh +AKSE_POSTDEPLOY=examples/k8s-upgrade/k8s-upgrade.sh EXPECTED_ORCHESTRATOR_VERSION=1.8.9 diff --git a/examples/k8s-upgrade/v1.8.4.json.env b/examples/k8s-upgrade/v1.8.4.json.env index 10387b6748..8bb1c5a920 100644 --- a/examples/k8s-upgrade/v1.8.4.json.env +++ b/examples/k8s-upgrade/v1.8.4.json.env @@ -1,2 +1,2 @@ -ACSE_POSTDEPLOY=examples/k8s-upgrade/k8s-upgrade.sh +AKSE_POSTDEPLOY=examples/k8s-upgrade/k8s-upgrade.sh EXPECTED_ORCHESTRATOR_VERSION=1.9.4 diff --git a/examples/keyvault-params/README.md b/examples/keyvault-params/README.md index ca04eed304..fc448560cb 100644 --- a/examples/keyvault-params/README.md +++ b/examples/keyvault-params/README.md @@ -1,8 +1,8 @@ -# Microsoft Azure Container Service Engine - Key vault referencing for k8s parameters +# Microsoft Azure Kubernetes Service Engine - Key vault referencing for k8s parameters ## Overview -ACS-Engine enables you to retrieve the following k8s deployment parameters from Microsoft Azure KeyVault: +AKS Engine enables you to retrieve the following k8s deployment parameters from Microsoft Azure KeyVault: * certificateProfile * apiServerCertificate diff --git a/examples/keyvaultcerts/README.md b/examples/keyvaultcerts/README.md index 4ae8267b09..d4cfaf38d8 100644 --- a/examples/keyvaultcerts/README.md +++ b/examples/keyvaultcerts/README.md @@ -1,16 +1,12 @@ -# Microsoft Azure Container Service Engine - Key vault certificate deployment +# Microsoft Azure Kubernetes Service Engine - Key vault certificate deployment ## Overview -ACS-Engine enables you to create customized Docker enabled cluster on Microsoft Azure with certs installed from key vault during deployment. +AKS Engine enables you to create a customized Kubernetes cluster on Microsoft Azure with certs installed from key vault during deployment. The examples show you how to configure installing a cert from keyvault. These certs are assumed to be in the secrets portion of your keyvault: -1. **dcos.json** - deploying and using [DC/OS](../../docs/dcos.md) -2. **kubernetes.json** - deploying and using [Kubernetes](../../docs/kubernetes.md) -3. **swarm.json** - deploying and using [Swarm](../../docs/swarm.md) -4. **swarm-windows.json** - deploying and using [Swarm](../../docs/swarm.md) -5. **swarmmode.json** - deploying and using [Swarm Mode](../../docs/swarmmode.md) +1. **kubernetes.json** - deploying and using [Kubernetes](../../docs/kubernetes.md) On windows machines certificates will be installed under the machine in the specified store. On linux machines the certificates will be installed in the folder /var/lib/waagent/. There will be two files diff --git a/examples/keyvaultcerts/dcos.json b/examples/keyvaultcerts/dcos.json deleted file mode 100644 index 0f9d21c9ac..0000000000 --- a/examples/keyvaultcerts/dcos.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - }, - "secrets":[ - { - "sourceVault":{ - "id":"" - }, - "vaultCertificates":[ - { - "certificateUrl" :"" - } - ] - } - ] - } - } -} diff --git a/examples/keyvaultcerts/swarm.json b/examples/keyvaultcerts/swarm.json deleted file mode 100644 index 94c2f6f72f..0000000000 --- a/examples/keyvaultcerts/swarm.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - }, - "secrets":[ - { - "sourceVault":{ - "id":"" - }, - "vaultCertificates":[ - { - "certificateUrl" :"" - } - ] - } - ] - } - } -} diff --git a/examples/keyvaultcerts/swarmmode.json b/examples/keyvaultcerts/swarmmode.json deleted file mode 100644 index fbca8ab59d..0000000000 --- a/examples/keyvaultcerts/swarmmode.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agent128", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "StorageAccount", - "diskSizesGB": [128, 128, 128, 128] - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "StorageAccount", - "diskSizesGB": [1], - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - }, - "secrets":[ - { - "sourceVault":{ - "id":"" - }, - "vaultCertificates":[ - { - "certificateUrl" :"" - } - ] - } - ] - } - } -} diff --git a/examples/kubernetes-config/README.md b/examples/kubernetes-config/README.md index e350979656..5c69156e20 100644 --- a/examples/kubernetes-config/README.md +++ b/examples/kubernetes-config/README.md @@ -1,4 +1,4 @@ -# Microsoft Azure Container Service Engine - Kubernetes Features +# Microsoft Azure Kubernetes Service Engine - Kubernetes Features ## Overview diff --git a/examples/kubernetes-labels/README.md b/examples/kubernetes-labels/README.md index 950dc5a90b..7c013bb270 100644 --- a/examples/kubernetes-labels/README.md +++ b/examples/kubernetes-labels/README.md @@ -22,7 +22,7 @@ The definition below adds 2 labels `"bar"` and `"baz"` to all nodes in the `firs ], ``` -In addition to any custom node labels you may add, ACS Engine will add another label, `"agentpool"`, which identifies which Agent Pool the node belongs to. +In addition to any custom node labels you may add, AKS Engine will add another label, `"agentpool"`, which identifies which Agent Pool the node belongs to. You can confirm the labels have been applied on the node by running `kubectl describe node `: diff --git a/examples/kubernetes-msi-userassigned/kube-vma.json b/examples/kubernetes-msi-userassigned/kube-vma.json index 70bd947e34..7c3921c57d 100644 --- a/examples/kubernetes-msi-userassigned/kube-vma.json +++ b/examples/kubernetes-msi-userassigned/kube-vma.json @@ -5,7 +5,7 @@ "orchestratorType": "Kubernetes", "kubernetesConfig": { "useManagedIdentity": true, - "userAssignedID": "acsenginetestid" + "userAssignedID": "aksenginetestid" } }, "masterProfile": { diff --git a/examples/kubernetes-msi-userassigned/kube-vmss.json b/examples/kubernetes-msi-userassigned/kube-vmss.json index 081b5d0652..f0734e96ae 100644 --- a/examples/kubernetes-msi-userassigned/kube-vmss.json +++ b/examples/kubernetes-msi-userassigned/kube-vmss.json @@ -5,7 +5,7 @@ "orchestratorType": "Kubernetes", "kubernetesConfig": { "useManagedIdentity": true, - "userAssignedID": "acsenginetestid" + "userAssignedID": "aksenginetestid" } }, "masterProfile": { diff --git a/examples/largeclusters/README.md b/examples/largeclusters/README.md index a2e949f8b0..18564b7a17 100644 --- a/examples/largeclusters/README.md +++ b/examples/largeclusters/README.md @@ -1,15 +1,9 @@ -# Microsoft Azure Container Service Engine - Large Clusters +# Microsoft Azure Kubernetes Service Engine - Large Clusters ## Overview -ACS-Engine enables you to create customized Docker enabled cluster on Microsoft Azure with 1200 nodes. +AKS Engine enables you to create customized Kubernetes cluster on Microsoft Azure with 1200 nodes. The examples show you how to configure up to 12 agent pools with 100 nodes each: -1. **dcos.json** - deploying and using [DC/OS](../../docs/dcos.md) -2. **dcos-vmas.json** - this provides an example using availability sets instead of the default virtual machine scale sets. You will want to use availability sets if you want to dynamically attach/detach disks. -3. **kubernetes.json** - deploying and using [Kubernetes](../../docs/kubernetes.md) -4. **swarm.json** - deploying and using [Swarm](../../docs/swarm.md) -5. **swarm-vmas.json** - this provides an example using availability sets instead of the default virtual machine scale sets. You will want to use availability sets if you want to dynamically attach/detach disks. -6. **swarmmode.json** - deploying and using [Swarm Mode](../../docs/swarmmode.md) -7. **swarmmode-vmas.json** - this provides an example using availability sets instead of the default virtual machine scale sets. You will want to use availability sets if you want to dynamically attach/detach disks. \ No newline at end of file +1. **kubernetes.json** - deploying and using [Kubernetes](../../docs/kubernetes.md) diff --git a/examples/largeclusters/dcos-vmas.json b/examples/largeclusters/dcos-vmas.json deleted file mode 100644 index 4701c909e3..0000000000 --- a/examples/largeclusters/dcos-vmas.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpool0", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool1", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool2", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool3", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool4", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool5", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool6", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool7", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool8", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool9", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool10", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool11", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/largeclusters/dcos.json b/examples/largeclusters/dcos.json deleted file mode 100644 index fafff2899f..0000000000 --- a/examples/largeclusters/dcos.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpool0", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool1", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool2", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool3", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool4", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool5", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool6", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool7", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool8", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool9", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool10", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool11", - "count": 100, - "vmSize": "Standard_D2_v2" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/largeclusters/swarm-vmas.json b/examples/largeclusters/swarm-vmas.json deleted file mode 100644 index a4f2b28b90..0000000000 --- a/examples/largeclusters/swarm-vmas.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpool0", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool1", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool2", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool3", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool4", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool5", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool6", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool7", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool8", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool9", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool10", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool11", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/largeclusters/swarm.json b/examples/largeclusters/swarm.json deleted file mode 100644 index 22c48ac839..0000000000 --- a/examples/largeclusters/swarm.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpool0", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool1", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool2", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool3", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool4", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool5", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool6", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool7", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool8", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool9", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool10", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool11", - "count": 100, - "vmSize": "Standard_D2_v2" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/largeclusters/swarmmode-vmas.json b/examples/largeclusters/swarmmode-vmas.json deleted file mode 100644 index 9dbd37c18f..0000000000 --- a/examples/largeclusters/swarmmode-vmas.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpool0", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool1", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool2", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool3", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool4", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool5", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool6", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool7", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool8", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool9", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool10", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpool11", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/largeclusters/swarmmode.json b/examples/largeclusters/swarmmode.json deleted file mode 100644 index 72f6a515c8..0000000000 --- a/examples/largeclusters/swarmmode.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpool0", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool1", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool2", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool3", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool4", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool5", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool6", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool7", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool8", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool9", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool10", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpool11", - "count": 100, - "vmSize": "Standard_D2_v2" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/networkplugin/README.md b/examples/networkplugin/README.md index 3afcaff870..ac101ba041 100644 --- a/examples/networkplugin/README.md +++ b/examples/networkplugin/README.md @@ -1,4 +1,4 @@ -# Microsoft Azure Container Service Engine - Network Plugin +# Microsoft Azure Kubernetes Service Engine - Network Plugin There are 2 different Network Plugin options : diff --git a/examples/networkpolicy/README.md b/examples/networkpolicy/README.md index 75309f7a3a..b8816a8c00 100644 --- a/examples/networkpolicy/README.md +++ b/examples/networkpolicy/README.md @@ -1,4 +1,4 @@ -# Microsoft Azure Container Service Engine - Network Policy +# Microsoft Azure Kubernetes Service Engine - Network Policy There are 2 different Network Policy options : @@ -7,7 +7,7 @@ There are 2 different Network Policy options : ## Calico -The kubernetes-calico deployment template enables Calico networking and policies for the ACS-engine cluster via `"networkPolicy": "calico"` being present inside the `kubernetesConfig`. +The kubernetes-calico deployment template enables Calico networking and policies for the AKS Engine cluster via `"networkPolicy": "calico"` being present inside the `kubernetesConfig`. ```json "properties": { @@ -32,10 +32,10 @@ Once the template has been successfully deployed, following the [simple policy t > Note: `ping` (ICMP) traffic is blocked on the cluster by default. Wherever `ping` is used in any tutorial substitute testing access with something like `wget -q --timeout=5 google.com -O -` instead. -### Update guidance for clusters deployed by acs-engine releases prior to 0.17.0 +### Update guidance for clusters deployed by aks-engine releases prior to 0.17.0 Clusters deployed with calico networkPolicy enabled prior to `0.17.0` had calico `2.6.3` deployed, and a daemonset with an `updateStrategy` of `Ondelete`. -acs-engine releases starting with 0.17.0 now produce an addon manifest for calico in `/etc/kubernetes/addons/calico-daemonset.yaml` contaning calico 3.1.x, and an `updateStrategy` of `RollingUpdate`. Due to breaking changes introduced by calico 3, one must first migrate through calico `2.6.5` or a later 2.6.x release in order to migrate to calico 3.1.x. as described in the [calico kubernetes upgrade documentation](https://docs.projectcalico.org/v3.1/getting-started/kubernetes/upgrade/). The acs-engine manifest for calico uses the [kubernetes API datastore, policy-only setup](https://docs.projectcalico.org/v3.1/getting-started/kubernetes/upgrade/upgrade#upgrading-an-installation-that-uses-the-kubernetes-api-datastore). +aks-engine releases starting with 0.17.0 now produce an addon manifest for calico in `/etc/kubernetes/addons/calico-daemonset.yaml` contaning calico 3.1.x, and an `updateStrategy` of `RollingUpdate`. Due to breaking changes introduced by calico 3, one must first migrate through calico `2.6.5` or a later 2.6.x release in order to migrate to calico 3.1.x. as described in the [calico kubernetes upgrade documentation](https://docs.projectcalico.org/v3.1/getting-started/kubernetes/upgrade/). The aks-engine manifest for calico uses the [kubernetes API datastore, policy-only setup](https://docs.projectcalico.org/v3.1/getting-started/kubernetes/upgrade/upgrade#upgrading-an-installation-that-uses-the-kubernetes-api-datastore). 1. To update to `2.6.5+` in preparation of an upgrade to 3.1.x as specified, edit `/etc/kubernetes/addons/calico-daemonset.yaml` on a master node, replacing `calico/node:v3.1.1` with `calico/node:v2.6.10` and `calico/cni:v3.1.1` with `calico/cni:v2.0.6`. Run `kubectl apply -f /etc/kubernetes/addons/calico-daemonset.yaml`. @@ -61,7 +61,7 @@ If you have any customized calico resource manifests, you must also follow the [ ## Cilium -The kubernetes-cilium deployment template enables Cilium networking and policies for the ACS-engine cluster via `"networkPolicy": "cilium"` or `"networkPlugin": "cilium"` being present inside the `kubernetesConfig`. +The kubernetes-cilium deployment template enables Cilium networking and policies for the AKS Engine cluster via `"networkPolicy": "cilium"` or `"networkPlugin": "cilium"` being present inside the `kubernetesConfig`. ```json "properties": { diff --git a/examples/openshift.json b/examples/openshift.json deleted file mode 100644 index de92125da4..0000000000 --- a/examples/openshift.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "OpenShift", - "openShiftConfig": { - "clusterUsername": "", - "clusterPassword": "", - "enableAADAuthentication": false - } - }, - "azProfile": { - "tenantId": "", - "subscriptionId": "", - "resourceGroup": "", - "location": "" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "imageReference": { - "name": "", - "resourceGroup": "" - }, - "storageProfile": "ManagedDisks", - "vmSize": "Standard_D4s_v3" - }, - "agentPoolProfiles": [ - { - "availabilityProfile": "AvailabilitySet", - "count": 1, - "imageReference": { - "name": "", - "resourceGroup": "" - }, - "name": "compute", - "storageProfile": "ManagedDisks", - "vmSize": "Standard_D4s_v3" - }, - { - "availabilityProfile": "AvailabilitySet", - "count": 1, - "imageReference": { - "name": "", - "resourceGroup": "" - }, - "role": "infra", - "name": "infra", - "storageProfile": "ManagedDisks", - "vmSize": "Standard_D4s_v3" - } - ], - "linuxProfile": { - "adminUsername": "cloud-user", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - }, - "servicePrincipalProfile": { - "clientId": "", - "secret": "" - } - } -} diff --git a/examples/service-mesh/README.md b/examples/service-mesh/README.md index ec226ce318..5de863ab4c 100644 --- a/examples/service-mesh/README.md +++ b/examples/service-mesh/README.md @@ -2,7 +2,7 @@ There are numerous implementations of a service mesh which integrate with kubernetes such as Istio, [Linkerd](http://linkerd.io), and [Conduit](https://conduit.io/). [This is one blog post](https://medium.com/microservices-in-practice/service-mesh-for-microservices-2953109a3c9a) which explains some fundamentals behind what it is and why to use it. -Some service mesh implementations **may** benefit from or require additional [customizations to the kubernetes cluster itself](https://github.com/Azure/acs-engine/blob/master/docs/clusterdefinition.md). +Some service mesh implementations **may** benefit from or require additional [customizations to the kubernetes cluster itself](https://github.com/Azure/aks-engine/blob/master/docs/clusterdefinition.md). ## Istio diff --git a/examples/swarm.json b/examples/swarm.json deleted file mode 100644 index 797884c9ac..0000000000 --- a/examples/swarm.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpublic", - "count": 1, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} diff --git a/examples/swarmmode-D2.json b/examples/swarmmode-D2.json deleted file mode 100644 index 0a73cf1443..0000000000 --- a/examples/swarmmode-D2.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "", - "vmSize": "Standard_D2" - }, - "agentPoolProfiles": [ - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} diff --git a/examples/swarmmode-rhel.json b/examples/swarmmode-rhel.json deleted file mode 100644 index 946674470e..0000000000 --- a/examples/swarmmode-rhel.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2", - "distro": "rhel" - }, - "agentPoolProfiles": [ - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ], - "distro": "rhel" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} diff --git a/examples/swarmmode.json b/examples/swarmmode.json deleted file mode 100644 index e4781fec81..0000000000 --- a/examples/swarmmode.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} diff --git a/examples/v20160330/dcos.json b/examples/v20160330/dcos.json deleted file mode 100644 index f1d41b904a..0000000000 --- a/examples/v20160330/dcos.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "apiVersion": "2016-09-30", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/v20160330/swarm.json b/examples/v20160330/swarm.json deleted file mode 100644 index 0f9c4fe2f0..0000000000 --- a/examples/v20160330/swarm.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "apiVersion": "2016-03-30", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "" - }, - "agentPoolProfiles": [ - { - "name": "agentpool1", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "" - }, - { - "name": "agentpool2", - "count": 3, - "vmSize": "Standard_D2_v2" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/v20160930/dcos.json b/examples/v20160930/dcos.json deleted file mode 100644 index f1d41b904a..0000000000 --- a/examples/v20160930/dcos.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "apiVersion": "2016-09-30", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/v20170131/dcos.json b/examples/v20170131/dcos.json deleted file mode 100644 index 8abfed9630..0000000000 --- a/examples/v20170131/dcos.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "apiVersion": "2017-01-31", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/v20170131/swarmmode.json b/examples/v20170131/swarmmode.json deleted file mode 100644 index 3a5387af27..0000000000 --- a/examples/v20170131/swarmmode.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "apiVersion": "2017-01-31", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpublic", - "count": 1, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} diff --git a/examples/v20170701/dcos.json b/examples/v20170701/dcos.json deleted file mode 100644 index 70634bf38f..0000000000 --- a/examples/v20170701/dcos.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "apiVersion": "2017-07-01", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 1, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpublic", - "count": 1, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} diff --git a/examples/v20170701/dockerce.json b/examples/v20170701/dockerce.json deleted file mode 100644 index 72b1b411e4..0000000000 --- a/examples/v20170701/dockerce.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "apiVersion": "2017-07-01", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DockerCE" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} diff --git a/examples/vnet/README.md b/examples/vnet/README.md index a4209d528b..9200fefc98 100644 --- a/examples/vnet/README.md +++ b/examples/vnet/README.md @@ -1,15 +1,11 @@ -# Microsoft Azure Container Service Engine - Custom VNET +# Microsoft Azure Kubernetes Service Engine - Custom VNET ## Overview -These examples show you how to build a customized Docker enabled cluster on Microsoft Azure where you can provide your own VNET. +These examples show you how to build a customized Kubernetes cluster on Microsoft Azure where you can provide your own VNET. -To try: +To try: 1. first deploy a custom vnet. An example of an arm template that does this is under directory vnetarmtemplate. 2. next configure the example templates and deploy according to the examples: 1. **kubernetes.json** - deploying and using [Kubernetes](../../docs/kubernetes/features.md#feat-custom-vnet) - 2. **dcos.json** - deploying and using [DC/OS](../../docs/dcos.md) - 3. **swarm.json** - deploying and using [Swarm](../../docs/swarm.md) - 4. **swarmmodevnet.json** - deploying and using [Swarm Mode](../../docs/swarmmode.md) - diff --git a/examples/vnet/dcosvnet.json b/examples/vnet/dcosvnet.json deleted file mode 100644 index 2669450c34..0000000000 --- a/examples/vnet/dcosvnet.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "", - "vmSize": "Standard_D2s_v3", - "vnetSubnetId": "/subscriptions/SUB_ID/resourceGroups/RG_NAME/providers/Microsoft.Network/virtualNetworks/VNET_NAME/subnets/MASTER_SUBNET_NAME", - "firstConsecutiveStaticIP": "10.100.0.5" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2s_v3", - "availabilityProfile": "AvailabilitySet", - "vnetSubnetId": "/subscriptions/SUB_ID/resourceGroups/RG_NAME/providers/Microsoft.Network/virtualNetworks/VNET_NAME/subnets/AGENT_SUBNET_NAME" - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2s_v3", - "dnsPrefix": "", - "vnetSubnetId": "/subscriptions/SUB_ID/resourceGroups/RG_NAME/providers/Microsoft.Network/virtualNetworks/VNET_NAME/subnets/AGENT_SUBNET_NAME", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } -} -} \ No newline at end of file diff --git a/examples/vnet/dcosvnet.json.env b/examples/vnet/dcosvnet.json.env deleted file mode 100644 index db307027d9..0000000000 --- a/examples/vnet/dcosvnet.json.env +++ /dev/null @@ -1 +0,0 @@ -ACSE_PREDEPLOY=examples/vnet/dual-subnet-vnet-predeploy.sh diff --git a/examples/vnet/kubernetesvnet-azure-cni.json.env b/examples/vnet/kubernetesvnet-azure-cni.json.env index 4f4f1105b7..23259af7a6 100644 --- a/examples/vnet/kubernetesvnet-azure-cni.json.env +++ b/examples/vnet/kubernetesvnet-azure-cni.json.env @@ -1 +1 @@ -ACSE_PREDEPLOY=examples/vnet/k8s-vnet-azure-cni-predeploy.sh +AKSE_PREDEPLOY=examples/vnet/k8s-vnet-azure-cni-predeploy.sh diff --git a/examples/vnet/kubernetesvnet-customnodesdns.json b/examples/vnet/kubernetesvnet-customnodesdns.json index b324148f74..92726c9b0a 100644 --- a/examples/vnet/kubernetesvnet-customnodesdns.json +++ b/examples/vnet/kubernetesvnet-customnodesdns.json @@ -61,7 +61,7 @@ "name": "register-dns", "version": "v1", "extensionParameters": "mydomain.com", - "rootURL": "https://raw.githubusercontent.com/Azure/acs-engine/master/extensions/dnsupdate/", + "rootURL": "https://raw.githubusercontent.com/Azure/aks-engine/master/extensions/dnsupdate/", "script": "register-dns.sh" } ], diff --git a/examples/vnet/kubernetesvnet.json.env b/examples/vnet/kubernetesvnet.json.env index 37d48a184d..e7cf3090b7 100644 --- a/examples/vnet/kubernetesvnet.json.env +++ b/examples/vnet/kubernetesvnet.json.env @@ -1,2 +1,2 @@ -ACSE_PREDEPLOY=examples/vnet/k8s-vnet-predeploy.sh -ACSE_POSTDEPLOY=examples/vnet/k8s-vnet-postdeploy.sh +AKSE_PREDEPLOY=examples/vnet/k8s-vnet-predeploy.sh +AKSE_POSTDEPLOY=examples/vnet/k8s-vnet-postdeploy.sh diff --git a/examples/vnet/kubernetesvnet1.5.json.env b/examples/vnet/kubernetesvnet1.5.json.env index 37d48a184d..e7cf3090b7 100644 --- a/examples/vnet/kubernetesvnet1.5.json.env +++ b/examples/vnet/kubernetesvnet1.5.json.env @@ -1,2 +1,2 @@ -ACSE_PREDEPLOY=examples/vnet/k8s-vnet-predeploy.sh -ACSE_POSTDEPLOY=examples/vnet/k8s-vnet-postdeploy.sh +AKSE_PREDEPLOY=examples/vnet/k8s-vnet-predeploy.sh +AKSE_POSTDEPLOY=examples/vnet/k8s-vnet-postdeploy.sh diff --git a/examples/vnet/kubernetesvnet1.6.json.env b/examples/vnet/kubernetesvnet1.6.json.env index 37d48a184d..e7cf3090b7 100644 --- a/examples/vnet/kubernetesvnet1.6.json.env +++ b/examples/vnet/kubernetesvnet1.6.json.env @@ -1,2 +1,2 @@ -ACSE_PREDEPLOY=examples/vnet/k8s-vnet-predeploy.sh -ACSE_POSTDEPLOY=examples/vnet/k8s-vnet-postdeploy.sh +AKSE_PREDEPLOY=examples/vnet/k8s-vnet-predeploy.sh +AKSE_POSTDEPLOY=examples/vnet/k8s-vnet-postdeploy.sh diff --git a/examples/vnet/openshift-vnet.json b/examples/vnet/openshift-vnet.json deleted file mode 100644 index ee5e7986f5..0000000000 --- a/examples/vnet/openshift-vnet.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "OpenShift", - "openShiftConfig": { - "clusterUsername": "", - "clusterPassword": "", - "enableAADAuthentication": false - } - }, - "azProfile": { - "tenantId": "", - "subscriptionId": "", - "resourceGroup": "", - "location": "" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "imageReference": { - "name": "", - "resourceGroup": "" - }, - "storageProfile": "ManagedDisks", - "vmSize": "Standard_D4s_v3", - "vnetSubnetId": "/subscriptions/SUB_ID/resourceGroups/RG_NAME/providers/Microsoft.Network/virtualNetworks/VNET_NAME/subnets/SUBNET_NAME", - "firstConsecutiveStaticIP": "10.239.0.239" - }, - "agentPoolProfiles": [ - { - "availabilityProfile": "AvailabilitySet", - "count": 1, - "imageReference": { - "name": "", - "resourceGroup": "" - }, - "name": "compute", - "storageProfile": "ManagedDisks", - "vmSize": "Standard_D4s_v3", - "vnetSubnetId": "/subscriptions/SUB_ID/resourceGroups/RG_NAME/providers/Microsoft.Network/virtualNetworks/VNET_NAME/subnets/SUBNET_NAME" - }, - { - "availabilityProfile": "AvailabilitySet", - "count": 1, - "imageReference": { - "name": "", - "resourceGroup": "" - }, - "role": "infra", - "name": "infra", - "storageProfile": "ManagedDisks", - "vmSize": "Standard_D4s_v3", - "vnetSubnetId": "/subscriptions/SUB_ID/resourceGroups/RG_NAME/providers/Microsoft.Network/virtualNetworks/VNET_NAME/subnets/SUBNET_NAME" - } - ], - "linuxProfile": { - "adminUsername": "cloud-user", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - }, - "servicePrincipalProfile": { - "clientId": "", - "secret": "" - } - } -} diff --git a/examples/vnet/swarmmodevnet.json b/examples/vnet/swarmmodevnet.json deleted file mode 100644 index da253f0fda..0000000000 --- a/examples/vnet/swarmmodevnet.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2", - "vnetSubnetId": "/subscriptions/SUB_ID/resourceGroups/RG_NAME/providers/Microsoft.Network/virtualNetworks/VNET_NAME/subnets/MASTER_SUBNET_NAME", - "firstConsecutiveStaticIP": "10.100.0.5" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 1, - "vmSize": "Standard_D2_v2", - "vnetSubnetId": "/subscriptions/SUB_ID/resourceGroups/RG_NAME/providers/Microsoft.Network/virtualNetworks/VNET_NAME/subnets/AGENT_SUBNET_NAME" - }, - { - "name": "agentpublic", - "count": 1, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "vnetSubnetId": "/subscriptions/SUB_ID/resourceGroups/RG_NAME/providers/Microsoft.Network/virtualNetworks/VNET_NAME/subnets/AGENT_SUBNET_NAME", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} \ No newline at end of file diff --git a/examples/vnet/swarmmodevnet.json.env b/examples/vnet/swarmmodevnet.json.env deleted file mode 100644 index db307027d9..0000000000 --- a/examples/vnet/swarmmodevnet.json.env +++ /dev/null @@ -1 +0,0 @@ -ACSE_PREDEPLOY=examples/vnet/dual-subnet-vnet-predeploy.sh diff --git a/examples/vnet/vnetarmtemplate/azuredeploy.dcos.json b/examples/vnet/vnetarmtemplate/azuredeploy.dcos.json deleted file mode 100644 index ce845ba2f8..0000000000 --- a/examples/vnet/vnetarmtemplate/azuredeploy.dcos.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { }, - "variables": { }, - "resources": [ - { - "apiVersion": "2016-03-30", - "location": "[resourceGroup().location]", - "name": "ExampleCustomVNET", - "properties": { - "addressSpace": { - "addressPrefixes": [ - "10.100.0.0/24", - "10.200.0.0/24" - ] - }, - "subnets": [ - { - "name": "ExampleMasterSubnet", - "properties": { - "addressPrefix": "10.100.0.0/24" - } - }, - { - "name": "ExampleAgentSubnet", - "properties": { - "addressPrefix": "10.200.0.0/24" - } - } - ] - }, - "type": "Microsoft.Network/virtualNetworks" - } - ] -} diff --git a/examples/vnet/vnetarmtemplate/azuredeploy.swarm.json b/examples/vnet/vnetarmtemplate/azuredeploy.swarm.json deleted file mode 100644 index ce845ba2f8..0000000000 --- a/examples/vnet/vnetarmtemplate/azuredeploy.swarm.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { }, - "variables": { }, - "resources": [ - { - "apiVersion": "2016-03-30", - "location": "[resourceGroup().location]", - "name": "ExampleCustomVNET", - "properties": { - "addressSpace": { - "addressPrefixes": [ - "10.100.0.0/24", - "10.200.0.0/24" - ] - }, - "subnets": [ - { - "name": "ExampleMasterSubnet", - "properties": { - "addressPrefix": "10.100.0.0/24" - } - }, - { - "name": "ExampleAgentSubnet", - "properties": { - "addressPrefix": "10.200.0.0/24" - } - } - ] - }, - "type": "Microsoft.Network/virtualNetworks" - } - ] -} diff --git a/examples/vnet/vnetarmtemplate/deploy.ps1 b/examples/vnet/vnetarmtemplate/deploy.ps1 index 913ad1744a..4c7512776d 100644 --- a/examples/vnet/vnetarmtemplate/deploy.ps1 +++ b/examples/vnet/vnetarmtemplate/deploy.ps1 @@ -2,8 +2,6 @@ $VerbosePreference="Continue" $deployName="myKubeVnet" $RGName=$deployName $locName="West US" -#$templateFile = "azuredeploy.dcos.json" -#$templateFile = "azuredeploy.swarm.json" $templateFile = "azuredeploy.kubernetes.json" New-AzureRmResourceGroup -Name $RGName -Location $locName -Force New-AzureRmResourceGroupDeployment -Name $deployName -ResourceGroupName $RGName -TemplateFile $templateFile diff --git a/examples/windows/README.md b/examples/windows/README.md index 0bdf2c33a0..0e5263f60a 100644 --- a/examples/windows/README.md +++ b/examples/windows/README.md @@ -1,15 +1,13 @@ -# Microsoft Azure Container Service Engine +# Microsoft Azure Kubernetes Service Engine ## Overview -These cluster definition examples demonstrate how to create customized Docker Enabled Cluster with Windows on Microsoft Azure. +These cluster definition examples demonstrate how to create customized Kubernetes clusters with Windows on Microsoft Azure. ## User Guides * [Kubernetes Windows Walkthrough](../../docs/kubernetes/windows.md) - shows how to create a hybrid Kubernetes Windows enabled Docker cluster on Azure. * [Building Kubernetes Windows binaries](../../docs/kubernetes-build-win-binaries.md) - shows how to build kubernetes windows binaries for use in a Windows Kubernetes cluster. -* [Hybrid Swarm Mode with Linux and Windows nodes](../../docs/swarmmode-hybrid.md) - shows how to create a hybrid Swarm Mode cluster on Azure. - ## Sample Deployments diff --git a/examples/windows/dcos-win-version.json b/examples/windows/dcos-win-version.json deleted file mode 100644 index f4076e53cb..0000000000 --- a/examples/windows/dcos-win-version.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "dcos-mstr", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "win2", - "count": 2, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet", - "osType": "Windows", - "dnsPrefix": "agnt", - "ports": [ - 80, - 443, - 8080, - 3389 - ] - } - ], - "windowsProfile": { - "adminUsername": "azureuser", - "adminPassword": "replacepassword1234$", - "imageVersion": "2016.127.20170411" - }, - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} diff --git a/examples/windows/dcos-win.json b/examples/windows/dcos-win.json deleted file mode 100644 index a3f10db5fd..0000000000 --- a/examples/windows/dcos-win.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "dcos-mstr", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "win2", - "count": 2, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet", - "osType": "Windows", - "dnsPrefix": "agnt", - "ports": [ - 80, - 443, - 8080, - 3389 - ] - } - ], - "windowsProfile": { - "adminUsername": "azureuser", - "adminPassword": "replacepassword1234$" - }, - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} diff --git a/examples/windows/dcos-winagent.json b/examples/windows/dcos-winagent.json deleted file mode 100644 index a3f10db5fd..0000000000 --- a/examples/windows/dcos-winagent.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "dcos-mstr", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "win2", - "count": 2, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet", - "osType": "Windows", - "dnsPrefix": "agnt", - "ports": [ - 80, - 443, - 8080, - 3389 - ] - } - ], - "windowsProfile": { - "adminUsername": "azureuser", - "adminPassword": "replacepassword1234$" - }, - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - } - } -} diff --git a/examples/windows/swarmmode-hybrid.json b/examples/windows/swarmmode-hybrid.json deleted file mode 100644 index 5147db9844..0000000000 --- a/examples/windows/swarmmode-hybrid.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "ports": [ - 80, - 443, - 8080 - ] - }, - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "", - "osType": "Windows" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "" - } - ] - } - }, - "windowsProfile": { - "adminUsername": "azureuser", - "adminPassword": "replacepassword1234$" - } - } -} \ No newline at end of file diff --git a/extensions/hello-world-dcos-windows/README.md b/extensions/hello-world-dcos-windows/README.md deleted file mode 100644 index c5bf8f5be7..0000000000 --- a/extensions/hello-world-dcos-windows/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# hello-world-dcos Extension - -Sample hello-world extension. Calls the following on the master: - -``` - curl -X post http://localhost:8080/v2/apps -d "{ \"id\": \"hello-marathon\", \"cmd\": \"while [ true ] ; do echo 'Hello World' ; sleep 5 ; done\", \"cpus\": 0.1, \"mem\": 10.0, \"instances\": 1 }" -H "Content-type:application/json" -``` - -You can validate that the extension was run by running (make sure you have tunneled into the master): -``` -dcos auth login -dcos task log hello-marathon -``` - -# Configuration -|Name|Required|Acceptable Value| -|---|---|---| -|name|yes|hello-world-k8s| -|version|yes|v1| -|extensionParameters|no|| -|rootURL|optional|| - -# Example -``` javascript - "masterProfile": { - ... - "extensions": [ - { - "name": "hello-world-dcos", - "singleOrAll": "single" - } - ] - }, - ... - "extensionProfiles": [ - { - "name": "hello-world-dcos", - "version": "v1" - } - ] - - -``` - -# Supported Orchestrators -"DCOS", "DCOS173", "DCOS184", "DCOS188" \ No newline at end of file diff --git a/extensions/hello-world-dcos-windows/v1/hello-world-dcos.ps1 b/extensions/hello-world-dcos-windows/v1/hello-world-dcos.ps1 deleted file mode 100644 index dd88a0695c..0000000000 --- a/extensions/hello-world-dcos-windows/v1/hello-world-dcos.ps1 +++ /dev/null @@ -1,20 +0,0 @@ -# Script file to run hello-world in dcos - -#!/usr/bin/pwsh - - -Write-Host "$(date) - Starting Script" - -# Deploy container -Write-Host "$(date) - Deploying hello-world" - -$uri = "http://"+($env:DCOS_AGENT_IP)+":5051/metrics/snapshot" -while($true) { - $obj = ((Invoke-Webrequest -Method GET -URI $uri ).Content | ConvertFrom-JSON ) - Write-Host "$(date) - system/cpus_total = " ($obj.'system/cpus_total') ", mem free bytes = " ($obj.'system/mem_free_bytes') ", mem total bytes = " ($obj.'system/mem_total_bytes') - sleep 5 -} - -Write-Host "$(date) - view resources in mesos UI to validate" -Write-Host "$(date) - Script complete" - diff --git a/extensions/hello-world-dcos-windows/v1/supported-orchestrators.json b/extensions/hello-world-dcos-windows/v1/supported-orchestrators.json deleted file mode 100644 index f033603f58..0000000000 --- a/extensions/hello-world-dcos-windows/v1/supported-orchestrators.json +++ /dev/null @@ -1 +0,0 @@ -["DCOS", "DCOS173", "DCOS184", "DCOS188", "DCOS190"] \ No newline at end of file diff --git a/extensions/hello-world-dcos-windows/v1/template-link.json b/extensions/hello-world-dcos-windows/v1/template-link.json deleted file mode 100644 index 049177d4d0..0000000000 --- a/extensions/hello-world-dcos-windows/v1/template-link.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "[concat(EXTENSION_TARGET_VM_NAME_PREFIX, copyIndex(EXTENSION_LOOP_OFFSET), 'HelloWorldDcos')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "[variables('apiVersionLinkDefault')]", - "dependsOn": [ - "[resourceId('Microsoft.Compute/virtualMachines/extensions', concat(variables('masterVMNamePrefix'), sub(variables('masterCount'), 1)), 'waitforleader')]" - ], - "copy": { - "count": "EXTENSION_LOOP_COUNT", - "name": "helloWorldExtensionLoop" - }, - "properties": { - "mode": "Incremental", - "templateLink": { - "uri": "EXTENSION_URL_REPLACEextensions/hello-world-dcos-windows/v1/template.json", - "contentVersion": "1.0.0.0" - }, - "parameters": { - "artifactsLocation": { - "value": "EXTENSION_URL_REPLACE" - }, - "apiVersionDefault": { - "value": "[variables('apiVersionDefault')]" - }, - "targetVMName": { - "value": "[concat(EXTENSION_TARGET_VM_NAME_PREFIX, copyIndex(EXTENSION_LOOP_OFFSET))]" - }, - "extensionParameters": { - "value": "EXTENSION_PARAMETERS_REPLACE" - } - } - } -} diff --git a/extensions/hello-world-dcos-windows/v1/template.json b/extensions/hello-world-dcos-windows/v1/template.json deleted file mode 100644 index ef3c720856..0000000000 --- a/extensions/hello-world-dcos-windows/v1/template.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "artifactsLocation": { - "type": "string", - "minLength": 1, - "metadata": { - "description": "Artifacts Location - URL" - } - }, - "apiVersionDefault": { - "type": "string", - "minLength": 1, - "metadata": { - "description": "Compute API Version" - } - }, - "targetVMName":{ - "type": "string", - "minLength": 1, - "metadata": { - "description": "Name of the vm to run the " - } - }, - "extensionParameters": { - "type": "securestring", - "minLength": 0, - "metadata": { - "description": "Custom Parameter for Extension - for hello-world, this is empty" - } - } - }, - "variables": { - "singleQuote": "'", - "initScriptUrl": "[concat(parameters('artifactsLocation'), 'extensions/hello-world-dcos-windows/v1/hello-world-dcos.ps1')]" - }, - "resources": [ - { - "apiVersion": "[parameters('apiVersionDefault')]", - "dependsOn": [], - "location": "[resourceGroup().location]", - "type": "Microsoft.Compute/virtualMachines/extensions", - "name": "[concat(parameters('targetVMName'),'/waitforleader')]", - "properties": { - "publisher": "Microsoft.OSTCExtensions", - "type": "CustomScriptForLinux", - "typeHandlerVersion": "1.5", - "autoUpgradeMinorVersion": true, - "settings": { - "fileUris": [ - "[variables('initScriptUrl')]" - ] - }, - "protectedSettings": { - "commandToExecute": "[concat('powershell \"./hello-world-dcos.ps1 ', variables('singleQuote'), parameters('extensionParameters'), variables('singleQuote'), ' >> c:/azuredata/hello-world-dcos-provision.log 2>&1 &\" &')]" - } - } - } - ], - "outputs": { } -} diff --git a/extensions/hello-world-dcos/README.md b/extensions/hello-world-dcos/README.md deleted file mode 100644 index c5bf8f5be7..0000000000 --- a/extensions/hello-world-dcos/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# hello-world-dcos Extension - -Sample hello-world extension. Calls the following on the master: - -``` - curl -X post http://localhost:8080/v2/apps -d "{ \"id\": \"hello-marathon\", \"cmd\": \"while [ true ] ; do echo 'Hello World' ; sleep 5 ; done\", \"cpus\": 0.1, \"mem\": 10.0, \"instances\": 1 }" -H "Content-type:application/json" -``` - -You can validate that the extension was run by running (make sure you have tunneled into the master): -``` -dcos auth login -dcos task log hello-marathon -``` - -# Configuration -|Name|Required|Acceptable Value| -|---|---|---| -|name|yes|hello-world-k8s| -|version|yes|v1| -|extensionParameters|no|| -|rootURL|optional|| - -# Example -``` javascript - "masterProfile": { - ... - "extensions": [ - { - "name": "hello-world-dcos", - "singleOrAll": "single" - } - ] - }, - ... - "extensionProfiles": [ - { - "name": "hello-world-dcos", - "version": "v1" - } - ] - - -``` - -# Supported Orchestrators -"DCOS", "DCOS173", "DCOS184", "DCOS188" \ No newline at end of file diff --git a/extensions/hello-world-dcos/v1/hello-world-dcos.sh b/extensions/hello-world-dcos/v1/hello-world-dcos.sh deleted file mode 100644 index ef0b9da08d..0000000000 --- a/extensions/hello-world-dcos/v1/hello-world-dcos.sh +++ /dev/null @@ -1,16 +0,0 @@ -# Script file to run hello-world in dcos - -#!/bin/bash - -set -e - -echo $(date) " - Starting Script" - -# Deploy container -echo $(date) " - Deploying hello-world" - -curl -X post http://localhost:8080/v2/apps -d "{ \"id\": \"hello-marathon\", \"cmd\": \"while [ true ] ; do echo 'Hello World' ; sleep 5 ; done\", \"cpus\": 0.1, \"mem\": 10.0, \"instances\": 1 }" -H "Content-type:application/json" - -echo $(date) " - view applications in marathon UI to validate" -echo $(date) " - Script complete" - diff --git a/extensions/hello-world-dcos/v1/supported-orchestrators.json b/extensions/hello-world-dcos/v1/supported-orchestrators.json deleted file mode 100644 index f033603f58..0000000000 --- a/extensions/hello-world-dcos/v1/supported-orchestrators.json +++ /dev/null @@ -1 +0,0 @@ -["DCOS", "DCOS173", "DCOS184", "DCOS188", "DCOS190"] \ No newline at end of file diff --git a/extensions/hello-world-dcos/v1/template-link.json b/extensions/hello-world-dcos/v1/template-link.json deleted file mode 100644 index 2058956b52..0000000000 --- a/extensions/hello-world-dcos/v1/template-link.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "[concat(EXTENSION_TARGET_VM_NAME_PREFIX, copyIndex(EXTENSION_LOOP_OFFSET), 'HelloWorldDcos')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "[variables('apiVersionLinkDefault')]", - "dependsOn": [ - "[resourceId('Microsoft.Compute/virtualMachines/extensions', concat(variables('masterVMNamePrefix'), sub(variables('masterCount'), 1)), 'waitforleader')]" - ], - "copy": { - "count": "EXTENSION_LOOP_COUNT", - "name": "helloWorldExtensionLoop" - }, - "properties": { - "mode": "Incremental", - "templateLink": { - "uri": "EXTENSION_URL_REPLACEextensions/hello-world-dcos/v1/template.json", - "contentVersion": "1.0.0.0" - }, - "parameters": { - "artifactsLocation": { - "value": "EXTENSION_URL_REPLACE" - }, - "apiVersionDefault": { - "value": "[variables('apiVersionDefault')]" - }, - "targetVMName": { - "value": "[concat(EXTENSION_TARGET_VM_NAME_PREFIX, copyIndex(EXTENSION_LOOP_OFFSET))]" - }, - "extensionParameters": { - "value": "EXTENSION_PARAMETERS_REPLACE" - } - } - } -} diff --git a/extensions/hello-world-dcos/v1/template.json b/extensions/hello-world-dcos/v1/template.json deleted file mode 100644 index 5f4d9d92e7..0000000000 --- a/extensions/hello-world-dcos/v1/template.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "artifactsLocation": { - "type": "string", - "minLength": 1, - "metadata": { - "description": "Artifacts Location - URL" - } - }, - "apiVersionDefault": { - "type": "string", - "minLength": 1, - "metadata": { - "description": "Compute API Version" - } - }, - "targetVMName":{ - "type": "string", - "minLength": 1, - "metadata": { - "description": "Name of the vm to run the " - } - }, - "extensionParameters": { - "type": "securestring", - "minLength": 0, - "metadata": { - "description": "Custom Parameter for Extension - for hello-world, this is empty" - } - } - }, - "variables": { - "singleQuote": "'", - "initScriptUrl": "[concat(parameters('artifactsLocation'), 'extensions/hello-world-dcos/v1/hello-world-dcos.sh')]" - }, - "resources": [ - { - "apiVersion": "[parameters('apiVersionDefault')]", - "dependsOn": [], - "location": "[resourceGroup().location]", - "type": "Microsoft.Compute/virtualMachines/extensions", - "name": "[concat(parameters('targetVMName'),'/waitforleader')]", - "properties": { - "publisher": "Microsoft.OSTCExtensions", - "type": "CustomScriptForLinux", - "typeHandlerVersion": "1.5", - "autoUpgradeMinorVersion": true, - "settings": { - "fileUris": [ - "[variables('initScriptUrl')]" - ] - }, - "protectedSettings": { - "commandToExecute": "[concat('/bin/bash -c \"/bin/bash ./hello-world-dcos.sh ', variables('singleQuote'), parameters('extensionParameters'), variables('singleQuote'), ' >> /var/log/azure/hello-world-dcos-provision.log 2>&1 &\" &')]" - } - } - } - ], - "outputs": { } -} diff --git a/extensions/hello-world/v1/supported-orchestrators.json b/extensions/hello-world/v1/supported-orchestrators.json index 0e1e1223fb..e476badb19 100644 --- a/extensions/hello-world/v1/supported-orchestrators.json +++ b/extensions/hello-world/v1/supported-orchestrators.json @@ -1 +1 @@ -["Kubernetes","Swarm","SwarmMode","DCOS", "DCOS173", "DCOS184", "DCOS188", "DCOS190"] \ No newline at end of file +["Kubernetes"] diff --git a/extensions/microsoft-oms-agent-k8s/v1/microsoft-oms-agent-k8s.sh b/extensions/microsoft-oms-agent-k8s/v1/microsoft-oms-agent-k8s.sh index ffad48ee38..5d6e0a6869 100644 --- a/extensions/microsoft-oms-agent-k8s/v1/microsoft-oms-agent-k8s.sh +++ b/extensions/microsoft-oms-agent-k8s/v1/microsoft-oms-agent-k8s.sh @@ -175,7 +175,7 @@ then fi log '' -log 'ACS-Engine - installing Microsoft OMS Agent (k8s)' +log 'AKS Engine - installing Microsoft OMS Agent (k8s)' log '--------------------------------------------------' install_script_dependencies diff --git a/extensions/prometheus-grafana-k8s/README.md b/extensions/prometheus-grafana-k8s/README.md index 8dd1d24403..b0b00838ba 100644 --- a/extensions/prometheus-grafana-k8s/README.md +++ b/extensions/prometheus-grafana-k8s/README.md @@ -1,7 +1,7 @@ # prometheus-grafana Extension -This is the prometheus-grafana extension. Add this extension to the api model you pass as input into acs-engine as shown below to automatically enable prometheus and grafana in your new Kubernetes cluster. +This is the prometheus-grafana extension. Add this extension to the api model you pass as input into aks-engine as shown below to automatically enable prometheus and grafana in your new Kubernetes cluster. ``` { @@ -42,7 +42,7 @@ This is the prometheus-grafana extension. Add this extension to the api model y { "name": "prometheus-grafana-k8s", "version": "v1", - "rootURL": "https://raw.githubusercontent.com/Azure/acs-engine/master/" + "rootURL": "https://raw.githubusercontent.com/Azure/aks-engine/master/" } ], "servicePrincipalProfile": { diff --git a/extensions/prometheus-grafana-k8s/v1/prometheus-grafana-k8s.sh b/extensions/prometheus-grafana-k8s/v1/prometheus-grafana-k8s.sh index bde3b0c4a5..3ab78d2020 100644 --- a/extensions/prometheus-grafana-k8s/v1/prometheus-grafana-k8s.sh +++ b/extensions/prometheus-grafana-k8s/v1/prometheus-grafana-k8s.sh @@ -287,8 +287,8 @@ ensure_k8s_namespace_exists() { } NAMESPACE=default -RAW_PROMETHEUS_CHART_VALS="https://raw.githubusercontent.com/Azure/acs-engine/master/extensions/prometheus-grafana-k8s/v1/prometheus_values.yaml" -CADVISOR_CONFIG_URL="https://raw.githubusercontent.com/Azure/acs-engine/master/extensions/prometheus-grafana-k8s/v1/cadvisor_daemonset.yml" +RAW_PROMETHEUS_CHART_VALS="https://raw.githubusercontent.com/Azure/aks-engine/master/extensions/prometheus-grafana-k8s/v1/prometheus_values.yaml" +CADVISOR_CONFIG_URL="https://raw.githubusercontent.com/Azure/aks-engine/master/extensions/prometheus-grafana-k8s/v1/cadvisor_daemonset.yml" # retrieve and parse extension parameters if [[ -n "$1" ]]; then diff --git a/extensions/vamp-dcos/README.md b/extensions/vamp-dcos/README.md deleted file mode 100644 index a0a8f53697..0000000000 --- a/extensions/vamp-dcos/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# vamp-dcos Extension - -Installs VAMP 0.9.4 as per the [VAMP Standard Install](http://vamp.io/documentation/installation/v0.9.4/dcos/#standard-install). -Should only be ran on a single master after the waitforall extension has succeeded - -# Configuration -|Name|Required|Acceptable Value| -|---|---|---| -|name|yes|vamp-dcos| -|version|yes|v1| -|extensionParameters|no|| -|rootURL|optional|| -|singleOrAll|Required|single| - -# Example -```javascript - "masterProfile": { - ... - "extensions": [ - { - "name": "vamp-dcos", - "singleOrAll": "single" - } - ... - ] - }, - ... - "extensionProfiles": [ - { - "name": "vamp-dcos", - "version": "v1" - } - ] - -``` - -# Supported Orchestrators -DCOS \ No newline at end of file diff --git a/extensions/vamp-dcos/v1/supported-orchestrators.json b/extensions/vamp-dcos/v1/supported-orchestrators.json deleted file mode 100644 index af2afb8c62..0000000000 --- a/extensions/vamp-dcos/v1/supported-orchestrators.json +++ /dev/null @@ -1 +0,0 @@ -["DCOS", "DCOS173", "DCOS184", "DCOS188"] \ No newline at end of file diff --git a/extensions/vamp-dcos/v1/template-link.json b/extensions/vamp-dcos/v1/template-link.json deleted file mode 100644 index 67de07ac49..0000000000 --- a/extensions/vamp-dcos/v1/template-link.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "[concat(EXTENSION_TARGET_VM_NAME_PREFIX, copyIndex(EXTENSION_LOOP_OFFSET), 'VampDcosExtension')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "[variables('apiVersionLinkDefault')]", - "dependsOn": [ - "[resourceId('Microsoft.Compute/virtualMachines/extensions', concat(variables('masterVMNamePrefix'), sub(variables('masterCount'), 1)), 'waitforleader')]" - ], - "copy": { - "count": "EXTENSION_LOOP_COUNT", - "name": "vampExtensionLoop" - }, - "properties": { - "mode": "Incremental", - "templateLink": { - "uri": "EXTENSION_URL_REPLACEextensions/vamp-dcos/v1/template.json", - "contentVersion": "1.0.0.0" - }, - "parameters": { - "artifactsLocation": { - "value": "EXTENSION_URL_REPLACE" - }, - "apiVersionDefault": { - "value": "[variables('apiVersionDefault')]" - }, - "targetVMName": { - "value": "[concat(EXTENSION_TARGET_VM_NAME_PREFIX, copyIndex(EXTENSION_LOOP_OFFSET))]" - }, - "extensionParameters": { - "value": "EXTENSION_PARAMETERS_REPLACE" - } - } - } -} diff --git a/extensions/vamp-dcos/v1/template.json b/extensions/vamp-dcos/v1/template.json deleted file mode 100644 index b50754c83f..0000000000 --- a/extensions/vamp-dcos/v1/template.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "artifactsLocation": { - "type": "string", - "minLength": 1, - "metadata": { - "description": "Artifacts Location - URL" - } - }, - "apiVersionDefault": { - "type": "string", - "minLength": 1, - "metadata": { - "description": "Compute API Version" - } - }, - "targetVMName":{ - "type": "string", - "minLength": 1, - "metadata": { - "description": "Name of the vm to run the " - } - }, - "extensionParameters": { - "type": "securestring", - "minLength": 0, - "metadata": { - "description": "Custom Parameter for Extension - for VAMP, this is currently empty" - } - } - }, - "variables": { - "singleQuote": "'", - "initScriptUrl": "[concat(parameters('artifactsLocation'), 'extensions/vamp-dcos/v1/vamp-dcos.sh')]" - }, - "resources": [ - { - "apiVersion": "[parameters('apiVersionDefault')]", - "dependsOn": [], - "location": "[resourceGroup().location]", - "type": "Microsoft.Compute/virtualMachines/extensions", - "name": "[concat(parameters('targetVMName'),'/waitforleader')]", - "properties": { - "publisher": "Microsoft.OSTCExtensions", - "type": "CustomScriptForLinux", - "typeHandlerVersion": "1.5", - "autoUpgradeMinorVersion": true, - "settings": { - "fileUris": [ - "[variables('initScriptUrl')]" - ] - }, - "protectedSettings": { - "commandToExecute": "[concat('/bin/bash -c \"/bin/bash ./vamp-dcos.sh ', variables('singleQuote'), parameters('extensionParameters'), variables('singleQuote'), ' >> /var/log/azure/vamp-dcos-provision.log 2>&1 &\" &')]" - } - } - } - ], - "outputs": { } -} diff --git a/extensions/vamp-dcos/v1/vamp-dcos.sh b/extensions/vamp-dcos/v1/vamp-dcos.sh deleted file mode 100644 index e0f737019b..0000000000 --- a/extensions/vamp-dcos/v1/vamp-dcos.sh +++ /dev/null @@ -1,91 +0,0 @@ -# baseUrl="http://localhost:8080/marathon" # handy for local testing with SSH -baseUrl="http://marathon.mesos:8080" - -# definitions for elasticsearch and vamp applications (from http://vamp.io/documentation/installation/v0.9.3/dcos/) -elasticsearch='{"id":"elasticsearch","instances":1,"cpus":0.2,"mem":1024,"container":{"docker":{"image":"magneticio/elastic:2.2","network":"HOST","forcePullImage":true}},"healthChecks":[{"protocol":"TCP","gracePeriodSeconds":30,"intervalSeconds":10,"timeoutSeconds":5,"port":9200,"maxConsecutiveFailures":0}]}' -vamp='{"id":"vamp/vamp","instances":1,"cpus":0.5,"mem":1024,"container":{"type":"DOCKER","docker":{"image":"magneticio/vamp:0.9.4-dcos","network":"BRIDGE","portMappings":[{"containerPort":8080,"hostPort":0,"name":"vip0","labels":{"VIP_0":"10.20.0.100:8080"}}],"forcePullImage":true}},"labels":{"DCOS_SERVICE_NAME":"vamp","DCOS_SERVICE_SCHEME":"http","DCOS_SERVICE_PORT_INDEX":"0"},"env":{"VAMP_WAIT_FOR":"http://elasticsearch.marathon.mesos:9200/.kibana","VAMP_WORKFLOW_DRIVER_VAMP_URL":"http://10.20.0.100:8080","VAMP_ELASTICSEARCH_URL":"http://elasticsearch.marathon.mesos:9200"},"healthChecks":[{"protocol":"TCP","gracePeriodSeconds":30,"intervalSeconds":10,"timeoutSeconds":5,"portIndex":0,"maxConsecutiveFailures":0}]}' - - -function wait_for_running_app(){ - ## args - ## $1 - app name - appname=$1 - - ## wait for deployment - waitCount=0 - appRunning=0 - while [ $waitCount -lt 12 ] - do - echo "Testing for $appname running..." - appResponse=$(curl "$baseUrl/v2/apps/$appname" 2>/dev/null) # url for $appname app - if [[ $appResponse =~ \"state\":\"TASK_RUNNING\" ]]; then # test for TASK_RUNNING - echo "$appname running!" - appRunning=1 - return 0 - fi - - sleep 10s - waitCount=$[$waitCount+1] - done - return 1 -} - -## Start elasticsearch deployment -echo "Starting elasticsearch deployment" -curl -X POST "$baseUrl/v2/apps" -H 'Content-Type: application/json' -d $elasticsearch -echo "" - -wait_for_running_app "elasticsearch" -elasticRunning=$? - -if [[ $elasticRunning -ne 0 ]]; then - echo "elasticsearch not running - quitting" - exit 100 -fi - -## Start vamp deployment -echo "Starting vamp deployment" -curl -X POST "$baseUrl/v2/apps" -H 'Content-Type: application/json' -d $vamp -echo "" - -wait_for_running_app "vamp/vamp" -running=$? -if [[ $running -ne 0 ]]; then - echo "vamp/vamp not running - quitting" - exit 100 -fi - -wait_for_running_app "vamp/vamp-gateway-agent" -running=$? -if [[ $running -ne 0 ]]; then - echo "vamp/vamp-gateway-agent not running - quitting" - exit 100 -fi - -wait_for_running_app "vamp/workflow-health" -running=$? -if [[ $running -ne 0 ]]; then - echo "vamp/workflow-health not running - quitting" - exit 100 -fi - -wait_for_running_app "vamp/workflow-kibana" -running=$? -if [[ $running -ne 0 ]]; then - echo "vamp/workflow-kibana not running - quitting" - exit 100 -fi - -wait_for_running_app "vamp/workflow-metrics" -running=$? -if [[ $running -ne 0 ]]; then - echo "vamp/workflow-metrics not running - quitting" - exit 100 -fi - -wait_for_running_app "vamp/workflow-vga" -running=$? -if [[ $running -ne 0 ]]; then - echo "vamp/workflow-vga not running - quitting" - exit 100 -fi diff --git a/extensions/windows-patches/README.md b/extensions/windows-patches/README.md index a660ffd307..755699b37b 100644 --- a/extensions/windows-patches/README.md +++ b/extensions/windows-patches/README.md @@ -11,7 +11,7 @@ This extension will install Windows Server patches, including prerelease hotfixe |-------------------|--------|----------------------| |name |yes | windows-patches | |version |yes | v1 | -|rootURL |optional| `https://raw.githubusercontent.com/Azure/acs-engine/master/` or any repo with the same extensions/... directory structure | +|rootURL |optional| `https://raw.githubusercontent.com/Azure/aks-engine/master/` or any repo with the same extensions/... directory structure | |extensionParameters|yes | comma-delimited list of URIs enclosed with ' such as `'https://privateupdates.domain.ext/Windows10.0-KB999999-x64-InstallForTestingPurposesOnly.exe', 'https://privateupdates.domain.ext/Windows10.0-KB123456-x64-InstallForTestingPurposesOnly.exe'` | ## Example @@ -33,7 +33,7 @@ This extension will install Windows Server patches, including prerelease hotfixe { "name": "windows-patches", "version": "v1", - "rootURL": "https://raw.githubusercontent.com/Azure/acs-engine/master/", + "rootURL": "https://raw.githubusercontent.com/Azure/aks-engine/master/", "extensionParameters": "'https://mypatches.blob.core.windows.net/hotfix3692/Windows10.0-KB999999-x64-InstallForTestingPurposesOnly.exe?sp=r&st=2018-08-17T00:25:01Z&se=2018-09-17T08:25:01Z&spr=https&sv=2017-11-09&sig=0000000000%3D&sr=b', 'http://download.windowsupdate.com/c/msdownload/update/software/secu/2018/08/windows10.0-kb4343909-x64_f931af6d56797388715fe3b0d97569af7aebdae6.msu'" } ] diff --git a/labels.yaml b/labels.yaml index 60246d568b..79f9830721 100644 --- a/labels.yaml +++ b/labels.yaml @@ -1,6 +1,6 @@ # Scanned and autogenerated by https://github.com/tonglil/labeler --- -repo: Azure/acs-engine +repo: Azure/aks-engine labels: - name: backlog color: e99695 @@ -36,14 +36,8 @@ labels: color: fbca04 - name: needs more information color: d93f0b -- name: orchestrator/dcos - color: fbca04 - name: orchestrator/k8s color: 2e64d2 -- name: orchestrator/swarm - color: "5319e7" -- name: orchestrator/swarmmode - color: 006b75 - name: priority/P0 color: b60205 - name: priority/P1 diff --git a/loc/cs-CZ/acsengine.po.lcl b/loc/cs-CZ/aksengine.po.lcl similarity index 96% rename from loc/cs-CZ/acsengine.po.lcl rename to loc/cs-CZ/aksengine.po.lcl index 13330cb236..65af3058b3 100644 --- a/loc/cs-CZ/acsengine.po.lcl +++ b/loc/cs-CZ/aksengine.po.lcl @@ -1,5 +1,5 @@  - + diff --git a/loc/de-DE/acsengine.po.lcl b/loc/de-DE/aksengine.po.lcl similarity index 96% rename from loc/de-DE/acsengine.po.lcl rename to loc/de-DE/aksengine.po.lcl index c4a75f8d8a..769fcc2ca6 100644 --- a/loc/de-DE/acsengine.po.lcl +++ b/loc/de-DE/aksengine.po.lcl @@ -1,5 +1,5 @@  - + diff --git a/loc/es-ES/acsengine.po.lcl b/loc/es-ES/aksengine.po.lcl similarity index 96% rename from loc/es-ES/acsengine.po.lcl rename to loc/es-ES/aksengine.po.lcl index fc0b0e8151..b92250ad5e 100644 --- a/loc/es-ES/acsengine.po.lcl +++ b/loc/es-ES/aksengine.po.lcl @@ -1,5 +1,5 @@  - + diff --git a/loc/fr-FR/acsengine.po.lcl b/loc/fr-FR/aksengine.po.lcl similarity index 96% rename from loc/fr-FR/acsengine.po.lcl rename to loc/fr-FR/aksengine.po.lcl index 76f485daf7..d3ea00a427 100644 --- a/loc/fr-FR/acsengine.po.lcl +++ b/loc/fr-FR/aksengine.po.lcl @@ -1,5 +1,5 @@  - + diff --git a/loc/hu-HU/acsengine.po.lcl b/loc/hu-HU/aksengine.po.lcl similarity index 96% rename from loc/hu-HU/acsengine.po.lcl rename to loc/hu-HU/aksengine.po.lcl index be6c28693a..e9ee436240 100644 --- a/loc/hu-HU/acsengine.po.lcl +++ b/loc/hu-HU/aksengine.po.lcl @@ -1,5 +1,5 @@  - + diff --git a/loc/it-IT/acsengine.po.lcl b/loc/it-IT/aksengine.po.lcl similarity index 96% rename from loc/it-IT/acsengine.po.lcl rename to loc/it-IT/aksengine.po.lcl index 2252f17d5f..49bdc7deaf 100644 --- a/loc/it-IT/acsengine.po.lcl +++ b/loc/it-IT/aksengine.po.lcl @@ -1,5 +1,5 @@  - + diff --git a/loc/ja-JP/acsengine.po.lcl b/loc/ja-JP/aksengine.po.lcl similarity index 96% rename from loc/ja-JP/acsengine.po.lcl rename to loc/ja-JP/aksengine.po.lcl index cd5a911aa8..dc2888d8e3 100644 --- a/loc/ja-JP/acsengine.po.lcl +++ b/loc/ja-JP/aksengine.po.lcl @@ -1,5 +1,5 @@  - + diff --git a/loc/ko-KR/acsengine.po.lcl b/loc/ko-KR/aksengine.po.lcl similarity index 96% rename from loc/ko-KR/acsengine.po.lcl rename to loc/ko-KR/aksengine.po.lcl index 1c8058041c..2a802df73e 100644 --- a/loc/ko-KR/acsengine.po.lcl +++ b/loc/ko-KR/aksengine.po.lcl @@ -1,5 +1,5 @@  - + diff --git a/loc/nl-NL/acsengine.po.lcl b/loc/nl-NL/aksengine.po.lcl similarity index 96% rename from loc/nl-NL/acsengine.po.lcl rename to loc/nl-NL/aksengine.po.lcl index e90d2a16ce..1940885127 100644 --- a/loc/nl-NL/acsengine.po.lcl +++ b/loc/nl-NL/aksengine.po.lcl @@ -1,5 +1,5 @@  - + diff --git a/loc/pl-PL/acsengine.po.lcl b/loc/pl-PL/aksengine.po.lcl similarity index 96% rename from loc/pl-PL/acsengine.po.lcl rename to loc/pl-PL/aksengine.po.lcl index d3af5f666d..0362ae11f5 100644 --- a/loc/pl-PL/acsengine.po.lcl +++ b/loc/pl-PL/aksengine.po.lcl @@ -1,5 +1,5 @@  - + diff --git a/loc/pt-BR/acsengine.po.lcl b/loc/pt-BR/aksengine.po.lcl similarity index 96% rename from loc/pt-BR/acsengine.po.lcl rename to loc/pt-BR/aksengine.po.lcl index d2e04f5bae..683bce8204 100644 --- a/loc/pt-BR/acsengine.po.lcl +++ b/loc/pt-BR/aksengine.po.lcl @@ -1,5 +1,5 @@  - + diff --git a/loc/pt-PT/acsengine.po.lcl b/loc/pt-PT/aksengine.po.lcl similarity index 96% rename from loc/pt-PT/acsengine.po.lcl rename to loc/pt-PT/aksengine.po.lcl index 414a3e19a2..62c7af2245 100644 --- a/loc/pt-PT/acsengine.po.lcl +++ b/loc/pt-PT/aksengine.po.lcl @@ -1,5 +1,5 @@  - + diff --git a/loc/ru-RU/acsengine.po.lcl b/loc/ru-RU/aksengine.po.lcl similarity index 96% rename from loc/ru-RU/acsengine.po.lcl rename to loc/ru-RU/aksengine.po.lcl index 173d0e7a1f..9ff940b7c5 100644 --- a/loc/ru-RU/acsengine.po.lcl +++ b/loc/ru-RU/aksengine.po.lcl @@ -1,5 +1,5 @@  - + diff --git a/loc/sv-SE/acsengine.po.lcl b/loc/sv-SE/aksengine.po.lcl similarity index 96% rename from loc/sv-SE/acsengine.po.lcl rename to loc/sv-SE/aksengine.po.lcl index 9cd2f670fa..31d6675fb2 100644 --- a/loc/sv-SE/acsengine.po.lcl +++ b/loc/sv-SE/aksengine.po.lcl @@ -1,5 +1,5 @@  - + diff --git a/loc/tr-TR/acsengine.po.lcl b/loc/tr-TR/aksengine.po.lcl similarity index 96% rename from loc/tr-TR/acsengine.po.lcl rename to loc/tr-TR/aksengine.po.lcl index dc4da22e72..2e2cbaacf0 100644 --- a/loc/tr-TR/acsengine.po.lcl +++ b/loc/tr-TR/aksengine.po.lcl @@ -1,5 +1,5 @@  - + diff --git a/loc/zh-CN/acsengine.po.lcl b/loc/zh-CN/aksengine.po.lcl similarity index 96% rename from loc/zh-CN/acsengine.po.lcl rename to loc/zh-CN/aksengine.po.lcl index b90e122d86..412e96144f 100644 --- a/loc/zh-CN/acsengine.po.lcl +++ b/loc/zh-CN/aksengine.po.lcl @@ -1,5 +1,5 @@  - + diff --git a/loc/zh-TW/acsengine.po.lcl b/loc/zh-TW/aksengine.po.lcl similarity index 96% rename from loc/zh-TW/acsengine.po.lcl rename to loc/zh-TW/aksengine.po.lcl index 579a50c026..04931de68c 100644 --- a/loc/zh-TW/acsengine.po.lcl +++ b/loc/zh-TW/aksengine.po.lcl @@ -1,5 +1,5 @@  - + diff --git a/main.go b/main.go index 5644a80507..75d1aa2ee4 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/Azure/acs-engine/cmd" + "github.com/Azure/aks-engine/cmd" "github.com/mattn/go-colorable" log "github.com/sirupsen/logrus" ) diff --git a/makedev.ps1 b/makedev.ps1 index f55733527d..62bc2bf085 100644 --- a/makedev.ps1 +++ b/makedev.ps1 @@ -1,4 +1,4 @@ -$REPO_PATH = "github.com/Azure/acs-engine" +$REPO_PATH = "github.com/Azure/aks-engine" $DEV_ENV_IMAGE = "quay.io/deis/go-dev:v1.17.2" $DEV_ENV_WORK_DIR = "/go/src/$REPO_PATH" diff --git a/packer/install-dependencies.sh b/packer/install-dependencies.sh index de5250f5e8..f5ed222f8f 100644 --- a/packer/install-dependencies.sh +++ b/packer/install-dependencies.sh @@ -153,7 +153,7 @@ done pullContainerImage "docker" "busybox" -# TODO: fetch supported k8s versions from an acs-engine command instead of hardcoding them here +# TODO: fetch supported k8s versions from an aks-engine command instead of hardcoding them here K8S_VERSIONS="1.7.15 1.7.16 1.8.14 1.8.15 1.9.10 1.9.11 1.10.8 1.10.9 1.11.3 1.11.4 1.12.1 1.12.2" for KUBERNETES_VERSION in ${K8S_VERSIONS}; do diff --git a/parts/agentoutputs.t b/parts/agentoutputs.t index f809141e28..a4a9aef535 100644 --- a/parts/agentoutputs.t +++ b/parts/agentoutputs.t @@ -1,5 +1,5 @@ {{if IsPublic .Ports}} - {{ if and (not IsKubernetes) (not IsOpenShift)}} + {{ if (not IsKubernetes) }} "{{.Name}}FQDN": { "type": "string", "value": "[reference(concat('Microsoft.Network/publicIPAddresses/', variables('{{.Name}}IPAddressName'))).dnsSettings.fqdn]" @@ -19,4 +19,4 @@ "type": "string", "value": "[variables('{{.Name}}SubnetName')]" }, -{{end}} \ No newline at end of file +{{end}} diff --git a/parts/dcos/bstrap/bootstrapcustomdata.yml b/parts/dcos/bstrap/bootstrapcustomdata.yml deleted file mode 100644 index 2d234013e0..0000000000 --- a/parts/dcos/bstrap/bootstrapcustomdata.yml +++ /dev/null @@ -1,87 +0,0 @@ -bootcmd: -- bash -c "if [ ! -f /var/lib/sdb-gpt ];then echo DCOS-5890;parted -s /dev/sdb mklabel - gpt;touch /var/lib/sdb-gpt;fi" -disk_setup: - ephemeral0: - layout: - - 50 - - 50 - overwrite: true - table_type: gpt -fs_setup: -- device: ephemeral0.1 - filesystem: ext4 - overwrite: true -- device: ephemeral0.2 - filesystem: ext4 - overwrite: true -mounts: -- - ephemeral0.1 - - /var/lib/mesos -- - ephemeral0.2 - - /var/lib/docker -runcmd: - - [ ln, -s, /bin/rm, /usr/bin/rm ] - - [ ln, -s, /bin/mkdir, /usr/bin/mkdir ] - - [ ln, -s, /bin/tar, /usr/bin/tar ] - - [ ln, -s, /bin/ln, /usr/bin/ln ] - - [ ln, -s, /bin/cp, /usr/bin/cp ] - - [ ln, -s, /bin/systemctl, /usr/bin/systemctl ] - - [ ln, -s, /bin/mount, /usr/bin/mount ] - - [ ln, -s, /bin/bash, /usr/bin/bash ] - - [ ln, -s, /usr/sbin/useradd, /usr/bin/useradd ] - - /opt/azure/containers/provision.sh - - /opt/azure/dcos/init_bootstrap.sh -write_files: -- content: | - DCOS_ENVIRONMENT={{{targetEnvironment}}} - owner: root - path: /opt/azure/dcos/environment - permissions: '0644' -- content: | - #!/bin/sh - - curl -H Metadata:true -fsSL "http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/privateIpAddress?api-version=2017-04-02&format=text" - owner: root - path: /opt/azure/dcos/genconf/ip-detect - permissions: '0755' -- content: | - bootstrap_url: http://BOOTSTRAP_IP:8086 - cluster_name: azure-dcos - exhibitor_storage_backend: static - master_discovery: static - oauth_enabled: BOOTSTRAP_OAUTH_ENABLED - ip_detect_public_filename: genconf/ip-detect - master_list: -MASTER_IP_LIST - resolvers: - - 168.63.129.16 - dns_search: - owner: root - path: /opt/azure/dcos/genconf/config.yaml - permissions: '0644' -- content: | - #!/bin/bash - - source /opt/azure/containers/provision_source.sh - - # update dns_search - dns=$(grep search /etc/resolv.conf | cut -d " " -f 2) - sed -i "/dns_search:/c dns_search: $dns" /opt/azure/dcos/genconf/config.yaml - # install and run bootstrap package - cd /opt/azure/dcos - retrycmd_if_failure 10 10 120 curl -fsSL -o dcos_generate_config.sh.sha1sum {{{dcosBootstrapURL}}}.sha1sum - retry_download 1 1 120 {{{dcosBootstrapURL}}} dcos_generate_config.sh $(cat dcos_generate_config.sh.sha1sum) - bash dcos_generate_config.sh - docker run -d -p 8086:80 -v $PWD/genconf/serve:/usr/share/nginx/html:ro nginx - owner: root - path: /opt/azure/dcos/init_bootstrap.sh - permissions: '0755' -- content: 'PROVISION_SOURCE_STR' - path: /opt/azure/containers/provision_source.sh - permissions: "0744" - owner: "root" -- content: 'PROVISION_STR' - path: /opt/azure/containers/provision.sh - permissions: "0744" - owner: "root" diff --git a/parts/dcos/bstrap/bootstrapparams.t b/parts/dcos/bstrap/bootstrapparams.t deleted file mode 100644 index 2de386493c..0000000000 --- a/parts/dcos/bstrap/bootstrapparams.t +++ /dev/null @@ -1,166 +0,0 @@ - "linuxAdminUsername": { - "metadata": { - "description": "User name for the Linux Virtual Machines (SSH or Password)." - }, - "type": "string" - }, - {{range .ExtensionProfiles}} - "{{.Name}}Parameters": { - "metadata": { - "description": "Parameters for the extension" - }, - "type": "securestring" - }, - {{end}} -{{if IsHostedBootstrap}} - "bootstrapSubnet": { - "defaultValue": "{{.HostedBootstrapProfile.Subnet}}", - "metadata": { - "description": "Sets the subnet for the VMs in the cluster." - }, - "type": "string" - }, - "bootstrapEndpoint": { - "defaultValue": "{{.HostedBootstrapProfile.FQDN}}", - "metadata": { - "description": "Sets the static IP of the first bootstrap" - }, - "type": "string" - }, -{{else}} - "bootstrapStaticIP": { - "metadata": { - "description": "Sets the static IP of the first bootstrap" - }, - "type": "string" - }, - "bootstrapVMSize": { - {{GetMasterAllowedSizes}} - "metadata": { - "description": "The size of the Virtual Machine." - }, - "type": "string" - }, -{{end}} - "sshRSAPublicKey": { - "metadata": { - "description": "SSH public key used for auth to all Linux machines. Not Required. If not set, you must provide a password key." - }, - "type": "string" - }, - "nameSuffix": { - "defaultValue": "{{GetUniqueNameSuffix}}", - "metadata": { - "description": "A string hash of the bootstrap DNS name to uniquely identify the cluster." - }, - "type": "string" - }, - "osImageName": { - "defaultValue": "", - "metadata": { - "description": "Name of a Linux OS image. Needs to be used in conjuction with osImageResourceGroup." - }, - "type": "string" - }, - "osImageResourceGroup": { - "defaultValue": "", - "metadata": { - "description": "Resource group of a Linux OS image. Needs to be used in conjuction with osImageName." - }, - "type": "string" - }, - "osImageOffer": { - "defaultValue": "UbuntuServer", - "metadata": { - "description": "Linux OS image type." - }, - "type": "string" - }, - "osImagePublisher": { - "defaultValue": "Canonical", - "metadata": { - "description": "OS image publisher." - }, - "type": "string" - }, - "osImageSKU": { - "defaultValue": "16.04-LTS", - "metadata": { - "description": "OS image SKU." - }, - "type": "string" - }, - "osImageVersion": { - "defaultValue": "16.04.201804050", - "metadata": { - "description": "OS image version." - }, - "type": "string" - }, - "fqdnEndpointSuffix":{ - "defaultValue": "cloudapp.azure.com", - "metadata": { - "description": "Endpoint of FQDN." - }, - "type": "string" - }, - "targetEnvironment": { - "defaultValue": "AzurePublicCloud", - "metadata": { - "description": "The azure deploy environment. Currently support: AzurePublicCloud, AzureChinaCloud" - }, - "type": "string" - }, - "location": { - "defaultValue": "{{GetLocation}}", - "metadata": { - "description": "Sets the location for all resources in the cluster" - }, - "type": "string" - } -{{if .LinuxProfile.HasSecrets}} - {{range $vIndex, $vault := .LinuxProfile.Secrets}} - , - "linuxKeyVaultID{{$vIndex}}": { - "metadata": { - "description": "KeyVaultId{{$vIndex}} to install certificates from on linux machines." - }, - "type": "string" - } - {{range $cIndex, $cert := $vault.VaultCertificates}} - , - "linuxKeyVaultID{{$vIndex}}CertificateURL{{$cIndex}}": { - "metadata": { - "description": "CertificateURL{{$cIndex}} to install from KeyVaultId{{$vIndex}} on linux machines." - }, - "type": "string" - } - {{end}} - {{end}} -{{end}} -{{if .HasWindows}}{{if .WindowsProfile.HasSecrets}} - {{range $vIndex, $vault := .WindowsProfile.Secrets}} - , - "windowsKeyVaultID{{$vIndex}}": { - "metadata": { - "description": "KeyVaultId{{$vIndex}} to install certificates from on windows machines." - }, - "type": "string" - } - {{range $cIndex, $cert := $vault.VaultCertificates}} - , - "windowsKeyVaultID{{$vIndex}}CertificateURL{{$cIndex}}": { - "metadata": { - "description": "Url to retrieve Certificate{{$cIndex}} from KeyVaultId{{$vIndex}} to install on windows machines." - }, - "type": "string" - }, - "windowsKeyVaultID{{$vIndex}}CertificateStore{{$cIndex}}": { - "metadata": { - "description": "CertificateStore to install Certificate{{$cIndex}} from KeyVaultId{{$vIndex}} on windows machines." - }, - "type": "string" - } - {{end}} - {{end}} -{{end}} {{end}} diff --git a/parts/dcos/bstrap/bootstrapprovision.sh b/parts/dcos/bstrap/bootstrapprovision.sh deleted file mode 100644 index bc0a63ae85..0000000000 --- a/parts/dcos/bstrap/bootstrapprovision.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -source /opt/azure/containers/provision_source.sh -source /opt/azure/dcos/environment - -# default dc/os component download address (Azure CDN) -packages=( - https://dcos-mirror.azureedge.net/pkg/libltdl7_2.4.6-0.1_amd64.deb - https://dcos-mirror.azureedge.net/pkg/docker-ce_17.09.0~ce-0~ubuntu_amd64.deb -) - -# sha1sum checksums for @packages -sha1sums=( - 9a0f9f2769d3dc834737aa7df50aaaea369af98d - 94f6e89be6d45d9988269a237eb27c7d6a844d7f -) - -case $DCOS_ENVIRONMENT in - # because of Chinese GreatWall Firewall, the default packages on Azure CDN is blocked. So the following Chinese local mirror url should be used instead. - AzureChinaCloud) - packages=( - http://acsengine.blob.core.chinacloudapi.cn/dcos/libltdl7_2.4.6-0.1_amd64.deb - http://mirror.kaiyuanshe.cn/docker-ce/linux/ubuntu/dists/xenial/pool/stable/amd64/docker-ce_17.09.0~ce-0~ubuntu_amd64.deb - ) - ;; -esac - -len=$((${#packages[@]}-1)) -for i in $(seq 0 $len); do - retry_get_install_deb 10 10 120 ${packages[$i]} ${sha1sums[$i]} - if [ $? -ne 0 ]; then - exit 1 - fi -done diff --git a/parts/dcos/bstrap/bootstrapresources.t b/parts/dcos/bstrap/bootstrapresources.t deleted file mode 100644 index 261133d712..0000000000 --- a/parts/dcos/bstrap/bootstrapresources.t +++ /dev/null @@ -1,177 +0,0 @@ -{{if HasBootstrapPublicIP}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "bootstrapPublicIP", - "properties": { - "publicIPAllocationMethod": "Dynamic" - }, - "type": "Microsoft.Network/publicIPAddresses" - }, -{{end}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('bootstrapNSGName')]", - "properties": { - "securityRules": [ - { - "properties": { - "priority": 200, - "access": "Allow", - "direction": "Inbound", - "destinationPortRange": "22", - "sourcePortRange": "*", - "destinationAddressPrefix": "*", - "protocol": "Tcp", - "description": "Allow SSH", - "sourceAddressPrefix": "*" - }, - "name": "ssh" - }, - { - "properties": { - "priority": 201, - "access": "Allow", - "direction": "Inbound", - "destinationPortRange": "8086", - "sourcePortRange": "*", - "destinationAddressPrefix": "*", - "protocol": "Tcp", - "description": "Allow bootstrap service", - "sourceAddressPrefix": "*" - }, - "name": "Port8086" - } - ] - }, - "type": "Microsoft.Network/networkSecurityGroups" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ -{{if not .MasterProfile.IsCustomVNET}} - "[variables('vnetID')]", -{{end}} -{{if HasBootstrapPublicIP}} - "bootstrapPublicIP", -{{end}} - "[variables('bootstrapNSGID')]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('bootstrapVMName'), '-nic')]", - "properties": { - "ipConfigurations": [ - { - "name": "ipConfigNode", - "properties": { - "privateIPAddress": "[variables('bootstrapStaticIP')]", - "privateIPAllocationMethod": "Static", -{{if HasBootstrapPublicIP}} - "publicIpAddress": { - "id": "[resourceId('Microsoft.Network/publicIpAddresses', 'bootstrapPublicIP')]" - }, -{{end}} - "subnet": { - "id": "[variables('masterVnetSubnetID')]" - } - } - } - ], - "networkSecurityGroup": { - "id": "[variables('bootstrapNSGID')]" - } - }, - "type": "Microsoft.Network/networkInterfaces" - }, - { - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", - "dependsOn": [ - "[concat('Microsoft.Network/networkInterfaces/', variables('bootstrapVMName'), '-nic')]", -{{if .MasterProfile.IsStorageAccount}} - "[variables('masterStorageAccountName')]", -{{end}} - "[variables('masterStorageAccountExhibitorName')]" - ], - "tags": - { - "creationSource": "[concat('acsengine-', variables('bootstrapVMName'))]", - "orchestratorName": "dcos", - "orchestratorVersion": "[variables('orchestratorVersion')]", - "orchestratorNode": "bootstrap" - }, - "location": "[variables('location')]", - "name": "[variables('bootstrapVMName')]", - "properties": { - "hardwareProfile": { - "vmSize": "[variables('bootstrapVMSize')]" - }, - "networkProfile": { - "networkInterfaces": [ - { - "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(variables('bootstrapVMName'), '-nic'))]" - } - ] - }, - "osProfile": { - "adminUsername": "[variables('adminUsername')]", - "computername": "[variables('bootstrapVMName')]", - {{GetDCOSBootstrapCustomData}} - "linuxConfiguration": { - "disablePasswordAuthentication": "true", - "ssh": { - "publicKeys": [ - { - "keyData": "[variables('sshRSAPublicKey')]", - "path": "[variables('sshKeyPath')]" - } - ] - } - } - {{if .LinuxProfile.HasSecrets}} - , - "secrets": "[variables('linuxProfileSecrets')]" - {{end}} - }, - "storageProfile": { - "imageReference": { - "offer": "[variables('osImageOffer')]", - "publisher": "[variables('osImagePublisher')]", - "sku": "[variables('osImageSKU')]", - "version": "[variables('osImageVersion')]" - }, - "osDisk": { - "caching": "ReadWrite" - ,"createOption": "FromImage" -{{if .MasterProfile.IsStorageAccount}} - ,"name": "[concat(variables('bootstrapVMName'), '-osdisk')]" - ,"vhd": { - "uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('masterStorageAccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'vhds/',variables('bootstrapVMName'),-osdisk.vhd')]" - } -{{end}} -{{if ne .OrchestratorProfile.DcosConfig.BootstrapProfile.OSDiskSizeGB 0}} - ,"diskSizeGB": "60" -{{end}} - } - } - }, - "type": "Microsoft.Compute/virtualMachines" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[concat('Microsoft.Compute/virtualMachines/', variables('bootstrapVMName'))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('bootstrapVMName'), '/bootstrapready')]", - "properties": { - "autoUpgradeMinorVersion": true, - "publisher": "Microsoft.OSTCExtensions", - "settings": { - "commandToExecute": "[concat('/bin/bash -c \"until curl -f http://', variables('bootstrapStaticIP'), ':8086/dcos_install.sh > /dev/null; do echo waiting for bootstrap node; sleep 15; done; echo bootstrap node up\"')]" - }, - "type": "CustomScriptForLinux", - "typeHandlerVersion": "1.4" - }, - "type": "Microsoft.Compute/virtualMachines/extensions" - }{{WriteLinkedTemplatesForExtensions}} diff --git a/parts/dcos/bstrap/bootstrapvars.t b/parts/dcos/bstrap/bootstrapvars.t deleted file mode 100644 index 3cc8c0a2d6..0000000000 --- a/parts/dcos/bstrap/bootstrapvars.t +++ /dev/null @@ -1,9 +0,0 @@ -{{if .OrchestratorProfile.DcosConfig.BootstrapProfile}} - , - "dcosBootstrapURL": "[parameters('dcosBootstrapURL')]", - "bootstrapVMSize": "[parameters('bootstrapVMSize')]", - "bootstrapNSGID": "[resourceId('Microsoft.Network/networkSecurityGroups',variables('bootstrapNSGName'))]", - "bootstrapNSGName": "[concat('bootstrap-nsg-', variables('nameSuffix'))]", - "bootstrapVMName": "[concat('bootstrap-', variables('nameSuffix'))]", - "bootstrapStaticIP": "[parameters('bootstrapStaticIP')]" -{{end}} diff --git a/parts/dcos/bstrap/dcos1.11.0.customdata.t b/parts/dcos/bstrap/dcos1.11.0.customdata.t deleted file mode 100644 index 2ce2107ca6..0000000000 --- a/parts/dcos/bstrap/dcos1.11.0.customdata.t +++ /dev/null @@ -1,99 +0,0 @@ -bootcmd: -- bash -c "if [ ! -f /var/lib/sdb-gpt ];then echo DCOS-5890;parted -s /dev/sdb mklabel - gpt;touch /var/lib/sdb-gpt;fi" -disk_setup: - ephemeral0: - layout: - - 50 - - 50 - overwrite: true - table_type: gpt -fs_setup: -- device: ephemeral0.1 - filesystem: ext4 - overwrite: true -- device: ephemeral0.2 - filesystem: ext4 - overwrite: true -mounts: -- - ephemeral0.1 - - /var/lib/mesos -- - ephemeral0.2 - - /var/lib/docker -runcmd: PREPROVISION_EXTENSION -- ln -s /bin/rm /usr/bin/rm -- ln -s /bin/mkdir /usr/bin/mkdir -- ln -s /bin/tar /usr/bin/tar -- ln -s /bin/ln /usr/bin/ln -- ln -s /bin/cp /usr/bin/cp -- ln -s /bin/systemctl /usr/bin/systemctl -- ln -s /bin/mount /usr/bin/mount -- ln -s /bin/bash /usr/bin/bash -- ln -s /usr/sbin/useradd /usr/bin/useradd -- systemctl disable --now resolvconf.service -- systemctl mask --now lxc-net.service -- systemctl disable --now unscd.service -- systemctl stop --now unscd.service -- /opt/azure/containers/provision.sh -- bash /tmp/dcos/dcos_install.sh ROLENAME -- /opt/azure/dcos/postinstall-cond.sh -- bash /opt/azure/dcos/diagnostics_fix.sh -write_files: -- content: | - [Service] - Restart=always - StartLimitInterval=0 - RestartSec=15 - ExecStartPre=-/sbin/ip link del docker0 - ExecStart= - ExecStart=/usr/bin/dockerd --storage-driver=overlay - path: /etc/systemd/system/docker.service.d/execstart.conf - permissions: '0644' -- content: | - [Unit] - PartOf=docker.service - [Socket] - ListenStream=/var/run/docker.sock - SocketMode=0660 - SocketUser=root - SocketGroup=docker - ListenStream=2375 - BindIPv6Only=both - [Install] - WantedBy=sockets.target - path: /etc/systemd/system/docker.socket - permissions: '0644' -- content: | - DCOS_ENVIRONMENT={{{targetEnvironment}}} - owner: root - path: /opt/azure/dcos/environment - permissions: '0644' -- content: | - #!/bin/bash - - for f in /opt/mesosphere/packages/dcos-config--setup_*/etc/dcos-diagnostics-runner-config.json; do - if [ -e $f ]; then - sed -i.bak "99 s/1s/10s/" $f - fi - done - owner: root - path: /opt/azure/dcos/diagnostics_fix.sh - permissions: '0744' -- path: /var/lib/dcos/mesos-slave-common - content: 'ATTRIBUTES_STR' - permissions: "0644" - owner: "root" -- content: 'PROVISION_SOURCE_STR' - path: /opt/azure/containers/provision_source.sh - permissions: "0744" - owner: "root" -- content: 'PROVISION_STR' - path: /opt/azure/containers/provision.sh - permissions: "0744" - owner: "root" -- content: | - #!/bin/bash - if [ -f /opt/azure/dcos/postinstall.sh ]; then /opt/azure/dcos/postinstall.sh; fi - path: /opt/azure/dcos/postinstall-cond.sh - permissions: "0744" - owner: "root" diff --git a/parts/dcos/bstrap/dcos1.11.2.customdata.t b/parts/dcos/bstrap/dcos1.11.2.customdata.t deleted file mode 100644 index 36670658fd..0000000000 --- a/parts/dcos/bstrap/dcos1.11.2.customdata.t +++ /dev/null @@ -1,87 +0,0 @@ -bootcmd: -- bash -c "if [ ! -f /var/lib/sdb-gpt ];then echo DCOS-5890;parted -s /dev/sdb mklabel - gpt;touch /var/lib/sdb-gpt;fi" -disk_setup: - ephemeral0: - layout: - - 50 - - 50 - overwrite: true - table_type: gpt -fs_setup: -- device: ephemeral0.1 - filesystem: ext4 - overwrite: true -- device: ephemeral0.2 - filesystem: ext4 - overwrite: true -mounts: -- - ephemeral0.1 - - /var/lib/mesos -- - ephemeral0.2 - - /var/lib/docker -runcmd: PREPROVISION_EXTENSION -- ln -s /bin/rm /usr/bin/rm -- ln -s /bin/mkdir /usr/bin/mkdir -- ln -s /bin/tar /usr/bin/tar -- ln -s /bin/ln /usr/bin/ln -- ln -s /bin/cp /usr/bin/cp -- ln -s /bin/systemctl /usr/bin/systemctl -- ln -s /bin/mount /usr/bin/mount -- ln -s /bin/bash /usr/bin/bash -- ln -s /usr/sbin/useradd /usr/bin/useradd -- systemctl disable --now resolvconf.service -- systemctl mask --now lxc-net.service -- systemctl disable --now unscd.service -- systemctl stop --now unscd.service -- /opt/azure/containers/provision.sh -- bash /tmp/dcos/dcos_install.sh ROLENAME -- /opt/azure/dcos/postinstall-cond.sh -write_files: -- content: | - [Service] - Restart=always - StartLimitInterval=0 - RestartSec=15 - ExecStartPre=-/sbin/ip link del docker0 - ExecStart= - ExecStart=/usr/bin/dockerd --storage-driver=overlay - path: /etc/systemd/system/docker.service.d/execstart.conf - permissions: '0644' -- content: | - [Unit] - PartOf=docker.service - [Socket] - ListenStream=/var/run/docker.sock - SocketMode=0660 - SocketUser=root - SocketGroup=docker - ListenStream=2375 - BindIPv6Only=both - [Install] - WantedBy=sockets.target - path: /etc/systemd/system/docker.socket - permissions: '0644' -- content: | - DCOS_ENVIRONMENT={{{targetEnvironment}}} - owner: root - path: /opt/azure/dcos/environment - permissions: '0644' -- path: /var/lib/dcos/mesos-slave-common - content: 'ATTRIBUTES_STR' - permissions: "0644" - owner: "root" -- content: 'PROVISION_SOURCE_STR' - path: /opt/azure/containers/provision_source.sh - permissions: "0744" - owner: "root" -- content: 'PROVISION_STR' - path: /opt/azure/containers/provision.sh - permissions: "0744" - owner: "root" -- content: | - #!/bin/bash - if [ -f /opt/azure/dcos/postinstall.sh ]; then /opt/azure/dcos/postinstall.sh; fi - path: /opt/azure/dcos/postinstall-cond.sh - permissions: "0744" - owner: "root" diff --git a/parts/dcos/bstrap/dcosbase.t b/parts/dcos/bstrap/dcosbase.t deleted file mode 100644 index 58cc6a3de8..0000000000 --- a/parts/dcos/bstrap/dcosbase.t +++ /dev/null @@ -1,65 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { - {{range .AgentPoolProfiles}}{{template "agentparams.t" .}},{{end}} - {{if .HasWindows}} - "dcosBinariesURL": { - "metadata": { - "description": "The download url for dcos/mesos windows binaries." - }, - "type": "string" - }, - "dcosBinariesVersion": { - "metadata": { - "description": "DCOS windows binaries version" - }, - "type": "string" - }, - {{template "windowsparams.t"}}, - {{end}} - {{template "dcos/dcosparams.t" .}} - {{template "dcos/bstrap/bootstrapparams.t" .}}, - {{template "masterparams.t" .}} - }, - "variables": { - {{range $index, $agent := .AgentPoolProfiles}} - "{{.Name}}Index": {{$index}}, - {{template "dcos/dcosagentvars.t" .}} - {{if .IsStorageAccount}} - "{{.Name}}StorageAccountOffset": "[mul(variables('maxStorageAccountsPerAgent'),{{$index}})]", - "{{.Name}}AccountName": "[concat(variables('storageAccountBaseName'), 'agnt{{$index}}')]", - {{if .HasDisks}} - "{{.Name}}DataAccountName": "[concat(variables('storageAccountBaseName'), 'data{{$index}}')]", - {{end}} - {{end}} - {{end}} - - {{template "dcos/bstrap/dcosmastervars.t" .}} - {{template "dcos/bstrap/bootstrapvars.t" .}} - }, - "resources": [ - {{range .AgentPoolProfiles}} - {{if .IsWindows}} - {{if .IsAvailabilitySets}} - {{template "dcos/dcosWindowsAgentResourcesVmas.t" .}}, - {{else}} - {{template "dcos/dcosWindowsAgentResourcesVmss.t" .}}, - {{end}} - {{else}} - {{if .IsAvailabilitySets}} - {{template "dcos/dcosagentresourcesvmas.t" .}}, - {{else}} - {{template "dcos/dcosagentresourcesvmss.t" .}}, - {{end}} - {{end}} - {{end}} - {{template "dcos/bstrap/bootstrapresources.t" .}}, - {{template "dcos/bstrap/dcosmasterresources.t" .}} - ], - "outputs": { - {{range .AgentPoolProfiles}}{{template "agentoutputs.t" .}} - {{end}} - {{template "masteroutputs.t" .}} - } -} diff --git a/parts/dcos/bstrap/dcosmasterresources.t b/parts/dcos/bstrap/dcosmasterresources.t deleted file mode 100644 index 9ee279ecd0..0000000000 --- a/parts/dcos/bstrap/dcosmasterresources.t +++ /dev/null @@ -1,357 +0,0 @@ -{{if .MasterProfile.IsManagedDisks}} - { - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", - "location": "[variables('location')]", - "name": "[variables('masterAvailabilitySet')]", - "properties": { - "platformFaultDomainCount": 2, - "platformUpdateDomainCount": 3, - "managed": "true" - }, - "type": "Microsoft.Compute/availabilitySets" - }, -{{else if .MasterProfile.IsStorageAccount}} - { - "apiVersion": "[variables('apiVersionStorage')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('masterStorageAccountName')]", - "properties": { - "accountType": "[variables('vmSizesMap')[variables('masterVMSize')].storageAccountType]" - }, - "type": "Microsoft.Storage/storageAccounts" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('masterAvailabilitySet')]", - "properties": {}, - "type": "Microsoft.Compute/availabilitySets" - }, -{{end}} - { - "apiVersion": "[variables('apiVersionStorage')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('masterStorageAccountExhibitorName')]", - "properties": { - "accountType": "Standard_LRS" - }, - "type": "Microsoft.Storage/storageAccounts" - }, -{{if not .MasterProfile.IsCustomVNET}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - {{GetVNETSubnetDependencies}} - ], - "location": "[variables('location')]", - "name": "[variables('virtualNetworkName')]", - "properties": { - "addressSpace": { - "addressPrefixes": [ - {{GetVNETAddressPrefixes}} - ] - }, - "subnets": [ - {{GetVNETSubnets true}} - ] - }, - "type": "Microsoft.Network/virtualNetworks" - }, -{{end}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('masterPublicIPAddressName')]", - "properties": { - "dnsSettings": { - "domainNameLabel": "[variables('masterEndpointDNSNamePrefix')]" - }, - "publicIPAllocationMethod": "Dynamic" - }, - "type": "Microsoft.Network/publicIPAddresses" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('masterLbName')]", - "properties": { - "backendAddressPools": [ - { - "name": "[variables('masterLbBackendPoolName')]" - } - ], - "frontendIPConfigurations": [ - { - "name": "[variables('masterLbIPConfigName')]", - "properties": { - "publicIPAddress": { - "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('masterPublicIPAddressName'))]" - } - } - } - ] -{{if .MasterProfile.OAuthEnabled}} - ,"loadBalancingRules": [ - { - "name": "LBRule443", - "properties": { - "frontendIPConfiguration": { - "id": "[variables('masterLbIPConfigID')]" - }, - "frontendPort": 443, - "backendPort": 443, - "enableFloatingIP": false, - "idleTimeoutInMinutes": 4, - "protocol": "Tcp", - "loadDistribution": "Default", - "backendAddressPool": { - "id": "[concat(variables('masterLbID'), '/backendAddressPools/', variables('masterLbBackendPoolName'))]" - }, - "probe": { - "id": "[concat(variables('masterLbID'),'/probes/dcosMasterProbe')]" - } - } - }, - { - "name": "LBRule80", - "properties": { - "frontendIPConfiguration": { - "id": "[variables('masterLbIPConfigID')]" - }, - "frontendPort": 80, - "backendPort": 80, - "enableFloatingIP": false, - "idleTimeoutInMinutes": 4, - "protocol": "Tcp", - "loadDistribution": "Default", - "backendAddressPool": { - "id": "[concat(variables('masterLbID'), '/backendAddressPools/', variables('masterLbBackendPoolName'))]" - }, - "probe": { - "id": "[concat(variables('masterLbID'),'/probes/dcosMasterProbe')]" - } - } - } - ], - "probes": [ - { - "name": "dcosMasterProbe", - "properties": { - "protocol": "Http", - "port": 5050, - "requestPath": "/health", - "intervalInSeconds": 5, - "numberOfProbes": 2 - } - } - ] -{{end}} - }, - "type": "Microsoft.Network/loadBalancers" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "copy": { - "count": "[variables('masterCount')]", - "name": "masterLbLoopNode" - }, - "dependsOn": [ - "[variables('masterLbID')]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('masterLbName'), '/', 'SSH-', variables('masterVMNamePrefix'), copyIndex())]", - "properties": { - "backendPort": 22, - "enableFloatingIP": false, - "frontendIPConfiguration": { - "id": "[variables('masterLbIPConfigID')]" - }, - "frontendPort": "[copyIndex(2200)]", - "protocol": "tcp" - }, - "type": "Microsoft.Network/loadBalancers/inboundNatRules" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('masterNSGName')]", - "properties": { - "securityRules": [ - { - "properties": { - "priority": 200, - "access": "Allow", - "direction": "Inbound", - "destinationPortRange": "22", - "sourcePortRange": "*", - "destinationAddressPrefix": "*", - "protocol": "Tcp", - "description": "Allow SSH", - "sourceAddressPrefix": "*" - }, - "name": "ssh" - } - ] - }, - "type": "Microsoft.Network/networkSecurityGroups" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "copy": { - "count": "[variables('masterCount')]", - "name": "nicLoopNode" - }, - "dependsOn": [ - "[variables('masterNSGID')]", -{{if not .MasterProfile.IsCustomVNET}} - "[variables('vnetID')]", -{{end}} - "[variables('masterLbID')]", - "[concat(variables('masterLbID'),'/inboundNatRules/SSH-',variables('masterVMNamePrefix'),copyIndex())]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('masterVMNamePrefix'), 'nic-', copyIndex())]", - "properties": { - "ipConfigurations": [ - { - "name": "ipConfigNode", - "properties": { - "loadBalancerBackendAddressPools": [ - { - "id": "[concat(variables('masterLbID'), '/backendAddressPools/', variables('masterLbBackendPoolName'))]" - } - ], - "loadBalancerInboundNatRules": [ - { - "id": "[concat(variables('masterLbID'),'/inboundNatRules/SSH-',variables('masterVMNamePrefix'),copyIndex())]" - } - ], - "privateIPAddress": "[concat(variables('masterFirstAddrPrefix'), copyIndex(int(variables('masterFirstAddrOctet4'))))]", - "privateIPAllocationMethod": "Static", - "subnet": { - "id": "[variables('masterVnetSubnetID')]" - } - } - } - ] - ,"networkSecurityGroup": { - "id": "[variables('masterNSGID')]" - } - }, - "type": "Microsoft.Network/networkInterfaces" - }, - { -{{if .MasterProfile.IsManagedDisks}} - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", -{{else}} - "apiVersion": "[variables('apiVersionDefault')]", -{{end}} - "copy": { - "count": "[variables('masterCount')]", - "name": "vmLoopNode" - }, - "dependsOn": [ - "[concat('Microsoft.Network/networkInterfaces/', variables('masterVMNamePrefix'), 'nic-', copyIndex())]", - "[concat('Microsoft.Compute/availabilitySets/',variables('masterAvailabilitySet'))]", -{{if .MasterProfile.IsStorageAccount}} - "[variables('masterStorageAccountName')]", -{{end}} - "[variables('masterStorageAccountExhibitorName')]" -{{if not IsHostedBootstrap}} - ,"[concat('Microsoft.Compute/virtualMachines/', variables('bootstrapVMName'), '/extensions/bootstrapready')]" -{{end}} - ], - "tags": - { - "creationSource" : "[concat('acsengine-', variables('masterVMNamePrefix'), copyIndex())]", - "orchestratorName": "dcos", - "orchestratorVersion": "[variables('orchestratorVersion')]", - "orchestratorNode": "master" - }, - "location": "[variables('location')]", - "name": "[concat(variables('masterVMNamePrefix'), copyIndex())]", - "properties": { - "availabilitySet": { - "id": "[resourceId('Microsoft.Compute/availabilitySets',variables('masterAvailabilitySet'))]" - }, - "hardwareProfile": { - "vmSize": "[variables('masterVMSize')]" - }, - "networkProfile": { - "networkInterfaces": [ - { - "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(variables('masterVMNamePrefix'), 'nic-', copyIndex()))]" - } - ] - }, - "osProfile": { - "adminUsername": "[variables('adminUsername')]", - "computername": "[concat(variables('masterVMNamePrefix'), copyIndex())]", - {{GetDCOSMasterCustomData}} - "linuxConfiguration": { - "disablePasswordAuthentication": "true", - "ssh": { - "publicKeys": [ - { - "keyData": "[variables('sshRSAPublicKey')]", - "path": "[variables('sshKeyPath')]" - } - ] - } - } - {{if .LinuxProfile.HasSecrets}} - , - "secrets": "[variables('linuxProfileSecrets')]" - {{end}} - }, - "storageProfile": { - "imageReference": { - "offer": "[variables('osImageOffer')]", - "publisher": "[variables('osImagePublisher')]", - "sku": "[variables('osImageSKU')]", - "version": "[variables('osImageVersion')]" - }, - "osDisk": { - "caching": "ReadWrite" - ,"createOption": "FromImage" -{{if .MasterProfile.IsStorageAccount}} - ,"name": "[concat(variables('masterVMNamePrefix'), copyIndex(),'-osdisk')]" - ,"vhd": { - "uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('masterStorageAccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'vhds/',variables('masterVMNamePrefix'),copyIndex(),'-osdisk.vhd')]" - } -{{end}} -{{if ne .MasterProfile.OSDiskSizeGB 0}} - ,"diskSizeGB": {{.MasterProfile.OSDiskSizeGB}} -{{end}} - } - } - }, - "type": "Microsoft.Compute/virtualMachines" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[concat('Microsoft.Compute/virtualMachines/', variables('masterVMNamePrefix'), sub(variables('masterCount'), 1))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('masterVMNamePrefix'), sub(variables('masterCount'), 1), '/waitforleader')]", - "properties": { - "autoUpgradeMinorVersion": true, - "publisher": "Microsoft.OSTCExtensions", - "settings": { - "commandToExecute": "sh -c 'until ping -c1 leader.mesos;do echo waiting for leader.mesos;sleep 15;done;echo leader.mesos up'" - }, - "type": "CustomScriptForLinux", - "typeHandlerVersion": "1.4" - }, - "type": "Microsoft.Compute/virtualMachines/extensions" - }{{WriteLinkedTemplatesForExtensions}} diff --git a/parts/dcos/bstrap/dcosmastervars.t b/parts/dcos/bstrap/dcosmastervars.t deleted file mode 100644 index e95d89e0bc..0000000000 --- a/parts/dcos/bstrap/dcosmastervars.t +++ /dev/null @@ -1,141 +0,0 @@ - "adminUsername": "[parameters('linuxAdminUsername')]", - "targetEnvironment": "[parameters('targetEnvironment')]", - "maxVMsPerPool": 100, - "apiVersionDefault": "2016-03-30", - "apiVersionLinkDefault": "2015-01-01", - "singleQuote": "'", - "doubleSingleQuote": "''", -{{if .LinuxProfile.HasSecrets}} - "linuxProfileSecrets" : - [ - {{range $vIndex, $vault := .LinuxProfile.Secrets}} - {{if $vIndex}} , {{end}} - { - "sourceVault":{ - "id":"[parameters('linuxKeyVaultID{{$vIndex}}')]" - }, - "vaultCertificates":[ - {{range $cIndex, $cert := $vault.VaultCertificates}} - {{if $cIndex}} , {{end}} - { - "certificateUrl" :"[parameters('linuxKeyVaultID{{$vIndex}}CertificateURL{{$cIndex}}')]" - } - {{end}} - ] - } - {{end}} - ], -{{end}} - "orchestratorVersion": "{{.OrchestratorProfile.OrchestratorVersion}}", -{{if .HasWindows}} - "windowsAdminUsername": "[parameters('windowsAdminUsername')]", - "windowsAdminPassword": "[parameters('windowsAdminPassword')]", - "agentWindowsBackendPort": 3389, - "agentWindowsPublisher": "[parameters('agentWindowsPublisher')]", - "agentWindowsOffer": "[parameters('agentWindowsOffer')]", - "agentWindowsSku": "[parameters('agentWindowsSku')]", - "agentWindowsVersion": "[parameters('agentWindowsVersion')]", - "dcosWindowsBootstrapURL" : "[parameters('dcosWindowsBootstrapURL')]", - "windowsCustomScriptSuffix": " $inputFile = '%SYSTEMDRIVE%\\AzureData\\CustomData.bin' ; $outputFile = '%SYSTEMDRIVE%\\AzureData\\dcosWindowsProvision.ps1' ; $inputStream = New-Object System.IO.FileStream $inputFile, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read) ; $sr = New-Object System.IO.StreamReader(New-Object System.IO.Compression.GZipStream($inputStream, [System.IO.Compression.CompressionMode]::Decompress)) ; $sr.ReadToEnd() | Out-File($outputFile) ; Invoke-Expression('{0} {1}' -f $outputFile, $arguments) ; ", - "windowsMasterCustomScriptArguments": "[concat('$arguments = ', variables('singleQuote'),'-MasterCount ', variables('masterCount'), ' -firstMasterIP ', parameters('firstConsecutiveStaticIP'), variables('singleQuote'), ' ; ')]", - - "windowsMasterCustomScript": "[concat('powershell.exe -ExecutionPolicy Unrestricted -command \"', variables('windowsMasterCustomScriptArguments'), variables('windowsCustomScriptSuffix'), '\" > %SYSTEMDRIVE%\\AzureData\\dcosWindowsProvision.log 2>&1')]", -{{end}} - "masterAvailabilitySet": "[concat(variables('orchestratorName'), '-master-availabilitySet-', variables('nameSuffix'))]", - "masterCount": {{.MasterProfile.Count}}, - "masterEndpointDNSNamePrefix": "[tolower(parameters('masterEndpointDNSNamePrefix'))]", - "masterHttpSourceAddressPrefix": "{{.MasterProfile.HTTPSourceAddressPrefix}}", - "masterLbBackendPoolName": "[concat(variables('orchestratorName'), '-master-pool-', variables('nameSuffix'))]", - "masterLbID": "[resourceId('Microsoft.Network/loadBalancers',variables('masterLbName'))]", - "masterLbIPConfigID": "[concat(variables('masterLbID'),'/frontendIPConfigurations/', variables('masterLbIPConfigName'))]", - "masterLbIPConfigName": "[concat(variables('orchestratorName'), '-master-lbFrontEnd-', variables('nameSuffix'))]", - "masterLbName": "[concat(variables('orchestratorName'), '-master-lb-', variables('nameSuffix'))]", - "masterNSGID": "[resourceId('Microsoft.Network/networkSecurityGroups',variables('masterNSGName'))]", - "masterNSGName": "[concat(variables('orchestratorName'), '-master-nsg-', variables('nameSuffix'))]", - "masterPublicIPAddressName": "[concat(variables('orchestratorName'), '-master-ip-', variables('masterEndpointDNSNamePrefix'), '-', variables('nameSuffix'))]", - "apiVersionStorage": "2015-06-15", - - "storageAccountBaseName": "[uniqueString(concat(variables('masterEndpointDNSNamePrefix'),variables('location'),variables('orchestratorName')))]", - "masterStorageAccountExhibitorName": "[concat(variables('storageAccountBaseName'), 'exhb0')]", - "storageAccountType": "Standard_LRS", -{{if .HasStorageAccountDisks}} - "maxVMsPerStorageAccount": 20, - "maxStorageAccountsPerAgent": "[div(variables('maxVMsPerPool'),variables('maxVMsPerStorageAccount'))]", - "dataStorageAccountPrefixSeed": 97, - "storageAccountPrefixes": [ "0", "6", "c", "i", "o", "u", "1", "7", "d", "j", "p", "v", "2", "8", "e", "k", "q", "w", "3", "9", "f", "l", "r", "x", "4", "a", "g", "m", "s", "y", "5", "b", "h", "n", "t", "z" ], - "storageAccountPrefixesCount": "[length(variables('storageAccountPrefixes'))]", - {{GetSizeMap}}, -{{else}} - "storageAccountPrefixes": [], -{{end}} -{{if .HasManagedDisks}} - "apiVersionStorageManagedDisks": "2016-04-30-preview", -{{end}} -{{if .MasterProfile.IsStorageAccount}} - "masterStorageAccountName": "[concat(variables('storageAccountBaseName'), 'mstr0')]", -{{end}} -{{if .MasterProfile.IsCustomVNET}} - "masterVnetSubnetID": "[parameters('masterVnetSubnetID')]", -{{else}} - "masterSubnet": "[parameters('masterSubnet')]", - "masterSubnetName": "[concat(variables('orchestratorName'), '-masterSubnet')]", - "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]", - "masterVnetSubnetID": "[concat(variables('vnetID'),'/subnets/',variables('masterSubnetName'))]", - "virtualNetworkName": "[concat(variables('orchestratorName'), '-vnet-', variables('nameSuffix'))]", -{{end}} - "masterFirstAddrOctets": "[split(parameters('firstConsecutiveStaticIP'),'.')]", - "masterFirstAddrOctet4": "[variables('masterFirstAddrOctets')[3]]", - "masterFirstAddrPrefix": "[concat(variables('masterFirstAddrOctets')[0],'.',variables('masterFirstAddrOctets')[1],'.',variables('masterFirstAddrOctets')[2],'.')]", - "masterVMNamePrefix": "[concat(variables('orchestratorName'), '-master-', variables('nameSuffix'), '-')]", - "masterVMNic": [ - "[concat(variables('masterVMNamePrefix'), 'nic-0')]", - "[concat(variables('masterVMNamePrefix'), 'nic-1')]", - "[concat(variables('masterVMNamePrefix'), 'nic-2')]", - "[concat(variables('masterVMNamePrefix'), 'nic-3')]", - "[concat(variables('masterVMNamePrefix'), 'nic-4')]", - "[concat(variables('masterVMNamePrefix'), 'nic-5')]", - "[concat(variables('masterVMNamePrefix'), 'nic-6')]" - ], - "masterVMSize": "[parameters('masterVMSize')]", - "nameSuffix": "[parameters('nameSuffix')]", - "oauthEnabled": "{{.MasterProfile.OAuthEnabled}}", - "orchestratorName": "dcos", - "osImageOffer": "[parameters('osImageOffer')]", - "osImagePublisher": "[parameters('osImagePublisher')]", - "osImageSKU": "[parameters('osImageSKU')]", - "osImageVersion": "[parameters('osImageVersion')]", - "sshKeyPath": "[concat('/home/', variables('adminUsername'), '/.ssh/authorized_keys')]", - "sshRSAPublicKey": "[parameters('sshRSAPublicKey')]", - "locations": [ - "[resourceGroup().location]", - "[parameters('location')]" - ], - "location": "[variables('locations')[mod(add(2,length(parameters('location'))),add(1,length(parameters('location'))))]]", - "masterSshInboundNatRuleIdPrefix": "[concat(variables('masterLbID'),'/inboundNatRules/SSH-',variables('masterVMNamePrefix'))]", - "masterLbInboundNatRules": [ - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'0')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'1')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'2')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'3')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'4')]" - } - ] - ] diff --git a/parts/dcos/bstrap/dcosprovision.sh b/parts/dcos/bstrap/dcosprovision.sh deleted file mode 100644 index 8ff378efb0..0000000000 --- a/parts/dcos/bstrap/dcosprovision.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash - -source /opt/azure/containers/provision_source.sh -source /opt/azure/dcos/environment - -TMPDIR="/tmp/dcos" -mkdir -p $TMPDIR - -# default dc/os component download address (Azure CDN) -packages=( - https://dcos-mirror.azureedge.net/pkg/libipset3_6.29-1_amd64.deb - https://dcos-mirror.azureedge.net/pkg/ipset_6.29-1_amd64.deb - https://dcos-mirror.azureedge.net/pkg/unzip_6.0-20ubuntu1_amd64.deb - https://dcos-mirror.azureedge.net/pkg/libltdl7_2.4.6-0.1_amd64.deb - https://dcos-mirror.azureedge.net/pkg/docker-ce_17.09.0~ce-0~ubuntu_amd64.deb - https://dcos-mirror.azureedge.net/pkg/selinux-utils_2.4-3build2_amd64.deb -) - -# sha1sum checksums for @packages -sha1sums=( - f88d09688291917c8bb65682fea9f5d571ec8d6a - 807dc11f5bfa39bb4b0dc9024fc51bb309905a21 - 57ae2bb6ded1fdf91b6d518294134df1ff13fcca - 9a0f9f2769d3dc834737aa7df50aaaea369af98d - 94f6e89be6d45d9988269a237eb27c7d6a844d7f - 77bdb5847060845c0a158f567b1ddd7fa34b7236 -) - -case $DCOS_ENVIRONMENT in - # because of Chinese GreatWall Firewall, the default packages on Azure CDN is blocked. So the following Chinese local mirror url should be used instead. - AzureChinaCloud) - packages=( - http://acsengine.blob.core.chinacloudapi.cn/dcos/libipset3_6.29-1_amd64.deb - http://acsengine.blob.core.chinacloudapi.cn/dcos/ipset_6.29-1_amd64.deb - http://acsengine.blob.core.chinacloudapi.cn/dcos/unzip_6.0-20ubuntu1_amd64.deb - http://acsengine.blob.core.chinacloudapi.cn/dcos/libltdl7_2.4.6-0.1_amd64.deb - http://mirror.kaiyuanshe.cn/docker-ce/linux/ubuntu/dists/xenial/pool/stable/amd64/docker-ce_17.09.0~ce-0~ubuntu_amd64.deb - http://acsengine.blob.core.chinacloudapi.cn/dcos/selinux-utils_2.4-3build2_amd64.deb - ) - ;; -esac - -len=$((${#packages[@]}-1)) -for i in $(seq 0 $len); do - retry_get_install_deb 10 10 120 ${packages[$i]} ${sha1sums[$i]} - if [ $? -ne 0 ]; then - exit 1 - fi -done - -retrycmd_if_failure 10 10 120 curl -fsSL -o $TMPDIR/dcos_install.sh http://BOOTSTRAP_IP:8086/dcos_install.sh -if [ $? -ne 0 ]; then - exit 1 -fi diff --git a/parts/dcos/dcosWindowsAgentResourcesVmas.t b/parts/dcos/dcosWindowsAgentResourcesVmas.t deleted file mode 100644 index 77f1a9e973..0000000000 --- a/parts/dcos/dcosWindowsAgentResourcesVmas.t +++ /dev/null @@ -1,294 +0,0 @@ - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}NSGName')]", - "properties": { - "securityRules": [ - {{GetSecurityRules .Ports}} - ] - }, - "type": "Microsoft.Network/networkSecurityGroups" - }, -{{if HasWindowsCustomImage}} - {"type": "Microsoft.Compute/images", - "apiVersion": "2017-12-01", - "name": "{{.Name}}CustomWindowsImage", - "location": "[variables('location')]", - "properties": { - "storageProfile": { - "osDisk": { - "osType": "Windows", - "osState": "Generalized", - "blobUri": "[parameters('agentWindowsSourceUrl')]", - "storageAccountType": "Standard_LRS" - } - } - } - }, -{{end}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "copy": { - "count": "[sub(variables('{{.Name}}Count'), variables('{{.Name}}Offset'))]", - "name": "loop" - }, - "dependsOn": [ -{{if .IsCustomVNET}} - "[concat('Microsoft.Network/networkSecurityGroups/', variables('{{.Name}}NSGName'))]" -{{else}} - "[variables('vnetID')]" -{{end}} -{{if IsPublic .Ports}} - ,"[variables('{{.Name}}LbID')]" -{{end}} - ], - "location": "[variables('location')]", - "name": "[concat(variables('{{.Name}}VMNamePrefix'), 'nic-', copyIndex(variables('{{.Name}}Offset')))]", - "properties": { -{{if .IsCustomVNET}} - "networkSecurityGroup": { - "id": "[resourceId('Microsoft.Network/networkSecurityGroups/', variables('{{.Name}}NSGName'))]" - }, -{{end}} - "ipConfigurations": [ - { - "name": "ipConfigNode", - "properties": { -{{if IsPublic .Ports}} - "loadBalancerBackendAddressPools": [ - { - "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/loadBalancers/', variables('{{.Name}}LbName'), '/backendAddressPools/',variables('{{.Name}}LbBackendPoolName'))]" - } - ], - "loadBalancerInboundNatPools": [ - { - "id": "[concat(variables('{{.Name}}LbID'), '/inboundNatPools/', 'RDP-', variables('{{.Name}}VMNamePrefix'))]" - } - ], -{{end}} - "privateIPAllocationMethod": "Dynamic", - "subnet": { - "id": "[variables('{{.Name}}VnetSubnetID')]" - } - } - } - ] - }, - "type": "Microsoft.Network/networkInterfaces" - }, -{{if .IsManagedDisks}} - { - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}AvailabilitySet')]", - "properties": { - "platformFaultDomainCount": 2, - "platformUpdateDomainCount": 3, - "managed": "true" - }, - "type": "Microsoft.Compute/availabilitySets" - }, -{{else if .IsStorageAccount}} - { - "apiVersion": "[variables('apiVersionStorage')]", - "copy": { - "count": "[variables('{{.Name}}StorageAccountsCount')]", - "name": "loop" - }, - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('storageAccountPrefixes')[mod(add(copyIndex(),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(copyIndex(),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "properties": { - "accountType": "[variables('vmSizesMap')[variables('{{.Name}}VMSize')].storageAccountType]" - }, - "type": "Microsoft.Storage/storageAccounts" - }, - {{if .HasDisks}} - { - "apiVersion": "[variables('apiVersionStorage')]", - "copy": { - "count": "[variables('{{.Name}}StorageAccountsCount')]", - "name": "datadiskLoop" - }, - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('storageAccountPrefixes')[mod(add(copyIndex(variables('dataStorageAccountPrefixSeed')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(copyIndex(variables('dataStorageAccountPrefixSeed')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}DataAccountName'))]", - "properties": { - "accountType": "[variables('vmSizesMap')[variables('{{.Name}}VMSize')].storageAccountType]" - }, - "type": "Microsoft.Storage/storageAccounts" - }, - {{end}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}AvailabilitySet')]", - "properties": {}, - "type": "Microsoft.Compute/availabilitySets" - }, -{{end}} -{{if IsPublic .Ports}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}IPAddressName')]", - "properties": { - "dnsSettings": { - "domainNameLabel": "[variables('{{.Name}}EndpointDNSNamePrefix')]" - }, - "publicIPAllocationMethod": "Dynamic" - }, - "type": "Microsoft.Network/publicIPAddresses" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('{{.Name}}IPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('{{.Name}}LbName')]", - "properties": { - "backendAddressPools": [ - { - "name": "[variables('{{.Name}}LbBackendPoolName')]" - } - ], - "frontendIPConfigurations": [ - { - "name": "[variables('{{.Name}}LbIPConfigName')]", - "properties": { - "publicIPAddress": { - "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('{{.Name}}IPAddressName'))]" - } - } - } - ], - "inboundNatPools": [ - { - "name": "[concat('RDP-', variables('{{.Name}}VMNamePrefix'))]", - "properties": { - "frontendIPConfiguration": { - "id": "[variables('{{.Name}}LbIPConfigID')]" - }, - "protocol": "tcp", - "frontendPortRangeStart": "[variables('{{.Name}}WindowsRDPNatRangeStart')]", - "frontendPortRangeEnd": "[variables('{{.Name}}WindowsRDPEndRangeStop')]", - "backendPort": "[variables('agentWindowsBackendPort')]" - } - } - ], - "loadBalancingRules": [ - {{(GetLBRules .Name .Ports)}} - ], - "probes": [ - {{(GetProbes .Ports)}} - ] - }, - "type": "Microsoft.Network/loadBalancers" - }, -{{end}} - { -{{if .IsManagedDisks}} - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", -{{else}} - "apiVersion": "[variables('apiVersionDefault')]", -{{end}} - "copy": { - "count": "[sub(variables('{{.Name}}Count'), variables('{{.Name}}Offset'))]", - "name": "vmLoopNode" - }, - "dependsOn": [ -{{if .IsStorageAccount}} - "[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - {{if .HasDisks}} - "[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('dataStorageAccountPrefixSeed')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('dataStorageAccountPrefixSeed')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}DataAccountName'))]", - {{end}} -{{end}} - "[concat('Microsoft.Network/networkInterfaces/', variables('{{.Name}}VMNamePrefix'), 'nic-', copyIndex(variables('{{.Name}}Offset')))]", - "[concat('Microsoft.Compute/availabilitySets/', variables('{{.Name}}AvailabilitySet'))]" - ], - "tags": - { - "creationSource" : "[concat('acsengine-', variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')))]", - "orchestratorName": "dcos", - "orchestratorVersion": "[variables('orchestratorVersion')]", - "orchestratorNode": "agent" - }, - "location": "[variables('location')]", - "name": "[concat(variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')))]", - "properties": { - "availabilitySet": { - "id": "[resourceId('Microsoft.Compute/availabilitySets',variables('{{.Name}}AvailabilitySet'))]" - }, - "hardwareProfile": { - "vmSize": "[variables('{{.Name}}VMSize')]" - }, - "networkProfile": { - "networkInterfaces": [ - { - "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(variables('{{.Name}}VMNamePrefix'), 'nic-', copyIndex(variables('{{.Name}}Offset'))))]" - } - ] - }, - "osProfile": { - "computername": "[concat(variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')))]", - "adminUsername": "[variables('windowsAdminUsername')]", - "adminPassword": "[variables('windowsAdminPassword')]", - {{GetDCOSWindowsAgentCustomData .}} - - }, - "storageProfile": { - {{GetDataDisks .}} - "imageReference": { -{{if HasWindowsCustomImage}} - "id": "[resourceId('Microsoft.Compute/images','{{.Name}}CustomWindowsImage')]" -{{else}} - "offer": "[variables('agentWindowsOffer')]", - "publisher": "[variables('agentWindowsPublisher')]", - "sku": "[variables('agentWindowsSKU')]", - "version": "[variables('agentWindowsVersion')]" -{{end}} - } - ,"osDisk": { - "caching": "ReadOnly" - ,"createOption": "FromImage" -{{if .IsStorageAccount}} - ,"name": "[concat(variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')),'-osdisk')]" - ,"vhd": { - "uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'osdisk/', variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')), '-osdisk.vhd')]" - } -{{end}} -{{if ne .OSDiskSizeGB 0}} - ,"diskSizeGB": {{.OSDiskSizeGB}} -{{end}} - } - } - }, - "type": "Microsoft.Compute/virtualMachines" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "copy": { - "count": "[sub(variables('{{.Name}}Count'), variables('{{.Name}}Offset'))]", - "name": "vmLoopNode" - }, - "dependsOn": [ - "[concat('Microsoft.Compute/virtualMachines/', variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')), '/cse')]", - "properties": { - "publisher": "Microsoft.Compute", - "type": "CustomScriptExtension", - "typeHandlerVersion": "1.8", - "autoUpgradeMinorVersion": true, - "settings": { - "commandToExecute": "[variables('{{.Name}}windowsAgentCustomScript')]" - } - }, - "type": "Microsoft.Compute/virtualMachines/extensions" - } diff --git a/parts/dcos/dcosWindowsAgentResourcesVmss.t b/parts/dcos/dcosWindowsAgentResourcesVmss.t deleted file mode 100644 index ef17f773c4..0000000000 --- a/parts/dcos/dcosWindowsAgentResourcesVmss.t +++ /dev/null @@ -1,229 +0,0 @@ - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}NSGName')]", - "properties": { - "securityRules": [ - {{GetSecurityRules .Ports}} - ] - }, - "type": "Microsoft.Network/networkSecurityGroups" - }, -{{if HasWindowsCustomImage}} - {"type": "Microsoft.Compute/images", - "apiVersion": "2017-12-01", - "name": "{{.Name}}CustomWindowsImage", - "location": "[variables('location')]", - "properties": { - "storageProfile": { - "osDisk": { - "osType": "Windows", - "osState": "Generalized", - "blobUri": "[parameters('agentWindowsSourceUrl')]", - "storageAccountType": "Standard_LRS" - } - } - } - }, -{{end}} -{{if .IsStorageAccount}} - { - "apiVersion": "[variables('apiVersionStorage')]", - "copy": { - "count": "[variables('{{.Name}}StorageAccountsCount')]", - "name": "loop" - }, - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('storageAccountPrefixes')[mod(add(copyIndex(),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(copyIndex(),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "properties": { - "accountType": "[variables('vmSizesMap')[variables('{{.Name}}VMSize')].storageAccountType]" - }, - "type": "Microsoft.Storage/storageAccounts" - }, -{{end}} -{{if IsPublic .Ports}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}IPAddressName')]", - "properties": { - "dnsSettings": { - "domainNameLabel": "[variables('{{.Name}}EndpointDNSNamePrefix')]" - }, - "publicIPAllocationMethod": "Dynamic" - }, - "type": "Microsoft.Network/publicIPAddresses" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('{{.Name}}IPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('{{.Name}}LbName')]", - "properties": { - "backendAddressPools": [ - { - "name": "[variables('{{.Name}}LbBackendPoolName')]" - } - ], - "frontendIPConfigurations": [ - { - "name": "[variables('{{.Name}}LbIPConfigName')]", - "properties": { - "publicIPAddress": { - "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('{{.Name}}IPAddressName'))]" - } - } - } - ], - "inboundNatRules": [], - "loadBalancingRules": [ - {{(GetLBRules .Name .Ports)}} - ], - "probes": [ - {{(GetProbes .Ports)}} - ] - }, - "type": "Microsoft.Network/loadBalancers" - }, -{{end}} - { -{{if .IsManagedDisks}} - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", -{{else}} - "apiVersion": "[variables('apiVersionDefault')]", -{{end}} - "dependsOn": [ -{{if .IsCustomVNET}} - "[concat('Microsoft.Network/networkSecurityGroups/', variables('{{.Name}}NSGName'))]" -{{else}} - "[variables('vnetID')]" -{{end}} -{{if .IsStorageAccount}} - ,"[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(0,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(0,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(1,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(1,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(2,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(2,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(3,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(3,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(4,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(4,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]" -{{end}} -{{if IsPublic .Ports}} - ,"[concat('Microsoft.Network/loadBalancers/', variables('{{.Name}}LbName'))]" -{{end}} - ], - "tags": - { - "creationSource" : "[concat('acsengine-', variables('{{.Name}}VMNamePrefix'), '-vmss')]", - "orchestratorName": "dcos", - "orchestratorVersion": "[variables('orchestratorVersion')]", - "orchestratorNode": "agent" - }, - "location": "[variables('location')]", - "name": "[concat(variables('{{.Name}}VMNamePrefix'), '-vmss')]", - "properties": { - "overprovision": false, - "upgradePolicy": { - "mode": "Manual" - }, - "virtualMachineProfile": { - "networkProfile": { - "networkInterfaceConfigurations": [ - { - "name": "nic", - "properties": { -{{if .IsCustomVNET}} - "networkSecurityGroup": { - "id": "[resourceId('Microsoft.Network/networkSecurityGroups/', variables('{{.Name}}NSGName'))]" - }, -{{end}} - "ipConfigurations": [ - { - "name": "nicipconfig", - "properties": { -{{if IsPublic .Ports}} - "loadBalancerBackendAddressPools": [ - { - "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/loadBalancers/', variables('{{.Name}}LbName'), '/backendAddressPools/',variables('{{.Name}}LbBackendPoolName'))]" - } - ], -{{end}} - "subnet": { - "id": "[variables('{{.Name}}VnetSubnetID')]" - } - } - } - ], - "primary": "true" - } - } - ] - }, - "osProfile": { - "computerNamePrefix": "[concat(substring(variables('nameSuffix'), 0, 5), 'acs')]", - "adminUsername": "[variables('windowsAdminUsername')]", - "adminPassword": "[variables('windowsAdminPassword')]", - {{GetDCOSWindowsAgentCustomData .}} - {{if HasWindowsSecrets}} - , - "secrets": "[variables('windowsProfileSecrets')]" - {{end}} - }, - "storageProfile": { - "imageReference": { -{{if HasWindowsCustomImage}} - "id": "[resourceId('Microsoft.Compute/images','{{.Name}}CustomWindowsImage')]" -{{else}} - "publisher": "[variables('agentWindowsPublisher')]", - "offer": "[variables('agentWindowsOffer')]", - "sku": "[variables('agentWindowsSku')]", - "version": "latest" -{{end}} - }, - {{GetDataDisks .}} - "osDisk": { - "caching": "ReadOnly", - "createOption": "FromImage" -{{if .IsStorageAccount}} - ,"name": "vmssosdisk" - ,"vhdContainers": [ - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(0,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(0,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'osdisk')]", - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(1,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(1,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'osdisk')]", - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(2,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(2,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'osdisk')]", - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(3,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(3,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'osdisk')]", - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(4,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(4,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'osdisk')]" - - ] -{{end}} -{{if ne .OSDiskSizeGB 0}} - ,"diskSizeGB": {{.OSDiskSizeGB}} -{{end}} - } - }, - "extensionProfile": { - "extensions": [ - { - "name": "vmssCustomScriptExtension", - "properties": { - "publisher": "Microsoft.Compute", - "type": "CustomScriptExtension", - "typeHandlerVersion": "1.8", - "autoUpgradeMinorVersion": true, - "settings": { - "commandToExecute": "[variables('{{.Name}}windowsAgentCustomScript')]" - } - } - } - ] - } - } - }, - "sku": { - "capacity": "[variables('{{.Name}}Count')]", - "name": "[variables('{{.Name}}VMSize')]", - "tier": "[variables('{{.Name}}VMSizeTier')]" - }, - "type": "Microsoft.Compute/virtualMachineScaleSets" - } diff --git a/parts/dcos/dcosWindowsProvision.ps1 b/parts/dcos/dcosWindowsProvision.ps1 deleted file mode 100644 index a2933b7eaa..0000000000 --- a/parts/dcos/dcosWindowsProvision.ps1 +++ /dev/null @@ -1,214 +0,0 @@ -<# - .SYNOPSIS - Provisions VM as a DCOS agent. - - .DESCRIPTION - Provisions VM as a DCOS agent. - - Invoke by: - -#> - -[CmdletBinding(DefaultParameterSetName="Standard")] -param( - [string] - [ValidateNotNullOrEmpty()] - $masterCount, - - [string] - [ValidateNotNullOrEmpty()] - $firstMasterIP, - - [string] - [ValidateNotNullOrEmpty()] - $bootstrapUri, - - [parameter()] - [ValidateNotNullOrEmpty()] - $isAgent, - - [parameter()] - [ValidateNotNullOrEmpty()] - $subnet, - - [parameter()] - [AllowNull()] - $isPublic = $false, - - [string] - [AllowNull()] - $customAttrs = "", - - [string] - [AllowNull()] - $preprovisionExtensionParams = "" -) - - - - -$global:BootstrapInstallDir = "C:\AzureData" - -filter Timestamp {"$(Get-Date -Format o): $_"} - - -function -Write-Log($message) -{ - $msg = $message | Timestamp - Write-Output $msg -} - - -function -Expand-ZIPFile($file, $destination) -{ - $shell = new-object -com shell.application - $zip = $shell.NameSpace($file) - foreach($item in $zip.items()) - { - $shell.Namespace($destination).copyhere($item, 0x14) - } -} - - -function -Remove-Directory($dirname) -{ - - try { - #Get-ChildItem $dirname -Recurse | Remove-Item -force -confirm:$false - # This doesn't work because of long file names - # But this does: - Invoke-Expression ("cmd /C rmdir /s /q "+$dirname) - } - catch { - # If this fails we don't want it to stop - - } -} - - -function -Check-Subnet ([string]$cidr, [string]$ip) -{ - try { - - $network, [int]$subnetlen = $cidr.Split('/') - - if ($subnetlen -eq 0) - { - $subnetlen = 8 # Default in case we get an IP addr, not CIDR - } - $a = ([IPAddress] $network) - [uint32] $unetwork = [uint32]$a.Address - - $mask = -bnot ((-bnot [uint32]0) -shl (32 - $subnetlen)) - - $a = [IPAddress]$ip - [uint32] $uip = [uint32]$a.Address - - return ($unetwork -eq ($mask -band $uip)) - } - catch { - return $false - } -} - -# -# Gets the bootstrap script from the blob store and places it in c:\AzureData - -function -Get-BootstrapScript($download_uri, $download_dir) -{ - # Get Mesos Binaries - $scriptfile = "DCOSWindowsAgentSetup.ps1" - - Write-Log "get script $download_uri/$scriptfile and put it $download_dir\$scriptfile" - - Invoke-WebRequest -Uri ($download_uri+"/"+$scriptfile) -OutFile ($download_dir+"\"+$scriptfile) -} - - -try -{ - # Set to false for debugging. This will output the start script to - # c:\AzureData\dcosProvisionScript.log, and then you can RDP - # to the windows machine, and run the script manually to watch - # the output. - Write-Log "Get the install script" - - Write-Log ("Parameters = isAgent = ["+ $isAgent + "] mastercount = ["+$MasterCount + "] First master ip= [" + $firstMasterIp+ "] boostrap URI = ["+ $bootstrapUri+"] Subnet = ["+ $subnet +"]" + " -customAttrs " + $customAttrs + " -preprovisionExtensionParms = "+ $preprovisionExtensionParams ) - - # Get the boostrap script - - Get-BootstrapScript $bootstrapUri $global:BootstrapInstallDir - - # Convert Master count and first IP to a JSON array of IPAddresses - $ip = ([IPAddress]$firstMasterIp).getAddressBytes() - [Array]::Reverse($ip) - $ip = ([IPAddress]($ip -join '.')).Address - - $MasterIP = @([IPAddress]$null) - - for ($i = 0; $i -lt $MasterCount; $i++ ) - { - $new_ip = ([IPAddress]$ip).getAddressBytes() - [Array]::Reverse($new_ip) - $new_ip = [IPAddress]($new_ip -join '.') - $MasterIP += $new_ip - - $ip++ - - } - $master_str = $MasterIP.IPAddressToString - - # Add the port numbers - if ($master_str.count -eq 1) { - $master_str += ":2181" - } - else { - for ($i = 0; $i -lt $master_str.count; $i++) - { - $master_str[$i] += ":2181" - } - } - $master_json = ConvertTo-Json $master_str - $master_json = $master_json -replace [Environment]::NewLine,"" - - $private_ip = ( Get-NetIPAddress | where { $_.AddressFamily -eq "IPv4" } | where { Check-Subnet $subnet $_.IPAddress } ) # We know the subnet we are on. Makes it easier and more robust - [Environment]::SetEnvironmentVariable("DCOS_AGENT_IP", $private_ip.IPAddress, "Machine") - - if ($isAgent) - { - $run_cmd = $global:BootstrapInstallDir+"\DCOSWindowsAgentSetup.ps1 -MasterIP '$master_json' -AgentPrivateIP "+($private_ip.IPAddress) +" -BootstrapUrl '$bootstrapUri' " - if ($isPublic) - { - $run_cmd += " -isPublic:`$true " - } - if ($customAttrs) - { - $run_cmd += " -customAttrs '$customAttrs'" - } - $run_cmd += ">"+$global:BootstrapInstallDir+"\DCOSWindowsAgentSetup.log 2>&1" - Write-Log "run setup script $run_cmd" - Invoke-Expression $run_cmd - Write-Log "setup script completed" - } - else # We must be deploying a master - { - $run_cmd = $global:BootstrapInstallDir+"\DCOSWindowsMasterSetup.ps1 -MasterIP '$master_json' -MasterPrivateIP $privateIP.IPAddress -BootstrapUrl '$bootstrapUri'" - Write-Log "run setup script $run_cmd" - Invoke-Expression $run_cmd - } - - PREPROVISION_EXTENSION - - Write-Log "Provisioning script succeeded" -} -catch -{ - Write-Log "Provisioning script failed" - Write-Error $_ - exit 1 -} diff --git a/parts/dcos/dcosagentresourcesvmas.t b/parts/dcos/dcosagentresourcesvmas.t deleted file mode 100644 index a4d8601161..0000000000 --- a/parts/dcos/dcosagentresourcesvmas.t +++ /dev/null @@ -1,250 +0,0 @@ - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}NSGName')]", - "properties": { - "securityRules": [ - {{GetSecurityRules .Ports}} - ] - }, - "type": "Microsoft.Network/networkSecurityGroups" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "copy": { - "count": "[sub(variables('{{.Name}}Count'), variables('{{.Name}}Offset'))]", - "name": "loop" - }, - "dependsOn": [ -{{if .IsCustomVNET}} - "[concat('Microsoft.Network/networkSecurityGroups/', variables('{{.Name}}NSGName'))]" -{{else}} - "[variables('vnetID')]" -{{end}} -{{if IsPublic .Ports}} - ,"[variables('{{.Name}}LbID')]" -{{end}} - ], - "location": "[variables('location')]", - "name": "[concat(variables('{{.Name}}VMNamePrefix'), 'nic-', copyIndex(variables('{{.Name}}Offset')))]", - "properties": { -{{if .IsCustomVNET}} - "networkSecurityGroup": { - "id": "[resourceId('Microsoft.Network/networkSecurityGroups/', variables('{{.Name}}NSGName'))]" - }, -{{end}} - "ipConfigurations": [ - { - "name": "ipConfigNode", - "properties": { -{{if IsPublic .Ports}} - "loadBalancerBackendAddressPools": [ - { - "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/loadBalancers/', variables('{{.Name}}LbName'), '/backendAddressPools/',variables('{{.Name}}LbBackendPoolName'))]" - } - ], -{{end}} - "privateIPAllocationMethod": "Dynamic", - "subnet": { - "id": "[variables('{{.Name}}VnetSubnetID')]" - } - } - } - ] - }, - "type": "Microsoft.Network/networkInterfaces" - }, -{{if .IsManagedDisks}} - { - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}AvailabilitySet')]", - "properties": { - "platformFaultDomainCount": 2, - "platformUpdateDomainCount": 3, - "managed": "true" - }, - "type": "Microsoft.Compute/availabilitySets" - }, -{{else if .IsStorageAccount}} - { - "apiVersion": "[variables('apiVersionStorage')]", - "copy": { - "count": "[variables('{{.Name}}StorageAccountsCount')]", - "name": "loop" - }, - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('storageAccountPrefixes')[mod(add(copyIndex(),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(copyIndex(),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "properties": { - "accountType": "[variables('vmSizesMap')[variables('{{.Name}}VMSize')].storageAccountType]" - }, - "type": "Microsoft.Storage/storageAccounts" - }, - {{if .HasDisks}} - { - "apiVersion": "[variables('apiVersionStorage')]", - "copy": { - "count": "[variables('{{.Name}}StorageAccountsCount')]", - "name": "datadiskLoop" - }, - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('storageAccountPrefixes')[mod(add(copyIndex(variables('dataStorageAccountPrefixSeed')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(copyIndex(variables('dataStorageAccountPrefixSeed')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}DataAccountName'))]", - "properties": { - "accountType": "[variables('vmSizesMap')[variables('{{.Name}}VMSize')].storageAccountType]" - }, - "type": "Microsoft.Storage/storageAccounts" - }, - {{end}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}AvailabilitySet')]", - "properties": {}, - "type": "Microsoft.Compute/availabilitySets" - }, -{{end}} -{{if IsPublic .Ports}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}IPAddressName')]", - "properties": { - "dnsSettings": { - "domainNameLabel": "[variables('{{.Name}}EndpointDNSNamePrefix')]" - }, - "publicIPAllocationMethod": "Dynamic" - }, - "type": "Microsoft.Network/publicIPAddresses" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('{{.Name}}IPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('{{.Name}}LbName')]", - "properties": { - "backendAddressPools": [ - { - "name": "[variables('{{.Name}}LbBackendPoolName')]" - } - ], - "frontendIPConfigurations": [ - { - "name": "[variables('{{.Name}}LbIPConfigName')]", - "properties": { - "publicIPAddress": { - "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('{{.Name}}IPAddressName'))]" - } - } - } - ], - "inboundNatRules": [], - "loadBalancingRules": [ - {{(GetLBRules .Name .Ports)}} - ], - "probes": [ - {{(GetProbes .Ports)}} - ] - }, - "type": "Microsoft.Network/loadBalancers" - }, -{{end}} - { -{{if .IsManagedDisks}} - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", -{{else}} - "apiVersion": "[variables('apiVersionDefault')]", -{{end}} - "copy": { - "count": "[sub(variables('{{.Name}}Count'), variables('{{.Name}}Offset'))]", - "name": "vmLoopNode" - }, - "dependsOn": [ -{{if .IsStorageAccount}} - "[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - {{if .HasDisks}} - "[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('dataStorageAccountPrefixSeed')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('dataStorageAccountPrefixSeed')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}DataAccountName'))]", - {{end}} -{{end}} - "[concat('Microsoft.Network/networkInterfaces/', variables('{{.Name}}VMNamePrefix'), 'nic-', copyIndex(variables('{{.Name}}Offset')))]", - "[concat('Microsoft.Compute/availabilitySets/', variables('{{.Name}}AvailabilitySet'))]" -{{if and HasBootstrap (not IsHostedBootstrap)}} - ,"[concat('Microsoft.Compute/virtualMachines/', variables('bootstrapVMName'), /extensions/bootstrapready')]" -{{end}} - ], - "tags": - { - "creationSource" : "[concat('acsengine-', variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')))]", - "orchestratorName": "dcos", - "orchestratorVersion": "[variables('orchestratorVersion')]", - "orchestratorNode": "agent" - }, - "location": "[variables('location')]", - "name": "[concat(variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')))]", - "properties": { - "availabilitySet": { - "id": "[resourceId('Microsoft.Compute/availabilitySets',variables('{{.Name}}AvailabilitySet'))]" - }, - "hardwareProfile": { - "vmSize": "[variables('{{.Name}}VMSize')]" - }, - "networkProfile": { - "networkInterfaces": [ - { - "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(variables('{{.Name}}VMNamePrefix'), 'nic-', copyIndex(variables('{{.Name}}Offset'))))]" - } - ] - }, - "osProfile": { - "adminUsername": "[variables('adminUsername')]", - "computername": "[concat(variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')))]", - {{GetDCOSAgentCustomData .}} - "linuxConfiguration": { - "disablePasswordAuthentication": "true", - "ssh": { - "publicKeys": [ - { - "keyData": "[parameters('sshRSAPublicKey')]", - "path": "[variables('sshKeyPath')]" - } - ] - } - } - {{if HasLinuxSecrets}} - , - "secrets": "[variables('linuxProfileSecrets')]" - {{end}} - }, - "storageProfile": { - {{GetDataDisks .}} - "imageReference": { - "offer": "[variables('osImageOffer')]", - "publisher": "[variables('osImagePublisher')]", - "sku": "[variables('osImageSKU')]", - "version": "[variables('osImageVersion')]" - } - ,"osDisk": { - "caching": "ReadOnly" - ,"createOption": "FromImage" -{{if .IsStorageAccount}} - ,"name": "[concat(variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')),'-osdisk')]" - ,"vhd": { - "uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'osdisk/', variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')), '-osdisk.vhd')]" - } -{{end}} -{{if ne .OSDiskSizeGB 0}} - ,"diskSizeGB": {{.OSDiskSizeGB}} -{{end}} - } - - } - }, - "type": "Microsoft.Compute/virtualMachines" - } diff --git a/parts/dcos/dcosagentresourcesvmss.t b/parts/dcos/dcosagentresourcesvmss.t deleted file mode 100644 index 10f798966a..0000000000 --- a/parts/dcos/dcosagentresourcesvmss.t +++ /dev/null @@ -1,205 +0,0 @@ - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}NSGName')]", - "properties": { - "securityRules": [ - {{GetSecurityRules .Ports}} - ] - }, - "type": "Microsoft.Network/networkSecurityGroups" - }, -{{if .IsStorageAccount}} - { - "apiVersion": "[variables('apiVersionStorage')]", - "copy": { - "count": "[variables('{{.Name}}StorageAccountsCount')]", - "name": "loop" - }, - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('storageAccountPrefixes')[mod(add(copyIndex(),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(copyIndex(),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "properties": { - "accountType": "[variables('vmSizesMap')[variables('{{.Name}}VMSize')].storageAccountType]" - }, - "type": "Microsoft.Storage/storageAccounts" - }, -{{end}} -{{if IsPublic .Ports}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}IPAddressName')]", - "properties": { - "dnsSettings": { - "domainNameLabel": "[variables('{{.Name}}EndpointDNSNamePrefix')]" - }, - "publicIPAllocationMethod": "Dynamic" - }, - "type": "Microsoft.Network/publicIPAddresses" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('{{.Name}}IPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('{{.Name}}LbName')]", - "properties": { - "backendAddressPools": [ - { - "name": "[variables('{{.Name}}LbBackendPoolName')]" - } - ], - "frontendIPConfigurations": [ - { - "name": "[variables('{{.Name}}LbIPConfigName')]", - "properties": { - "publicIPAddress": { - "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('{{.Name}}IPAddressName'))]" - } - } - } - ], - "inboundNatRules": [], - "loadBalancingRules": [ - {{(GetLBRules .Name .Ports)}} - ], - "probes": [ - {{(GetProbes .Ports)}} - ] - }, - "type": "Microsoft.Network/loadBalancers" - }, -{{end}} - { -{{if .IsManagedDisks}} - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", -{{else}} - "apiVersion": "[variables('apiVersionDefault')]", -{{end}} - "dependsOn": [ -{{if .IsCustomVNET}} - "[concat('Microsoft.Network/networkSecurityGroups/', variables('{{.Name}}NSGName'))]" -{{else}} - "[variables('vnetID')]" -{{end}} -{{if .IsStorageAccount}} - ,"[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(0,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(0,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(1,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(1,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(2,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(2,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(3,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(3,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(4,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(4,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]" -{{end}} -{{if IsPublic .Ports}} - ,"[concat('Microsoft.Network/loadBalancers/', variables('{{.Name}}LbName'))]" -{{end}} -{{if and HasBootstrap (not IsHostedBootstrap)}} - ,"[concat('Microsoft.Compute/virtualMachines/', variables('bootstrapVMName'), '/extensions/bootstrapready')]" -{{end}} - ], - "tags": - { - "creationSource" : "[concat('acsengine-', variables('{{.Name}}VMNamePrefix'), 'vmss')]", - "orchestratorName": "dcos", - "orchestratorVersion": "[variables('orchestratorVersion')]", - "orchestratorNode": "agent" - }, - "location": "[variables('location')]", - "name": "[concat(variables('{{.Name}}VMNamePrefix'), 'vmss')]", - "properties": { - "overprovision": false, - "upgradePolicy": { - "mode": "Manual" - }, - "virtualMachineProfile": { - "networkProfile": { - "networkInterfaceConfigurations": [ - { - "name": "nic", - "properties": { -{{if .IsCustomVNET}} - "networkSecurityGroup": { - "id": "[resourceId('Microsoft.Network/networkSecurityGroups/', variables('{{.Name}}NSGName'))]" - }, -{{end}} - "ipConfigurations": [ - { - "name": "nicipconfig", - "properties": { -{{if IsPublic .Ports}} - "loadBalancerBackendAddressPools": [ - { - "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/loadBalancers/', variables('{{.Name}}LbName'), '/backendAddressPools/',variables('{{.Name}}LbBackendPoolName'))]" - } - ], -{{end}} - "subnet": { - "id": "[variables('{{.Name}}VnetSubnetID')]" - } - } - } - ], - "primary": "true" - } - } - ] - }, - "osProfile": { - "adminUsername": "[variables('adminUsername')]", - "computerNamePrefix": "[variables('{{.Name}}VMNamePrefix')]", - {{GetDCOSAgentCustomData .}} - "linuxConfiguration": { - "disablePasswordAuthentication": "true", - "ssh": { - "publicKeys": [ - { - "keyData": "[parameters('sshRSAPublicKey')]", - "path": "[variables('sshKeyPath')]" - } - ] - } - } - {{if HasLinuxSecrets}} - , - "secrets": "[variables('linuxProfileSecrets')]" - {{end}} - }, - "storageProfile": { - "imageReference": { - "offer": "[variables('osImageOffer')]", - "publisher": "[variables('osImagePublisher')]", - "sku": "[variables('osImageSKU')]", - "version": "[variables('osImageVersion')]" - }, - {{GetDataDisks .}} - "osDisk": { - "caching": "ReadOnly", - "createOption": "FromImage" -{{if .IsStorageAccount}} - ,"name": "vmssosdisk" - ,"vhdContainers": [ - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(0,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(0,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'osdisk')]", - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(1,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(1,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'osdisk')]", - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(2,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(2,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'osdisk')]", - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(3,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(3,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'osdisk')]", - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(4,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(4,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'osdisk')]" - - ] -{{end}} -{{if ne .OSDiskSizeGB 0}} - ,"diskSizeGB": {{.OSDiskSizeGB}} -{{end}} - } - } - } - }, - "sku": { - "capacity": "[variables('{{.Name}}Count')]", - "name": "[variables('{{.Name}}VMSize')]", - "tier": "[variables('{{.Name}}VMSizeTier')]" - }, - "type": "Microsoft.Compute/virtualMachineScaleSets" - } diff --git a/parts/dcos/dcosagentvars.t b/parts/dcos/dcosagentvars.t deleted file mode 100644 index 859603b629..0000000000 --- a/parts/dcos/dcosagentvars.t +++ /dev/null @@ -1,64 +0,0 @@ - "{{.Name}}Count": "[parameters('{{.Name}}Count')]", - "{{.Name}}NSGID": "[resourceId('Microsoft.Network/networkSecurityGroups',variables('{{.Name}}NSGName'))]", - "{{.Name}}NSGName": "[concat(variables('orchestratorName'), '-{{.Name}}-nsg-', variables('nameSuffix'))]", -{{if .IsWindows}} - - "winResourceNamePrefix" : "[substring(variables('nameSuffix'), 0, 5)]", - {{if IsPublic .Ports}} - "{{.Name}}VMNamePrefix": "[concat('wp', variables('winResourceNamePrefix'), add(900,variables('{{.Name}}Index')))]", - "{{.Name}}windowsAgentCustomAttributes": "[concat(' -customAttrs ', variables('doubleSingleQuote'), '{{GetDCOSWindowsAgentCustomNodeAttributes . }}', variables('doubleSingleQuote') )]", - "{{.Name}}windowsAgentCustomScriptArguments": "[concat('$arguments = ', variables('singleQuote'), '-subnet ', variables('{{.Name}}Subnet'), ' -MasterCount ', variables('masterCount'), ' -firstMasterIP ', parameters('firstConsecutiveStaticIP'), ' -bootstrapUri ', '\"', variables('dcosWindowsBootstrapURL'), '\"', ' -isAgent $true -isPublic $true ', variables('{{.Name}}windowsAgentCustomAttributes'), ' -preprovisionExtensionParams ', variables('doubleSingleQuote'), '{{GetDCOSWindowsAgentPreprovisionParameters .}}', variables('doubleSingleQuote'), variables('singleQuote'), ' ; ')]", - {{else}} - "{{.Name}}VMNamePrefix": "[concat('w', variables('winResourceNamePrefix'), add(900,variables('{{.Name}}Index')))]", - "{{.Name}}windowsAgentCustomAttributes": "[concat(' -customAttrs ', variables('doubleSingleQuote'), '{{GetDCOSWindowsAgentCustomNodeAttributes . }}', variables('doubleSingleQuote') )]", - "{{.Name}}windowsAgentCustomScriptArguments": "[concat('$arguments = ', variables('singleQuote'), '-subnet ', variables('{{.Name}}Subnet'), ' -MasterCount ', variables('masterCount'), ' -firstMasterIP ', parameters('firstConsecutiveStaticIP'), ' -bootstrapUri ', '\"', variables('dcosWindowsBootstrapURL'), '\"', ' -isAgent $true -isPublic $false ', variables('{{.Name}}windowsAgentCustomAttributes'), ' -preprovisionExtensionParams ', variables('doubleSingleQuote'), '{{GetDCOSWindowsAgentPreprovisionParameters .}}', variables('doubleSingleQuote'), variables('singleQuote'), ' ; ')]", - {{end}} - - "{{.Name}}windowsAgentCustomScript": "[concat('powershell.exe -ExecutionPolicy Unrestricted -command \"', variables('{{.Name}}windowsAgentCustomScriptArguments'), variables('windowsCustomScriptSuffix'), '\" > %SYSTEMDRIVE%\\AzureData\\dcosWindowsProvision.log 2>&1; exit $LASTEXITCODE')]", - -{{else}} - "{{.Name}}VMNamePrefix": "[concat(variables('orchestratorName'), '-{{.Name}}-', variables('nameSuffix'), '-')]", -{{end}} - - "{{.Name}}VMSize": "[parameters('{{.Name}}VMSize')]", - "{{.Name}}VMSizeTier": "[split(parameters('{{.Name}}VMSize'),'_')[0]]", -{{if .IsAvailabilitySets}} - {{if .IsStorageAccount}} - "{{.Name}}StorageAccountsCount": "[add(div(variables('{{.Name}}Count'), variables('maxVMsPerStorageAccount')), mod(add(mod(variables('{{.Name}}Count'), variables('maxVMsPerStorageAccount')),2), add(mod(variables('{{.Name}}Count'), variables('maxVMsPerStorageAccount')),1)))]", - "{{.Name}}StorageAccountOffset": "[mul(variables('maxStorageAccountsPerAgent'),variables('{{.Name}}Index'))]", - {{end}} - "{{.Name}}AvailabilitySet": "[concat('{{.Name}}-availabilitySet-', variables('nameSuffix'))]", - "{{.Name}}Offset": "[parameters('{{.Name}}Offset')]", -{{else}} - {{if .IsStorageAccount}} - "{{.Name}}StorageAccountsCount": "[variables('maxStorageAccountsPerAgent')]", - {{end}} -{{end}} -{{if .IsCustomVNET}} - "{{.Name}}VnetSubnetID": "[parameters('{{.Name}}VnetSubnetID')]", -{{else}} - "{{.Name}}Subnet": "[parameters('{{.Name}}Subnet')]", - "{{.Name}}SubnetName": "[concat(variables('orchestratorName'), '-{{.Name}}Subnet')]", - "{{.Name}}VnetSubnetID": "[concat(variables('vnetID'),'/subnets/',variables('{{.Name}}SubnetName'))]", -{{end}} -{{if IsPublic .Ports}} - "{{.Name}}EndpointDNSNamePrefix": "[tolower(parameters('{{.Name}}EndpointDNSNamePrefix'))]", - "{{.Name}}IPAddressName": "[concat(variables('orchestratorName'), '-agent-ip-', variables('{{.Name}}EndpointDNSNamePrefix'), '-', variables('nameSuffix'))]", - "{{.Name}}LbBackendPoolName": "[concat(variables('orchestratorName'), '-{{.Name}}-', variables('nameSuffix'))]", - "{{.Name}}LbID": "[resourceId('Microsoft.Network/loadBalancers',variables('{{.Name}}LbName'))]", - "{{.Name}}LbIPConfigID": "[concat(variables('{{.Name}}LbID'),'/frontendIPConfigurations/', variables('{{.Name}}LbIPConfigName'))]", - "{{.Name}}LbIPConfigName": "[concat(variables('orchestratorName'), '-{{.Name}}-', variables('nameSuffix'))]", - "{{.Name}}LbName": "[concat(variables('orchestratorName'), '-{{.Name}}-', variables('nameSuffix'))]", - {{if .IsWindows}} - "{{.Name}}WindowsRDPNatRangeStart": 3389, - "{{.Name}}WindowsRDPEndRangeStop": "[add(variables('{{.Name}}WindowsRDPNatRangeStart'), add(variables('{{.Name}}Count'),variables('{{.Name}}Count')))]", - - {{end}} -{{end}} -{{if HasPrivateRegistry}} - "registry" : "[tolower(parameters('registry'))]", - "registryKey" : "[parameters('registryKey')]", -{{else}} - "registry" : "", - "registryKey" : "", -{{end}} diff --git a/parts/dcos/dcosbase.t b/parts/dcos/dcosbase.t deleted file mode 100644 index e2be64169b..0000000000 --- a/parts/dcos/dcosbase.t +++ /dev/null @@ -1,65 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { - {{range .AgentPoolProfiles}}{{template "agentparams.t" .}},{{end}} - {{if .HasWindows}} - "dcosBinariesURL": { - "metadata": { - "description": "The download url for dcos/mesos windows binaries." - }, - "type": "string" - }, - "dcosBinariesVersion": { - "metadata": { - "description": "DCOS windows binaries version" - }, - "type": "string" - }, - {{template "windowsparams.t"}}, - {{end}} - {{template "dcos/dcosparams.t" .}} - {{template "masterparams.t" .}} - }, - "variables": { - "dcosRepositoryURL": "[parameters('dcosRepositoryURL')]", - "dcosClusterPackageListID": "[parameters('dcosClusterPackageListID')]", - "dcosProviderPackageID": "[parameters('dcosProviderPackageID')]", - {{range $index, $agent := .AgentPoolProfiles}} - "{{.Name}}Index": {{$index}}, - {{template "dcos/dcosagentvars.t" .}} - {{if .IsStorageAccount}} - "{{.Name}}StorageAccountOffset": "[mul(variables('maxStorageAccountsPerAgent'),{{$index}})]", - "{{.Name}}AccountName": "[concat(variables('storageAccountBaseName'), 'agnt{{$index}}')]", - {{if .HasDisks}} - "{{.Name}}DataAccountName": "[concat(variables('storageAccountBaseName'), 'data{{$index}}')]", - {{end}} - {{end}} - {{end}} - - {{template "dcos/dcosmastervars.t" .}} - }, - "resources": [ - {{range .AgentPoolProfiles}} - {{if .IsWindows}} - {{if .IsAvailabilitySets}} - {{template "dcos/dcosWindowsAgentResourcesVmas.t" .}}, - {{else}} - {{template "dcos/dcosWindowsAgentResourcesVmss.t" .}}, - {{end}} - {{else}} - {{if .IsAvailabilitySets}} - {{template "dcos/dcosagentresourcesvmas.t" .}}, - {{else}} - {{template "dcos/dcosagentresourcesvmss.t" .}}, - {{end}} - {{end}} - {{end}} - {{template "dcos/dcosmasterresources.t" .}} - ], - "outputs": { - {{range .AgentPoolProfiles}}{{template "agentoutputs.t" .}} - {{end}} - {{template "masteroutputs.t" .}} - } -} diff --git a/parts/dcos/dcoscustomdata110.t b/parts/dcos/dcoscustomdata110.t deleted file mode 100644 index 86730c9900..0000000000 --- a/parts/dcos/dcoscustomdata110.t +++ /dev/null @@ -1,343 +0,0 @@ -bootcmd: -- bash -c "if [ ! -f /var/lib/sdb-gpt ];then echo DCOS-5890;parted -s /dev/sdb mklabel - gpt;touch /var/lib/sdb-gpt;fi" -- bash -c "if [ ! -f /var/lib/sdc-gpt ];then echo DCOS-5890;parted -s /dev/sdc mklabel - gpt&&touch /var/lib/sdc-gpt;fi" -- bash -c "if [ ! -f /var/lib/sdd-gpt ];then echo DCOS-5890;parted -s /dev/sdd mklabel - gpt&&touch /var/lib/sdd-gpt;fi" -- bash -c "if [ ! -f /var/lib/sde-gpt ];then echo DCOS-5890;parted -s /dev/sde mklabel - gpt&&touch /var/lib/sde-gpt;fi" -- bash -c "if [ ! -f /var/lib/sdf-gpt ];then echo DCOS-5890;parted -s /dev/sdf mklabel - gpt&&touch /var/lib/sdf-gpt;fi" -- bash -c "mkdir -p /dcos/volume{0,1,2,3}" -disk_setup: - ephemeral0: - layout: - - 45 - - 45 - - 10 - overwrite: true - table_type: gpt - /dev/sdc: - layout: true - overwrite: true - table_type: gpt - /dev/sdd: - layout: true - overwrite: true - table_type: gpt - /dev/sde: - layout: true - overwrite: true - table_type: gpt - /dev/sdf: - layout: true - overwrite: true - table_type: gpt -fs_setup: -- device: ephemeral0.1 - filesystem: ext4 - overwrite: true -- device: ephemeral0.2 - filesystem: ext4 - overwrite: true -- device: ephemeral0.3 - filesystem: ext4 - overwrite: true -- device: /dev/sdc1 - filesystem: ext4 - overwrite: true -- device: /dev/sdd1 - filesystem: ext4 - overwrite: true -- device: /dev/sde1 - filesystem: ext4 - overwrite: true -- device: /dev/sdf1 - filesystem: ext4 - overwrite: true -mounts: -- - ephemeral0.1 - - /var/lib/mesos -- - ephemeral0.2 - - /var/lib/docker -- - ephemeral0.3 - - /var/tmp -- - /dev/sdc1 - - /dcos/volume0 -- - /dev/sdd1 - - /dcos/volume1 -- - /dev/sde1 - - /dcos/volume2 -- - /dev/sdf1 - - /dcos/volume3 -runcmd: PREPROVISION_EXTENSION -- - ln - - -s - - /bin/rm - - /usr/bin/rm -- - ln - - -s - - /bin/mkdir - - /usr/bin/mkdir -- - ln - - -s - - /bin/tar - - /usr/bin/tar -- - ln - - -s - - /bin/ln - - /usr/bin/ln -- - ln - - -s - - /bin/cp - - /usr/bin/cp -- - ln - - -s - - /bin/systemctl - - /usr/bin/systemctl -- - ln - - -s - - /bin/mount - - /usr/bin/mount -- - ln - - -s - - /bin/bash - - /usr/bin/bash -- - ln - - -s - - /usr/sbin/useradd - - /usr/bin/useradd -- - systemctl - - disable - - --now - - resolvconf.service -- - systemctl - - mask - - --now - - lxc-net.service -- - systemctl - - disable - - --now - - unscd.service -- - systemctl - - stop - - --now - - unscd.service -- /opt/azure/containers/provision.sh -- - cp - - -p - - /etc/resolv.conf - - /tmp/resolv.conf -- - rm - - -f - - /etc/resolv.conf -- - cp - - -p - - /tmp/resolv.conf - - /etc/resolv.conf -- - systemctl - - start - - dcos-docker-install.service -- - systemctl - - start - - dcos-config-writer.service -- - systemctl - - restart - - systemd-journald.service -- - systemctl - - restart - - docker.service -- - systemctl - - start - - dcos-link-env.service -- - systemctl - - enable - - dcos-setup.service -- - systemctl - - --no-block - - start - - dcos-setup.service -write_files: -- content: '{{{dcosRepositoryURL}}} -' - owner: root - path: /etc/mesosphere/setup-flags/repository-url - permissions: '0644' -- content: '["adminrouter--1166a3736442e7963a68d1d644bf5f54ca3cb01d", "avro-cpp--9cb0ee14e3cd5bbdb171efcc72a84d16862ea02d", - "boost-libs--8d515c2f703c666ae1b6c5ccc35cc0f8fa36677f", "bootstrap--c1bc86593e212cf9fe83db2246bacd129a6b3adc", - "boto--3890cb2817c00b874ba033abe784b5b343caa3c7", "check-time--79e3f6ab99125471e1d94d5f6bc0fea88446831c", - "cni--7a8572e385c3f5262945c52c8003d1bbb22cf7aa", "cosmos--e84c5bf3259405df90d682536ba445cc4839a324", - "curl--17866a8ae9305826aa5f357a09db2c1f2b2c2ad0", "dcos-checks--8fd33919e6f163dba1bd13e4c7e4e0523919a719", - "dcos-cni--12a77c1e9bebd4cbd600524a864c2bd8483330d3", "dcos-config--setup_{{{dcosProviderPackageID}}}", - "dcos-diagnostics--e3b557b0ec8e98617d0cd0fdf136ef9dded96316", "dcos-history--23de88ddc1a5f9018dd11b279c5be6a768a18de4", - "dcos-image--df630d8e930d6650ce3d0ade519660142233d862", "dcos-image-deps--81d23d00b1acddb316c9b15fd8499c2b10f6b697", - "dcos-integration-test--9ec173650d4e73ba494603324e7583d23970e4b8", "dcos-log--d2af4b1a47d3755a51823e95fbc6c366cf0f9269", - "dcos-metadata--setup_{{{dcosProviderPackageID}}}", "dcos-metrics--2a26c0b50b0b6564f86c48d50aa86f681c9af93c", - "dcos-oauth--445bb1388670981c6acc667b2529fc32d4c1fbd4", "dcos-signal--4366023212ea49a64c5c9aef1965e5a3133c4b61", - "dcos-test-utils--1066d896d25f4c1e3f6d9a5e7f9c1c6e8c675bb7", "dcos-ui--cc2e3d26537ea190efacd6f899dd4cc2210d45b7", - "dnspython--0be432372a3820eafcfa66975943c9536dbe1164", "docker-gc--89f5535aea154dca504f84cd60eac6f61836aef9", - "dvdcli--ee85411e3cb9f0988ed54b5cc0789172b887f12f", "erlang--d693172f6f033707c7f07ff78fc18ac543d66b41", - "exhibitor--c3e48bbae19c0ed9c30d7f9396305d1e77130658", "flask--6d0f985ad677e8422c7190cbe207424acd813c3b", - "java--ce5ff19502fca31eaf4a9af86d50a10a8c212a5b", "libevent--05dc18bc0ab7434b2738318c5ebaa2e61a311f50", - "libffi--0e5b99b94f296b2a9a1b75e9fe5f74f5446f5e9b", "libsodium--e7056355f1fe160ade83aac0d11352a2bf3844e6", - "logrotate--877aece1fd506af3b9167b6938c316adfa79d4f5", "marathon--accdc43bafeca02da1be340baba4b55011eadf63", - "mesos--0677ce2b7d2e8c45091f6481884542f1f765c3d5", "mesos-dns--600da87080b7634f2380594499004a7ff0b34662", - "mesos-modules--1f5c4860450949db92ed27326c3146526041e681", "metronome--2ec6f56be44ed822e7228cb66c4dae6a78345789", - "navstar--c66f92f01d837433de3e2b19d221c64d26cc54b1", "ncurses--030fd6b08ed46a7ecce001c36901f5b4ad5d2af5", - "octarine--4e37c062d2f145f9c2ce01d30dadf72c2aac5c4a", "openssl--44777d19d54a3c33cc19543f2201cb20bf085d98", - "pkgpanda-api--30cb1e68f92ed5d4b89d57ca526f8a69b44132c8", "pkgpanda-role--612a6734567cc0c7c2ae1d508f03172f4bc7beed", - "pytest--5e26c8ed9fd2c325672d56fe558299bfbd0f7018", "python--5a4285ff7296548732203950bf73d360ea67f6ab", - "python-azure-mgmt-resource--26cbe8349f3fe139f7dc8bff7f0cb735382314fc", "python-cryptography--0d83d8afef4a8faddf0d8b713619d9d76e510a9e", - "python-dateutil--519201adebeba186049ecd79a9f358f614173b10", "python-docopt--0af809c220a922f7f6c58f15beafebaa043477c7", - "python-gunicorn--2ceb53716237da0736f67f4004682083f6ac68e1", "python-isodate--c9efb5859a0cfb06d82f25220cc5b387914af85d", - "python-jinja2--601a1443aa4c649ab1da10c2a6d7a4477a263fb3", "python-kazoo--0ff8e6ef528f58c6f36f0a9df6dc27d3871e5c27", - "python-markupsafe--1388c95920b4eb920c7a753d620a1ad07fc8b64d", "python-passlib--4691268be760073188b555dc436f836c6706b37a", - "python-pyyaml--d8a775d6e43da5eb239af5cccdf1d3fceeb0335f", "python-requests--db0474fab16019ba29a609a354285f221c1a2859", - "python-retrying--37dd25bf69bcbefe0c50139085d6bb2e22ccf439", "python-tox--322c468e2a75c5b143cb06af460b5e801ee34342", - "rexray--da7f17f8a4b772c0bac3f8d289a08abd4ff272b4", "six--93734bac9907087744815f9cb5b6152e9a198fae", - "spartan--c3d8005b1340bcbc3a00496861745b2d0bb2d697", "strace--9be573456909e3931a890785eb6474af7e0dcce4", - "teamcity-messages--073793b16cf369e58ebdb6348b93ed14b0e5e59a", "toybox--0c49f879bfe2f99e6f99b397136894fa5096fa0c"] - -' - owner: root - path: /etc/mesosphere/setup-flags/cluster-packages.json - permissions: '0644' -- content: | - [Journal] - MaxLevelConsole=warning - RateLimitInterval=1s - RateLimitBurst=20000 - owner: root - path: /etc/systemd/journald.conf.d/dcos.conf - permissions: '0644' -- content: | - rexray: - loglevel: info - modules: - default-docker: - disabled: true - service: vfs - path: /etc/rexray/config.yml - permissions: '0644' -- content: | - [Unit] - After=network-online.target - Wants=network-online.target - [Service] - Type=oneshot - Environment=DEBIAN_FRONTEND=noninteractive - StandardOutput=journal+console - StandardError=journal+console - ExecStartPre=/usr/bin/curl -fLsSv --retry 20 -Y 100000 -y 60 -o /var/tmp/d.deb https://mesosphere.blob.core.windows.net/dcos-deps/docker-engine_1.13.1-0-ubuntu-xenial_amd64.deb - ExecStart=/usr/bin/bash -c "try=1;until dpkg -D3 -i /var/tmp/d.deb || ((try>9));do echo retry $((try++));sleep $((try*try));done;systemctl --now start docker;systemctl restart docker.socket" - path: /etc/systemd/system/dcos-docker-install.service - permissions: '0644' -- content: | - [Service] - Restart=always - StartLimitInterval=0 - RestartSec=15 - ExecStartPre=-/sbin/ip link del docker0 - ExecStart= - ExecStart=/usr/bin/dockerd --storage-driver=overlay - path: /etc/systemd/system/docker.service.d/execstart.conf - permissions: '0644' -- content: | - [Unit] - PartOf=docker.service - [Socket] - ListenStream=/var/run/docker.sock - SocketMode=0660 - SocketUser=root - SocketGroup=docker - ListenStream=2375 - BindIPv6Only=both - [Install] - WantedBy=sockets.target - path: /etc/systemd/system/docker.socket - permissions: '0644' -- content: | - [Unit] - Requires=dcos-setup.service - After=dcos-setup.service - [Service] - Type=oneshot - EnvironmentFile=/etc/environment - EnvironmentFile=/opt/mesosphere/environment - ExecStart=/usr/bin/bash -c "echo $(detect_ip) $(hostname) > /etc/hosts" - path: /etc/systemd/system/dcos-config-writer.service - permissions: '0644' -- content: | - "bound_values": - "adminrouter_auth_enabled": |- - {{{oauthEnabled}}} - "cluster_name": |- - {{{masterPublicIPAddressName}}} - "exhibitor_azure_account_key": |- - ', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('masterStorageAccountExhibitorName')), '2015-06-15').key1, ' - "exhibitor_azure_account_name": |- - {{{masterStorageAccountExhibitorName}}} - "exhibitor_azure_prefix": |- - {{{masterPublicIPAddressName}}} - "master_list": |- - ["', DCOSCUSTOMDATAPUBLICIPSTR'"] - "oauth_enabled": |- - {{{oauthEnabled}}} - "late_bound_package_id": |- - dcos-provider-{{{dcosProviderPackageID}}}-azure--setup - owner: root - path: /etc/mesosphere/setup-flags/late-config.yaml - permissions: '0644' -- content: | - [Unit] - Before=dcos.target - [Service] - Type=oneshot - StandardOutput=journal+console - StandardError=journal+console - ExecStartPre=/usr/bin/mkdir -p /etc/profile.d - ExecStart=/usr/bin/ln -sf /opt/mesosphere/bin/add_dcos_path.sh /etc/profile.d/dcos.sh - path: /etc/systemd/system/dcos-link-env.service - permissions: '0644' -- content: | - [Unit] - Description=Pkgpanda: Download DC/OS to this host. - After=network-online.target - Wants=network-online.target - ConditionPathExists=!/opt/mesosphere/ - [Service] - Type=oneshot - StandardOutput=journal+console - StandardError=journal+console - ExecStartPre=/usr/bin/curl --keepalive-time 2 -fLsSv --retry 20 -Y 100000 -y 60 -o //var/tmp/bootstrap.tar.xz {{{dcosBootstrapURL}}} - ExecStartPre=/usr/bin/mkdir -p /opt/mesosphere - ExecStart=/usr/bin/tar -axf //var/tmp/bootstrap.tar.xz -C /opt/mesosphere - ExecStartPost=-/usr/bin/rm -f //var/tmp/bootstrap.tar.xz - path: /etc/systemd/system/dcos-download.service - permissions: '0644' -- content: | - [Unit] - Description=Pkgpanda: Specialize DC/OS for this host. - Requires=dcos-download.service - After=dcos-download.service - [Service] - Type=oneshot - StandardOutput=journal+console - StandardError=journal+console - EnvironmentFile=/opt/mesosphere/environment - ExecStart=/opt/mesosphere/bin/pkgpanda setup --no-block-systemd - [Install] - WantedBy=multi-user.target - path: /etc/systemd/system/dcos-setup.service - permissions: '0644' -- content: '' - path: /etc/mesosphere/roles/azure -- path: /var/lib/dcos/mesos-slave-common - content: 'ATTRIBUTES_STR' - permissions: "0644" - owner: "root" -- content: 'PROVISION_STR' - path: /opt/azure/containers/provision.sh - permissions: "0744" - owner: "root" diff --git a/parts/dcos/dcoscustomdata184.t b/parts/dcos/dcoscustomdata184.t deleted file mode 100644 index f5cae84415..0000000000 --- a/parts/dcos/dcoscustomdata184.t +++ /dev/null @@ -1,371 +0,0 @@ -bootcmd: -- bash -c "if [ ! -f /var/lib/sdb-gpt ];then echo DCOS-5890;parted -s /dev/sdb mklabel - gpt;touch /var/lib/sdb-gpt;fi" -disk_setup: - ephemeral0: - layout: - - 50 - - 50 - overwrite: true - table_type: gpt -fs_setup: -- device: ephemeral0.1 - filesystem: ext4 - overwrite: true -- device: ephemeral0.2 - filesystem: ext4 - overwrite: true -mounts: -- - ephemeral0.1 - - /var/lib/mesos -- - ephemeral0.2 - - /var/lib/docker -runcmd: PREPROVISION_EXTENSION -- /usr/lib/apt/apt.systemd.daily -- echo 2dd1ce17-079e-403c-b352-a1921ee207ee > /sys/bus/vmbus/drivers/hv_util/unbind # mitigation for bug https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1676635 -- sed -i "13i\echo 2dd1ce17-079e-403c-b352-a1921ee207ee > /sys/bus/vmbus/drivers/hv_util/unbind\n" /etc/rc.local # mitigation for bug https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1676635 -- - ln - - -s - - /bin/rm - - /usr/bin/rm -- - ln - - -s - - /bin/mkdir - - /usr/bin/mkdir -- - ln - - -s - - /bin/tar - - /usr/bin/tar -- - ln - - -s - - /bin/ln - - /usr/bin/ln -- - ln - - -s - - /bin/cp - - /usr/bin/cp -- - ln - - -s - - /bin/systemctl - - /usr/bin/systemctl -- - ln - - -s - - /bin/mount - - /usr/bin/mount -- - ln - - -s - - /bin/bash - - /usr/bin/bash -- - ln - - -s - - /usr/sbin/useradd - - /usr/bin/useradd -- - systemctl - - disable - - --now - - resolvconf.service -- - systemctl - - mask - - --now - - lxc-net.service -- - tar - - czf - - /etc/docker.tar.gz - - -C - - /tmp/xtoph - - .docker -- - rm - - -rf - - /tmp/xtoph -- /opt/azure/containers/provision.sh -- - cp - - -p - - /etc/resolv.conf - - /tmp/resolv.conf -- - rm - - -f - - /etc/resolv.conf -- - cp - - -p - - /tmp/resolv.conf - - /etc/resolv.conf -- - systemctl - - start - - dcos-docker-install.service -- - systemctl - - start - - dcos-config-writer.service -- - systemctl - - restart - - systemd-journald.service -- - systemctl - - restart - - docker.service -- - systemctl - - start - - dcos-link-env.service -- - systemctl - - enable - - dcos-setup.service -- - systemctl - - --no-block - - start - - dcos-setup.service -write_files: -- content: 'https://dcosio.azureedge.net/dcos/testing - - ' - owner: root - path: /etc/mesosphere/setup-flags/repository-url - permissions: '0644' -- content: 'DCOS_ENVIRONMENT={{{targetEnvironment}}} - - ' - owner: root - path: /etc/mesosphere/setup-flags/dcos-deploy-environment - permissions: '0644' -- content: 'BOOTSTRAP_ID=5b4aa43610c57ee1d60b4aa0751a1fb75824c083 - - ' - owner: root - path: /etc/mesosphere/setup-flags/bootstrap-id - permissions: '0644' -- content: '["dcos-config--setup_{{{dcosProviderPackageID}}}", "dcos-metadata--setup_{{{dcosProviderPackageID}}}"] - - ' - owner: root - path: /etc/mesosphere/setup-flags/cluster-packages.json - permissions: '0644' -- content: '[Journal] - - MaxLevelConsole=warning - - RateLimitInterval=1s - - RateLimitBurst=20000 - - ' - owner: root - path: /etc/systemd/journald.conf.d/dcos.conf - permissions: '0644' -- content: "rexray:\n loglevel: info\n modules:\n default-admin:\n host:\ - \ tcp://127.0.0.1:61003\n default-docker:\n disabled: true\n" - path: /etc/rexray/config.yml - permissions: '0644' -- content: '[Unit] - - After=network-online.target - - Wants=network-online.target - - [Service] - - Type=oneshot - - Environment=DEBIAN_FRONTEND=noninteractive - - StandardOutput=journal+console - - StandardError=journal+console - - ExecStart=/usr/bin/bash -c "try=1;until dpkg -D3 -i /var/lib/mesos/dl/d.deb || ((try>9));do - echo retry $((try++));sleep $((try*try));done;systemctl --now start docker;systemctl - restart docker.socket" - - ' - path: /etc/systemd/system/dcos-docker-install.service - permissions: '0644' -- content: '[Service] - - Restart=always - - StartLimitInterval=0 - - RestartSec=15 - - ExecStartPre=-/sbin/ip link del docker0 - - ExecStart= - - ExecStart=/usr/bin/docker daemon -H fd:// --storage-driver=overlay - - ' - path: /etc/systemd/system/docker.service.d/execstart.conf - permissions: '0644' -- content: '[Unit] - - PartOf=docker.service - - [Socket] - - ListenStream=/var/run/docker.sock - - SocketMode=0660 - - SocketUser=root - - SocketGroup=docker - - ListenStream=2375 - - BindIPv6Only=both - - [Install] - - WantedBy=sockets.target - - ' - path: /etc/systemd/system/docker.socket - permissions: '0644' -- content: '[Unit] - - Requires=dcos-setup.service - - After=dcos-setup.service - - [Service] - - Type=oneshot - - EnvironmentFile=/etc/environment - - EnvironmentFile=/opt/mesosphere/environment - - ExecStart=/usr/bin/bash -c "echo $(detect_ip) $(hostname) > /etc/hosts" - - ' - path: /etc/systemd/system/dcos-config-writer.service - permissions: '0644' -- content: 'MESOS_CLUSTER={{{masterPublicIPAddressName}}} - - ' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/etc/mesos-master-provider -- content: 'ADMINROUTER_ACTIVATE_AUTH_MODULE={{{oauthEnabled}}} - - ' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/etc/adminrouter.env -- content: '["'', DCOSCUSTOMDATAPUBLICIPSTR''"] - - ' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/etc/master_list -- content: 'EXHIBITOR_BACKEND=AZURE - - AZURE_CONTAINER=dcos-exhibitor - - AZURE_PREFIX={{{masterPublicIPAddressName}}} - - ' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/etc/exhibitor -- content: 'com.netflix.exhibitor.azure.account-name={{{masterStorageAccountExhibitorName}}} - - com.netflix.exhibitor.azure.account-key='', listKeys(resourceId(''Microsoft.Storage/storageAccounts'', - variables(''masterStorageAccountExhibitorName'')), ''2015-06-15'').key1,'' - - ' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/etc/exhibitor.properties -- content: '{"uiConfiguration":{"plugins":{"banner":{"enabled":false,"backgroundColor":"#1E232F","foregroundColor":"#FFFFFF","headerTitle":null,"headerContent":null,"footerContent":null,"imagePath":null,"dismissible":null},"branding":{"enabled":false},"external-links": - {"enabled": false}, - - - "authentication":{"enabled":false}, - - - "oauth":{"enabled":{{{oauthEnabled}}},"authHost":"https://dcos.auth0.com"}, - - - - "tracking":{"enabled":false}}}} - - ' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/etc/ui-config.json -- content: '{}' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/pkginfo.json -- content: '[Unit] - - Before=dcos.target - - [Service] - - Type=oneshot - - StandardOutput=journal+console - - StandardError=journal+console - - ExecStartPre=/usr/bin/mkdir -p /etc/profile.d - - ExecStart=/usr/bin/ln -sf /opt/mesosphere/environment.export /etc/profile.d/dcos.sh - - ' - path: /etc/systemd/system/dcos-link-env.service - permissions: '0644' -- content: '[Unit] - - Description=Pkgpanda: Download DC/OS to this host. - - After=network-online.target - - Wants=network-online.target - - ConditionPathExists=!/opt/mesosphere/ - - [Service] - - EnvironmentFile=/etc/mesosphere/setup-flags/bootstrap-id - - Type=oneshot - - StandardOutput=journal+console - - StandardError=journal+console - - ExecStartPre=/usr/bin/curl --keepalive-time 2 -fLsSv --retry 20 -Y 100000 -y 60 - -o /var/lib/mesos/dl/bootstrap.tar.xz {{{dcosBootstrapURL}}} - - ExecStartPre=/usr/bin/mkdir -p /opt/mesosphere - - ExecStart=/usr/bin/tar -axf /var/lib/mesos/dl/bootstrap.tar.xz -C /opt/mesosphere - - ExecStartPost=-/usr/bin/rm -f /var/lib/mesos/dl/bootstrap.tar.xz - - ' - path: /etc/systemd/system/dcos-download.service - permissions: '0644' -- content: '[Unit] - - Description=Pkgpanda: Specialize DC/OS for this host. - - Requires=dcos-download.service - - After=dcos-download.service - - [Service] - - Type=oneshot - - StandardOutput=journal+console - - StandardError=journal+console - - EnvironmentFile=/opt/mesosphere/environment - - ExecStart=/opt/mesosphere/bin/pkgpanda setup --no-block-systemd - - [Install] - - WantedBy=multi-user.target - - ' - path: /etc/systemd/system/dcos-setup.service - permissions: '0644' -- path: /var/lib/dcos/mesos-slave-common - content: 'ATTRIBUTES_STR' -- content: '' - path: /etc/mesosphere/roles/azure -- content: 'PROVISION_STR' - path: "/opt/azure/containers/provision.sh" - permissions: "0744" - owner: "root" -- content: '{ "auths": { "{{{registry}}}": { "auth" : "{{{registryKey}}}" } } }' - path: "/tmp/xtoph/.docker/config.json" - owner: "root" diff --git a/parts/dcos/dcoscustomdata187.t b/parts/dcos/dcoscustomdata187.t deleted file mode 100644 index e1a6e9e58e..0000000000 --- a/parts/dcos/dcoscustomdata187.t +++ /dev/null @@ -1,364 +0,0 @@ -bootcmd: -- bash -c "if [ ! -f /var/lib/sdb-gpt ];then echo DCOS-5890;parted -s /dev/sdb mklabel - gpt;touch /var/lib/sdb-gpt;fi" -disk_setup: - ephemeral0: - layout: - - 50 - - 50 - overwrite: true - table_type: gpt -fs_setup: -- device: ephemeral0.1 - filesystem: ext4 - overwrite: true -- device: ephemeral0.2 - filesystem: ext4 - overwrite: true -mounts: -- - ephemeral0.1 - - /var/lib/mesos -- - ephemeral0.2 - - /var/lib/docker -runcmd: PREPROVISION_EXTENSION -- /usr/lib/apt/apt.systemd.daily -- echo 2dd1ce17-079e-403c-b352-a1921ee207ee > /sys/bus/vmbus/drivers/hv_util/unbind # mitigation for bug https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1676635 -- sed -i "13i\echo 2dd1ce17-079e-403c-b352-a1921ee207ee > /sys/bus/vmbus/drivers/hv_util/unbind\n" /etc/rc.local # mitigation for bug https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1676635 -- - ln - - -s - - /bin/rm - - /usr/bin/rm -- - ln - - -s - - /bin/mkdir - - /usr/bin/mkdir -- - ln - - -s - - /bin/tar - - /usr/bin/tar -- - ln - - -s - - /bin/ln - - /usr/bin/ln -- - ln - - -s - - /bin/cp - - /usr/bin/cp -- - ln - - -s - - /bin/systemctl - - /usr/bin/systemctl -- - ln - - -s - - /bin/mount - - /usr/bin/mount -- - ln - - -s - - /bin/bash - - /usr/bin/bash -- - ln - - -s - - /usr/sbin/useradd - - /usr/bin/useradd -- - systemctl - - disable - - --now - - resolvconf.service -- - systemctl - - mask - - --now - - lxc-net.service -- - tar - - czf - - /etc/docker.tar.gz - - -C - - /tmp/xtoph - - .docker -- - rm - - -rf - - /tmp/xtoph -- /opt/azure/containers/provision.sh -- - cp - - -p - - /etc/resolv.conf - - /tmp/resolv.conf -- - rm - - -f - - /etc/resolv.conf -- - cp - - -p - - /tmp/resolv.conf - - /etc/resolv.conf -- - systemctl - - start - - dcos-docker-install.service -- - systemctl - - start - - dcos-config-writer.service -- - systemctl - - restart - - systemd-journald.service -- - systemctl - - restart - - docker.service -- - systemctl - - start - - dcos-link-env.service -- - systemctl - - enable - - dcos-setup.service -- - systemctl - - --no-block - - start - - dcos-setup.service -write_files: -- content: 'https://dcosio.azureedge.net/dcos/stable - - ' - owner: root - path: /etc/mesosphere/setup-flags/repository-url - permissions: '0644' -- content: '["dcos-config--setup_{{{dcosProviderPackageID}}}", "dcos-metadata--setup_{{{dcosProviderPackageID}}}"] - - ' - owner: root - path: /etc/mesosphere/setup-flags/cluster-packages.json - permissions: '0644' -- content: 'DCOS_ENVIRONMENT={{{targetEnvironment}}} - - ' - owner: root - path: /etc/mesosphere/setup-flags/dcos-deploy-environment - permissions: '0644' -- content: '[Journal] - - MaxLevelConsole=warning - - RateLimitInterval=1s - - RateLimitBurst=20000 - - ' - owner: root - path: /etc/systemd/journald.conf.d/dcos.conf - permissions: '0644' -- content: "rexray:\n loglevel: info\n modules:\n default-admin:\n host:\ - \ tcp://127.0.0.1:61003\n default-docker:\n disabled: true\n" - path: /etc/rexray/config.yml - permissions: '0644' -- content: '[Unit] - - After=network-online.target - - Wants=network-online.target - - [Service] - - Type=oneshot - - Environment=DEBIAN_FRONTEND=noninteractive - - StandardOutput=journal+console - - StandardError=journal+console - - ExecStart=/usr/bin/bash -c "try=1;until dpkg -D3 -i /var/lib/mesos/dl/d.deb || ((try>9));do - echo retry $((try++));sleep $((try*try));done;systemctl --now start docker;systemctl - restart docker.socket" - - ' - path: /etc/systemd/system/dcos-docker-install.service - permissions: '0644' -- content: '[Service] - - Restart=always - - StartLimitInterval=0 - - RestartSec=15 - - ExecStartPre=-/sbin/ip link del docker0 - - ExecStart= - - ExecStart=/usr/bin/docker daemon -H fd:// --storage-driver=overlay - - ' - path: /etc/systemd/system/docker.service.d/execstart.conf - permissions: '0644' -- content: '[Unit] - - PartOf=docker.service - - [Socket] - - ListenStream=/var/run/docker.sock - - SocketMode=0660 - - SocketUser=root - - SocketGroup=docker - - ListenStream=2375 - - BindIPv6Only=both - - [Install] - - WantedBy=sockets.target - - ' - path: /etc/systemd/system/docker.socket - permissions: '0644' -- content: '[Unit] - - Requires=dcos-setup.service - - After=dcos-setup.service - - [Service] - - Type=oneshot - - EnvironmentFile=/etc/environment - - EnvironmentFile=/opt/mesosphere/environment - - ExecStart=/usr/bin/bash -c "echo $(detect_ip) $(hostname) > /etc/hosts" - - ' - path: /etc/systemd/system/dcos-config-writer.service - permissions: '0644' -- content: 'MESOS_CLUSTER={{{masterPublicIPAddressName}}} - - ' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/etc/mesos-master-provider -- content: 'ADMINROUTER_ACTIVATE_AUTH_MODULE={{{oauthEnabled}}} - - ' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/etc/adminrouter.env -- content: '["'', DCOSCUSTOMDATAPUBLICIPSTR''"] - - ' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/etc/master_list -- content: 'EXHIBITOR_BACKEND=AZURE - - AZURE_CONTAINER=dcos-exhibitor - - AZURE_PREFIX={{{masterPublicIPAddressName}}} - - ' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/etc/exhibitor -- content: 'com.netflix.exhibitor.azure.account-name={{{masterStorageAccountExhibitorName}}} - - com.netflix.exhibitor.azure.account-key='', listKeys(resourceId(''Microsoft.Storage/storageAccounts'', - variables(''masterStorageAccountExhibitorName'')), ''2015-06-15'').key1,'' - - ' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/etc/exhibitor.properties -- content: '{"uiConfiguration":{"plugins":{"banner":{"enabled":false,"backgroundColor":"#1E232F","foregroundColor":"#FFFFFF","headerTitle":null,"headerContent":null,"footerContent":null,"imagePath":null,"dismissible":null},"branding":{"enabled":false},"external-links": - {"enabled": false}, - - - "authentication":{"enabled":false}, - - - "oauth":{"enabled":{{{oauthEnabled}}},"authHost":"https://dcos.auth0.com"}, - - - - "tracking":{"enabled":false}}}} - - ' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/etc/ui-config.json -- content: '{}' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/pkginfo.json -- content: '[Unit] - - Before=dcos.target - - [Service] - - Type=oneshot - - StandardOutput=journal+console - - StandardError=journal+console - - ExecStartPre=/usr/bin/mkdir -p /etc/profile.d - - ExecStart=/usr/bin/ln -sf /opt/mesosphere/environment.export /etc/profile.d/dcos.sh - - ' - path: /etc/systemd/system/dcos-link-env.service - permissions: '0644' -- content: '[Unit] - - Description=Pkgpanda: Download DC/OS to this host. - - After=network-online.target - - Wants=network-online.target - - ConditionPathExists=!/opt/mesosphere/ - - [Service] - - Type=oneshot - - StandardOutput=journal+console - - StandardError=journal+console - - ExecStartPre=/usr/bin/curl --keepalive-time 2 -fLsSv --retry 20 -Y 100000 -y 60 -o /var/lib/mesos/dl/bootstrap.tar.xz {{{dcosBootstrapURL}}} - - ExecStartPre=/usr/bin/mkdir -p /opt/mesosphere - - ExecStart=/usr/bin/tar -axf /var/lib/mesos/dl/bootstrap.tar.xz -C /opt/mesosphere - - ExecStartPost=-/usr/bin/rm -f /var/lib/mesos/dl/bootstrap.tar.xz - - ' - path: /etc/systemd/system/dcos-download.service - permissions: '0644' -- content: '[Unit] - - Description=Pkgpanda: Specialize DC/OS for this host. - - Requires=dcos-download.service - - After=dcos-download.service - - [Service] - - Type=oneshot - - StandardOutput=journal+console - - StandardError=journal+console - - EnvironmentFile=/opt/mesosphere/environment - - ExecStart=/opt/mesosphere/bin/pkgpanda setup --no-block-systemd - - [Install] - - WantedBy=multi-user.target - - ' - path: /etc/systemd/system/dcos-setup.service - permissions: '0644' -- content: '' - path: /etc/mesosphere/roles/azure -- content: 'PROVISION_STR' - path: "/opt/azure/containers/provision.sh" - permissions: "0744" - owner: "root" -- path: /var/lib/dcos/mesos-slave-common - content: 'ATTRIBUTES_STR' - permissions: "0644" - owner: "root" -- content: '{ "auths": { "{{{registry}}}": { "auth" : "{{{registryKey}}}" } } }' - path: "/tmp/xtoph/.docker/config.json" - owner: "root" diff --git a/parts/dcos/dcoscustomdata188.t b/parts/dcos/dcoscustomdata188.t deleted file mode 100644 index 6380c2022d..0000000000 --- a/parts/dcos/dcoscustomdata188.t +++ /dev/null @@ -1,364 +0,0 @@ -bootcmd: -- bash -c "if [ ! -f /var/lib/sdb-gpt ];then echo DCOS-5890;parted -s /dev/sdb mklabel - gpt;touch /var/lib/sdb-gpt;fi" -disk_setup: - ephemeral0: - layout: - - 50 - - 50 - overwrite: true - table_type: gpt -fs_setup: -- device: ephemeral0.1 - filesystem: ext4 - overwrite: true -- device: ephemeral0.2 - filesystem: ext4 - overwrite: true -mounts: -- - ephemeral0.1 - - /var/lib/mesos -- - ephemeral0.2 - - /var/lib/docker -runcmd: PREPROVISION_EXTENSION -- /usr/lib/apt/apt.systemd.daily -- echo 2dd1ce17-079e-403c-b352-a1921ee207ee > /sys/bus/vmbus/drivers/hv_util/unbind # mitigation for bug https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1676635 -- sed -i "13i\echo 2dd1ce17-079e-403c-b352-a1921ee207ee > /sys/bus/vmbus/drivers/hv_util/unbind\n" /etc/rc.local # mitigation for bug https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1676635 -- - ln - - -s - - /bin/rm - - /usr/bin/rm -- - ln - - -s - - /bin/mkdir - - /usr/bin/mkdir -- - ln - - -s - - /bin/tar - - /usr/bin/tar -- - ln - - -s - - /bin/ln - - /usr/bin/ln -- - ln - - -s - - /bin/cp - - /usr/bin/cp -- - ln - - -s - - /bin/systemctl - - /usr/bin/systemctl -- - ln - - -s - - /bin/mount - - /usr/bin/mount -- - ln - - -s - - /bin/bash - - /usr/bin/bash -- - ln - - -s - - /usr/sbin/useradd - - /usr/bin/useradd -- - systemctl - - disable - - --now - - resolvconf.service -- - systemctl - - mask - - --now - - lxc-net.service -- - tar - - czf - - /etc/docker.tar.gz - - -C - - /tmp/xtoph - - .docker -- - rm - - -rf - - /tmp/xtoph -- /opt/azure/containers/provision.sh -- - cp - - -p - - /etc/resolv.conf - - /tmp/resolv.conf -- - rm - - -f - - /etc/resolv.conf -- - cp - - -p - - /tmp/resolv.conf - - /etc/resolv.conf -- - systemctl - - start - - dcos-docker-install.service -- - systemctl - - start - - dcos-config-writer.service -- - systemctl - - restart - - systemd-journald.service -- - systemctl - - restart - - docker.service -- - systemctl - - start - - dcos-link-env.service -- - systemctl - - enable - - dcos-setup.service -- - systemctl - - --no-block - - start - - dcos-setup.service -write_files: -- content: 'https://dcosio.azureedge.net/dcos/stable - - ' - owner: root - path: /etc/mesosphere/setup-flags/repository-url - permissions: '0644' -- content: 'DCOS_ENVIRONMENT={{{targetEnvironment}}} - - ' - owner: root - path: /etc/mesosphere/setup-flags/dcos-deploy-environment - permissions: '0644' -- content: '["dcos-config--setup_{{{dcosProviderPackageID}}}", "dcos-metadata--setup_{{{dcosProviderPackageID}}}"] - - ' - owner: root - path: /etc/mesosphere/setup-flags/cluster-packages.json - permissions: '0644' -- content: '[Journal] - - MaxLevelConsole=warning - - RateLimitInterval=1s - - RateLimitBurst=20000 - - ' - owner: root - path: /etc/systemd/journald.conf.d/dcos.conf - permissions: '0644' -- content: "rexray:\n loglevel: info\n modules:\n default-admin:\n host:\ - \ tcp://127.0.0.1:61003\n default-docker:\n disabled: true\n" - path: /etc/rexray/config.yml - permissions: '0644' -- content: '[Unit] - - After=network-online.target - - Wants=network-online.target - - [Service] - - Type=oneshot - - Environment=DEBIAN_FRONTEND=noninteractive - - StandardOutput=journal+console - - StandardError=journal+console - - ExecStart=/usr/bin/bash -c "try=1;until dpkg -D3 -i /var/lib/mesos/dl/d.deb || ((try>9));do - echo retry $((try++));sleep $((try*try));done;systemctl --now start docker;systemctl - restart docker.socket" - - ' - path: /etc/systemd/system/dcos-docker-install.service - permissions: '0644' -- content: '[Service] - - Restart=always - - StartLimitInterval=0 - - RestartSec=15 - - ExecStartPre=-/sbin/ip link del docker0 - - ExecStart= - - ExecStart=/usr/bin/docker daemon -H fd:// --storage-driver=overlay - - ' - path: /etc/systemd/system/docker.service.d/execstart.conf - permissions: '0644' -- content: '[Unit] - - PartOf=docker.service - - [Socket] - - ListenStream=/var/run/docker.sock - - SocketMode=0660 - - SocketUser=root - - SocketGroup=docker - - ListenStream=2375 - - BindIPv6Only=both - - [Install] - - WantedBy=sockets.target - - ' - path: /etc/systemd/system/docker.socket - permissions: '0644' -- content: '[Unit] - - Requires=dcos-setup.service - - After=dcos-setup.service - - [Service] - - Type=oneshot - - EnvironmentFile=/etc/environment - - EnvironmentFile=/opt/mesosphere/environment - - ExecStart=/usr/bin/bash -c "echo $(detect_ip) $(hostname) > /etc/hosts" - - ' - path: /etc/systemd/system/dcos-config-writer.service - permissions: '0644' -- content: 'MESOS_CLUSTER={{{masterPublicIPAddressName}}} - - ' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/etc/mesos-master-provider -- content: 'ADMINROUTER_ACTIVATE_AUTH_MODULE={{{oauthEnabled}}} - - ' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/etc/adminrouter.env -- content: '["'', DCOSCUSTOMDATAPUBLICIPSTR''"] - - ' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/etc/master_list -- content: 'EXHIBITOR_BACKEND=AZURE - - AZURE_CONTAINER=dcos-exhibitor - - AZURE_PREFIX={{{masterPublicIPAddressName}}} - - ' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/etc/exhibitor -- content: 'com.netflix.exhibitor.azure.account-name={{{masterStorageAccountExhibitorName}}} - - com.netflix.exhibitor.azure.account-key='', listKeys(resourceId(''Microsoft.Storage/storageAccounts'', - variables(''masterStorageAccountExhibitorName'')), ''2015-06-15'').key1,'' - - ' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/etc/exhibitor.properties -- content: '{"uiConfiguration":{"plugins":{"banner":{"enabled":false,"backgroundColor":"#1E232F","foregroundColor":"#FFFFFF","headerTitle":null,"headerContent":null,"footerContent":null,"imagePath":null,"dismissible":null},"branding":{"enabled":false},"external-links": - {"enabled": false}, - - - "authentication":{"enabled":false}, - - - "oauth":{"enabled":{{{oauthEnabled}}},"authHost":"https://dcos.auth0.com"}, - - - - "tracking":{"enabled":false}}}} - - ' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/etc/ui-config.json -- content: '{}' - path: /etc/mesosphere/setup-packages/dcos-provider-azure--setup/pkginfo.json -- content: '[Unit] - - Before=dcos.target - - [Service] - - Type=oneshot - - StandardOutput=journal+console - - StandardError=journal+console - - ExecStartPre=/usr/bin/mkdir -p /etc/profile.d - - ExecStart=/usr/bin/ln -sf /opt/mesosphere/environment.export /etc/profile.d/dcos.sh - - ' - path: /etc/systemd/system/dcos-link-env.service - permissions: '0644' -- content: '[Unit] - - Description=Pkgpanda: Download DC/OS to this host. - - After=network-online.target - - Wants=network-online.target - - ConditionPathExists=!/opt/mesosphere/ - - [Service] - - Type=oneshot - - StandardOutput=journal+console - - StandardError=journal+console - - ExecStartPre=/usr/bin/curl --keepalive-time 2 -fLsSv --retry 20 -Y 100000 -y 60 -o /var/lib/mesos/dl/bootstrap.tar.xz {{{dcosBootstrapURL}}} - - ExecStartPre=/usr/bin/mkdir -p /opt/mesosphere - - ExecStart=/usr/bin/tar -axf /var/lib/mesos/dl/bootstrap.tar.xz -C /opt/mesosphere - - ExecStartPost=-/usr/bin/rm -f /var/lib/mesos/dl/bootstrap.tar.xz - - ' - path: /etc/systemd/system/dcos-download.service - permissions: '0644' -- content: '[Unit] - - Description=Pkgpanda: Specialize DC/OS for this host. - - Requires=dcos-download.service - - After=dcos-download.service - - [Service] - - Type=oneshot - - StandardOutput=journal+console - - StandardError=journal+console - - EnvironmentFile=/opt/mesosphere/environment - - ExecStart=/opt/mesosphere/bin/pkgpanda setup --no-block-systemd - - [Install] - - WantedBy=multi-user.target - - ' - path: /etc/systemd/system/dcos-setup.service - permissions: '0644' -- content: '' - path: /etc/mesosphere/roles/azure -- content: 'PROVISION_STR' - path: "/opt/azure/containers/provision.sh" - permissions: "0744" - owner: "root" -- path: /var/lib/dcos/mesos-slave-common - content: 'ATTRIBUTES_STR' - permissions: "0644" - owner: "root" -- content: '{ "auths": { "{{{registry}}}": { "auth" : "{{{registryKey}}}" } } }' - path: "/tmp/xtoph/.docker/config.json" - owner: "root" diff --git a/parts/dcos/dcoscustomdata190.t b/parts/dcos/dcoscustomdata190.t deleted file mode 100644 index 61c13441cf..0000000000 --- a/parts/dcos/dcoscustomdata190.t +++ /dev/null @@ -1,357 +0,0 @@ -bootcmd: -- bash -c "if [ ! -f /var/lib/sdb-gpt ];then echo DCOS-5890;parted -s /dev/sdb mklabel - gpt;touch /var/lib/sdb-gpt;fi" -disk_setup: - ephemeral0: - layout: - - 45 - - 45 - - 10 - overwrite: true - table_type: gpt -fs_setup: -- device: ephemeral0.1 - filesystem: ext4 - overwrite: true -- device: ephemeral0.2 - filesystem: ext4 - overwrite: true -- device: ephemeral0.3 - filesystem: ext4 - overwrite: true -mounts: -- - ephemeral0.1 - - /var/lib/mesos -- - ephemeral0.2 - - /var/lib/docker -- - ephemeral0.3 - - /var/tmp -runcmd: PREPROVISION_EXTENSION -- /usr/lib/apt/apt.systemd.daily -- echo 2dd1ce17-079e-403c-b352-a1921ee207ee > /sys/bus/vmbus/drivers/hv_util/unbind # mitigation for bug https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1676635 -- sed -i "13i\echo 2dd1ce17-079e-403c-b352-a1921ee207ee > /sys/bus/vmbus/drivers/hv_util/unbind\n" /etc/rc.local # mitigation for bug https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1676635 -- - ln - - -s - - /bin/rm - - /usr/bin/rm -- - ln - - -s - - /bin/mkdir - - /usr/bin/mkdir -- - ln - - -s - - /bin/tar - - /usr/bin/tar -- - ln - - -s - - /bin/ln - - /usr/bin/ln -- - ln - - -s - - /bin/cp - - /usr/bin/cp -- - ln - - -s - - /bin/systemctl - - /usr/bin/systemctl -- - ln - - -s - - /bin/mount - - /usr/bin/mount -- - ln - - -s - - /bin/bash - - /usr/bin/bash -- - ln - - -s - - /usr/sbin/useradd - - /usr/bin/useradd -- - systemctl - - disable - - --now - - resolvconf.service -- - systemctl - - mask - - --now - - lxc-net.service -- - systemctl - - disable - - --now - - unscd.service -- - systemctl - - stop - - --now - - unscd.service -- sed -i "s/^Port 22$/Port 22\nPort 2222/1" /etc/ssh/sshd_config -- service ssh restart -- /opt/azure/containers/setup_ephemeral_disk.sh -- - tar - - czf - - /etc/docker.tar.gz - - -C - - /tmp/xtoph - - .docker -- - rm - - -rf - - /tmp/xtoph -- /opt/azure/containers/provision.sh -- - cp - - -p - - /etc/resolv.conf - - /tmp/resolv.conf -- - rm - - -f - - /etc/resolv.conf -- - cp - - -p - - /tmp/resolv.conf - - /etc/resolv.conf -- - systemctl - - start - - dcos-docker-install.service -- - systemctl - - start - - dcos-config-writer.service -- - systemctl - - restart - - systemd-journald.service -- - systemctl - - restart - - docker.service -- - systemctl - - start - - dcos-link-env.service -- - systemctl - - enable - - dcos-setup.service -- - systemctl - - --no-block - - start - - dcos-setup.service -write_files: -- content: '{{{dcosRepositoryURL}}} - -' - owner: root - path: /etc/mesosphere/setup-flags/repository-url - permissions: '0644' -- content: '["3dt--7847ebb24bf6756c3103902971b34c3f09c3afbd", "adminrouter--0493a6fdaed08e1971871818e194aa4607df4f09", - "avro-cpp--760c214063f6b038b522eaf4b768b905fed56ebc", "boost-libs--2015ccb58fb756f61c02ee6aa05cc1e27459a9ec", - "bootstrap--59a905ecee27e71168ed44cefda4481fb76b816d", "boto--6344d31eef082c7bd13259b17034ea7b5c34aedf", - "check-time--be7d0ba757ec87f9965378fee7c76a6ee5ae996d", "cni--e48337da39a8cd379414acfe0da52a9226a10d24", - "cosmos--20decef90f0623ed253a12ec4cf5c148b18d8249", "curl--fc3486c43f98e63f9b12675f1356e8fe842f26b0", - "dcos-config--setup_{{{dcosProviderPackageID}}}", "dcos-history--77b0e97d7b25c8bedf8f7da0689cac65b83e3813", - "dcos-image--bda6a02bcb2eb21c4218453a870cc584f921a800", "dcos-image-deps--83584fd868e5b470f7cf754424a9a75b328e9b68", - "dcos-integration-test--c28bcb2347799dca43083f55e4c7b28503176f9c", "dcos-log--4d630df863228f38c6333e44670b4c4b20a74832", - "dcos-metadata--setup_{{{dcosProviderPackageID}}}", "dcos-metrics--23ee2f89c58b1258bc959f1d0dd7debcbb3d79d2", - "dcos-oauth--0079529da183c0f23a06d2b069721b6fa6cc7b52", "dcos-signal--1bcd3b612cbdc379380dcba17cdf9a3b6652d9dc", - "dcos-ui--d4afd695796404a5b35950c3daddcae322481ac4", "dnspython--0f833eb9a8abeba3179b43f3a200a8cd42d3795a", - "docker-gc--59a98ed6446a084bf74e4ff4b8e3479f59ea8528", "dvdcli--5374dd4ffb519f1dcefdec89b2247e3404f2e2e3", - "erlang--a9ee2530357a3301e53056b36a93420847b339a3", "exhibitor--72d9d8f947e5411eda524d40dde1a58edeb158ed", - "flask--26d1bcdb2d1c3dcf1d2c03bc0d4f29c86d321b21", "java--cd5e921ce66b0d3303883c06d73a657314044304", - "libevent--208be855d2be29c9271a7bd6c04723ff79946e02", "libffi--83ce3bd7eda2ef089e57efd2bc16c144d5a1f094", - "libsodium--9ff915db08c6bba7d6738af5084e782b13c84bf8", "logrotate--7f7bc4416d3ad101d0c5218872858483b516be07", - "marathon--bfb24f7f90cb3cd52a1cb22a07caafa5013bba21", "mesos--aaedd03eee0d57f5c0d49c74ff1e5721862cad98", - "mesos-dns--0401501b2b5152d01bfa84ff6d007fdafe414b16", "mesos-modules--311849eaae42696b8a7eefe86b9ab3ebd9bd48f5", - "metronome--467e4c64f804dbd4cd8572516e111a3f9298c10d", "navstar--1128db0234105a64fb4be52f4453cd6aa895ff30", - "ncurses--d889894b71aa1a5b311bafef0e85479025b4dacb", "octarine--e86d3312691b12523280d56f6260216729aaa0ad", - "openssl--b01a32a42e3ccba52b417276e9509a441e1d4a82", "pkgpanda-api--541feb8a8be58bdde8fecf1d2e5bfa0515f5a7d0", - "pkgpanda-role--f8a749a4a821476ad2ef7e9dd9d12b6a8c4643a4", "pytest--78aee3e58a049cdab0d266af74f77d658b360b4f", - "python--b7a144a49577a223d37d447c568f51330ee95390", "python-azure-mgmt-resource--03c05550f43b0e7a4455c33fe43b0deb755d87f0", - "python-cryptography--4184767c68e48801dd394072cb370c610a05029d", "python-dateutil--fdc6ff929f65dd0918cf75a9ad56704683d31781", - "python-docopt--beba78faa13e5bf4c52393b4b82d81f3c391aa65", "python-gunicorn--a537f95661fb2689c52fe12510eb0d01cb83af60", - "python-isodate--40d378c688e6badfd16676dd8b51b742bfebc8d5", "python-jinja2--7450f5ae5a822f63f7a58c717207be0456df51ed", - "python-kazoo--cb7ce13a1068cd82dd84ea0de32b529a760a4bdd", "python-markupsafe--dd46d2a3c58611656a235f96d4adc51b2a7a590e", - "python-passlib--802ec3605c0b82428fedba60983b1bafaa036bb8", "python-pyyaml--81dd44cc4a24db7cefa7016c6586a131acf279c3", - "python-requests--1b2cadbd3811cc0c2ee235ce927e13ea1d6af41d", "python-retrying--eb7b8bac133f50492b1e1349cbe77c3e38bd02c3", - "python-tox--07244f8a939a10353634c952c6d88ec4a3c05736", "rexray--869621bb411c9f2a793ea42cdfeed489e1972aaa", - "six--f06424b68523c4dfa2a7c3e7475d479f3d361e42", "spartan--9cc57a3d55452b905d90e3201f56913140914ecc", - "strace--7d01796d64994451c1b2b82d161a335cbe90569b", "teamcity-messages--e623a4d86eb3a8d199cefcc240dd4c5460cb2962", - "toybox--f235594ab8ea9a2864ee72abe86723d76f92e848"] - -' - owner: root - path: /etc/mesosphere/setup-flags/cluster-packages.json - permissions: '0644' -- content: | - [Journal] - MaxLevelConsole=warning - RateLimitInterval=1s - RateLimitBurst=20000 - owner: root - path: /etc/systemd/journald.conf.d/dcos.conf - permissions: '0644' -- content: | - rexray: - loglevel: info - modules: - default-admin: - host: tcp://127.0.0.1:61003 - default-docker: - disabled: true - path: /etc/rexray/config.yml - permissions: '0644' -- content: | - [Unit] - After=network-online.target - Wants=network-online.target - [Service] - Type=oneshot - Environment=DEBIAN_FRONTEND=noninteractive - StandardOutput=journal+console - StandardError=journal+console - ExecStartPre=/usr/bin/curl -fLsSv --retry 20 -Y 100000 -y 60 -o /var/tmp/d.deb https://az837203.vo.msecnd.net/dcos-deps/docker-engine_1.13.1-0-ubuntu-xenial_amd64.deb - ExecStart=/usr/bin/bash -c "try=1;until dpkg -D3 -i /var/tmp/d.deb || ((try>9));do echo retry $((try++));sleep $((try*try));done;systemctl --now start docker;systemctl restart docker.socket" - path: /etc/systemd/system/dcos-docker-install.service - permissions: '0644' -- content: | - [Service] - Restart=always - StartLimitInterval=0 - RestartSec=15 - LimitNOFILE=16384 - ExecStartPre=-/sbin/ip link del docker0 - ExecStart= - ExecStart=/usr/bin/docker daemon -H fd:// --storage-driver=overlay - path: /etc/systemd/system/docker.service.d/execstart.conf - permissions: '0644' -- content: | - [Unit] - PartOf=docker.service - [Socket] - ListenStream=/var/run/docker.sock - SocketMode=0660 - SocketUser=root - SocketGroup=docker - ListenStream=2375 - BindIPv6Only=both - [Install] - WantedBy=sockets.target - path: /etc/systemd/system/docker.socket - permissions: '0644' - content: | - [Unit] - Requires=dcos-setup.service - After=dcos-setup.service - [Service] - Type=oneshot - EnvironmentFile=/etc/environment - EnvironmentFile=/opt/mesosphere/environment - ExecStart=/usr/bin/bash -c "echo $(detect_ip) $(hostname) > /etc/hosts" - path: /etc/systemd/system/dcos-config-writer.service - permissions: '0644' -- content: | - "bound_values": - "adminrouter_auth_enabled": |- - {{{oauthEnabled}}} - "cluster_name": |- - {{{masterPublicIPAddressName}}} - "exhibitor_azure_account_key": |- - ', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('masterStorageAccountExhibitorName')), '2015-06-15').key1, ' - "exhibitor_azure_account_name": |- - {{{masterStorageAccountExhibitorName}}} - "exhibitor_azure_prefix": |- - {{{masterPublicIPAddressName}}} - "master_list": |- - ["', DCOSCUSTOMDATAPUBLICIPSTR'"] - "oauth_enabled": |- - {{{oauthEnabled}}} - "late_bound_package_id": |- - dcos-provider-{{{dcosProviderPackageID}}}-azure--setup - owner: root - path: /etc/mesosphere/setup-flags/late-config.yaml - permissions: '0644' -- content: | - [Unit] - Before=dcos.target - [Service] - Type=oneshot - StandardOutput=journal+console - StandardError=journal+console - ExecStartPre=/usr/bin/mkdir -p /etc/profile.d - ExecStart=/usr/bin/ln -sf /opt/mesosphere/bin/add_dcos_path.sh /etc/profile.d/dcos.sh - path: /etc/systemd/system/dcos-link-env.service - permissions: '0644' -- content: | - [Unit] - Description=Pkgpanda: Download DC/OS to this host. - After=network-online.target - Wants=network-online.target - ConditionPathExists=!/opt/mesosphere/ - [Service] - Type=oneshot - StandardOutput=journal+console - StandardError=journal+console - ExecStartPre=/usr/bin/curl --keepalive-time 2 -fLsSv --retry 20 -Y 100000 -y 60 -o //var/tmp/bootstrap.tar.xz {{{dcosBootstrapURL}}} - ExecStartPre=/usr/bin/mkdir -p /opt/mesosphere - ExecStart=/usr/bin/tar -axf //var/tmp/bootstrap.tar.xz -C /opt/mesosphere - ExecStartPost=-/usr/bin/rm -f //var/tmp/bootstrap.tar.xz - path: /etc/systemd/system/dcos-download.service - permissions: '0644' -- content: | - [Unit] - Description=Pkgpanda: Specialize DC/OS for this host. - Requires=dcos-download.service - After=dcos-download.service - [Service] - Type=oneshot - StandardOutput=journal+console - StandardError=journal+console - EnvironmentFile=/opt/mesosphere/environment - ExecStart=/opt/mesosphere/bin/pkgpanda setup --no-block-systemd - [Install] - WantedBy=multi-user.target - path: /etc/systemd/system/dcos-setup.service - permissions: '0644' -- content: '' - path: /etc/mesosphere/roles/azure -- content: 'PROVISION_STR' - path: "/opt/azure/containers/provision.sh" - permissions: "0744" - owner: "root" -- path: /var/lib/dcos/mesos-slave-common - content: 'ATTRIBUTES_STR' - permissions: "0644" - owner: "root" -- content: '{ "auths": { "{{{registry}}}": { "auth" : "{{{registryKey}}}" } } }' - path: "/tmp/xtoph/.docker/config.json" - owner: "root" -- content: | - #!/bin/bash - # Check the partitions on /dev/sdb created by cloudinit and force a detach and - # reformat of the parition. After which, all will be remounted. - EPHEMERAL_DISK="/dev/sdb" - PARTITIONS=`fdisk -l $EPHEMERAL_DISK | grep "^$EPHEMERAL_DISK" | cut -d" " -f1 | sed "s~$EPHEMERAL_DISK~~"` - if [ -n "$PARTITIONS" ]; then - for f in $PARTITIONS; do - df -k | grep "/dev/sdb$f" - if [ $? -eq 0 ]; then - umount -f /dev/sdb$f - fi - mkfs.ext4 /dev/sdb$f - done - mount -a - fi - # If there is a /var/tmp partition on the ephemeral disk, create a symlink such - # that the /var/log/mesos and /var/log/journal placed on the ephemeral disk. - VAR_TMP_PARTITION=`df -P /var/tmp | tail -1 | cut -d" " -f 1` - echo $VAR_TMP_PARTITION | grep "^$EPHEMERAL_DISK" - if [ $? -eq 0 ]; then - # Handle the /var/log/mesos directory - mkdir -p /var/tmp/log/mesos - if [ -d "/var/log/mesos" ]; then - cp -rp /var/log/mesos/* /var/tmp/log/mesos/ - rm -rf /var/log/mesos - fi - ln -s /var/tmp/log/mesos /var/log/mesos - # Handle the /var/log/journal direcotry - mkdir -p /var/tmp/log/journal - if [ -d "/var/log/journal" ]; then - cp -rp /var/log/journal/* /var/tmp/log/journal/ - rm -rf /var/log/journal - fi - ln -s /var/tmp/log/journal /var/log/journal - fi - path: "/opt/azure/containers/setup_ephemeral_disk.sh" - permissions: "0744" - owner: "root" \ No newline at end of file diff --git a/parts/dcos/dcoscustomdata198.t b/parts/dcos/dcoscustomdata198.t deleted file mode 100644 index 57621571f5..0000000000 --- a/parts/dcos/dcoscustomdata198.t +++ /dev/null @@ -1,357 +0,0 @@ -bootcmd: -- bash -c "if [ ! -f /var/lib/sdb-gpt ];then echo DCOS-5890;parted -s /dev/sdb mklabel - gpt;touch /var/lib/sdb-gpt;fi" -disk_setup: - ephemeral0: - layout: - - 45 - - 45 - - 10 - overwrite: true - table_type: gpt -fs_setup: -- device: ephemeral0.1 - filesystem: ext4 - overwrite: true -- device: ephemeral0.2 - filesystem: ext4 - overwrite: true -- device: ephemeral0.3 - filesystem: ext4 - overwrite: true -mounts: -- - ephemeral0.1 - - /var/lib/mesos -- - ephemeral0.2 - - /var/lib/docker -- - ephemeral0.3 - - /var/tmp -runcmd: PREPROVISION_EXTENSION -- /usr/lib/apt/apt.systemd.daily -- echo 2dd1ce17-079e-403c-b352-a1921ee207ee > /sys/bus/vmbus/drivers/hv_util/unbind # mitigation for bug https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1676635 -- sed -i "13i\echo 2dd1ce17-079e-403c-b352-a1921ee207ee > /sys/bus/vmbus/drivers/hv_util/unbind\n" /etc/rc.local # mitigation for bug https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1676635 -- - ln - - -s - - /bin/rm - - /usr/bin/rm -- - ln - - -s - - /bin/mkdir - - /usr/bin/mkdir -- - ln - - -s - - /bin/tar - - /usr/bin/tar -- - ln - - -s - - /bin/ln - - /usr/bin/ln -- - ln - - -s - - /bin/cp - - /usr/bin/cp -- - ln - - -s - - /bin/systemctl - - /usr/bin/systemctl -- - ln - - -s - - /bin/mount - - /usr/bin/mount -- - ln - - -s - - /bin/bash - - /usr/bin/bash -- - ln - - -s - - /usr/sbin/useradd - - /usr/bin/useradd -- - systemctl - - disable - - --now - - resolvconf.service -- - systemctl - - mask - - --now - - lxc-net.service -- - systemctl - - disable - - --now - - unscd.service -- - systemctl - - stop - - --now - - unscd.service -- sed -i "s/^Port 22$/Port 22\nPort 2222/1" /etc/ssh/sshd_config -- service ssh restart -- /opt/azure/containers/setup_ephemeral_disk.sh -- - tar - - czf - - /etc/docker.tar.gz - - -C - - /tmp/xtoph - - .docker -- - rm - - -rf - - /tmp/xtoph -- /opt/azure/containers/provision.sh -- - cp - - -p - - /etc/resolv.conf - - /tmp/resolv.conf -- - rm - - -f - - /etc/resolv.conf -- - cp - - -p - - /tmp/resolv.conf - - /etc/resolv.conf -- - systemctl - - start - - dcos-docker-install.service -- - systemctl - - start - - dcos-config-writer.service -- - systemctl - - restart - - systemd-journald.service -- - systemctl - - restart - - docker.service -- - systemctl - - start - - dcos-link-env.service -- - systemctl - - enable - - dcos-setup.service -- - systemctl - - --no-block - - start - - dcos-setup.service -write_files: -- content: '{{{dcosRepositoryURL}}} - -' - owner: root - path: /etc/mesosphere/setup-flags/repository-url - permissions: '0644' -- content: '["3dt--4eb6a10d16421bc87cb6e93ac97746f36aded925", "adminrouter--31f3f6390c8ef79a2774f42390d6340a24d67f08", - "avro-cpp--6194e9a67928c357c1c1b2bb409536ceef888e04", "boost-libs--2015ccb58fb756f61c02ee6aa05cc1e27459a9ec", - "bootstrap--d50592de9bf45937df7bcc7008e84a8739239c99", "boto--471853efd730e52e4ed7bfb890587432a576982a", - "check-time--be7d0ba757ec87f9965378fee7c76a6ee5ae996d", "cni--e48337da39a8cd379414acfe0da52a9226a10d24", - "cosmos--74e0339c91c278622d9f45b5fb0771872f443140", "curl--e7fd5880e4f94db05692d7e43279d8fe6348cb21", - "dcos-config--setup_{{{dcosProviderPackageID}}}", "dcos-history--787ce2fd81cb7469590c12951033f0482e879d2a", - "dcos-image--078703170a2f218447abea4b1be00b7431b340f1", "dcos-image-deps--5512ff49cdbba7f404759a5751a4ab1eae44c677", - "dcos-integration-test--bad12974ed31ace44432ad9a451c5b5dc3e20e81", "dcos-log--4d630df863228f38c6333e44670b4c4b20a74832", - "dcos-metadata--setup_{{{dcosProviderPackageID}}}", "dcos-metrics--e65d65e1b65335efdaa6bf7609a671f4288e7af9", - "dcos-oauth--23d8ca77549c1ac6087c11c9f7e8f8a4fddfc948", "dcos-signal--5633dc8da7e864cb34e3d29ed13e6756c7a6df94", - "dcos-ui--6f4af319cf4dd9bb8366de22ec37775beaa96747", "dnspython--1118f0ffaa60e6a779d4614f0ed692d215005f0e", - "docker-gc--9737ec72de5d1edc71175028762f06fe22c8a48c", "dvdcli--5374dd4ffb519f1dcefdec89b2247e3404f2e2e3", - "erlang--984871e11f69e37aeb76a471d4a4b90e93fdf355", "exhibitor--300da0c612afcf27541dbc681da5de3a6408de7e", - "flask--2936647fa917d16ee289d34e61fd1afcc49157b5", "java--091eb5a0f3dcbd7762a43e84c3e2d6aac8891111", - "libevent--468f4ae789f659e452e8356a9d2309c4f41135a8", "libffi--83ce3bd7eda2ef089e57efd2bc16c144d5a1f094", - "libsodium--9ff915db08c6bba7d6738af5084e782b13c84bf8", "logrotate--7f7bc4416d3ad101d0c5218872858483b516be07", - "marathon--99d0cbc65da6be31872878174f3a28fa63d0fa34", "mesos--0c992033b8d43e00dc69f0c548c826d573c82642", - "mesos-dns--ca591a18f9b010999106285fedddd010606c0d06", "mesos-modules--4c176c23a4fd3670d059fec55e2d4c8c7dbf1f6c", - "metronome--138ec50cd4da05bce74b6cd2c84ae873c2bd67ab", "navstar--fdf7e79fdf210548d183badfde00d60c1a540257", - "ncurses--d889894b71aa1a5b311bafef0e85479025b4dacb", "octarine--4e37c062d2f145f9c2ce01d30dadf72c2aac5c4a", - "openssl--ef04a6f76f6e5e194c783bc129fdabad16816aff", "pkgpanda-api--220e45fbd93403f8b4fd7f9c8c3d5178aff6e34b", - "pkgpanda-role--f8a749a4a821476ad2ef7e9dd9d12b6a8c4643a4", "pytest--63ab7e9520e4da70202b81076880fcdf2c1236cf", - "python--3c96ab7f21312f4d7d54a9b901cfe6382aa66b8a", "python-azure-mgmt-resource--2313114eec2adcb37ef61082cd2cfdceabf5c21e", - "python-cryptography--39ee7d59411569700f3343e64c32e9711a83decc", "python-dateutil--d098c1933ca6d754a90734afd366d556cc3107a8", - "python-docopt--85e7726dbb777584a9f5d4dd7bd58ed8ca5466d8", "python-gunicorn--bd425f55abd9236b5ead7e68a3c40c39b8d75bb7", - "python-isodate--9a15007db453e141892966ebf50a9175ee0ba08b", "python-jinja2--9fbc35d1405f06f1959c54629ab7d443cef79076", - "python-kazoo--050358610274815ebacabcdfca874729e53f4e0b", "python-markupsafe--09c65e6cdedd4783137a203cbc1b5a64ef3124eb", - "python-passlib--27056b95ad1a067b7992402e679c6260e673a554", "python-pyyaml--5be319fd73348558d69a03fb6dcb134e9b7f4c48", - "python-requests--63e1c3f4f03efc4607a4c20c5492026a9af7a9c7", "python-retrying--692b1a298d22436e25b2d14fc4f980be444adbe7", - "python-tox--7962137d89dae9eb45dd80b0ea59731fa3f5bbc9", "rexray--f07795e2c10f9a1a27de9d8e67ab171029db2e1d", - "six--9229b1a9d7d57bc086fa50f73fc9a753d9a4605d", "spartan--3dc1785bf698e65ceb2fecf26b2a439de219269f", - "strace--7d01796d64994451c1b2b82d161a335cbe90569b", "teamcity-messages--d13bc3f52ed0e30de3a71d86ff8718984b60b65f", - "toybox--c0e85790eb8aaeefe5037b053c2fcd140ab800a4"] - -' - owner: root - path: /etc/mesosphere/setup-flags/cluster-packages.json - permissions: '0644' -- content: | - [Journal] - MaxLevelConsole=warning - RateLimitInterval=1s - RateLimitBurst=20000 - owner: root - path: /etc/systemd/journald.conf.d/dcos.conf - permissions: '0644' -- content: | - rexray: - loglevel: info - modules: - default-admin: - host: tcp://127.0.0.1:61003 - default-docker: - disabled: true - path: /etc/rexray/config.yml - permissions: '0644' -- content: | - [Unit] - After=network-online.target - Wants=network-online.target - [Service] - Type=oneshot - Environment=DEBIAN_FRONTEND=noninteractive - StandardOutput=journal+console - StandardError=journal+console - ExecStartPre=/usr/bin/curl -fLsSv --retry 20 -Y 100000 -y 60 -o /var/tmp/d.deb https://az837203.vo.msecnd.net/dcos-deps/docker-engine_1.13.1-0-ubuntu-xenial_amd64.deb - ExecStart=/usr/bin/bash -c "try=1;until dpkg -D3 -i /var/tmp/d.deb || ((try>9));do echo retry $((try++));sleep $((try*try));done;systemctl --now start docker;systemctl restart docker.socket" - path: /etc/systemd/system/dcos-docker-install.service - permissions: '0644' -- content: | - [Service] - Restart=always - StartLimitInterval=0 - RestartSec=15 - LimitNOFILE=16384 - ExecStartPre=-/sbin/ip link del docker0 - ExecStart= - ExecStart=/usr/bin/docker daemon -H fd:// --storage-driver=overlay - path: /etc/systemd/system/docker.service.d/execstart.conf - permissions: '0644' -- content: | - [Unit] - PartOf=docker.service - [Socket] - ListenStream=/var/run/docker.sock - SocketMode=0660 - SocketUser=root - SocketGroup=docker - ListenStream=2375 - BindIPv6Only=both - [Install] - WantedBy=sockets.target - path: /etc/systemd/system/docker.socket - permissions: '0644' - content: | - [Unit] - Requires=dcos-setup.service - After=dcos-setup.service - [Service] - Type=oneshot - EnvironmentFile=/etc/environment - EnvironmentFile=/opt/mesosphere/environment - ExecStart=/usr/bin/bash -c "echo $(detect_ip) $(hostname) > /etc/hosts" - path: /etc/systemd/system/dcos-config-writer.service - permissions: '0644' -- content: | - "bound_values": - "adminrouter_auth_enabled": |- - {{{oauthEnabled}}} - "cluster_name": |- - {{{masterPublicIPAddressName}}} - "exhibitor_azure_account_key": |- - ', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('masterStorageAccountExhibitorName')), '2015-06-15').key1, ' - "exhibitor_azure_account_name": |- - {{{masterStorageAccountExhibitorName}}} - "exhibitor_azure_prefix": |- - {{{masterPublicIPAddressName}}} - "master_list": |- - ["', DCOSCUSTOMDATAPUBLICIPSTR'"] - "oauth_enabled": |- - {{{oauthEnabled}}} - "late_bound_package_id": |- - dcos-provider-{{{dcosProviderPackageID}}}-azure--setup - owner: root - path: /etc/mesosphere/setup-flags/late-config.yaml - permissions: '0644' -- content: | - [Unit] - Before=dcos.target - [Service] - Type=oneshot - StandardOutput=journal+console - StandardError=journal+console - ExecStartPre=/usr/bin/mkdir -p /etc/profile.d - ExecStart=/usr/bin/ln -sf /opt/mesosphere/bin/add_dcos_path.sh /etc/profile.d/dcos.sh - path: /etc/systemd/system/dcos-link-env.service - permissions: '0644' -- content: | - [Unit] - Description=Pkgpanda: Download DC/OS to this host. - After=network-online.target - Wants=network-online.target - ConditionPathExists=!/opt/mesosphere/ - [Service] - Type=oneshot - StandardOutput=journal+console - StandardError=journal+console - ExecStartPre=/usr/bin/curl --keepalive-time 2 -fLsSv --retry 20 -Y 100000 -y 60 -o //var/tmp/bootstrap.tar.xz {{{dcosBootstrapURL}}} - ExecStartPre=/usr/bin/mkdir -p /opt/mesosphere - ExecStart=/usr/bin/tar -axf //var/tmp/bootstrap.tar.xz -C /opt/mesosphere - ExecStartPost=-/usr/bin/rm -f //var/tmp/bootstrap.tar.xz - path: /etc/systemd/system/dcos-download.service - permissions: '0644' -- content: | - [Unit] - Description=Pkgpanda: Specialize DC/OS for this host. - Requires=dcos-download.service - After=dcos-download.service - [Service] - Type=oneshot - StandardOutput=journal+console - StandardError=journal+console - EnvironmentFile=/opt/mesosphere/environment - ExecStart=/opt/mesosphere/bin/pkgpanda setup --no-block-systemd - [Install] - WantedBy=multi-user.target - path: /etc/systemd/system/dcos-setup.service - permissions: '0644' -- content: '' - path: /etc/mesosphere/roles/azure -- content: 'PROVISION_STR' - path: "/opt/azure/containers/provision.sh" - permissions: "0744" - owner: "root" -- path: /var/lib/dcos/mesos-slave-common - content: 'ATTRIBUTES_STR' - permissions: "0644" - owner: "root" -- content: '{ "auths": { "{{{registry}}}": { "auth" : "{{{registryKey}}}" } } }' - path: "/tmp/xtoph/.docker/config.json" - owner: "root" -- content: | - #!/bin/bash - # Check the partitions on /dev/sdb created by cloudinit and force a detach and - # reformat of the parition. After which, all will be remounted. - EPHEMERAL_DISK="/dev/sdb" - PARTITIONS=`fdisk -l $EPHEMERAL_DISK | grep "^$EPHEMERAL_DISK" | cut -d" " -f1 | sed "s~$EPHEMERAL_DISK~~"` - if [ -n "$PARTITIONS" ]; then - for f in $PARTITIONS; do - df -k | grep "/dev/sdb$f" - if [ $? -eq 0 ]; then - umount -f /dev/sdb$f - fi - mkfs.ext4 /dev/sdb$f - done - mount -a - fi - # If there is a /var/tmp partition on the ephemeral disk, create a symlink such - # that the /var/log/mesos and /var/log/journal placed on the ephemeral disk. - VAR_TMP_PARTITION=`df -P /var/tmp | tail -1 | cut -d" " -f 1` - echo $VAR_TMP_PARTITION | grep "^$EPHEMERAL_DISK" - if [ $? -eq 0 ]; then - # Handle the /var/log/mesos directory - mkdir -p /var/tmp/log/mesos - if [ -d "/var/log/mesos" ]; then - cp -rp /var/log/mesos/* /var/tmp/log/mesos/ - rm -rf /var/log/mesos - fi - ln -s /var/tmp/log/mesos /var/log/mesos - # Handle the /var/log/journal direcotry - mkdir -p /var/tmp/log/journal - if [ -d "/var/log/journal" ]; then - cp -rp /var/log/journal/* /var/tmp/log/journal/ - rm -rf /var/log/journal - fi - ln -s /var/tmp/log/journal /var/log/journal - fi - path: "/opt/azure/containers/setup_ephemeral_disk.sh" - permissions: "0744" - owner: "root" diff --git a/parts/dcos/dcosmasterresources.t b/parts/dcos/dcosmasterresources.t deleted file mode 100644 index 44dcfb2f83..0000000000 --- a/parts/dcos/dcosmasterresources.t +++ /dev/null @@ -1,423 +0,0 @@ -{{if .MasterProfile.IsManagedDisks}} - { - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", - "location": "[variables('location')]", - "name": "[variables('masterAvailabilitySet')]", - "properties": { - "platformFaultDomainCount": 2, - "platformUpdateDomainCount": 3, - "managed": "true" - }, - "type": "Microsoft.Compute/availabilitySets" - }, -{{else if .MasterProfile.IsStorageAccount}} - { - "apiVersion": "[variables('apiVersionStorage')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('masterStorageAccountName')]", - "properties": { - "accountType": "[variables('vmSizesMap')[variables('masterVMSize')].storageAccountType]" - }, - "type": "Microsoft.Storage/storageAccounts" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('masterAvailabilitySet')]", - "properties": {}, - "type": "Microsoft.Compute/availabilitySets" - }, -{{end}} - { - "apiVersion": "[variables('apiVersionStorage')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('masterStorageAccountExhibitorName')]", - "properties": { - "accountType": "Standard_LRS" - }, - "type": "Microsoft.Storage/storageAccounts" - }, -{{if not .MasterProfile.IsCustomVNET}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - {{GetVNETSubnetDependencies}} - ], - "location": "[variables('location')]", - "name": "[variables('virtualNetworkName')]", - "properties": { - "addressSpace": { - "addressPrefixes": [ - {{GetVNETAddressPrefixes}} - ] - }, - "subnets": [ - {{GetVNETSubnets true}} - ] - }, - "type": "Microsoft.Network/virtualNetworks" - }, -{{end}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('masterPublicIPAddressName')]", - "properties": { - "dnsSettings": { - "domainNameLabel": "[variables('masterEndpointDNSNamePrefix')]" - }, - "publicIPAllocationMethod": "Dynamic" - }, - "type": "Microsoft.Network/publicIPAddresses" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('masterLbName')]", - "properties": { - "backendAddressPools": [ - { - "name": "[variables('masterLbBackendPoolName')]" - } - ], - "frontendIPConfigurations": [ - { - "name": "[variables('masterLbIPConfigName')]", - "properties": { - "publicIPAddress": { - "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('masterPublicIPAddressName'))]" - } - } - } - ] -{{if .MasterProfile.OAuthEnabled}} - ,"loadBalancingRules": [ - { - "name": "LBRule443", - "properties": { - "frontendIPConfiguration": { - "id": "[variables('masterLbIPConfigID')]" - }, - "frontendPort": 443, - "backendPort": 443, - "enableFloatingIP": false, - "idleTimeoutInMinutes": 4, - "protocol": "Tcp", - "loadDistribution": "Default", - "backendAddressPool": { - "id": "[concat(variables('masterLbID'), '/backendAddressPools/', variables('masterLbBackendPoolName'))]" - }, - "probe": { - "id": "[concat(variables('masterLbID'),'/probes/dcosMasterProbe')]" - } - } - }, - { - "name": "LBRule80", - "properties": { - "frontendIPConfiguration": { - "id": "[variables('masterLbIPConfigID')]" - }, - "frontendPort": 80, - "backendPort": 80, - "enableFloatingIP": false, - "idleTimeoutInMinutes": 4, - "protocol": "Tcp", - "loadDistribution": "Default", - "backendAddressPool": { - "id": "[concat(variables('masterLbID'), '/backendAddressPools/', variables('masterLbBackendPoolName'))]" - }, - "probe": { - "id": "[concat(variables('masterLbID'),'/probes/dcosMasterProbe')]" - } - } - } - ], - "probes": [ - { - "name": "dcosMasterProbe", - "properties": { - "protocol": "Http", - "port": 5050, - "requestPath": "/health", - "intervalInSeconds": 5, - "numberOfProbes": 2 - } - } - ] -{{end}} - }, - "type": "Microsoft.Network/loadBalancers" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "copy": { - "count": "[variables('masterCount')]", - "name": "masterLbLoopNode" - }, - "dependsOn": [ - "[variables('masterLbID')]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('masterLbName'), '/', 'SSH-', variables('masterVMNamePrefix'), copyIndex())]", - "properties": { - "backendPort": 22, - "enableFloatingIP": false, - "frontendIPConfiguration": { - "id": "[variables('masterLbIPConfigID')]" - }, - "frontendPort": "[copyIndex(2200)]", - "protocol": "tcp" - }, - "type": "Microsoft.Network/loadBalancers/inboundNatRules" - }, -{{if IsDCOS19}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[variables('masterLbID')]" - ], - "location": "[resourceGroup().location]", - - "name": "[concat(variables('masterLbName'), '/', 'SSHPort22-', variables('masterVMNamePrefix'), '0')]", - "properties": { - "backendPort": 2222, - "enableFloatingIP": false, - "frontendIPConfiguration": { - "id": "[variables('masterLbIPConfigID')]" - }, - "frontendPort": "22", - "protocol": "tcp" - }, - "type": "Microsoft.Network/loadBalancers/inboundNatRules" - }, -{{end}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('masterNSGName')]", - "properties": { - "securityRules": [ -{{if IsDCOS19}} - { - "properties": { - "priority": 201, - "access": "Allow", - "direction": "Inbound", - "destinationPortRange": "2222", - "sourcePortRange": "*", - "destinationAddressPrefix": "*", - "protocol": "Tcp", - "description": "Allow SSH", - "sourceAddressPrefix": "*" - }, - "name": "sshPort22" - }, -{{if .MasterProfile.OAuthEnabled}} - { - "name": "http", - "properties": { - "protocol": "Tcp", - "sourcePortRange": "*", - "destinationPortRange": "80", - "sourceAddressPrefix": "[variables('masterHttpSourceAddressPrefix')]", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 202, - "direction": "Inbound" - } - }, - { - "name": "https", - "properties": { - "protocol": "Tcp", - "sourcePortRange": "*", - "destinationPortRange": "443", - "sourceAddressPrefix": "[variables('masterHttpSourceAddressPrefix')]", - "destinationAddressPrefix": "*", - "access": "Allow", - "priority": 203, - "direction": "Inbound" - } - }, -{{end}} -{{end}} - { - "properties": { - "priority": 200, - "access": "Allow", - "direction": "Inbound", - "destinationPortRange": "22", - "sourcePortRange": "*", - "destinationAddressPrefix": "*", - "protocol": "Tcp", - "description": "Allow SSH", - "sourceAddressPrefix": "*" - }, - "name": "ssh" - } - ] - }, - "type": "Microsoft.Network/networkSecurityGroups" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "copy": { - "count": "[variables('masterCount')]", - "name": "nicLoopNode" - }, - "dependsOn": [ - "[variables('masterNSGID')]", -{{if not .MasterProfile.IsCustomVNET}} - "[variables('vnetID')]", -{{end}} - "[variables('masterLbID')]", -{{if IsDCOS19}} - "[concat(variables('masterLbID'),'/inboundNatRules/SSHPort22-',variables('masterVMNamePrefix'),0)]", -{{end}} - "[concat(variables('masterLbID'),'/inboundNatRules/SSH-',variables('masterVMNamePrefix'),copyIndex())]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('masterVMNamePrefix'), 'nic-', copyIndex())]", - "properties": { - "ipConfigurations": [ - { - "name": "ipConfigNode", - "properties": { - "loadBalancerBackendAddressPools": [ - { - "id": "[concat(variables('masterLbID'), '/backendAddressPools/', variables('masterLbBackendPoolName'))]" - } - ], -{{if IsDCOS19}} - "loadBalancerInboundNatRules": "[variables('masterLbInboundNatRules')[copyIndex()]]", -{{else}} - "loadBalancerInboundNatRules": [ - { - "id": "[concat(variables('masterLbID'),'/inboundNatRules/SSH-',variables('masterVMNamePrefix'),copyIndex())]" - } - ], -{{end}} - "privateIPAddress": "[concat(variables('masterFirstAddrPrefix'), copyIndex(int(variables('masterFirstAddrOctet4'))))]", - "privateIPAllocationMethod": "Static", - "subnet": { - "id": "[variables('masterVnetSubnetID')]" - } - } - } - ] - ,"networkSecurityGroup": { - "id": "[variables('masterNSGID')]" - } - }, - "type": "Microsoft.Network/networkInterfaces" - }, - { -{{if .MasterProfile.IsManagedDisks}} - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", -{{else}} - "apiVersion": "[variables('apiVersionDefault')]", -{{end}} - "copy": { - "count": "[variables('masterCount')]", - "name": "vmLoopNode" - }, - "dependsOn": [ - "[concat('Microsoft.Network/networkInterfaces/', variables('masterVMNamePrefix'), 'nic-', copyIndex())]", - "[concat('Microsoft.Compute/availabilitySets/',variables('masterAvailabilitySet'))]", -{{if .MasterProfile.IsStorageAccount}} - "[variables('masterStorageAccountName')]", -{{end}} - "[variables('masterStorageAccountExhibitorName')]" - ], - "tags": - { - "creationSource" : "[concat('acsengine-', variables('masterVMNamePrefix'), copyIndex())]" - }, - "location": "[variables('location')]", - "name": "[concat(variables('masterVMNamePrefix'), copyIndex())]", - "properties": { - "availabilitySet": { - "id": "[resourceId('Microsoft.Compute/availabilitySets',variables('masterAvailabilitySet'))]" - }, - "hardwareProfile": { - "vmSize": "[variables('masterVMSize')]" - }, - "networkProfile": { - "networkInterfaces": [ - { - "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(variables('masterVMNamePrefix'), 'nic-', copyIndex()))]" - } - ] - }, - "osProfile": { - "adminUsername": "[variables('adminUsername')]", - "computername": "[concat(variables('masterVMNamePrefix'), copyIndex())]", - {{GetDCOSMasterCustomData}} - "linuxConfiguration": { - "disablePasswordAuthentication": "true", - "ssh": { - "publicKeys": [ - { - "keyData": "[variables('sshRSAPublicKey')]", - "path": "[variables('sshKeyPath')]" - } - ] - } - } - {{if .LinuxProfile.HasSecrets}} - , - "secrets": "[variables('linuxProfileSecrets')]" - {{end}} - }, - "storageProfile": { - "imageReference": { - "offer": "[variables('osImageOffer')]", - "publisher": "[variables('osImagePublisher')]", - "sku": "[variables('osImageSKU')]", - "version": "[variables('osImageVersion')]" - }, - "osDisk": { - "caching": "ReadWrite" - ,"createOption": "FromImage" -{{if .MasterProfile.IsStorageAccount}} - ,"name": "[concat(variables('masterVMNamePrefix'), copyIndex(),'-osdisk')]" - ,"vhd": { - "uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('masterStorageAccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'vhds/',variables('masterVMNamePrefix'),copyIndex(),'-osdisk.vhd')]" - } -{{end}} -{{if ne .MasterProfile.OSDiskSizeGB 0}} - ,"diskSizeGB": {{.MasterProfile.OSDiskSizeGB}} -{{end}} - } - } - }, - "type": "Microsoft.Compute/virtualMachines" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[concat('Microsoft.Compute/virtualMachines/', variables('masterVMNamePrefix'), sub(variables('masterCount'), 1))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('masterVMNamePrefix'), sub(variables('masterCount'), 1), '/waitforleader')]", - "properties": { - "autoUpgradeMinorVersion": true, - "publisher": "Microsoft.OSTCExtensions", - "settings": { - "commandToExecute": "sh -c 'until ping -c1 leader.mesos;do echo waiting for leader.mesos;sleep 15;done;echo leader.mesos up'" - }, - "type": "CustomScriptForLinux", - "typeHandlerVersion": "1.4" - }, - "type": "Microsoft.Compute/virtualMachines/extensions" - }{{WriteLinkedTemplatesForExtensions}} diff --git a/parts/dcos/dcosmastervars.t b/parts/dcos/dcosmastervars.t deleted file mode 100644 index edceafe714..0000000000 --- a/parts/dcos/dcosmastervars.t +++ /dev/null @@ -1,149 +0,0 @@ - "adminUsername": "[parameters('linuxAdminUsername')]", - "targetEnvironment": "[parameters('targetEnvironment')]", - "maxVMsPerPool": 100, - "apiVersionDefault": "2016-03-30", - "apiVersionLinkDefault": "2015-01-01", - "singleQuote": "'", - "doubleSingleQuote": "''", -{{if .LinuxProfile.HasSecrets}} - "linuxProfileSecrets" : - [ - {{range $vIndex, $vault := .LinuxProfile.Secrets}} - {{if $vIndex}} , {{end}} - { - "sourceVault":{ - "id":"[parameters('linuxKeyVaultID{{$vIndex}}')]" - }, - "vaultCertificates":[ - {{range $cIndex, $cert := $vault.VaultCertificates}} - {{if $cIndex}} , {{end}} - { - "certificateUrl" :"[parameters('linuxKeyVaultID{{$vIndex}}CertificateURL{{$cIndex}}')]" - } - {{end}} - ] - } - {{end}} - ], -{{end}} - "orchestratorVersion": "{{.OrchestratorProfile.OrchestratorVersion}}", -{{if .HasWindows}} - "windowsAdminUsername": "[parameters('windowsAdminUsername')]", - "windowsAdminPassword": "[parameters('windowsAdminPassword')]", - "agentWindowsBackendPort": 3389, - "agentWindowsPublisher": "[parameters('agentWindowsPublisher')]", - "agentWindowsOffer": "[parameters('agentWindowsOffer')]", - "agentWindowsSku": "[parameters('agentWindowsSku')]", - "agentWindowsVersion": "[parameters('agentWindowsVersion')]", - "dcosWindowsBootstrapURL" : "[parameters('dcosWindowsBootstrapURL')]", - "windowsCustomScriptSuffix": " $inputFile = '%SYSTEMDRIVE%\\AzureData\\CustomData.bin' ; $outputFile = '%SYSTEMDRIVE%\\AzureData\\dcosWindowsProvision.ps1' ; $inputStream = New-Object System.IO.FileStream $inputFile, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read) ; $sr = New-Object System.IO.StreamReader(New-Object System.IO.Compression.GZipStream($inputStream, [System.IO.Compression.CompressionMode]::Decompress)) ; $sr.ReadToEnd() | Out-File($outputFile) ; Invoke-Expression('{0} {1}' -f $outputFile, $arguments) ; ", - "windowsMasterCustomScriptArguments": "[concat('$arguments = ', variables('singleQuote'),'-MasterCount ', variables('masterCount'), ' -firstMasterIP ', parameters('firstConsecutiveStaticIP'), variables('singleQuote'), ' ; ')]", - - "windowsMasterCustomScript": "[concat('powershell.exe -ExecutionPolicy Unrestricted -command \"', variables('windowsMasterCustomScriptArguments'), variables('windowsCustomScriptSuffix'), '\" > %SYSTEMDRIVE%\\AzureData\\dcosWindowsProvision.log 2>&1')]", -{{end}} - "masterAvailabilitySet": "[concat(variables('orchestratorName'), '-master-availabilitySet-', variables('nameSuffix'))]", - "masterCount": {{.MasterProfile.Count}}, - "masterEndpointDNSNamePrefix": "[tolower(parameters('masterEndpointDNSNamePrefix'))]", - "masterHttpSourceAddressPrefix": "{{.MasterProfile.HTTPSourceAddressPrefix}}", - "masterLbBackendPoolName": "[concat(variables('orchestratorName'), '-master-pool-', variables('nameSuffix'))]", - "masterLbID": "[resourceId('Microsoft.Network/loadBalancers',variables('masterLbName'))]", - "masterLbIPConfigID": "[concat(variables('masterLbID'),'/frontendIPConfigurations/', variables('masterLbIPConfigName'))]", - "masterLbIPConfigName": "[concat(variables('orchestratorName'), '-master-lbFrontEnd-', variables('nameSuffix'))]", - "masterLbName": "[concat(variables('orchestratorName'), '-master-lb-', variables('nameSuffix'))]", - "masterNSGID": "[resourceId('Microsoft.Network/networkSecurityGroups',variables('masterNSGName'))]", - "masterNSGName": "[concat(variables('orchestratorName'), '-master-nsg-', variables('nameSuffix'))]", - "masterPublicIPAddressName": "[concat(variables('orchestratorName'), '-master-ip-', variables('masterEndpointDNSNamePrefix'), '-', variables('nameSuffix'))]", - "apiVersionStorage": "2015-06-15", - - "storageAccountBaseName": "[uniqueString(concat(variables('masterEndpointDNSNamePrefix'),variables('location'),variables('orchestratorName')))]", - "masterStorageAccountExhibitorName": "[concat(variables('storageAccountBaseName'), 'exhb0')]", - "storageAccountType": "Standard_LRS", -{{if .HasStorageAccountDisks}} - "maxVMsPerStorageAccount": 20, - "maxStorageAccountsPerAgent": "[div(variables('maxVMsPerPool'),variables('maxVMsPerStorageAccount'))]", - "dataStorageAccountPrefixSeed": 97, - "storageAccountPrefixes": [ "0", "6", "c", "i", "o", "u", "1", "7", "d", "j", "p", "v", "2", "8", "e", "k", "q", "w", "3", "9", "f", "l", "r", "x", "4", "a", "g", "m", "s", "y", "5", "b", "h", "n", "t", "z" ], - "storageAccountPrefixesCount": "[length(variables('storageAccountPrefixes'))]", - {{GetSizeMap}}, -{{else}} - "storageAccountPrefixes": [], -{{end}} -{{if .HasManagedDisks}} - "apiVersionStorageManagedDisks": "2016-04-30-preview", -{{end}} -{{if .MasterProfile.IsStorageAccount}} - "masterStorageAccountName": "[concat(variables('storageAccountBaseName'), 'mstr0')]", -{{end}} -{{if .MasterProfile.IsCustomVNET}} - "masterVnetSubnetID": "[parameters('masterVnetSubnetID')]", -{{else}} - "masterSubnet": "[parameters('masterSubnet')]", - "masterSubnetName": "[concat(variables('orchestratorName'), '-masterSubnet')]", - "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]", - "masterVnetSubnetID": "[concat(variables('vnetID'),'/subnets/',variables('masterSubnetName'))]", - "virtualNetworkName": "[concat(variables('orchestratorName'), '-vnet-', variables('nameSuffix'))]", -{{end}} - "masterFirstAddrOctets": "[split(parameters('firstConsecutiveStaticIP'),'.')]", - "masterFirstAddrOctet4": "[variables('masterFirstAddrOctets')[3]]", - "masterFirstAddrPrefix": "[concat(variables('masterFirstAddrOctets')[0],'.',variables('masterFirstAddrOctets')[1],'.',variables('masterFirstAddrOctets')[2],'.')]", - "masterVMNamePrefix": "[concat(variables('orchestratorName'), '-master-', variables('nameSuffix'), '-')]", - "masterVMNic": [ - "[concat(variables('masterVMNamePrefix'), 'nic-0')]", - "[concat(variables('masterVMNamePrefix'), 'nic-1')]", - "[concat(variables('masterVMNamePrefix'), 'nic-2')]", - "[concat(variables('masterVMNamePrefix'), 'nic-3')]", - "[concat(variables('masterVMNamePrefix'), 'nic-4')]", - "[concat(variables('masterVMNamePrefix'), 'nic-5')]", - "[concat(variables('masterVMNamePrefix'), 'nic-6')]" - ], - "masterVMSize": "[parameters('masterVMSize')]", - "nameSuffix": "[parameters('nameSuffix')]", - "oauthEnabled": "{{.MasterProfile.OAuthEnabled}}", - "orchestratorName": "dcos", - "osImageOffer": "[parameters('osImageOffer')]", - "osImagePublisher": "[parameters('osImagePublisher')]", - "osImageSKU": "[parameters('osImageSKU')]", - "osImageVersion": "[parameters('osImageVersion')]", - "sshKeyPath": "[concat('/home/', variables('adminUsername'), '/.ssh/authorized_keys')]", - "sshRSAPublicKey": "[parameters('sshRSAPublicKey')]", - "locations": [ - "[resourceGroup().location]", - "[parameters('location')]" - ], - "location": "[variables('locations')[mod(add(2,length(parameters('location'))),add(1,length(parameters('location'))))]]", -{{if IsDCOS19}} - "masterSshInboundNatRuleIdPrefix": "[concat(variables('masterLbID'),'/inboundNatRules/SSH-',variables('masterVMNamePrefix'))]", - "masterSshPort22InboundNatRuleIdPrefix": "[concat(variables('masterLbID'),'/inboundNatRules/SSHPort22-',variables('masterVMNamePrefix'))]", - "masterLbInboundNatRules": [ - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'0')]" - }, - { - "id": "[concat(variables('masterSshPort22InboundNatRuleIdPrefix'),'0')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'1')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'2')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'3')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'4')]" - } - ] - ], -{{end}} - "dcosBootstrapURL": "[parameters('dcosBootstrapURL')]" - diff --git a/parts/dcos/dcosparams.t b/parts/dcos/dcosparams.t deleted file mode 100644 index 5d87d8d47f..0000000000 --- a/parts/dcos/dcosparams.t +++ /dev/null @@ -1,35 +0,0 @@ - "dcosBootstrapURL": { - "defaultValue": "https://dcosio.azureedge.net/dcos/stable/bootstrap/58fd0833ce81b6244fc73bf65b5deb43217b0bd7.bootstrap.tar.xz", - "metadata": { - "description": "The default mesosphere bootstrap package." - }, - "type": "string" - }, - "dcosWindowsBootstrapURL": { - "defaultValue": "http://dcos-win.westus.cloudapp.azure.com/dcos-windows/stable/", - "metadata": { - "description": "The default mesosphere bootstrap package location for windows." - }, - "type": "string" - }, - "dcosRepositoryURL": { - "defaultValue": "https://dcosio.azureedge.net/dcos/stable", - "metadata": { - "description": "The repository URL" - }, - "type": "string" - }, - "dcosClusterPackageListID": { - "defaultValue": "77282d8864a5bf36db345b54a0d1de3674a0e937", - "metadata": { - "description": "The default cluster package list IDs." - }, - "type": "string" - }, - "dcosProviderPackageID": { - "defaultValue": "", - "metadata": { - "description": "The guid for provider dcos-provider package." - }, - "type": "string" - }, diff --git a/parts/dcos/dcosprovision.sh b/parts/dcos/dcosprovision.sh deleted file mode 100644 index 7a5d785e3f..0000000000 --- a/parts/dcos/dcosprovision.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -MESOSDIR=/var/lib/mesos/dl -mkdir $MESOSDIR - -# load the env vars -. /etc/mesosphere/setup-flags/dcos-deploy-environment - -# default dc/os component download address (Azure CDN) -DOCKER_ENGINE_DOWNLOAD_URL=https://mesosphere.blob.core.windows.net/dcos-deps/docker-engine_1.13.1-0-ubuntu-xenial_amd64.deb -LIBIPSET_DOWNLOAD_URL=https://az837203.vo.msecnd.net/dcos-deps/libipset3_6.29-1_amd64.deb -IPSET_DOWNLOAD_URL=https://az837203.vo.msecnd.net/dcos-deps/ipset_6.29-1_amd64.deb -UNZIP_DOWNLOAD_URL=https://az837203.vo.msecnd.net/dcos-deps/unzip_6.0-20ubuntu1_amd64.deb -LIBLTDL_DOWNLOAD_URL=https://az837203.vo.msecnd.net/dcos-deps/libltdl7_2.4.6-0.1_amd64.deb - -case $DCOS_ENVIRONMENT in - # because of Chinese GreatWall Firewall, the default packages on Azure CDN is blocked. So the following Chinese local mirror url should be used instead. - AzureChinaCloud) - DOCKER_ENGINE_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/docker-engine_1.11.2-0~xenial_amd64.deb - LIBIPSET_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/libipset3_6.29-1_amd64.deb - IPSET_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/ipset_6.29-1_amd64.deb - UNZIP_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/unzip_6.0-20ubuntu1_amd64.deb - LIBLTDL_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/libltdl7_2.4.6-0.1_amd64.deb - ;; -esac - -curl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/d.deb $DOCKER_ENGINE_DOWNLOAD_URL & -curl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/1.deb $LIBIPSET_DOWNLOAD_URL & -curl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/2.deb $IPSET_DOWNLOAD_URL & -curl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/3.deb $UNZIP_DOWNLOAD_URL & -curl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/4.deb $LIBLTDL_DOWNLOAD_URL & -wait - -for i in {1..300}; do - dpkg -i $MESOSDIR/{1,2,3,4}.deb - if [ "$?" = "0" ] - then - echo "succeeded" - break - fi - sleep 1 -done - -ROLESFILECONTENTS - -# add Azure update domain and fault domain attributes -ud=$( curl -H Metadata:true "http://169.254.169.254/metadata/instance/compute/platformUpdateDomain?api-version=2017-04-02&format=text" ) -fd=$( curl -H Metadata:true "http://169.254.169.254/metadata/instance/compute/platformFaultDomain?api-version=2017-04-02&format=text" ) -echo ";azure.faultdomain:$fd;azure.updatedomain:$ud" >> /var/lib/dcos/mesos-slave-common \ No newline at end of file diff --git a/parts/dcos/dcosprovisionsource.sh b/parts/dcos/dcosprovisionsource.sh deleted file mode 100755 index 8233b77af2..0000000000 --- a/parts/dcos/dcosprovisionsource.sh +++ /dev/null @@ -1,58 +0,0 @@ -function retry_download() { - retries=$1; wait_sleep=$2; timeout=$3; url=$4; path=$5 checksum=$6 - for i in $(seq 1 $retries); do - rm -f $path - timeout $timeout curl -fsSL $url -o $path - if [ $? -ne 0 ]; then - echo "retry_download[$i] Error: Failed to execute curl -fsSL $url -o $path" - sleep $wait_sleep - continue - fi - if [ ! -z "${checksum:-}" ]; then - actual=$(sha1sum -b $path | cut -f 1 -d " ") - if [ $? -ne 0 ]; then - echo "retry_download[$i] Error: Failed to execute sha1sum -b $path (per $url)" - sleep $wait_sleep - continue - fi - if [ "$checksum" != "$actual" ]; then - echo "retry_download[$i] Error: sha1sum mismatch for $url" - sleep $wait_sleep - continue - fi - fi - return 0 - done - return 1 -} - -function retrycmd_if_failure() { - retries=$1; wait_sleep=$2; timeout=$3; shift && shift && shift - for i in $(seq 1 $retries); do - timeout $timeout ${@} - [ $? -eq 0 ] && break || \ - if [ $i -eq $retries ]; then - echo "Error: Failed to execute \"$@\" after $i attempts" - return 1 - else - sleep $wait_sleep - fi - done - echo Executed \"$@\" $i times; -} - -function retry_get_install_deb() { - retries=$1; wait_sleep=$2; timeout=$3; url=$4; checksum=$5 - deb=$(mktemp) - trap "rm -f $deb" RETURN - retry_download $retries $wait_sleep $timeout $url $deb $checksum - if [ $? -ne 0 ]; then - echo "Error: Failed to download $url" - return 1 - fi - retrycmd_if_failure $retries $wait_sleep $timeout dpkg -i $deb - if [ $? -ne 0 ]; then - echo "Error: Failed to install $url" - return 1 - fi -} diff --git a/parts/k8s/containeraddons/kubernetesmasteraddons-omsagent-daemonset.yaml b/parts/k8s/containeraddons/kubernetesmasteraddons-omsagent-daemonset.yaml index 230fcf10c7..947d86a3fa 100644 --- a/parts/k8s/containeraddons/kubernetesmasteraddons-omsagent-daemonset.yaml +++ b/parts/k8s/containeraddons/kubernetesmasteraddons-omsagent-daemonset.yaml @@ -136,7 +136,7 @@ spec: fieldRef: fieldPath: status.hostIP - name: ACS_RESOURCE_NAME - value: "my_acs_cluster_name" + value: "my_aks_cluster_name" - name: DISABLE_KUBE_SYSTEM_LOG_COLLECTION value: "true" - name: ISTEST diff --git a/parts/k8s/health-monitor.sh b/parts/k8s/health-monitor.sh index 5da9b7c26e..56315bcb2f 100755 --- a/parts/k8s/health-monitor.sh +++ b/parts/k8s/health-monitor.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # This script originated at https://github.com/kubernetes/kubernetes/blob/master/cluster/gce/gci/health-monitor.sh -# and has been modified for acs-engine. +# and has been modified for aks-engine. set -o nounset set -o pipefail diff --git a/parts/k8s/kubernetesagentresourcesvmas.t b/parts/k8s/kubernetesagentresourcesvmas.t index 41722082ed..52b0912cc6 100644 --- a/parts/k8s/kubernetesagentresourcesvmas.t +++ b/parts/k8s/kubernetesagentresourcesvmas.t @@ -5,44 +5,20 @@ "name": "loop" }, "dependsOn": [ -{{if not IsOpenShift}} {{if .IsCustomVNET}} "[variables('nsgID')]" {{else}} "[variables('vnetID')]" -{{end}} -{{else}} -{{if .IsCustomVNET}} - "[concat(variables('masterVMNamePrefix'), 'nic-0')]", -{{else}} - "[variables('vnetID')]", -{{end}} -{{if eq .Role "infra"}} - "[variables('routerLBName')]", - "[variables('routerNSGID')]" -{{else}} - "[variables('nsgID')]" -{{end}} {{end}} ], "location": "[variables('location')]", "name": "[concat(variables('{{.Name}}VMNamePrefix'), 'nic-', copyIndex(variables('{{.Name}}Offset')))]", "properties": { "enableAcceleratedNetworking" : "{{.AcceleratedNetworkingEnabled}}", -{{if not IsOpenShift}} {{if .IsCustomVNET}} "networkSecurityGroup": { "id": "[variables('nsgID')]" }, -{{end}} -{{else}} - "networkSecurityGroup": { - {{if eq .Role "infra"}} - "id": "[variables('routerNSGID')]" - {{else}} - "id": "[variables('nsgID')]" - {{end}} - }, {{end}} "ipConfigurations": [ {{range $seq := loop 1 .IPAddressCount}} @@ -164,7 +140,7 @@ "creationSource" : "[concat(parameters('generatorCode'), '-', variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')))]", "resourceNameSuffix" : "[parameters('nameSuffix')]", "orchestrator" : "[variables('orchestratorNameVersionTag')]", - "acsengineVersion" : "[parameters('acsengineVersion')]", + "aksengineVersion" : "[parameters('aksengineVersion')]", "poolName" : "{{.Name}}" }, "location": "[variables('location')]", @@ -183,13 +159,6 @@ }, {{end}} {{end}} - {{if and IsOpenShift (not (UseAgentCustomImage .))}} - "plan": { - "name": "[variables('{{.Name}}osImageSKU')]", - "publisher": "[variables('{{.Name}}osImagePublisher')]", - "product": "[variables('{{.Name}}osImageOffer')]" - }, - {{end}} "properties": { "availabilitySet": { "id": "[resourceId('Microsoft.Compute/availabilitySets',variables('{{.Name}}AvailabilitySet'))]" @@ -207,9 +176,7 @@ "osProfile": { "adminUsername": "[parameters('linuxAdminUsername')]", "computername": "[concat(variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')))]", - {{if not IsOpenShift}} {{GetKubernetesAgentCustomData .}} - {{end}} "linuxConfiguration": { "disablePasswordAuthentication": "true", "ssh": { @@ -328,11 +295,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - {{if IsOpenShift }} - "script": "{{ Base64 (OpenShiftGetNodeSh .) }}" - {{else}} "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $retries); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not BlockOutboundInternet}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}gcr.azk8s.cn 80{{else}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' GPU_NODE={{IsNSeriesSKU .}} /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1{{if CSERunInBackground }} &{{end}}\"')]" - {{end}} } } } @@ -359,4 +322,3 @@ } } {{end}} - diff --git a/parts/k8s/kubernetesbase.t b/parts/k8s/kubernetesbase.t index 1a177d6336..a220714660 100644 --- a/parts/k8s/kubernetesbase.t +++ b/parts/k8s/kubernetesbase.t @@ -50,9 +50,6 @@ ] }, {{end}} - {{if IsOpenShift}} - {{template "openshift/infraresources.t" .}} - {{end}} {{ range $index, $element := .AgentPoolProfiles}} {{if $index}}, {{end}} {{if .IsWindows}} diff --git a/parts/k8s/kubernetesmasterresources.t b/parts/k8s/kubernetesmasterresources.t index fdd82f9b93..d42ebe6245 100644 --- a/parts/k8s/kubernetesmasterresources.t +++ b/parts/k8s/kubernetesmasterresources.t @@ -41,11 +41,9 @@ "apiVersion": "[variables('apiVersionNetwork')]", "dependsOn": [ {{if RequireRouteTable}} - "[concat('Microsoft.Network/routeTables/', variables('routeTableName'))]"{{if not IsOpenShift}},{{end}} + "[concat('Microsoft.Network/routeTables/', variables('routeTableName'))]", {{end}} -{{if not IsOpenShift}} "[concat('Microsoft.Network/networkSecurityGroups/', variables('nsgName'))]" -{{end}} ], "location": "[variables('location')]", "name": "[variables('virtualNetworkName')]", @@ -60,12 +58,10 @@ "name": "[variables('subnetName')]", "properties": { "addressPrefix": "[parameters('masterSubnet')]" -{{if not IsOpenShift}} , "networkSecurityGroup": { "id": "[variables('nsgID')]" } -{{end}} {{if RequireRouteTable}} , "routeTable": { @@ -121,7 +117,7 @@ "access": "Allow", "description": "Allow kube-apiserver (tls) traffic to master", "destinationAddressPrefix": "*", - "destinationPortRange": {{if IsOpenShift}}"8443-8443"{{else}}"443-443"{{end}}, + "destinationPortRange": "443-443", "direction": "Inbound", "priority": 100, "protocol": "Tcp", @@ -218,8 +214,8 @@ "id": "[concat(variables('masterLbID'), '/backendAddressPools/', variables('masterLbBackendPoolName'))]" }, "protocol": "tcp", - "frontendPort": {{if IsOpenShift}}8443{{else}}443{{end}}, - "backendPort": {{if IsOpenShift}}8443{{else}}443{{end}}, + "frontendPort": 443, + "backendPort": 443, "enableFloatingIP": false, "idleTimeoutInMinutes": 5, "loadDistribution": "Default", @@ -234,7 +230,7 @@ "name": "tcpHTTPSProbe", "properties": { "protocol": "tcp", - "port": {{if IsOpenShift}}8443{{else}}443{{end}}, + "port": 443, "intervalInSeconds": "5", "numberOfProbes": "2" } @@ -272,17 +268,10 @@ "name": "nicLoopNode" }, "dependsOn": [ -{{if not IsOpenShift}} {{if .MasterProfile.IsCustomVNET}} "[variables('nsgID')]", {{else}} "[variables('vnetID')]", -{{end}} -{{else}} - "[variables('nsgID')]", -{{if not .MasterProfile.IsCustomVNET}} - "[variables('vnetID')]", -{{end}} {{end}} "[concat(variables('masterLbID'),'/inboundNatRules/SSH-',variables('masterVMNamePrefix'),copyIndex(variables('masterOffset')))]" {{if gt .MasterProfile.Count 1}} @@ -347,7 +336,7 @@ ] } {{end}} -{{if or .MasterProfile.IsCustomVNET IsOpenShift}} +{{if .MasterProfile.IsCustomVNET}} ,"networkSecurityGroup": { "id": "[variables('nsgID')]" } @@ -363,18 +352,11 @@ "name": "nicLoopNode" }, "dependsOn": [ - {{if not IsOpenShift}} {{if .MasterProfile.IsCustomVNET}} "[variables('nsgID')]" {{else}} "[variables('vnetID')]" {{end}} - {{else}} - "[variables('nsgID')]" - {{if not .MasterProfile.IsCustomVNET}} - ,"[variables('vnetID')]" - {{end}} - {{end}} {{if gt .MasterProfile.Count 1}} ,"[variables('masterInternalLbName')]" {{end}} @@ -430,7 +412,7 @@ ] } {{end}} - {{if or .MasterProfile.IsCustomVNET IsOpenShift}} + {{if .MasterProfile.IsCustomVNET}} ,"networkSecurityGroup": { "id": "[variables('nsgID')]" } @@ -623,12 +605,12 @@ "backendAddressPool": { "id": "[concat(variables('masterInternalLbID'), '/backendAddressPools/', variables('masterLbBackendPoolName'))]" }, - "backendPort": {{if IsOpenShift}}8443{{else}}4443{{end}}, + "backendPort": 443, "enableFloatingIP": false, "frontendIPConfiguration": { "id": "[variables('masterInternalLbIPConfigID')]" }, - "frontendPort": {{if IsOpenShift}}8443{{else}}443{{end}}, + "frontendPort": 443, "idleTimeoutInMinutes": 5, "protocol": "tcp", "probe": { @@ -643,7 +625,7 @@ "properties": { "intervalInSeconds": "5", "numberOfProbes": "2", - "port": {{if IsOpenShift}}8443{{else}}4443{{end}}, + "port": 443, "protocol": "tcp" } } @@ -668,7 +650,7 @@ "apiVersion": "[variables('apiVersionKeyVault')]", "location": "[variables('location')]", {{ if UseManagedIdentity}} - "dependsOn": + "dependsOn": [ {{if UserAssignedIDEnabled}} "[variables('userAssignedIDReference')]" @@ -696,7 +678,7 @@ "tenantId": "[variables('tenantID')]", {{if UseManagedIdentity}} {{if UserAssignedIDEnabled}} - "accessPolicies": + "accessPolicies": [ { "tenantId": "[variables('tenantID')]", @@ -782,7 +764,7 @@ "creationSource" : "[concat(parameters('generatorCode'), '-', variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]", "resourceNameSuffix" : "[parameters('nameSuffix')]", "orchestrator" : "[variables('orchestratorNameVersionTag')]", - "acsengineVersion" : "[parameters('acsengineVersion')]", + "aksengineVersion" : "[parameters('aksengineVersion')]", "poolName" : "master" }, "location": "[variables('location')]", @@ -801,13 +783,6 @@ }, {{end}} {{end}} - {{if and IsOpenShift (not UseMasterCustomImage)}} - "plan": { - "name": "[parameters('osImageSku')]", - "publisher": "[parameters('osImagePublisher')]", - "product": "[parameters('osImageOffer')]" - }, - {{end}} "properties": { "availabilitySet": { "id": "[resourceId('Microsoft.Compute/availabilitySets',variables('masterAvailabilitySet'))]" @@ -825,9 +800,7 @@ "osProfile": { "adminUsername": "[parameters('linuxAdminUsername')]", "computername": "[concat(variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]", - {{if not IsOpenShift}} {{GetKubernetesMasterCustomData .}} - {{end}} "linuxConfiguration": { "disablePasswordAuthentication": true, "ssh": { @@ -845,7 +818,7 @@ {{end}} }, "storageProfile": { - {{if and (not UseMasterCustomImage) (not IsOpenShift)}} + {{if (not UseMasterCustomImage)}} "dataDisks": [ { "createOption": "Empty" @@ -956,11 +929,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - {{if IsOpenShift}} - "script": "{{ Base64 OpenShiftGetMasterSh }}" - {{else}} "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $retries); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not BlockOutboundInternet}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}gcr.azk8s.cn 80{{else}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' ',variables('provisionScriptParametersMaster'), ' /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1\"')]" - {{end}} } } } diff --git a/parts/k8s/kubernetesmasterresourcesvmss.t b/parts/k8s/kubernetesmasterresourcesvmss.t index 70d3d69f58..779d62a651 100644 --- a/parts/k8s/kubernetesmasterresourcesvmss.t +++ b/parts/k8s/kubernetesmasterresourcesvmss.t @@ -304,7 +304,7 @@ "creationSource": "[concat(parameters('generatorCode'), '-', variables('masterVMNamePrefix'), 'vmss')]", "resourceNameSuffix": "[parameters('nameSuffix')]", "orchestrator": "[variables('orchestratorNameVersionTag')]", - "acsengineVersion" : "[parameters('acsengineVersion')]", + "aksengineVersion" : "[parameters('aksengineVersion')]", "poolName": "master" }, "location": "[variables('location')]", diff --git a/parts/k8s/kubernetesmastervars.t b/parts/k8s/kubernetesmastervars.t index 691668990a..149d1129d7 100644 --- a/parts/k8s/kubernetesmastervars.t +++ b/parts/k8s/kubernetesmastervars.t @@ -1,22 +1,14 @@ "maxVMsPerPool": 100, -{{ if IsOpenShift }} - "routerNSGName": "[concat(parameters('orchestratorName'), '-router-', parameters('nameSuffix'), '-nsg')]", - "routerNSGID": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('routerNSGName'))]", - "routerIPName": "[concat(parameters('orchestratorName'), '-router-ip-', variables('masterFqdnPrefix'), '-', parameters('nameSuffix'))]", - "routerLBName": "[concat(parameters('orchestratorName'), '-router-lb-', parameters('nameSuffix'))]", - "routerLBID": "[resourceId('Microsoft.Network/loadBalancers', variables('routerLBName'))]", -{{ end }} {{ if not IsHostedMaster }} - {{ if not IsOpenShift }} - {{if eq .MasterProfile.Count 1}} + {{if eq .MasterProfile.Count 1}} "etcdPeerPrivateKeys": [ "[parameters('etcdPeerPrivateKey0')]" ], "etcdPeerCertificates": [ "[parameters('etcdPeerCertificate0')]" ], - {{end}} - {{if eq .MasterProfile.Count 3}} + {{end}} + {{if eq .MasterProfile.Count 3}} "etcdPeerPrivateKeys": [ "[parameters('etcdPeerPrivateKey0')]", "[parameters('etcdPeerPrivateKey1')]", @@ -27,8 +19,8 @@ "[parameters('etcdPeerCertificate1')]", "[parameters('etcdPeerCertificate2')]" ], - {{end}} - {{if eq .MasterProfile.Count 5}} + {{end}} + {{if eq .MasterProfile.Count 5}} "etcdPeerPrivateKeys": [ "[parameters('etcdPeerPrivateKey0')]", "[parameters('etcdPeerPrivateKey1')]", @@ -43,7 +35,7 @@ "[parameters('etcdPeerCertificate3')]", "[parameters('etcdPeerCertificate4')]" ], - {{end}} + {{end}} "etcdPeerCertFilepath":[ "/etc/kubernetes/certs/etcdpeer0.crt", "/etc/kubernetes/certs/etcdpeer1.crt", @@ -63,7 +55,6 @@ "etcdClientKeyFilepath": "/etc/kubernetes/certs/etcdclient.key", "etcdServerCertFilepath": "/etc/kubernetes/certs/etcdserver.crt", "etcdServerKeyFilepath": "/etc/kubernetes/certs/etcdserver.key", - {{end}} {{end}} "useManagedIdentityExtension": "{{ UseManagedIdentity }}", "userAssignedID": "{{UserAssignedID}}", @@ -140,7 +131,6 @@ "customSearchDomainsScript": "{{GetKubernetesB64CustomSearchDomainsScript}}", "sshdConfig": "{{GetB64sshdConfig}}", "systemConf": "{{GetB64systemConf}}", -{{if not IsOpenShift}} "provisionScriptParametersCommon": "[concat('ADMINUSER=',parameters('linuxAdminUsername'),' ETCD_DOWNLOAD_URL=',parameters('etcdDownloadURLBase'),' ETCD_VERSION=',parameters('etcdVersion'),' TENANT_ID=',variables('tenantID'),' KUBERNETES_VERSION={{.OrchestratorProfile.OrchestratorVersion}} HYPERKUBE_URL=',parameters('kubernetesHyperkubeSpec'),' APISERVER_PUBLIC_KEY=',parameters('apiserverCertificate'),' SUBSCRIPTION_ID=',variables('subscriptionId'),' RESOURCE_GROUP=',variables('resourceGroup'),' LOCATION=',variables('location'),' VM_TYPE=',variables('vmType'),' SUBNET=',variables('subnetName'),' NETWORK_SECURITY_GROUP=',variables('nsgName'),' VIRTUAL_NETWORK=',variables('virtualNetworkName'),' VIRTUAL_NETWORK_RESOURCE_GROUP=',variables('virtualNetworkResourceGroupName'),' ROUTE_TABLE=',variables('routeTableName'),' PRIMARY_AVAILABILITY_SET=',variables('primaryAvailabilitySetName'),' PRIMARY_SCALE_SET=',variables('primaryScaleSetName'),' SERVICE_PRINCIPAL_CLIENT_ID=',variables('servicePrincipalClientId'),' SERVICE_PRINCIPAL_CLIENT_SECRET=',variables('singleQuote'),variables('servicePrincipalClientSecret'),variables('singleQuote'),' KUBELET_PRIVATE_KEY=',parameters('clientPrivateKey'),' TARGET_ENVIRONMENT=',parameters('targetEnvironment'),' NETWORK_PLUGIN=',parameters('networkPlugin'),' NETWORK_POLICY=',parameters('networkPolicy'),' VNET_CNI_PLUGINS_URL=',parameters('vnetCniLinuxPluginsURL'),' CNI_PLUGINS_URL=',parameters('cniPluginsURL'),' CLOUDPROVIDER_BACKOFF=',toLower(string(parameters('cloudproviderConfig').cloudProviderBackoff)),' CLOUDPROVIDER_BACKOFF_RETRIES=',parameters('cloudproviderConfig').cloudProviderBackoffRetries,' CLOUDPROVIDER_BACKOFF_EXPONENT=',parameters('cloudproviderConfig').cloudProviderBackoffExponent,' CLOUDPROVIDER_BACKOFF_DURATION=',parameters('cloudproviderConfig').cloudProviderBackoffDuration,' CLOUDPROVIDER_BACKOFF_JITTER=',parameters('cloudproviderConfig').cloudProviderBackoffJitter,' CLOUDPROVIDER_RATELIMIT=',toLower(string(parameters('cloudproviderConfig').cloudProviderRatelimit)),' CLOUDPROVIDER_RATELIMIT_QPS=',parameters('cloudproviderConfig').cloudProviderRatelimitQPS,' CLOUDPROVIDER_RATELIMIT_BUCKET=',parameters('cloudproviderConfig').cloudProviderRatelimitBucket,' USE_MANAGED_IDENTITY_EXTENSION=',variables('useManagedIdentityExtension'),' USER_ASSIGNED_IDENTITY_ID=',variables('userAssignedClientID'),' USE_INSTANCE_METADATA=',variables('useInstanceMetadata'),' LOAD_BALANCER_SKU=',variables('loadBalancerSku'),' EXCLUDE_MASTER_FROM_STANDARD_LB=',variables('excludeMasterFromStandardLB'),' CONTAINER_RUNTIME=',parameters('containerRuntime'),' CONTAINERD_DOWNLOAD_URL_BASE=',parameters('containerdDownloadURLBase'),' POD_INFRA_CONTAINER_SPEC=',parameters('kubernetesPodInfraContainerSpec'),' KMS_PROVIDER_VAULT_NAME=',variables('clusterKeyVaultName'),' IS_HOSTED_MASTER={{IsHostedMaster}}')]", {{if not IsHostedMaster}} {{if IsMasterVirtualMachineScaleSets}} @@ -149,7 +139,6 @@ "provisionScriptParametersMaster": "[concat('MASTER_VM_NAME=',variables('masterVMNames')[variables('masterOffset')],' ETCD_PEER_URL=',variables('masterEtcdPeerURLs')[variables('masterOffset')],' ETCD_CLIENT_URL=',variables('masterEtcdClientURLs')[variables('masterOffset')],' MASTER_NODE=true NO_OUTBOUND={{BlockOutboundInternet}} CLUSTER_AUTOSCALER_ADDON=',parameters('kubernetesClusterAutoscalerEnabled'),' ACI_CONNECTOR_ADDON=',parameters('kubernetesACIConnectorEnabled'),' APISERVER_PRIVATE_KEY=',parameters('apiServerPrivateKey'),' CA_CERTIFICATE=',parameters('caCertificate'),' CA_PRIVATE_KEY=',parameters('caPrivateKey'),' MASTER_FQDN=',variables('masterFqdnPrefix'),' KUBECONFIG_CERTIFICATE=',parameters('kubeConfigCertificate'),' KUBECONFIG_KEY=',parameters('kubeConfigPrivateKey'),' ETCD_SERVER_CERTIFICATE=',parameters('etcdServerCertificate'),' ETCD_CLIENT_CERTIFICATE=',parameters('etcdClientCertificate'),' ETCD_SERVER_PRIVATE_KEY=',parameters('etcdServerPrivateKey'),' ETCD_CLIENT_PRIVATE_KEY=',parameters('etcdClientPrivateKey'),' ETCD_PEER_CERTIFICATES=',string(variables('etcdPeerCertificates')),' ETCD_PEER_PRIVATE_KEYS=',string(variables('etcdPeerPrivateKeys')),' ENABLE_AGGREGATED_APIS=',string(parameters('enableAggregatedAPIs')),' KUBECONFIG_SERVER=',variables('kubeconfigServer'))]", {{end}} {{end}} -{{end}} "generateProxyCertsScript": "{{GetKubernetesB64GenerateProxyCerts}}", "orchestratorNameVersionTag": "{{.OrchestratorProfile.OrchestratorType}}:{{.OrchestratorProfile.OrchestratorVersion}}", diff --git a/parts/k8s/kubernetesparams.t b/parts/k8s/kubernetesparams.t index 2a6d0be905..1baef5d7ae 100644 --- a/parts/k8s/kubernetesparams.t +++ b/parts/k8s/kubernetesparams.t @@ -22,7 +22,6 @@ "type": "string" }, {{else}} -{{if not IsOpenShift}} "etcdServerCertificate": { "metadata": { "description": "The base 64 server certificate used on the master" @@ -112,8 +111,6 @@ {{end}} {{end}} {{end}} -{{end}} -{{if not IsOpenShift}} "apiServerCertificate": { "metadata": { "description": "The base 64 server certificate used on the master" @@ -162,7 +159,6 @@ }, "type": "securestring" }, -{{end}} "generatorCode": { "metadata": { "description": "The generator code used to identify the generator" diff --git a/parts/k8s/kuberneteswinagentresourcesvmas.t b/parts/k8s/kuberneteswinagentresourcesvmas.t index b22079948b..356e0d25c6 100644 --- a/parts/k8s/kuberneteswinagentresourcesvmas.t +++ b/parts/k8s/kuberneteswinagentresourcesvmas.t @@ -148,7 +148,7 @@ "creationSource" : "[concat(parameters('generatorCode'), '-', variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')))]", "resourceNameSuffix" : "[variables('winResourceNamePrefix')]", "orchestrator" : "[variables('orchestratorNameVersionTag')]", - "acsengineVersion" : "[parameters('acsengineVersion')]", + "aksengineVersion" : "[parameters('aksengineVersion')]", "poolName" : "{{.Name}}" }, "location": "[variables('location')]", diff --git a/parts/k8s/kuberneteswindowssetup.ps1 b/parts/k8s/kuberneteswindowssetup.ps1 index 54b9c32cee..07e1df2a31 100644 --- a/parts/k8s/kuberneteswindowssetup.ps1 +++ b/parts/k8s/kuberneteswindowssetup.ps1 @@ -8,7 +8,7 @@ The parameters passed in are required, and will vary per-deployment. Notes on modifying this file: - - This file extension is PS1, but it is actually used as a template from pkg/acsengine/template_generator.go + - This file extension is PS1, but it is actually used as a template from pkg/engine/template_generator.go - All of the lines that have braces in them will be modified. Please do not change them here, change them in the Go sources - Single quotes are forbidden, they are reserved to delineate the different members for the ARM template concat() call #> @@ -48,11 +48,11 @@ param( # These globals will not change between nodes in the same cluster, so they are not # passed as powershell parameters -## Certificates generated by acs-engine +## Certificates generated by aks-engine $global:CACertificate = "{{WrapAsParameter "caCertificate"}}" $global:AgentCertificate = "{{WrapAsParameter "clientCertificate"}}" -## Download sources provided by acs-engine +## Download sources provided by aks-engine $global:KubeBinariesPackageSASURL = "{{WrapAsParameter "kubeBinariesSASURL"}}" $global:WindowsKubeBinariesURL = "{{WrapAsParameter "windowsKubeBinariesURL"}}" $global:KubeBinariesVersion = "{{WrapAsParameter "kubeBinariesVersion"}}" @@ -87,7 +87,7 @@ $global:LoadBalancerSku = "{{WrapAsVariable "loadBalancerSku"}}" $global:ExcludeMasterFromStandardLB = "{{WrapAsVariable "excludeMasterFromStandardLB"}}" -# Windows defaults, not changed by acs-engine +# Windows defaults, not changed by aks-engine $global:KubeDir = "c:\k" $global:HNSModule = [Io.path]::Combine("$global:KubeDir", "hns.psm1") diff --git a/parts/k8s/windowskubeletfunc.ps1 b/parts/k8s/windowskubeletfunc.ps1 index 7e2f9f9cf5..476605fbbb 100644 --- a/parts/k8s/windowskubeletfunc.ps1 +++ b/parts/k8s/windowskubeletfunc.ps1 @@ -325,11 +325,11 @@ Install-KubernetesServices $KubeProxyStartFile = [io.path]::Combine($KubeDir, "kubeproxystart.ps1") mkdir $VolumePluginDir - $KubeletArgList = $KubeletConfigArgs # This is the initial list passed in from acs-engine + $KubeletArgList = $KubeletConfigArgs # This is the initial list passed in from aks-engine $KubeletArgList += "--node-labels=`$global:KubeletNodeLabels" # $KubeletArgList += "--hostname-override=`$global:AzureHostname" TODO: remove - dead code? $KubeletArgList += "--volume-plugin-dir=`$global:VolumePluginDir" - # If you are thinking about adding another arg here, you should be considering pkg/acsengine/defaults-kubelet.go first + # If you are thinking about adding another arg here, you should be considering pkg/engine/defaults-kubelet.go first # Only args that need to be calculated or combined with other ones on the Windows agent should be added here. diff --git a/parts/masterparams.t b/parts/masterparams.t index 0c88a2803c..6e10f27907 100644 --- a/parts/masterparams.t +++ b/parts/masterparams.t @@ -10,9 +10,9 @@ }, "type": "string" }, - "acsengineVersion": { + "aksengineVersion": { "metadata": { - "description": "Contains details of the acs-engine version which was used to provision the cluster" + "description": "Contains details of the aks-engine version which was used to provision the cluster" }, "type": "string" }, diff --git a/parts/openshift/OWNERS b/parts/openshift/OWNERS deleted file mode 100644 index 4e1cf8514f..0000000000 --- a/parts/openshift/OWNERS +++ /dev/null @@ -1,4 +0,0 @@ -approvers: -- jim-minter -- kargakis -- pweil- diff --git a/parts/openshift/infraresources.t b/parts/openshift/infraresources.t deleted file mode 100644 index 30d1c39e80..0000000000 --- a/parts/openshift/infraresources.t +++ /dev/null @@ -1,157 +0,0 @@ - { - "type": "Microsoft.Network/networkSecurityGroups", - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('routerNSGName')]", - "properties": { - "securityRules": [ - { - "name": "allow_http", - "properties": { - "access": "Allow", - "description": "Allow http traffic to infra nodes", - "destinationAddressPrefix": "*", - "destinationPortRange": "80", - "direction": "Inbound", - "priority": 110, - "protocol": "Tcp", - "sourceAddressPrefix": "*", - "sourcePortRange": "*" - } - }, - { - "name": "allow_https", - "properties": { - "access": "Allow", - "description": "Allow https traffic to infra nodes", - "destinationAddressPrefix": "*", - "destinationPortRange": "443", - "direction": "Inbound", - "priority": 111, - "protocol": "Tcp", - "sourceAddressPrefix": "*", - "sourcePortRange": "*" - } - } - ] - } - }, - { - "name": "[variables('routerIPName')]", - "type": "Microsoft.Network/publicIPAddresses", - "apiVersion": "2017-08-01", - "location": "[variables('location')]", - "properties": { - "publicIPAllocationMethod": "Static", - "dnsSettings": { - "domainNameLabel": "[concat(variables('masterFqdnPrefix'), '-router')]" - } - }, - "sku": { - "name": "Basic" - } - }, - { - "name": "[variables('routerLBName')]", - "type": "Microsoft.Network/loadBalancers", - "apiVersion": "2017-10-01", - "location": "[variables('location')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('routerIPName'))]" - ], - "properties": { - "frontendIPConfigurations": [ - { - "name": "frontend", - "properties": { - "privateIPAllocationMethod": "Dynamic", - "publicIPAddress": { - "id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('routerIPName'))]" - } - } - } - ], - "backendAddressPools": [ - { - "name": "backend" - } - ], - "loadBalancingRules": [ - { - "name": "port-80", - "properties": { - "frontendIPConfiguration": { - "id": "[concat(variables('routerLBID'), '/frontendIPConfigurations/frontend')]" - }, - "frontendPort": 80, - "backendPort": 80, - "enableFloatingIP": false, - "idleTimeoutInMinutes": 4, - "protocol": "Tcp", - "loadDistribution": "Default", - "backendAddressPool": { - "id": "[concat(variables('routerLBID'), '/backendAddressPools/backend')]" - }, - "probe": { - "id": "[concat(variables('routerLBID'), '/probes/port-80')]" - } - } - }, - { - "name": "port-443", - "properties": { - "frontendIPConfiguration": { - "id": "[concat(variables('routerLBID'), '/frontendIPConfigurations/frontend')]" - }, - "frontendPort": 443, - "backendPort": 443, - "enableFloatingIP": false, - "idleTimeoutInMinutes": 4, - "protocol": "Tcp", - "loadDistribution": "Default", - "backendAddressPool": { - "id": "[concat(variables('routerLBID'), '/backendAddressPools/backend')]" - }, - "probe": { - "id": "[concat(variables('routerLBID'), '/probes/port-443')]" - } - } - } - ], - "probes": [ - { - "name": "port-80", - "properties": { - "protocol": "Tcp", - "port": 80, - "intervalInSeconds": 5, - "numberOfProbes": 2 - } - }, - { - "name": "port-443", - "properties": { - "protocol": "Tcp", - "port": 443, - "intervalInSeconds": 5, - "numberOfProbes": 2 - } - } - ], - "inboundNatRules": [], - "outboundNatRules": [], - "inboundNatPools": [] - }, - "sku": { - "name": "Basic" - } - }, - { - "type": "Microsoft.Storage/storageAccounts", - "apiVersion": "[variables('apiVersionStorage')]", - "name": "[concat(variables('storageAccountBaseName'), 'registry')]", - "location": "[variables('location')]", - "properties": { - "accountType": "Standard_LRS" - } - }, \ No newline at end of file diff --git a/parts/openshift/release-3.9/openshiftmasterscript.sh b/parts/openshift/release-3.9/openshiftmasterscript.sh deleted file mode 100644 index e3eef5fd00..0000000000 --- a/parts/openshift/release-3.9/openshiftmasterscript.sh +++ /dev/null @@ -1,161 +0,0 @@ -#!/bin/bash -ex - -# TODO: /etc/dnsmasq.d/origin-upstream-dns.conf is currently hardcoded; it -# probably shouldn't be - -if [ -f "/etc/sysconfig/atomic-openshift-node" ]; then - SERVICE_TYPE=atomic-openshift -else - SERVICE_TYPE=origin -fi -VERSION="$(rpm -q $SERVICE_TYPE --queryformat %{VERSION})" - -if [ -f "/etc/sysconfig/atomic-openshift-node" ]; then - ANSIBLE_DEPLOY_TYPE="openshift-enterprise" - IMAGE_TYPE=ose - IMAGE_PREFIX="registry.access.redhat.com/openshift3" - ANSIBLE_CONTAINER_VERSION="v${VERSION}" - PROMETHEUS_EXPORTER_VERSION="v${VERSION}" - COCKPIT_PREFIX="${IMAGE_PREFIX}" - COCKPIT_BASENAME="registry-console" - COCKPIT_VERSION="v${VERSION}" -else - ANSIBLE_DEPLOY_TYPE="origin" - IMAGE_TYPE="${SERVICE_TYPE}" - IMAGE_PREFIX="openshift" - # FIXME: These versions are set to deal with differences in how Origin and OCP - # components are versioned - ANSIBLE_CONTAINER_VERSION="v${VERSION%.*}" - COCKPIT_PREFIX="cockpit" - COCKPIT_BASENAME="kubernetes" - COCKPIT_VERSION="latest" -fi - -echo "BOOTSTRAP_CONFIG_NAME=node-config-master" >>/etc/sysconfig/${SERVICE_TYPE}-node - -for dst in tcp,2379 tcp,2380 tcp,8443 tcp,8444 tcp,8053 udp,8053 tcp,9090; do - proto=${dst%%,*} - port=${dst##*,} - iptables -A OS_FIREWALL_ALLOW -p $proto -m state --state NEW -m $proto --dport $port -j ACCEPT -done - -iptables-save >/etc/sysconfig/iptables - -sed -i -e "s#--master=.*#--master=https://$(hostname --fqdn):8443#" /etc/sysconfig/${SERVICE_TYPE}-master-api -sed -i -e "s#--loglevel=2#--loglevel=4#" /etc/sysconfig/${SERVICE_TYPE}-master-api -sed -i -e "s#--loglevel=2#--loglevel=4#" /etc/sysconfig/${SERVICE_TYPE}-master-controllers - -rm -rf /etc/etcd/* /etc/origin/master/* /etc/origin/node/* - -MASTER_OREG_URL="$IMAGE_PREFIX/$IMAGE_TYPE-\${component}:\${version}" -if [[ -f /etc/origin/oreg_url ]]; then - MASTER_OREG_URL=$(cat /etc/origin/oreg_url) -fi - -oc adm create-bootstrap-policy-file --filename=/etc/origin/master/policy.json - -( cd / && base64 -d <<< {{ .ConfigBundle | shellQuote }} | tar -xz) - -cp /etc/origin/node/ca.crt /etc/pki/ca-trust/source/anchors/openshift-ca.crt -update-ca-trust - -# FIXME: It is horrible that we're installing az. Try to avoid adding -# additional functionality in this script that requires it. One route to remove -# this code is to bake this script into the base image, then pass in parameters -# such as the registry storage account name and key direct from ARM. -rpm -i https://packages.microsoft.com/yumrepos/azure-cli/azure-cli-2.0.31-1.el7.x86_64.rpm - -set +x -. <(sed -e 's/: */=/' /etc/azure/azure.conf) -az login --service-principal -u "$aadClientId" -p "$aadClientSecret" --tenant "$aadTenantId" &>/dev/null -REGISTRY_STORAGE_AZURE_ACCOUNTNAME=$(az storage account list -g "$resourceGroup" --query "[?ends_with(name, 'registry')].name" -o tsv) -REGISTRY_STORAGE_AZURE_ACCOUNTKEY=$(az storage account keys list -g "$resourceGroup" -n "$REGISTRY_STORAGE_AZURE_ACCOUNTNAME" --query "[?keyName == 'key1'].value" -o tsv) -az logout -set -x - -### -# retrieve the public ip via dns for the router public ip and sub it in for the routingConfig.subdomain -### -routerLBHost={{ .RouterLBHostname | shellQuote }} -routerLBIP=$(dig +short $routerLBHost) - -# NOTE: The version of openshift-ansible for origin defaults the ansible var -# openshift_prometheus_node_exporter_image_version correctly as needed by -# origin, but for OCP it does not. -# -# This is fixed in openshift/openshift-ansible@c27a0f4, which is in -# openshift-ansible >= 3.9.15, so once we're shipping OCP >= v3.9.15 we -# can remove this and the definition of the cooresonding variable in the -# ansible inventory file. -if [[ "${ANSIBLE_DEPLOY_TYPE}" == "origin" ]]; then - sed -i "/PROMETHEUS_EXPORTER_VERSION/d" /tmp/ansible/azure-local-master-inventory.yml -else - sed -i "s|PROMETHEUS_EXPORTER_VERSION|${PROMETHEUS_EXPORTER_VERSION}|g;" /tmp/ansible/azure-local-master-inventory.yml -fi - -for i in /etc/origin/master/master-config.yaml /tmp/bootstrapconfigs/* /tmp/ansible/azure-local-master-inventory.yml; do - sed -i "s/TEMPROUTERIP/${routerLBIP}/; s|IMAGE_PREFIX|$IMAGE_PREFIX|g; s|ANSIBLE_DEPLOY_TYPE|$ANSIBLE_DEPLOY_TYPE|g" $i - sed -i "s|REGISTRY_STORAGE_AZURE_ACCOUNTNAME|${REGISTRY_STORAGE_AZURE_ACCOUNTNAME}|g; s|REGISTRY_STORAGE_AZURE_ACCOUNTKEY|${REGISTRY_STORAGE_AZURE_ACCOUNTKEY}|g" $i - sed -i "s|COCKPIT_VERSION|${COCKPIT_VERSION}|g; s|COCKPIT_BASENAME|${COCKPIT_BASENAME}|g; s|COCKPIT_PREFIX|${COCKPIT_PREFIX}|g;" $i - sed -i "s|VERSION|${VERSION}|g; s|SHORT_VER|${VERSION%.*}|g; s|SERVICE_TYPE|${SERVICE_TYPE}|g; s|IMAGE_TYPE|${IMAGE_TYPE}|g" $i - sed -i "s|HOSTNAME|${HOSTNAME}|g;" $i - sed -i "s|MASTER_OREG_URL|${MASTER_OREG_URL}|g" $i -done - -# note: ${SERVICE_TYPE}-node crash loops until master is up -for unit in etcd.service ${SERVICE_TYPE}-master-api.service ${SERVICE_TYPE}-master-controllers.service; do - systemctl enable $unit - systemctl start $unit -done - -mkdir -p /root/.kube -cp /etc/origin/master/admin.kubeconfig /root/.kube/config - -export KUBECONFIG=/etc/origin/master/admin.kubeconfig - -while ! curl -o /dev/null -m 2 -kfs https://localhost:8443/healthz; do - sleep 1 -done - -while ! oc get svc kubernetes &>/dev/null; do - sleep 1 -done - -oc create -f - <<'EOF' -kind: StorageClass -apiVersion: storage.k8s.io/v1beta1 -metadata: - name: azure - annotations: - storageclass.kubernetes.io/is-default-class: "true" -provisioner: kubernetes.io/azure-disk -parameters: - skuName: Premium_LRS - location: {{ .Location | quote }} - kind: managed -EOF - -oc create configmap node-config-master --namespace openshift-node --from-file=node-config.yaml=/tmp/bootstrapconfigs/master-config.yaml -oc create configmap node-config-compute --namespace openshift-node --from-file=node-config.yaml=/tmp/bootstrapconfigs/compute-config.yaml -oc create configmap node-config-infra --namespace openshift-node --from-file=node-config.yaml=/tmp/bootstrapconfigs/infra-config.yaml - -# must start ${SERVICE_TYPE}-node after master is fully up and running -# otherwise the implicit dns change may cause master startup to fail -systemctl enable ${SERVICE_TYPE}-node.service -systemctl start ${SERVICE_TYPE}-node.service & - -chmod +x /tmp/ansible/ansible.sh - -docker run \ - --rm \ - -u "$(id -u)" \ - -v /etc/origin:/etc/origin:z \ - -v /tmp/ansible:/opt/app-root/src:z \ - -v /root/.kube:/opt/app-root/src/.kube:z \ - -w /opt/app-root/src \ - -e IMAGE_BASE="${IMAGE_PREFIX}/${IMAGE_TYPE}" \ - -e VERSION="$VERSION" \ - -e HOSTNAME="$(hostname)" \ - --network="host" \ - "${IMAGE_PREFIX}/${IMAGE_TYPE}-ansible:${ANSIBLE_CONTAINER_VERSION}" \ - /opt/app-root/src/ansible.sh diff --git a/parts/openshift/release-3.9/openshiftnodescript.sh b/parts/openshift/release-3.9/openshiftnodescript.sh deleted file mode 100644 index a70a8308e9..0000000000 --- a/parts/openshift/release-3.9/openshiftnodescript.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash -ex - -# TODO: /etc/dnsmasq.d/origin-upstream-dns.conf is currently hardcoded; it -# probably shouldn't be -SERVICE_TYPE=origin -if [ -f "/etc/sysconfig/atomic-openshift-node" ]; then - SERVICE_TYPE=atomic-openshift -fi - -{{if eq .Role "infra"}} -echo "BOOTSTRAP_CONFIG_NAME=node-config-infra" >>/etc/sysconfig/${SERVICE_TYPE}-node -{{else}} -echo "BOOTSTRAP_CONFIG_NAME=node-config-compute" >>/etc/sysconfig/${SERVICE_TYPE}-node -{{end}} - -sed -i -e "s#--loglevel=2#--loglevel=4#" /etc/sysconfig/${SERVICE_TYPE}-node - -rm -rf /etc/etcd/* /etc/origin/master/* /etc/origin/node/* - -( cd / && base64 -d <<< {{ .ConfigBundle | shellQuote }} | tar -xz) - -cp /etc/origin/node/ca.crt /etc/pki/ca-trust/source/anchors/openshift-ca.crt -update-ca-trust - -# note: ${SERVICE_TYPE}-node crash loops until master is up -systemctl enable ${SERVICE_TYPE}-node.service -systemctl start ${SERVICE_TYPE}-node.service & - -while [[ $(KUBECONFIG=/etc/origin/node/node.kubeconfig oc get node $(hostname) -o template \ - --template '{{`{{range .status.conditions}}{{if eq .type "Ready"}}{{.status}}{{end}}{{end}}`}}') != True ]]; do - sleep 1 -done diff --git a/parts/openshift/unstable/openshiftmasterscript.sh b/parts/openshift/unstable/openshiftmasterscript.sh deleted file mode 100644 index 825283d754..0000000000 --- a/parts/openshift/unstable/openshiftmasterscript.sh +++ /dev/null @@ -1,197 +0,0 @@ -#!/bin/bash -ex - -# TODO: /etc/dnsmasq.d/origin-upstream-dns.conf is currently hardcoded; it -# probably shouldn't be - -if [ -f "/etc/sysconfig/atomic-openshift-node" ]; then - SERVICE_TYPE=atomic-openshift -else - SERVICE_TYPE=origin -fi -VERSION="$(rpm -q $SERVICE_TYPE --queryformat %{VERSION})" -IP_ADDRESS="{{ .MasterIP }}" - -if [ -f "/etc/sysconfig/atomic-openshift-node" ]; then - ANSIBLE_DEPLOY_TYPE="openshift-enterprise" - IMAGE_TYPE=ose - IMAGE_PREFIX="registry.access.redhat.com/openshift3" - ANSIBLE_CONTAINER_VERSION="v${VERSION}" - PROMETHEUS_EXPORTER_VERSION="v${VERSION}" - COCKPIT_PREFIX="${IMAGE_PREFIX}" - COCKPIT_BASENAME="registry-console" - COCKPIT_VERSION="v${VERSION}" -else - ANSIBLE_DEPLOY_TYPE="origin" - IMAGE_TYPE="${SERVICE_TYPE}" - IMAGE_PREFIX="openshift" - # FIXME: These versions are set to deal with differences in how Origin and OCP - # components are versioned - ANSIBLE_CONTAINER_VERSION="v${VERSION%.*}" - COCKPIT_PREFIX="cockpit" - COCKPIT_BASENAME="kubernetes" - COCKPIT_VERSION="latest" -fi - -if grep -q ^ResourceDisk.Filesystem=xfs /etc/waagent.conf; then - # Bad image: docker and waagent are racing. Try to fix up. Leave this code - # until the bad images have gone away. - set +e - - # stop docker if it hasn't failed already - systemctl stop docker.service - - # wait until waagent has run mkfs and mounted /var/lib/docker - while ! mountpoint -q /var/lib/docker; do - sleep 1 - done - - # now roll us back. /var/lib/docker/* may be mounted if docker lost the - # race. - umount /var/lib/docker - umount /var/lib/docker/* - - # disable waagent from racing again if we reboot. - sed -i -e '/^ResourceDisk.Format=/ s/=.*/=n/' /etc/waagent.conf - set -e -fi - -systemctl stop docker.service -# Also a bad image: the umount should also go away. -umount /var/lib/docker || true -mkfs.xfs -f /dev/sdb1 -echo '/dev/sdb1 /var/lib/docker xfs grpquota 0 0' >>/etc/fstab -mount /var/lib/docker -restorecon -R /var/lib/docker -systemctl start docker.service - -echo "BOOTSTRAP_CONFIG_NAME=node-config-master" >>/etc/sysconfig/${SERVICE_TYPE}-node - -for dst in tcp,2379 tcp,2380 tcp,8443 tcp,8444 tcp,8053 udp,8053 tcp,9090; do - proto=${dst%%,*} - port=${dst##*,} - iptables -A OS_FIREWALL_ALLOW -p $proto -m state --state NEW -m $proto --dport $port -j ACCEPT -done - -iptables-save >/etc/sysconfig/iptables - -rm -rf /etc/etcd/* /etc/origin/master/* - -mkdir -p /etc/origin/master - -oc adm create-bootstrap-policy-file --filename=/etc/origin/master/policy.json - -( cd / && base64 -d <<< {{ .ConfigBundle | shellQuote }} | tar -xz) - -cp /etc/origin/node/ca.crt /etc/pki/ca-trust/source/anchors/openshift-ca.crt -update-ca-trust - -# FIXME: It is horrible that we're installing az. Try to avoid adding -# additional functionality in this script that requires it. One route to remove -# this code is to bake this script into the base image, then pass in parameters -# such as the registry storage account name and key direct from ARM. -rpm -i https://packages.microsoft.com/yumrepos/azure-cli/azure-cli-2.0.31-1.el7.x86_64.rpm - -set +x -. <(sed -e 's/: */=/' /etc/origin/cloudprovider/azure.conf) -az login --service-principal -u "$aadClientId" -p "$aadClientSecret" --tenant "$aadTenantId" &>/dev/null -REGISTRY_STORAGE_AZURE_ACCOUNTNAME=$(az storage account list -g "$resourceGroup" --query "[?ends_with(name, 'registry')].name" -o tsv) -REGISTRY_STORAGE_AZURE_ACCOUNTKEY=$(az storage account keys list -g "$resourceGroup" -n "$REGISTRY_STORAGE_AZURE_ACCOUNTNAME" --query "[?keyName == 'key1'].value" -o tsv) -az logout -set -x - -### -# retrieve the public ip via dns for the router public ip and sub it in for the routingConfig.subdomain -### -routerLBHost={{ .RouterLBHostname | shellQuote }} -routerLBIP=$(dig +short $routerLBHost) - -# NOTE: The version of openshift-ansible for origin defaults the ansible var -# openshift_prometheus_node_exporter_image_version correctly as needed by -# origin, but for OCP it does not. -# -# This is fixed in openshift/openshift-ansible@c27a0f4, which is in -# openshift-ansible >= 3.9.15, so once we're shipping OCP >= v3.9.15 we -# can remove this and the definition of the cooresonding variable in the -# ansible inventory file. -if [[ "${ANSIBLE_DEPLOY_TYPE}" == "origin" ]]; then - sed -i "/PROMETHEUS_EXPORTER_VERSION/d" /tmp/ansible/azure-local-master-inventory.yml -else - sed -i "s|PROMETHEUS_EXPORTER_VERSION|${PROMETHEUS_EXPORTER_VERSION}|g;" /tmp/ansible/azure-local-master-inventory.yml -fi - -MASTER_OREG_URL="$IMAGE_PREFIX/$IMAGE_TYPE-\${component}:\${version}" -if [[ -f /etc/origin/oreg_url ]]; then - MASTER_OREG_URL=$(cat /etc/origin/oreg_url) -fi - -for i in /etc/origin/master/master-config.yaml /tmp/bootstrapconfigs/* /tmp/ansible/azure-local-master-inventory.yml; do - sed -i "s/TEMPROUTERIP/${routerLBIP}/; s|IMAGE_PREFIX|$IMAGE_PREFIX|g; s|ANSIBLE_DEPLOY_TYPE|$ANSIBLE_DEPLOY_TYPE|g" $i - sed -i "s|REGISTRY_STORAGE_AZURE_ACCOUNTNAME|${REGISTRY_STORAGE_AZURE_ACCOUNTNAME}|g; s|REGISTRY_STORAGE_AZURE_ACCOUNTKEY|${REGISTRY_STORAGE_AZURE_ACCOUNTKEY}|g" $i - sed -i "s|COCKPIT_VERSION|${COCKPIT_VERSION}|g; s|COCKPIT_BASENAME|${COCKPIT_BASENAME}|g; s|COCKPIT_PREFIX|${COCKPIT_PREFIX}|g;" $i - sed -i "s|VERSION|${VERSION}|g; s|SHORT_VER|${VERSION%.*}|g; s|SERVICE_TYPE|${SERVICE_TYPE}|g; s|IMAGE_TYPE|${IMAGE_TYPE}|g" $i - sed -i "s|HOSTNAME|${HOSTNAME}|g;" $i - sed -i "s|MASTER_OREG_URL|${MASTER_OREG_URL}|g" $i -done - -mkdir -p /root/.kube - -for loc in /root/.kube/config /etc/origin/node/bootstrap.kubeconfig /etc/origin/node/node.kubeconfig; do - cp /etc/origin/master/admin.kubeconfig "$loc" -done - - -# Patch the etcd_ip address placed inside of the static pod definition from the node install -sed -i "s/ETCD_IP_REPLACE/${IP_ADDRESS}/g" /etc/origin/node/disabled/etcd.yaml - -export KUBECONFIG=/etc/origin/master/admin.kubeconfig - -# Move each static pod into place so the kubelet will run it. -# Pods: [apiserver, controller, etcd] -oc set env --local -f /etc/origin/node/disabled/apiserver.yaml DEBUG_LOGLEVEL=4 -o yaml --dry-run > /etc/origin/node/pods/apiserver.yaml -oc set env --local -f /etc/origin/node/disabled/controller.yaml DEBUG_LOGLEVEL=4 -o yaml --dry-run > /etc/origin/node/pods/controller.yaml -mv /etc/origin/node/disabled/etcd.yaml /etc/origin/node/pods/etcd.yaml -rm -rf /etc/origin/node/disabled - -systemctl start ${SERVICE_TYPE}-node - -while ! curl -o /dev/null -m 2 -kfs https://localhost:8443/healthz; do - sleep 1 -done - -while ! oc get svc kubernetes &>/dev/null; do - sleep 1 -done - -oc create -f - <<'EOF' -kind: StorageClass -apiVersion: storage.k8s.io/v1beta1 -metadata: - name: azure - annotations: - storageclass.kubernetes.io/is-default-class: "true" -provisioner: kubernetes.io/azure-disk -parameters: - skuName: Premium_LRS - location: {{ .Location | quote }} - kind: managed -EOF - -oc create configmap node-config-master --namespace openshift-node --from-file=node-config.yaml=/tmp/bootstrapconfigs/master-config.yaml -oc create configmap node-config-compute --namespace openshift-node --from-file=node-config.yaml=/tmp/bootstrapconfigs/compute-config.yaml -oc create configmap node-config-infra --namespace openshift-node --from-file=node-config.yaml=/tmp/bootstrapconfigs/infra-config.yaml - -chmod +x /tmp/ansible/ansible.sh - -docker run \ - --rm \ - -u "$(id -u)" \ - -v /etc/origin:/etc/origin:z \ - -v /tmp/ansible:/opt/app-root/src:z \ - -v /root/.kube:/opt/app-root/src/.kube:z \ - -w /opt/app-root/src \ - -e IMAGE_BASE="${IMAGE_PREFIX}/${IMAGE_TYPE}" \ - -e VERSION="$VERSION" \ - -e HOSTNAME="$(hostname)" \ - --network="host" \ - "${IMAGE_PREFIX}/${IMAGE_TYPE}-ansible:${ANSIBLE_CONTAINER_VERSION}" \ - /opt/app-root/src/ansible.sh diff --git a/parts/openshift/unstable/openshiftnodescript.sh b/parts/openshift/unstable/openshiftnodescript.sh deleted file mode 100644 index 7c8b79aff3..0000000000 --- a/parts/openshift/unstable/openshiftnodescript.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/bash -ex - -# TODO: /etc/dnsmasq.d/origin-upstream-dns.conf is currently hardcoded; it -# probably shouldn't be -SERVICE_TYPE=origin -if [ -f "/etc/sysconfig/atomic-openshift-node" ]; then - SERVICE_TYPE=atomic-openshift -fi - -if grep -q ^ResourceDisk.Filesystem=xfs /etc/waagent.conf; then - # Bad image: docker and waagent are racing. Try to fix up. Leave this code - # until the bad images have gone away. - set +e - - # stop docker if it hasn't failed already - systemctl stop docker.service - - # wait until waagent has run mkfs and mounted /var/lib/docker - while ! mountpoint -q /var/lib/docker; do - sleep 1 - done - - # now roll us back. /var/lib/docker/* may be mounted if docker lost the - # race. - umount /var/lib/docker - umount /var/lib/docker/* - - # disable waagent from racing again if we reboot. - sed -i -e '/^ResourceDisk.Format=/ s/=.*/=n/' /etc/waagent.conf - set -e -fi - -systemctl stop docker.service -# Also a bad image: the umount should also go away. -umount /var/lib/docker || true -mkfs.xfs -f /dev/sdb1 -echo '/dev/sdb1 /var/lib/docker xfs grpquota 0 0' >>/etc/fstab -mount /var/lib/docker -restorecon -R /var/lib/docker -systemctl start docker.service - -{{if eq .Role "infra"}} -echo "BOOTSTRAP_CONFIG_NAME=node-config-infra" >>/etc/sysconfig/${SERVICE_TYPE}-node -{{else}} -echo "BOOTSTRAP_CONFIG_NAME=node-config-compute" >>/etc/sysconfig/${SERVICE_TYPE}-node -{{end}} - -sed -i -e "s#DEBUG_LOGLEVEL=2#DEBUG_LOGLEVEL=4#" /etc/sysconfig/${SERVICE_TYPE}-node - -rm -rf /etc/etcd/* /etc/origin/master/* - -( cd / && base64 -d <<< {{ .ConfigBundle | shellQuote }} | tar -xz) - -cp /etc/origin/node/ca.crt /etc/pki/ca-trust/source/anchors/openshift-ca.crt -update-ca-trust - -# note: ${SERVICE_TYPE}-node crash loops until master is up -systemctl enable ${SERVICE_TYPE}-node.service -systemctl start ${SERVICE_TYPE}-node.service & - -while [[ $(KUBECONFIG=/etc/origin/node/node.kubeconfig oc get node $(hostname) -o template \ - --template '{{`{{range .status.conditions}}{{if eq .type "Ready"}}{{.status}}{{end}}{{end}}`}}') != True ]]; do - sleep 1 -done diff --git a/parts/swarm/Install-ContainerHost-And-Join-Swarm.ps1 b/parts/swarm/Install-ContainerHost-And-Join-Swarm.ps1 deleted file mode 100644 index 360c8c44e3..0000000000 --- a/parts/swarm/Install-ContainerHost-And-Join-Swarm.ps1 +++ /dev/null @@ -1,214 +0,0 @@ -############################################################ -# Script adapted from -# https://raw.githubusercontent.com/Microsoft/Virtualization-Documentation/master/windows-server-container-tools/Install-ContainerHost/Install-ContainerHost.ps1 - -<# - .NOTES - Copyright (c) Microsoft Corporation. All rights reserved. - - Use of this sample source code is subject to the terms of the Microsoft - license agreement under which you licensed this sample source code. If - you did not accept the terms of the license agreement, you are not - authorized to use this sample source code. For the terms of the license, - please see the license agreement between you and Microsoft or, if applicable, - see the LICENSE.RTF on your install media or the root of your tools installation. - THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES. - - .SYNOPSIS - Installs the prerequisites for creating Windows containers - Opens TCP ports (80,443,2375,8080) in Windows Firewall. - Connects Docker to a swarm master. - - .DESCRIPTION - Installs the prerequisites for creating Windows containers - Opens TCP ports (80,443,2375,8080) in Windows Firewall. - Connects Docker to a swarm master. - - .PARAMETER SwarmMasterIP - IP Address of Docker Swarm Master - - .EXAMPLE - .\Install-ContainerHost.ps1 -SwarmMasterIP 192.168.255.5 - -#> -#Requires -Version 5.0 - -[CmdletBinding(DefaultParameterSetName="Standard")] -param( - [string] - [ValidateNotNullOrEmpty()] - $SwarmMasterIP = "172.16.0.5" -) - -$global:DockerServiceName = "Docker" -$global:HNSServiceName = "hns" - -filter Timestamp {"$(Get-Date -Format o): $_"} - -function Write-Log($message) -{ - $msg = $message | Timestamp - Write-Output $msg -} - -function -Start-Docker() -{ - Write-Log "Starting $global:DockerServiceName..." - $startTime = Get-Date - - while (-not $dockerReady) - { - try - { - Start-Service -Name $global:DockerServiceName -ea Stop - - $dockerReady = $true - } - catch - { - $timeElapsed = $(Get-Date) - $startTime - if ($($timeElapsed).TotalMinutes -ge 5) - { - Write-Log "Docker Daemon did not start successfully within 5 minutes." - break - } - - $errorStr = $_.Exception.Message - Write-Log "Starting Service failed: $errorStr" - Write-Log "sleeping for 10 seconds..." - Start-Sleep -sec 10 - } - } -} - - -function -Stop-Docker() -{ - Write-Log "Stopping $global:DockerServiceName..." - try - { - Stop-Service -Name $global:DockerServiceName -ea Stop - } - catch - { - Write-Log "Failed to stop Docker" - } -} - -function -Update-DockerServiceRecoveryPolicy() -{ - $dockerReady = $false - $startTime = Get-Date - - # wait until the service exists - while (-not $dockerReady) - { - if (Get-Service $global:DockerServiceName -ErrorAction SilentlyContinue) - { - $dockerReady = $true - } - else - { - $timeElapsed = $(Get-Date) - $startTime - if ($($timeElapsed).TotalMinutes -ge 5) - { - Write-Log "Unable to find service $global:DockerServiceName within 5 minutes." - break - } - Write-Log "failed to find $global:DockerServiceName, sleeping for 5 seconds" - Start-Sleep -sec 5 - } - } - - Write-Log "Updating docker restart policy, to ensure it restarts on error" - $services = Get-WMIObject win32_service | Where-Object {$_.name -imatch $global:DockerServiceName} - foreach ($service in $services) - { - sc.exe failure $service.name reset= 86400 actions= restart/5000 - } -} - -# Open Windows Firewall Ports Needed -function Open-FirewallPorts() -{ - $ports = @(80,443,2375,8080) - foreach ($port in $ports) - { - $netsh = "netsh advfirewall firewall add rule name='Open Port $port' dir=in action=allow protocol=TCP localport=$port" - Write-Log "enabling port with command $netsh" - Invoke-Expression -Command:$netsh - } -} - -# Update Docker Config to have cluster-store=consul:// address configured for Swarm cluster. -function Write-DockerDaemonJson() -{ - $dataDir = $env:ProgramData - - # create the target directory - $targetDir = $dataDir + '\docker\config' - if(!(Test-Path -Path $targetDir )){ - New-Item -ItemType directory -Path $targetDir - } - - Write-Log "Delete key file, so that this node is unique to swarm" - $keyFileName = "$targetDir\key.json" - Write-Log "Removing $($keyFileName)" - if (Test-Path $keyFileName) { - Remove-Item $keyFileName - } - - $ipAddress = Get-IPAddress - - Write-Log "Advertise $($ipAddress) to consul://$($SwarmMasterIP):8500" - $OutFile = @" -{ - "hosts": ["tcp://0.0.0.0:2375", "npipe://"], - "cluster-store": "consul://$($SwarmMasterIP):8500", - "cluster-advertise": "$($ipAddress):2375" -} -"@ - - $OutFile | Out-File -encoding ASCII -filepath "$targetDir\daemon.json" -} - -# Get Node IPV4 Address -function Get-IPAddress() -{ - return (Get-NetIPAddress | where {$_.IPAddress -Like '10.*' -and $_.AddressFamily -eq 'IPV4'})[0].IPAddress -} - -try -{ - Write-Log "Provisioning $global:DockerServiceName... with Swarm IP $SwarmMasterIP" - - Write-Log "Stop Docker" - Stop-Docker - - Write-Log "Opening firewall ports" - Open-FirewallPorts - - Write-Log "Write Docker Configuration" - Write-DockerDaemonJson - - Write-Log "Update Docker restart policy" - Update-DockerServiceRecoveryPolicy - - Write-Log "Start Docker" - Start-Docker - - #remove-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Wininit" Headless - #Write-Log "shutdown /r /f /t 60" - #shutdown /r /f /t 60 - - Write-Log "Setup Complete" -} -catch -{ - Write-Error $_ -} - - diff --git a/parts/swarm/Join-SwarmMode-cluster.ps1 b/parts/swarm/Join-SwarmMode-cluster.ps1 deleted file mode 100644 index 26e0521d56..0000000000 --- a/parts/swarm/Join-SwarmMode-cluster.ps1 +++ /dev/null @@ -1,335 +0,0 @@ -############################################################ -# Script adapted from -# https://raw.githubusercontent.com/Microsoft/Virtualization-Documentation/master/windows-server-container-tools/Install-ContainerHost/Install-ContainerHost.ps1 - -<# - .NOTES - Copyright (c) Microsoft Corporation. All rights reserved. - - Use of this sample source code is subject to the terms of the Microsoft - license agreement under which you licensed this sample source code. If - you did not accept the terms of the license agreement, you are not - authorized to use this sample source code. For the terms of the license, - please see the license agreement between you and Microsoft or, if applicable, - see the LICENSE.RTF on your install media or the root of your tools installation. - THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES. - - .SYNOPSIS - Installs the prerequisites for creating Windows containers - Opens TCP ports (80,443,2375,8080) in Windows Firewall. - Connects Docker to a Swarm Mode master. - - .DESCRIPTION - Installs the prerequisites for creating Windows containers - Opens TCP ports (80,443,2375,8080) in Windows Firewall. - Connects Docker to a Swarm Mode master. - - .PARAMETER SwarmMasterIP - IP Address of Docker Swarm Mode Master - - .EXAMPLE - .\Join-SwarmMode-cluster.ps1 -SwarmMasterIP 192.168.255.5 - -#> -#Requires -Version 5.0 - -[CmdletBinding(DefaultParameterSetName="Standard")] -param( - [string] - [ValidateNotNullOrEmpty()] - $SwarmMasterIP = "172.16.0.5" -) - -$global:DockerServiceName = "Docker" -$global:DockerBinariesURL = "https://acsengine.blob.core.windows.net/swarmm/docker.zip" -$global:DockerExePath = "C:\Program Files\Docker" -$global:IsNewDockerVersion = $false - -filter Timestamp {"$(Get-Date -Format o): $_"} - -function Write-Log($message) -{ - $msg = $message | Timestamp - Write-Output $msg -} - -function Start-Docker() -{ - Write-Log "Starting $global:DockerServiceName..." - $startTime = Get-Date - - while (-not $dockerReady) - { - try - { - Start-Service -Name $global:DockerServiceName -ea Stop - - $dockerReady = $true - } - catch - { - $timeElapsed = $(Get-Date) - $startTime - if ($($timeElapsed).TotalMinutes -ge 5) - { - Write-Log "Docker Daemon did not start successfully within 5 minutes." - break - } - - $errorStr = $_.Exception.Message - Write-Log "Starting Service failed: $errorStr" - Write-Log "sleeping for 10 seconds..." - Start-Sleep -sec 10 - } - } -} - -function Stop-Docker() -{ - Write-Log "Stopping $global:DockerServiceName..." - try - { - Stop-Service -Name $global:DockerServiceName -ea Stop - } - catch - { - Write-Log "Failed to stop Docker" - } -} - -function Expand-ZIPFile($file, $destination) -{ - $shell = new-object -com shell.application - $zip = $shell.NameSpace($file) - foreach($item in $zip.items()) - { - $shell.Namespace($destination).copyhere($item, 0x14) - } -} - -function Install-DockerBinaries() -{ - if( $global:IsNewDockerVersion) - { - Write-Log "Skipping installation of new Docker binaries because latest is already installed." - return - } - - $currentRetry = 0; - $success = $false; - - $zipfile = "c:\swarmm.zip" - - do { - try - { - Write-Log "Downloading and installing Docker binaries...." - Invoke-WebRequest -Uri $global:DockerBinariesURL -OutFile $zipfile - $success = $true; - Write-Log "Successfully downloaded Docker binaries. Number of retries: $currentRetry"; - } - catch [System.Exception] - { - $message = 'Exception occurred while trying to download binaries:' + $_.Exception.ToString(); - Write-Log $message; - if ($currentRetry -gt 5) { - $message = "Could not download Docker binaries, aborting install. Error: " + $_.Exception.ToString(); - throw $message; - } else { - Write-Log "Sleeping before retry number: $currentRetry to download binaries."; - Start-Sleep -sec 5; - } - $currentRetry = $currentRetry + 1; - } - } while (!$success); - - Write-Log "Expanding zip file at destination: $global:DockerExePath" - Expand-ZIPFile -File $zipfile -Destination $global:DockerExePath - - Write-Log "Deleting zip file at: $zipfile" - Remove-Item $zipfile -} - -function Update-DockerServiceRecoveryPolicy() -{ - $dockerReady = $false - $startTime = Get-Date - - # wait until the service exists - while (-not $dockerReady) - { - if (Get-Service $global:DockerServiceName -ErrorAction SilentlyContinue) - { - $dockerReady = $true - } - else - { - $timeElapsed = $(Get-Date) - $startTime - if ($($timeElapsed).TotalMinutes -ge 5) - { - Write-Log "Unable to find service $global:DockerServiceName within 5 minutes." - break - } - Write-Log "failed to find $global:DockerServiceName, sleeping for 5 seconds" - Start-Sleep -sec 5 - } - } - - Write-Log "Updating docker restart policy, to ensure it restarts on error" - $services = Get-WMIObject win32_service | Where-Object {$_.name -imatch $global:DockerServiceName} - foreach ($service in $services) - { - sc.exe failure $service.name reset= 86400 actions= restart/5000 - } -} - -# Open Windows Firewall Ports Needed -function Open-FirewallPorts() -{ - $tcpports = @(80,443,2375,8080,2377,7946,4789) - foreach ($tcpport in $tcpports) - { - $netsh = "netsh advfirewall firewall add rule name='Open Port $tcpport' dir=in action=allow protocol=TCP localport=$tcpport" - Write-Log "enabling port with command $netsh" - Invoke-Expression -Command:$netsh - } - - $udpports = @(7946,4789) - foreach ($udpport in $udpports) - { - $netsh = "netsh advfirewall firewall add rule name='Open Port $udpport' dir=in action=allow protocol=UDP localport=$udpport" - Write-Log "enabling port with command $netsh" - Invoke-Expression -Command:$netsh - } -} - -# Update Docker Config to have cluster-store=consul:// address configured for Swarm cluster. -function Write-DockerDaemonJson() -{ - $dataDir = $env:ProgramData - - # create the target directory - $targetDir = $dataDir + '\docker\config' - if(!(Test-Path -Path $targetDir )){ - New-Item -ItemType directory -Path $targetDir - } - - Write-Log "Delete key file, so that this node is unique to swarm" - $keyFileName = "$targetDir\key.json" - Write-Log "Removing $($keyFileName)" - if (Test-Path $keyFileName) { - Remove-Item $keyFileName - } - - Write-Log "Configure Docker Engine to accept incoming connections on port 2375" - $OutFile = @" -{ - "hosts": ["tcp://0.0.0.0:2375", "npipe://"] -} -"@ - - $OutFile | Out-File -encoding ASCII -filepath "$targetDir\daemon.json" -} - -function Join-Swarm() -{ - $currentRetry = 0; - $success = $false; - $getTokenCommand = "docker -H $($SwarmMasterIP):2375 swarm join-token -q worker" - $swarmmodetoken; - - do { - try - { - Write-Log "Executing [$getTokenCommand] command...." - <#& $swarmmodetoken#> - $swarmmodetoken = Invoke-Expression -Command:$getTokenCommand - $success = $true; - Write-Log "Successfully executed [$getTokenCommand] command. Number of entries: $currentRetry. Token: [$swarmmodetoken]"; - } - catch [System.Exception] - { - $message = 'Exception occurred while trying to execute command [$swarmmodetoken]:' + $_.Exception.ToString(); - Write-Log $message; - if ($currentRetry -gt 120) { - $message = "Agent couldn't join Swarm, aborting install. Error: " + $_.Exception.ToString(); - throw $message; - } else { - Write-Log "Sleeping before $currentRetry retry of [$getTokenCommand] command"; - Start-Sleep -sec 5; - } - $currentRetry = $currentRetry + 1; - } - } while (!$success); - - $joinSwarmCommand = "docker swarm join --token $($swarmmodetoken) $($SwarmMasterIP):2377" - Write-Log "Joining Swarm. Command [$joinSwarmCommand]...." - Invoke-Expression -Command:$joinSwarmCommand -} - -function Confirm-DockerVersion() -{ - $dockerServerVersionCmd = "docker version --format '{{.Server.Version}}'" - Write-Log "Running command: $dockerServerVersionCmd" - $dockerServerVersion = Invoke-Expression -Command:$dockerServerVersionCmd - - $dockerClientVersionCmd = "docker version --format '{{.Client.Version}}'" - Write-Log "Running command: $dockerClientVersionCmd" - $dockerClientVersion = Invoke-Expression -Command:$dockerClientVersionCmd - - Write-Log "Docker Server version: $dockerServerVersion, Docker Client verison: $dockerClientVersion" - - $serverVersionData = $dockerServerVersion.Split(".") - $isNewServerVersion = $false; - if(($serverVersionData[0] -ge 1) -and ($serverVersionData[1] -ge 13)){ - $isNewServerVersion = $true; - Write-Log "Setting isNewServerVersion to $isNewServerVersion" - } - - $clientVersionData = $dockerClientVersion.Split(".") - $isNewClientVersion = $false; - if(($clientVersionData[0] -ge 1) -and ($clientVersionData[1] -ge 13)){ - $isNewClientVersion = $true; - Write-Log "Setting isNewClientVersion to $isNewClientVersion" - } - - if($isNewServerVersion -and $isNewClientVersion) - { - $global:IsNewDockerVersion = $true; - Write-Log "Setting IsNewDockerVersion to $global:IsNewDockerVersion" - } -} - -try -{ - Write-Log "Provisioning $global:DockerServiceName... with Swarm IP $SwarmMasterIP" - - Write-Log "Checking Docker version" - Confirm-DockerVersion - - Write-Log "Stop Docker" - Stop-Docker - - Write-Log "Installing Docker binaries" - Install-DockerBinaries - - Write-Log "Opening firewall ports" - Open-FirewallPorts - - Write-Log "Write Docker Configuration" - Write-DockerDaemonJson - - Write-Log "Update Docker restart policy" - Update-DockerServiceRecoveryPolicy - - Write-Log "Start Docker" - Start-Docker - - Write-Log "Join existing Swarm" - Join-Swarm - - Write-Log "Setup Complete" -} -catch -{ - Write-Error $_ -} \ No newline at end of file diff --git a/parts/swarm/configure-swarm-cluster.sh b/parts/swarm/configure-swarm-cluster.sh deleted file mode 100644 index 7b2532b209..0000000000 --- a/parts/swarm/configure-swarm-cluster.sh +++ /dev/null @@ -1,294 +0,0 @@ -#!/bin/bash - -set -x - -echo "starting swarm cluster configuration" -date -ps ax - -############# -# Parameters -############# - -SWARM_VERSION=${1} -DOCKER_COMPOSE_VERSION=${2} -MASTERCOUNT=${3} -MASTERPREFIX=${4} -MASTERFIRSTADDR=${5} -AZUREUSER=${6} -POSTINSTALLSCRIPTURI=${7} -BASESUBNET=${8} -DOCKERENGINEDOWNLOADREPO=${9} -DOCKERCOMPOSEDOWNLOADURL=${10} -DOCKER_CE_VERSION=17.03.* -VMNAME=`hostname` -VMNUMBER=`echo $VMNAME | sed 's/.*[^0-9]\([0-9]\+\)*$/\1/'` -VMPREFIX=`echo $VMNAME | sed 's/\(.*[^0-9]\)*[0-9]\+$/\1/'` - -echo "Master Count: $MASTERCOUNT" -echo "Master Prefix: $MASTERPREFIX" -echo "Master First Addr: $MASTERFIRSTADDR" -echo "vmname: $VMNAME" -echo "VMNUMBER: $VMNUMBER, VMPREFIX: $VMPREFIX" -echo "BASESUBNET: $BASESUBNET" -echo "AZUREUSER: $AZUREUSER" - -################### -# Common Functions -################### - -ensureAzureNetwork() -{ - # ensure the network works - networkHealthy=1 - for i in {1..12}; do - wget -O/dev/null http://bing.com - if [ $? -eq 0 ] - then - # hostname has been found continue - networkHealthy=0 - echo "the network is healthy" - break - fi - sleep 10 - done - if [ $networkHealthy -ne 0 ] - then - echo "the network is not healthy, aborting install" - ifconfig - ip a - exit 1 - fi - # ensure the host ip can resolve - networkHealthy=1 - for i in {1..120}; do - hostname -i - if [ $? -eq 0 ] - then - # hostname has been found continue - networkHealthy=0 - echo "the network is healthy" - break - fi - sleep 1 - done - # attempt to fix hostname, in case dns is not resolving Azure IPs (but can resolve public ips) - if [ $networkHealthy -ne 0 ] - then - HOSTNAME=`hostname` - HOSTADDR=`ip address show dev eth0 | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*'` - echo $HOSTADDR $HOSTNAME >> /etc/hosts - hostname -i - if [ $? -eq 0 ] - then - # hostname has been found continue - networkHealthy=0 - echo "the network is healthy by updating /etc/hosts" - fi - fi - if [ $networkHealthy -ne 0 ] - then - echo "the network is not healthy, cannot resolve ip address, aborting install" - ifconfig - ip a - exit 2 - fi -} -ensureAzureNetwork -HOSTADDR=`hostname -i` - -# apply all Canonical security updates during provisioning -/usr/lib/apt/apt.systemd.daily - -ismaster () -{ - if [ "$MASTERPREFIX" == "$VMPREFIX" ] - then - return 0 - else - return 1 - fi -} -if ismaster ; then - echo "this node is a master" -fi - -isagent() -{ - if ismaster ; then - return 1 - else - return 0 - fi -} -if isagent ; then - echo "this node is an agent" -fi - -consulstr() -{ - consulargs="" - for i in `seq 0 $((MASTERCOUNT-1))` ; - do - MASTEROCTET=`expr $MASTERFIRSTADDR + $i` - IPADDR="${BASESUBNET}${MASTEROCTET}" - - if [ "$VMNUMBER" -eq "0" ] - then - consulargs="${consulargs}-bootstrap-expect $MASTERCOUNT " - fi - if [ "$VMNUMBER" -eq "$i" ] - then - consulargs="${consulargs}-advertise $IPADDR " - else - consulargs="${consulargs}-retry-join $IPADDR " - fi - done - echo $consulargs -} - -consulargs=$(consulstr) -MASTER0IPADDR="${BASESUBNET}${MASTERFIRSTADDR}" - -###################### -# resolve self in DNS -###################### - -echo "$HOSTADDR $VMNAME" | sudo tee -a /etc/hosts - -################ -# Install Docker -################ - -echo "Installing and configuring docker" - -# simple general command retry function -retrycmd_if_failure() { for i in 1 2 3 4 5; do $@; [ $? -eq 0 ] && break || sleep 5; done ; } - -installDocker() -{ - for i in {1..10}; do - apt-get install -y apt-transport-https ca-certificates curl software-properties-common - curl --max-time 60 -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - - add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" - apt-get update - apt-get install -y docker-ce=${DOCKER_CE_VERSION} - if [ $? -eq 0 ] - then - # hostname has been found continue - echo "Docker installed successfully" - break - fi - sleep 10 - done -} -time installDocker -sudo usermod -aG docker $AZUREUSER -if isagent ; then - # Start Docker and listen on :2375 (no auth, but in vnet) - echo 'DOCKER_OPTS="-H unix:///var/run/docker.sock -H 0.0.0.0:2375 --cluster-store=consul://'$MASTER0IPADDR:8500 --cluster-advertise=$HOSTADDR:2375'"' | sudo tee -a /etc/default/docker -fi - -echo "Installing docker compose" -installDockerCompose() -{ - for i in {1..10}; do - wget --tries 4 --retry-connrefused --waitretry=15 -qO- $DOCKERCOMPOSEDOWNLOADURL/$DOCKER_COMPOSE_VERSION/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose - if [ $? -eq 0 ] - then - # hostname has been found continue - echo "docker-compose installed successfully" - break - fi - sleep 10 - done -} -time installDockerCompose -chmod +x /usr/local/bin/docker-compose - -sudo service docker restart - -ensureDocker() -{ - # ensure that docker is healthy - dockerHealthy=1 - for i in {1..3}; do - sudo docker info - if [ $? -eq 0 ] - then - # hostname has been found continue - dockerHealthy=0 - echo "Docker is healthy" - sudo docker ps -a - break - fi - sleep 10 - done - if [ $dockerHealthy -ne 0 ] - then - echo "Docker is not healthy" - fi -} -ensureDocker - -############################################## -# configure init rules restart all processes -############################################## - -if ismaster ; then - mkdir -p /data/consul - echo "consul: - image: \"progrium/consul\" - command: -server -node $VMNAME $consulargs - ports: - - \"8500:8500\" - - \"8300:8300\" - - \"8301:8301\" - - \"8301:8301/udp\" - - \"8302:8302\" - - \"8302:8302/udp\" - - \"8400:8400\" - volumes: - - \"/data/consul:/data\" - restart: \"always\" -swarm: - image: \"$SWARM_VERSION\" - command: manage --replication --advertise $HOSTADDR:2375 --discovery-opt kv.path=docker/nodes consul://$MASTER0IPADDR:8500 - ports: - - \"2375:2375\" - links: - - \"consul\" - volumes: - - \"/etc/docker:/etc/docker\" - restart: \"always\" -" > /opt/azure/containers/docker-compose.yml - - pushd /opt/azure/containers/ - docker-compose up -d - popd - echo "completed starting docker swarm on the master" -fi - -if ismaster ; then - echo "Having ssh listen to port 2222 as well as 22" - sudo sed -i "s/^Port 22$/Port 22\nPort 2222/1" /etc/ssh/sshd_config -fi - -if [ $POSTINSTALLSCRIPTURI != "disabled" ] -then - echo "downloading, and kicking off post install script" - /bin/bash -c "wget --tries 20 --retry-connrefused --waitretry=15 -qO- $POSTINSTALLSCRIPTURI | nohup /bin/bash >> /var/log/azure/cluster-bootstrap-postinstall.log 2>&1 &" -fi - -echo "processes at end of script" -ps ax -date -echo "completed Swarm cluster configuration" - -echo "restart system to install any remaining software" -if isagent ; then - shutdown -r now -else - # wait 1 minute to restart master - /bin/bash -c "shutdown -r 1 &" -fi diff --git a/parts/swarm/configure-swarmmode-cluster.sh b/parts/swarm/configure-swarmmode-cluster.sh deleted file mode 100644 index 20cb2edbd7..0000000000 --- a/parts/swarm/configure-swarmmode-cluster.sh +++ /dev/null @@ -1,374 +0,0 @@ -#!/bin/bash - -########################################################### -# Configure Swarm Mode One Box -# -# This installs the following components -# - Docker -# - Docker Compose -# - Swarm Mode masters -# - Swarm Mode agents -########################################################### - -set -x - -echo "starting Swarm Mode cluster configuration" -date -ps ax - -############# -# Parameters -############# - -DOCKER_CE_VERSION=${1} -DOCKER_COMPOSE_VERSION=${2} -MASTERCOUNT=${3} -MASTERPREFIX=${4} -MASTERFIRSTADDR=${5} -AZUREUSER=${6} -POSTINSTALLSCRIPTURI=${7} -BASESUBNET=${8} -DOCKERENGINEDOWNLOADREPO=${9} -DOCKERCOMPOSEDOWNLOADURL=${10} -VMNAME=`hostname` -VMNUMBER=`echo $VMNAME | sed 's/.*[^0-9]\([0-9]\+\)*$/\1/'` -VMPREFIX=`echo $VMNAME | sed 's/\(.*[^0-9]\)*[0-9]\+$/\1/'` -OS="$(. /etc/os-release; echo $ID)" - -echo "Master Count: $MASTERCOUNT" -echo "Master Prefix: $MASTERPREFIX" -echo "Master First Addr: $MASTERFIRSTADDR" -echo "vmname: $VMNAME" -echo "VMNUMBER: $VMNUMBER, VMPREFIX: $VMPREFIX" -echo "BASESUBNET: $BASESUBNET" -echo "AZUREUSER: $AZUREUSER" -echo "OS ID: $OS" - -################### -# Common Functions -################### - -isUbuntu() -{ - if [ "$OS" == "ubuntu" ] - then - return 0 - else - return 1 - fi -} - -isRHEL() -{ - if [ "$OS" == "rhel" ] - then - return 0 - else - return 1 - fi -} - -ensureAzureNetwork() -{ - # ensure the network works - networkHealthy=1 - for i in {1..12}; do - wget -O/dev/null http://bing.com - if [ $? -eq 0 ] - then - # hostname has been found continue - networkHealthy=0 - echo "the network is healthy" - break - fi - sleep 10 - done - if [ $networkHealthy -ne 0 ] - then - echo "the network is not healthy, aborting install" - ifconfig - ip a - exit 1 - fi - # ensure the host ip can resolve - networkHealthy=1 - for i in {1..120}; do - hostname -i - if [ $? -eq 0 ] - then - # hostname has been found continue - networkHealthy=0 - echo "the network is healthy" - break - fi - sleep 1 - done - # attempt to fix hostname, in case dns is not resolving Azure IPs (but can resolve public ips) - if [ $networkHealthy -ne 0 ] - then - HOSTNAME=`hostname` - HOSTADDR=`ip address show dev eth0 | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*'` - echo $HOSTADDR $HOSTNAME >> /etc/hosts - hostname -i - if [ $? -eq 0 ] - then - # hostname has been found continue - networkHealthy=0 - echo "the network is healthy by updating /etc/hosts" - fi - fi - if [ $networkHealthy -ne 0 ] - then - echo "the network is not healthy, cannot resolve ip address, aborting install" - ifconfig - ip a - exit 2 - fi -} -ensureAzureNetwork -HOSTADDR=`hostname -i` - -# apply all Canonical security updates during provisioning -/usr/lib/apt/apt.systemd.daily - -ismaster () -{ - if [ "$MASTERPREFIX" == "$VMPREFIX" ] - then - return 0 - else - return 1 - fi -} -if ismaster ; then - echo "this node is a master" -fi - -isagent() -{ - if ismaster ; then - return 1 - else - return 0 - fi -} -if isagent ; then - echo "this node is an agent" -fi - -MASTER0IPADDR="${BASESUBNET}${MASTERFIRSTADDR}" - -###################### -# resolve self in DNS -###################### - -if [ -z "$(grep "$HOSTADDR $VMNAME" /etc/hosts)" ]; then - echo "$HOSTADDR $VMNAME" | sudo tee -a /etc/hosts -fi - -################ -# Install Docker -################ - -echo "Installing and configuring Docker" - -installDockerUbuntu() -{ - for i in {1..10}; do - apt-get install -y apt-transport-https ca-certificates curl software-properties-common - curl --max-time 60 -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - - add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" - apt-get update - apt-get install -y docker-ce=${DOCKER_CE_VERSION} - if [ $? -eq 0 ] - then - systemctl restart docker - # hostname has been found continue - echo "Docker installed successfully" - break - fi - sleep 10 - done -} - -installDockerRHEL() -{ - for i in {1..10}; do - yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo - yum makecache fast - yum -y install docker-ce - if [ $? -eq 0 ] - then - systemctl enable docker - systemctl start docker - echo "Docker installed successfully" - break - fi - sleep 10 - done -} - -installDocker() -{ - if isUbuntu ; then - installDockerUbuntu - elif isRHEL ; then - installDockerRHEL - else - echo "OS not supported, aborting install" - exit 5 - fi -} - -time installDocker - -sudo usermod -aG docker $AZUREUSER - -echo "Updating Docker daemon options" - -updateDockerDaemonOptions() -{ - sudo mkdir -p /etc/systemd/system/docker.service.d - # Start Docker and listen on :2375 (no auth, but in vnet) and - # also have it bind to the unix socket at /var/run/docker.sock - sudo bash -c 'echo "[Service] - ExecStart= - ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock - " > /etc/systemd/system/docker.service.d/override.conf' -} -time updateDockerDaemonOptions - -echo "Installing Docker Compose" -installDockerCompose() -{ - # sudo -i - - for i in {1..10}; do - wget --tries 4 --retry-connrefused --waitretry=15 -qO- $DOCKERCOMPOSEDOWNLOADURL/$DOCKER_COMPOSE_VERSION/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose - if [ $? -eq 0 ] - then - # hostname has been found continue - echo "docker-compose installed successfully" - break - fi - sleep 10 - done -} -time installDockerCompose -chmod +x /usr/local/bin/docker-compose - -if ismaster && isRHEL ; then - echo "Opening Docker ports" - firewall-cmd --add-port=2375/tcp --permanent - firewall-cmd --add-port=2377/tcp --permanent - firewall-cmd --reload -fi - -echo "Restarting Docker" -sudo systemctl daemon-reload -sudo service docker restart - -ensureDocker() -{ - # ensure that docker is healthy - dockerHealthy=1 - for i in {1..3}; do - sudo docker info - if [ $? -eq 0 ] - then - # hostname has been found continue - dockerHealthy=0 - echo "Docker is healthy" - sudo docker ps -a - break - fi - sleep 10 - done - if [ $dockerHealthy -ne 0 ] - then - echo "Docker is not healthy" - fi -} -ensureDocker - -############################################## -# configure init rules restart all processes -############################################## - -if ismaster ; then - if [ "$HOSTADDR" = "$MASTER0IPADDR" ]; then - echo "Creating a new Swarm on first master" - docker swarm init --advertise-addr $(hostname -i):2377 --listen-addr $(hostname -i):2377 - else - echo "Secondary master attempting to join an existing Swarm" - swarmmodetoken="" - swarmmodetokenAcquired=1 - for i in {1..120}; do - swarmmodetoken=$(docker -H $MASTER0IPADDR:2375 swarm join-token -q manager) - if [ $? -eq 0 ]; then - swarmmodetokenAcquired=0 - break - fi - sleep 5 - done - if [ $swarmmodetokenAcquired -ne 0 ] - then - echo "Secondary master couldn't connect to Swarm, aborting install" - exit 3 - fi - docker swarm join --token $swarmmodetoken $MASTER0IPADDR:2377 - fi -fi - -if ismaster ; then - echo "Having ssh listen to port 2222 as well as 22" - sudo sed -i "s/^Port 22$/Port 22\nPort 2222/1" /etc/ssh/sshd_config -fi - -if ismaster ; then - echo "Setting availability of master node: '$VMNAME' to pause" - docker node update --availability pause $VMNAME -fi - -if isagent ; then - echo "Agent attempting to join an existing Swarm" - swarmmodetoken="" - swarmmodetokenAcquired=1 - for i in {1..120}; do - swarmmodetoken=$(docker -H $MASTER0IPADDR:2375 swarm join-token -q worker) - if [ $? -eq 0 ]; then - swarmmodetokenAcquired=0 - break - fi - sleep 5 - done - if [ $swarmmodetokenAcquired -ne 0 ] - then - echo "Agent couldn't join Swarm, aborting install" - exit 4 - fi - docker swarm join --token $swarmmodetoken $MASTER0IPADDR:2377 -fi - -if [ $POSTINSTALLSCRIPTURI != "disabled" ] -then - echo "downloading, and kicking off post install script" - /bin/bash -c "wget --tries 20 --retry-connrefused --waitretry=15 -qO- $POSTINSTALLSCRIPTURI | nohup /bin/bash >> /var/log/azure/cluster-bootstrap-postinstall.log 2>&1 &" -fi - -# mitigation for bug https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1676635 -echo 2dd1ce17-079e-403c-b352-a1921ee207ee > /sys/bus/vmbus/drivers/hv_util/unbind -sed -i "13i\echo 2dd1ce17-079e-403c-b352-a1921ee207ee > /sys/bus/vmbus/drivers/hv_util/unbind\n" /etc/rc.local - -echo "processes at end of script" -ps ax -date -echo "completed Swarm Mode cluster configuration" - -echo "restart system to install any remaining software" -if isagent ; then - shutdown -r now -else - # wait 1 minute to restart master - /bin/bash -c "shutdown -r 1 &" -fi diff --git a/parts/swarm/swarmagentresourcesvmas.t b/parts/swarm/swarmagentresourcesvmas.t deleted file mode 100644 index 9843181871..0000000000 --- a/parts/swarm/swarmagentresourcesvmas.t +++ /dev/null @@ -1,258 +0,0 @@ - { - "apiVersion": "[variables('apiVersionDefault')]", - "copy": { - "count": "[variables('{{.Name}}Count')]", - "name": "loop" - }, - "dependsOn": [ -{{if not .IsCustomVNET}} - "[variables('vnetID')]" -{{end}} -{{if IsPublic .Ports}} - ,"[variables('{{.Name}}LbID')]" -{{end}} - ], - "location": "[variables('location')]", - "name": "[concat(variables('{{.Name}}VMNamePrefix'), 'nic-', copyIndex(variables('{{.Name}}Offset')))]", - "properties": { - "ipConfigurations": [ - { - "name": "ipConfigNode", - "properties": { -{{if IsPublic .Ports}} - "loadBalancerBackendAddressPools": [ - { - "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/loadBalancers/', variables('{{.Name}}LbName'), '/backendAddressPools/',variables('{{.Name}}LbBackendPoolName'))]" - } - ], -{{end}} - "privateIPAllocationMethod": "Dynamic", - "subnet": { - "id": "[variables('{{.Name}}VnetSubnetID')]" - } - } - } - ] - }, - "type": "Microsoft.Network/networkInterfaces" - }, -{{if .IsManagedDisks}} - { - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}AvailabilitySet')]", - "properties": { - "platformFaultDomainCount": 2, - "platformUpdateDomainCount": 3, - "managed": "true" - }, - "type": "Microsoft.Compute/availabilitySets" - }, -{{else if .IsStorageAccount}} - { - "apiVersion": "[variables('apiVersionStorage')]", - "copy": { - "count": "[variables('{{.Name}}StorageAccountsCount')]", - "name": "vmLoopNode" - }, - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('storageAccountPrefixes')[mod(add(copyIndex(),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(copyIndex(),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "properties": { - "accountType": "[variables('vmSizesMap')[variables('{{.Name}}VMSize')].storageAccountType]" - }, - "type": "Microsoft.Storage/storageAccounts" - }, - {{if .HasDisks}} - { - "apiVersion": "[variables('apiVersionStorage')]", - "copy": { - "count": "[variables('{{.Name}}StorageAccountsCount')]", - "name": "datadiskLoop" - }, - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('storageAccountPrefixes')[mod(add(copyIndex(variables('dataStorageAccountPrefixSeed')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(copyIndex(variables('dataStorageAccountPrefixSeed')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}DataAccountName'))]", - "properties": { - "accountType": "[variables('vmSizesMap')[variables('{{.Name}}VMSize')].storageAccountType]" - }, - "type": "Microsoft.Storage/storageAccounts" - }, - {{end}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}AvailabilitySet')]", - "properties": {}, - "type": "Microsoft.Compute/availabilitySets" - }, -{{end}} -{{if IsPublic .Ports}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}IPAddressName')]", - "properties": { - "dnsSettings": { - "domainNameLabel": "[variables('{{.Name}}EndpointDNSNamePrefix')]" - }, - "publicIPAllocationMethod": "Dynamic" - }, - "type": "Microsoft.Network/publicIPAddresses" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('{{.Name}}IPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('{{.Name}}LbName')]", - "properties": { - "backendAddressPools": [ - { - "name": "[variables('{{.Name}}LbBackendPoolName')]" - } - ], - "frontendIPConfigurations": [ - { - "name": "[variables('{{.Name}}LbIPConfigName')]", - "properties": { - "publicIPAddress": { - "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('{{.Name}}IPAddressName'))]" - } - } - } - ], - "inboundNatRules": [], - "loadBalancingRules": [ - {{(GetLBRules .Name .Ports)}} - ], - "probes": [ - {{(GetProbes .Ports)}} - ] - }, - "type": "Microsoft.Network/loadBalancers" - }, -{{end}} - { -{{if .IsManagedDisks}} - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", -{{else}} - "apiVersion": "[variables('apiVersionDefault')]", -{{end}} - "copy": { - "count": "[variables('{{.Name}}Count')]", - "name": "vmLoopNode" - }, - "dependsOn": [ -{{if .IsStorageAccount}} - "[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - {{if .HasDisks}} - "[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('dataStorageAccountPrefixSeed')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('dataStorageAccountPrefixSeed')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}DataAccountName'))]", - {{end}} -{{end}} - "[concat('Microsoft.Network/networkInterfaces/', variables('{{.Name}}VMNamePrefix'), 'nic-', copyIndex(variables('{{.Name}}Offset')))]", - "[concat('Microsoft.Compute/availabilitySets/', variables('{{.Name}}AvailabilitySet'))]" - ], - "tags": - { - "creationSource" : "[concat('acsengine-', variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')))]" - }, - "location": "[variables('location')]", - "name": "[concat(variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')))]", - "properties": { - "availabilitySet": { - "id": "[resourceId('Microsoft.Compute/availabilitySets',variables('{{.Name}}AvailabilitySet'))]" - }, - "hardwareProfile": { - "vmSize": "[variables('{{.Name}}VMSize')]" - }, - "networkProfile": { - "networkInterfaces": [ - { - "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(variables('{{.Name}}VMNamePrefix'), 'nic-', copyIndex(variables('{{.Name}}Offset'))))]" - } - ] - }, - "osProfile": { - "adminUsername": "[variables('adminUsername')]", - "computername": "[concat(variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')))]", -{{if IsSwarmMode}} - {{if not .IsRHEL}} - {{GetAgentSwarmModeCustomData .}} - {{end}} -{{else}} - {{GetAgentSwarmCustomData .}} -{{end}} - "linuxConfiguration": { - "disablePasswordAuthentication": "true", - "ssh": { - "publicKeys": [ - { - "keyData": "[parameters('sshRSAPublicKey')]", - "path": "[variables('sshKeyPath')]" - } - ] - } - } - {{if HasLinuxSecrets}} - , - "secrets": "[variables('linuxProfileSecrets')]" - {{end}} - }, - "storageProfile": { - {{GetDataDisks .}} - "imageReference": { - "offer": "[variables('{{.Name}}OSImageOffer')]", - "publisher": "[variables('{{.Name}}OSImagePublisher')]", - "sku": "[variables('{{.Name}}OSImageSKU')]", - "version": "[variables('{{.Name}}OSImageVersion')]" - } - - ,"osDisk": { - "caching": "ReadOnly" - ,"createOption": "FromImage" -{{if .IsStorageAccount}} - ,"name": "[concat(variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')),'-osdisk')]" - ,"vhd": { - "uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'osdisk/', variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')), '-osdisk.vhd')]" - } -{{end}} -{{if ne .OSDiskSizeGB 0}} - ,"diskSizeGB": {{.OSDiskSizeGB}} -{{end}} - } - } - }, - "type": "Microsoft.Compute/virtualMachines" - } -{{if .IsRHEL}} - ,{ - "apiVersion": "[variables('apiVersionDefault')]", - "copy": { - "count": "[variables('{{.Name}}Count')]", - "name": "vmLoopNode" - }, - "dependsOn": [ - "[concat('Microsoft.Compute/virtualMachines/', concat(variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset'))))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')), '/configureagent')]", - "properties": { - "publisher": "Microsoft.Azure.Extensions", - "settings": { - "commandToExecute": "[variables('agentCustomScript')]", - "fileUris": [ - "[concat('{{ GetConfigurationScriptRootURL }}', variables('configureClusterScriptFile'))]" - ] - }, - "type": "CustomScript", - "typeHandlerVersion": "2.0" - }, - "type": "Microsoft.Compute/virtualMachines/extensions" - } -{{end}} diff --git a/parts/swarm/swarmagentresourcesvmss.t b/parts/swarm/swarmagentresourcesvmss.t deleted file mode 100644 index 6a652e7c5f..0000000000 --- a/parts/swarm/swarmagentresourcesvmss.t +++ /dev/null @@ -1,206 +0,0 @@ -{{if .IsStorageAccount}} - { - "apiVersion": "[variables('apiVersionStorage')]", - "copy": { - "count": "[variables('{{.Name}}StorageAccountsCount')]", - "name": "vmLoopNode" - }, - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('storageAccountPrefixes')[mod(add(copyIndex(),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(copyIndex(),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "properties": { - "accountType": "[variables('vmSizesMap')[variables('{{.Name}}VMSize')].storageAccountType]" - }, - "type": "Microsoft.Storage/storageAccounts" - }, -{{end}} -{{if IsPublic .Ports}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}IPAddressName')]", - "properties": { - "dnsSettings": { - "domainNameLabel": "[variables('{{.Name}}EndpointDNSNamePrefix')]" - }, - "publicIPAllocationMethod": "Dynamic" - }, - "type": "Microsoft.Network/publicIPAddresses" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('{{.Name}}IPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('{{.Name}}LbName')]", - "properties": { - "backendAddressPools": [ - { - "name": "[variables('{{.Name}}LbBackendPoolName')]" - } - ], - "frontendIPConfigurations": [ - { - "name": "[variables('{{.Name}}LbIPConfigName')]", - "properties": { - "publicIPAddress": { - "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('{{.Name}}IPAddressName'))]" - } - } - } - ], - "inboundNatRules": [], - "loadBalancingRules": [ - {{(GetLBRules .Name .Ports)}} - ], - "probes": [ - {{(GetProbes .Ports)}} - ] - }, - "type": "Microsoft.Network/loadBalancers" - }, -{{end}} - { -{{if .IsManagedDisks}} - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", -{{else}} - "apiVersion": "[variables('apiVersionDefault')]", -{{end}} - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" -{{if .IsStorageAccount}} - ,"[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountPrefixes')[mod(add(0,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(0,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountPrefixes')[mod(add(1,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(1,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountPrefixes')[mod(add(2,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(2,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountPrefixes')[mod(add(3,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(3,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountPrefixes')[mod(add(4,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(4,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]" -{{end}} -{{if not .IsCustomVNET}} - ,"[variables('vnetID')]" -{{end}} -{{if IsPublic .Ports}} - ,"[variables('{{.Name}}LbID')]" -{{end}} - ], - "tags": - { - "creationSource" : "[concat('acsengine-', variables('{{.Name}}VMNamePrefix'), '-vmss')]" - }, - "location": "[variables('location')]", - "name": "[concat(variables('{{.Name}}VMNamePrefix'), '-vmss')]", - "properties": { - "upgradePolicy": { - "mode": "Automatic" - }, - "virtualMachineProfile": { - "networkProfile": { - "networkInterfaceConfigurations": [ - { - "name": "nic", - "properties": { - "ipConfigurations": [ - { - "name": "nicipconfig", - "properties": { -{{if IsPublic .Ports}} - "loadBalancerBackendAddressPools": [ - { - "id": "[concat(variables('{{.Name}}LbID'), '/backendAddressPools/', variables('{{.Name}}LbBackendPoolName'))]" - } - ], -{{end}} - "subnet": { - "id": "[variables('{{.Name}}VnetSubnetID')]" - } - } - } - ], - "primary": "true" - } - } - ] - }, - "osProfile": { - "adminUsername": "[variables('adminUsername')]", - "computerNamePrefix": "[variables('{{.Name}}VMNamePrefix')]", -{{if IsSwarmMode}} - {{if not .IsRHEL}} - {{GetAgentSwarmModeCustomData .}} - {{end}} -{{else}} - {{GetAgentSwarmCustomData .}} -{{end}} - "linuxConfiguration": { - "disablePasswordAuthentication": "true", - "ssh": { - "publicKeys": [ - { - "keyData": "[parameters('sshRSAPublicKey')]", - "path": "[variables('sshKeyPath')]" - } - ] - } - } - {{if HasLinuxSecrets}} - , - "secrets": "[variables('linuxProfileSecrets')]" - {{end}} - }, - "storageProfile": { - "imageReference": { - "offer": "[variables('{{.Name}}OSImageOffer')]", - "publisher": "[variables('{{.Name}}OSImagePublisher')]", - "sku": "[variables('{{.Name}}OSImageSKU')]", - "version": "[variables('{{.Name}}OSImageVersion')]" - }, - {{GetDataDisks .}} - "osDisk": { - "caching": "ReadWrite" - ,"createOption": "FromImage" -{{if .IsStorageAccount}} - ,"name": "vmssosdisk" - ,"vhdContainers": [ - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(0,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(0,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')), variables('apiVersionStorage') ).primaryEndpoints.blob, 'osdisk')]", - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(1,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(1,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')), variables('apiVersionStorage')).primaryEndpoints.blob, 'osdisk')]", - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(2,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(2,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')), variables('apiVersionStorage')).primaryEndpoints.blob, 'osdisk')]", - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(3,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(3,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')), variables('apiVersionStorage')).primaryEndpoints.blob, 'osdisk')]", - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(4,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(4,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')), variables('apiVersionStorage')).primaryEndpoints.blob, 'osdisk')]" - ] -{{end}} -{{if ne .OSDiskSizeGB 0}} - ,"diskSizeGB": {{.OSDiskSizeGB}} -{{end}} - } - } -{{if .IsRHEL}} - ,"extensionProfile": { - "extensions": [ - { - "name": "configure{{.Name}}", - "properties": { - "publisher": "Microsoft.Azure.Extensions", - "settings": { - "commandToExecute": "[variables('agentCustomScript')]", - "fileUris": [ - "[concat('{{ GetConfigurationScriptRootURL }}', variables('configureClusterScriptFile'))]" - ] - }, - "type": "CustomScript", - "typeHandlerVersion": "2.0" - } - } - ] - } -{{end}} - } - }, - "sku": { - "capacity": "[variables('{{.Name}}Count')]", - "name": "[variables('{{.Name}}VMSize')]", - "tier": "[variables('{{.Name}}VMSizeTier')]" - }, - "type": "Microsoft.Compute/virtualMachineScaleSets" - } diff --git a/parts/swarm/swarmagentvars.t b/parts/swarm/swarmagentvars.t deleted file mode 100644 index d861b1b1c5..0000000000 --- a/parts/swarm/swarmagentvars.t +++ /dev/null @@ -1,51 +0,0 @@ -{{if not .IsRHEL}} - "{{.Name}}RunCmd": "[concat('runcmd:\n {{GetSwarmAgentPreprovisionExtensionCommands .}} \n- [ /bin/bash, /opt/azure/containers/install-cluster.sh ]\n\n')]", - "{{.Name}}RunCmdFile": "[concat(' - content: |\n #!/bin/bash\n ','sudo mkdir -p /var/log/azure\n ',variables('agentCustomScript'),'\n path: /opt/azure/containers/install-cluster.sh\n permissions: \"0744\"\n')]", -{{end}} -{{if IsSwarmMode }} - "{{.Name}}OSImageOffer": {{GetAgentOSImageOffer .}}, - "{{.Name}}OSImagePublisher": {{GetAgentOSImagePublisher .}}, - "{{.Name}}OSImageSKU": {{GetAgentOSImageSKU .}}, - "{{.Name}}OSImageVersion": {{GetAgentOSImageVersion .}}, -{{else}} - "{{.Name}}OSImageOffer": "[variables('osImageOffer')]", - "{{.Name}}OSImagePublisher": "[variables('osImagePublisher')]", - "{{.Name}}OSImageSKU": "[variables('osImageSKU')]", - "{{.Name}}OSImageVersion": "[variables('osImageVersion')]", -{{end}} - "{{.Name}}Count": "[parameters('{{.Name}}Count')]", - "{{.Name}}VMNamePrefix": "[concat(variables('orchestratorName'), '-{{.Name}}-', variables('nameSuffix'))]", - "{{.Name}}VMSize": "[parameters('{{.Name}}VMSize')]", - "{{.Name}}VMSizeTier": "[split(parameters('{{.Name}}VMSize'),'_')[0]]", -{{if .IsAvailabilitySets}} - {{if .IsStorageAccount}} - "{{.Name}}StorageAccountsCount": "[add(div(variables('{{.Name}}Count'), variables('maxVMsPerStorageAccount')), mod(add(mod(variables('{{.Name}}Count'), variables('maxVMsPerStorageAccount')),2), add(mod(variables('{{.Name}}Count'), variables('maxVMsPerStorageAccount')),1)))]", - "{{.Name}}StorageAccountOffset": "[mul(variables('maxStorageAccountsPerAgent'),variables('{{.Name}}Index'))]", - {{end}} - "{{.Name}}AvailabilitySet": "[concat('{{.Name}}-availabilitySet-', variables('nameSuffix'))]", - "{{.Name}}Offset": "[parameters('{{.Name}}Offset')]", -{{else}} - {{if .IsStorageAccount}} - "{{.Name}}StorageAccountsCount": "[variables('maxStorageAccountsPerAgent')]", - {{end}} -{{end}} -{{if .IsCustomVNET}} - "{{.Name}}VnetSubnetID": "[parameters('{{.Name}}VnetSubnetID')]", -{{else}} - "{{.Name}}Subnet": "[parameters('{{.Name}}Subnet')]", - "{{.Name}}SubnetName": "[concat(variables('orchestratorName'), '-{{.Name}}subnet')]", - "{{.Name}}VnetSubnetID": "[concat(variables('vnetID'),'/subnets/',variables('{{.Name}}SubnetName'))]", -{{end}} -{{if IsPublic .Ports}} - "{{.Name}}EndpointDNSNamePrefix": "[tolower(parameters('{{.Name}}EndpointDNSNamePrefix'))]", - "{{.Name}}IPAddressName": "[concat(variables('orchestratorName'), '-agent-ip-', variables('{{.Name}}EndpointDNSNamePrefix'), '-', variables('nameSuffix'))]", - "{{.Name}}LbBackendPoolName": "[concat(variables('orchestratorName'), '-{{.Name}}-', variables('nameSuffix'))]", - "{{.Name}}LbID": "[resourceId('Microsoft.Network/loadBalancers',variables('{{.Name}}LbName'))]", - "{{.Name}}LbIPConfigID": "[concat(variables('{{.Name}}LbID'),'/frontendIPConfigurations/', variables('{{.Name}}LbIPConfigName'))]", - "{{.Name}}LbIPConfigName": "[concat(variables('orchestratorName'), '-{{.Name}}-', variables('nameSuffix'))]", - "{{.Name}}LbName": "[concat(variables('orchestratorName'), '-{{.Name}}-', variables('nameSuffix'))]", - {{if .IsWindows}} - "{{.Name}}WindowsRDPNatRangeStart": 3389, - "{{.Name}}WindowsRDPEndRangeStop": "[add(variables('{{.Name}}WindowsRDPNatRangeStart'), add(variables('{{.Name}}Count'),variables('{{.Name}}Count')))]", - {{end}} - {{end}} diff --git a/parts/swarm/swarmbase.t b/parts/swarm/swarmbase.t deleted file mode 100644 index 8eeb4f77d7..0000000000 --- a/parts/swarm/swarmbase.t +++ /dev/null @@ -1,50 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { - {{range .AgentPoolProfiles}}{{template "agentparams.t" .}},{{end}} - {{if .HasWindows}} - {{template "windowsparams.t"}}, - {{end}} - {{template "masterparams.t" .}} - {{template "swarm/swarmparams.t" .}} - }, - "variables": { - {{range $index, $agent := .AgentPoolProfiles}} - "{{.Name}}Index": {{$index}}, - {{template "swarm/swarmagentvars.t" .}} - {{if .IsStorageAccount}} - "{{.Name}}StorageAccountOffset": "[mul(variables('maxStorageAccountsPerAgent'),{{$index}})]", - "{{.Name}}AccountName": "[concat(variables('storageAccountBaseName'), 'agnt{{$index}}')]", - {{if .HasDisks}} - "{{.Name}}DataAccountName": "[concat(variables('storageAccountBaseName'), 'data{{$index}}')]", - {{end}} - {{end}} - {{end}} - - {{template "swarm/swarmmastervars.t" .}} - }, - "resources": [ - {{range .AgentPoolProfiles}} - {{if .IsWindows}} - {{if .IsAvailabilitySets}} - {{template "swarm/swarmwinagentresourcesvmas.t" .}}, - {{else}} - {{template "swarm/swarmwinagentresourcesvmss.t" .}}, - {{end}} - {{else}} - {{if .IsAvailabilitySets}} - {{template "swarm/swarmagentresourcesvmas.t" .}}, - {{else}} - {{template "swarm/swarmagentresourcesvmss.t" .}}, - {{end}} - {{end}} - {{end}} - {{template "swarm/swarmmasterresources.t" .}} - ], - "outputs": { - {{range .AgentPoolProfiles}}{{template "agentoutputs.t" .}} - {{end}} - {{template "masteroutputs.t" .}} - } -} diff --git a/parts/swarm/swarmmasterresources.t b/parts/swarm/swarmmasterresources.t deleted file mode 100644 index c3c6557cc4..0000000000 --- a/parts/swarm/swarmmasterresources.t +++ /dev/null @@ -1,287 +0,0 @@ -{{if not .MasterProfile.IsCustomVNET}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('virtualNetworkName')]", - "properties": { - "addressSpace": { - "addressPrefixes": [ - {{GetVNETAddressPrefixes}} - ] - }, - "subnets": [ - {{GetVNETSubnets false}} - ] - }, - "type": "Microsoft.Network/virtualNetworks" - }, -{{end}} -{{if .MasterProfile.IsManagedDisks}} - { - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", - "location": "[variables('location')]", - "name": "[variables('masterAvailabilitySet')]", - "properties": { - "platformFaultDomainCount": 2, - "platformUpdateDomainCount": 3, - "managed": "true" - }, - "type": "Microsoft.Compute/availabilitySets" - }, -{{else if .MasterProfile.IsStorageAccount}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('masterAvailabilitySet')]", - "properties": {}, - "type": "Microsoft.Compute/availabilitySets" - }, - { - "apiVersion": "[variables('apiVersionStorage')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('masterStorageAccountName')]", - "properties": { - "accountType": "[variables('vmSizesMap')[variables('masterVMSize')].storageAccountType]" - }, - "type": "Microsoft.Storage/storageAccounts" - }, -{{end}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('masterPublicIPAddressName')]", - "properties": { - "dnsSettings": { - "domainNameLabel": "[variables('masterEndpointDNSNamePrefix')]" - }, - "publicIPAllocationMethod": "Dynamic" - }, - "type": "Microsoft.Network/publicIPAddresses" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('masterLbName')]", - "properties": { - "backendAddressPools": [ - { - "name": "[variables('masterLbBackendPoolName')]" - } - ], - "frontendIPConfigurations": [ - { - "name": "[variables('masterLbIPConfigName')]", - "properties": { - "publicIPAddress": { - "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('masterPublicIPAddressName'))]" - } - } - } - ] - }, - "type": "Microsoft.Network/loadBalancers" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "copy": { - "count": "[variables('masterCount')]", - "name": "masterLbLoopNode" - }, - "dependsOn": [ - "[variables('masterLbID')]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('masterLbName'), '/', 'SSH-', variables('masterVMNamePrefix'), copyIndex())]", - "properties": { - "backendPort": 22, - "enableFloatingIP": false, - "frontendIPConfiguration": { - "id": "[variables('masterLbIPConfigID')]" - }, - "frontendPort": "[copyIndex(2200)]", - "protocol": "tcp" - }, - "type": "Microsoft.Network/loadBalancers/inboundNatRules" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[variables('masterLbID')]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('masterSshPort22InboundNatRuleNamePrefix'), '0')]", - "properties": { - "backendPort": 2222, - "enableFloatingIP": false, - "frontendIPConfiguration": { - "id": "[variables('masterLbIPConfigID')]" - }, - "frontendPort": "22", - "protocol": "tcp" - }, - "type": "Microsoft.Network/loadBalancers/inboundNatRules" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "copy": { - "count": "[variables('masterCount')]", - "name": "nicLoopNode" - }, - "dependsOn": [ -{{if not .MasterProfile.IsCustomVNET}} - "[variables('vnetID')]", -{{end}} - "[variables('masterLbID')]", - "[concat(variables('masterSshPort22InboundNatRuleIdPrefix'),'0')]", - "[concat(variables('masterSshInboundNatRuleIdPrefix'),copyIndex())]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('masterVMNamePrefix'), 'nic-', copyIndex())]", - "properties": { - "ipConfigurations": [ - { - "name": "ipConfigNode", - "properties": { - "loadBalancerBackendAddressPools": [ - { - "id": "[concat(variables('masterLbID'), '/backendAddressPools/', variables('masterLbBackendPoolName'))]" - } - ], - "loadBalancerInboundNatRules": "[variables('masterLbInboundNatRules')[copyIndex()]]", - "privateIPAddress": "[concat(variables('masterFirstAddrPrefix'), copyIndex(int(variables('masterFirstAddrOctet4'))))]", - "privateIPAllocationMethod": "Static", - "subnet": { - "id": "[variables('masterVnetSubnetID')]" - } - } - } - ] - }, - "type": "Microsoft.Network/networkInterfaces" - }, - { -{{if .MasterProfile.IsManagedDisks}} - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", -{{else}} - "apiVersion": "[variables('apiVersionDefault')]", -{{end}} - "copy": { - "count": "[variables('masterCount')]", - "name": "vmLoopNode" - }, - "dependsOn": [ - "[concat('Microsoft.Network/networkInterfaces/', variables('masterVMNamePrefix'), 'nic-', copyIndex())]", - "[concat('Microsoft.Compute/availabilitySets/',variables('masterAvailabilitySet'))]" -{{if .MasterProfile.IsStorageAccount}} - ,"[variables('masterStorageAccountName')]" -{{end}} - ], - "tags": - { - "creationSource" : "[concat('acsengine-', variables('masterVMNamePrefix'), copyIndex())]" - }, - "location": "[variables('location')]", - "name": "[concat(variables('masterVMNamePrefix'), copyIndex())]", - "properties": { - "availabilitySet": { - "id": "[resourceId('Microsoft.Compute/availabilitySets',variables('masterAvailabilitySet'))]" - }, - "hardwareProfile": { - "vmSize": "[variables('masterVMSize')]" - }, - "networkProfile": { - "networkInterfaces": [ - { - "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(variables('masterVMNamePrefix'), 'nic-', copyIndex()))]" - } - ] - }, - "osProfile": { - "adminUsername": "[variables('adminUsername')]", - "computername": "[concat(variables('masterVMNamePrefix'), copyIndex())]", - {{if .OrchestratorProfile.IsSwarmMode}} - {{if not .MasterProfile.IsRHEL}} - {{GetMasterSwarmModeCustomData}} - {{end}} - {{else}} - {{GetMasterSwarmCustomData}} - {{end}} - "linuxConfiguration": { - "disablePasswordAuthentication": "true", - "ssh": { - "publicKeys": [ - { - "keyData": "[variables('sshRSAPublicKey')]", - "path": "[variables('sshKeyPath')]" - } - ] - } - } - {{if .LinuxProfile.HasSecrets}} - , - "secrets": "[variables('linuxProfileSecrets')]" - {{end}} - }, - "storageProfile": { - "imageReference": { - {{if .OrchestratorProfile.IsSwarmMode}} - "offer": "[variables('masterOSImageOffer')]", - "publisher": "[variables('masterOSImagePublisher')]", - "sku": "[variables('masterOSImageSKU')]", - "version": "[variables('masterOSImageVersion')]" - {{else}} - "offer": "[variables('osImageOffer')]", - "publisher": "[variables('osImagePublisher')]", - "sku": "[variables('osImageSKU')]", - "version": "[variables('osImageVersion')]" - {{end}} - }, - "osDisk": { - "caching": "ReadWrite" - ,"createOption": "FromImage" -{{if .MasterProfile.IsStorageAccount}} - ,"name": "[concat(variables('masterVMNamePrefix'), copyIndex(),'-osdisk')]" - ,"vhd": { - "uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('masterStorageAccountName')), variables('apiVersionStorage')).primaryEndpoints.blob, 'vhds/', variables('masterVMNamePrefix'), copyIndex(), '-osdisk.vhd')]" - } -{{end}} -{{if ne .MasterProfile.OSDiskSizeGB 0}} - ,"diskSizeGB": {{.MasterProfile.OSDiskSizeGB}} -{{end}} - } - } - }, - "type": "Microsoft.Compute/virtualMachines" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "copy": { - "count": "[variables('masterCount')]", - "name": "vmLoopNode" - }, - "dependsOn": [ - "[concat('Microsoft.Compute/virtualMachines/', concat(variables('masterVMNamePrefix'), copyIndex()))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('masterVMNamePrefix'), copyIndex(), '/configuremaster')]", - "properties": { - "publisher": "Microsoft.Azure.Extensions", - "settings": { - "commandToExecute": "[variables('masterCustomScript')]", - "fileUris": [ -{{if .MasterProfile.IsRHEL}} - "[concat('{{ GetConfigurationScriptRootURL }}', variables('configureClusterScriptFile'))]" -{{end}} - ] - }, - "type": "CustomScript", - "typeHandlerVersion": "2.0" - }, - "type": "Microsoft.Compute/virtualMachines/extensions" - } diff --git a/parts/swarm/swarmmastervars.t b/parts/swarm/swarmmastervars.t deleted file mode 100644 index 2f88c2f918..0000000000 --- a/parts/swarm/swarmmastervars.t +++ /dev/null @@ -1,178 +0,0 @@ - "adminUsername": "[parameters('linuxAdminUsername')]", - "maxVMsPerPool": 100, - "apiVersionDefault": "2016-03-30", -{{if .OrchestratorProfile.IsSwarmMode}} - "configureClusterScriptFile": "configure-swarmmode-cluster.sh", -{{else}} - "configureClusterScriptFile": "configure-swarm-cluster.sh", -{{end}} -{{if .MasterProfile.IsRHEL}} - "agentCustomScript": "[concat('/usr/bin/nohup /bin/bash -c \"/bin/bash ',variables('configureClusterScriptFile'), ' ',variables('clusterInstallParameters'),' >> /var/log/azure/cluster-bootstrap.log 2>&1 &\" &')]", -{{else}} - "agentCustomScript": "[concat('/usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/',variables('configureClusterScriptFile'), ' ',variables('clusterInstallParameters'),' >> /var/log/azure/cluster-bootstrap.log 2>&1 &\" &')]", -{{end}} - "agentMaxVMs": 100, - "clusterInstallParameters": "[concat(variables('orchestratorVersion'), ' ',variables('dockerComposeVersion'), ' ',variables('masterCount'), ' ',variables('masterVMNamePrefix'), ' ',variables('masterFirstAddrOctet4'), ' ',variables('adminUsername'),' ',variables('postInstallScriptURI'),' ',variables('masterFirstAddrPrefix'),' ', parameters('dockerEngineDownloadRepo'), ' ', parameters('dockerComposeDownloadURL'))]", -{{if .LinuxProfile.HasSecrets}} - "linuxProfileSecrets" : - [ - {{range $vIndex, $vault := .LinuxProfile.Secrets}} - {{if $vIndex}} , {{end}} - { - "sourceVault":{ - "id":"[parameters('linuxKeyVaultID{{$vIndex}}')]" - }, - "vaultCertificates":[ - {{range $cIndex, $cert := $vault.VaultCertificates}} - {{if $cIndex}} , {{end}} - { - "certificateUrl" :"[parameters('linuxKeyVaultID{{$vIndex}}CertificateURL{{$cIndex}}')]" - } - {{end}} - ] - } - {{end}} - ], -{{end}} - "masterAvailabilitySet": "[concat(variables('orchestratorName'), '-master-availabilitySet-', variables('nameSuffix'))]", - "masterCount": {{.MasterProfile.Count}}, -{{if .MasterProfile.IsRHEL}} - "masterCustomScript": "[concat('/bin/bash -c \"/bin/bash ',variables('configureClusterScriptFile'), ' ',variables('clusterInstallParameters'),' >> /var/log/azure/cluster-bootstrap.log 2>&1\"')]", -{{else}} - "masterCustomScript": "[concat('/bin/bash -c \"/bin/bash /opt/azure/containers/',variables('configureClusterScriptFile'), ' ',variables('clusterInstallParameters'),' >> /var/log/azure/cluster-bootstrap.log 2>&1\"')]", -{{end}} - "masterEndpointDNSNamePrefix": "[tolower(parameters('masterEndpointDNSNamePrefix'))]", - "masterLbBackendPoolName": "[concat(variables('orchestratorName'), '-master-pool-', variables('nameSuffix'))]", - "masterLbID": "[resourceId('Microsoft.Network/loadBalancers',variables('masterLbName'))]", - "masterLbIPConfigID": "[concat(variables('masterLbID'),'/frontendIPConfigurations/', variables('masterLbIPConfigName'))]", - "masterLbIPConfigName": "[concat(variables('orchestratorName'), '-master-lbFrontEnd-', variables('nameSuffix'))]", - "masterLbName": "[concat(variables('orchestratorName'), '-master-lb-', variables('nameSuffix'))]", - "masterPublicIPAddressName": "[concat(variables('orchestratorName'), '-master-ip-', variables('masterEndpointDNSNamePrefix'), '-', variables('nameSuffix'))]", -{{if .MasterProfile.IsCustomVNET}} - "masterVnetSubnetID": "[parameters('masterVnetSubnetID')]", -{{else}} - "masterSubnet": "[parameters('masterSubnet')]", - "masterSubnetName": "[concat(variables('orchestratorName'), '-masterSubnet')]", - "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]", - "masterVnetSubnetID": "[concat(variables('vnetID'),'/subnets/',variables('masterSubnetName'))]", - "virtualNetworkName": "[concat(variables('orchestratorName'), '-vnet-', variables('nameSuffix'))]", -{{end}} - "masterFirstAddrOctets": "[split(parameters('firstConsecutiveStaticIP'),'.')]", - "masterFirstAddrOctet4": "[variables('masterFirstAddrOctets')[3]]", - "masterFirstAddrPrefix": "[concat(variables('masterFirstAddrOctets')[0],'.',variables('masterFirstAddrOctets')[1],'.',variables('masterFirstAddrOctets')[2],'.')]", - "masterVMNamePrefix": "[concat(variables('orchestratorName'), '-master-', variables('nameSuffix'), '-')]", - "masterVMSize": "[parameters('masterVMSize')]", - "nameSuffix": "[parameters('nameSuffix')]", - "masterSshInboundNatRuleIdPrefix": "[concat(variables('masterLbID'),'/inboundNatRules/SSH-',variables('masterVMNamePrefix'))]", - "masterSshPort22InboundNatRuleNamePrefix": "[concat(variables('masterLbName'),'/SSHPort22-',variables('masterVMNamePrefix'))]", - "masterSshPort22InboundNatRuleIdPrefix": "[concat(variables('masterLbID'),'/inboundNatRules/SSHPort22-',variables('masterVMNamePrefix'))]", - "masterLbInboundNatRules":[ - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'0')]" - }, - { - "id": "[concat(variables('masterSshPort22InboundNatRuleIdPrefix'),'0')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'1')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'2')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'3')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'4')]" - } - ] - ], -{{if .OrchestratorProfile.IsSwarmMode}} - "orchestratorName": "swarmm", - "masterOSImageOffer": {{GetMasterOSImageOffer}}, - "masterOSImagePublisher": {{GetMasterOSImagePublisher}}, - "masterOSImageSKU": {{GetMasterOSImageSKU}}, - "masterOSImageVersion": {{GetMasterOSImageVersion}}, - {{GetSwarmModeVersions}} -{{else}} - "orchestratorName": "swarm", - "osImageOffer": "[parameters('osImageOffer')]", - "osImagePublisher": "[parameters('osImagePublisher')]", - "osImageSKU": "14.04.5-LTS", - "osImageVersion": "14.04.201706190", - {{getSwarmVersions}} -{{end}} - "locations": [ - "[resourceGroup().location]", - "[parameters('location')]" - ], - "location": "[variables('locations')[mod(add(2,length(parameters('location'))),add(1,length(parameters('location'))))]]", - "postInstallScriptURI": "disabled", - "sshKeyPath": "[concat('/home/', variables('adminUsername'), '/.ssh/authorized_keys')]", -{{if .HasStorageAccountDisks}} - "apiVersionStorage": "2015-06-15", - "maxVMsPerStorageAccount": 20, - "maxStorageAccountsPerAgent": "[div(variables('maxVMsPerPool'),variables('maxVMsPerStorageAccount'))]", - "dataStorageAccountPrefixSeed": 97, - "storageAccountPrefixes": [ "0", "6", "c", "i", "o", "u", "1", "7", "d", "j", "p", "v", "2", "8", "e", "k", "q", "w", "3", "9", "f", "l", "r", "x", "4", "a", "g", "m", "s", "y", "5", "b", "h", "n", "t", "z" ], - "storageAccountPrefixesCount": "[length(variables('storageAccountPrefixes'))]", - "vmsPerStorageAccount": 20, - "storageAccountBaseName": "[uniqueString(concat(variables('masterEndpointDNSNamePrefix'),variables('location')))]", - {{GetSizeMap}}, -{{else}} - "storageAccountPrefixes": [], - "storageAccountBaseName": "", -{{end}} -{{if .HasManagedDisks}} - "apiVersionStorageManagedDisks": "2016-04-30-preview", -{{end}} -{{if .MasterProfile.IsStorageAccount}} - "masterStorageAccountName": "[concat(variables('storageAccountBaseName'), '0')]", -{{end}} - "sshRSAPublicKey": "[parameters('sshRSAPublicKey')]" -{{if .HasWindows}} - ,"windowsAdminUsername": "[parameters('windowsAdminUsername')]", - "windowsAdminPassword": "[parameters('windowsAdminPassword')]", - "agentWindowsPublisher": "[parameters('agentWindowsPublisher')]", - "agentWindowsOffer": "[parameters('agentWindowsOffer')]", - "agentWindowsSku": "[parameters('agentWindowsSku')]", - "agentWindowsVersion": "[parameters('agentWindowsVersion')]", - "singleQuote": "'", - "windowsCustomScriptArguments": "[concat('$arguments = ', variables('singleQuote'),'-SwarmMasterIP ', variables('masterFirstAddrPrefix'), variables('masterFirstAddrOctet4'), variables('singleQuote'), ' ; ')]", - "windowsCustomScriptSuffix": " $inputFile = '%SYSTEMDRIVE%\\AzureData\\CustomData.bin' ; $outputFile = '%SYSTEMDRIVE%\\AzureData\\CustomDataSetupScript.ps1' ; $inputStream = New-Object System.IO.FileStream $inputFile, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read) ; $sr = New-Object System.IO.StreamReader(New-Object System.IO.Compression.GZipStream($inputStream, [System.IO.Compression.CompressionMode]::Decompress)) ; $sr.ReadToEnd() | Out-File($outputFile) ; Invoke-Expression('{0} {1}' -f $outputFile, $arguments) ; ", - "windowsCustomScript": "[concat('powershell.exe -ExecutionPolicy Unrestricted -command \"', variables('windowsCustomScriptArguments'), variables('windowsCustomScriptSuffix'), '\" > %SYSTEMDRIVE%\\AzureData\\CustomDataSetupScript.log 2>&1')]", - "agentWindowsBackendPort": 3389 - {{if .WindowsProfile.HasSecrets}} - , - "windowsProfileSecrets" : - [ - {{range $vIndex, $vault := .LinuxProfile.Secrets}} - {{if $vIndex}} , {{end}} - { - "sourceVault":{ - "id":"[parameters('windowsKeyVaultID{{$vIndex}}')]" - }, - "vaultCertificates":[ - {{range $cIndex, $cert := $vault.VaultCertificates}} - {{if $cIndex}} , {{end}} - { - "certificateUrl" :"[parameters('windowsKeyVaultID{{$vIndex}}CertificateURL{{$cIndex}}')]", - "certificateStore" :"[parameters('windowsKeyVaultID{{$vIndex}}CertificateStore{{$cIndex}}')]" - } - {{end}} - ] - } - {{end}} - ] - {{end}} -{{end}} - diff --git a/parts/swarm/swarmparams.t b/parts/swarm/swarmparams.t deleted file mode 100644 index 13f5d8c527..0000000000 --- a/parts/swarm/swarmparams.t +++ /dev/null @@ -1,15 +0,0 @@ - , - "dockerEngineDownloadRepo": { - "defaultValue": "", - "metadata": { - "description": "Docker engine download repo." - }, - "type": "string" - }, - "dockerComposeDownloadURL": { - "defaultValue": "", - "metadata": { - "description": "Docker compose download URL." - }, - "type": "string" - } \ No newline at end of file diff --git a/parts/swarm/swarmwinagentresourcesvmas.t b/parts/swarm/swarmwinagentresourcesvmas.t deleted file mode 100644 index 2781dc2efe..0000000000 --- a/parts/swarm/swarmwinagentresourcesvmas.t +++ /dev/null @@ -1,259 +0,0 @@ - { - "apiVersion": "[variables('apiVersionDefault')]", - "copy": { - "count": "[sub(variables('{{.Name}}Count'), variables('{{.Name}}Offset'))]", - "name": "loop" - }, - "dependsOn": [ -{{if not .IsCustomVNET}} - "[variables('vnetID')]" -{{end}} -{{if IsPublic .Ports}} - ,"[variables('{{.Name}}LbID')]" -{{end}} - ], - "location": "[variables('location')]", - "name": "[concat(variables('{{.Name}}VMNamePrefix'), 'nic-', copyIndex(variables('{{.Name}}Offset')))]", - "properties": { - "ipConfigurations": [ - { - "name": "ipConfigNode", - "properties": { -{{if IsPublic .Ports}} - "loadBalancerBackendAddressPools": [ - { - "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/loadBalancers/', variables('{{.Name}}LbName'), '/backendAddressPools/',variables('{{.Name}}LbBackendPoolName'))]" - } - ], - "loadBalancerInboundNatPools": [ - { - "id": "[concat(variables('{{.Name}}LbID'), '/inboundNatPools/', 'RDP-', variables('{{.Name}}VMNamePrefix'))]" - } - ], -{{end}} - "privateIPAllocationMethod": "Dynamic", - "subnet": { - "id": "[variables('{{.Name}}VnetSubnetID')]" - } - } - } - ] - }, - "type": "Microsoft.Network/networkInterfaces" - }, -{{if .IsManagedDisks}} - { - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}AvailabilitySet')]", - "properties": { - "platformFaultDomainCount": 2, - "platformUpdateDomainCount": 3, - "managed": "true" - }, - "type": "Microsoft.Compute/availabilitySets" - }, -{{else if .IsStorageAccount}} - { - "apiVersion": "[variables('apiVersionStorage')]", - "copy": { - "count": "[variables('{{.Name}}StorageAccountsCount')]", - "name": "vmLoopNode" - }, - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('storageAccountPrefixes')[mod(add(copyIndex(),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(copyIndex(),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "properties": { - "accountType": "[variables('vmSizesMap')[variables('{{.Name}}VMSize')].storageAccountType]" - }, - "type": "Microsoft.Storage/storageAccounts" - }, - {{if .HasDisks}} - { - "apiVersion": "[variables('apiVersionStorage')]", - "copy": { - "count": "[variables('{{.Name}}StorageAccountsCount')]", - "name": "datadiskLoop" - }, - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('storageAccountPrefixes')[mod(add(copyIndex(variables('dataStorageAccountPrefixSeed')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(copyIndex(variables('dataStorageAccountPrefixSeed')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}DataAccountName'))]", - "properties": { - "accountType": "[variables('vmSizesMap')[variables('{{.Name}}VMSize')].storageAccountType]" - }, - "type": "Microsoft.Storage/storageAccounts" - }, - {{end}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}AvailabilitySet')]", - "properties": {}, - "type": "Microsoft.Compute/availabilitySets" - }, -{{end}} -{{if IsPublic .Ports}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}IPAddressName')]", - "properties": { - "dnsSettings": { - "domainNameLabel": "[variables('{{.Name}}EndpointDNSNamePrefix')]" - }, - "publicIPAllocationMethod": "Dynamic" - }, - "type": "Microsoft.Network/publicIPAddresses" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('{{.Name}}IPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('{{.Name}}LbName')]", - "properties": { - "backendAddressPools": [ - { - "name": "[variables('{{.Name}}LbBackendPoolName')]" - } - ], - "frontendIPConfigurations": [ - { - "name": "[variables('{{.Name}}LbIPConfigName')]", - "properties": { - "publicIPAddress": { - "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('{{.Name}}IPAddressName'))]" - } - } - } - ], - "inboundNatPools": [ - { - "name": "[concat('RDP-', variables('{{.Name}}VMNamePrefix'))]", - "properties": { - "frontendIPConfiguration": { - "id": "[variables('{{.Name}}LbIPConfigID')]" - }, - "protocol": "tcp", - "frontendPortRangeStart": "[variables('{{.Name}}WindowsRDPNatRangeStart')]", - "frontendPortRangeEnd": "[variables('{{.Name}}WindowsRDPEndRangeStop')]", - "backendPort": "[variables('agentWindowsBackendPort')]" - } - } - ], - "loadBalancingRules": [ - {{(GetLBRules .Name .Ports)}} - ], - "probes": [ - {{(GetProbes .Ports)}} - ] - }, - "type": "Microsoft.Network/loadBalancers" - }, -{{end}} - { -{{if .IsManagedDisks}} - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", -{{else}} - "apiVersion": "[variables('apiVersionDefault')]", -{{end}} - "copy": { - "count": "[sub(variables('{{.Name}}Count'), variables('{{.Name}}Offset'))]", - "name": "vmLoopNode" - }, - "dependsOn": [ -{{if .IsStorageAccount}} - "[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - {{if .HasDisks}} - "[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('dataStorageAccountPrefixSeed')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('dataStorageAccountPrefixSeed')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}DataAccountName'))]", - {{end}} -{{end}} - "[concat('Microsoft.Network/networkInterfaces/', variables('{{.Name}}VMNamePrefix'), 'nic-', copyIndex(variables('{{.Name}}Offset')))]", - "[concat('Microsoft.Compute/availabilitySets/', variables('{{.Name}}AvailabilitySet'))]" - ], - "tags": - { - "creationSource" : "[concat('acsengine-', variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')))]" - }, - "location": "[variables('location')]", - "name": "[concat(variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')))]", - "properties": { - "availabilitySet": { - "id": "[resourceId('Microsoft.Compute/availabilitySets',variables('{{.Name}}AvailabilitySet'))]" - }, - "hardwareProfile": { - "vmSize": "[variables('{{.Name}}VMSize')]" - }, - "networkProfile": { - "networkInterfaces": [ - { - "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(variables('{{.Name}}VMNamePrefix'), 'nic-', copyIndex(variables('{{.Name}}Offset'))))]" - } - ] - }, - "osProfile": { - "computername": "[concat(substring(variables('nameSuffix'), 0, 5), 'acs', copyIndex(variables('{{.Name}}Offset')), add(900,variables('{{.Name}}Index')))]", - "adminUsername": "[variables('windowsAdminUsername')]", - "adminPassword": "[variables('windowsAdminPassword')]", - {{if IsSwarmMode}} - {{GetWinAgentSwarmModeCustomData}} - {{else}} - {{GetWinAgentSwarmCustomData}} - {{end}} - {{if HasWindowsSecrets}} - , - "secrets": "[variables('windowsProfileSecrets')]" - {{end}} - }, - "storageProfile": { - {{GetDataDisks .}} - "imageReference": { - "publisher": "[variables('agentWindowsPublisher')]", - "offer": "[variables('agentWindowsOffer')]", - "sku": "[variables('agentWindowsSku')]", - "version": "[variables('agentWindowsVersion')]" - } - ,"osDisk": { - "caching": "ReadOnly" - ,"createOption": "FromImage" -{{if .IsStorageAccount}} - ,"name": "[concat(variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')),'-osdisk')]" - ,"vhd": { - "uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(div(copyIndex(variables('{{.Name}}Offset')),variables('maxVMsPerStorageAccount')),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'osdisk/', variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')), '-osdisk.vhd')]" - } -{{end}} -{{if ne .OSDiskSizeGB 0}} - ,"diskSizeGB": {{.OSDiskSizeGB}} -{{end}} - } - } - }, - "type": "Microsoft.Compute/virtualMachines" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "copy": { - "count": "[sub(variables('{{.Name}}Count'), variables('{{.Name}}Offset'))]", - "name": "vmLoopNode" - }, - "dependsOn": [ - "[concat('Microsoft.Compute/virtualMachines/', variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('{{.Name}}VMNamePrefix'), copyIndex(variables('{{.Name}}Offset')), '/cse')]", - "properties": { - "publisher": "Microsoft.Compute", - "type": "CustomScriptExtension", - "typeHandlerVersion": "1.8", - "autoUpgradeMinorVersion": true, - "settings": { - "commandToExecute": "[variables('windowsCustomScript')]" - } - }, - "type": "Microsoft.Compute/virtualMachines/extensions" - } diff --git a/parts/swarm/swarmwinagentresourcesvmss.t b/parts/swarm/swarmwinagentresourcesvmss.t deleted file mode 100644 index de3c424770..0000000000 --- a/parts/swarm/swarmwinagentresourcesvmss.t +++ /dev/null @@ -1,208 +0,0 @@ -{{if .IsStorageAccount}} - { - "apiVersion": "[variables('apiVersionStorage')]", - "copy": { - "count": "[variables('{{.Name}}StorageAccountsCount')]", - "name": "vmLoopNode" - }, - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('storageAccountPrefixes')[mod(add(copyIndex(),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(copyIndex(),variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "properties": { - "accountType": "[variables('vmSizesMap')[variables('{{.Name}}VMSize')].storageAccountType]" - }, - "type": "Microsoft.Storage/storageAccounts" - }, -{{end}} -{{if IsPublic .Ports}} - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('{{.Name}}IPAddressName')]", - "properties": { - "dnsSettings": { - "domainNameLabel": "[variables('{{.Name}}EndpointDNSNamePrefix')]" - }, - "publicIPAllocationMethod": "Dynamic" - }, - "type": "Microsoft.Network/publicIPAddresses" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('{{.Name}}IPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('{{.Name}}LbName')]", - "properties": { - "backendAddressPools": [ - { - "name": "[variables('{{.Name}}LbBackendPoolName')]" - } - ], - "frontendIPConfigurations": [ - { - "name": "[variables('{{.Name}}LbIPConfigName')]", - "properties": { - "publicIPAddress": { - "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('{{.Name}}IPAddressName'))]" - } - } - } - ], - "inboundNatRules": [], - "loadBalancingRules": [ - {{(GetLBRules .Name .Ports)}} - ], - "probes": [ - {{(GetProbes .Ports)}} - ], - "inboundNatPools": [ - { - "name": "[concat('RDP-', variables('{{.Name}}VMNamePrefix'))]", - "properties": { - "frontendIPConfiguration": { - "id": "[variables('{{.Name}}LbIPConfigID')]" - }, - "protocol": "tcp", - "frontendPortRangeStart": "[variables('{{.Name}}WindowsRDPNatRangeStart')]", - "frontendPortRangeEnd": "[variables('{{.Name}}WindowsRDPEndRangeStop')]", - "backendPort": "[variables('agentWindowsBackendPort')]" - } - } - ] - }, - "type": "Microsoft.Network/loadBalancers" - }, -{{end}} - { -{{if .IsManagedDisks}} - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", -{{else}} - "apiVersion": "[variables('apiVersionDefault')]", -{{end}} - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" -{{if .IsStorageAccount}} - ,"[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountPrefixes')[mod(add(0,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(0,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountPrefixes')[mod(add(1,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(1,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountPrefixes')[mod(add(2,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(2,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountPrefixes')[mod(add(3,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(3,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]", - "[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountPrefixes')[mod(add(4,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(4,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName'))]" -{{end}} -{{if not .IsCustomVNET}} - ,"[variables('vnetID')]" -{{end}} -{{if IsPublic .Ports}} - ,"[variables('{{.Name}}LbID')]" -{{end}} - ], - "tags": - { - "creationSource" : "[concat('acsengine-', variables('{{.Name}}VMNamePrefix'), '-vmss')]" - }, - "location": "[variables('location')]", - "name": "[concat(variables('{{.Name}}VMNamePrefix'), '-vmss')]", - "properties": { - "upgradePolicy": { - "mode": "Automatic" - }, - "virtualMachineProfile": { - "networkProfile": { - "networkInterfaceConfigurations": [ - { - "name": "nic", - "properties": { - "ipConfigurations": [ - { - "name": "nicipconfig", - "properties": { -{{if IsPublic .Ports}} - "loadBalancerBackendAddressPools": [ - { - "id": "[concat(variables('{{.Name}}LbID'), '/backendAddressPools/', variables('{{.Name}}LbBackendPoolName'))]" - } - ], - "loadBalancerInboundNatPools": [ - { - "id": "[concat(variables('{{.Name}}LbID'), '/inboundNatPools/', 'RDP-', variables('{{.Name}}VMNamePrefix'))]" - } - ], -{{end}} - "subnet": { - "id": "[variables('{{.Name}}VnetSubnetID')]" - } - } - } - ], - "primary": "true" - } - } - ] - }, - "osProfile": { - "computerNamePrefix": "[concat(substring(variables('nameSuffix'), 0, 5), 'acs')]", - "adminUsername": "[variables('windowsAdminUsername')]", - "adminPassword": "[variables('windowsAdminPassword')]", - {{if IsSwarmMode}} - {{GetWinAgentSwarmModeCustomData}} - {{else}} - {{GetWinAgentSwarmCustomData}} - {{end}} - {{if HasWindowsSecrets}} - , - "secrets": "[variables('windowsProfileSecrets')]" - {{end}} - }, - "storageProfile": { - "imageReference": { - "publisher": "[variables('agentWindowsPublisher')]", - "offer": "[variables('agentWindowsOffer')]", - "sku": "[variables('agentWindowsSku')]", - "version": "[variables('agentWindowsVersion')]" - }, - "osDisk": { - "caching": "ReadWrite" - ,"createOption": "FromImage" -{{if .IsStorageAccount}} - ,"name": "vmssosdisk" - ,"vhdContainers": [ - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(0,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(0,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')), variables('apiVersionStorage') ).primaryEndpoints.blob, 'osdisk')]", - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(1,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(1,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')), variables('apiVersionStorage')).primaryEndpoints.blob, 'osdisk')]", - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(2,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(2,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')), variables('apiVersionStorage')).primaryEndpoints.blob, 'osdisk')]", - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(3,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(3,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')), variables('apiVersionStorage')).primaryEndpoints.blob, 'osdisk')]", - "[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(4,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(4,variables('{{.Name}}StorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('{{.Name}}AccountName')), variables('apiVersionStorage')).primaryEndpoints.blob, 'osdisk')]" - ] -{{end}} -{{if ne .OSDiskSizeGB 0}} - ,"diskSizeGB": {{.OSDiskSizeGB}} -{{end}} - } - }, - "extensionProfile": { - "extensions": [ - { - "name": "vmssCustomScriptExtension", - "properties": { - "publisher": "Microsoft.Compute", - "type": "CustomScriptExtension", - "typeHandlerVersion": "1.8", - "autoUpgradeMinorVersion": true, - "settings": { - "commandToExecute": "[variables('windowsCustomScript')]" - } - } - } - ] - } - } - }, - "sku": { - "capacity": "[variables('{{.Name}}Count')]", - "name": "[variables('{{.Name}}VMSize')]", - "tier": "[variables('{{.Name}}VMSizeTier')]" - }, - "type": "Microsoft.Compute/virtualMachineScaleSets" - } diff --git a/parts/windowsparams.t b/parts/windowsparams.t index 61a7e2d16f..1067efdfe4 100644 --- a/parts/windowsparams.t +++ b/parts/windowsparams.t @@ -1,4 +1,4 @@ - {{if or IsKubernetes IsOpenShift}} + {{if IsKubernetes}} "kubeBinariesSASURL": { "metadata": { "description": "The download url for kubernetes windows binaries package that is created by scripts/build-windows-k8s.sh" @@ -33,13 +33,13 @@ "windowsAdminUsername": { "type": "string", "metadata": { - "description": "User name for the Windows Swarm Agent Virtual Machines (Password Only Supported)." + "description": "User name for the Windows Agent Virtual Machines (Password Only Supported)." } }, "windowsAdminPassword": { "type": "securestring", "metadata": { - "description": "Password for the Windows Swarm Agent Virtual Machines." + "description": "Password for the Windows Agent Virtual Machines." } }, "agentWindowsVersion": { diff --git a/pkg/acsengine/doc.go b/pkg/acsengine/doc.go deleted file mode 100644 index 4cb879eb13..0000000000 --- a/pkg/acsengine/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package acsengine takes an ACS cluster model and generates the corresponding template -package acsengine diff --git a/pkg/acsengine/testdata/disks-managed/dcos-vmas.json b/pkg/acsengine/testdata/disks-managed/dcos-vmas.json deleted file mode 100644 index 8650369fd4..0000000000 --- a/pkg/acsengine/testdata/disks-managed/dcos-vmas.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agent128", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "ManagedDisks", - "diskSizesGB": [128, 128, 128, 128] - }, - { - "name": "agent1public", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agent1public", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "ManagedDisks", - "diskSizesGB": [1], - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/disks-managed/dcos-vmss.json b/pkg/acsengine/testdata/disks-managed/dcos-vmss.json deleted file mode 100644 index 4516d55dac..0000000000 --- a/pkg/acsengine/testdata/disks-managed/dcos-vmss.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agent128", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "VirtualMachineScaleSets", - "storageProfile": "ManagedDisks", - "diskSizesGB": [128, 128, 128, 128] - }, - { - "name": "agent1public", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agent1public", - "availabilityProfile": "VirtualMachineScaleSets", - "storageProfile": "ManagedDisks", - "diskSizesGB": [1], - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/disks-managed/swarm-vmas.json b/pkg/acsengine/testdata/disks-managed/swarm-vmas.json deleted file mode 100644 index bb76f540e3..0000000000 --- a/pkg/acsengine/testdata/disks-managed/swarm-vmas.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agent128", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "ManagedDisks", - "diskSizesGB": [128, 128, 128, 128] - }, - { - "name": "agent1public", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agent1public", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "ManagedDisks", - "diskSizesGB": [1], - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/disks-managed/swarm-vmss.json b/pkg/acsengine/testdata/disks-managed/swarm-vmss.json deleted file mode 100644 index e9b0085a3d..0000000000 --- a/pkg/acsengine/testdata/disks-managed/swarm-vmss.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agent128", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "VirtualMachineScaleSets", - "storageProfile": "ManagedDisks", - "diskSizesGB": [128, 128, 128, 128] - }, - { - "name": "agent1public", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agent1public", - "availabilityProfile": "VirtualMachineScaleSets", - "storageProfile": "ManagedDisks", - "diskSizesGB": [1], - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/disks-managed/swarm-windows-vmas.json b/pkg/acsengine/testdata/disks-managed/swarm-windows-vmas.json deleted file mode 100644 index b09fb62466..0000000000 --- a/pkg/acsengine/testdata/disks-managed/swarm-windows-vmas.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agent128", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "ManagedDisks", - "diskSizesGB": [128, 128, 128, 128], - "osType": "Windows" - }, - { - "name": "agent1public", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agent1public", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "ManagedDisks", - "diskSizesGB": [1], - "osType": "Windows", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "windowsProfile": { - "adminUsername": "azureuser", - "adminPassword": "replacepassword1234$" - }, - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/disks-managed/swarm-windows-vmss.json b/pkg/acsengine/testdata/disks-managed/swarm-windows-vmss.json deleted file mode 100644 index 9f9d7a55fd..0000000000 --- a/pkg/acsengine/testdata/disks-managed/swarm-windows-vmss.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agent128", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "VirtualMachineScaleSets", - "storageProfile": "ManagedDisks", - "diskSizesGB": [128, 128, 128, 128], - "osType": "Windows" - }, - { - "name": "agent1public", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agent1public", - "availabilityProfile": "VirtualMachineScaleSets", - "storageProfile": "ManagedDisks", - "diskSizesGB": [1], - "osType": "Windows", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "windowsProfile": { - "adminUsername": "azureuser", - "adminPassword": "replacepassword1234$" - }, - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/disks-managed/swarmmode-vmas.json b/pkg/acsengine/testdata/disks-managed/swarmmode-vmas.json deleted file mode 100644 index 6d138604ab..0000000000 --- a/pkg/acsengine/testdata/disks-managed/swarmmode-vmas.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agent128", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "ManagedDisks", - "diskSizesGB": [128, 128, 128, 128] - }, - { - "name": "agent1public", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agent1public", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "ManagedDisks", - "diskSizesGB": [1], - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/disks-managed/swarmmode-vmss.json b/pkg/acsengine/testdata/disks-managed/swarmmode-vmss.json deleted file mode 100644 index 99638bd642..0000000000 --- a/pkg/acsengine/testdata/disks-managed/swarmmode-vmss.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agent128", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "VirtualMachineScaleSets", - "storageProfile": "ManagedDisks", - "diskSizesGB": [128, 128, 128, 128] - }, - { - "name": "agent1public", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agent1public", - "availabilityProfile": "VirtualMachineScaleSets", - "storageProfile": "ManagedDisks", - "diskSizesGB": [1], - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/disks-storageaccount/dcos.json b/pkg/acsengine/testdata/disks-storageaccount/dcos.json deleted file mode 100644 index 8a56269d55..0000000000 --- a/pkg/acsengine/testdata/disks-storageaccount/dcos.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agent128", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "StorageAccount", - "diskSizesGB": [128, 128, 128, 128] - }, - { - "name": "agent1public", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agent1public", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "StorageAccount", - "diskSizesGB": [1], - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/disks-storageaccount/swarm.json b/pkg/acsengine/testdata/disks-storageaccount/swarm.json deleted file mode 100644 index 7517d0b586..0000000000 --- a/pkg/acsengine/testdata/disks-storageaccount/swarm.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agent128", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "StorageAccount", - "diskSizesGB": [128, 128, 128, 128] - }, - { - "name": "agent1public", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agent1public", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "StorageAccount", - "diskSizesGB": [1], - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/disks-storageaccount/swarmmode.json b/pkg/acsengine/testdata/disks-storageaccount/swarmmode.json deleted file mode 100644 index 5f8a271263..0000000000 --- a/pkg/acsengine/testdata/disks-storageaccount/swarmmode.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agent128", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "StorageAccount", - "diskSizesGB": [128, 128, 128, 128] - }, - { - "name": "agent1public", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agent1public", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "StorageAccount", - "diskSizesGB": [1], - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/extensions/dcos.json b/pkg/acsengine/testdata/extensions/dcos.json deleted file mode 100644 index 471ef15828..0000000000 --- a/pkg/acsengine/testdata/extensions/dcos.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2", - "preProvisionExtension": { - "name": "hello-world", - "singleOrAll": "All" - } - }, - "agentPoolProfiles": [ - { - "name": "agentpool1", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet", - "preProvisionExtension": { - "name": "hello-world", - "singleOrAll": "All" - } - }, - { - "name": "agentpool2", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - }, - "extensionProfiles": [ - { - "name": "hello-world", - "version": "v1", - "rootURL": "https://raw.githubusercontent.com/Azure/acs-engine/master/", - "script": "hello.sh" - } - ] - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/extensions/swarmmode.json b/pkg/acsengine/testdata/extensions/swarmmode.json deleted file mode 100644 index 8ed54447fa..0000000000 --- a/pkg/acsengine/testdata/extensions/swarmmode.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "apiVersion": "vlabs", - "plan": {}, - "properties": { - "provisioningState": "", - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2", - "firstConsecutiveStaticIP": "172.16.0.5", - "preProvisionExtension": - { - "name": "hello-world-k8s", - "singleOrAll": "all" - } - , - "extensions": [ - { - "name": "hello-world-k8s", - "singleOrAll": "all" - } - ] - }, - "agentPoolProfiles": [ - { - "name": "agentpool1", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentdns1", - "ports": [ - 80, - 443, - 8080 - ], - "availabilityProfile": "AvailabilitySet", - "storageProfile": "StorageAccount", - "extensions": [ - { - "name": "hello-world-k8s", - "singleOrAll": "all" - } - ] - }, - { - "name": "agentpool2", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet", - "storageProfile": "StorageAccount" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - }, - "extensionProfiles": [ - { - "name": "hello-world-k8s", - "version": "v1", - "extensionParameters": "extensionParameters", - "rootURL": "https://raw.githubusercontent.com/Azure/acs-engine/master/", - "script": "test.sh" - } - ], - "windowsProfile": {}, - "servicePrincipalProfile": {}, - "certificateProfile": {} - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/key-vault-certs/dcos.json b/pkg/acsengine/testdata/key-vault-certs/dcos.json deleted file mode 100644 index 3f8049183e..0000000000 --- a/pkg/acsengine/testdata/key-vault-certs/dcos.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentpublic1", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - }, - "secrets":[ - { - "sourceVault":{ - "id":"vaultId" - }, - "vaultCertificates":[ - { - "certificateUrl" :"http://url1" - } - ] - } - ] - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/key-vault-certs/swarm.json b/pkg/acsengine/testdata/key-vault-certs/swarm.json deleted file mode 100644 index 92c2d74738..0000000000 --- a/pkg/acsengine/testdata/key-vault-certs/swarm.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpool1", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentdns1", - "ports": [ - 80, - 443, - 8080 - ] - }, - { - "name": "agentpool2", - "count": 3, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpoolw", - "count": 3, - "vmSize": "Standard_D2_v2", - "osType": "Windows" - } - ], - "windowsProfile": { - "adminUsername": "azureuser", - "adminPassword": "replacepassword1234$", - "secrets":[ - { - "sourceVault":{ - "id":"vaultId" - }, - "vaultCertificates":[ - { - "certificateUrl" :"http://url3", - "certificateStore" : "store" - }, - { - "certificateUrl" :"http://url4", - "certificateStore" : "store" - } - ] - } - ] - }, - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - }, - "secrets":[ - { - "sourceVault":{ - "id":"vaultId" - }, - "vaultCertificates":[ - { - "certificateUrl" :"http://url2" - } - ] - }, - { - "sourceVault":{ - "id":"vaultId2" - }, - "vaultCertificates":[ - { - "certificateUrl" :"http://url1" - } - ] - } - ] - } - } -} diff --git a/pkg/acsengine/testdata/key-vault-certs/swarmmode.json b/pkg/acsengine/testdata/key-vault-certs/swarmmode.json deleted file mode 100644 index 7f4a9619f6..0000000000 --- a/pkg/acsengine/testdata/key-vault-certs/swarmmode.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpool1", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentdns1", - "ports": [ - 80, - 443, - 8080 - ] - }, - { - "name": "agentpool2", - "count": 3, - "vmSize": "Standard_D2_v2" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - }, - "secrets":[ - { - "sourceVault":{ - "id":"vaultId" - }, - "vaultCertificates":[ - { - "certificateUrl" :"http://url2" - } - ] - }, - { - "sourceVault":{ - "id":"vaultId2" - }, - "vaultCertificates":[ - { - "certificateUrl" :"http://url1" - } - ] - } - ] - } - } -} diff --git a/pkg/acsengine/testdata/largeclusters/dcos-vmas.json b/pkg/acsengine/testdata/largeclusters/dcos-vmas.json deleted file mode 100644 index 9b51b32543..0000000000 --- a/pkg/acsengine/testdata/largeclusters/dcos-vmas.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpri0", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri1", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri2", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri3", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri4", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri5", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri6", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri7", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri8", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri9", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri10", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpublic1", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet", - "dnsPrefix": "agentpublic1", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/largeclusters/dcos.json b/pkg/acsengine/testdata/largeclusters/dcos.json deleted file mode 100644 index 1ea576b784..0000000000 --- a/pkg/acsengine/testdata/largeclusters/dcos.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpri0", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri1", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri2", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri3", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri4", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri5", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri6", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri7", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri8", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri9", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri10", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpublic1", - "count": 100, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentpublic1", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/largeclusters/swarm.json b/pkg/acsengine/testdata/largeclusters/swarm.json deleted file mode 100644 index d9772de683..0000000000 --- a/pkg/acsengine/testdata/largeclusters/swarm.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpri0", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri1", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri2", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri3", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri4", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri5", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri6", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri7", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri8", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri9", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri10", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpublic1", - "count": 100, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentpublic1", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/largeclusters/swarmmode.json b/pkg/acsengine/testdata/largeclusters/swarmmode.json deleted file mode 100644 index 62c2f72575..0000000000 --- a/pkg/acsengine/testdata/largeclusters/swarmmode.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpri0", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri1", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri2", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri3", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri4", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri5", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri6", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri7", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri8", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri9", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpri10", - "count": 100, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpublic1", - "count": 100, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentpublic1", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8fhkh3jpHUQsrUIezFB5k4Rq9giJM8G1Cr0u2IRMiqG++nat5hbOr3gODpTA0h11q9bzb6nJtK7NtDzIHx+w3YNIVpcTGLiUEsfUbY53IHg7Nl/p3/gkST3g0R6BSL7Hg45SfyvpH7kwY30MoVHG/6P3go4SKlYoHXlgaaNr3fMwUTIeE9ofvyS3fcr6xxlsoB6luKuEs50h0NGsE4QEnbfSY4Yd/C1ucc3mEw+QFXBIsENHfHfZYrLNHm2L8MXYVmAH8k//5sFs4Migln9GiUgEQUT6uOjowsZyXBbXwfT11og+syPkAq4eqjiC76r0w6faVihdBYVoc/UcyupgH azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/largeclusters/swarmmodevmas.json b/pkg/acsengine/testdata/largeclusters/swarmmodevmas.json deleted file mode 100644 index 743e70365b..0000000000 --- a/pkg/acsengine/testdata/largeclusters/swarmmodevmas.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpri0", - "count": 1, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri1", - "count": 1, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri2", - "count": 1, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri3", - "count": 1, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri4", - "count": 1, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri5", - "count": 1, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri6", - "count": 1, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri7", - "count": 1, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri8", - "count": 1, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri9", - "count": 1, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri10", - "count": 1, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri11", - "count": 1, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8fhkh3jpHUQsrUIezFB5k4Rq9giJM8G1Cr0u2IRMiqG++nat5hbOr3gODpTA0h11q9bzb6nJtK7NtDzIHx+w3YNIVpcTGLiUEsfUbY53IHg7Nl/p3/gkST3g0R6BSL7Hg45SfyvpH7kwY30MoVHG/6P3go4SKlYoHXlgaaNr3fMwUTIeE9ofvyS3fcr6xxlsoB6luKuEs50h0NGsE4QEnbfSY4Yd/C1ucc3mEw+QFXBIsENHfHfZYrLNHm2L8MXYVmAH8k//5sFs4Migln9GiUgEQUT6uOjowsZyXBbXwfT11og+syPkAq4eqjiC76r0w6faVihdBYVoc/UcyupgH azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/largeclusters/swarmvmas.json b/pkg/acsengine/testdata/largeclusters/swarmvmas.json deleted file mode 100644 index 63b119dbbc..0000000000 --- a/pkg/acsengine/testdata/largeclusters/swarmvmas.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpri0", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri1", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri2", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri3", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri4", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri5", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri6", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri7", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri8", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri9", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri10", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - }, - { - "name": "agentpri11", - "count": 100, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8fhkh3jpHUQsrUIezFB5k4Rq9giJM8G1Cr0u2IRMiqG++nat5hbOr3gODpTA0h11q9bzb6nJtK7NtDzIHx+w3YNIVpcTGLiUEsfUbY53IHg7Nl/p3/gkST3g0R6BSL7Hg45SfyvpH7kwY30MoVHG/6P3go4SKlYoHXlgaaNr3fMwUTIeE9ofvyS3fcr6xxlsoB6luKuEs50h0NGsE4QEnbfSY4Yd/C1ucc3mEw+QFXBIsENHfHfZYrLNHm2L8MXYVmAH8k//5sFs4Migln9GiUgEQUT6uOjowsZyXBbXwfT11og+syPkAq4eqjiC76r0w6faVihdBYVoc/UcyupgH azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/location/dcos.json b/pkg/acsengine/testdata/location/dcos.json deleted file mode 100644 index d942686ae9..0000000000 --- a/pkg/acsengine/testdata/location/dcos.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "apiVersion": "vlabs", - "location": "eastus", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentpublic1", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/location/swarm.json b/pkg/acsengine/testdata/location/swarm.json deleted file mode 100644 index 316b17d0bc..0000000000 --- a/pkg/acsengine/testdata/location/swarm.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "apiVersion": "vlabs", - "location": "centralus", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpool1", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentdns1", - "ports": [ - 80, - 443, - 8080 - ] - }, - { - "name": "agentpool2", - "count": 3, - "vmSize": "Standard_D2_v2" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/simple/dcos.json b/pkg/acsengine/testdata/simple/dcos.json deleted file mode 100644 index 193e020dc1..0000000000 --- a/pkg/acsengine/testdata/simple/dcos.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentpublic1", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/simple/dcos1.10.0.json b/pkg/acsengine/testdata/simple/dcos1.10.0.json deleted file mode 100644 index 3fab18e994..0000000000 --- a/pkg/acsengine/testdata/simple/dcos1.10.0.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS", - "orchestratorRelease": "1.10" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentpublic1", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} diff --git a/pkg/acsengine/testdata/simple/dcos1.8.8.json b/pkg/acsengine/testdata/simple/dcos1.8.8.json deleted file mode 100644 index a5de9b1be2..0000000000 --- a/pkg/acsengine/testdata/simple/dcos1.8.8.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS", - "orchestratorRelease": "1.8" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentpublic1", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} diff --git a/pkg/acsengine/testdata/simple/dcos1.9.0.json b/pkg/acsengine/testdata/simple/dcos1.9.0.json deleted file mode 100644 index 2edd5d37b2..0000000000 --- a/pkg/acsengine/testdata/simple/dcos1.9.0.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS", - "orchestratorRelease": "1.9" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentpublic1", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} diff --git a/pkg/acsengine/testdata/simple/swarm.json b/pkg/acsengine/testdata/simple/swarm.json deleted file mode 100644 index a32d1f2b64..0000000000 --- a/pkg/acsengine/testdata/simple/swarm.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpool1", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentdns1", - "ports": [ - 80, - 443, - 8080 - ] - }, - { - "name": "agentpool2", - "count": 3, - "vmSize": "Standard_D2_v2" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/simple/swarmmode.json b/pkg/acsengine/testdata/simple/swarmmode.json deleted file mode 100644 index a257703ffe..0000000000 --- a/pkg/acsengine/testdata/simple/swarmmode.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "apiVersion": "vlabs", - "plan": {}, - "properties": { - "provisioningState": "", - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2", - "firstConsecutiveStaticIP": "172.16.0.5" - }, - "agentPoolProfiles": [ - { - "name": "agentpool1", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentdns1", - "ports": [ - 80, - 443, - 8080 - ], - "availabilityProfile": "VirtualMachineScaleSets", - "storageProfile": "StorageAccount" - }, - { - "name": "agentpool2", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "VirtualMachineScaleSets", - "storageProfile": "StorageAccount" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - }, - "windowsProfile": {}, - "servicePrincipalProfile": {}, - "certificateProfile": {} - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/simple/swarmmode_classicmode.json b/pkg/acsengine/testdata/simple/swarmmode_classicmode.json deleted file mode 100644 index 12ece77057..0000000000 --- a/pkg/acsengine/testdata/simple/swarmmode_classicmode.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "apiVersion": "vlabs", - "plan": {}, - "properties": { - "provisioningState": "", - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "master", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agent", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentdns1", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/v20160330/dcos.json b/pkg/acsengine/testdata/v20160330/dcos.json deleted file mode 100644 index 642e1c12f5..0000000000 --- a/pkg/acsengine/testdata/v20160330/dcos.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "apiVersion": "2016-03-30", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "test-dcos-pool", - "osType": "Linux" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/v20160330/defaults.json b/pkg/acsengine/testdata/v20160330/defaults.json deleted file mode 100644 index eb7c8dd84d..0000000000 --- a/pkg/acsengine/testdata/v20160330/defaults.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "apiVersion": "2016-03-30", - "properties": { - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "test-dcos-pool", - "osType": "Linux" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/v20160330/swarm.json b/pkg/acsengine/testdata/v20160330/swarm.json deleted file mode 100644 index 4b2162f938..0000000000 --- a/pkg/acsengine/testdata/v20160330/swarm.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "apiVersion": "2016-03-30", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "masterdns1" - }, - "agentPoolProfiles": [ - { - "name": "agentpool1", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentdns1" - }, - { - "name": "agentpool2", - "count": 3, - "vmSize": "Standard_D2_v2" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/v20160930/dcos.json b/pkg/acsengine/testdata/v20160930/dcos.json deleted file mode 100644 index 509dde1eeb..0000000000 --- a/pkg/acsengine/testdata/v20160930/dcos.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "apiVersion": "2016-09-30", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "test-dcos-pool", - "osType": "Linux" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/v20160930/defaults.json b/pkg/acsengine/testdata/v20160930/defaults.json deleted file mode 100644 index 2ebd84142f..0000000000 --- a/pkg/acsengine/testdata/v20160930/defaults.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "apiVersion": "2016-09-30", - "properties": { - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "test-dcos-pool", - "osType": "Linux" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/v20170131/dcos.json b/pkg/acsengine/testdata/v20170131/dcos.json deleted file mode 100644 index 8577992536..0000000000 --- a/pkg/acsengine/testdata/v20170131/dcos.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "apiVersion": "2017-01-31", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "test-dcos-pool", - "osType": "Linux" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/v20170131/defaults.json b/pkg/acsengine/testdata/v20170131/defaults.json deleted file mode 100644 index 5b4c489e7a..0000000000 --- a/pkg/acsengine/testdata/v20170131/defaults.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "apiVersion": "2017-01-31", - "properties": { - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "test-dcos-pool", - "osType": "Linux" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/v20170131/swarmmode.json b/pkg/acsengine/testdata/v20170131/swarmmode.json deleted file mode 100644 index 36497cad8b..0000000000 --- a/pkg/acsengine/testdata/v20170131/swarmmode.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "apiVersion": "2017-01-31", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentdns1", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} diff --git a/pkg/acsengine/testdata/v20170701/dcos.json b/pkg/acsengine/testdata/v20170701/dcos.json deleted file mode 100644 index 6fdc8c3bd7..0000000000 --- a/pkg/acsengine/testdata/v20170701/dcos.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "apiVersion": "2017-07-01", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 1, - "vmSize": "Standard_D2_v2" - }, - { - "name": "agentpublic", - "count": 1, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentpublic1", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} diff --git a/pkg/acsengine/testdata/v20170701/dockerce.json b/pkg/acsengine/testdata/v20170701/dockerce.json deleted file mode 100644 index 5846030d60..0000000000 --- a/pkg/acsengine/testdata/v20170701/dockerce.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "apiVersion": "2017-07-01", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DockerCE" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentdns1", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} diff --git a/pkg/acsengine/testdata/vnet/dcosvnet.json b/pkg/acsengine/testdata/vnet/dcosvnet.json deleted file mode 100644 index b89de4c767..0000000000 --- a/pkg/acsengine/testdata/vnet/dcosvnet.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "DCOS", - "dcosConfig": { - "bootstrapProfile": { - "staticIP": "10.100.0.240" - } - } - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2", - "vnetSubnetId": "/subscriptions/SUBSCRIPTION/resourceGroups/ExampleRG/providers/Microsoft.Network/virtualNetworks/ExampleCustomVNET/subnets/ExampleMasterSubnet", - "firstConsecutiveStaticIP": "10.100.0.5" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet", - "vnetSubnetId": "/subscriptions/SUBSCRIPTION/resourceGroups/ExampleRG/providers/Microsoft.Network/virtualNetworks/ExampleCustomVNET/subnets/ExampleAgentSubnet" - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentpublic", - "vnetSubnetId": "/subscriptions/SUBSCRIPTION/resourceGroups/ExampleRG/providers/Microsoft.Network/virtualNetworks/ExampleCustomVNET/subnets/ExampleAgentSubnet", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } -} -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/vnet/swarmmodevnet.json b/pkg/acsengine/testdata/vnet/swarmmodevnet.json deleted file mode 100644 index ca0b8e5688..0000000000 --- a/pkg/acsengine/testdata/vnet/swarmmodevnet.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2", - "vnetSubnetId": "/subscriptions/SUBSCRIPTION/resourceGroups/ExampleRG/providers/Microsoft.Network/virtualNetworks/ExampleCustomVNET/subnets/ExampleMasterSubnet", - "firstConsecutiveStaticIP": "10.100.0.5" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2", - "vnetSubnetId": "/subscriptions/SUBSCRIPTION/resourceGroups/ExampleRG/providers/Microsoft.Network/virtualNetworks/ExampleCustomVNET/subnets/ExampleAgentSubnet" - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentpublic", - "vnetSubnetId": "/subscriptions/SUBSCRIPTION/resourceGroups/ExampleRG/providers/Microsoft.Network/virtualNetworks/ExampleCustomVNET/subnets/ExampleAgentSubnet", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/vnet/swarmvnet.json b/pkg/acsengine/testdata/vnet/swarmvnet.json deleted file mode 100644 index 9e66f03ec9..0000000000 --- a/pkg/acsengine/testdata/vnet/swarmvnet.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2", - "vnetSubnetId": "/subscriptions/SUBSCRIPTION/resourceGroups/ExampleRG/providers/Microsoft.Network/virtualNetworks/ExampleCustomVNET/subnets/ExampleMasterSubnet", - "firstConsecutiveStaticIP": "10.100.0.5" - }, - "agentPoolProfiles": [ - { - "name": "agentprivate", - "count": 3, - "vmSize": "Standard_D2_v2", - "vnetSubnetId": "/subscriptions/SUBSCRIPTION/resourceGroups/ExampleRG/providers/Microsoft.Network/virtualNetworks/ExampleCustomVNET/subnets/ExampleAgentSubnet" - }, - { - "name": "agentpublic", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "agentpublic", - "vnetSubnetId": "/subscriptions/SUBSCRIPTION/resourceGroups/ExampleRG/providers/Microsoft.Network/virtualNetworks/ExampleCustomVNET/subnets/ExampleAgentSubnet", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/windows/swarm-vmas.json b/pkg/acsengine/testdata/windows/swarm-vmas.json deleted file mode 100644 index 9ce3e58dc0..0000000000 --- a/pkg/acsengine/testdata/windows/swarm-vmas.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "publicwin1", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "publicwin1", - "osType": "Windows", - "availabilityProfile": "AvailabilitySet", - "ports": [ - 80, - 443, - 8080 - ] - }, - { - "name": "privatewin", - "count": 3, - "vmSize": "Standard_D2_v2", - "availabilityProfile": "AvailabilitySet", - "osType": "Windows" - } - ], - "windowsProfile": { - "adminUsername": "azureuser", - "adminPassword": "replacepassword1234$" - }, - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/windows/swarm.json b/pkg/acsengine/testdata/windows/swarm.json deleted file mode 100644 index 97c31303b4..0000000000 --- a/pkg/acsengine/testdata/windows/swarm.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "publicwin1", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "publicwin1", - "osType": "Windows", - "ports": [ - 80, - 443, - 8080 - ] - }, - { - "name": "privatewin", - "count": 3, - "vmSize": "Standard_D2_v2", - "osType": "Windows" - } - ], - "windowsProfile": { - "adminUsername": "azureuser", - "adminPassword": "replacepassword1234$" - }, - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/windows/swarmWinAndLin.json b/pkg/acsengine/testdata/windows/swarmWinAndLin.json deleted file mode 100644 index ec05653678..0000000000 --- a/pkg/acsengine/testdata/windows/swarmWinAndLin.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "apiVersion": "vlabs", - "properties": { - "orchestratorProfile": { - "orchestratorType": "Swarm" - }, - "masterProfile": { - "count": 1, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "publicwin1", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "publicwin1", - "osType": "Windows", - "ports": [ - 80, - 443, - 8080 - ] - }, - { - "name": "privatewin", - "count": 3, - "vmSize": "Standard_D2_v2", - "osType": "Windows" - }, - { - "name": "privatelinux", - "count": 3, - "vmSize": "Standard_D2_v2", - "osType": "Linux" - } - ], - "windowsProfile": { - "adminUsername": "azureuser", - "adminPassword": "replacepassword1234$" - }, - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/windows/swarmmode-windows_classicmode.json b/pkg/acsengine/testdata/windows/swarmmode-windows_classicmode.json deleted file mode 100644 index c10a850bee..0000000000 --- a/pkg/acsengine/testdata/windows/swarmmode-windows_classicmode.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "apiVersion": "vlabs", - "plan": {}, - "properties": { - "provisioningState": "", - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "master", - "vmSize": "Standard_D2_v2" - }, - "agentPoolProfiles": [ - { - "name": "agent", - "count": 3, - "vmSize": "Standard_D2_v2", - "osType": "Windows", - "dnsPrefix": "agentdns1", - "ports": [ - 80, - 443, - 8080 - ] - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - }, - "windowsProfile": { - "adminUsername": "azureuser", - "adminPassword": "replacepassword1234$" - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/testdata/windows/swarmmodeWinAndLin.json b/pkg/acsengine/testdata/windows/swarmmodeWinAndLin.json deleted file mode 100644 index 670e9f9402..0000000000 --- a/pkg/acsengine/testdata/windows/swarmmodeWinAndLin.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "apiVersion": "vlabs", - "plan": {}, - "properties": { - "provisioningState": "", - "orchestratorProfile": { - "orchestratorType": "SwarmMode" - }, - "masterProfile": { - "count": 3, - "dnsPrefix": "masterdns1", - "vmSize": "Standard_D2_v2", - "firstConsecutiveStaticIP": "172.16.0.5" - }, - "agentPoolProfiles": [ - { - "name": "publicwin1", - "count": 3, - "vmSize": "Standard_D2_v2", - "dnsPrefix": "publicwin1", - "osType": "Windows", - "ports": [ - 80, - 443, - 8080 - ] - }, - { - "name": "privatewin", - "count": 3, - "vmSize": "Standard_D2_v2", - "osType": "Windows" - }, - { - "name": "privatelinux", - "count": 3, - "vmSize": "Standard_D2_v2", - "osType": "Linux" - } - ], - "linuxProfile": { - "adminUsername": "azureuser", - "ssh": { - "publicKeys": [ - { - "keyData": "ssh-rsa PUBLICKEY azureuser@linuxvm" - } - ] - } - }, - "windowsProfile": { - "adminUsername": "azureuser", - "adminPassword": "replacepassword1234$" - }, - "servicePrincipalProfile": {}, - "certificateProfile": {} - } -} \ No newline at end of file diff --git a/pkg/acsengine/transform/transformtestfiles/dcos_scale_template.json b/pkg/acsengine/transform/transformtestfiles/dcos_scale_template.json deleted file mode 100644 index f3d907ea6e..0000000000 --- a/pkg/acsengine/transform/transformtestfiles/dcos_scale_template.json +++ /dev/null @@ -1,1142 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "agentpri2Count": { - "allowedValues": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31, - 32, - 33, - 34, - 35, - 36, - 37, - 38, - 39, - 40, - 41, - 42, - 43, - 44, - 45, - 46, - 47, - 48, - 49, - 50, - 51, - 52, - 53, - 54, - 55, - 56, - 57, - 58, - 59, - 60, - 61, - 62, - 63, - 64, - 65, - 66, - 67, - 68, - 69, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, - 79, - 80, - 81, - 82, - 83, - 84, - 85, - 86, - 87, - 88, - 89, - 90, - 91, - 92, - 93, - 94, - 95, - 96, - 97, - 98, - 99, - 100 - ], - "defaultValue": 2, - "metadata": { - "description": "The number of agents for the cluster. This value can be from 1 to 100" - }, - "type": "int" - }, - "agentpri2Subnet": { - "defaultValue": "10.1.0.0/16", - "metadata": { - "description": "Sets the subnet of agent pool 'agentpri2'." - }, - "type": "string" - }, - "agentpri2VMSize": { - "allowedValues": [ - "Standard_A10", - "Standard_A11", - "Standard_A2", - "Standard_A2_v2", - "Standard_A2m_v2", - "Standard_A3", - "Standard_A4", - "Standard_A4_v2", - "Standard_A4m_v2", - "Standard_A5", - "Standard_A6", - "Standard_A7", - "Standard_A8", - "Standard_A8_v2", - "Standard_A8m_v2", - "Standard_A9", - "Standard_D11", - "Standard_D11_v2", - "Standard_D11_v2_Promo", - "Standard_D12", - "Standard_D12_v2", - "Standard_D12_v2_Promo", - "Standard_D13", - "Standard_D13_v2", - "Standard_D13_v2_Promo", - "Standard_D14", - "Standard_D14_v2", - "Standard_D14_v2_Promo", - "Standard_D15_v2", - "Standard_D2", - "Standard_D2_v2", - "Standard_D2_v2_Promo", - "Standard_D3", - "Standard_D3_v2", - "Standard_D3_v2_Promo", - "Standard_D4", - "Standard_D4_v2", - "Standard_D4_v2_Promo", - "Standard_D5_v2", - "Standard_D5_v2_Promo", - "Standard_DS11", - "Standard_DS11_v2", - "Standard_DS11_v2_Promo", - "Standard_DS12", - "Standard_DS12_v2", - "Standard_DS12_v2_Promo", - "Standard_DS13", - "Standard_DS13_v2", - "Standard_DS13_v2_Promo", - "Standard_DS14", - "Standard_DS14_v2", - "Standard_DS14_v2_Promo", - "Standard_DS15_v2", - "Standard_DS2", - "Standard_DS2_v2", - "Standard_DS2_v2_Promo", - "Standard_DS3", - "Standard_DS3_v2", - "Standard_DS3_v2_Promo", - "Standard_DS4", - "Standard_DS4_v2", - "Standard_DS4_v2_Promo", - "Standard_DS5_v2", - "Standard_DS5_v2_Promo", - "Standard_F16", - "Standard_F16s", - "Standard_F2", - "Standard_F2s", - "Standard_F4", - "Standard_F4s", - "Standard_F8", - "Standard_F8s", - "Standard_G1", - "Standard_G2", - "Standard_G3", - "Standard_G4", - "Standard_G5", - "Standard_GS1", - "Standard_GS2", - "Standard_GS3", - "Standard_GS4", - "Standard_GS5", - "Standard_H16", - "Standard_H16m", - "Standard_H16mr", - "Standard_H16r", - "Standard_H8", - "Standard_H8m", - "Standard_L16s", - "Standard_L32s", - "Standard_L4s", - "Standard_L8s", - "Standard_M128ms", - "Standard_M128s", - "Standard_M64ms", - "Standard_NC12", - "Standard_NC24", - "Standard_NC24r", - "Standard_NC6", - "Standard_NV12", - "Standard_NV24", - "Standard_NV6" - ], - "defaultValue": "Standard_D2_v2", - "metadata": { - "description": "The size of the Virtual Machine." - }, - "type": "string" - }, - "agentpriCount": { - "allowedValues": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31, - 32, - 33, - 34, - 35, - 36, - 37, - 38, - 39, - 40, - 41, - 42, - 43, - 44, - 45, - 46, - 47, - 48, - 49, - 50, - 51, - 52, - 53, - 54, - 55, - 56, - 57, - 58, - 59, - 60, - 61, - 62, - 63, - 64, - 65, - 66, - 67, - 68, - 69, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, - 79, - 80, - 81, - 82, - 83, - 84, - 85, - 86, - 87, - 88, - 89, - 90, - 91, - 92, - 93, - 94, - 95, - 96, - 97, - 98, - 99, - 100 - ], - "defaultValue": 2, - "metadata": { - "description": "The number of agents for the cluster. This value can be from 1 to 100" - }, - "type": "int" - }, - "agentpriSubnet": { - "defaultValue": "10.0.0.0/16", - "metadata": { - "description": "Sets the subnet of agent pool 'agentpri'." - }, - "type": "string" - }, - "agentpriVMSize": { - "allowedValues": [ - "Standard_A10", - "Standard_A11", - "Standard_A2", - "Standard_A2_v2", - "Standard_A2m_v2", - "Standard_A3", - "Standard_A4", - "Standard_A4_v2", - "Standard_A4m_v2", - "Standard_A5", - "Standard_A6", - "Standard_A7", - "Standard_A8", - "Standard_A8_v2", - "Standard_A8m_v2", - "Standard_A9", - "Standard_D11", - "Standard_D11_v2", - "Standard_D11_v2_Promo", - "Standard_D12", - "Standard_D12_v2", - "Standard_D12_v2_Promo", - "Standard_D13", - "Standard_D13_v2", - "Standard_D13_v2_Promo", - "Standard_D14", - "Standard_D14_v2", - "Standard_D14_v2_Promo", - "Standard_D15_v2", - "Standard_D2", - "Standard_D2_v2", - "Standard_D2_v2_Promo", - "Standard_D3", - "Standard_D3_v2", - "Standard_D3_v2_Promo", - "Standard_D4", - "Standard_D4_v2", - "Standard_D4_v2_Promo", - "Standard_D5_v2", - "Standard_D5_v2_Promo", - "Standard_DS11", - "Standard_DS11_v2", - "Standard_DS11_v2_Promo", - "Standard_DS12", - "Standard_DS12_v2", - "Standard_DS12_v2_Promo", - "Standard_DS13", - "Standard_DS13_v2", - "Standard_DS13_v2_Promo", - "Standard_DS14", - "Standard_DS14_v2", - "Standard_DS14_v2_Promo", - "Standard_DS15_v2", - "Standard_DS2", - "Standard_DS2_v2", - "Standard_DS2_v2_Promo", - "Standard_DS3", - "Standard_DS3_v2", - "Standard_DS3_v2_Promo", - "Standard_DS4", - "Standard_DS4_v2", - "Standard_DS4_v2_Promo", - "Standard_DS5_v2", - "Standard_DS5_v2_Promo", - "Standard_F16", - "Standard_F16s", - "Standard_F2", - "Standard_F2s", - "Standard_F4", - "Standard_F4s", - "Standard_F8", - "Standard_F8s", - "Standard_G1", - "Standard_G2", - "Standard_G3", - "Standard_G4", - "Standard_G5", - "Standard_GS1", - "Standard_GS2", - "Standard_GS3", - "Standard_GS4", - "Standard_GS5", - "Standard_H16", - "Standard_H16m", - "Standard_H16mr", - "Standard_H16r", - "Standard_H8", - "Standard_H8m", - "Standard_L16s", - "Standard_L32s", - "Standard_L4s", - "Standard_L8s", - "Standard_M128ms", - "Standard_M128s", - "Standard_M64ms", - "Standard_NC12", - "Standard_NC24", - "Standard_NC24r", - "Standard_NC6", - "Standard_NV12", - "Standard_NV24", - "Standard_NV6" - ], - "defaultValue": "Standard_D2_v2", - "metadata": { - "description": "The size of the Virtual Machine." - }, - "type": "string" - }, - "dcosBootstrapURL": { - "defaultValue": "https://dcosio.azureedge.net/dcos/stable/bootstrap/58fd0833ce81b6244fc73bf65b5deb43217b0bd7.bootstrap.tar.xz", - "metadata": { - "description": "The default mesosphere bootstrap package." - }, - "type": "string" - }, - "firstConsecutiveStaticIP": { - "defaultValue": "172.16.0.5", - "metadata": { - "description": "Sets the static IP of the first master" - }, - "type": "string" - }, - "linuxAdminUsername": { - "metadata": { - "description": "User name for the Linux Virtual Machines (SSH or Password)." - }, - "type": "string" - }, - "location": { - "defaultValue": "", - "metadata": { - "description": "Sets the location for all resources in the cluster" - }, - "type": "string" - }, - "masterEndpointDNSNamePrefix": { - "metadata": { - "description": "Sets the Domain name label for the master IP Address. The concatenation of the domain name label and the regional DNS zone make up the fully qualified domain name associated with the public IP address." - }, - "type": "string" - }, - "masterSubnet": { - "defaultValue": "172.16.0.0/24", - "metadata": { - "description": "Sets the subnet of the master node(s)." - }, - "type": "string" - }, - "masterVMSize": { - "allowedValues": [ - "Standard_A10", - "Standard_A11", - "Standard_A2", - "Standard_A3", - "Standard_A4", - "Standard_A5", - "Standard_A6", - "Standard_A7", - "Standard_A8", - "Standard_A9", - "Standard_D11", - "Standard_D11_v2", - "Standard_D11_v2_Promo", - "Standard_D12", - "Standard_D12_v2", - "Standard_D12_v2_Promo", - "Standard_D13", - "Standard_D13_v2", - "Standard_D13_v2_Promo", - "Standard_D14", - "Standard_D14_v2", - "Standard_D14_v2_Promo", - "Standard_D15_v2", - "Standard_D2", - "Standard_D2_v2", - "Standard_D2_v2_Promo", - "Standard_D3", - "Standard_D3_v2", - "Standard_D3_v2_Promo", - "Standard_D4", - "Standard_D4_v2", - "Standard_D4_v2_Promo", - "Standard_D5_v2", - "Standard_D5_v2_Promo", - "Standard_DS13", - "Standard_DS13_v2", - "Standard_DS13_v2_Promo", - "Standard_DS14", - "Standard_DS14_v2", - "Standard_DS14_v2_Promo", - "Standard_DS15_v2", - "Standard_DS5_v2", - "Standard_DS5_v2_Promo", - "Standard_F16", - "Standard_F8", - "Standard_G1", - "Standard_G2", - "Standard_G3", - "Standard_G4", - "Standard_G5", - "Standard_GS2", - "Standard_GS3", - "Standard_GS4", - "Standard_GS5", - "Standard_H16", - "Standard_H16m", - "Standard_H16mr", - "Standard_H16r", - "Standard_H8", - "Standard_H8m", - "Standard_L16s", - "Standard_L32s", - "Standard_L4s", - "Standard_L8s", - "Standard_M128ms", - "Standard_M128s", - "Standard_M64ms", - "Standard_NC12", - "Standard_NC24", - "Standard_NC24r", - "Standard_NC6", - "Standard_NV12", - "Standard_NV24", - "Standard_NV6" - ], - "metadata": { - "description": "The size of the Virtual Machine." - }, - "type": "string" - }, - "nameSuffix": { - "defaultValue": "25033075", - "metadata": { - "description": "A string hash of the master DNS name to uniquely identify the cluster." - }, - "type": "string" - }, - "sshRSAPublicKey": { - "metadata": { - "description": "SSH public key used for auth to all Linux machines. Not Required. If not set, you must provide a password key." - }, - "type": "string" - }, - "targetEnvironment": { - "defaultValue": "AzurePublicCloud", - "metadata": { - "description": "The azure deploy environment. Currently support: AzurePublicCloud, AzureChinaCloud" - }, - "type": "string" - } - }, - "variables": { - "adminUsername": "[parameters('linuxAdminUsername')]", - "agentpri2Count": "[parameters('agentpri2Count')]", - "agentpri2NSGID": "[resourceId('Microsoft.Network/networkSecurityGroups',variables('agentpri2NSGName'))]", - "agentpri2NSGName": "[concat(variables('orchestratorName'), '-agentpri2-nsg-', variables('nameSuffix'))]", - "agentpri2Subnet": "[parameters('agentpri2Subnet')]", - "agentpri2SubnetName": "[concat(variables('orchestratorName'), '-agentpri2Subnet')]", - "agentpri2VMNamePrefix": "[concat(variables('orchestratorName'), '-agentpri2-', variables('nameSuffix'))]", - "agentpri2VMSize": "[parameters('agentpri2VMSize')]", - "agentpri2VMSizeTier": "[split(parameters('agentpri2VMSize'),'_')[0]]", - "agentpri2VnetSubnetID": "[concat(variables('vnetID'),'/subnets/',variables('agentpri2SubnetName'))]", - "agentpriCount": "[parameters('agentpriCount')]", - "agentpriNSGID": "[resourceId('Microsoft.Network/networkSecurityGroups',variables('agentpriNSGName'))]", - "agentpriNSGName": "[concat(variables('orchestratorName'), '-agentpri-nsg-', variables('nameSuffix'))]", - "agentpriSubnet": "[parameters('agentpriSubnet')]", - "agentpriSubnetName": "[concat(variables('orchestratorName'), '-agentpriSubnet')]", - "agentpriVMNamePrefix": "[concat(variables('orchestratorName'), '-agentpri-', variables('nameSuffix'))]", - "agentpriVMSize": "[parameters('agentpriVMSize')]", - "agentpriVMSizeTier": "[split(parameters('agentpriVMSize'),'_')[0]]", - "agentpriVnetSubnetID": "[concat(variables('vnetID'),'/subnets/',variables('agentpriSubnetName'))]", - "apiVersionDefault": "2016-03-30", - "apiVersionStorage": "2015-06-15", - "apiVersionStorageManagedDisks": "2016-04-30-preview", - "dcosBootstrapURL": "[parameters('dcosBootstrapURL')]", - "location": "[variables('locations')[mod(add(2,length(parameters('location'))),add(1,length(parameters('location'))))]]", - "locations": [ - "[resourceGroup().location]", - "[parameters('location')]" - ], - "masterAvailabilitySet": "[concat(variables('orchestratorName'), '-master-availabilitySet-', variables('nameSuffix'))]", - "masterCount": 1, - "masterEndpointDNSNamePrefix": "[tolower(parameters('masterEndpointDNSNamePrefix'))]", - "masterFirstAddrOctet4": "[variables('masterFirstAddrOctets')[3]]", - "masterFirstAddrOctets": "[split(parameters('firstConsecutiveStaticIP'),'.')]", - "masterFirstAddrPrefix": "[concat(variables('masterFirstAddrOctets')[0],'.',variables('masterFirstAddrOctets')[1],'.',variables('masterFirstAddrOctets')[2],'.')]", - "masterHttpSourceAddressPrefix": "*", - "masterLbBackendPoolName": "[concat(variables('orchestratorName'), '-master-pool-', variables('nameSuffix'))]", - "masterLbID": "[resourceId('Microsoft.Network/loadBalancers',variables('masterLbName'))]", - "masterLbIPConfigID": "[concat(variables('masterLbID'),'/frontendIPConfigurations/', variables('masterLbIPConfigName'))]", - "masterLbIPConfigName": "[concat(variables('orchestratorName'), '-master-lbFrontEnd-', variables('nameSuffix'))]", - "masterLbInboundNatRules": [ - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'0')]" - }, - { - "id": "[concat(variables('masterSshPort22InboundNatRuleIdPrefix'),'0')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'1')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'2')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'3')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'4')]" - } - ] - ], - "masterLbName": "[concat(variables('orchestratorName'), '-master-lb-', variables('nameSuffix'))]", - "masterNSGID": "[resourceId('Microsoft.Network/networkSecurityGroups',variables('masterNSGName'))]", - "masterNSGName": "[concat(variables('orchestratorName'), '-master-nsg-', variables('nameSuffix'))]", - "masterPublicIPAddressName": "[concat(variables('orchestratorName'), '-master-ip-', variables('masterEndpointDNSNamePrefix'), '-', variables('nameSuffix'))]", - "masterSshInboundNatRuleIdPrefix": "[concat(variables('masterLbID'),'/inboundNatRules/SSH-',variables('masterVMNamePrefix'))]", - "masterSshPort22InboundNatRuleIdPrefix": "[concat(variables('masterLbID'),'/inboundNatRules/SSHPort22-',variables('masterVMNamePrefix'))]", - "masterStorageAccountExhibitorName": "[concat(variables('storageAccountBaseName'), 'exhb0')]", - "masterSubnet": "[parameters('masterSubnet')]", - "masterSubnetName": "[concat(variables('orchestratorName'), '-masterSubnet')]", - "masterVMNamePrefix": "[concat(variables('orchestratorName'), '-master-', variables('nameSuffix'), '-')]", - "masterVMNic": [ - "[concat(variables('masterVMNamePrefix'), 'nic-0')]", - "[concat(variables('masterVMNamePrefix'), 'nic-1')]", - "[concat(variables('masterVMNamePrefix'), 'nic-2')]", - "[concat(variables('masterVMNamePrefix'), 'nic-3')]", - "[concat(variables('masterVMNamePrefix'), 'nic-4')]", - "[concat(variables('masterVMNamePrefix'), 'nic-5')]", - "[concat(variables('masterVMNamePrefix'), 'nic-6')]" - ], - "masterVMSize": "[parameters('masterVMSize')]", - "masterVnetSubnetID": "[concat(variables('vnetID'),'/subnets/',variables('masterSubnetName'))]", - "maxVMsPerPool": 100, - "nameSuffix": "[parameters('nameSuffix')]", - "oauthEnabled": "false", - "orchestratorName": "dcos", - "osImageOffer": "UbuntuServer", - "osImagePublisher": "Canonical", - "osImageSKU": "16.04-LTS", - "osImageVersion": "16.04.201708151", - "sshKeyPath": "[concat('/home/', variables('adminUsername'), '/.ssh/authorized_keys')]", - "sshRSAPublicKey": "[parameters('sshRSAPublicKey')]", - "storageAccountBaseName": "[uniqueString(concat(variables('masterEndpointDNSNamePrefix'),variables('location'),variables('orchestratorName')))]", - "storageAccountPrefixes": [], - "storageAccountType": "Standard_LRS", - "targetEnvironment": "[parameters('targetEnvironment')]", - "virtualNetworkName": "[concat(variables('orchestratorName'), '-vnet-', variables('nameSuffix'))]", - "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]" - }, - "resources": [ - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('agentpriNSGName')]", - "properties": { - "securityRules": [] - }, - "type": "Microsoft.Network/networkSecurityGroups" - }, - { - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", - "dependsOn": [ - "[variables('vnetID')]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('agentpriVMNamePrefix'), '-vmss')]", - "properties": { - "upgradePolicy": { - "mode": "Manual" - }, - "virtualMachineProfile": { - "networkProfile": { - "networkInterfaceConfigurations": [ - { - "name": "nic", - "properties": { - "ipConfigurations": [ - { - "name": "nicipconfig", - "properties": { - "subnet": { - "id": "[variables('agentpriVnetSubnetID')]" - } - } - } - ], - "primary": "true" - } - } - ] - }, - "osProfile": { - "adminUsername": "[variables('adminUsername')]", - "computerNamePrefix": "[variables('agentpriVMNamePrefix')]", - "linuxConfiguration": { - "disablePasswordAuthentication": "true", - "ssh": { - "publicKeys": [ - { - "keyData": "[parameters('sshRSAPublicKey')]", - "path": "[variables('sshKeyPath')]" - } - ] - } - } - }, - "storageProfile": { - "osDisk": { - "caching": "ReadOnly", - "createOption": "FromImage" - } - } - } - }, - "sku": { - "capacity": "[variables('agentpriCount')]", - "name": "[variables('agentpriVMSize')]", - "tier": "[variables('agentpriVMSizeTier')]" - }, - "tags": { - "creationSource": "[concat('acsengine-', variables('agentpriVMNamePrefix'), '-vmss')]" - }, - "type": "Microsoft.Compute/virtualMachineScaleSets" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('agentpri2NSGName')]", - "properties": { - "securityRules": [] - }, - "type": "Microsoft.Network/networkSecurityGroups" - }, - { - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", - "dependsOn": [ - "[variables('vnetID')]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('agentpri2VMNamePrefix'), '-vmss')]", - "properties": { - "upgradePolicy": { - "mode": "Manual" - }, - "virtualMachineProfile": { - "networkProfile": { - "networkInterfaceConfigurations": [ - { - "name": "nic", - "properties": { - "ipConfigurations": [ - { - "name": "nicipconfig", - "properties": { - "subnet": { - "id": "[variables('agentpri2VnetSubnetID')]" - } - } - } - ], - "primary": "true" - } - } - ] - }, - "osProfile": { - "adminUsername": "[variables('adminUsername')]", - "computerNamePrefix": "[variables('agentpri2VMNamePrefix')]", - "linuxConfiguration": { - "disablePasswordAuthentication": "true", - "ssh": { - "publicKeys": [ - { - "keyData": "[parameters('sshRSAPublicKey')]", - "path": "[variables('sshKeyPath')]" - } - ] - } - } - }, - "storageProfile": { - "osDisk": { - "caching": "ReadOnly", - "createOption": "FromImage" - } - } - } - }, - "sku": { - "capacity": "[variables('agentpri2Count')]", - "name": "[variables('agentpri2VMSize')]", - "tier": "[variables('agentpri2VMSizeTier')]" - }, - "tags": { - "creationSource": "[concat('acsengine-', variables('agentpri2VMNamePrefix'), '-vmss')]" - }, - "type": "Microsoft.Compute/virtualMachineScaleSets" - }, - { - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", - "location": "[variables('location')]", - "name": "[variables('masterAvailabilitySet')]", - "properties": { - "managed": "true", - "platformFaultDomainCount": 2, - "platformUpdateDomainCount": 3 - }, - "type": "Microsoft.Compute/availabilitySets" - }, - { - "apiVersion": "[variables('apiVersionStorage')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('masterStorageAccountExhibitorName')]", - "properties": { - "accountType": "Standard_LRS" - }, - "type": "Microsoft.Storage/storageAccounts" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[concat('Microsoft.Network/networkSecurityGroups/', variables('agentpriNSGName'))]", - "[concat('Microsoft.Network/networkSecurityGroups/', variables('agentpri2NSGName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('virtualNetworkName')]", - "properties": { - "addressSpace": { - "addressPrefixes": [ - "[variables('masterSubnet')]", - "[variables('agentpriSubnet')]", - "[variables('agentpri2Subnet')]" - ] - }, - "subnets": [ - { - "name": "[variables('masterSubnetName')]", - "properties": { - "addressPrefix": "[variables('masterSubnet')]" - } - }, - { - "name": "[variables('agentpriSubnetName')]", - "properties": { - "addressPrefix": "[variables('agentpriSubnet')]", - "networkSecurityGroup": { - "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('agentpriNSGName'))]" - } - } - }, - { - "name": "[variables('agentpri2SubnetName')]", - "properties": { - "addressPrefix": "[variables('agentpri2Subnet')]", - "networkSecurityGroup": { - "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('agentpri2NSGName'))]" - } - } - } - ] - }, - "type": "Microsoft.Network/virtualNetworks" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('masterPublicIPAddressName')]", - "properties": { - "dnsSettings": { - "domainNameLabel": "[variables('masterEndpointDNSNamePrefix')]" - }, - "publicIPAllocationMethod": "Dynamic" - }, - "type": "Microsoft.Network/publicIPAddresses" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('masterLbName')]", - "properties": { - "backendAddressPools": [ - { - "name": "[variables('masterLbBackendPoolName')]" - } - ], - "frontendIPConfigurations": [ - { - "name": "[variables('masterLbIPConfigName')]", - "properties": { - "publicIPAddress": { - "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('masterPublicIPAddressName'))]" - } - } - } - ] - }, - "type": "Microsoft.Network/loadBalancers" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "copy": { - "count": "[variables('masterCount')]", - "name": "masterLbLoopNode" - }, - "dependsOn": [ - "[variables('masterLbID')]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('masterLbName'), '/', 'SSH-', variables('masterVMNamePrefix'), copyIndex())]", - "properties": { - "backendPort": 22, - "enableFloatingIP": false, - "frontendIPConfiguration": { - "id": "[variables('masterLbIPConfigID')]" - }, - "frontendPort": "[copyIndex(2200)]", - "protocol": "tcp" - }, - "type": "Microsoft.Network/loadBalancers/inboundNatRules" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[variables('masterLbID')]" - ], - "location": "[resourceGroup().location]", - "name": "[concat(variables('masterLbName'), '/', 'SSHPort22-', variables('masterVMNamePrefix'), '0')]", - "properties": { - "backendPort": 2222, - "enableFloatingIP": false, - "frontendIPConfiguration": { - "id": "[variables('masterLbIPConfigID')]" - }, - "frontendPort": "22", - "protocol": "tcp" - }, - "type": "Microsoft.Network/loadBalancers/inboundNatRules" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('masterNSGName')]", - "properties": { - "securityRules": [ - { - "name": "sshPort22", - "properties": { - "access": "Allow", - "description": "Allow SSH", - "destinationAddressPrefix": "*", - "destinationPortRange": "2222", - "direction": "Inbound", - "priority": 201, - "protocol": "Tcp", - "sourceAddressPrefix": "*", - "sourcePortRange": "*" - } - }, - { - "name": "ssh", - "properties": { - "access": "Allow", - "description": "Allow SSH", - "destinationAddressPrefix": "*", - "destinationPortRange": "22", - "direction": "Inbound", - "priority": 200, - "protocol": "Tcp", - "sourceAddressPrefix": "*", - "sourcePortRange": "*" - } - } - ] - }, - "type": "Microsoft.Network/networkSecurityGroups" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "copy": { - "count": "[variables('masterCount')]", - "name": "nicLoopNode" - }, - "dependsOn": [ - "[variables('masterNSGID')]", - "[variables('vnetID')]", - "[variables('masterLbID')]", - "[concat(variables('masterLbID'),'/inboundNatRules/SSHPort22-',variables('masterVMNamePrefix'),0)]", - "[concat(variables('masterLbID'),'/inboundNatRules/SSH-',variables('masterVMNamePrefix'),copyIndex())]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('masterVMNamePrefix'), 'nic-', copyIndex())]", - "properties": { - "ipConfigurations": [ - { - "name": "ipConfigNode", - "properties": { - "loadBalancerBackendAddressPools": [ - { - "id": "[concat(variables('masterLbID'), '/backendAddressPools/', variables('masterLbBackendPoolName'))]" - } - ], - "loadBalancerInboundNatRules": "[variables('masterLbInboundNatRules')[copyIndex()]]", - "privateIPAddress": "[concat(variables('masterFirstAddrPrefix'), copyIndex(int(variables('masterFirstAddrOctet4'))))]", - "privateIPAllocationMethod": "Static", - "subnet": { - "id": "[variables('masterVnetSubnetID')]" - } - } - } - ], - "networkSecurityGroup": { - "id": "[variables('masterNSGID')]" - } - }, - "type": "Microsoft.Network/networkInterfaces" - }, - { - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", - "copy": { - "count": "[variables('masterCount')]", - "name": "vmLoopNode" - }, - "dependsOn": [ - "[concat('Microsoft.Network/networkInterfaces/', variables('masterVMNamePrefix'), 'nic-', copyIndex())]", - "[concat('Microsoft.Compute/availabilitySets/',variables('masterAvailabilitySet'))]", - "[variables('masterStorageAccountExhibitorName')]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('masterVMNamePrefix'), copyIndex())]", - "properties": { - "availabilitySet": { - "id": "[resourceId('Microsoft.Compute/availabilitySets',variables('masterAvailabilitySet'))]" - }, - "hardwareProfile": {}, - "networkProfile": { - "networkInterfaces": [ - { - "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(variables('masterVMNamePrefix'), 'nic-', copyIndex()))]" - } - ] - }, - "osProfile": { - "adminUsername": "[variables('adminUsername')]", - "computername": "[concat(variables('masterVMNamePrefix'), copyIndex())]", - "linuxConfiguration": { - "disablePasswordAuthentication": "true", - "ssh": { - "publicKeys": [ - { - "keyData": "[variables('sshRSAPublicKey')]", - "path": "[variables('sshKeyPath')]" - } - ] - } - } - }, - "storageProfile": { - "osDisk": { - "caching": "ReadWrite", - "createOption": "FromImage" - } - } - }, - "tags": { - "creationSource": "[concat('acsengine-', variables('masterVMNamePrefix'), copyIndex())]" - }, - "type": "Microsoft.Compute/virtualMachines" - } - ], - "outputs": { - "masterFQDN": { - "type": "string", - "value": "[reference(concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))).dnsSettings.fqdn]" - } - } -} \ No newline at end of file diff --git a/pkg/acsengine/transform/transformtestfiles/dcos_template.json b/pkg/acsengine/transform/transformtestfiles/dcos_template.json deleted file mode 100644 index f36b37bb56..0000000000 --- a/pkg/acsengine/transform/transformtestfiles/dcos_template.json +++ /dev/null @@ -1,1183 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "agentpri2Count": { - "allowedValues": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31, - 32, - 33, - 34, - 35, - 36, - 37, - 38, - 39, - 40, - 41, - 42, - 43, - 44, - 45, - 46, - 47, - 48, - 49, - 50, - 51, - 52, - 53, - 54, - 55, - 56, - 57, - 58, - 59, - 60, - 61, - 62, - 63, - 64, - 65, - 66, - 67, - 68, - 69, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, - 79, - 80, - 81, - 82, - 83, - 84, - 85, - 86, - 87, - 88, - 89, - 90, - 91, - 92, - 93, - 94, - 95, - 96, - 97, - 98, - 99, - 100 - ], - "defaultValue": 2, - "metadata": { - "description": "The number of agents for the cluster. This value can be from 1 to 100" - }, - "type": "int" - }, - "agentpri2Subnet": { - "defaultValue": "10.1.0.0/16", - "metadata": { - "description": "Sets the subnet of agent pool 'agentpri2'." - }, - "type": "string" - }, - "agentpri2VMSize": { - "allowedValues": [ - "Standard_A10", - "Standard_A11", - "Standard_A2", - "Standard_A2_v2", - "Standard_A2m_v2", - "Standard_A3", - "Standard_A4", - "Standard_A4_v2", - "Standard_A4m_v2", - "Standard_A5", - "Standard_A6", - "Standard_A7", - "Standard_A8", - "Standard_A8_v2", - "Standard_A8m_v2", - "Standard_A9", - "Standard_D11", - "Standard_D11_v2", - "Standard_D11_v2_Promo", - "Standard_D12", - "Standard_D12_v2", - "Standard_D12_v2_Promo", - "Standard_D13", - "Standard_D13_v2", - "Standard_D13_v2_Promo", - "Standard_D14", - "Standard_D14_v2", - "Standard_D14_v2_Promo", - "Standard_D15_v2", - "Standard_D2", - "Standard_D2_v2", - "Standard_D2_v2_Promo", - "Standard_D3", - "Standard_D3_v2", - "Standard_D3_v2_Promo", - "Standard_D4", - "Standard_D4_v2", - "Standard_D4_v2_Promo", - "Standard_D5_v2", - "Standard_D5_v2_Promo", - "Standard_DS11", - "Standard_DS11_v2", - "Standard_DS11_v2_Promo", - "Standard_DS12", - "Standard_DS12_v2", - "Standard_DS12_v2_Promo", - "Standard_DS13", - "Standard_DS13_v2", - "Standard_DS13_v2_Promo", - "Standard_DS14", - "Standard_DS14_v2", - "Standard_DS14_v2_Promo", - "Standard_DS15_v2", - "Standard_DS2", - "Standard_DS2_v2", - "Standard_DS2_v2_Promo", - "Standard_DS3", - "Standard_DS3_v2", - "Standard_DS3_v2_Promo", - "Standard_DS4", - "Standard_DS4_v2", - "Standard_DS4_v2_Promo", - "Standard_DS5_v2", - "Standard_DS5_v2_Promo", - "Standard_F16", - "Standard_F16s", - "Standard_F2", - "Standard_F2s", - "Standard_F4", - "Standard_F4s", - "Standard_F8", - "Standard_F8s", - "Standard_G1", - "Standard_G2", - "Standard_G3", - "Standard_G4", - "Standard_G5", - "Standard_GS1", - "Standard_GS2", - "Standard_GS3", - "Standard_GS4", - "Standard_GS5", - "Standard_H16", - "Standard_H16m", - "Standard_H16mr", - "Standard_H16r", - "Standard_H8", - "Standard_H8m", - "Standard_L16s", - "Standard_L32s", - "Standard_L4s", - "Standard_L8s", - "Standard_M128ms", - "Standard_M128s", - "Standard_M64ms", - "Standard_NC12", - "Standard_NC24", - "Standard_NC24r", - "Standard_NC6", - "Standard_NV12", - "Standard_NV24", - "Standard_NV6" - ], - "defaultValue": "Standard_D2_v2", - "metadata": { - "description": "The size of the Virtual Machine." - }, - "type": "string" - }, - "agentpriCount": { - "allowedValues": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31, - 32, - 33, - 34, - 35, - 36, - 37, - 38, - 39, - 40, - 41, - 42, - 43, - 44, - 45, - 46, - 47, - 48, - 49, - 50, - 51, - 52, - 53, - 54, - 55, - 56, - 57, - 58, - 59, - 60, - 61, - 62, - 63, - 64, - 65, - 66, - 67, - 68, - 69, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, - 79, - 80, - 81, - 82, - 83, - 84, - 85, - 86, - 87, - 88, - 89, - 90, - 91, - 92, - 93, - 94, - 95, - 96, - 97, - 98, - 99, - 100 - ], - "defaultValue": 2, - "metadata": { - "description": "The number of agents for the cluster. This value can be from 1 to 100" - }, - "type": "int" - }, - "agentpriSubnet": { - "defaultValue": "10.0.0.0/16", - "metadata": { - "description": "Sets the subnet of agent pool 'agentpri'." - }, - "type": "string" - }, - "agentpriVMSize": { - "allowedValues": [ - "Standard_A10", - "Standard_A11", - "Standard_A2", - "Standard_A2_v2", - "Standard_A2m_v2", - "Standard_A3", - "Standard_A4", - "Standard_A4_v2", - "Standard_A4m_v2", - "Standard_A5", - "Standard_A6", - "Standard_A7", - "Standard_A8", - "Standard_A8_v2", - "Standard_A8m_v2", - "Standard_A9", - "Standard_D11", - "Standard_D11_v2", - "Standard_D11_v2_Promo", - "Standard_D12", - "Standard_D12_v2", - "Standard_D12_v2_Promo", - "Standard_D13", - "Standard_D13_v2", - "Standard_D13_v2_Promo", - "Standard_D14", - "Standard_D14_v2", - "Standard_D14_v2_Promo", - "Standard_D15_v2", - "Standard_D2", - "Standard_D2_v2", - "Standard_D2_v2_Promo", - "Standard_D3", - "Standard_D3_v2", - "Standard_D3_v2_Promo", - "Standard_D4", - "Standard_D4_v2", - "Standard_D4_v2_Promo", - "Standard_D5_v2", - "Standard_D5_v2_Promo", - "Standard_DS11", - "Standard_DS11_v2", - "Standard_DS11_v2_Promo", - "Standard_DS12", - "Standard_DS12_v2", - "Standard_DS12_v2_Promo", - "Standard_DS13", - "Standard_DS13_v2", - "Standard_DS13_v2_Promo", - "Standard_DS14", - "Standard_DS14_v2", - "Standard_DS14_v2_Promo", - "Standard_DS15_v2", - "Standard_DS2", - "Standard_DS2_v2", - "Standard_DS2_v2_Promo", - "Standard_DS3", - "Standard_DS3_v2", - "Standard_DS3_v2_Promo", - "Standard_DS4", - "Standard_DS4_v2", - "Standard_DS4_v2_Promo", - "Standard_DS5_v2", - "Standard_DS5_v2_Promo", - "Standard_F16", - "Standard_F16s", - "Standard_F2", - "Standard_F2s", - "Standard_F4", - "Standard_F4s", - "Standard_F8", - "Standard_F8s", - "Standard_G1", - "Standard_G2", - "Standard_G3", - "Standard_G4", - "Standard_G5", - "Standard_GS1", - "Standard_GS2", - "Standard_GS3", - "Standard_GS4", - "Standard_GS5", - "Standard_H16", - "Standard_H16m", - "Standard_H16mr", - "Standard_H16r", - "Standard_H8", - "Standard_H8m", - "Standard_L16s", - "Standard_L32s", - "Standard_L4s", - "Standard_L8s", - "Standard_M128ms", - "Standard_M128s", - "Standard_M64ms", - "Standard_NC12", - "Standard_NC24", - "Standard_NC24r", - "Standard_NC6", - "Standard_NV12", - "Standard_NV24", - "Standard_NV6" - ], - "defaultValue": "Standard_D2_v2", - "metadata": { - "description": "The size of the Virtual Machine." - }, - "type": "string" - }, - "dcosBootstrapURL": { - "defaultValue": "https://dcosio.azureedge.net/dcos/stable/bootstrap/58fd0833ce81b6244fc73bf65b5deb43217b0bd7.bootstrap.tar.xz", - "metadata": { - "description": "The default mesosphere bootstrap package." - }, - "type": "string" - }, - "firstConsecutiveStaticIP": { - "defaultValue": "172.16.0.5", - "metadata": { - "description": "Sets the static IP of the first master" - }, - "type": "string" - }, - "linuxAdminUsername": { - "metadata": { - "description": "User name for the Linux Virtual Machines (SSH or Password)." - }, - "type": "string" - }, - "location": { - "defaultValue": "", - "metadata": { - "description": "Sets the location for all resources in the cluster" - }, - "type": "string" - }, - "masterEndpointDNSNamePrefix": { - "metadata": { - "description": "Sets the Domain name label for the master IP Address. The concatenation of the domain name label and the regional DNS zone make up the fully qualified domain name associated with the public IP address." - }, - "type": "string" - }, - "masterSubnet": { - "defaultValue": "172.16.0.0/24", - "metadata": { - "description": "Sets the subnet of the master node(s)." - }, - "type": "string" - }, - "masterVMSize": { - "allowedValues": [ - "Standard_A10", - "Standard_A11", - "Standard_A2", - "Standard_A3", - "Standard_A4", - "Standard_A5", - "Standard_A6", - "Standard_A7", - "Standard_A8", - "Standard_A9", - "Standard_D11", - "Standard_D11_v2", - "Standard_D11_v2_Promo", - "Standard_D12", - "Standard_D12_v2", - "Standard_D12_v2_Promo", - "Standard_D13", - "Standard_D13_v2", - "Standard_D13_v2_Promo", - "Standard_D14", - "Standard_D14_v2", - "Standard_D14_v2_Promo", - "Standard_D15_v2", - "Standard_D2", - "Standard_D2_v2", - "Standard_D2_v2_Promo", - "Standard_D3", - "Standard_D3_v2", - "Standard_D3_v2_Promo", - "Standard_D4", - "Standard_D4_v2", - "Standard_D4_v2_Promo", - "Standard_D5_v2", - "Standard_D5_v2_Promo", - "Standard_DS13", - "Standard_DS13_v2", - "Standard_DS13_v2_Promo", - "Standard_DS14", - "Standard_DS14_v2", - "Standard_DS14_v2_Promo", - "Standard_DS15_v2", - "Standard_DS5_v2", - "Standard_DS5_v2_Promo", - "Standard_F16", - "Standard_F8", - "Standard_G1", - "Standard_G2", - "Standard_G3", - "Standard_G4", - "Standard_G5", - "Standard_GS2", - "Standard_GS3", - "Standard_GS4", - "Standard_GS5", - "Standard_H16", - "Standard_H16m", - "Standard_H16mr", - "Standard_H16r", - "Standard_H8", - "Standard_H8m", - "Standard_L16s", - "Standard_L32s", - "Standard_L4s", - "Standard_L8s", - "Standard_M128ms", - "Standard_M128s", - "Standard_M64ms", - "Standard_NC12", - "Standard_NC24", - "Standard_NC24r", - "Standard_NC6", - "Standard_NV12", - "Standard_NV24", - "Standard_NV6" - ], - "metadata": { - "description": "The size of the Virtual Machine." - }, - "type": "string" - }, - "nameSuffix": { - "defaultValue": "25033075", - "metadata": { - "description": "A string hash of the master DNS name to uniquely identify the cluster." - }, - "type": "string" - }, - "sshRSAPublicKey": { - "metadata": { - "description": "SSH public key used for auth to all Linux machines. Not Required. If not set, you must provide a password key." - }, - "type": "string" - }, - "targetEnvironment": { - "defaultValue": "AzurePublicCloud", - "metadata": { - "description": "The azure deploy environment. Currently support: AzurePublicCloud, AzureChinaCloud" - }, - "type": "string" - } - }, - "variables": { - "adminUsername": "[parameters('linuxAdminUsername')]", - "agentpri2Count": "[parameters('agentpri2Count')]", - "agentpri2NSGID": "[resourceId('Microsoft.Network/networkSecurityGroups',variables('agentpri2NSGName'))]", - "agentpri2NSGName": "[concat(variables('orchestratorName'), '-agentpri2-nsg-', variables('nameSuffix'))]", - "agentpri2Subnet": "[parameters('agentpri2Subnet')]", - "agentpri2SubnetName": "[concat(variables('orchestratorName'), '-agentpri2Subnet')]", - "agentpri2VMNamePrefix": "[concat(variables('orchestratorName'), '-agentpri2-', variables('nameSuffix'))]", - "agentpri2VMSize": "[parameters('agentpri2VMSize')]", - "agentpri2VMSizeTier": "[split(parameters('agentpri2VMSize'),'_')[0]]", - "agentpri2VnetSubnetID": "[concat(variables('vnetID'),'/subnets/',variables('agentpri2SubnetName'))]", - "agentpriCount": "[parameters('agentpriCount')]", - "agentpriNSGID": "[resourceId('Microsoft.Network/networkSecurityGroups',variables('agentpriNSGName'))]", - "agentpriNSGName": "[concat(variables('orchestratorName'), '-agentpri-nsg-', variables('nameSuffix'))]", - "agentpriSubnet": "[parameters('agentpriSubnet')]", - "agentpriSubnetName": "[concat(variables('orchestratorName'), '-agentpriSubnet')]", - "agentpriVMNamePrefix": "[concat(variables('orchestratorName'), '-agentpri-', variables('nameSuffix'))]", - "agentpriVMSize": "[parameters('agentpriVMSize')]", - "agentpriVMSizeTier": "[split(parameters('agentpriVMSize'),'_')[0]]", - "agentpriVnetSubnetID": "[concat(variables('vnetID'),'/subnets/',variables('agentpriSubnetName'))]", - "apiVersionDefault": "2016-03-30", - "apiVersionStorage": "2015-06-15", - "apiVersionStorageManagedDisks": "2016-04-30-preview", - "dcosBootstrapURL": "[parameters('dcosBootstrapURL')]", - "location": "[variables('locations')[mod(add(2,length(parameters('location'))),add(1,length(parameters('location'))))]]", - "locations": [ - "[resourceGroup().location]", - "[parameters('location')]" - ], - "masterAvailabilitySet": "[concat(variables('orchestratorName'), '-master-availabilitySet-', variables('nameSuffix'))]", - "masterCount": 1, - "masterEndpointDNSNamePrefix": "[tolower(parameters('masterEndpointDNSNamePrefix'))]", - "masterFirstAddrOctet4": "[variables('masterFirstAddrOctets')[3]]", - "masterFirstAddrOctets": "[split(parameters('firstConsecutiveStaticIP'),'.')]", - "masterFirstAddrPrefix": "[concat(variables('masterFirstAddrOctets')[0],'.',variables('masterFirstAddrOctets')[1],'.',variables('masterFirstAddrOctets')[2],'.')]", - "masterHttpSourceAddressPrefix": "*", - "masterLbBackendPoolName": "[concat(variables('orchestratorName'), '-master-pool-', variables('nameSuffix'))]", - "masterLbID": "[resourceId('Microsoft.Network/loadBalancers',variables('masterLbName'))]", - "masterLbIPConfigID": "[concat(variables('masterLbID'),'/frontendIPConfigurations/', variables('masterLbIPConfigName'))]", - "masterLbIPConfigName": "[concat(variables('orchestratorName'), '-master-lbFrontEnd-', variables('nameSuffix'))]", - "masterLbInboundNatRules": [ - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'0')]" - }, - { - "id": "[concat(variables('masterSshPort22InboundNatRuleIdPrefix'),'0')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'1')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'2')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'3')]" - } - ], - [ - { - "id": "[concat(variables('masterSshInboundNatRuleIdPrefix'),'4')]" - } - ] - ], - "masterLbName": "[concat(variables('orchestratorName'), '-master-lb-', variables('nameSuffix'))]", - "masterNSGID": "[resourceId('Microsoft.Network/networkSecurityGroups',variables('masterNSGName'))]", - "masterNSGName": "[concat(variables('orchestratorName'), '-master-nsg-', variables('nameSuffix'))]", - "masterPublicIPAddressName": "[concat(variables('orchestratorName'), '-master-ip-', variables('masterEndpointDNSNamePrefix'), '-', variables('nameSuffix'))]", - "masterSshInboundNatRuleIdPrefix": "[concat(variables('masterLbID'),'/inboundNatRules/SSH-',variables('masterVMNamePrefix'))]", - "masterSshPort22InboundNatRuleIdPrefix": "[concat(variables('masterLbID'),'/inboundNatRules/SSHPort22-',variables('masterVMNamePrefix'))]", - "masterStorageAccountExhibitorName": "[concat(variables('storageAccountBaseName'), 'exhb0')]", - "masterSubnet": "[parameters('masterSubnet')]", - "masterSubnetName": "[concat(variables('orchestratorName'), '-masterSubnet')]", - "masterVMNamePrefix": "[concat(variables('orchestratorName'), '-master-', variables('nameSuffix'), '-')]", - "masterVMNic": [ - "[concat(variables('masterVMNamePrefix'), 'nic-0')]", - "[concat(variables('masterVMNamePrefix'), 'nic-1')]", - "[concat(variables('masterVMNamePrefix'), 'nic-2')]", - "[concat(variables('masterVMNamePrefix'), 'nic-3')]", - "[concat(variables('masterVMNamePrefix'), 'nic-4')]", - "[concat(variables('masterVMNamePrefix'), 'nic-5')]", - "[concat(variables('masterVMNamePrefix'), 'nic-6')]" - ], - "masterVMSize": "[parameters('masterVMSize')]", - "masterVnetSubnetID": "[concat(variables('vnetID'),'/subnets/',variables('masterSubnetName'))]", - "maxVMsPerPool": 100, - "nameSuffix": "[parameters('nameSuffix')]", - "oauthEnabled": "false", - "orchestratorName": "dcos", - "osImageOffer": "UbuntuServer", - "osImagePublisher": "Canonical", - "osImageSKU": "16.04-LTS", - "osImageVersion": "16.04.201708151", - "sshKeyPath": "[concat('/home/', variables('adminUsername'), '/.ssh/authorized_keys')]", - "sshRSAPublicKey": "[parameters('sshRSAPublicKey')]", - "storageAccountBaseName": "[uniqueString(concat(variables('masterEndpointDNSNamePrefix'),variables('location'),variables('orchestratorName')))]", - "storageAccountPrefixes": [], - "storageAccountType": "Standard_LRS", - "targetEnvironment": "[parameters('targetEnvironment')]", - "virtualNetworkName": "[concat(variables('orchestratorName'), '-vnet-', variables('nameSuffix'))]", - "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]" - }, - "resources": [ - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('agentpriNSGName')]", - "properties": { - "securityRules": [] - }, - "type": "Microsoft.Network/networkSecurityGroups" - }, - { - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", - "dependsOn": [ - "[variables('vnetID')]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('agentpriVMNamePrefix'), '-vmss')]", - "properties": { - "upgradePolicy": { - "mode": "Manual" - }, - "virtualMachineProfile": { - "networkProfile": { - "networkInterfaceConfigurations": [ - { - "name": "nic", - "properties": { - "ipConfigurations": [ - { - "name": "nicipconfig", - "properties": { - "subnet": { - "id": "[variables('agentpriVnetSubnetID')]" - } - } - } - ], - "primary": "true" - } - } - ] - }, - "osProfile": { - "adminUsername": "[variables('adminUsername')]", - "computerNamePrefix": "[variables('agentpriVMNamePrefix')]", - "customData": "[base64(concat('#cloud-config\n\n', '{\"bootcmd\":[\"bash -c \\\"if [ ! -f /var/lib/sdb-gpt ];then echo DCOS-5890;parted -s /dev/sdb mklabel gpt;touch /var/lib/sdb-gpt;fi\\\"\"],\"disk_setup\":{\"ephemeral0\":{\"layout\":[45,45,10],\"overwrite\":true,\"table_type\":\"gpt\"}},\"fs_setup\":[{\"device\":\"ephemeral0.1\",\"filesystem\":\"ext4\",\"overwrite\":true},{\"device\":\"ephemeral0.2\",\"filesystem\":\"ext4\",\"overwrite\":true},{\"device\":\"ephemeral0.3\",\"filesystem\":\"ext4\",\"overwrite\":true}],\"mounts\":[[\"ephemeral0.1\",\"/var/lib/mesos\"],[\"ephemeral0.2\",\"/var/lib/docker\"],[\"ephemeral0.3\",\"/var/tmp\"]],\"runcmd\":[\"/usr/lib/apt/apt.systemd.daily\",\"echo 2dd1ce17-079e-403c-b352-a1921ee207ee \\u003e /sys/bus/vmbus/drivers/hv_util/unbind\",\"sed -i \\\"13i\\\\echo 2dd1ce17-079e-403c-b352-a1921ee207ee \\u003e /sys/bus/vmbus/drivers/hv_util/unbind\\\\n\\\" /etc/rc.local\",[\"ln\",\"-s\",\"/bin/rm\",\"/usr/bin/rm\"],[\"ln\",\"-s\",\"/bin/mkdir\",\"/usr/bin/mkdir\"],[\"ln\",\"-s\",\"/bin/tar\",\"/usr/bin/tar\"],[\"ln\",\"-s\",\"/bin/ln\",\"/usr/bin/ln\"],[\"ln\",\"-s\",\"/bin/cp\",\"/usr/bin/cp\"],[\"ln\",\"-s\",\"/bin/systemctl\",\"/usr/bin/systemctl\"],[\"ln\",\"-s\",\"/bin/mount\",\"/usr/bin/mount\"],[\"ln\",\"-s\",\"/bin/bash\",\"/usr/bin/bash\"],[\"ln\",\"-s\",\"/usr/sbin/useradd\",\"/usr/bin/useradd\"],[\"systemctl\",\"disable\",\"--now\",\"resolvconf.service\"],[\"systemctl\",\"mask\",\"--now\",\"lxc-net.service\"],[\"systemctl\",\"disable\",\"--now\",\"unscd.service\"],[\"systemctl\",\"stop\",\"--now\",\"unscd.service\"],\"sed -i \\\"s/^Port 22$/Port 22\\\\nPort 2222/1\\\" /etc/ssh/sshd_config\",\"service ssh restart\",\"/opt/azure/containers/provision.sh\",[\"cp\",\"-p\",\"/etc/resolv.conf\",\"/tmp/resolv.conf\"],[\"rm\",\"-f\",\"/etc/resolv.conf\"],[\"cp\",\"-p\",\"/tmp/resolv.conf\",\"/etc/resolv.conf\"],[\"systemctl\",\"start\",\"dcos-docker-install.service\"],[\"systemctl\",\"start\",\"dcos-config-writer.service\"],[\"systemctl\",\"restart\",\"systemd-journald.service\"],[\"systemctl\",\"restart\",\"docker.service\"],[\"systemctl\",\"start\",\"dcos-link-env.service\"],[\"systemctl\",\"enable\",\"dcos-setup.service\"],[\"systemctl\",\"--no-block\",\"start\",\"dcos-setup.service\"],\"/opt/azure/containers/add_admin_to_docker_group.sh\"],\"write_files\":[{\"content\":\"https://dcosio.azureedge.net/dcos/stable\\n\",\"owner\":\"root\",\"path\":\"/etc/mesosphere/setup-flags/repository-url\",\"permissions\":\"0644\"},{\"content\":\"[\\\"3dt--7847ebb24bf6756c3103902971b34c3f09c3afbd\\\", \\\"adminrouter--0493a6fdaed08e1971871818e194aa4607df4f09\\\", \\\"avro-cpp--760c214063f6b038b522eaf4b768b905fed56ebc\\\", \\\"boost-libs--2015ccb58fb756f61c02ee6aa05cc1e27459a9ec\\\", \\\"bootstrap--59a905ecee27e71168ed44cefda4481fb76b816d\\\", \\\"boto--6344d31eef082c7bd13259b17034ea7b5c34aedf\\\", \\\"check-time--be7d0ba757ec87f9965378fee7c76a6ee5ae996d\\\", \\\"cni--e48337da39a8cd379414acfe0da52a9226a10d24\\\", \\\"cosmos--20decef90f0623ed253a12ec4cf5c148b18d8249\\\", \\\"curl--fc3486c43f98e63f9b12675f1356e8fe842f26b0\\\", \\\"dcos-config--setup_bcc883b7a3191412cf41824bdee06c1142187a0b\\\", \\\"dcos-history--77b0e97d7b25c8bedf8f7da0689cac65b83e3813\\\", \\\"dcos-image--bda6a02bcb2eb21c4218453a870cc584f921a800\\\", \\\"dcos-image-deps--83584fd868e5b470f7cf754424a9a75b328e9b68\\\", \\\"dcos-integration-test--c28bcb2347799dca43083f55e4c7b28503176f9c\\\", \\\"dcos-log--4d630df863228f38c6333e44670b4c4b20a74832\\\", \\\"dcos-metadata--setup_bcc883b7a3191412cf41824bdee06c1142187a0b\\\", \\\"dcos-metrics--23ee2f89c58b1258bc959f1d0dd7debcbb3d79d2\\\", \\\"dcos-oauth--0079529da183c0f23a06d2b069721b6fa6cc7b52\\\", \\\"dcos-signal--1bcd3b612cbdc379380dcba17cdf9a3b6652d9dc\\\", \\\"dcos-ui--d4afd695796404a5b35950c3daddcae322481ac4\\\", \\\"dnspython--0f833eb9a8abeba3179b43f3a200a8cd42d3795a\\\", \\\"docker-gc--59a98ed6446a084bf74e4ff4b8e3479f59ea8528\\\", \\\"dvdcli--5374dd4ffb519f1dcefdec89b2247e3404f2e2e3\\\", \\\"erlang--a9ee2530357a3301e53056b36a93420847b339a3\\\", \\\"exhibitor--72d9d8f947e5411eda524d40dde1a58edeb158ed\\\", \\\"flask--26d1bcdb2d1c3dcf1d2c03bc0d4f29c86d321b21\\\", \\\"java--cd5e921ce66b0d3303883c06d73a657314044304\\\", \\\"libevent--208be855d2be29c9271a7bd6c04723ff79946e02\\\", \\\"libffi--83ce3bd7eda2ef089e57efd2bc16c144d5a1f094\\\", \\\"libsodium--9ff915db08c6bba7d6738af5084e782b13c84bf8\\\", \\\"logrotate--7f7bc4416d3ad101d0c5218872858483b516be07\\\", \\\"marathon--bfb24f7f90cb3cd52a1cb22a07caafa5013bba21\\\", \\\"mesos--aaedd03eee0d57f5c0d49c74ff1e5721862cad98\\\", \\\"mesos-dns--0401501b2b5152d01bfa84ff6d007fdafe414b16\\\", \\\"mesos-modules--311849eaae42696b8a7eefe86b9ab3ebd9bd48f5\\\", \\\"metronome--467e4c64f804dbd4cd8572516e111a3f9298c10d\\\", \\\"navstar--1128db0234105a64fb4be52f4453cd6aa895ff30\\\", \\\"ncurses--d889894b71aa1a5b311bafef0e85479025b4dacb\\\", \\\"octarine--e86d3312691b12523280d56f6260216729aaa0ad\\\", \\\"openssl--b01a32a42e3ccba52b417276e9509a441e1d4a82\\\", \\\"pkgpanda-api--541feb8a8be58bdde8fecf1d2e5bfa0515f5a7d0\\\", \\\"pkgpanda-role--f8a749a4a821476ad2ef7e9dd9d12b6a8c4643a4\\\", \\\"pytest--78aee3e58a049cdab0d266af74f77d658b360b4f\\\", \\\"python--b7a144a49577a223d37d447c568f51330ee95390\\\", \\\"python-azure-mgmt-resource--03c05550f43b0e7a4455c33fe43b0deb755d87f0\\\", \\\"python-cryptography--4184767c68e48801dd394072cb370c610a05029d\\\", \\\"python-dateutil--fdc6ff929f65dd0918cf75a9ad56704683d31781\\\", \\\"python-docopt--beba78faa13e5bf4c52393b4b82d81f3c391aa65\\\", \\\"python-gunicorn--a537f95661fb2689c52fe12510eb0d01cb83af60\\\", \\\"python-isodate--40d378c688e6badfd16676dd8b51b742bfebc8d5\\\", \\\"python-jinja2--7450f5ae5a822f63f7a58c717207be0456df51ed\\\", \\\"python-kazoo--cb7ce13a1068cd82dd84ea0de32b529a760a4bdd\\\", \\\"python-markupsafe--dd46d2a3c58611656a235f96d4adc51b2a7a590e\\\", \\\"python-passlib--802ec3605c0b82428fedba60983b1bafaa036bb8\\\", \\\"python-pyyaml--81dd44cc4a24db7cefa7016c6586a131acf279c3\\\", \\\"python-requests--1b2cadbd3811cc0c2ee235ce927e13ea1d6af41d\\\", \\\"python-retrying--eb7b8bac133f50492b1e1349cbe77c3e38bd02c3\\\", \\\"python-tox--07244f8a939a10353634c952c6d88ec4a3c05736\\\", \\\"rexray--869621bb411c9f2a793ea42cdfeed489e1972aaa\\\", \\\"six--f06424b68523c4dfa2a7c3e7475d479f3d361e42\\\", \\\"spartan--9cc57a3d55452b905d90e3201f56913140914ecc\\\", \\\"strace--7d01796d64994451c1b2b82d161a335cbe90569b\\\", \\\"teamcity-messages--e623a4d86eb3a8d199cefcc240dd4c5460cb2962\\\", \\\"toybox--f235594ab8ea9a2864ee72abe86723d76f92e848\\\"]\\n\",\"owner\":\"root\",\"path\":\"/etc/mesosphere/setup-flags/cluster-packages.json\",\"permissions\":\"0644\"},{\"content\":\"[Journal]\\nMaxLevelConsole=warning\\nRateLimitInterval=1s\\nRateLimitBurst=20000\\n\",\"owner\":\"root\",\"path\":\"/etc/systemd/journald.conf.d/dcos.conf\",\"permissions\":\"0644\"},{\"content\":\"rexray:\\n loglevel: info\\n modules:\\n default-admin:\\n host: tcp://127.0.0.1:61003\\n default-docker:\\n disabled: true\\n\",\"path\":\"/etc/rexray/config.yml\",\"permissions\":\"0644\"},{\"content\":\"[Unit]\\nAfter=network-online.target\\nWants=network-online.target\\n[Service]\\nType=oneshot\\nEnvironment=DEBIAN_FRONTEND=noninteractive\\nStandardOutput=journal+console\\nStandardError=journal+console\\nExecStartPre=/usr/bin/curl -fLsSv --retry 20 -Y 100000 -y 60 -o /var/tmp/d.deb https://az837203.vo.msecnd.net/dcos-deps/docker-engine_1.13.1-0-ubuntu-xenial_amd64.deb\\nExecStart=/usr/bin/bash -c \\\"try=1;until dpkg -D3 -i /var/tmp/d.deb || ((try\\u003e9));do echo retry $((try++));sleep $((try*try));done;systemctl --now start docker;systemctl restart docker.socket\\\"\\n\",\"path\":\"/etc/systemd/system/dcos-docker-install.service\",\"permissions\":\"0644\"},{\"content\":\"[Service]\\nRestart=always\\nStartLimitInterval=0\\nRestartSec=15\\nLimitNOFILE=16384\\nExecStartPre=-/sbin/ip link del docker0\\nExecStart=\\nExecStart=/usr/bin/docker daemon -H fd:// --storage-driver=overlay\\n\",\"path\":\"/etc/systemd/system/docker.service.d/execstart.conf\",\"permissions\":\"0644\"},{\"content\":\"[Unit]\\nRequires=dcos-setup.service\\nAfter=dcos-setup.service\\n[Service]\\nType=oneshot\\nEnvironmentFile=/etc/environment\\nEnvironmentFile=/opt/mesosphere/environment\\nExecStart=/usr/bin/bash -c \\\"echo $(detect_ip) $(hostname) \\u003e /etc/hosts\\\"\\n\",\"path\":\"/etc/systemd/system/dcos-config-writer.service\",\"permissions\":\"0644\"},{\"content\":\"\\\"bound_values\\\":\\n \\\"adminrouter_auth_enabled\\\": |-\\n ',variables('oauthEnabled'),'\\n \\\"cluster_name\\\": |-\\n ',variables('masterPublicIPAddressName'),'\\n \\\"exhibitor_azure_account_key\\\": |-\\n ', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('masterStorageAccountExhibitorName')), '2015-06-15').key1, '\\n \\\"exhibitor_azure_account_name\\\": |-\\n ',variables('masterStorageAccountExhibitorName'),'\\n \\\"exhibitor_azure_prefix\\\": |-\\n ',variables('masterPublicIPAddressName'),'\\n \\\"master_list\\\": |-\\n [\\\"', reference(variables('masterVMNic')[0]).ipConfigurations[0].properties.privateIPAddress,'\\\"]\\n \\\"oauth_enabled\\\": |-\\n ',variables('oauthEnabled'),'\\n\\\"late_bound_package_id\\\": |-\\n dcos-provider-bcc883b7a3191412cf41824bdee06c1142187a0b-azure--setup\\n\",\"owner\":\"root\",\"path\":\"/etc/mesosphere/setup-flags/late-config.yaml\",\"permissions\":\"0644\"},{\"content\":\"[Unit]\\nBefore=dcos.target\\n[Service]\\nType=oneshot\\nStandardOutput=journal+console\\nStandardError=journal+console\\nExecStartPre=/usr/bin/mkdir -p /etc/profile.d\\nExecStart=/usr/bin/ln -sf /opt/mesosphere/bin/add_dcos_path.sh /etc/profile.d/dcos.sh\\n\",\"path\":\"/etc/systemd/system/dcos-link-env.service\",\"permissions\":\"0644\"},{\"content\":\"[Unit]\\nDescription=Pkgpanda: Download DC/OS to this host.\\nAfter=network-online.target\\nWants=network-online.target\\nConditionPathExists=!/opt/mesosphere/\\n[Service]\\nType=oneshot\\nStandardOutput=journal+console\\nStandardError=journal+console\\nExecStartPre=/usr/bin/curl --keepalive-time 2 -fLsSv --retry 20 -Y 100000 -y 60 -o //var/tmp/bootstrap.tar.xz ',variables('dcosBootstrapURL'),'\\nExecStartPre=/usr/bin/mkdir -p /opt/mesosphere\\nExecStart=/usr/bin/tar -axf //var/tmp/bootstrap.tar.xz -C /opt/mesosphere\\nExecStartPost=-/usr/bin/rm -f //var/tmp/bootstrap.tar.xz\\n\",\"path\":\"/etc/systemd/system/dcos-download.service\",\"permissions\":\"0644\"},{\"content\":\"[Unit]\\nDescription=Pkgpanda: Specialize DC/OS for this host.\\nRequires=dcos-download.service\\nAfter=dcos-download.service\\n[Service]\\nType=oneshot\\nStandardOutput=journal+console\\nStandardError=journal+console\\nEnvironmentFile=/opt/mesosphere/environment\\nExecStart=/opt/mesosphere/bin/pkgpanda setup --no-block-systemd\\n[Install]\\nWantedBy=multi-user.target\\n\",\"path\":\"/etc/systemd/system/dcos-setup.service\",\"permissions\":\"0644\"},{\"content\":\"\",\"path\":\"/etc/mesosphere/roles/azure\"},{\"content\":\"#!/bin/bash\\n\\n\\nMESOSDIR=/var/lib/mesos/dl\\nmkdir $MESOSDIR\\n\\n\\n# load the env vars\\n. /etc/mesosphere/setup-flags/dcos-deploy-environment\\n\\n\\n# default dc/os component download address (Azure CDN)\\nDOCKER_ENGINE_DOWNLOAD_URL=https://mesosphere.blob.core.windows.net/dcos-deps/docker-engine_1.13.1-0-ubuntu-xenial_amd64.deb\\nLIBIPSET_DOWNLOAD_URL=https://az837203.vo.msecnd.net/dcos-deps/libipset3_6.29-1_amd64.deb\\nIPSET_DOWNLOAD_URL=https://az837203.vo.msecnd.net/dcos-deps/ipset_6.29-1_amd64.deb\\nUNZIP_DOWNLOAD_URL=https://az837203.vo.msecnd.net/dcos-deps/unzip_6.0-20ubuntu1_amd64.deb\\nLIBLTDL_DOWNLOAD_URL=https://az837203.vo.msecnd.net/dcos-deps/libltdl7_2.4.6-0.1_amd64.deb\\n\\n\\ncase $DCOS_ENVIRONMENT in\\n# because of Chinese GreatWall Firewall, the default packages on Azure CDN is blocked. So the following Chinese local mirror url should be used instead.\\nAzureChinaCloud)\\nDOCKER_ENGINE_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/docker-engine_1.11.2-0~xenial_amd64.deb\\nLIBIPSET_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/libipset3_6.29-1_amd64.deb\\nIPSET_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/ipset_6.29-1_amd64.deb\\nUNZIP_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/unzip_6.0-20ubuntu1_amd64.deb\\nLIBLTDL_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/libltdl7_2.4.6-0.1_amd64.deb\\n;;\\nesac\\n\\n\\ncurl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/d.deb $DOCKER_ENGINE_DOWNLOAD_URL \\u0026\\ncurl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/1.deb $LIBIPSET_DOWNLOAD_URL \\u0026\\ncurl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/2.deb $IPSET_DOWNLOAD_URL \\u0026\\ncurl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/3.deb $UNZIP_DOWNLOAD_URL \\u0026\\ncurl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/4.deb $LIBLTDL_DOWNLOAD_URL \\u0026\\nwait\\n\\n\\nfor i in {1..300}; do\\ndpkg -i $MESOSDIR/{1,2,3,4}.deb\\nif [ \\\"$?\\\" = \\\"0\\\" ]\\nthen\\necho \\\"succeeded\\\"\\nbreak\\nfi\\nsleep 1\\ndone\\n\\n\\ntouch /etc/mesosphere/roles/slave\\n\",\"owner\":\"root\",\"path\":\"/opt/azure/containers/provision.sh\",\"permissions\":\"0744\"},{\"content\":\"\",\"owner\":\"root\",\"path\":\"/var/lib/dcos/mesos-slave-common\",\"permissions\":\"0644\"},{\"content\":\"#!/bin/bash\\nadduser ',variables('adminUsername'),' docker\\n\",\"owner\":\"root\",\"path\":\"/opt/azure/containers/add_admin_to_docker_group.sh\",\"permissions\":\"0744\"}]}'))]", - "linuxConfiguration": { - "disablePasswordAuthentication": "true", - "ssh": { - "publicKeys": [ - { - "keyData": "[parameters('sshRSAPublicKey')]", - "path": "[variables('sshKeyPath')]" - } - ] - } - } - }, - "storageProfile": { - "imageReference": { - "offer": "[variables('osImageOffer')]", - "publisher": "[variables('osImagePublisher')]", - "sku": "[variables('osImageSKU')]", - "version": "[variables('osImageVersion')]" - }, - "osDisk": { - "caching": "ReadOnly", - "createOption": "FromImage" - } - } - } - }, - "sku": { - "capacity": "[variables('agentpriCount')]", - "name": "[variables('agentpriVMSize')]", - "tier": "[variables('agentpriVMSizeTier')]" - }, - "tags": { - "creationSource": "[concat('acsengine-', variables('agentpriVMNamePrefix'), '-vmss')]" - }, - "type": "Microsoft.Compute/virtualMachineScaleSets" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('agentpri2NSGName')]", - "properties": { - "securityRules": [] - }, - "type": "Microsoft.Network/networkSecurityGroups" - }, - { - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", - "dependsOn": [ - "[variables('vnetID')]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('agentpri2VMNamePrefix'), '-vmss')]", - "properties": { - "upgradePolicy": { - "mode": "Manual" - }, - "virtualMachineProfile": { - "networkProfile": { - "networkInterfaceConfigurations": [ - { - "name": "nic", - "properties": { - "ipConfigurations": [ - { - "name": "nicipconfig", - "properties": { - "subnet": { - "id": "[variables('agentpri2VnetSubnetID')]" - } - } - } - ], - "primary": "true" - } - } - ] - }, - "osProfile": { - "adminUsername": "[variables('adminUsername')]", - "computerNamePrefix": "[variables('agentpri2VMNamePrefix')]", - "customData": "[base64(concat('#cloud-config\n\n', '{\"bootcmd\":[\"bash -c \\\"if [ ! -f /var/lib/sdb-gpt ];then echo DCOS-5890;parted -s /dev/sdb mklabel gpt;touch /var/lib/sdb-gpt;fi\\\"\"],\"disk_setup\":{\"ephemeral0\":{\"layout\":[45,45,10],\"overwrite\":true,\"table_type\":\"gpt\"}},\"fs_setup\":[{\"device\":\"ephemeral0.1\",\"filesystem\":\"ext4\",\"overwrite\":true},{\"device\":\"ephemeral0.2\",\"filesystem\":\"ext4\",\"overwrite\":true},{\"device\":\"ephemeral0.3\",\"filesystem\":\"ext4\",\"overwrite\":true}],\"mounts\":[[\"ephemeral0.1\",\"/var/lib/mesos\"],[\"ephemeral0.2\",\"/var/lib/docker\"],[\"ephemeral0.3\",\"/var/tmp\"]],\"runcmd\":[\"/usr/lib/apt/apt.systemd.daily\",\"echo 2dd1ce17-079e-403c-b352-a1921ee207ee \\u003e /sys/bus/vmbus/drivers/hv_util/unbind\",\"sed -i \\\"13i\\\\echo 2dd1ce17-079e-403c-b352-a1921ee207ee \\u003e /sys/bus/vmbus/drivers/hv_util/unbind\\\\n\\\" /etc/rc.local\",[\"ln\",\"-s\",\"/bin/rm\",\"/usr/bin/rm\"],[\"ln\",\"-s\",\"/bin/mkdir\",\"/usr/bin/mkdir\"],[\"ln\",\"-s\",\"/bin/tar\",\"/usr/bin/tar\"],[\"ln\",\"-s\",\"/bin/ln\",\"/usr/bin/ln\"],[\"ln\",\"-s\",\"/bin/cp\",\"/usr/bin/cp\"],[\"ln\",\"-s\",\"/bin/systemctl\",\"/usr/bin/systemctl\"],[\"ln\",\"-s\",\"/bin/mount\",\"/usr/bin/mount\"],[\"ln\",\"-s\",\"/bin/bash\",\"/usr/bin/bash\"],[\"ln\",\"-s\",\"/usr/sbin/useradd\",\"/usr/bin/useradd\"],[\"systemctl\",\"disable\",\"--now\",\"resolvconf.service\"],[\"systemctl\",\"mask\",\"--now\",\"lxc-net.service\"],[\"systemctl\",\"disable\",\"--now\",\"unscd.service\"],[\"systemctl\",\"stop\",\"--now\",\"unscd.service\"],\"sed -i \\\"s/^Port 22$/Port 22\\\\nPort 2222/1\\\" /etc/ssh/sshd_config\",\"service ssh restart\",\"/opt/azure/containers/provision.sh\",[\"cp\",\"-p\",\"/etc/resolv.conf\",\"/tmp/resolv.conf\"],[\"rm\",\"-f\",\"/etc/resolv.conf\"],[\"cp\",\"-p\",\"/tmp/resolv.conf\",\"/etc/resolv.conf\"],[\"systemctl\",\"start\",\"dcos-docker-install.service\"],[\"systemctl\",\"start\",\"dcos-config-writer.service\"],[\"systemctl\",\"restart\",\"systemd-journald.service\"],[\"systemctl\",\"restart\",\"docker.service\"],[\"systemctl\",\"start\",\"dcos-link-env.service\"],[\"systemctl\",\"enable\",\"dcos-setup.service\"],[\"systemctl\",\"--no-block\",\"start\",\"dcos-setup.service\"],\"/opt/azure/containers/add_admin_to_docker_group.sh\"],\"write_files\":[{\"content\":\"https://dcosio.azureedge.net/dcos/stable\\n\",\"owner\":\"root\",\"path\":\"/etc/mesosphere/setup-flags/repository-url\",\"permissions\":\"0644\"},{\"content\":\"[\\\"3dt--7847ebb24bf6756c3103902971b34c3f09c3afbd\\\", \\\"adminrouter--0493a6fdaed08e1971871818e194aa4607df4f09\\\", \\\"avro-cpp--760c214063f6b038b522eaf4b768b905fed56ebc\\\", \\\"boost-libs--2015ccb58fb756f61c02ee6aa05cc1e27459a9ec\\\", \\\"bootstrap--59a905ecee27e71168ed44cefda4481fb76b816d\\\", \\\"boto--6344d31eef082c7bd13259b17034ea7b5c34aedf\\\", \\\"check-time--be7d0ba757ec87f9965378fee7c76a6ee5ae996d\\\", \\\"cni--e48337da39a8cd379414acfe0da52a9226a10d24\\\", \\\"cosmos--20decef90f0623ed253a12ec4cf5c148b18d8249\\\", \\\"curl--fc3486c43f98e63f9b12675f1356e8fe842f26b0\\\", \\\"dcos-config--setup_bcc883b7a3191412cf41824bdee06c1142187a0b\\\", \\\"dcos-history--77b0e97d7b25c8bedf8f7da0689cac65b83e3813\\\", \\\"dcos-image--bda6a02bcb2eb21c4218453a870cc584f921a800\\\", \\\"dcos-image-deps--83584fd868e5b470f7cf754424a9a75b328e9b68\\\", \\\"dcos-integration-test--c28bcb2347799dca43083f55e4c7b28503176f9c\\\", \\\"dcos-log--4d630df863228f38c6333e44670b4c4b20a74832\\\", \\\"dcos-metadata--setup_bcc883b7a3191412cf41824bdee06c1142187a0b\\\", \\\"dcos-metrics--23ee2f89c58b1258bc959f1d0dd7debcbb3d79d2\\\", \\\"dcos-oauth--0079529da183c0f23a06d2b069721b6fa6cc7b52\\\", \\\"dcos-signal--1bcd3b612cbdc379380dcba17cdf9a3b6652d9dc\\\", \\\"dcos-ui--d4afd695796404a5b35950c3daddcae322481ac4\\\", \\\"dnspython--0f833eb9a8abeba3179b43f3a200a8cd42d3795a\\\", \\\"docker-gc--59a98ed6446a084bf74e4ff4b8e3479f59ea8528\\\", \\\"dvdcli--5374dd4ffb519f1dcefdec89b2247e3404f2e2e3\\\", \\\"erlang--a9ee2530357a3301e53056b36a93420847b339a3\\\", \\\"exhibitor--72d9d8f947e5411eda524d40dde1a58edeb158ed\\\", \\\"flask--26d1bcdb2d1c3dcf1d2c03bc0d4f29c86d321b21\\\", \\\"java--cd5e921ce66b0d3303883c06d73a657314044304\\\", \\\"libevent--208be855d2be29c9271a7bd6c04723ff79946e02\\\", \\\"libffi--83ce3bd7eda2ef089e57efd2bc16c144d5a1f094\\\", \\\"libsodium--9ff915db08c6bba7d6738af5084e782b13c84bf8\\\", \\\"logrotate--7f7bc4416d3ad101d0c5218872858483b516be07\\\", \\\"marathon--bfb24f7f90cb3cd52a1cb22a07caafa5013bba21\\\", \\\"mesos--aaedd03eee0d57f5c0d49c74ff1e5721862cad98\\\", \\\"mesos-dns--0401501b2b5152d01bfa84ff6d007fdafe414b16\\\", \\\"mesos-modules--311849eaae42696b8a7eefe86b9ab3ebd9bd48f5\\\", \\\"metronome--467e4c64f804dbd4cd8572516e111a3f9298c10d\\\", \\\"navstar--1128db0234105a64fb4be52f4453cd6aa895ff30\\\", \\\"ncurses--d889894b71aa1a5b311bafef0e85479025b4dacb\\\", \\\"octarine--e86d3312691b12523280d56f6260216729aaa0ad\\\", \\\"openssl--b01a32a42e3ccba52b417276e9509a441e1d4a82\\\", \\\"pkgpanda-api--541feb8a8be58bdde8fecf1d2e5bfa0515f5a7d0\\\", \\\"pkgpanda-role--f8a749a4a821476ad2ef7e9dd9d12b6a8c4643a4\\\", \\\"pytest--78aee3e58a049cdab0d266af74f77d658b360b4f\\\", \\\"python--b7a144a49577a223d37d447c568f51330ee95390\\\", \\\"python-azure-mgmt-resource--03c05550f43b0e7a4455c33fe43b0deb755d87f0\\\", \\\"python-cryptography--4184767c68e48801dd394072cb370c610a05029d\\\", \\\"python-dateutil--fdc6ff929f65dd0918cf75a9ad56704683d31781\\\", \\\"python-docopt--beba78faa13e5bf4c52393b4b82d81f3c391aa65\\\", \\\"python-gunicorn--a537f95661fb2689c52fe12510eb0d01cb83af60\\\", \\\"python-isodate--40d378c688e6badfd16676dd8b51b742bfebc8d5\\\", \\\"python-jinja2--7450f5ae5a822f63f7a58c717207be0456df51ed\\\", \\\"python-kazoo--cb7ce13a1068cd82dd84ea0de32b529a760a4bdd\\\", \\\"python-markupsafe--dd46d2a3c58611656a235f96d4adc51b2a7a590e\\\", \\\"python-passlib--802ec3605c0b82428fedba60983b1bafaa036bb8\\\", \\\"python-pyyaml--81dd44cc4a24db7cefa7016c6586a131acf279c3\\\", \\\"python-requests--1b2cadbd3811cc0c2ee235ce927e13ea1d6af41d\\\", \\\"python-retrying--eb7b8bac133f50492b1e1349cbe77c3e38bd02c3\\\", \\\"python-tox--07244f8a939a10353634c952c6d88ec4a3c05736\\\", \\\"rexray--869621bb411c9f2a793ea42cdfeed489e1972aaa\\\", \\\"six--f06424b68523c4dfa2a7c3e7475d479f3d361e42\\\", \\\"spartan--9cc57a3d55452b905d90e3201f56913140914ecc\\\", \\\"strace--7d01796d64994451c1b2b82d161a335cbe90569b\\\", \\\"teamcity-messages--e623a4d86eb3a8d199cefcc240dd4c5460cb2962\\\", \\\"toybox--f235594ab8ea9a2864ee72abe86723d76f92e848\\\"]\\n\",\"owner\":\"root\",\"path\":\"/etc/mesosphere/setup-flags/cluster-packages.json\",\"permissions\":\"0644\"},{\"content\":\"[Journal]\\nMaxLevelConsole=warning\\nRateLimitInterval=1s\\nRateLimitBurst=20000\\n\",\"owner\":\"root\",\"path\":\"/etc/systemd/journald.conf.d/dcos.conf\",\"permissions\":\"0644\"},{\"content\":\"rexray:\\n loglevel: info\\n modules:\\n default-admin:\\n host: tcp://127.0.0.1:61003\\n default-docker:\\n disabled: true\\n\",\"path\":\"/etc/rexray/config.yml\",\"permissions\":\"0644\"},{\"content\":\"[Unit]\\nAfter=network-online.target\\nWants=network-online.target\\n[Service]\\nType=oneshot\\nEnvironment=DEBIAN_FRONTEND=noninteractive\\nStandardOutput=journal+console\\nStandardError=journal+console\\nExecStartPre=/usr/bin/curl -fLsSv --retry 20 -Y 100000 -y 60 -o /var/tmp/d.deb https://az837203.vo.msecnd.net/dcos-deps/docker-engine_1.13.1-0-ubuntu-xenial_amd64.deb\\nExecStart=/usr/bin/bash -c \\\"try=1;until dpkg -D3 -i /var/tmp/d.deb || ((try\\u003e9));do echo retry $((try++));sleep $((try*try));done;systemctl --now start docker;systemctl restart docker.socket\\\"\\n\",\"path\":\"/etc/systemd/system/dcos-docker-install.service\",\"permissions\":\"0644\"},{\"content\":\"[Service]\\nRestart=always\\nStartLimitInterval=0\\nRestartSec=15\\nLimitNOFILE=16384\\nExecStartPre=-/sbin/ip link del docker0\\nExecStart=\\nExecStart=/usr/bin/docker daemon -H fd:// --storage-driver=overlay\\n\",\"path\":\"/etc/systemd/system/docker.service.d/execstart.conf\",\"permissions\":\"0644\"},{\"content\":\"[Unit]\\nRequires=dcos-setup.service\\nAfter=dcos-setup.service\\n[Service]\\nType=oneshot\\nEnvironmentFile=/etc/environment\\nEnvironmentFile=/opt/mesosphere/environment\\nExecStart=/usr/bin/bash -c \\\"echo $(detect_ip) $(hostname) \\u003e /etc/hosts\\\"\\n\",\"path\":\"/etc/systemd/system/dcos-config-writer.service\",\"permissions\":\"0644\"},{\"content\":\"\\\"bound_values\\\":\\n \\\"adminrouter_auth_enabled\\\": |-\\n ',variables('oauthEnabled'),'\\n \\\"cluster_name\\\": |-\\n ',variables('masterPublicIPAddressName'),'\\n \\\"exhibitor_azure_account_key\\\": |-\\n ', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('masterStorageAccountExhibitorName')), '2015-06-15').key1, '\\n \\\"exhibitor_azure_account_name\\\": |-\\n ',variables('masterStorageAccountExhibitorName'),'\\n \\\"exhibitor_azure_prefix\\\": |-\\n ',variables('masterPublicIPAddressName'),'\\n \\\"master_list\\\": |-\\n [\\\"', reference(variables('masterVMNic')[0]).ipConfigurations[0].properties.privateIPAddress,'\\\"]\\n \\\"oauth_enabled\\\": |-\\n ',variables('oauthEnabled'),'\\n\\\"late_bound_package_id\\\": |-\\n dcos-provider-bcc883b7a3191412cf41824bdee06c1142187a0b-azure--setup\\n\",\"owner\":\"root\",\"path\":\"/etc/mesosphere/setup-flags/late-config.yaml\",\"permissions\":\"0644\"},{\"content\":\"[Unit]\\nBefore=dcos.target\\n[Service]\\nType=oneshot\\nStandardOutput=journal+console\\nStandardError=journal+console\\nExecStartPre=/usr/bin/mkdir -p /etc/profile.d\\nExecStart=/usr/bin/ln -sf /opt/mesosphere/bin/add_dcos_path.sh /etc/profile.d/dcos.sh\\n\",\"path\":\"/etc/systemd/system/dcos-link-env.service\",\"permissions\":\"0644\"},{\"content\":\"[Unit]\\nDescription=Pkgpanda: Download DC/OS to this host.\\nAfter=network-online.target\\nWants=network-online.target\\nConditionPathExists=!/opt/mesosphere/\\n[Service]\\nType=oneshot\\nStandardOutput=journal+console\\nStandardError=journal+console\\nExecStartPre=/usr/bin/curl --keepalive-time 2 -fLsSv --retry 20 -Y 100000 -y 60 -o //var/tmp/bootstrap.tar.xz ',variables('dcosBootstrapURL'),'\\nExecStartPre=/usr/bin/mkdir -p /opt/mesosphere\\nExecStart=/usr/bin/tar -axf //var/tmp/bootstrap.tar.xz -C /opt/mesosphere\\nExecStartPost=-/usr/bin/rm -f //var/tmp/bootstrap.tar.xz\\n\",\"path\":\"/etc/systemd/system/dcos-download.service\",\"permissions\":\"0644\"},{\"content\":\"[Unit]\\nDescription=Pkgpanda: Specialize DC/OS for this host.\\nRequires=dcos-download.service\\nAfter=dcos-download.service\\n[Service]\\nType=oneshot\\nStandardOutput=journal+console\\nStandardError=journal+console\\nEnvironmentFile=/opt/mesosphere/environment\\nExecStart=/opt/mesosphere/bin/pkgpanda setup --no-block-systemd\\n[Install]\\nWantedBy=multi-user.target\\n\",\"path\":\"/etc/systemd/system/dcos-setup.service\",\"permissions\":\"0644\"},{\"content\":\"\",\"path\":\"/etc/mesosphere/roles/azure\"},{\"content\":\"#!/bin/bash\\n\\n\\nMESOSDIR=/var/lib/mesos/dl\\nmkdir $MESOSDIR\\n\\n\\n# load the env vars\\n. /etc/mesosphere/setup-flags/dcos-deploy-environment\\n\\n\\n# default dc/os component download address (Azure CDN)\\nDOCKER_ENGINE_DOWNLOAD_URL=https://mesosphere.blob.core.windows.net/dcos-deps/docker-engine_1.13.1-0-ubuntu-xenial_amd64.deb\\nLIBIPSET_DOWNLOAD_URL=https://az837203.vo.msecnd.net/dcos-deps/libipset3_6.29-1_amd64.deb\\nIPSET_DOWNLOAD_URL=https://az837203.vo.msecnd.net/dcos-deps/ipset_6.29-1_amd64.deb\\nUNZIP_DOWNLOAD_URL=https://az837203.vo.msecnd.net/dcos-deps/unzip_6.0-20ubuntu1_amd64.deb\\nLIBLTDL_DOWNLOAD_URL=https://az837203.vo.msecnd.net/dcos-deps/libltdl7_2.4.6-0.1_amd64.deb\\n\\n\\ncase $DCOS_ENVIRONMENT in\\n# because of Chinese GreatWall Firewall, the default packages on Azure CDN is blocked. So the following Chinese local mirror url should be used instead.\\nAzureChinaCloud)\\nDOCKER_ENGINE_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/docker-engine_1.11.2-0~xenial_amd64.deb\\nLIBIPSET_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/libipset3_6.29-1_amd64.deb\\nIPSET_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/ipset_6.29-1_amd64.deb\\nUNZIP_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/unzip_6.0-20ubuntu1_amd64.deb\\nLIBLTDL_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/libltdl7_2.4.6-0.1_amd64.deb\\n;;\\nesac\\n\\n\\ncurl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/d.deb $DOCKER_ENGINE_DOWNLOAD_URL \\u0026\\ncurl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/1.deb $LIBIPSET_DOWNLOAD_URL \\u0026\\ncurl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/2.deb $IPSET_DOWNLOAD_URL \\u0026\\ncurl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/3.deb $UNZIP_DOWNLOAD_URL \\u0026\\ncurl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/4.deb $LIBLTDL_DOWNLOAD_URL \\u0026\\nwait\\n\\n\\nfor i in {1..300}; do\\ndpkg -i $MESOSDIR/{1,2,3,4}.deb\\nif [ \\\"$?\\\" = \\\"0\\\" ]\\nthen\\necho \\\"succeeded\\\"\\nbreak\\nfi\\nsleep 1\\ndone\\n\\n\\ntouch /etc/mesosphere/roles/slave\\n\",\"owner\":\"root\",\"path\":\"/opt/azure/containers/provision.sh\",\"permissions\":\"0744\"},{\"content\":\"\",\"owner\":\"root\",\"path\":\"/var/lib/dcos/mesos-slave-common\",\"permissions\":\"0644\"},{\"content\":\"#!/bin/bash\\nadduser ',variables('adminUsername'),' docker\\n\",\"owner\":\"root\",\"path\":\"/opt/azure/containers/add_admin_to_docker_group.sh\",\"permissions\":\"0744\"}]}'))]", - "linuxConfiguration": { - "disablePasswordAuthentication": "true", - "ssh": { - "publicKeys": [ - { - "keyData": "[parameters('sshRSAPublicKey')]", - "path": "[variables('sshKeyPath')]" - } - ] - } - } - }, - "storageProfile": { - "imageReference": { - "offer": "[variables('osImageOffer')]", - "publisher": "[variables('osImagePublisher')]", - "sku": "[variables('osImageSKU')]", - "version": "[variables('osImageVersion')]" - }, - "osDisk": { - "caching": "ReadOnly", - "createOption": "FromImage" - } - } - } - }, - "sku": { - "capacity": "[variables('agentpri2Count')]", - "name": "[variables('agentpri2VMSize')]", - "tier": "[variables('agentpri2VMSizeTier')]" - }, - "tags": { - "creationSource": "[concat('acsengine-', variables('agentpri2VMNamePrefix'), '-vmss')]" - }, - "type": "Microsoft.Compute/virtualMachineScaleSets" - }, - { - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", - "location": "[variables('location')]", - "name": "[variables('masterAvailabilitySet')]", - "properties": { - "managed": "true", - "platformFaultDomainCount": 2, - "platformUpdateDomainCount": 3 - }, - "type": "Microsoft.Compute/availabilitySets" - }, - { - "apiVersion": "[variables('apiVersionStorage')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('masterStorageAccountExhibitorName')]", - "properties": { - "accountType": "Standard_LRS" - }, - "type": "Microsoft.Storage/storageAccounts" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[concat('Microsoft.Network/networkSecurityGroups/', variables('agentpriNSGName'))]", - "[concat('Microsoft.Network/networkSecurityGroups/', variables('agentpri2NSGName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('virtualNetworkName')]", - "properties": { - "addressSpace": { - "addressPrefixes": [ - "[variables('masterSubnet')]", - "[variables('agentpriSubnet')]", - "[variables('agentpri2Subnet')]" - ] - }, - "subnets": [ - { - "name": "[variables('masterSubnetName')]", - "properties": { - "addressPrefix": "[variables('masterSubnet')]" - } - }, - { - "name": "[variables('agentpriSubnetName')]", - "properties": { - "addressPrefix": "[variables('agentpriSubnet')]", - "networkSecurityGroup": { - "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('agentpriNSGName'))]" - } - } - }, - { - "name": "[variables('agentpri2SubnetName')]", - "properties": { - "addressPrefix": "[variables('agentpri2Subnet')]", - "networkSecurityGroup": { - "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('agentpri2NSGName'))]" - } - } - } - ] - }, - "type": "Microsoft.Network/virtualNetworks" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('masterPublicIPAddressName')]", - "properties": { - "dnsSettings": { - "domainNameLabel": "[variables('masterEndpointDNSNamePrefix')]" - }, - "publicIPAllocationMethod": "Dynamic" - }, - "type": "Microsoft.Network/publicIPAddresses" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))]" - ], - "location": "[variables('location')]", - "name": "[variables('masterLbName')]", - "properties": { - "backendAddressPools": [ - { - "name": "[variables('masterLbBackendPoolName')]" - } - ], - "frontendIPConfigurations": [ - { - "name": "[variables('masterLbIPConfigName')]", - "properties": { - "publicIPAddress": { - "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('masterPublicIPAddressName'))]" - } - } - } - ] - }, - "type": "Microsoft.Network/loadBalancers" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "copy": { - "count": "[variables('masterCount')]", - "name": "masterLbLoopNode" - }, - "dependsOn": [ - "[variables('masterLbID')]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('masterLbName'), '/', 'SSH-', variables('masterVMNamePrefix'), copyIndex())]", - "properties": { - "backendPort": 22, - "enableFloatingIP": false, - "frontendIPConfiguration": { - "id": "[variables('masterLbIPConfigID')]" - }, - "frontendPort": "[copyIndex(2200)]", - "protocol": "tcp" - }, - "type": "Microsoft.Network/loadBalancers/inboundNatRules" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[variables('masterLbID')]" - ], - "location": "[resourceGroup().location]", - "name": "[concat(variables('masterLbName'), '/', 'SSHPort22-', variables('masterVMNamePrefix'), '0')]", - "properties": { - "backendPort": 2222, - "enableFloatingIP": false, - "frontendIPConfiguration": { - "id": "[variables('masterLbIPConfigID')]" - }, - "frontendPort": "22", - "protocol": "tcp" - }, - "type": "Microsoft.Network/loadBalancers/inboundNatRules" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "location": "[variables('location')]", - "name": "[variables('masterNSGName')]", - "properties": { - "securityRules": [ - { - "name": "sshPort22", - "properties": { - "access": "Allow", - "description": "Allow SSH", - "destinationAddressPrefix": "*", - "destinationPortRange": "2222", - "direction": "Inbound", - "priority": 201, - "protocol": "Tcp", - "sourceAddressPrefix": "*", - "sourcePortRange": "*" - } - }, - { - "name": "ssh", - "properties": { - "access": "Allow", - "description": "Allow SSH", - "destinationAddressPrefix": "*", - "destinationPortRange": "22", - "direction": "Inbound", - "priority": 200, - "protocol": "Tcp", - "sourceAddressPrefix": "*", - "sourcePortRange": "*" - } - } - ] - }, - "type": "Microsoft.Network/networkSecurityGroups" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "copy": { - "count": "[variables('masterCount')]", - "name": "nicLoopNode" - }, - "dependsOn": [ - "[variables('masterNSGID')]", - "[variables('vnetID')]", - "[variables('masterLbID')]", - "[concat(variables('masterLbID'),'/inboundNatRules/SSHPort22-',variables('masterVMNamePrefix'),0)]", - "[concat(variables('masterLbID'),'/inboundNatRules/SSH-',variables('masterVMNamePrefix'),copyIndex())]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('masterVMNamePrefix'), 'nic-', copyIndex())]", - "properties": { - "ipConfigurations": [ - { - "name": "ipConfigNode", - "properties": { - "loadBalancerBackendAddressPools": [ - { - "id": "[concat(variables('masterLbID'), '/backendAddressPools/', variables('masterLbBackendPoolName'))]" - } - ], - "loadBalancerInboundNatRules": "[variables('masterLbInboundNatRules')[copyIndex()]]", - "privateIPAddress": "[concat(variables('masterFirstAddrPrefix'), copyIndex(int(variables('masterFirstAddrOctet4'))))]", - "privateIPAllocationMethod": "Static", - "subnet": { - "id": "[variables('masterVnetSubnetID')]" - } - } - } - ], - "networkSecurityGroup": { - "id": "[variables('masterNSGID')]" - } - }, - "type": "Microsoft.Network/networkInterfaces" - }, - { - "apiVersion": "[variables('apiVersionStorageManagedDisks')]", - "copy": { - "count": "[variables('masterCount')]", - "name": "vmLoopNode" - }, - "dependsOn": [ - "[concat('Microsoft.Network/networkInterfaces/', variables('masterVMNamePrefix'), 'nic-', copyIndex())]", - "[concat('Microsoft.Compute/availabilitySets/',variables('masterAvailabilitySet'))]", - "[variables('masterStorageAccountExhibitorName')]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('masterVMNamePrefix'), copyIndex())]", - "properties": { - "availabilitySet": { - "id": "[resourceId('Microsoft.Compute/availabilitySets',variables('masterAvailabilitySet'))]" - }, - "hardwareProfile": { - "vmSize": "[variables('masterVMSize')]" - }, - "networkProfile": { - "networkInterfaces": [ - { - "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(variables('masterVMNamePrefix'), 'nic-', copyIndex()))]" - } - ] - }, - "osProfile": { - "adminUsername": "[variables('adminUsername')]", - "computername": "[concat(variables('masterVMNamePrefix'), copyIndex())]", - "customData": "[base64(concat('#cloud-config\n\n', '{\"bootcmd\":[\"bash -c \\\"if [ ! -f /var/lib/sdb-gpt ];then echo DCOS-5890;parted -s /dev/sdb mklabel gpt;touch /var/lib/sdb-gpt;fi\\\"\"],\"disk_setup\":{\"ephemeral0\":{\"layout\":[45,45,10],\"overwrite\":true,\"table_type\":\"gpt\"}},\"fs_setup\":[{\"device\":\"ephemeral0.1\",\"filesystem\":\"ext4\",\"overwrite\":true},{\"device\":\"ephemeral0.2\",\"filesystem\":\"ext4\",\"overwrite\":true},{\"device\":\"ephemeral0.3\",\"filesystem\":\"ext4\",\"overwrite\":true}],\"mounts\":[[\"ephemeral0.1\",\"/var/lib/mesos\"],[\"ephemeral0.2\",\"/var/lib/docker\"],[\"ephemeral0.3\",\"/var/tmp\"]],\"runcmd\":[\"/usr/lib/apt/apt.systemd.daily\",\"echo 2dd1ce17-079e-403c-b352-a1921ee207ee \\u003e /sys/bus/vmbus/drivers/hv_util/unbind\",\"sed -i \\\"13i\\\\echo 2dd1ce17-079e-403c-b352-a1921ee207ee \\u003e /sys/bus/vmbus/drivers/hv_util/unbind\\\\n\\\" /etc/rc.local\",[\"ln\",\"-s\",\"/bin/rm\",\"/usr/bin/rm\"],[\"ln\",\"-s\",\"/bin/mkdir\",\"/usr/bin/mkdir\"],[\"ln\",\"-s\",\"/bin/tar\",\"/usr/bin/tar\"],[\"ln\",\"-s\",\"/bin/ln\",\"/usr/bin/ln\"],[\"ln\",\"-s\",\"/bin/cp\",\"/usr/bin/cp\"],[\"ln\",\"-s\",\"/bin/systemctl\",\"/usr/bin/systemctl\"],[\"ln\",\"-s\",\"/bin/mount\",\"/usr/bin/mount\"],[\"ln\",\"-s\",\"/bin/bash\",\"/usr/bin/bash\"],[\"ln\",\"-s\",\"/usr/sbin/useradd\",\"/usr/bin/useradd\"],[\"systemctl\",\"disable\",\"--now\",\"resolvconf.service\"],[\"systemctl\",\"mask\",\"--now\",\"lxc-net.service\"],[\"systemctl\",\"disable\",\"--now\",\"unscd.service\"],[\"systemctl\",\"stop\",\"--now\",\"unscd.service\"],\"sed -i \\\"s/^Port 22$/Port 22\\\\nPort 2222/1\\\" /etc/ssh/sshd_config\",\"service ssh restart\",\"/opt/azure/containers/provision.sh\",[\"cp\",\"-p\",\"/etc/resolv.conf\",\"/tmp/resolv.conf\"],[\"rm\",\"-f\",\"/etc/resolv.conf\"],[\"cp\",\"-p\",\"/tmp/resolv.conf\",\"/etc/resolv.conf\"],[\"systemctl\",\"start\",\"dcos-docker-install.service\"],[\"systemctl\",\"start\",\"dcos-config-writer.service\"],[\"systemctl\",\"restart\",\"systemd-journald.service\"],[\"systemctl\",\"restart\",\"docker.service\"],[\"systemctl\",\"start\",\"dcos-link-env.service\"],[\"systemctl\",\"enable\",\"dcos-setup.service\"],[\"systemctl\",\"--no-block\",\"start\",\"dcos-setup.service\"],\"/opt/azure/containers/add_admin_to_docker_group.sh\"],\"write_files\":[{\"content\":\"https://dcosio.azureedge.net/dcos/stable\\n\",\"owner\":\"root\",\"path\":\"/etc/mesosphere/setup-flags/repository-url\",\"permissions\":\"0644\"},{\"content\":\"[\\\"3dt--7847ebb24bf6756c3103902971b34c3f09c3afbd\\\", \\\"adminrouter--0493a6fdaed08e1971871818e194aa4607df4f09\\\", \\\"avro-cpp--760c214063f6b038b522eaf4b768b905fed56ebc\\\", \\\"boost-libs--2015ccb58fb756f61c02ee6aa05cc1e27459a9ec\\\", \\\"bootstrap--59a905ecee27e71168ed44cefda4481fb76b816d\\\", \\\"boto--6344d31eef082c7bd13259b17034ea7b5c34aedf\\\", \\\"check-time--be7d0ba757ec87f9965378fee7c76a6ee5ae996d\\\", \\\"cni--e48337da39a8cd379414acfe0da52a9226a10d24\\\", \\\"cosmos--20decef90f0623ed253a12ec4cf5c148b18d8249\\\", \\\"curl--fc3486c43f98e63f9b12675f1356e8fe842f26b0\\\", \\\"dcos-config--setup_bcc883b7a3191412cf41824bdee06c1142187a0b\\\", \\\"dcos-history--77b0e97d7b25c8bedf8f7da0689cac65b83e3813\\\", \\\"dcos-image--bda6a02bcb2eb21c4218453a870cc584f921a800\\\", \\\"dcos-image-deps--83584fd868e5b470f7cf754424a9a75b328e9b68\\\", \\\"dcos-integration-test--c28bcb2347799dca43083f55e4c7b28503176f9c\\\", \\\"dcos-log--4d630df863228f38c6333e44670b4c4b20a74832\\\", \\\"dcos-metadata--setup_bcc883b7a3191412cf41824bdee06c1142187a0b\\\", \\\"dcos-metrics--23ee2f89c58b1258bc959f1d0dd7debcbb3d79d2\\\", \\\"dcos-oauth--0079529da183c0f23a06d2b069721b6fa6cc7b52\\\", \\\"dcos-signal--1bcd3b612cbdc379380dcba17cdf9a3b6652d9dc\\\", \\\"dcos-ui--d4afd695796404a5b35950c3daddcae322481ac4\\\", \\\"dnspython--0f833eb9a8abeba3179b43f3a200a8cd42d3795a\\\", \\\"docker-gc--59a98ed6446a084bf74e4ff4b8e3479f59ea8528\\\", \\\"dvdcli--5374dd4ffb519f1dcefdec89b2247e3404f2e2e3\\\", \\\"erlang--a9ee2530357a3301e53056b36a93420847b339a3\\\", \\\"exhibitor--72d9d8f947e5411eda524d40dde1a58edeb158ed\\\", \\\"flask--26d1bcdb2d1c3dcf1d2c03bc0d4f29c86d321b21\\\", \\\"java--cd5e921ce66b0d3303883c06d73a657314044304\\\", \\\"libevent--208be855d2be29c9271a7bd6c04723ff79946e02\\\", \\\"libffi--83ce3bd7eda2ef089e57efd2bc16c144d5a1f094\\\", \\\"libsodium--9ff915db08c6bba7d6738af5084e782b13c84bf8\\\", \\\"logrotate--7f7bc4416d3ad101d0c5218872858483b516be07\\\", \\\"marathon--bfb24f7f90cb3cd52a1cb22a07caafa5013bba21\\\", \\\"mesos--aaedd03eee0d57f5c0d49c74ff1e5721862cad98\\\", \\\"mesos-dns--0401501b2b5152d01bfa84ff6d007fdafe414b16\\\", \\\"mesos-modules--311849eaae42696b8a7eefe86b9ab3ebd9bd48f5\\\", \\\"metronome--467e4c64f804dbd4cd8572516e111a3f9298c10d\\\", \\\"navstar--1128db0234105a64fb4be52f4453cd6aa895ff30\\\", \\\"ncurses--d889894b71aa1a5b311bafef0e85479025b4dacb\\\", \\\"octarine--e86d3312691b12523280d56f6260216729aaa0ad\\\", \\\"openssl--b01a32a42e3ccba52b417276e9509a441e1d4a82\\\", \\\"pkgpanda-api--541feb8a8be58bdde8fecf1d2e5bfa0515f5a7d0\\\", \\\"pkgpanda-role--f8a749a4a821476ad2ef7e9dd9d12b6a8c4643a4\\\", \\\"pytest--78aee3e58a049cdab0d266af74f77d658b360b4f\\\", \\\"python--b7a144a49577a223d37d447c568f51330ee95390\\\", \\\"python-azure-mgmt-resource--03c05550f43b0e7a4455c33fe43b0deb755d87f0\\\", \\\"python-cryptography--4184767c68e48801dd394072cb370c610a05029d\\\", \\\"python-dateutil--fdc6ff929f65dd0918cf75a9ad56704683d31781\\\", \\\"python-docopt--beba78faa13e5bf4c52393b4b82d81f3c391aa65\\\", \\\"python-gunicorn--a537f95661fb2689c52fe12510eb0d01cb83af60\\\", \\\"python-isodate--40d378c688e6badfd16676dd8b51b742bfebc8d5\\\", \\\"python-jinja2--7450f5ae5a822f63f7a58c717207be0456df51ed\\\", \\\"python-kazoo--cb7ce13a1068cd82dd84ea0de32b529a760a4bdd\\\", \\\"python-markupsafe--dd46d2a3c58611656a235f96d4adc51b2a7a590e\\\", \\\"python-passlib--802ec3605c0b82428fedba60983b1bafaa036bb8\\\", \\\"python-pyyaml--81dd44cc4a24db7cefa7016c6586a131acf279c3\\\", \\\"python-requests--1b2cadbd3811cc0c2ee235ce927e13ea1d6af41d\\\", \\\"python-retrying--eb7b8bac133f50492b1e1349cbe77c3e38bd02c3\\\", \\\"python-tox--07244f8a939a10353634c952c6d88ec4a3c05736\\\", \\\"rexray--869621bb411c9f2a793ea42cdfeed489e1972aaa\\\", \\\"six--f06424b68523c4dfa2a7c3e7475d479f3d361e42\\\", \\\"spartan--9cc57a3d55452b905d90e3201f56913140914ecc\\\", \\\"strace--7d01796d64994451c1b2b82d161a335cbe90569b\\\", \\\"teamcity-messages--e623a4d86eb3a8d199cefcc240dd4c5460cb2962\\\", \\\"toybox--f235594ab8ea9a2864ee72abe86723d76f92e848\\\"]\\n\",\"owner\":\"root\",\"path\":\"/etc/mesosphere/setup-flags/cluster-packages.json\",\"permissions\":\"0644\"},{\"content\":\"[Journal]\\nMaxLevelConsole=warning\\nRateLimitInterval=1s\\nRateLimitBurst=20000\\n\",\"owner\":\"root\",\"path\":\"/etc/systemd/journald.conf.d/dcos.conf\",\"permissions\":\"0644\"},{\"content\":\"rexray:\\n loglevel: info\\n modules:\\n default-admin:\\n host: tcp://127.0.0.1:61003\\n default-docker:\\n disabled: true\\n\",\"path\":\"/etc/rexray/config.yml\",\"permissions\":\"0644\"},{\"content\":\"[Unit]\\nAfter=network-online.target\\nWants=network-online.target\\n[Service]\\nType=oneshot\\nEnvironment=DEBIAN_FRONTEND=noninteractive\\nStandardOutput=journal+console\\nStandardError=journal+console\\nExecStartPre=/usr/bin/curl -fLsSv --retry 20 -Y 100000 -y 60 -o /var/tmp/d.deb https://az837203.vo.msecnd.net/dcos-deps/docker-engine_1.13.1-0-ubuntu-xenial_amd64.deb\\nExecStart=/usr/bin/bash -c \\\"try=1;until dpkg -D3 -i /var/tmp/d.deb || ((try\\u003e9));do echo retry $((try++));sleep $((try*try));done;systemctl --now start docker;systemctl restart docker.socket\\\"\\n\",\"path\":\"/etc/systemd/system/dcos-docker-install.service\",\"permissions\":\"0644\"},{\"content\":\"[Service]\\nRestart=always\\nStartLimitInterval=0\\nRestartSec=15\\nLimitNOFILE=16384\\nExecStartPre=-/sbin/ip link del docker0\\nExecStart=\\nExecStart=/usr/bin/docker daemon -H fd:// --storage-driver=overlay\\n\",\"path\":\"/etc/systemd/system/docker.service.d/execstart.conf\",\"permissions\":\"0644\"},{\"content\":\"[Unit]\\nRequires=dcos-setup.service\\nAfter=dcos-setup.service\\n[Service]\\nType=oneshot\\nEnvironmentFile=/etc/environment\\nEnvironmentFile=/opt/mesosphere/environment\\nExecStart=/usr/bin/bash -c \\\"echo $(detect_ip) $(hostname) \\u003e /etc/hosts\\\"\\n\",\"path\":\"/etc/systemd/system/dcos-config-writer.service\",\"permissions\":\"0644\"},{\"content\":\"\\\"bound_values\\\":\\n \\\"adminrouter_auth_enabled\\\": |-\\n ',variables('oauthEnabled'),'\\n \\\"cluster_name\\\": |-\\n ',variables('masterPublicIPAddressName'),'\\n \\\"exhibitor_azure_account_key\\\": |-\\n ', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('masterStorageAccountExhibitorName')), '2015-06-15').key1, '\\n \\\"exhibitor_azure_account_name\\\": |-\\n ',variables('masterStorageAccountExhibitorName'),'\\n \\\"exhibitor_azure_prefix\\\": |-\\n ',variables('masterPublicIPAddressName'),'\\n \\\"master_list\\\": |-\\n [\\\"', reference(variables('masterVMNic')[0]).ipConfigurations[0].properties.privateIPAddress,'\\\"]\\n \\\"oauth_enabled\\\": |-\\n ',variables('oauthEnabled'),'\\n\\\"late_bound_package_id\\\": |-\\n dcos-provider-bcc883b7a3191412cf41824bdee06c1142187a0b-azure--setup\\n\",\"owner\":\"root\",\"path\":\"/etc/mesosphere/setup-flags/late-config.yaml\",\"permissions\":\"0644\"},{\"content\":\"[Unit]\\nBefore=dcos.target\\n[Service]\\nType=oneshot\\nStandardOutput=journal+console\\nStandardError=journal+console\\nExecStartPre=/usr/bin/mkdir -p /etc/profile.d\\nExecStart=/usr/bin/ln -sf /opt/mesosphere/bin/add_dcos_path.sh /etc/profile.d/dcos.sh\\n\",\"path\":\"/etc/systemd/system/dcos-link-env.service\",\"permissions\":\"0644\"},{\"content\":\"[Unit]\\nDescription=Pkgpanda: Download DC/OS to this host.\\nAfter=network-online.target\\nWants=network-online.target\\nConditionPathExists=!/opt/mesosphere/\\n[Service]\\nType=oneshot\\nStandardOutput=journal+console\\nStandardError=journal+console\\nExecStartPre=/usr/bin/curl --keepalive-time 2 -fLsSv --retry 20 -Y 100000 -y 60 -o //var/tmp/bootstrap.tar.xz ',variables('dcosBootstrapURL'),'\\nExecStartPre=/usr/bin/mkdir -p /opt/mesosphere\\nExecStart=/usr/bin/tar -axf //var/tmp/bootstrap.tar.xz -C /opt/mesosphere\\nExecStartPost=-/usr/bin/rm -f //var/tmp/bootstrap.tar.xz\\n\",\"path\":\"/etc/systemd/system/dcos-download.service\",\"permissions\":\"0644\"},{\"content\":\"[Unit]\\nDescription=Pkgpanda: Specialize DC/OS for this host.\\nRequires=dcos-download.service\\nAfter=dcos-download.service\\n[Service]\\nType=oneshot\\nStandardOutput=journal+console\\nStandardError=journal+console\\nEnvironmentFile=/opt/mesosphere/environment\\nExecStart=/opt/mesosphere/bin/pkgpanda setup --no-block-systemd\\n[Install]\\nWantedBy=multi-user.target\\n\",\"path\":\"/etc/systemd/system/dcos-setup.service\",\"permissions\":\"0644\"},{\"content\":\"\",\"path\":\"/etc/mesosphere/roles/azure\"},{\"content\":\"#!/bin/bash\\n\\n\\nMESOSDIR=/var/lib/mesos/dl\\nmkdir $MESOSDIR\\n\\n\\n# load the env vars\\n. /etc/mesosphere/setup-flags/dcos-deploy-environment\\n\\n\\n# default dc/os component download address (Azure CDN)\\nDOCKER_ENGINE_DOWNLOAD_URL=https://mesosphere.blob.core.windows.net/dcos-deps/docker-engine_1.13.1-0-ubuntu-xenial_amd64.deb\\nLIBIPSET_DOWNLOAD_URL=https://az837203.vo.msecnd.net/dcos-deps/libipset3_6.29-1_amd64.deb\\nIPSET_DOWNLOAD_URL=https://az837203.vo.msecnd.net/dcos-deps/ipset_6.29-1_amd64.deb\\nUNZIP_DOWNLOAD_URL=https://az837203.vo.msecnd.net/dcos-deps/unzip_6.0-20ubuntu1_amd64.deb\\nLIBLTDL_DOWNLOAD_URL=https://az837203.vo.msecnd.net/dcos-deps/libltdl7_2.4.6-0.1_amd64.deb\\n\\n\\ncase $DCOS_ENVIRONMENT in\\n# because of Chinese GreatWall Firewall, the default packages on Azure CDN is blocked. So the following Chinese local mirror url should be used instead.\\nAzureChinaCloud)\\nDOCKER_ENGINE_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/docker-engine_1.11.2-0~xenial_amd64.deb\\nLIBIPSET_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/libipset3_6.29-1_amd64.deb\\nIPSET_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/ipset_6.29-1_amd64.deb\\nUNZIP_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/unzip_6.0-20ubuntu1_amd64.deb\\nLIBLTDL_DOWNLOAD_URL=http://acsengine.blob.core.chinacloudapi.cn/dcos/libltdl7_2.4.6-0.1_amd64.deb\\n;;\\nesac\\n\\n\\ncurl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/d.deb $DOCKER_ENGINE_DOWNLOAD_URL \\u0026\\ncurl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/1.deb $LIBIPSET_DOWNLOAD_URL \\u0026\\ncurl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/2.deb $IPSET_DOWNLOAD_URL \\u0026\\ncurl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/3.deb $UNZIP_DOWNLOAD_URL \\u0026\\ncurl -fLsSv --retry 20 -Y 100000 -y 60 -o $MESOSDIR/4.deb $LIBLTDL_DOWNLOAD_URL \\u0026\\nwait\\n\\n\\nfor i in {1..300}; do\\ndpkg -i $MESOSDIR/{1,2,3,4}.deb\\nif [ \\\"$?\\\" = \\\"0\\\" ]\\nthen\\necho \\\"succeeded\\\"\\nbreak\\nfi\\nsleep 1\\ndone\\n\\n\\ntouch /etc/mesosphere/roles/master\\ntouch /etc/mesosphere/roles/azure_master\\n\",\"owner\":\"root\",\"path\":\"/opt/azure/containers/provision.sh\",\"permissions\":\"0744\"},{\"content\":\"\",\"owner\":\"root\",\"path\":\"/var/lib/dcos/mesos-slave-common\",\"permissions\":\"0644\"},{\"content\":\"#!/bin/bash\\nadduser ',variables('adminUsername'),' docker\\n\",\"owner\":\"root\",\"path\":\"/opt/azure/containers/add_admin_to_docker_group.sh\",\"permissions\":\"0744\"}]}'))]", - "linuxConfiguration": { - "disablePasswordAuthentication": "true", - "ssh": { - "publicKeys": [ - { - "keyData": "[variables('sshRSAPublicKey')]", - "path": "[variables('sshKeyPath')]" - } - ] - } - } - }, - "storageProfile": { - "imageReference": { - "offer": "[variables('osImageOffer')]", - "publisher": "[variables('osImagePublisher')]", - "sku": "[variables('osImageSKU')]", - "version": "[variables('osImageVersion')]" - }, - "osDisk": { - "caching": "ReadWrite", - "createOption": "FromImage" - } - } - }, - "tags": { - "creationSource": "[concat('acsengine-', variables('masterVMNamePrefix'), copyIndex())]" - }, - "type": "Microsoft.Compute/virtualMachines" - }, - { - "apiVersion": "[variables('apiVersionDefault')]", - "dependsOn": [ - "[concat('Microsoft.Compute/virtualMachines/', variables('masterVMNamePrefix'), sub(variables('masterCount'), 1))]" - ], - "location": "[variables('location')]", - "name": "[concat(variables('masterVMNamePrefix'), sub(variables('masterCount'), 1), '/waitforleader')]", - "properties": { - "autoUpgradeMinorVersion": true, - "publisher": "Microsoft.OSTCExtensions", - "settings": { - "commandToExecute": "sh -c 'until ping -c1 leader.mesos;do echo waiting for leader.mesos;sleep 15;done;echo leader.mesos up'" - }, - "type": "CustomScriptForLinux", - "typeHandlerVersion": "1.4" - }, - "type": "Microsoft.Compute/virtualMachines/extensions" - } - ], - "outputs": { - "masterFQDN": { - "type": "string", - "value": "[reference(concat('Microsoft.Network/publicIPAddresses/', variables('masterPublicIPAddressName'))).dnsSettings.fqdn]" - } - } -} \ No newline at end of file diff --git a/pkg/api/addons.go b/pkg/api/addons.go index 6b7a16266f..3e057fb6ef 100644 --- a/pkg/api/addons.go +++ b/pkg/api/addons.go @@ -3,8 +3,8 @@ package api import ( "strconv" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/helpers" ) func (cs *ContainerService) setAddonsConfig(isUpdate bool) { diff --git a/pkg/api/agentPoolOnlyApi/v20170831/types.go b/pkg/api/agentPoolOnlyApi/v20170831/types.go index c6269834aa..aa6d1d48de 100644 --- a/pkg/api/agentPoolOnlyApi/v20170831/types.go +++ b/pkg/api/agentPoolOnlyApi/v20170831/types.go @@ -27,7 +27,7 @@ type ManagedCluster struct { Properties *Properties `json:"properties"` } -// Properties represents the ACS cluster definition +// Properties represents the AKS cluster definition type Properties struct { ProvisioningState ProvisioningState `json:"provisioningState,omitempty"` KubernetesVersion string `json:"kubernetesVersion"` diff --git a/pkg/api/agentPoolOnlyApi/v20170831/validate.go b/pkg/api/agentPoolOnlyApi/v20170831/validate.go index dd9aacd9dd..86d5c80f19 100644 --- a/pkg/api/agentPoolOnlyApi/v20170831/validate.go +++ b/pkg/api/agentPoolOnlyApi/v20170831/validate.go @@ -4,7 +4,7 @@ import ( "regexp" "strings" - "github.com/Azure/acs-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/api/common" "github.com/pkg/errors" "gopkg.in/go-playground/validator.v9" ) diff --git a/pkg/api/agentPoolOnlyApi/v20180331/apiloader_test.go b/pkg/api/agentPoolOnlyApi/v20180331/apiloader_test.go index ed1bd14e09..555297ba90 100644 --- a/pkg/api/agentPoolOnlyApi/v20180331/apiloader_test.go +++ b/pkg/api/agentPoolOnlyApi/v20180331/apiloader_test.go @@ -1,11 +1,11 @@ package v20180331_test import ( - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/api/agentPoolOnlyApi/v20180331" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/i18n" - . "github.com/Azure/acs-engine/pkg/test" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/api/agentPoolOnlyApi/v20180331" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/i18n" + . "github.com/Azure/aks-engine/pkg/test" "github.com/leonelquinteros/gotext" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" diff --git a/pkg/api/agentPoolOnlyApi/v20180331/merge_test.go b/pkg/api/agentPoolOnlyApi/v20180331/merge_test.go index fb9e3941c1..c45dc8a3bd 100644 --- a/pkg/api/agentPoolOnlyApi/v20180331/merge_test.go +++ b/pkg/api/agentPoolOnlyApi/v20180331/merge_test.go @@ -3,7 +3,7 @@ package v20180331 import ( "testing" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/helpers" ) func TestMerge_DNSPrefix(t *testing.T) { diff --git a/pkg/api/agentPoolOnlyApi/v20180331/types.go b/pkg/api/agentPoolOnlyApi/v20180331/types.go index 0ef4b7abf3..44ee202d29 100644 --- a/pkg/api/agentPoolOnlyApi/v20180331/types.go +++ b/pkg/api/agentPoolOnlyApi/v20180331/types.go @@ -27,7 +27,7 @@ type ManagedCluster struct { Properties *Properties `json:"properties"` } -// Properties represents the ACS cluster definition +// Properties represents the AKS cluster definition type Properties struct { ProvisioningState ProvisioningState `json:"provisioningState,omitempty"` KubernetesVersion string `json:"kubernetesVersion"` diff --git a/pkg/api/agentPoolOnlyApi/v20180331/validate.go b/pkg/api/agentPoolOnlyApi/v20180331/validate.go index e16e8b8f80..d0a4872a68 100644 --- a/pkg/api/agentPoolOnlyApi/v20180331/validate.go +++ b/pkg/api/agentPoolOnlyApi/v20180331/validate.go @@ -5,8 +5,8 @@ import ( "regexp" "strings" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/helpers" "github.com/pkg/errors" validator "gopkg.in/go-playground/validator.v9" ) diff --git a/pkg/api/agentPoolOnlyApi/v20180331/validate_test.go b/pkg/api/agentPoolOnlyApi/v20180331/validate_test.go index 51819cba92..dde7e72e22 100644 --- a/pkg/api/agentPoolOnlyApi/v20180331/validate_test.go +++ b/pkg/api/agentPoolOnlyApi/v20180331/validate_test.go @@ -3,7 +3,7 @@ package v20180331 import ( "testing" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/helpers" ) func TestValidateVNET(t *testing.T) { diff --git a/pkg/api/agentPoolOnlyApi/vlabs/types.go b/pkg/api/agentPoolOnlyApi/vlabs/types.go index ded6078062..1ea8216ea5 100644 --- a/pkg/api/agentPoolOnlyApi/vlabs/types.go +++ b/pkg/api/agentPoolOnlyApi/vlabs/types.go @@ -27,7 +27,7 @@ type ManagedCluster struct { Properties *Properties `json:"properties"` } -// Properties represents the ACS cluster definition +// Properties represents the AKS cluster definition type Properties struct { ProvisioningState ProvisioningState `json:"provisioningState,omitempty"` KubernetesVersion string `json:"kubernetesVersion"` diff --git a/pkg/api/agentPoolOnlyApi/vlabs/validate.go b/pkg/api/agentPoolOnlyApi/vlabs/validate.go index aa2f0d7794..9b78150a75 100644 --- a/pkg/api/agentPoolOnlyApi/vlabs/validate.go +++ b/pkg/api/agentPoolOnlyApi/vlabs/validate.go @@ -4,7 +4,7 @@ import ( "regexp" "strings" - "github.com/Azure/acs-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/api/common" "github.com/pkg/errors" validator "gopkg.in/go-playground/validator.v9" ) diff --git a/pkg/api/apiloader.go b/pkg/api/apiloader.go index c474849bfb..57a517ac7d 100644 --- a/pkg/api/apiloader.go +++ b/pkg/api/apiloader.go @@ -6,17 +6,16 @@ import ( "io/ioutil" "reflect" - "github.com/Azure/acs-engine/pkg/api/agentPoolOnlyApi/v20170831" - "github.com/Azure/acs-engine/pkg/api/agentPoolOnlyApi/v20180331" - apvlabs "github.com/Azure/acs-engine/pkg/api/agentPoolOnlyApi/vlabs" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/api/v20160330" - "github.com/Azure/acs-engine/pkg/api/v20160930" - "github.com/Azure/acs-engine/pkg/api/v20170131" - "github.com/Azure/acs-engine/pkg/api/v20170701" - "github.com/Azure/acs-engine/pkg/api/vlabs" - "github.com/Azure/acs-engine/pkg/helpers" - "github.com/Azure/acs-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/api/agentPoolOnlyApi/v20170831" + "github.com/Azure/aks-engine/pkg/api/agentPoolOnlyApi/v20180331" + apvlabs "github.com/Azure/aks-engine/pkg/api/agentPoolOnlyApi/vlabs" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/api/v20160930" + "github.com/Azure/aks-engine/pkg/api/v20170131" + "github.com/Azure/aks-engine/pkg/api/v20170701" + "github.com/Azure/aks-engine/pkg/api/vlabs" + "github.com/Azure/aks-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/i18n" "github.com/pkg/errors" log "github.com/sirupsen/logrus" ) @@ -26,7 +25,7 @@ type Apiloader struct { Translator *i18n.Translator } -// LoadContainerServiceFromFile loads an ACS Cluster API Model from a JSON file +// LoadContainerServiceFromFile loads an AKS cluster API Model from a JSON file func (a *Apiloader) LoadContainerServiceFromFile(jsonFile string, validate, isUpdate bool, existingContainerService *ContainerService) (*ContainerService, string, error) { contents, e := ioutil.ReadFile(jsonFile) if e != nil { @@ -58,7 +57,7 @@ func LoadDefaultContainerServiceProperties() (TypeMeta, *vlabs.Properties) { } } -// DeserializeContainerService loads an ACS Cluster API Model, validates it, and returns the unversioned representation +// DeserializeContainerService loads an AKS cluster API Model, validates it, and returns the unversioned representation func (a *Apiloader) DeserializeContainerService(contents []byte, validate, isUpdate bool, existingContainerService *ContainerService) (*ContainerService, string, error) { m := &TypeMeta{} if err := json.Unmarshal(contents, &m); err != nil { @@ -77,7 +76,7 @@ func (a *Apiloader) DeserializeContainerService(contents []byte, validate, isUpd return service, version, err } -// LoadContainerService loads an ACS Cluster API Model, validates it, and returns the unversioned representation +// LoadContainerService loads an AKS cluster API Model, validates it, and returns the unversioned representation func (a *Apiloader) LoadContainerService( contents []byte, version string, @@ -112,30 +111,6 @@ func (a *Apiloader) LoadContainerService( unversioned.Properties.OrchestratorProfile.OrchestratorVersion = curOrchVersion } return unversioned, nil - case v20160330.APIVersion: - containerService := &v20160330.ContainerService{} - if e := json.Unmarshal(contents, &containerService); e != nil { - return nil, e - } - if hasExistingCS { - vecs := ConvertContainerServiceToV20160330(existingContainerService) - if e := containerService.Merge(vecs); e != nil { - return nil, e - } - } - setContainerServiceDefaultsv20160330(containerService) - if containerService.Properties == nil { - return nil, errors.New("missing ContainerService Properties") - } - if e := containerService.Properties.Validate(); validate && e != nil { - return nil, e - } - unversioned := ConvertV20160330ContainerService(containerService) - if curOrchVersion != "" { - unversioned.Properties.OrchestratorProfile.OrchestratorVersion = curOrchVersion - } - return unversioned, nil - case v20170131.APIVersion: containerService := &v20170131.ContainerService{} if e := json.Unmarshal(contents, &containerService); e != nil { @@ -219,7 +194,7 @@ func (a *Apiloader) LoadContainerService( } } -// LoadContainerServiceForAgentPoolOnlyCluster loads an ACS Cluster API Model, validates it, and returns the unversioned representation +// LoadContainerServiceForAgentPoolOnlyCluster loads an AKS cluster API Model, validates it, and returns the unversioned representation func (a *Apiloader) LoadContainerServiceForAgentPoolOnlyCluster( contents []byte, version string, @@ -357,17 +332,6 @@ func (a *Apiloader) SerializeContainerService(containerService *ContainerService } return b, nil - case v20160330.APIVersion: - v20160330ContainerService := ConvertContainerServiceToV20160330(containerService) - armContainerService := &V20160330ARMContainerService{} - armContainerService.ContainerService = v20160330ContainerService - armContainerService.APIVersion = version - b, err := helpers.JSONMarshalIndent(armContainerService, "", " ", false) - if err != nil { - return nil, err - } - return b, nil - case v20170131.APIVersion: v20170131ContainerService := ConvertContainerServiceToV20170131(containerService) armContainerService := &V20170131ARMContainerService{} @@ -436,26 +400,13 @@ func (a *Apiloader) serializeHostedContainerService(containerService *ContainerS // Sets default container service property values for any appropriate zero values func setContainerServiceDefaultsv20160930(c *v20160930.ContainerService) { if c.Properties.OrchestratorProfile == nil { - c.Properties.OrchestratorProfile = &v20160930.OrchestratorProfile{ - OrchestratorType: v20160930.DCOS, - } - } -} - -// Sets default container service property values for any appropriate zero values -func setContainerServiceDefaultsv20160330(c *v20160330.ContainerService) { - if c.Properties.OrchestratorProfile == nil { - c.Properties.OrchestratorProfile = &v20160330.OrchestratorProfile{ - OrchestratorType: v20160330.DCOS, - } + c.Properties.OrchestratorProfile = &v20160930.OrchestratorProfile{} } } // Sets default container service property values for any appropriate zero values func setContainerServiceDefaultsv20170131(c *v20170131.ContainerService) { if c.Properties.OrchestratorProfile == nil { - c.Properties.OrchestratorProfile = &v20170131.OrchestratorProfile{ - OrchestratorType: v20170131.DCOS, - } + c.Properties.OrchestratorProfile = &v20170131.OrchestratorProfile{} } } diff --git a/pkg/api/apiloader_test.go b/pkg/api/apiloader_test.go index cf4c2b4e61..80125cbddb 100644 --- a/pkg/api/apiloader_test.go +++ b/pkg/api/apiloader_test.go @@ -2,19 +2,18 @@ package api import ( "encoding/json" - - "github.com/Azure/acs-engine/pkg/api/agentPoolOnlyApi/v20170831" - "github.com/Azure/acs-engine/pkg/api/agentPoolOnlyApi/v20180331" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/i18n" - "github.com/leonelquinteros/gotext" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "io/ioutil" "os" "path" "testing" + + "github.com/Azure/aks-engine/pkg/api/agentPoolOnlyApi/v20170831" + "github.com/Azure/aks-engine/pkg/api/agentPoolOnlyApi/v20180331" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/i18n" + "github.com/leonelquinteros/gotext" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" ) func TestLoadContainerServiceFromFile(t *testing.T) { @@ -29,7 +28,7 @@ func TestLoadContainerServiceFromFile(t *testing.T) { }, } - containerService, _, err := apiloader.LoadContainerServiceFromFile("../acsengine/testdata/v20170701/kubernetes.json", true, false, existingContainerService) + containerService, _, err := apiloader.LoadContainerServiceFromFile("../engine/testdata/v20170701/kubernetes.json", true, false, existingContainerService) if err != nil { t.Error(err.Error()) } @@ -37,7 +36,7 @@ func TestLoadContainerServiceFromFile(t *testing.T) { t.Errorf("Failed to set orcherstator version when it is set in the json, expected 1.8.12 but got %s", containerService.Properties.OrchestratorProfile.OrchestratorVersion) } - containerService, _, err = apiloader.LoadContainerServiceFromFile("../acsengine/testdata/v20170701/kubernetes-default-version.json", true, false, existingContainerService) + containerService, _, err = apiloader.LoadContainerServiceFromFile("../engine/testdata/v20170701/kubernetes-default-version.json", true, false, existingContainerService) if err != nil { t.Error(err.Error()) } @@ -45,7 +44,7 @@ func TestLoadContainerServiceFromFile(t *testing.T) { t.Errorf("Failed to set orcherstator version when it is not set in the json, got %s", containerService.Properties.OrchestratorProfile.OrchestratorVersion) } - containerService, _, err = apiloader.LoadContainerServiceFromFile("../acsengine/testdata/v20170131/kubernetes.json", true, false, existingContainerService) + containerService, _, err = apiloader.LoadContainerServiceFromFile("../engine/testdata/v20170131/kubernetes.json", true, false, existingContainerService) if err != nil { t.Error(err.Error()) } @@ -53,7 +52,7 @@ func TestLoadContainerServiceFromFile(t *testing.T) { t.Errorf("Failed to set orcherstator version when it is not set in the json, got %s", containerService.Properties.OrchestratorProfile.OrchestratorVersion) } - containerService, _, err = apiloader.LoadContainerServiceFromFile("../acsengine/testdata/v20160930/kubernetes.json", true, false, existingContainerService) + containerService, _, err = apiloader.LoadContainerServiceFromFile("../engine/testdata/v20160930/kubernetes.json", true, false, existingContainerService) if err != nil { t.Error(err.Error()) } @@ -61,7 +60,7 @@ func TestLoadContainerServiceFromFile(t *testing.T) { t.Errorf("Failed to set orcherstator version when it is not set in the json, got %s", containerService.Properties.OrchestratorProfile.OrchestratorVersion) } - containerService, _, err = apiloader.LoadContainerServiceFromFile("../acsengine/testdata/v20170701/kubernetes-default-version.json", true, false, nil) + containerService, _, err = apiloader.LoadContainerServiceFromFile("../engine/testdata/v20170701/kubernetes-default-version.json", true, false, nil) if err != nil { t.Error(err.Error()) } @@ -69,7 +68,7 @@ func TestLoadContainerServiceFromFile(t *testing.T) { t.Errorf("Failed to set orcherstator version when it is not set in the json API v20170701, got %s but expected %s", containerService.Properties.OrchestratorProfile.OrchestratorVersion, common.GetDefaultKubernetesVersion(false)) } - containerService, _, err = apiloader.LoadContainerServiceFromFile("../acsengine/testdata/v20170701/kubernetes-win-default-version.json", true, false, nil) + containerService, _, err = apiloader.LoadContainerServiceFromFile("../engine/testdata/v20170701/kubernetes-win-default-version.json", true, false, nil) if err != nil { t.Error(err.Error()) } @@ -77,7 +76,7 @@ func TestLoadContainerServiceFromFile(t *testing.T) { t.Errorf("Failed to set orcherstator version to windows default when it is not set in the json API v20170701, got %s but expected %s", containerService.Properties.OrchestratorProfile.OrchestratorVersion, common.GetDefaultKubernetesVersion(true)) } - containerService, _, err = apiloader.LoadContainerServiceFromFile("../acsengine/testdata/v20170131/kubernetes.json", true, false, nil) + containerService, _, err = apiloader.LoadContainerServiceFromFile("../engine/testdata/v20170131/kubernetes.json", true, false, nil) if err != nil { t.Error(err.Error()) } @@ -85,7 +84,7 @@ func TestLoadContainerServiceFromFile(t *testing.T) { t.Errorf("Failed to set orcherstator version when it is not set in the json API v20170131, got %s but expected %s", containerService.Properties.OrchestratorProfile.OrchestratorVersion, common.GetDefaultKubernetesVersion(false)) } - containerService, _, err = apiloader.LoadContainerServiceFromFile("../acsengine/testdata/v20170131/kubernetes-win.json", true, false, nil) + containerService, _, err = apiloader.LoadContainerServiceFromFile("../engine/testdata/v20170131/kubernetes-win.json", true, false, nil) if err != nil { t.Error(err.Error()) } diff --git a/pkg/api/azenvtypes.go b/pkg/api/azenvtypes.go index a7991b92ec..50c919ea80 100644 --- a/pkg/api/azenvtypes.go +++ b/pkg/api/azenvtypes.go @@ -1,13 +1,10 @@ package api -import "fmt" - //AzureEnvironmentSpecConfig is the overall configuration differences in different cloud environments. type AzureEnvironmentSpecConfig struct { CloudName string DockerSpecConfig DockerSpecConfig KubernetesSpecConfig KubernetesSpecConfig - DCOSSpecConfig DCOSSpecConfig EndpointConfig AzureEndpointConfig OSImageConfig map[Distro]AzureOSImageConfig } @@ -18,19 +15,6 @@ type DockerSpecConfig struct { DockerComposeDownloadURL string } -//DCOSSpecConfig is the configurations of DCOS -type DCOSSpecConfig struct { - DCOS188BootstrapDownloadURL string - DCOS190BootstrapDownloadURL string - DCOS198BootstrapDownloadURL string - DCOS110BootstrapDownloadURL string - DCOS111BootstrapDownloadURL string - DCOSWindowsBootstrapDownloadURL string - DcosRepositoryURL string // For custom install, for example CI, need these three addributes - DcosClusterPackageListID string // the id of the package list file - DcosProviderPackageID string // the id of the dcos-provider-xxx package -} - //KubernetesSpecConfig is the kubernetes container images used. type KubernetesSpecConfig struct { KubernetesImageBase string @@ -77,18 +61,6 @@ var ( ContainerdDownloadURLBase: "https://storage.googleapis.com/cri-containerd-release/", } - //DefaultDCOSSpecConfig is the default DC/OS binary download URL. - DefaultDCOSSpecConfig = DCOSSpecConfig{ - DCOS188BootstrapDownloadURL: fmt.Sprintf(AzureEdgeDCOSBootstrapDownloadURL, "stable", "5df43052907c021eeb5de145419a3da1898c58a5"), - DCOS190BootstrapDownloadURL: fmt.Sprintf(AzureEdgeDCOSBootstrapDownloadURL, "stable", "58fd0833ce81b6244fc73bf65b5deb43217b0bd7"), - DCOS198BootstrapDownloadURL: fmt.Sprintf(AzureEdgeDCOSBootstrapDownloadURL, "stable/1.9.8", "f4ae0d20665fc68ee25282d6f78681b2773c6e10"), - DCOS110BootstrapDownloadURL: fmt.Sprintf(AzureEdgeDCOSBootstrapDownloadURL, "stable/1.10.0", "4d92536e7381176206e71ee15b5ffe454439920c"), - DCOS111BootstrapDownloadURL: fmt.Sprintf(AzureEdgeDCOSBootstrapDownloadURL, "stable/1.11.0", "a0654657903fb68dff60f6e522a7f241c1bfbf0f"), - DCOSWindowsBootstrapDownloadURL: "http://dcos-win.westus.cloudapp.azure.com/dcos-windows/stable/", - DcosRepositoryURL: "https://dcosio.azureedge.net/dcos/stable/1.11.0", - DcosClusterPackageListID: "248a66388bba1adbcb14a52fd3b7b424ab06fa76", - } - //DefaultDockerSpecConfig is the default Docker engine repo. DefaultDockerSpecConfig = DockerSpecConfig{ DockerEngineRepo: "https://aptdocker.azureedge.net/repo", @@ -151,22 +123,6 @@ var ( ImageVersion: "2018.11.08", } - //DefaultOpenShift39RHELImageConfig is the OpenShift on RHEL distribution. - DefaultOpenShift39RHELImageConfig = AzureOSImageConfig{ - ImageOffer: "acsengine-preview", - ImageSku: "rhel74", - ImagePublisher: "redhat", - ImageVersion: "latest", - } - - //DefaultOpenShift39CentOSImageConfig is the OpenShift on CentOS distribution. - DefaultOpenShift39CentOSImageConfig = AzureOSImageConfig{ - ImageOffer: "origin-acsengine-preview", - ImageSku: "centos7", - ImagePublisher: "redhat", - ImageVersion: "latest", - } - //AzureCloudSpec is the default configurations for global azure. AzureCloudSpec = AzureEnvironmentSpecConfig{ CloudName: AzurePublicCloud, @@ -174,7 +130,6 @@ var ( DockerSpecConfig: DefaultDockerSpecConfig, //KubernetesSpecConfig is the default kubernetes container image url. KubernetesSpecConfig: DefaultKubernetesSpecConfig, - DCOSSpecConfig: DefaultDCOSSpecConfig, EndpointConfig: AzureEndpointConfig{ ResourceManagerVMDNSSuffix: "cloudapp.azure.com", @@ -186,9 +141,6 @@ var ( CoreOS: DefaultCoreOSImageConfig, AKS: DefaultAKSOSImageConfig, AKSDockerEngine: DefaultAKSDockerEngineOSImageConfig, - // Image config supported for OpenShift - OpenShift39RHEL: DefaultOpenShift39RHELImageConfig, - OpenShiftCentOS: DefaultOpenShift39CentOSImageConfig, }, } @@ -197,7 +149,6 @@ var ( CloudName: azureGermanCloud, DockerSpecConfig: DefaultDockerSpecConfig, KubernetesSpecConfig: DefaultKubernetesSpecConfig, - DCOSSpecConfig: DefaultDCOSSpecConfig, EndpointConfig: AzureEndpointConfig{ ResourceManagerVMDNSSuffix: "cloudapp.microsoftazure.de", }, @@ -214,7 +165,6 @@ var ( CloudName: azureUSGovernmentCloud, DockerSpecConfig: DefaultDockerSpecConfig, KubernetesSpecConfig: DefaultKubernetesSpecConfig, - DCOSSpecConfig: DefaultDCOSSpecConfig, EndpointConfig: AzureEndpointConfig{ ResourceManagerVMDNSSuffix: "cloudapp.usgovcloudapi.net", }, @@ -249,12 +199,6 @@ var ( VnetCNIWindowsPluginsDownloadURL: "https://mirror.azk8s.cn/kubernetes/azure-container-networking/azure-vnet-cni-windows-amd64-" + AzureCniPluginVerWindows + ".zip", ContainerdDownloadURLBase: "https://mirror.azk8s.cn/kubernetes/containerd/", }, - DCOSSpecConfig: DCOSSpecConfig{ - DCOS188BootstrapDownloadURL: fmt.Sprintf(AzureChinaCloudDCOSBootstrapDownloadURL, "5df43052907c021eeb5de145419a3da1898c58a5"), - DCOSWindowsBootstrapDownloadURL: "https://dcosdevstorage.blob.core.windows.net/dcos-windows", - DCOS190BootstrapDownloadURL: fmt.Sprintf(AzureChinaCloudDCOSBootstrapDownloadURL, "58fd0833ce81b6244fc73bf65b5deb43217b0bd7"), - DCOS198BootstrapDownloadURL: fmt.Sprintf(AzureChinaCloudDCOSBootstrapDownloadURL, "f4ae0d20665fc68ee25282d6f78681b2773c6e10"), - }, EndpointConfig: AzureEndpointConfig{ ResourceManagerVMDNSSuffix: "cloudapp.chinacloudapi.cn", diff --git a/pkg/api/common/const.go b/pkg/api/common/const.go index c18aea25dd..bd29d33d0b 100644 --- a/pkg/api/common/const.go +++ b/pkg/api/common/const.go @@ -2,18 +2,8 @@ package common // the orchestrators supported const ( - // Mesos is the string constant for MESOS orchestrator type - Mesos string = "Mesos" - // DCOS is the string constant for DCOS orchestrator type and defaults to DCOS188 - DCOS string = "DCOS" - // Swarm is the string constant for the Swarm orchestrator type - Swarm string = "Swarm" // Kubernetes is the string constant for the Kubernetes orchestrator type Kubernetes string = "Kubernetes" - // SwarmMode is the string constant for the Swarm Mode orchestrator type - SwarmMode string = "SwarmMode" - // OpenShift is the string constant for the OpenShift orchestrator type - OpenShift string = "OpenShift" ) // validation values @@ -60,66 +50,3 @@ const ( // KubernetesDefaultReleaseWindows is the default Kubernetes release KubernetesDefaultReleaseWindows string = "1.9" ) - -const ( - // DCOSVersion1Dot11Dot2 is the major.minor.patch string for 1.11.0 versions of DCOS - DCOSVersion1Dot11Dot2 string = "1.11.2" - // DCOSVersion1Dot11Dot0 is the major.minor.patch string for 1.11.0 versions of DCOS - DCOSVersion1Dot11Dot0 string = "1.11.0" - // DCOSVersion1Dot10Dot0 is the major.minor.patch string for 1.10.0 versions of DCOS - DCOSVersion1Dot10Dot0 string = "1.10.0" - // DCOSVersion1Dot9Dot0 is the major.minor.patch string for 1.9.0 versions of DCOS - DCOSVersion1Dot9Dot0 string = "1.9.0" - // DCOSVersion1Dot9Dot8 is the major.minor.patch string for 1.9.8 versions of DCOS - DCOSVersion1Dot9Dot8 string = "1.9.8" - // DCOSVersion1Dot8Dot8 is the major.minor.patch string for 1.8.8 versions of DCOS - DCOSVersion1Dot8Dot8 string = "1.8.8" - // DCOSDefaultVersion is the default major.minor.patch version for DCOS - DCOSDefaultVersion string = DCOSVersion1Dot11Dot0 -) - -// AllDCOSSupportedVersions maintain a list of available dcos versions in acs-engine -var AllDCOSSupportedVersions = []string{ - DCOSVersion1Dot11Dot2, - DCOSVersion1Dot11Dot0, - DCOSVersion1Dot10Dot0, - DCOSVersion1Dot9Dot8, - DCOSVersion1Dot9Dot0, - DCOSVersion1Dot8Dot8, -} - -const ( - // OpenShiftVersion3Dot9Dot0 is the major.minor.patch string for the 3.9.0 version of OpenShift - OpenShiftVersion3Dot9Dot0 string = "3.9.0" - // OpenShiftVersionUnstable is used for development in acs-engine and should not be used by end-users. - OpenShiftVersionUnstable string = "unstable" - // OpenShiftDefaultVersion is the default major.minor.patch version for OpenShift - OpenShiftDefaultVersion string = OpenShiftVersion3Dot9Dot0 -) - -const ( - // SwarmVersion is the Swarm orchestrator version - SwarmVersion = "swarm:1.1.0" - // DockerCEVersion is the DockerCE orchestrator version - DockerCEVersion = "17.03.*" -) - -// GetAllSupportedDCOSVersions returns a slice of all supported DCOS versions. -func GetAllSupportedDCOSVersions() []string { - return AllDCOSSupportedVersions -} - -// GetAllSupportedOpenShiftVersions returns a slice of all supported OpenShift versions. -func GetAllSupportedOpenShiftVersions() []string { - return []string{OpenShiftVersion3Dot9Dot0, OpenShiftVersionUnstable} -} - -// GetAllSupportedSwarmVersions returns a slice of all supported Swarm versions. -func GetAllSupportedSwarmVersions() []string { - return []string{SwarmVersion} -} - -// GetAllSupportedDockerCEVersions returns a slice of all supported Docker CE versions. -func GetAllSupportedDockerCEVersions() []string { - return []string{DockerCEVersion} -} diff --git a/pkg/api/common/versions.go b/pkg/api/common/versions.go index 1291ee2480..27432655fe 100644 --- a/pkg/api/common/versions.go +++ b/pkg/api/common/versions.go @@ -224,7 +224,7 @@ func getSortedSemverVersions(versions []string, preRelease bool) []semver.Versio return semverVersions } -// AllKubernetesWindowsSupportedVersions maintain a set of available k8s Windows versions in acs-engine +// AllKubernetesWindowsSupportedVersions maintain a set of available k8s Windows versions in aks-engine var AllKubernetesWindowsSupportedVersions = getAllKubernetesWindowsSupportedVersionsMap() func getAllKubernetesWindowsSupportedVersionsMap() map[string]bool { @@ -260,11 +260,6 @@ func GetSupportedVersions(orchType string, isUpdate, hasWindows bool) (versions switch orchType { case Kubernetes: return GetAllSupportedKubernetesVersions(isUpdate, hasWindows), GetDefaultKubernetesVersion(hasWindows) - case OpenShift: - return GetAllSupportedOpenShiftVersions(), string(OpenShiftDefaultVersion) - - case DCOS: - return AllDCOSSupportedVersions, DCOSDefaultVersion default: return nil, "" } diff --git a/pkg/api/common/versions_test.go b/pkg/api/common/versions_test.go index ceea52cdef..7d9d178796 100644 --- a/pkg/api/common/versions_test.go +++ b/pkg/api/common/versions_test.go @@ -342,11 +342,6 @@ func Test_GetValidPatchVersion(t *testing.T) { t.Errorf("It is not the default Kubernetes version") } - v = GetValidPatchVersion(Mesos, "1.6.0", false, false) - if v != "" { - t.Errorf("Expected empty version for unsupported orchType") - } - for version, enabled := range AllKubernetesWindowsSupportedVersions { if enabled { v = GetValidPatchVersion(Kubernetes, version, false, true) diff --git a/pkg/api/const.go b/pkg/api/const.go index e47cc4c441..84a423b15d 100644 --- a/pkg/api/const.go +++ b/pkg/api/const.go @@ -2,18 +2,8 @@ package api // the orchestrators supported by vlabs const ( - // Mesos is the string constant for MESOS orchestrator type - Mesos string = "Mesos" - // DCOS is the string constant for DCOS orchestrator type and defaults to DCOS188 - DCOS string = "DCOS" - // Swarm is the string constant for the Swarm orchestrator type - Swarm string = "Swarm" // Kubernetes is the string constant for the Kubernetes orchestrator type Kubernetes string = "Kubernetes" - // SwarmMode is the string constant for the Swarm Mode orchestrator type - SwarmMode string = "SwarmMode" - // OpenShift is the string constant for the OpenShift orchestrator type - OpenShift string = "OpenShift" ) // the OSTypes supported by vlabs @@ -29,20 +19,9 @@ const ( CoreOS Distro = "coreos" AKS Distro = "aks" AKSDockerEngine Distro = "aks-docker-engine" - // Supported distros by OpenShift - OpenShift39RHEL Distro = "openshift39_rhel" - OpenShiftCentOS Distro = "openshift39_centos" ) const ( - // SwarmVersion is the Swarm orchestrator version - SwarmVersion = "swarm:1.1.0" - // SwarmDockerComposeVersion is the Docker Compose version - SwarmDockerComposeVersion = "1.6.2" - // DockerCEVersion is the DockerCE orchestrator version - DockerCEVersion = "17.03.*" - // DockerCEDockerComposeVersion is the Docker Compose version - DockerCEDockerComposeVersion = "1.14.0" // KubernetesWindowsDockerVersion is the default version for docker on Windows nodes in kubernetes KubernetesWindowsDockerVersion = "18.09.0" ) @@ -67,8 +46,6 @@ const ( AvailabilitySet = "AvailabilitySet" // DefaultOrchestratorName specifies the 3 character orchestrator code of the cluster template and affects resource naming. DefaultOrchestratorName = "k8s" - // DefaultOpenshiftOrchestratorName specifies the 3 character orchestrator code of the cluster template and affects resource naming. - DefaultOpenshiftOrchestratorName = "ocp" // DefaultHostedProfileMasterName specifies the 3 character orchestrator code of the clusters with hosted master profiles. DefaultHostedProfileMasterName = "aks" // DefaultFirstConsecutiveKubernetesStaticIP specifies the static IP address on Kubernetes master 0 @@ -107,43 +84,40 @@ const ( ManagedDisks = "ManagedDisks" ) -// To identify programmatically generated public agent pools -const publicAgentPoolSuffix = "-public" - const ( - // DefaultTillerAddonEnabled determines the acs-engine provided default for enabling tiller addon + // DefaultTillerAddonEnabled determines the aks-engine provided default for enabling tiller addon DefaultTillerAddonEnabled = true - // DefaultAADPodIdentityAddonEnabled determines the acs-engine provided default for enabling aad-pod-identity addon + // DefaultAADPodIdentityAddonEnabled determines the aks-engine provided default for enabling aad-pod-identity addon DefaultAADPodIdentityAddonEnabled = false - // DefaultACIConnectorAddonEnabled determines the acs-engine provided default for enabling aci connector addon + // DefaultACIConnectorAddonEnabled determines the aks-engine provided default for enabling aci connector addon DefaultACIConnectorAddonEnabled = false - // DefaultClusterAutoscalerAddonEnabled determines the acs-engine provided default for enabling cluster autoscaler addon + // DefaultClusterAutoscalerAddonEnabled determines the aks-engine provided default for enabling cluster autoscaler addon DefaultClusterAutoscalerAddonEnabled = false - // DefaultBlobfuseFlexVolumeAddonEnabled determines the acs-engine provided default for enabling blobfuse flexvolume addon + // DefaultBlobfuseFlexVolumeAddonEnabled determines the aks-engine provided default for enabling blobfuse flexvolume addon DefaultBlobfuseFlexVolumeAddonEnabled = true - // DefaultSMBFlexVolumeAddonEnabled determines the acs-engine provided default for enabling smb flexvolume addon + // DefaultSMBFlexVolumeAddonEnabled determines the aks-engine provided default for enabling smb flexvolume addon DefaultSMBFlexVolumeAddonEnabled = true - // DefaultKeyVaultFlexVolumeAddonEnabled determines the acs-engine provided default for enabling key vault flexvolume addon + // DefaultKeyVaultFlexVolumeAddonEnabled determines the aks-engine provided default for enabling key vault flexvolume addon DefaultKeyVaultFlexVolumeAddonEnabled = true - // DefaultDashboardAddonEnabled determines the acs-engine provided default for enabling kubernetes-dashboard addon + // DefaultDashboardAddonEnabled determines the aks-engine provided default for enabling kubernetes-dashboard addon DefaultDashboardAddonEnabled = true - // DefaultReschedulerAddonEnabled determines the acs-engine provided default for enabling kubernetes-rescheduler addon + // DefaultReschedulerAddonEnabled determines the aks-engine provided default for enabling kubernetes-rescheduler addon DefaultReschedulerAddonEnabled = false - // DefaultRBACEnabled determines the acs-engine provided default for enabling kubernetes RBAC + // DefaultRBACEnabled determines the aks-engine provided default for enabling kubernetes RBAC DefaultRBACEnabled = true - // DefaultUseInstanceMetadata determines the acs-engine provided default for enabling Azure cloudprovider instance metadata service + // DefaultUseInstanceMetadata determines the aks-engine provided default for enabling Azure cloudprovider instance metadata service DefaultUseInstanceMetadata = true - // DefaultLoadBalancerSku determines the acs-engine provided default for enabling Azure cloudprovider load balancer SKU + // DefaultLoadBalancerSku determines the aks-engine provided default for enabling Azure cloudprovider load balancer SKU DefaultLoadBalancerSku = "Basic" - // DefaultExcludeMasterFromStandardLB determines the acs-engine provided default for excluding master nodes from standard load balancer. + // DefaultExcludeMasterFromStandardLB determines the aks-engine provided default for excluding master nodes from standard load balancer. DefaultExcludeMasterFromStandardLB = true - // DefaultSecureKubeletEnabled determines the acs-engine provided default for securing kubelet communications + // DefaultSecureKubeletEnabled determines the aks-engine provided default for securing kubelet communications DefaultSecureKubeletEnabled = true - // DefaultMetricsServerAddonEnabled determines the acs-engine provided default for enabling kubernetes metrics-server addon + // DefaultMetricsServerAddonEnabled determines the aks-engine provided default for enabling kubernetes metrics-server addon DefaultMetricsServerAddonEnabled = false - // DefaultNVIDIADevicePluginAddonEnabled determines the acs-engine provided default for enabling NVIDIA Device Plugin + // DefaultNVIDIADevicePluginAddonEnabled determines the aks-engine provided default for enabling NVIDIA Device Plugin DefaultNVIDIADevicePluginAddonEnabled = false - // DefaultContainerMonitoringAddonEnabled determines the acs-engine provided default for enabling kubernetes container monitoring addon + // DefaultContainerMonitoringAddonEnabled determines the aks-engine provided default for enabling kubernetes container monitoring addon DefaultContainerMonitoringAddonEnabled = false // DefaultDNSAutoscalerAddonEnabled determines the acs-engine provided default for dns-autoscaler addon DefaultDNSAutoscalerAddonEnabled = false @@ -175,7 +149,7 @@ const ( ContainerMonitoringAddonName = "container-monitoring" // IPMASQAgentAddonName is the name of the ip masq agent addon IPMASQAgentAddonName = "ip-masq-agent" - // DefaultPrivateClusterEnabled determines the acs-engine provided default for enabling kubernetes Private Cluster + // DefaultPrivateClusterEnabled determines the aks-engine provided default for enabling kubernetes Private Cluster DefaultPrivateClusterEnabled = false // NetworkPolicyAzure is the string expression for Azure CNI network policy manager NetworkPolicyAzure = "azure" @@ -185,14 +159,14 @@ const ( NetworkPluginKubenet = "kubenet" // NetworkPluginAzure is the string expression for Azure CNI plugin. NetworkPluginAzure = "azure" - // DefaultSinglePlacementGroup determines the acs-engine provided default for supporting large VMSS + // DefaultSinglePlacementGroup determines the aks-engine provided default for supporting large VMSS // (true = single placement group 0-100 VMs, false = multiple placement group 0-1000 VMs) DefaultSinglePlacementGroup = true // ARMNetworkNamespace is the ARM-specific namespace for ARM's network providers. ARMNetworkNamespace = "Microsoft.Networks" // ARMVirtualNetworksResourceType is the ARM resource type for virtual network resources of ARM. ARMVirtualNetworksResourceType = "virtualNetworks" - // DefaultAcceleratedNetworkingWindowsEnabled determines the acs-engine provided default for enabling accelerated networking on Windows nodes + // DefaultAcceleratedNetworkingWindowsEnabled determines the aks-engine provided default for enabling accelerated networking on Windows nodes DefaultAcceleratedNetworkingWindowsEnabled = false // DefaultDNSAutoscalerAddonName is the name of the dns-autoscaler addon DefaultDNSAutoscalerAddonName = "dns-autoscaler" @@ -200,7 +174,7 @@ const ( const ( // AgentPoolProfileRoleEmpty is the empty role. Deprecated; only used in - // acs-engine. + // aks-engine. AgentPoolProfileRoleEmpty AgentPoolProfileRole = "" // AgentPoolProfileRoleCompute is the compute role AgentPoolProfileRoleCompute AgentPoolProfileRole = "compute" @@ -230,14 +204,6 @@ const ( DefaultKubernetesCloudProviderRateLimitBucket = 10 ) -const ( - //AzureEdgeDCOSBootstrapDownloadURL is the azure edge CDN download url - AzureEdgeDCOSBootstrapDownloadURL = "https://dcosio.azureedge.net/dcos/%s/bootstrap/%s.bootstrap.tar.xz" - //AzureChinaCloudDCOSBootstrapDownloadURL is the China specific DCOS package download url. - AzureChinaCloudDCOSBootstrapDownloadURL = "https://acsengine.blob.core.chinacloudapi.cn/dcos/%s.bootstrap.tar.xz" - //AzureEdgeDCOSWindowsBootstrapDownloadURL -) - const ( // AzureCniPluginVerLinux specifies version of Azure CNI plugin, which has been mirrored from // https://github.com/Azure/azure-container-networking/releases/download/${AZURE_PLUGIN_VER}/azure-vnet-cni-linux-amd64-${AZURE_PLUGIN_VER}.tgz @@ -253,24 +219,6 @@ const ( ) const ( - // DefaultOpenShiftMasterSubnet is the default value for master subnet for Openshift. - DefaultOpenShiftMasterSubnet = "10.0.0.0/24" - // DefaultOpenShiftFirstConsecutiveStaticIP is the default static ip address for master 0 for Openshift. - DefaultOpenShiftFirstConsecutiveStaticIP = "10.0.0.11" - // DefaultMasterSubnet specifies the default master subnet for DCOS or Swarm - DefaultMasterSubnet = "172.16.0.0/24" - // DefaultFirstConsecutiveStaticIP specifies the static IP address on master 0 for DCOS or Swarm - DefaultFirstConsecutiveStaticIP = "172.16.0.5" - // DefaultSwarmWindowsMasterSubnet specifies the default master subnet for a Swarm Windows cluster - DefaultSwarmWindowsMasterSubnet = "192.168.255.0/24" - // DefaultSwarmWindowsFirstConsecutiveStaticIP specifies the static IP address on master 0 for a Swarm WIndows cluster - DefaultSwarmWindowsFirstConsecutiveStaticIP = "192.168.255.5" - // DefaultDCOSMasterSubnet specifies the default master subnet for a DCOS cluster - DefaultDCOSMasterSubnet = "192.168.255.0/24" - // DefaultDCOSFirstConsecutiveStaticIP specifies the static IP address on master 0 for a DCOS cluster - DefaultDCOSFirstConsecutiveStaticIP = "192.168.255.5" - // DefaultDCOSBootstrapStaticIP specifies the static IP address on bootstrap for a DCOS cluster - DefaultDCOSBootstrapStaticIP = "192.168.255.240" // DefaultKubernetesMasterSubnet specifies the default subnet for masters and agents. // Except when master VMSS is used, this specifies the default subnet for masters. DefaultKubernetesMasterSubnet = "10.240.0.0/16" @@ -380,7 +328,7 @@ const ( const ( //DefaultExtensionsRootURL Root URL for extensions - DefaultExtensionsRootURL = "https://raw.githubusercontent.com/Azure/acs-engine/master/" + DefaultExtensionsRootURL = "https://raw.githubusercontent.com/Azure/aks-engine/master/" ) const ( diff --git a/pkg/api/converterfromagentpoolonlyapi.go b/pkg/api/converterfromagentpoolonlyapi.go index 0772df6a06..01a40495f9 100644 --- a/pkg/api/converterfromagentpoolonlyapi.go +++ b/pkg/api/converterfromagentpoolonlyapi.go @@ -3,9 +3,9 @@ package api import ( "strconv" - "github.com/Azure/acs-engine/pkg/api/agentPoolOnlyApi/v20170831" - "github.com/Azure/acs-engine/pkg/api/agentPoolOnlyApi/v20180331" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/api/agentPoolOnlyApi/v20170831" + "github.com/Azure/aks-engine/pkg/api/agentPoolOnlyApi/v20180331" + "github.com/Azure/aks-engine/pkg/helpers" ) /////////////////////////////////////////////////////////// diff --git a/pkg/api/converterfromagentpoolonlyapi_test.go b/pkg/api/converterfromagentpoolonlyapi_test.go index 208e5c1709..2f8c34ce27 100644 --- a/pkg/api/converterfromagentpoolonlyapi_test.go +++ b/pkg/api/converterfromagentpoolonlyapi_test.go @@ -4,8 +4,8 @@ import ( "strconv" "testing" - "github.com/Azure/acs-engine/pkg/api/agentPoolOnlyApi/v20180331" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/api/agentPoolOnlyApi/v20180331" + "github.com/Azure/aks-engine/pkg/helpers" ) func TestConvertOrchestratorProfileToV20180331AgentPoolOnly(t *testing.T) { diff --git a/pkg/api/converterfromapi.go b/pkg/api/converterfromapi.go index 02ddb1ea6d..c58cf52729 100644 --- a/pkg/api/converterfromapi.go +++ b/pkg/api/converterfromapi.go @@ -2,18 +2,13 @@ package api import ( "fmt" - "regexp" - "strings" + "github.com/Azure/aks-engine/pkg/api/v20160930" + "github.com/Azure/aks-engine/pkg/api/v20170131" + "github.com/Azure/aks-engine/pkg/api/v20170701" + "github.com/Azure/aks-engine/pkg/api/v20170930" + "github.com/Azure/aks-engine/pkg/api/vlabs" "github.com/blang/semver" - - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/api/v20160330" - "github.com/Azure/acs-engine/pkg/api/v20160930" - "github.com/Azure/acs-engine/pkg/api/v20170131" - "github.com/Azure/acs-engine/pkg/api/v20170701" - "github.com/Azure/acs-engine/pkg/api/v20170930" - "github.com/Azure/acs-engine/pkg/api/vlabs" ) /////////////////////////////////////////////////////////// @@ -44,26 +39,6 @@ func ConvertContainerServiceToV20160930(api *ContainerService) *v20160930.Contai return v20160930CS } -// ConvertContainerServiceToV20160330 converts an unversioned ContainerService to a v20160330 ContainerService -func ConvertContainerServiceToV20160330(api *ContainerService) *v20160330.ContainerService { - v20160330CS := &v20160330.ContainerService{} - v20160330CS.ID = api.ID - v20160330CS.Location = api.Location - v20160330CS.Name = api.Name - if api.Plan != nil { - v20160330CS.Plan = &v20160330.ResourcePurchasePlan{} - convertResourcePurchasePlanToV20160330(api.Plan, v20160330CS.Plan) - } - v20160330CS.Tags = map[string]string{} - for k, v := range api.Tags { - v20160330CS.Tags[k] = v - } - v20160330CS.Type = api.Type - v20160330CS.Properties = &v20160330.Properties{} - convertPropertiesToV20160330(api.Properties, v20160330CS.Properties) - return v20160330CS -} - // ConvertContainerServiceToV20170131 converts an unversioned ContainerService to a v20170131 ContainerService func ConvertContainerServiceToV20170131(api *ContainerService) *v20170131.ContainerService { v20170131CS := &v20170131.ContainerService{} @@ -130,12 +105,6 @@ func ConvertOrchestratorVersionProfileToV20170930(api *OrchestratorVersionProfil switch api.OrchestratorType { case Kubernetes: vProfile.OrchestratorType = v20170930.Kubernetes - case DCOS: - vProfile.OrchestratorType = v20170930.DCOS - case Swarm: - vProfile.OrchestratorType = v20170930.Swarm - case SwarmMode: - vProfile.OrchestratorType = v20170930.DockerCE } vProfile.OrchestratorVersion = api.OrchestratorVersion vProfile.Default = api.Default @@ -156,14 +125,6 @@ func ConvertOrchestratorVersionProfileToVLabs(api *OrchestratorVersionProfile) * switch api.OrchestratorType { case Kubernetes: vlabsProfile.OrchestratorType = vlabs.Kubernetes - case DCOS: - vlabsProfile.OrchestratorType = vlabs.DCOS - case Swarm: - vlabsProfile.OrchestratorType = vlabs.Swarm - case SwarmMode: - vlabsProfile.OrchestratorType = vlabs.SwarmMode - case OpenShift: - vlabsProfile.OrchestratorType = vlabs.OpenShift } vlabsProfile.OrchestratorVersion = api.OrchestratorVersion vlabsProfile.Default = api.Default @@ -186,14 +147,6 @@ func convertResourcePurchasePlanToV20160930(api *ResourcePurchasePlan, v20160930 v20160930.Publisher = api.Publisher } -// convertResourcePurchasePlanToV20160330 converts a v20160330 ResourcePurchasePlan to an unversioned ResourcePurchasePlan -func convertResourcePurchasePlanToV20160330(api *ResourcePurchasePlan, v20160330 *v20160330.ResourcePurchasePlan) { - v20160330.Name = api.Name - v20160330.Product = api.Product - v20160330.PromotionCode = api.PromotionCode - v20160330.Publisher = api.Publisher -} - // convertResourcePurchasePlanToV20170131 converts an unversioned ResourcePurchasePlan to a v20170131 ResourcePurchasePlan func convertResourcePurchasePlanToV20170131(api *ResourcePurchasePlan, v20170131 *v20170131.ResourcePurchasePlan) { v20170131.Name = api.Name @@ -229,31 +182,10 @@ func convertPropertiesToV20160930(api *Properties, p *v20160930.Properties) { convertMasterProfileToV20160930(api.MasterProfile, p.MasterProfile) } p.AgentPoolProfiles = []*v20160930.AgentPoolProfile{} - // DCOS conversion logic - if api.OrchestratorProfile.IsDCOS() && len(api.AgentPoolProfiles) == 2 { - var privIndex, pubIndex int - for i, apiProfile := range api.AgentPoolProfiles { - // We added a pool with a "-public" suffix when converting to API model; - // we don't want to include that when converting back to a version-specific model - matched, err := regexp.MatchString(publicAgentPoolSuffix+"$", apiProfile.Name) - if !matched && err == nil { - v20160930Profile := &v20160930.AgentPoolProfile{} - convertAgentPoolProfileToV20160930(apiProfile, v20160930Profile) - p.AgentPoolProfiles = append(p.AgentPoolProfiles, v20160930Profile) - privIndex = i - } else { - pubIndex = i - } - } - // Assign DNS Prefix to private agent pool from public agent pool - p.AgentPoolProfiles[privIndex].DNSPrefix = api.AgentPoolProfiles[pubIndex].DNSPrefix - p.AgentPoolProfiles[privIndex].FQDN = api.AgentPoolProfiles[pubIndex].FQDN - } else { - for _, apiProfile := range api.AgentPoolProfiles { - v20160930Profile := &v20160930.AgentPoolProfile{} - convertAgentPoolProfileToV20160930(apiProfile, v20160930Profile) - p.AgentPoolProfiles = append(p.AgentPoolProfiles, v20160930Profile) - } + for _, apiProfile := range api.AgentPoolProfiles { + v20160930Profile := &v20160930.AgentPoolProfile{} + convertAgentPoolProfileToV20160930(apiProfile, v20160930Profile) + p.AgentPoolProfiles = append(p.AgentPoolProfiles, v20160930Profile) } if api.LinuxProfile != nil { p.LinuxProfile = &v20160930.LinuxProfile{} @@ -281,61 +213,6 @@ func convertPropertiesToV20160930(api *Properties, p *v20160930.Properties) { } } -func convertPropertiesToV20160330(api *Properties, p *v20160330.Properties) { - p.ProvisioningState = v20160330.ProvisioningState(api.ProvisioningState) - if api.OrchestratorProfile != nil { - p.OrchestratorProfile = &v20160330.OrchestratorProfile{} - convertOrchestratorProfileToV20160330(api.OrchestratorProfile, p.OrchestratorProfile) - } - if api.MasterProfile != nil { - p.MasterProfile = &v20160330.MasterProfile{} - convertMasterProfileToV20160330(api.MasterProfile, p.MasterProfile) - } - p.AgentPoolProfiles = []*v20160330.AgentPoolProfile{} - // DCOS conversion logic - if api.OrchestratorProfile.IsDCOS() && len(api.AgentPoolProfiles) == 2 { - var privIndex, pubIndex int - for i, apiProfile := range api.AgentPoolProfiles { - // We added a pool with a "-public" suffix when converting to API model; - // we don't want to include that when converting back to a version-specific model - matched, err := regexp.MatchString(publicAgentPoolSuffix+"$", apiProfile.Name) - if !matched && err == nil { - v20160330Profile := &v20160330.AgentPoolProfile{} - convertAgentPoolProfileToV20160330(apiProfile, v20160330Profile) - p.AgentPoolProfiles = append(p.AgentPoolProfiles, v20160330Profile) - privIndex = i - } else { - pubIndex = i - } - } - // Assign DNS Prefix to private agent pool from public agent pool - p.AgentPoolProfiles[privIndex].DNSPrefix = api.AgentPoolProfiles[pubIndex].DNSPrefix - p.AgentPoolProfiles[privIndex].FQDN = api.AgentPoolProfiles[pubIndex].FQDN - } else { - for _, apiProfile := range api.AgentPoolProfiles { - v20160330Profile := &v20160330.AgentPoolProfile{} - convertAgentPoolProfileToV20160330(apiProfile, v20160330Profile) - p.AgentPoolProfiles = append(p.AgentPoolProfiles, v20160330Profile) - } - } - if api.LinuxProfile != nil { - p.LinuxProfile = &v20160330.LinuxProfile{} - convertLinuxProfileToV20160330(api.LinuxProfile, p.LinuxProfile) - } - if api.WindowsProfile != nil { - p.WindowsProfile = &v20160330.WindowsProfile{} - convertWindowsProfileToV20160330(api.WindowsProfile, p.WindowsProfile) - } - if api.DiagnosticsProfile != nil { - p.DiagnosticsProfile = &v20160330.DiagnosticsProfile{} - convertDiagnosticsProfileToV20160330(api.DiagnosticsProfile, p.DiagnosticsProfile) - } - if api.JumpboxProfile != nil { - p.JumpboxProfile = &v20160330.JumpboxProfile{} - convertJumpboxProfileToV20160330(api.JumpboxProfile, p.JumpboxProfile) - } -} - func convertPropertiesToV20170131(api *Properties, p *v20170131.Properties) { p.ProvisioningState = v20170131.ProvisioningState(api.ProvisioningState) if api.OrchestratorProfile != nil { @@ -347,31 +224,10 @@ func convertPropertiesToV20170131(api *Properties, p *v20170131.Properties) { convertMasterProfileToV20170131(api.MasterProfile, p.MasterProfile) } p.AgentPoolProfiles = []*v20170131.AgentPoolProfile{} - // DCOS conversion logic - if api.OrchestratorProfile.IsDCOS() && len(api.AgentPoolProfiles) == 2 { - var privIndex, pubIndex int - for i, apiProfile := range api.AgentPoolProfiles { - // We added a pool with a "-public" suffix when converting to API model; - // we don't want to include that when converting back to a version-specific model - matched, err := regexp.MatchString(publicAgentPoolSuffix+"$", apiProfile.Name) - if !matched && err == nil { - v20170131Profile := &v20170131.AgentPoolProfile{} - convertAgentPoolProfileToV20170131(apiProfile, v20170131Profile) - p.AgentPoolProfiles = append(p.AgentPoolProfiles, v20170131Profile) - privIndex = i - } else { - pubIndex = i - } - } - // Assign DNS Prefix to private agent pool from public agent pool - p.AgentPoolProfiles[privIndex].DNSPrefix = api.AgentPoolProfiles[pubIndex].DNSPrefix - p.AgentPoolProfiles[privIndex].FQDN = api.AgentPoolProfiles[pubIndex].FQDN - } else { - for _, apiProfile := range api.AgentPoolProfiles { - v20170131Profile := &v20170131.AgentPoolProfile{} - convertAgentPoolProfileToV20170131(apiProfile, v20170131Profile) - p.AgentPoolProfiles = append(p.AgentPoolProfiles, v20170131Profile) - } + for _, apiProfile := range api.AgentPoolProfiles { + v20170131Profile := &v20170131.AgentPoolProfile{} + convertAgentPoolProfileToV20170131(apiProfile, v20170131Profile) + p.AgentPoolProfiles = append(p.AgentPoolProfiles, v20170131Profile) } if api.LinuxProfile != nil { p.LinuxProfile = &v20170131.LinuxProfile{} @@ -496,16 +352,6 @@ func convertLinuxProfileToV20160930(api *LinuxProfile, obj *v20160930.LinuxProfi } } -func convertLinuxProfileToV20160330(api *LinuxProfile, obj *v20160330.LinuxProfile) { - obj.AdminUsername = api.AdminUsername - obj.SSH.PublicKeys = []v20160330.PublicKey{} - for _, d := range api.SSH.PublicKeys { - obj.SSH.PublicKeys = append(obj.SSH.PublicKeys, v20160330.PublicKey{ - KeyData: d.KeyData, - }) - } -} - func convertLinuxProfileToV20170131(api *LinuxProfile, obj *v20170131.LinuxProfile) { obj.AdminUsername = api.AdminUsername obj.SSH.PublicKeys = []v20170131.PublicKey{} @@ -578,11 +424,6 @@ func convertWindowsProfileToV20160930(api *WindowsProfile, v20160930 *v20160930. v20160930.AdminPassword = api.AdminPassword } -func convertWindowsProfileToV20160330(api *WindowsProfile, v20160330 *v20160330.WindowsProfile) { - v20160330.AdminUsername = api.AdminUsername - v20160330.AdminPassword = api.AdminPassword -} - func convertWindowsProfileToV20170131(api *WindowsProfile, v20170131 *v20170131.WindowsProfile) { v20170131.AdminUsername = api.AdminUsername v20170131.AdminPassword = api.AdminPassword @@ -611,35 +452,15 @@ func convertWindowsProfileToVLabs(api *WindowsProfile, vlabsProfile *vlabs.Windo } func convertOrchestratorProfileToV20160930(api *OrchestratorProfile, o *v20160930.OrchestratorProfile) { - if strings.HasPrefix(api.OrchestratorType, v20160930.DCOS) { - o.OrchestratorType = v20160930.DCOS - } else { - o.OrchestratorType = api.OrchestratorType - } -} - -func convertOrchestratorProfileToV20160330(api *OrchestratorProfile, o *v20160330.OrchestratorProfile) { - if strings.HasPrefix(api.OrchestratorType, v20160330.DCOS) { - o.OrchestratorType = v20160330.DCOS - } else { - o.OrchestratorType = api.OrchestratorType - } + o.OrchestratorType = api.OrchestratorType } func convertOrchestratorProfileToV20170131(api *OrchestratorProfile, o *v20170131.OrchestratorProfile) { - if strings.HasPrefix(api.OrchestratorType, v20170131.DCOS) { - o.OrchestratorType = v20170131.DCOS - } else { - o.OrchestratorType = api.OrchestratorType - } + o.OrchestratorType = api.OrchestratorType } func convertOrchestratorProfileToV20170701(api *OrchestratorProfile, o *v20170701.OrchestratorProfile) { - if api.OrchestratorType == SwarmMode { - o.OrchestratorType = v20170701.DockerCE - } else { - o.OrchestratorType = api.OrchestratorType - } + o.OrchestratorType = api.OrchestratorType if api.OrchestratorVersion != "" { o.OrchestratorVersion = api.OrchestratorVersion @@ -651,69 +472,14 @@ func convertOrchestratorProfileToVLabs(api *OrchestratorProfile, o *vlabs.Orches if api.OrchestratorVersion != "" { o.OrchestratorVersion = api.OrchestratorVersion - // Enable using "unstable" as a valid version in the openshift orchestrator. - // Required for progressing on an unreleased version. - if !api.IsOpenShift() || api.OrchestratorVersion != common.OpenShiftVersionUnstable { - sv, _ := semver.Make(o.OrchestratorVersion) - o.OrchestratorRelease = fmt.Sprintf("%d.%d", sv.Major, sv.Minor) - } + sv, _ := semver.Make(o.OrchestratorVersion) + o.OrchestratorRelease = fmt.Sprintf("%d.%d", sv.Major, sv.Minor) } if api.KubernetesConfig != nil { o.KubernetesConfig = &vlabs.KubernetesConfig{} convertKubernetesConfigToVLabs(api.KubernetesConfig, o.KubernetesConfig) } - - if api.OpenShiftConfig != nil { - o.OpenShiftConfig = &vlabs.OpenShiftConfig{} - convertOpenShiftConfigToVLabs(api.OpenShiftConfig, o.OpenShiftConfig) - } - - if api.DcosConfig != nil { - o.DcosConfig = &vlabs.DcosConfig{} - convertDcosConfigToVLabs(api.DcosConfig, o.DcosConfig) - } -} - -func convertOpenShiftConfigToVLabs(api *OpenShiftConfig, vl *vlabs.OpenShiftConfig) { - vl.KubernetesConfig = &vlabs.KubernetesConfig{} - if api.KubernetesConfig != nil { - convertKubernetesConfigToVLabs(api.KubernetesConfig, vl.KubernetesConfig) - } - vl.ClusterUsername = api.ClusterUsername - vl.ClusterPassword = api.ClusterPassword - vl.EnableAADAuthentication = api.EnableAADAuthentication - vl.ConfigBundles = api.ConfigBundles -} - -func convertDcosConfigToVLabs(api *DcosConfig, vl *vlabs.DcosConfig) { - vl.DcosBootstrapURL = api.DcosBootstrapURL - vl.DcosWindowsBootstrapURL = api.DcosWindowsBootstrapURL - - if api.Registry != "" { - vl.Registry = api.Registry - } - - if api.RegistryUser != "" { - vl.RegistryUser = api.RegistryUser - } - - if api.RegistryPass != "" { - vl.RegistryPass = api.RegistryPass - } - vl.DcosRepositoryURL = api.DcosRepositoryURL - vl.DcosClusterPackageListID = api.DcosClusterPackageListID - vl.DcosProviderPackageID = api.DcosProviderPackageID - - if api.BootstrapProfile != nil { - vl.BootstrapProfile = &vlabs.BootstrapProfile{ - VMSize: api.BootstrapProfile.VMSize, - OSDiskSizeGB: api.BootstrapProfile.OSDiskSizeGB, - OAuthEnabled: api.BootstrapProfile.OAuthEnabled, - StaticIP: api.BootstrapProfile.StaticIP, - Subnet: api.BootstrapProfile.Subnet, - } - } } func convertKubernetesConfigToVLabs(api *KubernetesConfig, vlabs *vlabs.KubernetesConfig) { @@ -877,13 +643,6 @@ func convertMasterProfileToV20160930(api *MasterProfile, v20160930 *v20160930.Ma v20160930.SetSubnet(api.Subnet) } -func convertMasterProfileToV20160330(api *MasterProfile, v20160330 *v20160330.MasterProfile) { - v20160330.Count = api.Count - v20160330.DNSPrefix = api.DNSPrefix - v20160330.FQDN = api.FQDN - v20160330.SetSubnet(api.Subnet) -} - func convertMasterProfileToV20170131(api *MasterProfile, v20170131 *v20170131.MasterProfile) { v20170131.Count = api.Count v20170131.DNSPrefix = api.DNSPrefix @@ -965,16 +724,6 @@ func convertAgentPoolProfileToV20160930(api *AgentPoolProfile, p *v20160930.Agen p.SetSubnet(api.Subnet) } -func convertAgentPoolProfileToV20160330(api *AgentPoolProfile, p *v20160330.AgentPoolProfile) { - p.Name = api.Name - p.Count = api.Count - p.VMSize = api.VMSize - p.DNSPrefix = api.DNSPrefix - p.FQDN = api.FQDN - p.OSType = v20160330.OSType(api.OSType) - p.SetSubnet(api.Subnet) -} - func convertAgentPoolProfileToV20170131(api *AgentPoolProfile, p *v20170131.AgentPoolProfile) { p.Name = api.Name p.Count = api.Count @@ -1065,18 +814,6 @@ func convertVMDiagnosticsToV20160930(api *VMDiagnostics, v20160930 *v20160930.VM v20160930.StorageURL = api.StorageURL } -func convertDiagnosticsProfileToV20160330(api *DiagnosticsProfile, dp *v20160330.DiagnosticsProfile) { - if api.VMDiagnostics != nil { - dp.VMDiagnostics = &v20160330.VMDiagnostics{} - convertVMDiagnosticsToV20160330(api.VMDiagnostics, dp.VMDiagnostics) - } -} - -func convertVMDiagnosticsToV20160330(api *VMDiagnostics, v20160330 *v20160330.VMDiagnostics) { - v20160330.Enabled = api.Enabled - v20160330.StorageURL = api.StorageURL -} - func convertDiagnosticsProfileToV20170131(api *DiagnosticsProfile, dp *v20170131.DiagnosticsProfile) { if api.VMDiagnostics != nil { dp.VMDiagnostics = &v20170131.VMDiagnostics{} @@ -1095,12 +832,6 @@ func convertJumpboxProfileToV20160930(api *JumpboxProfile, jb *v20160930.Jumpbox jb.FQDN = api.FQDN } -func convertJumpboxProfileToV20160330(api *JumpboxProfile, jb *v20160330.JumpboxProfile) { - jb.OSType = v20160330.OSType(api.OSType) - jb.DNSPrefix = api.DNSPrefix - jb.FQDN = api.FQDN -} - func convertJumpboxProfileToV20170131(api *JumpboxProfile, jb *v20170131.JumpboxProfile) { jb.OSType = v20170131.OSType(api.OSType) jb.DNSPrefix = api.DNSPrefix diff --git a/pkg/api/converterfromosaapi.go b/pkg/api/converterfromosaapi.go deleted file mode 100644 index 0eece7922f..0000000000 --- a/pkg/api/converterfromosaapi.go +++ /dev/null @@ -1,68 +0,0 @@ -package api - -import ( - "github.com/Azure/acs-engine/pkg/api/osa/vlabs" -) - -// ConvertVLabsOpenShiftClusterToContainerService converts from a -// vlabs.OpenShiftCluster to a ContainerService. -func ConvertVLabsOpenShiftClusterToContainerService(oc *vlabs.OpenShiftCluster) *ContainerService { - cs := &ContainerService{ - ID: oc.ID, - Location: oc.Location, - Name: oc.Name, - Tags: oc.Tags, - Type: oc.Type, - } - - if oc.Plan != nil { - cs.Plan = &ResourcePurchasePlan{ - Name: oc.Plan.Name, - Product: oc.Plan.Product, - PromotionCode: oc.Plan.PromotionCode, - Publisher: oc.Plan.Publisher, - } - } - - if oc.Properties != nil { - cs.Properties = &Properties{ - ProvisioningState: ProvisioningState(oc.Properties.ProvisioningState), - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorVersion: oc.Properties.OpenShiftVersion, - OpenShiftConfig: &OpenShiftConfig{ - PublicHostname: oc.Properties.PublicHostname, - }, - }, - MasterProfile: &MasterProfile{ - FQDN: oc.Properties.FQDN, - }, - ServicePrincipalProfile: &ServicePrincipalProfile{ - ClientID: oc.Properties.ServicePrincipalProfile.ClientID, - Secret: oc.Properties.ServicePrincipalProfile.Secret, - }, - } - - cs.Properties.OrchestratorProfile.OpenShiftConfig.RouterProfiles = make([]OpenShiftRouterProfile, len(oc.Properties.RouterProfiles)) - for i, rp := range oc.Properties.RouterProfiles { - cs.Properties.OrchestratorProfile.OpenShiftConfig.RouterProfiles[i] = OpenShiftRouterProfile{ - Name: rp.Name, - PublicSubdomain: rp.PublicSubdomain, - FQDN: rp.FQDN, - } - } - - cs.Properties.AgentPoolProfiles = make([]*AgentPoolProfile, len(oc.Properties.AgentPoolProfiles)) - for i, app := range oc.Properties.AgentPoolProfiles { - cs.Properties.AgentPoolProfiles[i] = &AgentPoolProfile{ - Name: app.Name, - Count: app.Count, - VMSize: app.VMSize, - OSType: OSType(app.OSType), - VnetSubnetID: app.VnetSubnetID, - Role: AgentPoolProfileRole(app.Role), - } - } - } - - return cs -} diff --git a/pkg/api/converterfromosaapi_test.go b/pkg/api/converterfromosaapi_test.go deleted file mode 100644 index 5f386051c4..0000000000 --- a/pkg/api/converterfromosaapi_test.go +++ /dev/null @@ -1,135 +0,0 @@ -package api - -import ( - "reflect" - "testing" - - "github.com/Azure/acs-engine/pkg/api/osa/vlabs" -) - -var testOpenShiftCluster = &vlabs.OpenShiftCluster{ - ID: "id", - Location: "location", - Name: "name", - Plan: &vlabs.ResourcePurchasePlan{ - Name: "plan.name", - Product: "plan.product", - PromotionCode: "plan.promotionCode", - Publisher: "plan.publisher", - }, - Tags: map[string]string{ - "tags.k1": "v1", - "tags.k2": "v2", - }, - Type: "type", - Properties: &vlabs.Properties{ - ProvisioningState: "properties.provisioningState", - OpenShiftVersion: "properties.openShiftVersion", - PublicHostname: "properties.publicHostname", - FQDN: "properties.fqdn", - RouterProfiles: []vlabs.RouterProfile{ - { - Name: "properties.routerProfiles.0.name", - PublicSubdomain: "properties.routerProfiles.0.publicSubdomain", - FQDN: "properties.routerProfiles.0.fqdn", - }, - { - Name: "properties.routerProfiles.1.name", - PublicSubdomain: "properties.routerProfiles.1.publicSubdomain", - FQDN: "properties.routerProfiles.1.fqdn", - }, - }, - AgentPoolProfiles: []vlabs.AgentPoolProfile{ - { - Name: "properties.agentPoolProfiles.0.name", - Role: "properties.agentPoolProfiles.0.role", - Count: 1, - VMSize: "properties.agentPoolProfiles.0.vmSize", - VnetSubnetID: "properties.agentPoolProfiles.0.vnetSubnetID", - OSType: "properties.agentPoolProfiles.0.osType", - }, - { - Name: "properties.agentPoolProfiles.0.name", - Role: "properties.agentPoolProfiles.0.role", - Count: 2, - VMSize: "properties.agentPoolProfiles.0.vmSize", - VnetSubnetID: "properties.agentPoolProfiles.0.vnetSubnetID", - OSType: "properties.agentPoolProfiles.0.osType", - }, - }, - ServicePrincipalProfile: vlabs.ServicePrincipalProfile{ - ClientID: "properties.servicePrincipalProfile.clientID", - Secret: "properties.servicePrincipalProfile.secret", - }, - }, -} - -var testContainerService = &ContainerService{ - ID: "id", - Location: "location", - Name: "name", - Plan: &ResourcePurchasePlan{ - Name: "plan.name", - Product: "plan.product", - PromotionCode: "plan.promotionCode", - Publisher: "plan.publisher", - }, - Tags: map[string]string{ - "tags.k1": "v1", - "tags.k2": "v2", - }, - Type: "type", - Properties: &Properties{ - ProvisioningState: "properties.provisioningState", - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorVersion: "properties.openShiftVersion", - OpenShiftConfig: &OpenShiftConfig{ - PublicHostname: "properties.publicHostname", - RouterProfiles: []OpenShiftRouterProfile{ - { - Name: "properties.routerProfiles.0.name", - PublicSubdomain: "properties.routerProfiles.0.publicSubdomain", - FQDN: "properties.routerProfiles.0.fqdn", - }, - { - Name: "properties.routerProfiles.1.name", - PublicSubdomain: "properties.routerProfiles.1.publicSubdomain", - FQDN: "properties.routerProfiles.1.fqdn", - }, - }, - }, - }, - MasterProfile: &MasterProfile{ - FQDN: "properties.fqdn", - }, - AgentPoolProfiles: []*AgentPoolProfile{ - { - Name: "properties.agentPoolProfiles.0.name", - Count: 1, - VMSize: "properties.agentPoolProfiles.0.vmSize", - OSType: "properties.agentPoolProfiles.0.osType", - VnetSubnetID: "properties.agentPoolProfiles.0.vnetSubnetID", - Role: "properties.agentPoolProfiles.0.role", - }, - { - Name: "properties.agentPoolProfiles.0.name", - Count: 2, - VMSize: "properties.agentPoolProfiles.0.vmSize", - OSType: "properties.agentPoolProfiles.0.osType", - VnetSubnetID: "properties.agentPoolProfiles.0.vnetSubnetID", - Role: "properties.agentPoolProfiles.0.role", - }, - }, - ServicePrincipalProfile: &ServicePrincipalProfile{ - ClientID: "properties.servicePrincipalProfile.clientID", - Secret: "properties.servicePrincipalProfile.secret", - }, - }, -} - -func TestConvertVLabsOpenShiftClusterToContainerService(t *testing.T) { - cs := ConvertVLabsOpenShiftClusterToContainerService(testOpenShiftCluster) - if !reflect.DeepEqual(cs, testContainerService) { - t.Errorf("ConvertVLabsOpenShiftClusterToContainerService returned unexpected result\n%#v\n", cs) - } -} diff --git a/pkg/api/convertertoagentpoolonlyapi.go b/pkg/api/convertertoagentpoolonlyapi.go index 09076c5df1..da41c72da9 100644 --- a/pkg/api/convertertoagentpoolonlyapi.go +++ b/pkg/api/convertertoagentpoolonlyapi.go @@ -4,11 +4,11 @@ import ( "encoding/json" "strconv" - "github.com/Azure/acs-engine/pkg/api/agentPoolOnlyApi/v20170831" - "github.com/Azure/acs-engine/pkg/api/agentPoolOnlyApi/v20180331" - "github.com/Azure/acs-engine/pkg/api/agentPoolOnlyApi/vlabs" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/api/agentPoolOnlyApi/v20170831" + "github.com/Azure/aks-engine/pkg/api/agentPoolOnlyApi/v20180331" + "github.com/Azure/aks-engine/pkg/api/agentPoolOnlyApi/vlabs" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/helpers" ) /////////////////////////////////////////////////////////// diff --git a/pkg/api/convertertoagentpoolonlyapi_test.go b/pkg/api/convertertoagentpoolonlyapi_test.go index 602b2434a1..cb8d6dcdce 100644 --- a/pkg/api/convertertoagentpoolonlyapi_test.go +++ b/pkg/api/convertertoagentpoolonlyapi_test.go @@ -4,8 +4,8 @@ import ( "strconv" "testing" - "github.com/Azure/acs-engine/pkg/api/agentPoolOnlyApi/v20180331" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/api/agentPoolOnlyApi/v20180331" + "github.com/Azure/aks-engine/pkg/helpers" ) func TestConvertV20180331AgentPoolOnlyOrchestratorProfile(t *testing.T) { diff --git a/pkg/api/convertertoapi.go b/pkg/api/convertertoapi.go index 55300bc030..84f2f3291a 100644 --- a/pkg/api/convertertoapi.go +++ b/pkg/api/convertertoapi.go @@ -1,13 +1,12 @@ package api import ( - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/api/v20160330" - "github.com/Azure/acs-engine/pkg/api/v20160930" - "github.com/Azure/acs-engine/pkg/api/v20170131" - "github.com/Azure/acs-engine/pkg/api/v20170701" - "github.com/Azure/acs-engine/pkg/api/vlabs" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/api/v20160930" + "github.com/Azure/aks-engine/pkg/api/v20170131" + "github.com/Azure/aks-engine/pkg/api/v20170701" + "github.com/Azure/aks-engine/pkg/api/vlabs" + "github.com/Azure/aks-engine/pkg/helpers" ) /////////////////////////////////////////////////////////// @@ -38,26 +37,6 @@ func ConvertV20160930ContainerService(v20160930 *v20160930.ContainerService) *Co return c } -// ConvertV20160330ContainerService converts a v20160330 ContainerService to an unversioned ContainerService -func ConvertV20160330ContainerService(v20160330 *v20160330.ContainerService) *ContainerService { - c := &ContainerService{} - c.ID = v20160330.ID - c.Location = helpers.NormalizeAzureRegion(v20160330.Location) - c.Name = v20160330.Name - if v20160330.Plan != nil { - c.Plan = &ResourcePurchasePlan{} - convertV20160330ResourcePurchasePlan(v20160330.Plan, c.Plan) - } - c.Tags = map[string]string{} - for k, v := range v20160330.Tags { - c.Tags[k] = v - } - c.Type = v20160330.Type - c.Properties = &Properties{} - convertV20160330Properties(v20160330.Properties, c.Properties) - return c -} - // ConvertV20170131ContainerService converts a v20170131 ContainerService to an unversioned ContainerService func ConvertV20170131ContainerService(v20170131 *v20170131.ContainerService) *ContainerService { c := &ContainerService{} @@ -126,14 +105,6 @@ func convertV20160930ResourcePurchasePlan(v20160930 *v20160930.ResourcePurchaseP api.Publisher = v20160930.Publisher } -// convertV20160330ResourcePurchasePlan converts a v20160330 ResourcePurchasePlan to an unversioned ResourcePurchasePlan -func convertV20160330ResourcePurchasePlan(v20160330 *v20160330.ResourcePurchasePlan, api *ResourcePurchasePlan) { - api.Name = v20160330.Name - api.Product = v20160330.Product - api.PromotionCode = v20160330.PromotionCode - api.Publisher = v20160330.Publisher -} - // convertV20170131ResourcePurchasePlan converts a v20170131 ResourcePurchasePlan to an unversioned ResourcePurchasePlan func convertV20170131ResourcePurchasePlan(v20170131 *v20170131.ResourcePurchasePlan, api *ResourcePurchasePlan) { api.Name = v20170131.Name @@ -205,47 +176,6 @@ func convertV20160930Properties(v20160930 *v20160930.Properties, api *Properties api.CustomProfile = &CustomProfile{} convertV20160930CustomProfile(v20160930.CustomProfile, api.CustomProfile) } - if api.OrchestratorProfile.IsDCOS() && len(api.AgentPoolProfiles) == 1 { - addDCOSPublicAgentPool(api) - } -} - -func convertV20160330Properties(v20160330 *v20160330.Properties, api *Properties) { - api.ProvisioningState = ProvisioningState(v20160330.ProvisioningState) - if v20160330.OrchestratorProfile != nil { - api.OrchestratorProfile = &OrchestratorProfile{} - convertV20160330OrchestratorProfile(v20160330.OrchestratorProfile, api.OrchestratorProfile) - } - if v20160330.MasterProfile != nil { - api.MasterProfile = &MasterProfile{} - convertV20160330MasterProfile(v20160330.MasterProfile, api.MasterProfile) - } - api.AgentPoolProfiles = []*AgentPoolProfile{} - for _, p := range v20160330.AgentPoolProfiles { - apiProfile := &AgentPoolProfile{} - convertV20160330AgentPoolProfile(p, apiProfile) - api.AgentPoolProfiles = append(api.AgentPoolProfiles, apiProfile) - - } - if v20160330.LinuxProfile != nil { - api.LinuxProfile = &LinuxProfile{} - convertV20160330LinuxProfile(v20160330.LinuxProfile, api.LinuxProfile) - } - if v20160330.WindowsProfile != nil { - api.WindowsProfile = &WindowsProfile{} - convertV20160330WindowsProfile(v20160330.WindowsProfile, api.WindowsProfile) - } - if v20160330.DiagnosticsProfile != nil { - api.DiagnosticsProfile = &DiagnosticsProfile{} - convertV20160330DiagnosticsProfile(v20160330.DiagnosticsProfile, api.DiagnosticsProfile) - } - if v20160330.JumpboxProfile != nil { - api.JumpboxProfile = &JumpboxProfile{} - convertV20160330JumpboxProfile(v20160330.JumpboxProfile, api.JumpboxProfile) - } - if api.OrchestratorProfile.IsDCOS() && len(api.AgentPoolProfiles) == 1 { - addDCOSPublicAgentPool(api) - } } func convertV20170131Properties(v20170131 *v20170131.Properties, api *Properties) { @@ -295,9 +225,6 @@ func convertV20170131Properties(v20170131 *v20170131.Properties, api *Properties api.CustomProfile = &CustomProfile{} convertV20170131CustomProfile(v20170131.CustomProfile, api.CustomProfile) } - if api.OrchestratorProfile.IsDCOS() && len(api.AgentPoolProfiles) == 1 { - addDCOSPublicAgentPool(api) - } } func convertV20170701Properties(v20170701 *v20170701.Properties, api *Properties) { @@ -361,7 +288,7 @@ func convertVLabsProperties(vlabs *vlabs.Properties, api *Properties, isUpdate b apiProfile := &AgentPoolProfile{} convertVLabsAgentPoolProfile(p, apiProfile) // by default vlabs will use managed disks for all orchestrators but kubernetes as it has encryption at rest. - if !api.OrchestratorProfile.IsKubernetes() && !api.OrchestratorProfile.IsOpenShift() { + if !api.OrchestratorProfile.IsKubernetes() { if len(p.StorageProfile) == 0 { apiProfile.StorageProfile = ManagedDisks } @@ -427,15 +354,6 @@ func convertV20160930LinuxProfile(obj *v20160930.LinuxProfile, api *LinuxProfile } } -func convertV20160330LinuxProfile(v20160330 *v20160330.LinuxProfile, api *LinuxProfile) { - api.AdminUsername = v20160330.AdminUsername - api.SSH.PublicKeys = []PublicKey{} - for _, d := range v20160330.SSH.PublicKeys { - api.SSH.PublicKeys = append(api.SSH.PublicKeys, - PublicKey{KeyData: d.KeyData}) - } -} - func convertV20170131LinuxProfile(v20170131 *v20170131.LinuxProfile, api *LinuxProfile) { api.AdminUsername = v20170131.AdminUsername api.SSH.PublicKeys = []PublicKey{} @@ -507,11 +425,6 @@ func convertV20160930WindowsProfile(v20160930 *v20160930.WindowsProfile, api *Wi api.AdminPassword = v20160930.AdminPassword } -func convertV20160330WindowsProfile(v20160330 *v20160330.WindowsProfile, api *WindowsProfile) { - api.AdminUsername = v20160330.AdminUsername - api.AdminPassword = v20160330.AdminPassword -} - func convertV20170131WindowsProfile(v20170131 *v20170131.WindowsProfile, api *WindowsProfile) { api.AdminUsername = v20170131.AdminUsername api.AdminPassword = v20170131.AdminPassword @@ -543,15 +456,6 @@ func convertV20160930OrchestratorProfile(v20160930 *v20160930.OrchestratorProfil api.OrchestratorType = v20160930.OrchestratorType if api.OrchestratorType == Kubernetes { api.OrchestratorVersion = "1.6.9" - } else if api.OrchestratorType == DCOS { - api.OrchestratorVersion = common.DCOSVersion1Dot9Dot0 - } -} - -func convertV20160330OrchestratorProfile(v20160330 *v20160330.OrchestratorProfile, api *OrchestratorProfile) { - api.OrchestratorType = v20160330.OrchestratorType - if api.OrchestratorType == DCOS { - api.OrchestratorVersion = common.DCOSVersion1Dot9Dot0 } } @@ -559,28 +463,15 @@ func convertV20170131OrchestratorProfile(v20170131 *v20170131.OrchestratorProfil api.OrchestratorType = v20170131.OrchestratorType if api.OrchestratorType == Kubernetes { api.OrchestratorVersion = common.GetSupportedKubernetesVersion("", hasWindows) - } else if api.OrchestratorType == DCOS { - api.OrchestratorVersion = common.DCOSVersion1Dot9Dot0 } } func convertV20170701OrchestratorProfile(v20170701cs *v20170701.OrchestratorProfile, api *OrchestratorProfile, hasWindows bool) { - if v20170701cs.OrchestratorType == v20170701.DockerCE { - api.OrchestratorType = SwarmMode - } else { - api.OrchestratorType = v20170701cs.OrchestratorType - } + api.OrchestratorType = v20170701cs.OrchestratorType switch api.OrchestratorType { case Kubernetes: api.OrchestratorVersion = common.GetSupportedKubernetesVersion(v20170701cs.OrchestratorVersion, hasWindows) - case DCOS: - switch v20170701cs.OrchestratorVersion { - case common.DCOSVersion1Dot10Dot0, common.DCOSVersion1Dot9Dot0, common.DCOSVersion1Dot8Dot8: - api.OrchestratorVersion = v20170701cs.OrchestratorVersion - default: - api.OrchestratorVersion = common.DCOSVersion1Dot9Dot0 - } default: break } @@ -590,27 +481,6 @@ func convertVLabsOrchestratorProfile(vp *vlabs.Properties, api *OrchestratorProf vlabscs := vp.OrchestratorProfile api.OrchestratorType = vlabscs.OrchestratorType switch api.OrchestratorType { - case OpenShift: - if vlabscs.OpenShiftConfig != nil { - api.OpenShiftConfig = &OpenShiftConfig{} - convertVLabsOpenShiftConfig(vlabscs.OpenShiftConfig, api.OpenShiftConfig) - } - // Set api.KubernetesConfig to api.OpenShiftConfig.KubernetesConfig so - // acs-engine can reuse the same code used for generating parameters from - // KubernetesConfig for OpenShiftConfig. - if api.OpenShiftConfig != nil && api.OpenShiftConfig.KubernetesConfig != nil { - api.KubernetesConfig = api.OpenShiftConfig.KubernetesConfig - } - if vlabscs.OrchestratorVersion != common.OpenShiftVersionUnstable { - api.OrchestratorVersion = common.RationalizeReleaseAndVersion( - vlabscs.OrchestratorType, - vlabscs.OrchestratorRelease, - vlabscs.OrchestratorVersion, - isUpdate, - false) - } else { - api.OrchestratorVersion = vlabscs.OrchestratorVersion - } case Kubernetes: if vlabscs.KubernetesConfig != nil { api.KubernetesConfig = &KubernetesConfig{} @@ -623,62 +493,7 @@ func convertVLabsOrchestratorProfile(vp *vlabs.Properties, api *OrchestratorProf vlabscs.OrchestratorVersion, isUpdate, vp.HasWindows()) - case DCOS: - if vlabscs.DcosConfig != nil { - api.DcosConfig = &DcosConfig{} - convertVLabsDcosConfig(vlabscs.DcosConfig, api.DcosConfig) - } - api.OrchestratorVersion = common.RationalizeReleaseAndVersion( - vlabscs.OrchestratorType, - vlabscs.OrchestratorRelease, - vlabscs.OrchestratorVersion, - isUpdate, - false) - } -} - -func convertVLabsDcosConfig(vlabs *vlabs.DcosConfig, api *DcosConfig) { - api.DcosBootstrapURL = vlabs.DcosBootstrapURL - api.DcosWindowsBootstrapURL = vlabs.DcosWindowsBootstrapURL - - if len(vlabs.Registry) > 0 { - api.Registry = vlabs.Registry - } - - if len(vlabs.RegistryUser) > 0 { - api.RegistryUser = vlabs.RegistryUser - } - - if len(vlabs.RegistryPass) > 0 { - api.RegistryPass = vlabs.RegistryPass - } - api.DcosRepositoryURL = vlabs.DcosRepositoryURL - api.DcosClusterPackageListID = vlabs.DcosClusterPackageListID - api.DcosProviderPackageID = vlabs.DcosProviderPackageID - - if vlabs.BootstrapProfile != nil { - api.BootstrapProfile = &BootstrapProfile{ - VMSize: vlabs.BootstrapProfile.VMSize, - OSDiskSizeGB: vlabs.BootstrapProfile.OSDiskSizeGB, - OAuthEnabled: vlabs.BootstrapProfile.OAuthEnabled, - StaticIP: vlabs.BootstrapProfile.StaticIP, - Subnet: vlabs.BootstrapProfile.Subnet, - } - } -} - -func convertVLabsOpenShiftConfig(vlabs *vlabs.OpenShiftConfig, api *OpenShiftConfig) { - // NOTE: This is a hack to avoid breaking the rest of the acs-engine - // code when KubernetesConfig is accessed for various things. We don't - // use anything from it today. Maybe do something cleaner here. - api.KubernetesConfig = &KubernetesConfig{} - if vlabs.KubernetesConfig != nil { - convertVLabsKubernetesConfig(vlabs.KubernetesConfig, api.KubernetesConfig) } - api.ClusterUsername = vlabs.ClusterUsername - api.ClusterPassword = vlabs.ClusterPassword - api.EnableAADAuthentication = vlabs.EnableAADAuthentication - api.ConfigBundles = vlabs.ConfigBundles } func convertVLabsKubernetesConfig(vlabs *vlabs.KubernetesConfig, api *KubernetesConfig) { @@ -872,15 +687,6 @@ func convertV20160930MasterProfile(v20160930 *v20160930.MasterProfile, api *Mast api.VMSize = "Standard_D2_v2" } -func convertV20160330MasterProfile(v20160330 *v20160330.MasterProfile, api *MasterProfile) { - api.Count = v20160330.Count - api.DNSPrefix = v20160330.DNSPrefix - api.FQDN = v20160330.FQDN - api.Subnet = v20160330.GetSubnet() - // Set default VMSize - api.VMSize = "Standard_D2_v2" -} - func convertV20170131MasterProfile(v20170131 *v20170131.MasterProfile, api *MasterProfile) { api.Count = v20170131.Count api.DNSPrefix = v20170131.DNSPrefix @@ -973,20 +779,6 @@ func convertV20160930AgentPoolProfile(v20160930 *v20160930.AgentPoolProfile, ava api.AvailabilityProfile = availabilityProfile } -func convertV20160330AgentPoolProfile(v20160330 *v20160330.AgentPoolProfile, api *AgentPoolProfile) { - api.Name = v20160330.Name - api.Count = v20160330.Count - api.VMSize = v20160330.VMSize - api.DNSPrefix = v20160330.DNSPrefix - if api.DNSPrefix != "" { - // Set default Ports when DNSPrefix specified - api.Ports = []int{80, 443, 8080} - } - api.FQDN = v20160330.FQDN - api.OSType = OSType(v20160330.OSType) - api.Subnet = v20160330.GetSubnet() -} - func convertV20170131AgentPoolProfile(v20170131 *v20170131.AgentPoolProfile, availabilityProfile string, api *AgentPoolProfile) { api.Name = v20170131.Name api.Count = v20170131.Count @@ -1095,18 +887,6 @@ func convertV20160930VMDiagnostics(v20160930 *v20160930.VMDiagnostics, api *VMDi api.StorageURL = v20160930.StorageURL } -func convertV20160330DiagnosticsProfile(v20160330 *v20160330.DiagnosticsProfile, api *DiagnosticsProfile) { - if v20160330.VMDiagnostics != nil { - api.VMDiagnostics = &VMDiagnostics{} - convertV20160330VMDiagnostics(v20160330.VMDiagnostics, api.VMDiagnostics) - } -} - -func convertV20160330VMDiagnostics(v20160330 *v20160330.VMDiagnostics, api *VMDiagnostics) { - api.Enabled = v20160330.Enabled - api.StorageURL = v20160330.StorageURL -} - func convertV20170131DiagnosticsProfile(v20170131 *v20170131.DiagnosticsProfile, api *DiagnosticsProfile) { if v20170131.VMDiagnostics != nil { api.VMDiagnostics = &VMDiagnostics{} @@ -1125,12 +905,6 @@ func convertV20160930JumpboxProfile(v20160930 *v20160930.JumpboxProfile, api *Ju api.FQDN = v20160930.FQDN } -func convertV20160330JumpboxProfile(v20160330 *v20160330.JumpboxProfile, api *JumpboxProfile) { - api.OSType = OSType(v20160330.OSType) - api.DNSPrefix = v20160330.DNSPrefix - api.FQDN = v20160330.FQDN -} - func convertV20170131JumpboxProfile(v20170131 *v20170131.JumpboxProfile, api *JumpboxProfile) { api.OSType = OSType(v20170131.OSType) api.DNSPrefix = v20170131.DNSPrefix @@ -1211,27 +985,3 @@ func convertVLabsAADProfile(vlabs *vlabs.AADProfile, api *AADProfile) { api.AdminGroupID = vlabs.AdminGroupID api.Authenticator = OIDC } - -func addDCOSPublicAgentPool(api *Properties) { - publicPool := &AgentPoolProfile{} - // tag this agent pool with a known suffix string - publicPool.Name = api.AgentPoolProfiles[0].Name + publicAgentPoolSuffix - // move DNS prefix to public pool - publicPool.DNSPrefix = api.AgentPoolProfiles[0].DNSPrefix - api.AgentPoolProfiles[0].DNSPrefix = "" - publicPool.VMSize = api.AgentPoolProfiles[0].VMSize // - use same VMsize for public pool - publicPool.OSType = api.AgentPoolProfiles[0].OSType // - use same OSType for public pool - api.AgentPoolProfiles[0].Ports = nil - for _, port := range [3]int{80, 443, 8080} { - publicPool.Ports = append(publicPool.Ports, port) - } - // - VM Count for public agents is based on the following: - // 1 master => 1 VM - // 3, 5 master => 3 VMsize - if api.MasterProfile.Count == 1 { - publicPool.Count = 1 - } else { - publicPool.Count = 3 - } - api.AgentPoolProfiles = append(api.AgentPoolProfiles, publicPool) -} diff --git a/pkg/api/convertertoapi_test.go b/pkg/api/convertertoapi_test.go index 4bd2c2baba..5b150fa522 100644 --- a/pkg/api/convertertoapi_test.go +++ b/pkg/api/convertertoapi_test.go @@ -3,82 +3,13 @@ package api import ( "testing" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/api/v20170701" + "github.com/Azure/aks-engine/pkg/api/vlabs" "github.com/davecgh/go-spew/spew" "k8s.io/apimachinery/pkg/api/equality" - - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/api/v20170701" - "github.com/Azure/acs-engine/pkg/api/vlabs" ) -func TestAddDCOSPublicAgentPool(t *testing.T) { - expectedNumPools := 2 - for _, masterCount := range [2]int{1, 3} { - profiles := []*AgentPoolProfile{} - profile := makeAgentPoolProfile(1, "agentprivate", "test-dcos-pool", "Standard_D2_v2", "Linux") - profiles = append(profiles, profile) - master := makeMasterProfile(masterCount, "test-dcos", "Standard_D2_v2") - props := getProperties(profiles, master) - expectedPublicPoolName := props.AgentPoolProfiles[0].Name + publicAgentPoolSuffix - expectedPublicDNSPrefix := props.AgentPoolProfiles[0].DNSPrefix - expectedPrivateDNSPrefix := "" - expectedPublicOSType := props.AgentPoolProfiles[0].OSType - expectedPublicVMSize := props.AgentPoolProfiles[0].VMSize - addDCOSPublicAgentPool(props) - if len(props.AgentPoolProfiles) != expectedNumPools { - t.Fatalf("incorrect agent pools count. expected=%d actual=%d", expectedNumPools, len(props.AgentPoolProfiles)) - } - if props.AgentPoolProfiles[1].Name != expectedPublicPoolName { - t.Fatalf("incorrect public pool name. expected=%s actual=%s", expectedPublicPoolName, props.AgentPoolProfiles[1].Name) - } - if props.AgentPoolProfiles[1].DNSPrefix != expectedPublicDNSPrefix { - t.Fatalf("incorrect public pool DNS prefix. expected=%s actual=%s", expectedPublicDNSPrefix, props.AgentPoolProfiles[1].DNSPrefix) - } - if props.AgentPoolProfiles[0].DNSPrefix != expectedPrivateDNSPrefix { - t.Fatalf("incorrect private pool DNS prefix. expected=%s actual=%s", expectedPrivateDNSPrefix, props.AgentPoolProfiles[0].DNSPrefix) - } - if props.AgentPoolProfiles[1].OSType != expectedPublicOSType { - t.Fatalf("incorrect public pool OS type. expected=%s actual=%s", expectedPublicOSType, props.AgentPoolProfiles[1].OSType) - } - if props.AgentPoolProfiles[1].VMSize != expectedPublicVMSize { - t.Fatalf("incorrect public pool VM size. expected=%s actual=%s", expectedPublicVMSize, props.AgentPoolProfiles[1].VMSize) - } - for i, port := range [3]int{80, 443, 8080} { - if props.AgentPoolProfiles[1].Ports[i] != port { - t.Fatalf("incorrect public pool port assignment. expected=%d actual=%d", port, props.AgentPoolProfiles[1].Ports[i]) - } - } - if props.AgentPoolProfiles[1].Count != masterCount { - t.Fatalf("incorrect public pool VM size. expected=%d actual=%d", masterCount, props.AgentPoolProfiles[1].Count) - } - } -} - -func makeAgentPoolProfile(count int, name, dNSPrefix, vMSize string, oSType OSType) *AgentPoolProfile { - return &AgentPoolProfile{ - Name: name, - Count: count, - DNSPrefix: dNSPrefix, - OSType: oSType, - VMSize: vMSize, - } -} - -func makeMasterProfile(count int, dNSPrefix, vMSize string) *MasterProfile { - return &MasterProfile{ - Count: count, - DNSPrefix: "test-dcos", - VMSize: "Standard_D2_v2", - } -} - -func getProperties(profiles []*AgentPoolProfile, master *MasterProfile) *Properties { - return &Properties{ - AgentPoolProfiles: profiles, - MasterProfile: master, - } -} - func TestOrchestratorVersion(t *testing.T) { // test v20170701 v20170701cs := &v20170701.ContainerService{ @@ -163,6 +94,7 @@ func TestKubernetesVlabsDefaults(t *testing.T) { } func TestConvertVLabsOrchestratorProfile(t *testing.T) { + t.Skip("Should be refactored to expect Kubernetes orchestrator.") tests := map[string]struct { props *vlabs.Properties expect *OrchestratorProfile @@ -170,39 +102,12 @@ func TestConvertVLabsOrchestratorProfile(t *testing.T) { "nilOpenShiftConfig": { props: &vlabs.Properties{ OrchestratorProfile: &vlabs.OrchestratorProfile{ - OrchestratorType: OpenShift, + OrchestratorType: Kubernetes, }, }, expect: &OrchestratorProfile{ - OrchestratorType: OpenShift, - OrchestratorVersion: common.OpenShiftDefaultVersion, - }, - }, - "setOpenShiftConfig": { - props: &vlabs.Properties{ - OrchestratorProfile: &vlabs.OrchestratorProfile{ - OrchestratorType: OpenShift, - OpenShiftConfig: &vlabs.OpenShiftConfig{ - KubernetesConfig: &vlabs.KubernetesConfig{ - NetworkPlugin: "azure", - ContainerRuntime: "docker", - }, - }, - }, - }, - expect: &OrchestratorProfile{ - OrchestratorType: OpenShift, - OrchestratorVersion: common.OpenShiftDefaultVersion, - KubernetesConfig: &KubernetesConfig{ - NetworkPlugin: "azure", - ContainerRuntime: "docker", - }, - OpenShiftConfig: &OpenShiftConfig{ - KubernetesConfig: &KubernetesConfig{ - NetworkPlugin: "azure", - ContainerRuntime: "docker", - }, - }, + OrchestratorType: Kubernetes, + OrchestratorVersion: common.KubernetesDefaultRelease, }, }, } diff --git a/pkg/api/convertertoosaapi.go b/pkg/api/convertertoosaapi.go deleted file mode 100644 index 84e21b8230..0000000000 --- a/pkg/api/convertertoosaapi.go +++ /dev/null @@ -1,74 +0,0 @@ -package api - -import ( - "github.com/Azure/acs-engine/pkg/api/osa/vlabs" -) - -// ConvertContainerServiceToVLabsOpenShiftCluster converts from a -// ContainerService to a vlabs.OpenShiftCluster. -func ConvertContainerServiceToVLabsOpenShiftCluster(cs *ContainerService) *vlabs.OpenShiftCluster { - oc := &vlabs.OpenShiftCluster{ - ID: cs.ID, - Location: cs.Location, - Name: cs.Name, - Tags: cs.Tags, - Type: cs.Type, - } - - if cs.Plan != nil { - oc.Plan = &vlabs.ResourcePurchasePlan{ - Name: cs.Plan.Name, - Product: cs.Plan.Product, - PromotionCode: cs.Plan.PromotionCode, - Publisher: cs.Plan.Publisher, - } - } - - if cs.Properties != nil { - oc.Properties = &vlabs.Properties{ - ProvisioningState: vlabs.ProvisioningState(cs.Properties.ProvisioningState), - } - - if cs.Properties.OrchestratorProfile != nil { - oc.Properties.OpenShiftVersion = cs.Properties.OrchestratorProfile.OrchestratorVersion - - if cs.Properties.OrchestratorProfile.OpenShiftConfig != nil { - oc.Properties.PublicHostname = cs.Properties.OrchestratorProfile.OpenShiftConfig.PublicHostname - - oc.Properties.RouterProfiles = make([]vlabs.RouterProfile, len(cs.Properties.OrchestratorProfile.OpenShiftConfig.RouterProfiles)) - for i, rp := range cs.Properties.OrchestratorProfile.OpenShiftConfig.RouterProfiles { - oc.Properties.RouterProfiles[i] = vlabs.RouterProfile{ - Name: rp.Name, - PublicSubdomain: rp.PublicSubdomain, - FQDN: rp.FQDN, - } - } - } - } - - if cs.Properties.MasterProfile != nil { - oc.Properties.FQDN = cs.Properties.MasterProfile.FQDN - } - - if cs.Properties.ServicePrincipalProfile != nil { - oc.Properties.ServicePrincipalProfile = vlabs.ServicePrincipalProfile{ - ClientID: cs.Properties.ServicePrincipalProfile.ClientID, - Secret: cs.Properties.ServicePrincipalProfile.Secret, - } - } - - oc.Properties.AgentPoolProfiles = make([]vlabs.AgentPoolProfile, len(cs.Properties.AgentPoolProfiles)) - for i, app := range cs.Properties.AgentPoolProfiles { - oc.Properties.AgentPoolProfiles[i] = vlabs.AgentPoolProfile{ - Name: app.Name, - Count: app.Count, - VMSize: app.VMSize, - OSType: vlabs.OSType(app.OSType), - VnetSubnetID: app.VnetSubnetID, - Role: vlabs.AgentPoolProfileRole(app.Role), - } - } - } - - return oc -} diff --git a/pkg/api/convertertoosaapi_test.go b/pkg/api/convertertoosaapi_test.go deleted file mode 100644 index 53117ea7d8..0000000000 --- a/pkg/api/convertertoosaapi_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package api - -import ( - "reflect" - "testing" -) - -// testContainerService and testOpenShiftCluster are defined in -// converterfromosaapi_test.go. - -func TestConvertContainerServiceToVLabsOpenShiftCluster(t *testing.T) { - oc := ConvertContainerServiceToVLabsOpenShiftCluster(testContainerService) - if !reflect.DeepEqual(oc, testOpenShiftCluster) { - t.Errorf("ConvertContainerServiceToVLabsOpenShiftCluster returned unexpected result\n%#v\n", oc) - } -} diff --git a/pkg/api/defaults-apiserver.go b/pkg/api/defaults-apiserver.go index 033747cd3b..c313f96f88 100644 --- a/pkg/api/defaults-apiserver.go +++ b/pkg/api/defaults-apiserver.go @@ -3,8 +3,8 @@ package api import ( "strconv" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/helpers" ) func (cs *ContainerService) setAPIServerConfig() { diff --git a/pkg/api/defaults-apiserver_test.go b/pkg/api/defaults-apiserver_test.go index 18652290a0..509e2b8f1a 100644 --- a/pkg/api/defaults-apiserver_test.go +++ b/pkg/api/defaults-apiserver_test.go @@ -3,7 +3,7 @@ package api import ( "testing" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/helpers" ) const defaultTestClusterVer = "1.7.12" diff --git a/pkg/api/defaults-controller-manager.go b/pkg/api/defaults-controller-manager.go index 307d7f1c87..a306186616 100644 --- a/pkg/api/defaults-controller-manager.go +++ b/pkg/api/defaults-controller-manager.go @@ -3,7 +3,7 @@ package api import ( "strconv" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/helpers" ) func (cs *ContainerService) setControllerManagerConfig() { diff --git a/pkg/api/defaults-controller-manager_test.go b/pkg/api/defaults-controller-manager_test.go index a96b5c8474..1d98e3823c 100644 --- a/pkg/api/defaults-controller-manager_test.go +++ b/pkg/api/defaults-controller-manager_test.go @@ -3,7 +3,7 @@ package api import ( "testing" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/helpers" ) func TestControllerManagerConfigEnableRbac(t *testing.T) { diff --git a/pkg/api/defaults-kubelet.go b/pkg/api/defaults-kubelet.go index df2857c995..c023778f71 100644 --- a/pkg/api/defaults-kubelet.go +++ b/pkg/api/defaults-kubelet.go @@ -4,8 +4,8 @@ import ( "strconv" "strings" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/helpers" ) func (cs *ContainerService) setKubeletConfig() { diff --git a/pkg/api/defaults-kubelet_test.go b/pkg/api/defaults-kubelet_test.go index b9a03de885..5381b376e1 100644 --- a/pkg/api/defaults-kubelet_test.go +++ b/pkg/api/defaults-kubelet_test.go @@ -4,7 +4,7 @@ import ( "strconv" "testing" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/helpers" ) func TestKubeletConfigDefaults(t *testing.T) { diff --git a/pkg/api/defaults-openshift-certs.go b/pkg/api/defaults-openshift-certs.go deleted file mode 100644 index bbe8359366..0000000000 --- a/pkg/api/defaults-openshift-certs.go +++ /dev/null @@ -1,96 +0,0 @@ -package api - -import ( - "fmt" - "net" - - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/openshift/certgen/release39" - "github.com/Azure/acs-engine/pkg/openshift/certgen/unstable" -) - -// setOpenShiftSetDefaultCerts sets default certificate and configuration properties in the -// openshift orchestrator. -func setOpenShiftSetDefaultCerts(a *Properties, orchestratorName, clusterID string) (bool, []net.IP, error) { - if len(a.OrchestratorProfile.OpenShiftConfig.ConfigBundles["master"]) > 0 && - len(a.OrchestratorProfile.OpenShiftConfig.ConfigBundles["bootstrap"]) > 0 { - return true, nil, nil - } - if a.OrchestratorProfile.OpenShiftConfig.ConfigBundles == nil { - a.OrchestratorProfile.OpenShiftConfig.ConfigBundles = make(map[string][]byte) - } - - var err error - - var masterBundle, nodeBundle []byte - - switch a.OrchestratorProfile.OrchestratorVersion { - case common.OpenShiftVersion3Dot9Dot0: - c := createR39Config(a, orchestratorName, clusterID) - masterBundle, nodeBundle, err = release39.OpenShiftSetDefaultCerts(c) - default: - c := createUnstableReleaseConfig(a, orchestratorName, clusterID) - masterBundle, nodeBundle, err = unstable.OpenShiftSetDefaultCerts(c) - } - - if err != nil { - return false, nil, err - } - - a.OrchestratorProfile.OpenShiftConfig.ConfigBundles["master"] = masterBundle - a.OrchestratorProfile.OpenShiftConfig.ConfigBundles["bootstrap"] = nodeBundle - - return true, nil, nil -} - -func createR39Config(a *Properties, orchestratorName, clusterID string) *release39.Config { - return &release39.Config{ - Master: &release39.Master{ - Hostname: fmt.Sprintf("%s-master-%s-0", orchestratorName, clusterID), - IPs: []net.IP{ - net.ParseIP(a.MasterProfile.FirstConsecutiveStaticIP), - }, - Port: 8443, - }, - ExternalMasterHostname: fmt.Sprintf("%s.%s.cloudapp.azure.com", a.MasterProfile.DNSPrefix, a.AzProfile.Location), - ClusterUsername: a.OrchestratorProfile.OpenShiftConfig.ClusterUsername, - ClusterPassword: a.OrchestratorProfile.OpenShiftConfig.ClusterPassword, - EnableAADAuthentication: a.OrchestratorProfile.OpenShiftConfig.EnableAADAuthentication, - AzureConfig: release39.AzureConfig{ - TenantID: a.AzProfile.TenantID, - SubscriptionID: a.AzProfile.SubscriptionID, - AADClientID: a.ServicePrincipalProfile.ClientID, - AADClientSecret: a.ServicePrincipalProfile.Secret, - ResourceGroup: a.AzProfile.ResourceGroup, - Location: a.AzProfile.Location, - SecurityGroupName: fmt.Sprintf("%s-master-%s-nsg", orchestratorName, clusterID), - PrimaryAvailabilitySetName: fmt.Sprintf("compute-availabilityset-%s", clusterID), - }, - } -} - -func createUnstableReleaseConfig(a *Properties, orchestratorName, clusterID string) *unstable.Config { - return &unstable.Config{ - Master: &unstable.Master{ - Hostname: fmt.Sprintf("%s-master-%s-0", orchestratorName, clusterID), - IPs: []net.IP{ - net.ParseIP(a.MasterProfile.FirstConsecutiveStaticIP), - }, - Port: 8443, - }, - ExternalMasterHostname: fmt.Sprintf("%s.%s.cloudapp.azure.com", a.MasterProfile.DNSPrefix, a.AzProfile.Location), - ClusterUsername: a.OrchestratorProfile.OpenShiftConfig.ClusterUsername, - ClusterPassword: a.OrchestratorProfile.OpenShiftConfig.ClusterPassword, - EnableAADAuthentication: a.OrchestratorProfile.OpenShiftConfig.EnableAADAuthentication, - AzureConfig: unstable.AzureConfig{ - TenantID: a.AzProfile.TenantID, - SubscriptionID: a.AzProfile.SubscriptionID, - AADClientID: a.ServicePrincipalProfile.ClientID, - AADClientSecret: a.ServicePrincipalProfile.Secret, - ResourceGroup: a.AzProfile.ResourceGroup, - Location: a.AzProfile.Location, - SecurityGroupName: fmt.Sprintf("%s-master-%s-nsg", orchestratorName, clusterID), - PrimaryAvailabilitySetName: fmt.Sprintf("compute-availabilityset-%s", clusterID), - }, - } -} diff --git a/pkg/api/defaults.go b/pkg/api/defaults.go index 4335d03221..0236f72f85 100644 --- a/pkg/api/defaults.go +++ b/pkg/api/defaults.go @@ -11,9 +11,8 @@ import ( "strconv" "strings" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/helpers" - "github.com/blang/semver" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/helpers" "github.com/pkg/errors" ) @@ -237,32 +236,6 @@ func (cs *ContainerService) setOrchestratorDefaults(isUpdate bool) { cs.setAPIServerConfig() // Configure scheduler cs.setSchedulerConfig() - - case DCOS: - if o.DcosConfig == nil { - o.DcosConfig = &DcosConfig{} - } - dcosSemVer, _ := semver.Make(o.OrchestratorVersion) - dcosBootstrapSemVer, _ := semver.Make(common.DCOSVersion1Dot11Dot0) - if !dcosSemVer.LT(dcosBootstrapSemVer) { - if o.DcosConfig.BootstrapProfile == nil { - o.DcosConfig.BootstrapProfile = &BootstrapProfile{} - } - if len(o.DcosConfig.BootstrapProfile.VMSize) == 0 { - o.DcosConfig.BootstrapProfile.VMSize = "Standard_D2s_v3" - } - } - case OpenShift: - kc := a.OrchestratorProfile.OpenShiftConfig.KubernetesConfig - if kc == nil { - kc = &KubernetesConfig{} - } - if kc.ContainerRuntime == "" { - kc.ContainerRuntime = DefaultContainerRuntime - } - if kc.NetworkPlugin == "" { - kc.NetworkPlugin = DefaultNetworkPlugin - } } } @@ -281,8 +254,6 @@ func (p *Properties) setMasterProfileDefaults(isUpgrade bool) { if p.MasterProfile.Distro == "" { if p.OrchestratorProfile.IsKubernetes() { p.MasterProfile.Distro = AKS - } else if !p.OrchestratorProfile.IsOpenShift() { - p.MasterProfile.Distro = Ubuntu } } // set default to VMAS for now @@ -317,34 +288,6 @@ func (p *Properties) setMasterProfileDefaults(isUpgrade bool) { } } } - } else if p.OrchestratorProfile.OrchestratorType == OpenShift { - p.MasterProfile.Subnet = DefaultOpenShiftMasterSubnet - if !isUpgrade || len(p.MasterProfile.FirstConsecutiveStaticIP) == 0 { - p.MasterProfile.FirstConsecutiveStaticIP = DefaultOpenShiftFirstConsecutiveStaticIP - } - } else if p.OrchestratorProfile.OrchestratorType == DCOS { - p.MasterProfile.Subnet = DefaultDCOSMasterSubnet - // FirstConsecutiveStaticIP is not reset if it is upgrade and some value already exists - if !isUpgrade || len(p.MasterProfile.FirstConsecutiveStaticIP) == 0 { - p.MasterProfile.FirstConsecutiveStaticIP = DefaultDCOSFirstConsecutiveStaticIP - } - if p.OrchestratorProfile.DcosConfig != nil && p.OrchestratorProfile.DcosConfig.BootstrapProfile != nil { - if !isUpgrade || len(p.OrchestratorProfile.DcosConfig.BootstrapProfile.StaticIP) == 0 { - p.OrchestratorProfile.DcosConfig.BootstrapProfile.StaticIP = DefaultDCOSBootstrapStaticIP - } - } - } else if p.HasWindows() { - p.MasterProfile.Subnet = DefaultSwarmWindowsMasterSubnet - // FirstConsecutiveStaticIP is not reset if it is upgrade and some value already exists - if !isUpgrade || len(p.MasterProfile.FirstConsecutiveStaticIP) == 0 { - p.MasterProfile.FirstConsecutiveStaticIP = DefaultSwarmWindowsFirstConsecutiveStaticIP - } - } else { - p.MasterProfile.Subnet = DefaultMasterSubnet - // FirstConsecutiveStaticIP is not reset if it is upgrade and some value already exists - if !isUpgrade || len(p.MasterProfile.FirstConsecutiveStaticIP) == 0 { - p.MasterProfile.FirstConsecutiveStaticIP = DefaultFirstConsecutiveStaticIP - } } } @@ -407,8 +350,7 @@ func (p *Properties) setAgentProfileDefaults(isUpgrade, isScale bool) { if p.MasterProfile != nil && !p.MasterProfile.IsCustomVNET() { subnetCounter := 0 for _, profile := range p.AgentPoolProfiles { - if p.OrchestratorProfile.OrchestratorType == Kubernetes || - p.OrchestratorProfile.OrchestratorType == OpenShift { + if p.OrchestratorProfile.OrchestratorType == Kubernetes { if !p.MasterProfile.IsVirtualMachineScaleSets() { profile.Subnet = p.MasterProfile.Subnet } @@ -450,7 +392,7 @@ func (p *Properties) setAgentProfileDefaults(isUpgrade, isScale bool) { profile.Distro = AKS } } - } else if !p.OrchestratorProfile.IsOpenShift() { + } else { profile.Distro = Ubuntu } // Ensure distro is set properly for N Series SKUs, because @@ -513,10 +455,6 @@ func (p *Properties) setHostedMasterProfileDefaults() { } func (p *Properties) setDefaultCerts() (bool, []net.IP, error) { - if p.MasterProfile != nil && p.OrchestratorProfile.OrchestratorType == OpenShift { - return setOpenShiftSetDefaultCerts(p, DefaultOpenshiftOrchestratorName, p.GetClusterID()) - } - if p.MasterProfile == nil || p.OrchestratorProfile.OrchestratorType != Kubernetes { return false, nil, nil } diff --git a/pkg/api/defaults_test.go b/pkg/api/defaults_test.go index ad3dc3b0de..1e1e803522 100644 --- a/pkg/api/defaults_test.go +++ b/pkg/api/defaults_test.go @@ -7,7 +7,7 @@ import ( "reflect" "testing" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/helpers" ) func TestCertsAlreadyPresent(t *testing.T) { @@ -761,34 +761,6 @@ func TestSetComponentsNetworkDefaults(t *testing.T) { }, AKS, }, - { - "default_openshift", - OrchestratorProfile{ - OrchestratorType: OpenShift, - }, - "", - }, - { - "default_swarm", - OrchestratorProfile{ - OrchestratorType: Swarm, - }, - Ubuntu, - }, - { - "default_swarmmode", - OrchestratorProfile{ - OrchestratorType: SwarmMode, - }, - Ubuntu, - }, - { - "default_dcos", - OrchestratorProfile{ - OrchestratorType: DCOS, - }, - Ubuntu, - }, } for _, test := range tests { @@ -968,7 +940,7 @@ func TestAKSDockerEngineDistro(t *testing.T) { t.Fatalf("Expected %s distro for D-series pool, got %s instead", AKS, properties.AgentPoolProfiles[1].Distro) } if properties.AgentPoolProfiles[2].Distro != Ubuntu { - t.Fatalf("Expected %s distro for D-series pool, got %s instead", Ubuntu, properties.AgentPoolProfiles[2].Distro) + t.Fatalf("Expected %s distro for N-series pool, got %s instead", Ubuntu, properties.AgentPoolProfiles[2].Distro) } if properties.AgentPoolProfiles[3].Distro != Ubuntu { t.Fatalf("Expected %s distro for D-series pool, got %s instead", Ubuntu, properties.AgentPoolProfiles[3].Distro) @@ -1229,81 +1201,6 @@ func TestSetCertDefaults(t *testing.T) { } -func TestSetOpenShiftCertDefaults(t *testing.T) { - cs := &ContainerService{ - Properties: &Properties{ - AzProfile: &AzProfile{ - TenantID: "sampleTenantID", - SubscriptionID: "foobarsubscription", - ResourceGroup: "sampleRG", - Location: "westus2", - }, - ServicePrincipalProfile: &ServicePrincipalProfile{ - ClientID: "barClientID", - Secret: "bazSecret", - }, - MasterProfile: &MasterProfile{ - Count: 1, - DNSPrefix: "myprefix1", - VMSize: "Standard_DS2_v2", - }, - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: OpenShift, - OrchestratorVersion: "3.9.0", - OpenShiftConfig: &OpenShiftConfig{}, - }, - }, - } - - cs.Properties.setMasterProfileDefaults(false) - - result, _, err := cs.Properties.setDefaultCerts() - if !result { - t.Error("expected setOpenShiftDefaultCerts to return true") - } - - if err != nil { - t.Errorf("unexpected error thrown while executing setOpenShiftDefaultCerts %s", err.Error()) - } - - cs = &ContainerService{ - Properties: &Properties{ - AzProfile: &AzProfile{ - TenantID: "sampleTenantID", - SubscriptionID: "foobarsubscription", - ResourceGroup: "sampleRG", - Location: "westus2", - }, - ServicePrincipalProfile: &ServicePrincipalProfile{ - ClientID: "barClientID", - Secret: "bazSecret", - }, - MasterProfile: &MasterProfile{ - Count: 1, - DNSPrefix: "myprefix1", - VMSize: "Standard_DS2_v2", - AvailabilityProfile: VirtualMachineScaleSets, - }, - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: OpenShift, - OrchestratorVersion: "3.7.0", - OpenShiftConfig: &OpenShiftConfig{}, - }, - }, - } - - cs.Properties.setMasterProfileDefaults(false) - result, _, err = cs.Properties.setDefaultCerts() - - if !result { - t.Error("expected setOpenShiftDefaultCerts to return true") - } - - if err != nil { - t.Errorf("unexpected error thrown while executing setOpenShiftDefaultCerts %s", err.Error()) - } -} - func getMockBaseContainerService(orchestratorVersion string) ContainerService { mockAPIProperties := getMockAPIProperties(orchestratorVersion) return ContainerService{ diff --git a/pkg/api/k8s_versions.go b/pkg/api/k8s_versions.go index 80f381ae58..2e7c4aac65 100644 --- a/pkg/api/k8s_versions.go +++ b/pkg/api/k8s_versions.go @@ -4,7 +4,7 @@ import ( "strconv" "strings" - "github.com/Azure/acs-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/api/common" ) // k8sComponentVersions defines "best known-working" component versions for each minor version of k8s diff --git a/pkg/api/mocks.go b/pkg/api/mocks.go index 097c1357b1..98eb74f0e0 100644 --- a/pkg/api/mocks.go +++ b/pkg/api/mocks.go @@ -1,7 +1,7 @@ package api import ( - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/helpers" "github.com/satori/go.uuid" ) diff --git a/pkg/api/orchestrators.go b/pkg/api/orchestrators.go index 5a9549ead8..5c8849de58 100644 --- a/pkg/api/orchestrators.go +++ b/pkg/api/orchestrators.go @@ -4,9 +4,9 @@ import ( "strconv" "strings" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/api/v20170930" - "github.com/Azure/acs-engine/pkg/api/vlabs" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/api/v20170930" + "github.com/Azure/aks-engine/pkg/api/vlabs" "github.com/blang/semver" "github.com/pkg/errors" ) @@ -19,17 +19,9 @@ var versionsMap map[string][]string func init() { funcmap = map[string]orchestratorsFunc{ Kubernetes: kubernetesInfo, - DCOS: dcosInfo, - Swarm: swarmInfo, - SwarmMode: dockerceInfo, - OpenShift: openShiftInfo, } versionsMap = map[string][]string{ Kubernetes: common.GetAllSupportedKubernetesVersions(true, false), - DCOS: common.GetAllSupportedDCOSVersions(), - Swarm: common.GetAllSupportedSwarmVersions(), - SwarmMode: common.GetAllSupportedDockerCEVersions(), - OpenShift: common.GetAllSupportedOpenShiftVersions(), } } @@ -37,14 +29,6 @@ func validate(orchestrator, version string) (string, error) { switch { case strings.EqualFold(orchestrator, Kubernetes): return Kubernetes, nil - case strings.EqualFold(orchestrator, DCOS): - return DCOS, nil - case strings.EqualFold(orchestrator, Swarm): - return Swarm, nil - case strings.EqualFold(orchestrator, SwarmMode): - return SwarmMode, nil - case strings.EqualFold(orchestrator, OpenShift): - return OpenShift, nil case orchestrator == "": if version != "" { return "", errors.Errorf("Must specify orchestrator for version '%s'", version) @@ -123,7 +107,7 @@ func GetOrchestratorVersionProfile(orch *OrchestratorProfile, hasWindows bool) ( return nil, errors.New("Missing Orchestrator Version") } switch orch.OrchestratorType { - case Kubernetes, DCOS: + case Kubernetes: arr, err := funcmap[orch.OrchestratorType](orch, hasWindows) if err != nil { return nil, err @@ -219,145 +203,3 @@ func getKubernetesAvailableUpgradeVersions(orchestratorVersion string, supported return []string{}, nil } - -func dcosInfo(csOrch *OrchestratorProfile, hasWindows bool) ([]*OrchestratorVersionProfile, error) { - orchs := []*OrchestratorVersionProfile{} - if csOrch.OrchestratorVersion == "" { - // get info for all supported versions - for _, ver := range common.AllDCOSSupportedVersions { - upgrades, err := dcosUpgrades(&OrchestratorProfile{OrchestratorVersion: ver}) - if err != nil { - return nil, err - } - orchs = append(orchs, - &OrchestratorVersionProfile{ - OrchestratorProfile: OrchestratorProfile{ - OrchestratorType: DCOS, - OrchestratorVersion: ver, - }, - Default: ver == common.DCOSDefaultVersion, - Upgrades: upgrades, - }) - } - } else { - if !isVersionSupported(csOrch) { - return nil, errors.Errorf("DCOS version %s is not supported", csOrch.OrchestratorVersion) - } - - // get info for the specified version - upgrades, err := dcosUpgrades(csOrch) - if err != nil { - return nil, err - } - orchs = append(orchs, - &OrchestratorVersionProfile{ - OrchestratorProfile: OrchestratorProfile{ - OrchestratorType: DCOS, - OrchestratorVersion: csOrch.OrchestratorVersion, - }, - Default: csOrch.OrchestratorVersion == common.DCOSDefaultVersion, - Upgrades: upgrades, - }) - } - return orchs, nil -} - -func dcosUpgrades(csOrch *OrchestratorProfile) ([]*OrchestratorProfile, error) { - ret := []*OrchestratorProfile{} - - switch csOrch.OrchestratorVersion { - case common.DCOSVersion1Dot11Dot0: - ret = append(ret, &OrchestratorProfile{ - OrchestratorType: DCOS, - OrchestratorVersion: common.DCOSVersion1Dot11Dot2, - }) - } - return ret, nil -} - -func swarmInfo(csOrch *OrchestratorProfile, hasWindows bool) ([]*OrchestratorVersionProfile, error) { - if csOrch.OrchestratorVersion == "" { - return []*OrchestratorVersionProfile{ - { - OrchestratorProfile: OrchestratorProfile{ - OrchestratorType: Swarm, - OrchestratorVersion: SwarmVersion, - }, - }, - }, nil - } - - if !isVersionSupported(csOrch) { - return nil, errors.Errorf("Swarm version %s is not supported", csOrch.OrchestratorVersion) - } - return []*OrchestratorVersionProfile{ - { - OrchestratorProfile: OrchestratorProfile{ - OrchestratorType: Swarm, - OrchestratorVersion: csOrch.OrchestratorVersion, - }, - }, - }, nil -} - -func dockerceInfo(csOrch *OrchestratorProfile, hasWindows bool) ([]*OrchestratorVersionProfile, error) { - - if csOrch.OrchestratorVersion == "" { - return []*OrchestratorVersionProfile{ - { - OrchestratorProfile: OrchestratorProfile{ - OrchestratorType: SwarmMode, - OrchestratorVersion: DockerCEVersion, - }, - }, - }, nil - } - - if !isVersionSupported(csOrch) { - return nil, errors.Errorf("Docker CE version %s is not supported", csOrch.OrchestratorVersion) - } - return []*OrchestratorVersionProfile{ - { - OrchestratorProfile: OrchestratorProfile{ - OrchestratorType: SwarmMode, - OrchestratorVersion: csOrch.OrchestratorVersion, - }, - }, - }, nil -} - -func openShiftInfo(csOrch *OrchestratorProfile, hasWindows bool) ([]*OrchestratorVersionProfile, error) { - orchs := []*OrchestratorVersionProfile{} - if csOrch.OrchestratorVersion == "" { - // get info for all supported versions - for _, ver := range common.GetAllSupportedOpenShiftVersions() { - if ver == common.OpenShiftVersionUnstable { - continue - } - // TODO: populate OrchestratorVersionProfile.Upgrades - orchs = append(orchs, - &OrchestratorVersionProfile{ - OrchestratorProfile: OrchestratorProfile{ - OrchestratorType: OpenShift, - OrchestratorVersion: ver, - }, - Default: ver == common.OpenShiftDefaultVersion, - }) - } - } else { - if !isVersionSupported(csOrch) { - return nil, errors.Errorf("OpenShift version %s is not supported", csOrch.OrchestratorVersion) - } - - // TODO: populate OrchestratorVersionProfile.Upgrades - orchs = append(orchs, - &OrchestratorVersionProfile{ - OrchestratorProfile: OrchestratorProfile{ - OrchestratorType: OpenShift, - OrchestratorVersion: csOrch.OrchestratorVersion, - }, - Default: csOrch.OrchestratorVersion == common.OpenShiftDefaultVersion, - }) - } - return orchs, nil -} diff --git a/pkg/api/orchestrators_test.go b/pkg/api/orchestrators_test.go index 44ee195522..320a2f91de 100644 --- a/pkg/api/orchestrators_test.go +++ b/pkg/api/orchestrators_test.go @@ -3,7 +3,7 @@ package api import ( "testing" - "github.com/Azure/acs-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/api/common" "github.com/blang/semver" . "github.com/onsi/gomega" ) @@ -78,14 +78,8 @@ func TestGetOrchestratorVersionProfileListV20170930(t *testing.T) { // v20170930 - all orchestrators list, e := GetOrchestratorVersionProfileListV20170930("", "") Expect(e).To(BeNil()) - numSwarmVersions := 1 - numDockerCEVersions := 1 - totalNumVersions := numSwarmVersions + - numDockerCEVersions + - len(common.GetAllSupportedKubernetesVersions(false, false)) + - len(common.AllDCOSSupportedVersions) + - len(common.GetAllSupportedOpenShiftVersions()) - 1 + totalNumVersions := len(common.GetAllSupportedKubernetesVersions(false, false)) Expect(len(list.Properties.Orchestrators)).To(Equal(totalNumVersions)) @@ -121,125 +115,6 @@ func TestKubernetesInfo(t *testing.T) { } -func TestOpenshiftInfo(t *testing.T) { - RegisterTestingT(t) - - invalid := []string{ - "invalid number", - "invalid.number", - "a4.b7.c3", - "31.29.", - ".17.02", - "43.156.89.", - "1.2.a", - "3.8.9", - "3.9.2"} - - for _, v := range invalid { - csOrch := &OrchestratorProfile{ - OrchestratorType: OpenShift, - OrchestratorVersion: v, - } - - _, e := openShiftInfo(csOrch, false) - Expect(e).NotTo(BeNil()) - } - - // test good value - csOrch := &OrchestratorProfile{ - OrchestratorType: OpenShift, - OrchestratorVersion: common.OpenShiftDefaultVersion, - } - - _, e := openShiftInfo(csOrch, false) - Expect(e).To(BeNil()) -} - -func TestDcosInfo(t *testing.T) { - RegisterTestingT(t) - invalid := []string{ - "invalid number", - "invalid.number", - "a4.b7.c3", - "31.29.", - ".17.02", - "43.156.89.", - "1.2.a"} - - for _, v := range invalid { - csOrch := &OrchestratorProfile{ - OrchestratorType: DCOS, - OrchestratorVersion: v, - } - - _, e := dcosInfo(csOrch, false) - Expect(e).NotTo(BeNil()) - } - - // test good value - csOrch := &OrchestratorProfile{ - OrchestratorType: DCOS, - OrchestratorVersion: common.DCOSDefaultVersion, - } - - _, e := dcosInfo(csOrch, false) - Expect(e).To(BeNil()) -} - -func TestSwarmInfo(t *testing.T) { - RegisterTestingT(t) - invalid := []string{ - "swarm:1.1.1", - "swarm:1.1.2", - } - - for _, v := range invalid { - csOrch := &OrchestratorProfile{ - OrchestratorType: Swarm, - OrchestratorVersion: v, - } - - _, e := swarmInfo(csOrch, false) - Expect(e).NotTo(BeNil()) - } - - // test good value - csOrch := &OrchestratorProfile{ - OrchestratorType: Swarm, - OrchestratorVersion: common.SwarmVersion, - } - - _, e := swarmInfo(csOrch, false) - Expect(e).To(BeNil()) -} - -func TestDockerceInfoInfo(t *testing.T) { - RegisterTestingT(t) - invalid := []string{ - "17.02.1", - "43.156.89", - } - - for _, v := range invalid { - csOrch := &OrchestratorProfile{ - OrchestratorType: SwarmMode, - OrchestratorVersion: v, - } - - _, e := dockerceInfo(csOrch, false) - Expect(e).NotTo(BeNil()) - } - - // test good value - csOrch := &OrchestratorProfile{ - OrchestratorType: SwarmMode, - OrchestratorVersion: common.DockerCEVersion, - } - - _, e := dockerceInfo(csOrch, false) - Expect(e).To(BeNil()) -} - func TestGetKubernetesAvailableUpgradeVersions(t *testing.T) { RegisterTestingT(t) cases := []struct { diff --git a/pkg/api/osa/vlabs/types.go b/pkg/api/osa/vlabs/types.go deleted file mode 100644 index 9a24e7efba..0000000000 --- a/pkg/api/osa/vlabs/types.go +++ /dev/null @@ -1,133 +0,0 @@ -package vlabs - -// OpenShiftCluster complies with the ARM model of resource definition in a JSON -// template. -type OpenShiftCluster struct { - ID string `json:"id,omitempty"` - Location string `json:"location,omitempty"` - Name string `json:"name,omitempty"` - Plan *ResourcePurchasePlan `json:"plan,omitempty"` - Tags map[string]string `json:"tags,omitempty"` - Type string `json:"type,omitempty"` - Properties *Properties `json:"properties,omitempty"` -} - -// ResourcePurchasePlan defines the resource plan as required by ARM for billing -// purposes. -type ResourcePurchasePlan struct { - Name string `json:"name,omitempty"` - Product string `json:"product,omitempty"` - PromotionCode string `json:"promotionCode,omitempty"` - Publisher string `json:"publisher,omitempty"` -} - -// Properties represents the cluster definition. -type Properties struct { - // ProvisioningState (out): current state of the OSA resource. - ProvisioningState ProvisioningState `json:"provisioningState,omitempty"` - - // OpenShiftVersion (in): OpenShift version to be created/updated, e.g. - // `v3.10`. - OpenShiftVersion string `json:"openShiftVersion,omitempty"` - - // PublicHostname (in,optional): Optional user-specified FQDN for OpenShift - // API server. If specified, after OSA cluster creation, user must create a - // PublicHostname CNAME record forwarding to the returned FQDN value. - PublicHostname string `json:"publicHostname,omitempty"` - - // FQDN (out): Auto-allocated FQDN for OpenShift API server. - FQDN string `json:"fqdn,omitempty"` - - // RouterProfiles (in,optional/out): Configuration for OpenShift router(s). - RouterProfiles []RouterProfile `json:"routerProfiles,omitempty"` - - // AgentPoolProfiles (in): configuration of OpenShift cluster VMs. - AgentPoolProfiles []AgentPoolProfile `json:"agentPoolProfiles,omitempty"` - - // TODO: is this compatible with MSI? - // ServicePrincipalProfile (in): Service principal for OpenShift cluster. - ServicePrincipalProfile ServicePrincipalProfile `json:"servicePrincipalProfile,omitempty"` -} - -// ProvisioningState represents the current state of the OSA resource. -type ProvisioningState string - -const ( - // Creating means the OSA resource is being created. - Creating ProvisioningState = "Creating" - // Updating means the existing OSA resource is being updated. - Updating ProvisioningState = "Updating" - // Failed means the OSA resource is in failed state. - Failed ProvisioningState = "Failed" - // Succeeded means the last create/update succeeded. - Succeeded ProvisioningState = "Succeeded" - // Deleting means the OSA resource is being deleted. - Deleting ProvisioningState = "Deleting" - // Migrating means the OSA resource is being migrated from one subscription - // or resource group to another. - Migrating ProvisioningState = "Migrating" - // Upgrading means the existing OAS resource is being upgraded. - Upgrading ProvisioningState = "Upgrading" -) - -// RouterProfile represents an OpenShift router. -type RouterProfile struct { - Name string `json:"name,omitempty"` - - // PublicSubdomain (in,optional/out): DNS subdomain for OpenShift router. If - // specified, after OSA cluster creation, user must create a (wildcard) - // *.PublicSubdomain CNAME record forwarding to the returned FQDN value. If - // not specified, OSA will auto-allocate and setup a PublicSubdomain and - // return it. The OpenShift master is configured with the PublicSubdomain - // of the "default" RouterProfile. - PublicSubdomain string `json:"publicSubdomain,omitempty"` - - // FQDN (out): Auto-allocated FQDN for the OpenShift router. - FQDN string `json:"fqdn,omitempty"` -} - -// AgentPoolProfile represents configuration of OpenShift cluster VMs. -type AgentPoolProfile struct { - Name string `json:"name,omitempty"` - Role AgentPoolProfileRole `json:"role,omitempty"` - Count int `json:"count,omitempty"` - VMSize string `json:"vmSize,omitempty"` - - // VnetSubnetID is expected to be empty or match - // `^/subscriptions/[^/]+ - // /resourceGroups/[^/]+ - // /providers/Microsoft.Network - // /virtualNetworks/[^/]+ - // /subnets/[^/]+$` - VnetSubnetID string `json:"vnetSubnetID,omitempty"` - OSType OSType `json:"osType,omitempty"` -} - -// AgentPoolProfileRole represents the role of the AgentPoolProfile. -type AgentPoolProfileRole string - -const ( - // AgentPoolProfileRoleCompute is the compute role. - AgentPoolProfileRoleCompute AgentPoolProfileRole = "compute" - // AgentPoolProfileRoleInfra is the infra role. - AgentPoolProfileRoleInfra AgentPoolProfileRole = "infra" - // AgentPoolProfileRoleMaster is the master role. - AgentPoolProfileRoleMaster AgentPoolProfileRole = "master" -) - -// OSType represents the OS type of VMs in an AgentPool. -type OSType string - -const ( - // OSTypeLinux is Linux. - OSTypeLinux OSType = "Linux" - // OSTypeWindows is Windows. - OSTypeWindows OSType = "Windows" -) - -// ServicePrincipalProfile contains the client and secret used by the cluster -// for Azure Resource CRUD. -type ServicePrincipalProfile struct { - ClientID string `json:"clientId,omitempty"` - Secret string `json:"secret,omitempty"` -} diff --git a/pkg/api/osa/vlabs/types_test.go b/pkg/api/osa/vlabs/types_test.go deleted file mode 100644 index 3862d9ee17..0000000000 --- a/pkg/api/osa/vlabs/types_test.go +++ /dev/null @@ -1,143 +0,0 @@ -package vlabs - -import ( - "bytes" - "encoding/json" - "reflect" - "testing" -) - -var testOpenShiftCluster = &OpenShiftCluster{ - ID: "id", - Location: "location", - Name: "name", - Plan: &ResourcePurchasePlan{ - Name: "plan.name", - Product: "plan.product", - PromotionCode: "plan.promotionCode", - Publisher: "plan.publisher", - }, - Tags: map[string]string{ - "tags.k1": "v1", - "tags.k2": "v2", - }, - Type: "type", - Properties: &Properties{ - ProvisioningState: "properties.provisioningState", - OpenShiftVersion: "properties.openShiftVersion", - PublicHostname: "properties.publicHostname", - FQDN: "properties.fqdn", - RouterProfiles: []RouterProfile{ - { - Name: "properties.routerProfiles.0.name", - PublicSubdomain: "properties.routerProfiles.0.publicSubdomain", - FQDN: "properties.routerProfiles.0.fqdn", - }, - { - Name: "properties.routerProfiles.1.name", - PublicSubdomain: "properties.routerProfiles.1.publicSubdomain", - FQDN: "properties.routerProfiles.1.fqdn", - }, - }, - AgentPoolProfiles: []AgentPoolProfile{ - { - Name: "properties.agentPoolProfiles.0.name", - Role: "properties.agentPoolProfiles.0.role", - Count: 1, - VMSize: "properties.agentPoolProfiles.0.vmSize", - VnetSubnetID: "properties.agentPoolProfiles.0.vnetSubnetID", - OSType: "properties.agentPoolProfiles.0.osType", - }, - { - Name: "properties.agentPoolProfiles.0.name", - Role: "properties.agentPoolProfiles.0.role", - Count: 2, - VMSize: "properties.agentPoolProfiles.0.vmSize", - VnetSubnetID: "properties.agentPoolProfiles.0.vnetSubnetID", - OSType: "properties.agentPoolProfiles.0.osType", - }, - }, - ServicePrincipalProfile: ServicePrincipalProfile{ - ClientID: "properties.servicePrincipalProfile.clientID", - Secret: "properties.servicePrincipalProfile.secret", - }, - }, -} - -var testOpenShiftClusterJSON = []byte(`{ - "id": "id", - "location": "location", - "name": "name", - "plan": { - "name": "plan.name", - "product": "plan.product", - "promotionCode": "plan.promotionCode", - "publisher": "plan.publisher" - }, - "tags": { - "tags.k1": "v1", - "tags.k2": "v2" - }, - "type": "type", - "properties": { - "provisioningState": "properties.provisioningState", - "openShiftVersion": "properties.openShiftVersion", - "publicHostname": "properties.publicHostname", - "fqdn": "properties.fqdn", - "routerProfiles": [ - { - "name": "properties.routerProfiles.0.name", - "publicSubdomain": "properties.routerProfiles.0.publicSubdomain", - "fqdn": "properties.routerProfiles.0.fqdn" - }, - { - "name": "properties.routerProfiles.1.name", - "publicSubdomain": "properties.routerProfiles.1.publicSubdomain", - "fqdn": "properties.routerProfiles.1.fqdn" - } - ], - "agentPoolProfiles": [ - { - "name": "properties.agentPoolProfiles.0.name", - "role": "properties.agentPoolProfiles.0.role", - "count": 1, - "vmSize": "properties.agentPoolProfiles.0.vmSize", - "vnetSubnetID": "properties.agentPoolProfiles.0.vnetSubnetID", - "osType": "properties.agentPoolProfiles.0.osType" - }, - { - "name": "properties.agentPoolProfiles.0.name", - "role": "properties.agentPoolProfiles.0.role", - "count": 2, - "vmSize": "properties.agentPoolProfiles.0.vmSize", - "vnetSubnetID": "properties.agentPoolProfiles.0.vnetSubnetID", - "osType": "properties.agentPoolProfiles.0.osType" - } - ], - "servicePrincipalProfile": { - "clientId": "properties.servicePrincipalProfile.clientID", - "secret": "properties.servicePrincipalProfile.secret" - } - } -}`) - -func TestMarshal(t *testing.T) { - b, err := json.MarshalIndent(testOpenShiftCluster, "", "\t") - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(b, testOpenShiftClusterJSON) { - t.Errorf("json.MarshalIndent returned unexpected result\n%s\n", string(b)) - } -} - -func TestUnmarshal(t *testing.T) { - var oc *OpenShiftCluster - err := json.Unmarshal(testOpenShiftClusterJSON, &oc) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(oc, testOpenShiftCluster) { - t.Errorf("json.Unmarshal returned unexpected result\n%#v\n", oc) - } -} diff --git a/pkg/api/strictjson_test.go b/pkg/api/strictjson_test.go index 94fac51d87..0b384c927e 100644 --- a/pkg/api/strictjson_test.go +++ b/pkg/api/strictjson_test.go @@ -5,11 +5,10 @@ import ( "strings" "testing" - "github.com/Azure/acs-engine/pkg/api/v20160330" - "github.com/Azure/acs-engine/pkg/api/v20160930" - "github.com/Azure/acs-engine/pkg/api/v20170131" - "github.com/Azure/acs-engine/pkg/api/v20170701" - "github.com/Azure/acs-engine/pkg/api/vlabs" + "github.com/Azure/aks-engine/pkg/api/v20160930" + "github.com/Azure/aks-engine/pkg/api/v20170131" + "github.com/Azure/aks-engine/pkg/api/v20170701" + "github.com/Azure/aks-engine/pkg/api/vlabs" ) type SubTestProfile struct { @@ -200,7 +199,7 @@ const jsonWithTypo = ` "apiVersion": "ignored", "properties": { "orchestratorProfile": { - "orchestratorType": "DCOS" + "orchestratorType": "Kubernetes" }, "masterProfile": { "count": 1, @@ -231,7 +230,7 @@ func TestStrictJSONValidationIsNotAppliedToApiVersions20170701AndEarlier(t *test // These API versions existed before we added strict JSON validation: // we cannot apply it retrospectively because it could break existing // customer apimodels. - preStrictVersions := []string{v20160330.APIVersion, v20160930.APIVersion, v20170131.APIVersion, v20170701.APIVersion /*, v20170930.APIVersion */} + preStrictVersions := []string{v20160930.APIVersion, v20170131.APIVersion, v20170701.APIVersion /*, v20170930.APIVersion */} a := &Apiloader{ Translator: nil, } diff --git a/pkg/api/types.go b/pkg/api/types.go index 8556941b84..112232b891 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -10,15 +10,14 @@ import ( "strings" "sync" - "github.com/Azure/acs-engine/pkg/api/agentPoolOnlyApi/v20170831" - "github.com/Azure/acs-engine/pkg/api/agentPoolOnlyApi/v20180331" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/api/v20160330" - "github.com/Azure/acs-engine/pkg/api/v20160930" - "github.com/Azure/acs-engine/pkg/api/v20170131" - "github.com/Azure/acs-engine/pkg/api/v20170701" - "github.com/Azure/acs-engine/pkg/api/vlabs" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/api/agentPoolOnlyApi/v20170831" + "github.com/Azure/aks-engine/pkg/api/agentPoolOnlyApi/v20180331" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/api/v20160930" + "github.com/Azure/aks-engine/pkg/api/v20170131" + "github.com/Azure/aks-engine/pkg/api/v20170701" + "github.com/Azure/aks-engine/pkg/api/vlabs" + "github.com/Azure/aks-engine/pkg/helpers" "github.com/blang/semver" ) @@ -50,7 +49,7 @@ type ContainerService struct { Properties *Properties `json:"properties,omitempty"` } -// Properties represents the ACS cluster definition +// Properties represents the AKS cluster definition type Properties struct { ClusterID string ProvisioningState ProvisioningState `json:"provisioningState,omitempty"` @@ -72,7 +71,7 @@ type Properties struct { FeatureFlags *FeatureFlags `json:"featureFlags,omitempty"` } -// ClusterMetadata represents the metadata of the ACS cluster. +// ClusterMetadata represents the metadata of the AKS cluster. type ClusterMetadata struct { SubnetName string `json:"subnetName,omitempty"` VNetResourceGroupName string `json:"vnetResourceGroupName,omitempty"` @@ -222,8 +221,6 @@ type OrchestratorProfile struct { OrchestratorType string `json:"orchestratorType"` OrchestratorVersion string `json:"orchestratorVersion"` KubernetesConfig *KubernetesConfig `json:"kubernetesConfig,omitempty"` - OpenShiftConfig *OpenShiftConfig `json:"openshiftConfig,omitempty"` - DcosConfig *DcosConfig `json:"dcosConfig,omitempty"` } // OrchestratorVersionProfile contains information of a supported orchestrator version: @@ -381,52 +378,6 @@ type CustomFile struct { Dest string `json:"dest,omitempty"` } -// BootstrapProfile represents the definition of the DCOS bootstrap node used to deploy the cluster -type BootstrapProfile struct { - VMSize string `json:"vmSize,omitempty"` - OSDiskSizeGB int `json:"osDiskSizeGB,omitempty"` - OAuthEnabled bool `json:"oauthEnabled,omitempty"` - StaticIP string `json:"staticIP,omitempty"` - Subnet string `json:"subnet,omitempty"` -} - -// DcosConfig Configuration for DC/OS -type DcosConfig struct { - DcosBootstrapURL string `json:"dcosBootstrapURL,omitempty"` - DcosWindowsBootstrapURL string `json:"dcosWindowsBootstrapURL,omitempty"` - Registry string `json:"registry,omitempty"` - RegistryUser string `json:"registryUser,omitempty"` - RegistryPass string `json:"registryPassword,omitempty"` - DcosRepositoryURL string `json:"dcosRepositoryURL,omitempty"` // For CI use, you need to specify - DcosClusterPackageListID string `json:"dcosClusterPackageListID,omitempty"` // all three of these items - DcosProviderPackageID string `json:"dcosProviderPackageID,omitempty"` // repo url is the location of the build, - BootstrapProfile *BootstrapProfile `json:"bootstrapProfile,omitempty"` -} - -// OpenShiftConfig holds configuration for OpenShift -type OpenShiftConfig struct { - KubernetesConfig *KubernetesConfig `json:"kubernetesConfig,omitempty"` - - // ClusterUsername and ClusterPassword are temporary, do not rely on them. - ClusterUsername string `json:"clusterUsername,omitempty"` - ClusterPassword string `json:"clusterPassword,omitempty"` - - // EnableAADAuthentication is temporary, do not rely on it. - EnableAADAuthentication bool `json:"enableAADAuthentication,omitempty"` - - ConfigBundles map[string][]byte `json:"configBundles,omitempty"` - - PublicHostname string - RouterProfiles []OpenShiftRouterProfile -} - -// OpenShiftRouterProfile represents an OpenShift router. -type OpenShiftRouterProfile struct { - Name string - PublicSubdomain string - FQDN string -} - // MasterProfile represents the definition of the master cluster type MasterProfile struct { Count int `json:"count"` @@ -636,23 +587,15 @@ type CustomProfile struct { } // VlabsARMContainerService is the type we read and write from file -// needed because the json that is sent to ARM and acs-engine +// needed because the json that is sent to ARM and aks-engine // is different from the json that the ACS RP Api gets from ARM type VlabsARMContainerService struct { TypeMeta *vlabs.ContainerService } -// V20160330ARMContainerService is the type we read and write from file -// needed because the json that is sent to ARM and acs-engine -// is different from the json that the ACS RP Api gets from ARM -type V20160330ARMContainerService struct { - TypeMeta - *v20160330.ContainerService -} - // V20160930ARMContainerService is the type we read and write from file -// needed because the json that is sent to ARM and acs-engine +// needed because the json that is sent to ARM and aks-engine // is different from the json that the ACS RP Api gets from ARM type V20160930ARMContainerService struct { TypeMeta @@ -660,7 +603,7 @@ type V20160930ARMContainerService struct { } // V20170131ARMContainerService is the type we read and write from file -// needed because the json that is sent to ARM and acs-engine +// needed because the json that is sent to ARM and aks-engine // is different from the json that the ACS RP Api gets from ARM type V20170131ARMContainerService struct { TypeMeta @@ -668,7 +611,7 @@ type V20170131ARMContainerService struct { } // V20170701ARMContainerService is the type we read and write from file -// needed because the json that is sent to ARM and acs-engine +// needed because the json that is sent to ARM and aks-engine // is different from the json that the ACS RP Api gets from ARM type V20170701ARMContainerService struct { TypeMeta @@ -676,7 +619,7 @@ type V20170701ARMContainerService struct { } // V20170831ARMManagedContainerService is the type we read and write from file -// needed because the json that is sent to ARM and acs-engine +// needed because the json that is sent to ARM and aks-engine // is different from the json that the ACS RP Api gets from ARM type V20170831ARMManagedContainerService struct { TypeMeta @@ -684,7 +627,7 @@ type V20170831ARMManagedContainerService struct { } // V20180331ARMManagedContainerService is the type we read and write from file -// needed because the json that is sent to ARM and acs-engine +// needed because the json that is sent to ARM and aks-engine // is different from the json that the ACS RP Api gets from ARM type V20180331ARMManagedContainerService struct { TypeMeta @@ -719,9 +662,6 @@ func (p *Properties) HasManagedDisks() bool { // HasStorageAccountDisks returns true if the cluster contains Storage Account Disks func (p *Properties) HasStorageAccountDisks() bool { - if p.OrchestratorProfile != nil && p.OrchestratorProfile.OrchestratorType == OpenShift { - return true - } if p.MasterProfile != nil && p.MasterProfile.StorageProfile == StorageAccount { return true } @@ -760,15 +700,11 @@ func (p *Properties) HasVMSSAgentPool() bool { // K8sOrchestratorName returns the 3 character orchestrator code for kubernetes-based clusters. func (p *Properties) K8sOrchestratorName() string { - if p.OrchestratorProfile.IsKubernetes() || - p.OrchestratorProfile.IsOpenShift() { + if p.OrchestratorProfile.IsKubernetes() { if p.HostedMasterProfile != nil { return DefaultHostedProfileMasterName - } else if p.OrchestratorProfile.IsOpenShift() { - return DefaultOpenshiftOrchestratorName - } else { - return DefaultOrchestratorName } + return DefaultOrchestratorName } return "" } @@ -1125,26 +1061,11 @@ func (l *LinuxProfile) HasCustomNodesDNS() bool { return false } -// IsSwarmMode returns true if this template is for Swarm Mode orchestrator -func (o *OrchestratorProfile) IsSwarmMode() bool { - return o.OrchestratorType == SwarmMode -} - // IsKubernetes returns true if this template is for Kubernetes orchestrator func (o *OrchestratorProfile) IsKubernetes() bool { return o.OrchestratorType == Kubernetes } -// IsOpenShift returns true if this template is for OpenShift orchestrator -func (o *OrchestratorProfile) IsOpenShift() bool { - return o.OrchestratorType == OpenShift -} - -// IsDCOS returns true if this template is for DCOS orchestrator -func (o *OrchestratorProfile) IsDCOS() bool { - return o.OrchestratorType == DCOS -} - // IsAzureCNI returns true if Azure CNI network plugin is enabled func (o *OrchestratorProfile) IsAzureCNI() bool { if o.KubernetesConfig != nil { diff --git a/pkg/api/types_test.go b/pkg/api/types_test.go index 4a62ae3fe1..3d3d1d6fd5 100644 --- a/pkg/api/types_test.go +++ b/pkg/api/types_test.go @@ -5,8 +5,8 @@ import ( "reflect" "testing" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/helpers" ) const exampleCustomHyperkubeImage = `example.azurecr.io/example/hyperkube-amd64:custom` @@ -636,14 +636,6 @@ func TestRequireRouteTable(t *testing.T) { p Properties expected bool }{ - { - p: Properties{ - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: DCOS, - }, - }, - expected: false, - }, { p: Properties{ OrchestratorProfile: &OrchestratorProfile{ @@ -718,73 +710,22 @@ func TestIsAzureCNI(t *testing.T) { func TestOrchestrator(t *testing.T) { cases := []struct { p Properties - expectedIsDCOS bool expectedIsKubernetes bool - expectedIsOpenShift bool - expectedIsSwarmMode bool }{ - { - p: Properties{ - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: DCOS, - }, - }, - expectedIsDCOS: true, - expectedIsKubernetes: false, - expectedIsOpenShift: false, - expectedIsSwarmMode: false, - }, { p: Properties{ OrchestratorProfile: &OrchestratorProfile{ OrchestratorType: Kubernetes, }, }, - expectedIsDCOS: false, expectedIsKubernetes: true, - expectedIsOpenShift: false, - expectedIsSwarmMode: false, - }, - { - p: Properties{ - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: OpenShift, - }, - }, - expectedIsDCOS: false, - expectedIsKubernetes: false, - expectedIsOpenShift: true, - expectedIsSwarmMode: false, - }, - { - p: Properties{ - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: SwarmMode, - }, - }, - expectedIsDCOS: false, - expectedIsKubernetes: false, - expectedIsOpenShift: false, - expectedIsSwarmMode: true, }, } for _, c := range cases { - if c.expectedIsDCOS != c.p.OrchestratorProfile.IsDCOS() { - t.Fatalf("Expected IsDCOS() to be %t with OrchestratorType=%s", c.expectedIsDCOS, c.p.OrchestratorProfile.OrchestratorType) - } if c.expectedIsKubernetes != c.p.OrchestratorProfile.IsKubernetes() { t.Fatalf("Expected IsKubernetes() to be %t with OrchestratorType=%s", c.expectedIsKubernetes, c.p.OrchestratorProfile.OrchestratorType) } - if c.expectedIsOpenShift != c.p.OrchestratorProfile.IsOpenShift() { - t.Fatalf("Expected IsOpenShift() to be %t with OrchestratorType=%s", c.expectedIsOpenShift, c.p.OrchestratorProfile.OrchestratorType) - } - if c.expectedIsSwarmMode != c.p.OrchestratorProfile.IsSwarmMode() { - t.Fatalf("Expected IsSwarmMode() to be %t with OrchestratorType=%s", c.expectedIsSwarmMode, c.p.OrchestratorProfile.OrchestratorType) - } - if c.expectedIsOpenShift && !c.p.HasStorageAccountDisks() { - t.Fatalf("Expected HasStorageAccountDisks() to return true when OrchestratorType is OpenShift") - } } } diff --git a/pkg/api/v20160330/const.go b/pkg/api/v20160330/const.go deleted file mode 100644 index bf662cc84a..0000000000 --- a/pkg/api/v20160330/const.go +++ /dev/null @@ -1,27 +0,0 @@ -package v20160330 - -const ( - // APIVersion is the version of this API - APIVersion = "2016-03-30" -) - -// v20160330 supports orchestrators Mesos, Swarm, DCOS -const ( - Mesos string = "Mesos" - Swarm string = "Swarm" - DCOS string = "DCOS" -) - -// v20160330 supports OSTypes Windows and Linux -const ( - Windows OSType = "Windows" - Linux OSType = "Linux" -) - -// validation values -const ( - // MinAgentCount are the minimum number of agents - MinAgentCount = 1 - // MaxAgentCount are the maximum number of agents - MaxAgentCount = 100 -) diff --git a/pkg/api/v20160330/doc.go b/pkg/api/v20160330/doc.go deleted file mode 100644 index a5511e93e9..0000000000 --- a/pkg/api/v20160330/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package v20160330 stores the api model for version "2016-03-30" -package v20160330 diff --git a/pkg/api/v20160330/merge.go b/pkg/api/v20160330/merge.go deleted file mode 100644 index 4078e5dfd7..0000000000 --- a/pkg/api/v20160330/merge.go +++ /dev/null @@ -1,19 +0,0 @@ -package v20160330 - -import ( - "github.com/imdario/mergo" -) - -// Merge existing containerService attribute into cs -func (cs *ContainerService) Merge(ecs *ContainerService) error { - if ecs.Properties.WindowsProfile != nil { - if cs.Properties.WindowsProfile == nil { - cs.Properties.WindowsProfile = &WindowsProfile{} - } - if err := mergo.Merge(cs.Properties.WindowsProfile, - *ecs.Properties.WindowsProfile); err != nil { - return err - } - } - return nil -} diff --git a/pkg/api/v20160330/merge_test.go b/pkg/api/v20160330/merge_test.go deleted file mode 100644 index 714fdaeecc..0000000000 --- a/pkg/api/v20160330/merge_test.go +++ /dev/null @@ -1,56 +0,0 @@ -package v20160330 - -import "testing" - -func TestMerge(t *testing.T) { - newCS := &ContainerService{ - Properties: &Properties{ - WindowsProfile: &WindowsProfile{ - AdminUsername: "azureuser", - AdminPassword: "", - }, - }, - } - - existingCS := &ContainerService{ - Properties: &Properties{ - WindowsProfile: &WindowsProfile{ - AdminUsername: "azureuser", - AdminPassword: "existingPassword", - }, - }, - } - if err := newCS.Merge(existingCS); err != nil { - t.Fatalf("unexpectedly detected merge failure, %+v", err) - } - if newCS.Properties.WindowsProfile.AdminPassword != "existingPassword" { - t.Fatalf("unexpected Properties.WindowsProfile.AdminPassword not updated") - } -} - -func TestMergeWithNil(t *testing.T) { - newCS := &ContainerService{ - Properties: &Properties{}, - } - - existingCS := &ContainerService{ - Properties: &Properties{ - WindowsProfile: &WindowsProfile{ - AdminUsername: "azureuser", - AdminPassword: "existingPassword", - }, - }, - } - if err := newCS.Merge(existingCS); err != nil { - t.Fatalf("unexpectedly detected merge failure, %+v", err) - } - if newCS.Properties.WindowsProfile == nil { - t.Fatalf("unexpected Properties.WindowsProfile not updated") - } - if newCS.Properties.WindowsProfile.AdminUsername != "azureuser" { - t.Fatalf("unexpected Properties.WindowsProfile.AdminUsername not updated") - } - if newCS.Properties.WindowsProfile.AdminPassword != "existingPassword" { - t.Fatalf("unexpected Properties.WindowsProfile.AdminPassword not updated") - } -} diff --git a/pkg/api/v20160330/types.go b/pkg/api/v20160330/types.go deleted file mode 100644 index 232bcc4a71..0000000000 --- a/pkg/api/v20160330/types.go +++ /dev/null @@ -1,270 +0,0 @@ -package v20160330 - -import ( - "encoding/json" - neturl "net/url" - "strings" - - "github.com/pkg/errors" -) - -// ResourcePurchasePlan defines resource plan as required by ARM -// for billing purposes. -type ResourcePurchasePlan struct { - Name string `json:"name,omitempty"` - Product string `json:"product,omitempty"` - PromotionCode string `json:"promotionCode,omitempty"` - Publisher string `json:"publisher,omitempty"` -} - -// ContainerService complies with the ARM model of -// resource definition in a JSON template. -type ContainerService struct { - ID string `json:"id,omitempty"` - Location string `json:"location,omitempty"` - Name string `json:"name,omitempty"` - Plan *ResourcePurchasePlan `json:"plan,omitempty"` - Tags map[string]string `json:"tags,omitempty"` - Type string `json:"type,omitempty"` - - Properties *Properties `json:"properties"` -} - -// Properties is currently incomplete. More fields will be added later. -type Properties struct { - ProvisioningState ProvisioningState `json:"provisioningState,omitempty"` - OrchestratorProfile *OrchestratorProfile `json:"orchestratorProfile,omitempty"` - MasterProfile *MasterProfile `json:"masterProfile,omitempty"` - AgentPoolProfiles []*AgentPoolProfile `json:"agentPoolProfiles,omitempty"` - LinuxProfile *LinuxProfile `json:"linuxProfile,omitempty"` - WindowsProfile *WindowsProfile `json:"windowsProfile,omitempty"` - - // TODO: This field is versioned to "2016-03-30" - DiagnosticsProfile *DiagnosticsProfile `json:"diagnosticsProfile,omitempty"` - - // JumpboxProfile has made it into the new ACS RP stack for - // backward compatibility. - // TODO: Version this field so that newer versions don't - // allow jumpbox creation - JumpboxProfile *JumpboxProfile `json:"jumpboxProfile,omitempty"` -} - -// LinuxProfile represents the Linux configuration passed to the cluster -type LinuxProfile struct { - AdminUsername string `json:"adminUsername"` - - SSH struct { - PublicKeys []PublicKey `json:"publicKeys"` - } `json:"ssh"` -} - -// PublicKey represents an SSH key for LinuxProfile -type PublicKey struct { - KeyData string `json:"keyData"` -} - -// WindowsProfile represents the Windows configuration passed to the cluster -type WindowsProfile struct { - AdminUsername string `json:"adminUsername"` - AdminPassword string `json:"adminPassword"` -} - -// ProvisioningState represents the current state of container service resource. -type ProvisioningState string - -const ( - // Creating means ContainerService resource is being created. - Creating ProvisioningState = "Creating" - // Updating means an existing ContainerService resource is being updated - Updating ProvisioningState = "Updating" - // Failed means resource is in failed state - Failed ProvisioningState = "Failed" - // Succeeded means resource created succeeded during last create/update - Succeeded ProvisioningState = "Succeeded" - // Deleting means resource is in the process of being deleted - Deleting ProvisioningState = "Deleting" - // Migrating means resource is being migrated from one subscription or - // resource group to another - Migrating ProvisioningState = "Migrating" -) - -// OrchestratorProfile contains Orchestrator properties -type OrchestratorProfile struct { - OrchestratorType string `json:"orchestratorType"` -} - -// MasterProfile represents the definition of master cluster -type MasterProfile struct { - Count int `json:"count"` - DNSPrefix string `json:"dnsPrefix"` - - // Master LB public endpoint/FQDN with port - // The format will be FQDN:2376 - // Not used during PUT, returned as part of GET - FQDN string `json:"fqdn,omitempty"` - - // subnet is internal - subnet string -} - -// UnmarshalJSON unmarshal json using the default behavior -// And do fields manipulation, such as populating default value -func (m *MasterProfile) UnmarshalJSON(b []byte) error { - // Need to have a alias type to avoid circular unmarshal - type aliasMasterProfile MasterProfile - mm := aliasMasterProfile{} - if e := json.Unmarshal(b, &mm); e != nil { - return e - } - *m = MasterProfile(mm) - if m.Count == 0 { - // if MasterProfile.Count is missing or 0, set to default 1 - m.Count = 1 - } - return nil -} - -// AgentPoolProfile represents configuration of VMs running agent -// daemons that register with the master and offer resources to -// host applications in containers. -type AgentPoolProfile struct { - Name string `json:"name"` - Count int `json:"count"` - VMSize string `json:"vmSize"` - DNSPrefix string `json:"dnsPrefix"` - FQDN string `json:"fqdn"` - OSType OSType `json:"osType"` // TODO: This field is versioned to "2016-03-30" - // subnet is internal - subnet string -} - -// UnmarshalJSON unmarshal json using the default behavior -// And do fields manipulation, such as populating default value -func (a *AgentPoolProfile) UnmarshalJSON(b []byte) error { - // Need to have a alias type to avoid circular unmarshal - type aliasAgentPoolProfile AgentPoolProfile - aa := aliasAgentPoolProfile{} - if e := json.Unmarshal(b, &aa); e != nil { - return e - } - *a = AgentPoolProfile(aa) - if a.Count == 0 { - // if AgentPoolProfile.Count is missing or 0, set it to default 1 - a.Count = 1 - } - - if string(a.OSType) == "" { - // OSType is the operating system type for agents - // Set as nullable to support backward compat because - // this property was added later. - // If the value is null or not set, it defaulted to Linux. - a.OSType = Linux - } - return nil -} - -// JumpboxProfile dscribes properties of the jumpbox setup -// in the ACS container cluster. -type JumpboxProfile struct { - OSType OSType `json:"osType"` - DNSPrefix string `json:"dnsPrefix"` - - // Jumpbox public endpoint/FQDN with port - // The format will be FQDN:2376 - // Not used during PUT, returned as part of GET - FQDN string `json:"fqdn,omitempty"` -} - -// DiagnosticsProfile setting to enable/disable capturing -// diagnostics for VMs hosting container cluster. -type DiagnosticsProfile struct { - VMDiagnostics *VMDiagnostics `json:"vmDiagnostics"` -} - -// VMDiagnostics contains settings to on/off boot diagnostics collection -// in RD Host -type VMDiagnostics struct { - Enabled bool `json:"enabled"` - - // Specifies storage account Uri where Boot Diagnostics (CRP & - // VMSS BootDiagostics) and VM Diagnostics logs (using Linux - // Diagnostics Extension) will be stored. Uri will be of standard - // blob domain. i.e. https://storageaccount.blob.core.windows.net/ - // This field is readonly as ACS RP will create a storage account - // for the customer. - StorageURL *neturl.URL `json:"storageUrl"` -} - -// UnmarshalJSON unmarshal json using the default behavior -// And do fields manipulation, such as populating default value -func (o *OrchestratorProfile) UnmarshalJSON(b []byte) error { - // Need to have a alias type to avoid circular unmarshal - type aliasOrchestratorProfile OrchestratorProfile - op := aliasOrchestratorProfile{} - if e := json.Unmarshal(b, &op); e != nil { - return e - } - *o = OrchestratorProfile(op) - - // Unmarshal OrchestratorType, format it as well - orchestratorType := o.OrchestratorType - switch { - case strings.EqualFold(orchestratorType, DCOS): - o.OrchestratorType = DCOS - case strings.EqualFold(orchestratorType, Swarm): - o.OrchestratorType = Swarm - case strings.EqualFold(orchestratorType, Mesos): - o.OrchestratorType = Mesos - default: - return errors.Errorf("OrchestratorType has unknown orchestrator: %s", orchestratorType) - } - return nil -} - -// OSType represents OS types of agents -type OSType string - -// HasWindows returns true if the cluster contains windows -func (a *Properties) HasWindows() bool { - for _, agentPoolProfile := range a.AgentPoolProfiles { - if agentPoolProfile.OSType == Windows { - return true - } - } - return false -} - -// GetSubnet returns the read-only subnet for the master -func (m *MasterProfile) GetSubnet() string { - return m.subnet -} - -// SetSubnet sets the read-only subnet for the master -func (m *MasterProfile) SetSubnet(subnet string) { - m.subnet = subnet -} - -// IsWindows returns true if the agent pool is windows -func (a *AgentPoolProfile) IsWindows() bool { - return a.OSType == Windows -} - -// IsLinux returns true if the agent pool is linux -func (a *AgentPoolProfile) IsLinux() bool { - return a.OSType == Linux -} - -// IsDCOS returns true if this template is for DCOS orchestrator -func (o *OrchestratorProfile) IsDCOS() bool { - return o.OrchestratorType == DCOS -} - -// GetSubnet returns the read-only subnet for the agent pool -func (a *AgentPoolProfile) GetSubnet() string { - return a.subnet -} - -// SetSubnet sets the read-only subnet for the agent pool -func (a *AgentPoolProfile) SetSubnet(subnet string) { - a.subnet = subnet -} diff --git a/pkg/api/v20160330/types_test.go b/pkg/api/v20160330/types_test.go deleted file mode 100644 index 87061feab1..0000000000 --- a/pkg/api/v20160330/types_test.go +++ /dev/null @@ -1,88 +0,0 @@ -package v20160330 - -import ( - "encoding/json" - "testing" -) - -func TestIsDCOS(t *testing.T) { - dCOSProfile := &OrchestratorProfile{ - OrchestratorType: "DCOS", - } - if !dCOSProfile.IsDCOS() { - t.Fatalf("unable to detect DCOS orchestrator profile from OrchestratorType=%s", dCOSProfile.OrchestratorType) - } - kubernetesProfile := &OrchestratorProfile{ - OrchestratorType: "Kubernetes", - } - if kubernetesProfile.IsDCOS() { - t.Fatalf("unexpectedly detected DCOS orchestrator profile from OrchestratorType=%s", kubernetesProfile.OrchestratorType) - } -} - -func TestAgentPoolProfile(t *testing.T) { - // With osType not specified - AgentPoolProfileText := `{ "name": "linuxpool1", "count": 0, "vmSize": "Standard_D2_v2", "availabilityProfile": "AvailabilitySet" }` - ap := &AgentPoolProfile{} - if e := json.Unmarshal([]byte(AgentPoolProfileText), ap); e != nil { - t.Fatalf("unexpectedly detected unmarshal failure for AgentPoolProfile, %+v", e) - } - - if ap.Count != 1 { - t.Fatalf("unexpectedly detected AgentPoolProfile.Count != 1 after unmarshal") - } - - if !ap.IsLinux() { - t.Fatalf("unexpectedly detected AgentPoolProfile.OSType != Linux after unmarshal") - } - - // With osType specified - AgentPoolProfileText = `{ "name": "linuxpool1", "osType" : "Windows", "count": 1, "vmSize": "Standard_D2_v2", -"availabilityProfile": "AvailabilitySet", "storageProfile" : "ManagedDisks", "vnetSubnetID" : "12345" }` - ap = &AgentPoolProfile{} - if e := json.Unmarshal([]byte(AgentPoolProfileText), ap); e != nil { - t.Fatalf("unexpectedly detected unmarshal failure for AgentPoolProfile, %+v", e) - } - - if ap.Count != 1 { - t.Fatalf("unexpectedly detected AgentPoolProfile.Count != 1 after unmarshal") - } - - if !ap.IsWindows() { - t.Fatalf("unexpectedly detected AgentPoolProfile.OSType != Windows after unmarshal") - } -} - -func TestMasterProfile(t *testing.T) { - MasterProfileText := `{ "count": 0, "dnsPrefix": "", "vmSize": "Standard_D2_v2" }` - mp := &MasterProfile{} - if e := json.Unmarshal([]byte(MasterProfileText), mp); e != nil { - t.Fatalf("unexpectedly detected unmarshal failure for MasterProfile, %+v", e) - } -} - -func TestOrchestratorProfile(t *testing.T) { - OrchestratorProfileText := `{ "orchestratorType": "Mesos" }` - op := &OrchestratorProfile{} - if e := json.Unmarshal([]byte(OrchestratorProfileText), op); e != nil { - t.Fatalf("unexpectedly detected unmarshal failure for OrchestratorProfile, %+v", e) - } - - OrchestratorProfileText = `{ "orchestratorType": "Swarm" }` - op = &OrchestratorProfile{} - if e := json.Unmarshal([]byte(OrchestratorProfileText), op); e != nil { - t.Fatalf("unexpectedly detected unmarshal failure for OrchestratorProfile, %+v", e) - } - - OrchestratorProfileText = `{ "orchestratorType": "DCOS" }` - op = &OrchestratorProfile{} - if e := json.Unmarshal([]byte(OrchestratorProfileText), op); e != nil { - t.Fatalf("unexpectedly detected unmarshal failure for OrchestratorProfile, %+v", e) - } - - OrchestratorProfileText = `{ "orchestratorType": "Kubernetes" }` - op = &OrchestratorProfile{} - if e := json.Unmarshal([]byte(OrchestratorProfileText), op); e == nil { - t.Fatalf("expected unmarshal failure for OrchestratorProfile") - } -} diff --git a/pkg/api/v20160330/validate.go b/pkg/api/v20160330/validate.go deleted file mode 100644 index c53acf2414..0000000000 --- a/pkg/api/v20160330/validate.go +++ /dev/null @@ -1,142 +0,0 @@ -package v20160330 - -import ( - "regexp" - - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/pkg/errors" -) - -// Validate implements APIObject -func (o *OrchestratorProfile) Validate() error { - switch o.OrchestratorType { - case DCOS: - case Mesos: - case Swarm: - default: - return errors.Errorf("OrchestratorProfile has unknown orchestrator: %s", o.OrchestratorType) - } - - return nil -} - -// Validate implements APIObject -func (m *MasterProfile) Validate() error { - if m.Count != 1 && m.Count != 3 && m.Count != 5 { - return errors.New("MasterProfile count needs to be 1, 3, or 5") - } - if e := validateName(m.DNSPrefix, "MasterProfile.DNSPrefix"); e != nil { - return e - } - return common.ValidateDNSPrefix(m.DNSPrefix) -} - -// Validate implements APIObject -func (a *AgentPoolProfile) Validate() error { - if e := validateName(a.Name, "AgentPoolProfile.Name"); e != nil { - return e - } - if e := validatePoolName(a.Name); e != nil { - return e - } - if a.Count < MinAgentCount || a.Count > MaxAgentCount { - return errors.Errorf("AgentPoolProfile count needs to be in the range [%d,%d]", MinAgentCount, MaxAgentCount) - } - if e := validateName(a.VMSize, "AgentPoolProfile.VMSize"); e != nil { - return e - } - if a.DNSPrefix != "" { - if e := common.ValidateDNSPrefix(a.DNSPrefix); e != nil { - return e - } - } - return nil -} - -// Validate implements APIObject -func (l *LinuxProfile) Validate() error { - if e := validateName(l.AdminUsername, "LinuxProfile.AdminUsername"); e != nil { - return e - } - if len(l.SSH.PublicKeys) != 1 { - return errors.New("LinuxProfile.PublicKeys requires only 1 SSH Key") - } - return validateName(l.SSH.PublicKeys[0].KeyData, "LinuxProfile.PublicKeys.KeyData") -} - -// Validate implements APIObject -func (a *Properties) Validate() error { - if a.OrchestratorProfile == nil { - return errors.New("missing OrchestratorProfile") - } - if a.MasterProfile == nil { - return errors.New("missing MasterProfile") - } - if a.LinuxProfile == nil { - return errors.New("missing LinuxProfile") - } - if e := a.OrchestratorProfile.Validate(); e != nil { - return e - } - if e := a.MasterProfile.Validate(); e != nil { - return e - } - if e := validateUniqueProfileNames(a.AgentPoolProfiles); e != nil { - return e - } - - for _, agentPoolProfile := range a.AgentPoolProfiles { - if e := agentPoolProfile.Validate(); e != nil { - return e - } - if agentPoolProfile.OSType == Windows { - if a.WindowsProfile == nil { - return errors.New("missing WindowsProfile") - } - switch a.OrchestratorProfile.OrchestratorType { - case Swarm: - default: - return errors.Errorf("Orchestrator %s does not support Windows", a.OrchestratorProfile.OrchestratorType) - } - if len(a.WindowsProfile.AdminUsername) == 0 { - return errors.Errorf("WindowsProfile.AdminUsername must not be empty since agent pool '%s' specifies windows", agentPoolProfile.Name) - } - if len(a.WindowsProfile.AdminPassword) == 0 { - return errors.Errorf("WindowsProfile.AdminPassword must not be empty since agent pool '%s' specifies windows", agentPoolProfile.Name) - } - } - } - return a.LinuxProfile.Validate() -} - -func validateName(name string, label string) error { - if name == "" { - return errors.Errorf("%s must be a non-empty value", label) - } - return nil -} - -func validatePoolName(poolName string) error { - // we will cap at length of 12 and all lowercase letters since this makes up the VMName - poolNameRegex := `^([a-z][a-z0-9]{0,11})$` - re, err := regexp.Compile(poolNameRegex) - if err != nil { - return err - } - submatches := re.FindStringSubmatch(poolName) - if len(submatches) != 2 { - return errors.Errorf("pool name '%s' is invalid. A pool name must start with a lowercase letter, have max length of 12, and only have characters a-z0-9", poolName) - } - return nil -} - -func validateUniqueProfileNames(profiles []*AgentPoolProfile) error { - profileNames := make(map[string]bool) - for _, profile := range profiles { - if _, ok := profileNames[profile.Name]; ok { - return errors.Errorf("profile name '%s' already exists, profile names must be unique across pools", profile.Name) - } - profileNames[profile.Name] = true - } - return nil -} diff --git a/pkg/api/v20160930/const.go b/pkg/api/v20160930/const.go index 933fa057ca..c8555c9312 100644 --- a/pkg/api/v20160930/const.go +++ b/pkg/api/v20160930/const.go @@ -7,12 +7,6 @@ const ( // the orchestrators supported by 2016-09-30 const ( - // Mesos is the string constant for the Mesos orchestrator type - Mesos string = "Mesos" - // DCOS is the string constant for DCOS orchestrator type and defaults to DCOS187 - DCOS string = "DCOS" - // Swarm is the string constant for the Swarm orchestrator type - Swarm string = "Swarm" // Kubernetes is the string constant for the Kubernetes orchestrator type Kubernetes string = "Kubernetes" ) diff --git a/pkg/api/v20160930/types.go b/pkg/api/v20160930/types.go index 1e2bd60bc1..2757a9958b 100644 --- a/pkg/api/v20160930/types.go +++ b/pkg/api/v20160930/types.go @@ -30,7 +30,7 @@ type ContainerService struct { Properties *Properties `json:"properties"` } -// Properties represents the ACS cluster definition +// Properties represents the AKS cluster definition type Properties struct { ProvisioningState ProvisioningState `json:"provisioningState,omitempty"` OrchestratorProfile *OrchestratorProfile `json:"orchestratorProfile,omitempty"` @@ -223,14 +223,8 @@ func (o *OrchestratorProfile) UnmarshalJSON(b []byte) error { // Unmarshal OrchestratorType, format it as well orchestratorType := o.OrchestratorType switch { - case strings.EqualFold(orchestratorType, DCOS): - o.OrchestratorType = DCOS - case strings.EqualFold(orchestratorType, Swarm): - o.OrchestratorType = Swarm case strings.EqualFold(orchestratorType, Kubernetes): o.OrchestratorType = Kubernetes - case strings.EqualFold(orchestratorType, Mesos): - o.OrchestratorType = Mesos default: return errors.Errorf("OrchestratorType has unknown orchestrator: %s", orchestratorType) } @@ -270,11 +264,6 @@ func (a *AgentPoolProfile) IsLinux() bool { return a.OSType == Linux } -// IsDCOS returns true if this template is for DCOS orchestrator -func (o *OrchestratorProfile) IsDCOS() bool { - return o.OrchestratorType == DCOS -} - // GetSubnet returns the read-only subnet for the agent pool func (a *AgentPoolProfile) GetSubnet() string { return a.subnet diff --git a/pkg/api/v20160930/types_test.go b/pkg/api/v20160930/types_test.go index 3ac851506a..128a8999bd 100644 --- a/pkg/api/v20160930/types_test.go +++ b/pkg/api/v20160930/types_test.go @@ -5,21 +5,6 @@ import ( "testing" ) -func TestIsDCOS(t *testing.T) { - dCOSProfile := &OrchestratorProfile{ - OrchestratorType: "DCOS", - } - if !dCOSProfile.IsDCOS() { - t.Fatalf("unable to detect DCOS orchestrator profile from OrchestratorType=%s", dCOSProfile.OrchestratorType) - } - kubernetesProfile := &OrchestratorProfile{ - OrchestratorType: "Kubernetes", - } - if kubernetesProfile.IsDCOS() { - t.Fatalf("unexpectedly detected DCOS orchestrator profile from OrchestratorType=%s", kubernetesProfile.OrchestratorType) - } -} - func TestMasterProfile(t *testing.T) { MasterProfileText := "{\"count\" : 0}" mp := &MasterProfile{} @@ -49,7 +34,7 @@ func TestAgentPoolProfile(t *testing.T) { } // With osType specified - AgentPoolProfileText = `{ "name": "linuxpool1", "osType" : "Windows", "count": 1, "vmSize": "Standard_D2_v2", + AgentPoolProfileText = `{ "name": "linuxpool1", "osType" : "Windows", "count": 1, "vmSize": "Standard_D2_v2", "availabilityProfile": "AvailabilitySet", "storageProfile" : "ManagedDisks", "vnetSubnetID" : "12345" }` ap = &AgentPoolProfile{} if e := json.Unmarshal([]byte(AgentPoolProfileText), ap); e != nil { @@ -66,28 +51,9 @@ func TestAgentPoolProfile(t *testing.T) { } func TestOrchestratorProfile(t *testing.T) { - OrchestratorProfileText := `{ "orchestratorType": "Mesos" }` + OrchestratorProfileText := `{ "orchestratorType": "Kubernetes" }` op := &OrchestratorProfile{} if e := json.Unmarshal([]byte(OrchestratorProfileText), op); e != nil { t.Fatalf("unexpectedly detected unmarshal failure for OrchestratorProfile, %+v", e) } - - OrchestratorProfileText = `{ "orchestratorType": "Swarm" }` - op = &OrchestratorProfile{} - if e := json.Unmarshal([]byte(OrchestratorProfileText), op); e != nil { - t.Fatalf("unexpectedly detected unmarshal failure for OrchestratorProfile, %+v", e) - } - - OrchestratorProfileText = `{ "orchestratorType": "DCOS" }` - op = &OrchestratorProfile{} - if e := json.Unmarshal([]byte(OrchestratorProfileText), op); e != nil { - t.Fatalf("unexpectedly detected unmarshal failure for OrchestratorProfile, %+v", e) - } - - OrchestratorProfileText = `{ "orchestratorType": "Kubernetes" }` - op = &OrchestratorProfile{} - if e := json.Unmarshal([]byte(OrchestratorProfileText), op); e != nil { - t.Fatalf("unexpectedly detected unmarshal failure for OrchestratorProfile, %+v", e) - - } } diff --git a/pkg/api/v20160930/validate.go b/pkg/api/v20160930/validate.go index 5da8dd5c29..e4b8a8e825 100644 --- a/pkg/api/v20160930/validate.go +++ b/pkg/api/v20160930/validate.go @@ -3,16 +3,13 @@ package v20160930 import ( "regexp" - "github.com/Azure/acs-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/api/common" "github.com/pkg/errors" ) // Validate implements APIObject func (o *OrchestratorProfile) Validate() error { switch o.OrchestratorType { - case DCOS: - case Mesos: - case Swarm: case Kubernetes: default: return errors.Errorf("OrchestratorProfile has unknown orchestrator: %s", o.OrchestratorType) @@ -102,16 +99,9 @@ func (a *Properties) Validate() error { return errors.New("missing WindowsProfile") } switch a.OrchestratorProfile.OrchestratorType { - case Swarm: default: return errors.Errorf("Orchestrator %s does not support Windows", a.OrchestratorProfile.OrchestratorType) } - if len(a.WindowsProfile.AdminUsername) == 0 { - return errors.Errorf("WindowsProfile.AdminUsername must not be empty since agent pool '%s' specifies windows", agentPoolProfile.Name) - } - if len(a.WindowsProfile.AdminPassword) == 0 { - return errors.Errorf("WindowsProfile.AdminPassword must not be empty since agent pool '%s' specifies windows", agentPoolProfile.Name) - } } } return a.LinuxProfile.Validate() diff --git a/pkg/api/v20170131/const.go b/pkg/api/v20170131/const.go index 92a4eff8e2..280ea9424d 100644 --- a/pkg/api/v20170131/const.go +++ b/pkg/api/v20170131/const.go @@ -7,16 +7,8 @@ const ( // the orchestrators supported by 2017-01-31 const ( - // Mesos is the string constant for the Mesos orchestrator type - Mesos string = "Mesos" - // DCOS is the string constant for DCOS orchestrator type and defaults to DCOS187 - DCOS string = "DCOS" - // Swarm is the string constant for the Swarm orchestrator type - Swarm string = "Swarm" // Kubernetes is the string constant for the Kubernetes orchestrator type Kubernetes string = "Kubernetes" - // SwarmMode is the string constant for the Swarm Mode orchestrator type - SwarmMode string = "SwarmMode" ) const ( diff --git a/pkg/api/v20170131/types.go b/pkg/api/v20170131/types.go index 9b0d4a4ddf..9d146a23cb 100644 --- a/pkg/api/v20170131/types.go +++ b/pkg/api/v20170131/types.go @@ -30,7 +30,7 @@ type ContainerService struct { Properties *Properties `json:"properties"` } -// Properties represents the ACS cluster definition +// Properties represents the AKS cluster definition type Properties struct { ProvisioningState ProvisioningState `json:"provisioningState,omitempty"` OrchestratorProfile *OrchestratorProfile `json:"orchestratorProfile,omitempty"` @@ -223,16 +223,8 @@ func (o *OrchestratorProfile) UnmarshalJSON(b []byte) error { // Unmarshal OrchestratorType, format it as well orchestratorType := o.OrchestratorType switch { - case strings.EqualFold(orchestratorType, DCOS): - o.OrchestratorType = DCOS - case strings.EqualFold(orchestratorType, Swarm): - o.OrchestratorType = Swarm case strings.EqualFold(orchestratorType, Kubernetes): o.OrchestratorType = Kubernetes - case strings.EqualFold(orchestratorType, Mesos): - o.OrchestratorType = Mesos - case strings.EqualFold(orchestratorType, SwarmMode): - o.OrchestratorType = SwarmMode default: return errors.Errorf("OrchestratorType has unknown orchestrator: %s", orchestratorType) } @@ -272,11 +264,6 @@ func (a *AgentPoolProfile) IsLinux() bool { return a.OSType == Linux } -// IsDCOS returns true if this template is for DCOS orchestrator -func (o *OrchestratorProfile) IsDCOS() bool { - return o.OrchestratorType == DCOS -} - // GetSubnet returns the read-only subnet for the agent pool func (a *AgentPoolProfile) GetSubnet() string { return a.subnet @@ -286,8 +273,3 @@ func (a *AgentPoolProfile) GetSubnet() string { func (a *AgentPoolProfile) SetSubnet(subnet string) { a.subnet = subnet } - -// IsSwarmMode returns true if this template is for Swarm Mode orchestrator -func (o *OrchestratorProfile) IsSwarmMode() bool { - return o.OrchestratorType == SwarmMode -} diff --git a/pkg/api/v20170131/types_test.go b/pkg/api/v20170131/types_test.go index 8afb3509dc..f8a49a3aa8 100644 --- a/pkg/api/v20170131/types_test.go +++ b/pkg/api/v20170131/types_test.go @@ -5,21 +5,6 @@ import ( "testing" ) -func TestIsDCOS(t *testing.T) { - dCOSProfile := &OrchestratorProfile{ - OrchestratorType: "DCOS", - } - if !dCOSProfile.IsDCOS() { - t.Fatalf("unable to detect DCOS orchestrator profile from OrchestratorType=%s", dCOSProfile.OrchestratorType) - } - kubernetesProfile := &OrchestratorProfile{ - OrchestratorType: "Kubernetes", - } - if kubernetesProfile.IsDCOS() { - t.Fatalf("unexpectedly detected DCOS orchestrator profile from OrchestratorType=%s", kubernetesProfile.OrchestratorType) - } -} - func TestMasterProfile(t *testing.T) { MasterProfileText := "{\"count\" : 0}" mp := &MasterProfile{} diff --git a/pkg/api/v20170131/validate.go b/pkg/api/v20170131/validate.go index efc5b2cf2a..ec8f78ada3 100644 --- a/pkg/api/v20170131/validate.go +++ b/pkg/api/v20170131/validate.go @@ -3,17 +3,13 @@ package v20170131 import ( "regexp" - "github.com/Azure/acs-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/api/common" "github.com/pkg/errors" ) // Validate implements APIObject func (o *OrchestratorProfile) Validate() error { switch o.OrchestratorType { - case DCOS: - case Mesos: - case Swarm: - case SwarmMode: case Kubernetes: default: return errors.Errorf("OrchestratorProfile has unknown orchestrator: %s", o.OrchestratorType) @@ -111,7 +107,6 @@ func (a *Properties) Validate() error { return errors.New("missing WindowsProfile") } switch a.OrchestratorProfile.OrchestratorType { - case Swarm: case Kubernetes: default: return errors.Errorf("Orchestrator %s does not support Windows", a.OrchestratorProfile.OrchestratorType) diff --git a/pkg/api/v20170701/const.go b/pkg/api/v20170701/const.go index d9713aa81d..f8615d8885 100644 --- a/pkg/api/v20170701/const.go +++ b/pkg/api/v20170701/const.go @@ -7,14 +7,8 @@ const ( // the orchestrators supported by 2017-07-01 const ( - // DCOS is the string constant for DCOS orchestrator type and defaults to DCOS187 - DCOS string = "DCOS" - // Swarm is the string constant for the Swarm orchestrator type - Swarm string = "Swarm" // Kubernetes is the string constant for the Kubernetes orchestrator type Kubernetes string = "Kubernetes" - // DockerCE is the string constant for the Docker CE orchestrator type - DockerCE string = "DockerCE" ) const ( diff --git a/pkg/api/v20170701/types.go b/pkg/api/v20170701/types.go index e9b3b5dc1d..cfeceac36d 100644 --- a/pkg/api/v20170701/types.go +++ b/pkg/api/v20170701/types.go @@ -32,7 +32,7 @@ type ContainerService struct { Properties *Properties `json:"properties"` } -// Properties represents the ACS cluster definition +// Properties represents the AKS cluster definition type Properties struct { ProvisioningState ProvisioningState `json:"provisioningState,omitempty"` OrchestratorProfile *OrchestratorProfile `json:"orchestratorProfile,omitempty" validate:"required"` @@ -254,14 +254,8 @@ func (o *OrchestratorProfile) UnmarshalJSON(b []byte) error { // Unmarshal OrchestratorType, format it as well orchestratorType := o.OrchestratorType switch { - case strings.EqualFold(orchestratorType, DCOS): - o.OrchestratorType = DCOS case strings.EqualFold(orchestratorType, Kubernetes): o.OrchestratorType = Kubernetes - case strings.EqualFold(orchestratorType, Swarm): - o.OrchestratorType = Swarm - case strings.EqualFold(orchestratorType, DockerCE): - o.OrchestratorType = DockerCE default: return errors.Errorf("OrchestratorType has unknown orchestrator: %s", orchestratorType) } @@ -340,8 +334,3 @@ func (a *AgentPoolProfile) GetSubnet() string { func (a *AgentPoolProfile) SetSubnet(subnet string) { a.subnet = subnet } - -// IsSwarmMode returns true if this template is for Docker CE orchestrator -func (o *OrchestratorProfile) IsSwarmMode() bool { - return o.OrchestratorType == DockerCE -} diff --git a/pkg/api/v20170701/types_test.go b/pkg/api/v20170701/types_test.go index df6b4d79db..7c0ed6ef45 100644 --- a/pkg/api/v20170701/types_test.go +++ b/pkg/api/v20170701/types_test.go @@ -42,7 +42,7 @@ func TestAgentPoolProfile(t *testing.T) { } // With osType specified - AgentPoolProfileText = `{ "name": "linuxpool1", "osType" : "Windows", "count": 1, "vmSize": "Standard_D2_v2", + AgentPoolProfileText = `{ "name": "linuxpool1", "osType" : "Windows", "count": 1, "vmSize": "Standard_D2_v2", "availabilityProfile": "AvailabilitySet", "storageProfile" : "ManagedDisks", "vnetSubnetID" : "12345" }` ap = &AgentPoolProfile{} if e := json.Unmarshal([]byte(AgentPoolProfileText), ap); e != nil { @@ -69,33 +69,9 @@ func TestOrchestratorProfile(t *testing.T) { t.Fatalf("expected unmarshal failure for OrchestratorProfile when passing an invalid orchestratorType") } - OrchestratorProfileText = `{ "orchestratorType": "Swarm" }` - op = &OrchestratorProfile{} - if e := json.Unmarshal([]byte(OrchestratorProfileText), op); e != nil { - t.Fatalf("unexpectedly detected unmarshal failure for OrchestratorProfile, %+v", e) - } - - OrchestratorProfileText = `{ "orchestratorType": "DockerCE" }` - op = &OrchestratorProfile{} - if e := json.Unmarshal([]byte(OrchestratorProfileText), op); e != nil { - t.Fatalf("unexpectedly detected unmarshal failure for OrchestratorProfile, %+v", e) - } - - if !op.IsSwarmMode() { - t.Fatalf("unexpectedly detected OrchestratorProfile.Type != DockerCE after unmarshal") - - } - - OrchestratorProfileText = `{ "orchestratorType": "DCOS" }` - op = &OrchestratorProfile{} - if e := json.Unmarshal([]byte(OrchestratorProfileText), op); e != nil { - t.Fatalf("unexpectedly detected unmarshal failure for OrchestratorProfile, %+v", e) - } - OrchestratorProfileText = `{ "orchestratorType": "Kubernetes" }` op = &OrchestratorProfile{} if e := json.Unmarshal([]byte(OrchestratorProfileText), op); e != nil { t.Fatalf("unexpectedly detected unmarshal failure for OrchestratorProfile, %+v", e) - } } diff --git a/pkg/api/v20170701/validate.go b/pkg/api/v20170701/validate.go index 41806cce82..8fc2dc2ec2 100644 --- a/pkg/api/v20170701/validate.go +++ b/pkg/api/v20170701/validate.go @@ -4,7 +4,7 @@ import ( "net" "regexp" - "github.com/Azure/acs-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/api/common" "github.com/pkg/errors" "gopkg.in/go-playground/validator.v9" ) @@ -26,19 +26,6 @@ func (o *OrchestratorProfile) Validate(isUpdate, hasWindows bool) error { // On updates we only need to make sure there is a supported patch version for the minor version if !isUpdate { switch o.OrchestratorType { - case Swarm: - case DCOS: - switch o.OrchestratorVersion { - case common.DCOSVersion1Dot11Dot0: - case common.DCOSVersion1Dot10Dot0: - case common.DCOSVersion1Dot9Dot0: - case common.DCOSVersion1Dot9Dot8: - case common.DCOSVersion1Dot8Dot8: - case "": - default: - return errors.Errorf("OrchestratorProfile has unknown orchestrator version: %s", o.OrchestratorVersion) - } - case DockerCE: case Kubernetes: if k8sVersion := o.OrchestratorVersion; !common.IsSupportedKubernetesVersion(k8sVersion, isUpdate, hasWindows) && o.OrchestratorVersion != "" { return errors.Errorf("OrchestratorProfile has unknown orchestrator version: %s", o.OrchestratorVersion) @@ -49,7 +36,7 @@ func (o *OrchestratorProfile) Validate(isUpdate, hasWindows bool) error { } } else { switch o.OrchestratorType { - case DCOS, Kubernetes: + case Kubernetes: patchVersion := common.GetValidPatchVersion(o.OrchestratorType, o.OrchestratorVersion, isUpdate, hasWindows) // if there isn't a supported patch version for this version fail if patchVersion == "" { diff --git a/pkg/api/v20170930/const.go b/pkg/api/v20170930/const.go index ce51ef0976..be2235c45a 100644 --- a/pkg/api/v20170930/const.go +++ b/pkg/api/v20170930/const.go @@ -7,12 +7,6 @@ const ( // the orchestrators supported by 2017-07-01 const ( - // DCOS is the string constant for DCOS orchestrator type and defaults to DCOS187 - DCOS string = "DCOS" - // Swarm is the string constant for the Swarm orchestrator type - Swarm string = "Swarm" // Kubernetes is the string constant for the Kubernetes orchestrator type Kubernetes string = "Kubernetes" - // DockerCE is the string constant for the Docker CE orchestrator type - DockerCE string = "DockerCE" ) diff --git a/pkg/api/v20170930/types.go b/pkg/api/v20170930/types.go index b4a60be81e..a612b6d8ad 100644 --- a/pkg/api/v20170930/types.go +++ b/pkg/api/v20170930/types.go @@ -4,7 +4,7 @@ package v20170930 type OSType string // OrchestratorProfile contains orchestrator properties: -// - type: kubernetes, DCOS, etc. +// - type: kubernetes, etc. // - release: major and minor version numbers // - version: major, minor, and patch version numbers type OrchestratorProfile struct { diff --git a/pkg/api/v20170930/validate.go b/pkg/api/v20170930/validate.go index 1b6d6b5ca7..db7b384cd6 100644 --- a/pkg/api/v20170930/validate.go +++ b/pkg/api/v20170930/validate.go @@ -11,12 +11,6 @@ func (o *OrchestratorVersionProfile) Validate() error { switch { case strings.EqualFold(o.OrchestratorType, Kubernetes): o.OrchestratorType = Kubernetes - case strings.EqualFold(o.OrchestratorType, DCOS): - o.OrchestratorType = DCOS - case strings.EqualFold(o.OrchestratorType, Swarm): - o.OrchestratorType = Swarm - case strings.EqualFold(o.OrchestratorType, DockerCE): - o.OrchestratorType = DockerCE default: return errors.Errorf("Unsupported orchestrator '%s'", o.OrchestratorType) } @@ -26,8 +20,6 @@ func (o *OrchestratorVersionProfile) Validate() error { // ValidateForUpgrade validates upgrade input data func (o *OrchestratorProfile) ValidateForUpgrade() error { switch o.OrchestratorType { - case DCOS, DockerCE, Swarm: - return errors.Errorf("Upgrade is not supported for orchestrator %s", o.OrchestratorType) case Kubernetes: switch o.OrchestratorVersion { case "1.6.13": diff --git a/pkg/api/vlabs/const.go b/pkg/api/vlabs/const.go index 29778da911..ed18b35ac9 100644 --- a/pkg/api/vlabs/const.go +++ b/pkg/api/vlabs/const.go @@ -7,16 +7,8 @@ const ( // the orchestrators supported by vlabs const ( - // DCOS is the string constant for DCOS orchestrator type and defaults to DCOS188 - DCOS string = "DCOS" - // Swarm is the string constant for the Swarm orchestrator type - Swarm string = "Swarm" // Kubernetes is the string constant for the Kubernetes orchestrator type Kubernetes string = "Kubernetes" - // SwarmMode is the string constant for the Swarm Mode orchestrator type - SwarmMode string = "SwarmMode" - // OpenShift is the string constant for the OpenShift orchestrator type - OpenShift string = "OpenShift" ) // the OSTypes supported by vlabs diff --git a/pkg/api/vlabs/types.go b/pkg/api/vlabs/types.go index 2466bdb9d3..0ec480dc84 100644 --- a/pkg/api/vlabs/types.go +++ b/pkg/api/vlabs/types.go @@ -4,7 +4,7 @@ import ( "encoding/json" "strings" - "github.com/Azure/acs-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/api/common" "github.com/pkg/errors" ) @@ -30,7 +30,7 @@ type ContainerService struct { Properties *Properties `json:"properties"` } -// Properties represents the ACS cluster definition +// Properties represents the AKS cluster definition type Properties struct { ProvisioningState ProvisioningState `json:"provisioningState,omitempty"` OrchestratorProfile *OrchestratorProfile `json:"orchestratorProfile,omitempty" validate:"required"` @@ -194,8 +194,6 @@ type OrchestratorProfile struct { OrchestratorRelease string `json:"orchestratorRelease,omitempty"` OrchestratorVersion string `json:"orchestratorVersion,omitempty"` KubernetesConfig *KubernetesConfig `json:"kubernetesConfig,omitempty"` - OpenShiftConfig *OpenShiftConfig `json:"openshiftConfig,omitempty"` - DcosConfig *DcosConfig `json:"dcosConfig,omitempty"` } // UnmarshalJSON unmarshal json using the default behavior @@ -211,16 +209,8 @@ func (o *OrchestratorProfile) UnmarshalJSON(b []byte) error { // Unmarshal OrchestratorType, format it as well orchestratorType := o.OrchestratorType switch { - case strings.EqualFold(orchestratorType, DCOS): - o.OrchestratorType = DCOS - case strings.EqualFold(orchestratorType, Swarm): - o.OrchestratorType = Swarm case strings.EqualFold(orchestratorType, Kubernetes): o.OrchestratorType = Kubernetes - case strings.EqualFold(orchestratorType, SwarmMode): - o.OrchestratorType = SwarmMode - case strings.EqualFold(orchestratorType, OpenShift): - o.OrchestratorType = OpenShift default: return errors.Errorf("OrchestratorType has unknown orchestrator: %s", orchestratorType) } @@ -333,42 +323,6 @@ type CustomFile struct { Dest string `json:"dest,omitempty"` } -// BootstrapProfile represents the definition of the DCOS bootstrap node used to deploy the cluster -type BootstrapProfile struct { - VMSize string `json:"vmSize,omitempty"` - OSDiskSizeGB int `json:"osDiskSizeGB,omitempty"` - OAuthEnabled bool `json:"oauthEnabled,omitempty"` - StaticIP string `json:"staticIP,omitempty"` - Subnet string `json:"subnet,omitempty"` -} - -// DcosConfig Configuration for DC/OS -type DcosConfig struct { - DcosBootstrapURL string `json:"dcosBootstrapURL,omitempty"` - DcosWindowsBootstrapURL string `json:"dcosWindowsBootstrapURL,omitempty"` - Registry string `json:"registry,omitempty"` - RegistryUser string `json:"registryUser,omitempty"` - RegistryPass string `json:"registryPassword,omitempty"` - DcosRepositoryURL string `json:"dcosRepositoryURL,omitempty"` // For CI use, you need to specify - DcosClusterPackageListID string `json:"dcosClusterPackageListID,omitempty"` // all three of these items - DcosProviderPackageID string `json:"dcosProviderPackageID,omitempty"` // repo url is the location of the build, - BootstrapProfile *BootstrapProfile `json:"bootstrapProfile,omitempty"` -} - -// OpenShiftConfig holds configuration for OpenShift -type OpenShiftConfig struct { - KubernetesConfig *KubernetesConfig `json:"kubernetesConfig,omitempty"` - - // ClusterUsername and ClusterPassword are temporary, do not rely on them. - ClusterUsername string `json:"clusterUsername,omitempty"` - ClusterPassword string `json:"clusterPassword,omitempty"` - - // EnableAADAuthentication is temporary, do not rely on it. - EnableAADAuthentication bool `json:"enableAADAuthentication,omitempty"` - - ConfigBundles map[string][]byte `json:"configBundles,omitempty"` -} - // MasterProfile represents the definition of the master cluster type MasterProfile struct { Count int `json:"count" validate:"required,eq=1|eq=3|eq=5"` @@ -699,11 +653,6 @@ func (l *LinuxProfile) HasCustomNodesDNS() bool { return false } -// IsSwarmMode returns true if this template is for Swarm Mode orchestrator -func (o *OrchestratorProfile) IsSwarmMode() bool { - return o.OrchestratorType == SwarmMode -} - // RequiresDocker returns if the kubernetes settings require docker binary to be installed. func (k *KubernetesConfig) RequiresDocker() bool { runtime := strings.ToLower(k.ContainerRuntime) diff --git a/pkg/api/vlabs/types_test.go b/pkg/api/vlabs/types_test.go index 0f6cae7f74..4b340f347f 100644 --- a/pkg/api/vlabs/types_test.go +++ b/pkg/api/vlabs/types_test.go @@ -4,7 +4,7 @@ import ( "encoding/json" "testing" - "github.com/Azure/acs-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/api/common" ) func TestKubernetesAddon(t *testing.T) { @@ -52,29 +52,6 @@ func TestOrchestratorProfile(t *testing.T) { t.Fatalf("expected unmarshal failure for OrchestratorProfile when passing an invalid orchestratorType") } - OrchestratorProfileText = `{ "orchestratorType": "Swarm" }` - op = &OrchestratorProfile{} - if e := json.Unmarshal([]byte(OrchestratorProfileText), op); e != nil { - t.Fatalf("unexpectedly detected unmarshal failure for OrchestratorProfile, %+v", e) - } - - OrchestratorProfileText = `{ "orchestratorType": "SwarmMode" }` - op = &OrchestratorProfile{} - if e := json.Unmarshal([]byte(OrchestratorProfileText), op); e != nil { - t.Fatalf("unexpectedly detected unmarshal failure for OrchestratorProfile, %+v", e) - } - - if !op.IsSwarmMode() { - t.Fatalf("unexpectedly detected OrchestratorProfile.Type != DockerCE after unmarshal") - - } - - OrchestratorProfileText = `{ "orchestratorType": "DCOS" }` - op = &OrchestratorProfile{} - if e := json.Unmarshal([]byte(OrchestratorProfileText), op); e != nil { - t.Fatalf("unexpectedly detected unmarshal failure for OrchestratorProfile, %+v", e) - } - OrchestratorProfileText = `{ "orchestratorType": "Kubernetes" }` op = &OrchestratorProfile{} if e := json.Unmarshal([]byte(OrchestratorProfileText), op); e != nil { @@ -166,7 +143,7 @@ func TestAgentPoolProfile(t *testing.T) { } // With osType Windows - AgentPoolProfileText = `{ "name": "linuxpool1", "osType" : "Windows", "count": 1, "vmSize": "Standard_D2_v2", + AgentPoolProfileText = `{ "name": "linuxpool1", "osType" : "Windows", "count": 1, "vmSize": "Standard_D2_v2", "availabilityProfile": "AvailabilitySet", "storageProfile" : "ManagedDisks", "vnetSubnetID" : "12345" }` ap = &AgentPoolProfile{} if e := json.Unmarshal([]byte(AgentPoolProfileText), ap); e != nil { @@ -186,7 +163,7 @@ func TestAgentPoolProfile(t *testing.T) { } // With osType Linux and RHEL distro - AgentPoolProfileText = `{ "name": "linuxpool1", "osType" : "Linux", "distro" : "rhel", "count": 1, "vmSize": "Standard_D2_v2", + AgentPoolProfileText = `{ "name": "linuxpool1", "osType" : "Linux", "distro" : "rhel", "count": 1, "vmSize": "Standard_D2_v2", "availabilityProfile": "AvailabilitySet", "storageProfile" : "ManagedDisks", "vnetSubnetID" : "12345" }` ap = &AgentPoolProfile{} if e := json.Unmarshal([]byte(AgentPoolProfileText), ap); e != nil { @@ -210,7 +187,7 @@ func TestAgentPoolProfile(t *testing.T) { } // With osType Linux and coreos distro - AgentPoolProfileText = `{ "name": "linuxpool1", "osType" : "Linux", "distro" : "coreos", "count": 1, "vmSize": "Standard_D2_v2", + AgentPoolProfileText = `{ "name": "linuxpool1", "osType" : "Linux", "distro" : "coreos", "count": 1, "vmSize": "Standard_D2_v2", "availabilityProfile": "VirtualMachineScaleSets", "storageProfile" : "ManagedDisks", "diskSizesGB" : [750, 250, 600, 1000] }` ap = &AgentPoolProfile{} if e := json.Unmarshal([]byte(AgentPoolProfileText), ap); e != nil { @@ -244,7 +221,7 @@ func TestAgentPoolProfile(t *testing.T) { func TestContainerServiceProperties(t *testing.T) { // Agent pool with availability zones - ContainerServicePropertiesText := `{"orchestratorProfile": {"orchestratorType": "Kubernetes","orchestratorRelease": "1.11"}, "agentPoolProfiles":[{ "name": "linuxpool1", "osType" : "Linux", "count": 1, "vmSize": "Standard_D2_v2", + ContainerServicePropertiesText := `{"orchestratorProfile": {"orchestratorType": "Kubernetes","orchestratorRelease": "1.11"}, "agentPoolProfiles":[{ "name": "linuxpool1", "osType" : "Linux", "count": 1, "vmSize": "Standard_D2_v2", "availabilityProfile": "VirtualMachineScaleSets", "AvailabilityZones": ["1","2"]}]}` prop := &Properties{} if e := json.Unmarshal([]byte(ContainerServicePropertiesText), prop); e != nil { @@ -256,7 +233,7 @@ func TestContainerServiceProperties(t *testing.T) { } // master profile with availability zones - ContainerServicePropertiesText = `{"orchestratorProfile": {"orchestratorType": "Kubernetes","orchestratorRelease": "1.12"}, "masterProfile":{"count": 4, "vmSize": "Standard_D2_v2", "availabilityProfile": "VirtualMachineScaleSets", "storageProfile": "ManagedDisks", "diskSizesGB": [750, 250, 600, 1000], "availabilityZones": ["1","2"] }, "agentPoolProfiles":[{ "name": "linuxpool1", "osType" : "Linux", "count": 1, "vmSize": "Standard_D2_v2", + ContainerServicePropertiesText = `{"orchestratorProfile": {"orchestratorType": "Kubernetes","orchestratorRelease": "1.12"}, "masterProfile":{"count": 4, "vmSize": "Standard_D2_v2", "availabilityProfile": "VirtualMachineScaleSets", "storageProfile": "ManagedDisks", "diskSizesGB": [750, 250, 600, 1000], "availabilityZones": ["1","2"] }, "agentPoolProfiles":[{ "name": "linuxpool1", "osType" : "Linux", "count": 1, "vmSize": "Standard_D2_v2", "availabilityProfile": "VirtualMachineScaleSets"}]}` prop = &Properties{} if e := json.Unmarshal([]byte(ContainerServicePropertiesText), prop); e != nil { @@ -271,7 +248,7 @@ func TestContainerServiceProperties(t *testing.T) { t.Fatalf("unexpectedly detected ContainerServiceProperties MastersAndAgentsUseAvailabilityZones returns true after unmarshal") } // master profile and agent profile with availability zones - ContainerServicePropertiesText = `{"orchestratorProfile": {"orchestratorType": "Kubernetes","orchestratorRelease": "1.12"}, "masterProfile":{"count": 4, "vmSize": "Standard_D2_v2", "availabilityProfile": "VirtualMachineScaleSets", "storageProfile": "ManagedDisks", "diskSizesGB": [750, 250, 600, 1000], "availabilityZones": ["1","2"] }, "agentPoolProfiles":[{ "name": "linuxpool1", "osType" : "Linux", "count": 1, "vmSize": "Standard_D2_v2", + ContainerServicePropertiesText = `{"orchestratorProfile": {"orchestratorType": "Kubernetes","orchestratorRelease": "1.12"}, "masterProfile":{"count": 4, "vmSize": "Standard_D2_v2", "availabilityProfile": "VirtualMachineScaleSets", "storageProfile": "ManagedDisks", "diskSizesGB": [750, 250, 600, 1000], "availabilityZones": ["1","2"] }, "agentPoolProfiles":[{ "name": "linuxpool1", "osType" : "Linux", "count": 1, "vmSize": "Standard_D2_v2", "availabilityProfile": "VirtualMachineScaleSets", "availabilityZones": ["1","2"] }]}` prop = &Properties{} if e := json.Unmarshal([]byte(ContainerServicePropertiesText), prop); e != nil { diff --git a/pkg/api/vlabs/validate.go b/pkg/api/vlabs/validate.go index 8d5dc1c596..e2fc737748 100644 --- a/pkg/api/vlabs/validate.go +++ b/pkg/api/vlabs/validate.go @@ -5,13 +5,12 @@ import ( "fmt" "net" "net/url" - "reflect" "regexp" "strings" "time" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/helpers" "github.com/blang/semver" "github.com/pkg/errors" "github.com/satori/go.uuid" @@ -145,9 +144,6 @@ func (a *Properties) Validate(isUpdate bool) error { return e } - if e := a.validateAzProfile(); e != nil { - return e - } return nil } @@ -162,26 +158,6 @@ func (a *Properties) validateOrchestratorProfile(isUpdate bool) error { // On updates we only need to make sure there is a supported patch version for the minor version if !isUpdate { switch o.OrchestratorType { - case DCOS: - version := common.RationalizeReleaseAndVersion( - o.OrchestratorType, - o.OrchestratorRelease, - o.OrchestratorVersion, - isUpdate, - false) - if version == "" { - return errors.Errorf("the following OrchestratorProfile configuration is not supported: OrchestratorType: %s, OrchestratorRelease: %s, OrchestratorVersion: %s. Please check supported Release or Version for this build of acs-engine", o.OrchestratorType, o.OrchestratorRelease, o.OrchestratorVersion) - } - if o.DcosConfig != nil && o.DcosConfig.BootstrapProfile != nil { - if len(o.DcosConfig.BootstrapProfile.StaticIP) > 0 { - if net.ParseIP(o.DcosConfig.BootstrapProfile.StaticIP) == nil { - return errors.Errorf("DcosConfig.BootstrapProfile.StaticIP '%s' is an invalid IP address", - o.DcosConfig.BootstrapProfile.StaticIP) - } - } - } - case Swarm: - case SwarmMode: case Kubernetes: version := common.RationalizeReleaseAndVersion( o.OrchestratorType, @@ -267,7 +243,7 @@ func (a *Properties) validateOrchestratorProfile(isUpdate bool) error { return errors.Errorf("could not validate version") } if sv.LT(minVersion) { - return errors.Errorf("enablePodSecurityPolicy is only supported in acs-engine for Kubernetes version %s or greater; unable to validate for Kubernetes version %s", + return errors.Errorf("enablePodSecurityPolicy is only supported in aks-engine for Kubernetes version %s or greater; unable to validate for Kubernetes version %s", minVersion.String(), version) } } @@ -290,29 +266,12 @@ func (a *Properties) validateOrchestratorProfile(isUpdate bool) error { log.Warnf("docker-engine is deprecated in favor of moby, but you passed in a dockerEngineVersion configuration. This will be ignored.") } } - case OpenShift: - // TODO: add appropriate additional validation logic - if o.OrchestratorVersion != common.OpenShiftVersionUnstable { - version := common.RationalizeReleaseAndVersion( - o.OrchestratorType, - o.OrchestratorRelease, - o.OrchestratorVersion, - isUpdate, - false) - if version == "" { - return errors.Errorf("OrchestratorProfile is not able to be rationalized, check supported Release or Version") - } - } - if o.OpenShiftConfig == nil { - return errors.Errorf("OpenShiftConfig must be specified for OpenShift orchestrator") - } - return o.OpenShiftConfig.Validate() default: return errors.Errorf("OrchestratorProfile has unknown orchestrator: %s", o.OrchestratorType) } } else { switch o.OrchestratorType { - case DCOS, Kubernetes: + case Kubernetes: version := common.RationalizeReleaseAndVersion( o.OrchestratorType, @@ -325,25 +284,17 @@ func (a *Properties) validateOrchestratorProfile(isUpdate bool) error { // if there isn't a supported patch version for this version fail if patchVersion == "" { if a.HasWindows() { - return errors.Errorf("the following OrchestratorProfile configuration is not supported with Windows agentpools: OrchestratorType: \"%s\", OrchestratorRelease: \"%s\", OrchestratorVersion: \"%s\". Please check supported Release or Version for this build of acs-engine", o.OrchestratorType, o.OrchestratorRelease, o.OrchestratorVersion) + return errors.Errorf("the following OrchestratorProfile configuration is not supported with Windows agentpools: OrchestratorType: \"%s\", OrchestratorRelease: \"%s\", OrchestratorVersion: \"%s\". Please check supported Release or Version for this build of aks-engine", o.OrchestratorType, o.OrchestratorRelease, o.OrchestratorVersion) } - return errors.Errorf("the following OrchestratorProfile configuration is not supported: OrchestratorType: \"%s\", OrchestratorRelease: \"%s\", OrchestratorVersion: \"%s\". Please check supported Release or Version for this build of acs-engine", o.OrchestratorType, o.OrchestratorRelease, o.OrchestratorVersion) + return errors.Errorf("the following OrchestratorProfile configuration is not supported: OrchestratorType: \"%s\", OrchestratorRelease: \"%s\", OrchestratorVersion: \"%s\". Please check supported Release or Version for this build of aks-engine", o.OrchestratorType, o.OrchestratorRelease, o.OrchestratorVersion) } } } } - if (o.OrchestratorType != Kubernetes && o.OrchestratorType != OpenShift) && o.KubernetesConfig != nil { - return errors.Errorf("KubernetesConfig can be specified only when OrchestratorType is Kubernetes or OpenShift") - } - - if o.OrchestratorType != OpenShift && o.OpenShiftConfig != nil { - return errors.Errorf("OpenShiftConfig can be specified only when OrchestratorType is OpenShift") - } - - if o.OrchestratorType != DCOS && o.DcosConfig != nil && (*o.DcosConfig != DcosConfig{}) { - return errors.Errorf("DcosConfig can be specified only when OrchestratorType is DCOS") + if (o.OrchestratorType != Kubernetes) && o.KubernetesConfig != nil { + return errors.Errorf("KubernetesConfig can be specified only when OrchestratorType is Kubernetes") } if e := a.validateContainerRuntime(); e != nil { @@ -355,18 +306,6 @@ func (a *Properties) validateOrchestratorProfile(isUpdate bool) error { func (a *Properties) validateMasterProfile() error { m := a.MasterProfile - if a.OrchestratorProfile.OrchestratorType == OpenShift { - if m.Count != 1 { - return errors.New("openshift can only deployed with one master") - } - if m.VnetSubnetID != "" && m.FirstConsecutiveStaticIP == "" { - return errors.New("when specifying a vnetsubnetid the firstconsecutivestaticip is required") - } - if m.StorageProfile != ManagedDisks { - return errors.New("OpenShift orchestrator supports only ManagedDisks") - } - } - if a.OrchestratorProfile.OrchestratorType == Kubernetes { if m.IsVirtualMachineScaleSets() && m.VnetSubnetID != "" && m.FirstConsecutiveStaticIP != "" { return errors.New("when masterProfile's availabilityProfile is VirtualMachineScaleSets and a vnetSubnetID is specified, the firstConsecutiveStaticIP should be empty and will be determined by an offset from the first IP in the vnetCidr") @@ -380,7 +319,7 @@ func (a *Properties) validateMasterProfile() error { } if m.IsVirtualMachineScaleSets() && a.OrchestratorProfile.OrchestratorType == Kubernetes { - log.Warnf("Clusters with VMSS masters are not yet upgradable! You will not be able to upgrade your cluster until a future version of acs-engine!") + log.Warnf("Clusters with VMSS masters are not yet upgradable! You will not be able to upgrade your cluster until a future version of aks-engine!") e := validateVMSS(a.OrchestratorProfile, false, m.StorageProfile) if e != nil { return e @@ -465,23 +404,11 @@ func (a *Properties) validateAgentPoolProfiles(isUpdate bool) error { } } - if a.OrchestratorProfile.OrchestratorType == OpenShift { - if (agentPoolProfile.Name == "infra") != (agentPoolProfile.Role == "infra") { - return errors.New("OpenShift requires that the 'infra' agent pool profile, and no other, should have role 'infra'") - } - } - if e := agentPoolProfile.validateWindows(a.OrchestratorProfile, a.WindowsProfile, isUpdate); agentPoolProfile.OSType == Windows && e != nil { return e } } - if a.OrchestratorProfile.OrchestratorType == OpenShift { - if !reflect.DeepEqual(profileNames, map[string]bool{"compute": true, "infra": true}) { - return errors.New("OpenShift requires exactly two agent pool profiles: compute and infra") - } - } - return nil } @@ -563,7 +490,7 @@ func (a *Properties) validateAddons() error { false, false) if version == "" { - return errors.Errorf("the following user supplied OrchestratorProfile configuration is not supported: OrchestratorType: %s, OrchestratorRelease: %s, OrchestratorVersion: %s. Please check supported Release or Version for this build of acs-engine", a.OrchestratorProfile.OrchestratorType, a.OrchestratorProfile.OrchestratorRelease, a.OrchestratorProfile.OrchestratorVersion) + return errors.Errorf("the following user supplied OrchestratorProfile configuration is not supported: OrchestratorType: %s, OrchestratorRelease: %s, OrchestratorVersion: %s. Please check supported Release or Version for this build of aks-engine", a.OrchestratorProfile.OrchestratorType, a.OrchestratorProfile.OrchestratorRelease, a.OrchestratorProfile.OrchestratorVersion) } sv, err := semver.Make(version) if err != nil { @@ -700,7 +627,7 @@ func (a *Properties) validateManagedIdentity() error { false, false) if version == "" { - return errors.Errorf("the following user supplied OrchestratorProfile configuration is not supported: OrchestratorType: %s, OrchestratorRelease: %s, OrchestratorVersion: %s. Please check supported Release or Version for this build of acs-engine", a.OrchestratorProfile.OrchestratorType, a.OrchestratorProfile.OrchestratorRelease, a.OrchestratorProfile.OrchestratorVersion) + return errors.Errorf("the following user supplied OrchestratorProfile configuration is not supported: OrchestratorType: %s, OrchestratorRelease: %s, OrchestratorVersion: %s. Please check supported Release or Version for this build of aks-engine", a.OrchestratorProfile.OrchestratorType, a.OrchestratorProfile.OrchestratorRelease, a.OrchestratorProfile.OrchestratorVersion) } sv, err := semver.Make(version) if err != nil { @@ -749,30 +676,6 @@ func (a *Properties) validateAADProfile() error { return nil } -func (a *Properties) validateAzProfile() error { - switch a.OrchestratorProfile.OrchestratorType { - case OpenShift: - if a.AzProfile == nil || a.AzProfile.Location == "" || - a.AzProfile.ResourceGroup == "" || a.AzProfile.SubscriptionID == "" || - a.AzProfile.TenantID == "" { - return errors.Errorf("'azProfile' must be supplied in full for orchestrator '%v'", OpenShift) - } - default: - if a.AzProfile != nil { - return errors.Errorf("'azProfile' is only supported by orchestrator '%v'", OpenShift) - } - } - return nil -} - -// Validate OpenShiftConfig ensures that the OpenShiftConfig is valid. -func (o *OpenShiftConfig) Validate() error { - if o.ClusterUsername == "" || o.ClusterPassword == "" { - return errors.Errorf("ClusterUsername and ClusterPassword must both be specified") - } - return nil -} - func (a *AgentPoolProfile) validateAvailabilityProfile(orchestratorType string) error { switch a.AvailabilityProfile { case AvailabilitySet: @@ -783,18 +686,11 @@ func (a *AgentPoolProfile) validateAvailabilityProfile(orchestratorType string) return errors.Errorf("unknown availability profile type '%s' for agent pool '%s'. Specify either %s, or %s", a.AvailabilityProfile, a.Name, AvailabilitySet, VirtualMachineScaleSets) } } - - if orchestratorType == OpenShift && a.AvailabilityProfile != AvailabilitySet { - return errors.Errorf("Only AvailabilityProfile: AvailabilitySet is supported for Orchestrator 'OpenShift'") - } return nil } func (a *AgentPoolProfile) validateRoles(orchestratorType string) error { validRoles := []AgentPoolProfileRole{AgentPoolProfileRoleEmpty} - if orchestratorType == OpenShift { - validRoles = append(validRoles, AgentPoolProfileRoleInfra) - } var found bool for _, validRole := range validRoles { if a.Role == validRole { @@ -812,27 +708,18 @@ func (a *AgentPoolProfile) validateStorageProfile(orchestratorType string) error /* this switch statement is left to protect newly added orchestrators until they support Managed Disks*/ if a.StorageProfile == ManagedDisks { switch orchestratorType { - case DCOS: - case Swarm: case Kubernetes: - case OpenShift: - case SwarmMode: default: return errors.Errorf("HA volumes are currently unsupported for Orchestrator %s", orchestratorType) } } - if orchestratorType == OpenShift && a.StorageProfile != ManagedDisks { - return errors.New("OpenShift orchestrator supports only ManagedDisks") - } - return nil } func (a *AgentPoolProfile) validateCustomNodeLabels(orchestratorType string) error { if len(a.CustomNodeLabels) > 0 { switch orchestratorType { - case DCOS: case Kubernetes: for k, v := range a.CustomNodeLabels { if e := validateKubernetesLabelKey(k); e != nil { @@ -843,7 +730,7 @@ func (a *AgentPoolProfile) validateCustomNodeLabels(orchestratorType string) err } } default: - return errors.New("Agent CustomNodeLabels are only supported for DCOS and Kubernetes") + return errors.New("Agent CustomNodeLabels are only supported for Kubernetes") } } return nil @@ -868,7 +755,7 @@ func validateVMSS(o *OrchestratorProfile, isUpdate bool, storageProfile string) isUpdate, false) if version == "" { - return errors.Errorf("the following OrchestratorProfile configuration is not supported: OrchestratorType: %s, OrchestratorRelease: %s, OrchestratorVersion: %s. Please check supported Release or Version for this build of acs-engine", o.OrchestratorType, o.OrchestratorRelease, o.OrchestratorVersion) + return errors.Errorf("the following OrchestratorProfile configuration is not supported: OrchestratorType: %s, OrchestratorRelease: %s, OrchestratorVersion: %s. Please check supported Release or Version for this build of aks-engine", o.OrchestratorType, o.OrchestratorRelease, o.OrchestratorVersion) } sv, err := semver.Make(version) @@ -901,9 +788,6 @@ func validateVMSS(o *OrchestratorProfile, isUpdate bool, storageProfile string) func (a *AgentPoolProfile) validateWindows(o *OrchestratorProfile, w *WindowsProfile, isUpdate bool) error { switch o.OrchestratorType { - case DCOS: - case Swarm: - case SwarmMode: case Kubernetes: version := common.RationalizeReleaseAndVersion( o.OrchestratorType, @@ -999,8 +883,8 @@ func validateKeyVaultSecrets(secrets []KeyVaultSecrets, requireCertificateStore // Validate ensures that the WindowsProfile is valid func (w *WindowsProfile) Validate(orchestratorType string) error { if w.WindowsImageSourceURL != "" { - if orchestratorType != DCOS && orchestratorType != Kubernetes { - return errors.New("Windows Custom Images are only supported if the Orchestrator Type is DCOS or Kubernetes") + if orchestratorType != Kubernetes { + return errors.New("Windows Custom Images are only supported if the Orchestrator Type is Kubernetes") } } if e := validate.Var(w.AdminUsername, "required"); e != nil { @@ -1097,7 +981,7 @@ func (k *KubernetesConfig) Validate(k8sVersion string, hasWindows bool) error { ctrlMgrNodeMonitorGracePeriod, _ := time.ParseDuration(k.ControllerManagerConfig["--node-monitor-grace-period"]) kubeletRetries := ctrlMgrNodeMonitorGracePeriod.Seconds() / nodeStatusUpdateFrequency.Seconds() if kubeletRetries < minKubeletRetries { - return errors.Errorf("acs-engine requires that --node-monitor-grace-period(%f)s be larger than nodeStatusUpdateFrequency(%f)s by at least a factor of %d; ", ctrlMgrNodeMonitorGracePeriod.Seconds(), nodeStatusUpdateFrequency.Seconds(), minKubeletRetries) + return errors.Errorf("aks-engine requires that --node-monitor-grace-period(%f)s be larger than nodeStatusUpdateFrequency(%f)s by at least a factor of %d; ", ctrlMgrNodeMonitorGracePeriod.Seconds(), nodeStatusUpdateFrequency.Seconds(), minKubeletRetries) } } } diff --git a/pkg/api/vlabs/validate_test.go b/pkg/api/vlabs/validate_test.go index bb82f13a7d..3f26a9f7f3 100644 --- a/pkg/api/vlabs/validate_test.go +++ b/pkg/api/vlabs/validate_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/helpers" "github.com/blang/semver" "github.com/pkg/errors" ) @@ -35,17 +35,6 @@ func Test_OrchestratorProfile_Validate(t *testing.T) { expectedError string isUpdate bool }{ - "should error when KubernetesConfig populated for non-Kubernetes OrchestratorType": { - properties: &Properties{ - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: "DCOS", - KubernetesConfig: &KubernetesConfig{ - ClusterSubnet: "10.0.0.0/16", - }, - }, - }, - expectedError: "KubernetesConfig can be specified only when OrchestratorType is Kubernetes or OpenShift", - }, "should error when KubernetesConfig has invalid etcd version": { properties: &Properties{ OrchestratorProfile: &OrchestratorProfile{ @@ -154,61 +143,15 @@ func Test_OrchestratorProfile_Validate(t *testing.T) { }, }, }, - expectedError: "enablePodSecurityPolicy is only supported in acs-engine for Kubernetes version 1.8.0 or greater; unable to validate for Kubernetes version 1.7.16", + expectedError: "enablePodSecurityPolicy is only supported in aks-engine for Kubernetes version 1.8.0 or greater; unable to validate for Kubernetes version 1.7.16", }, "should not error with empty object": { properties: &Properties{ OrchestratorProfile: &OrchestratorProfile{ OrchestratorType: "Kubernetes", - DcosConfig: &DcosConfig{}, }, }, }, - "should error when DcosConfig orchestrator has invalid configuration": { - properties: &Properties{ - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: "DCOS", - OrchestratorVersion: "1.12.0", - }, - }, - expectedError: "the following OrchestratorProfile configuration is not supported: OrchestratorType: DCOS, OrchestratorRelease: , OrchestratorVersion: 1.12.0. Please check supported Release or Version for this build of acs-engine", - }, - "should error when DcosConfig orchestrator configuration has invalid static IP": { - properties: &Properties{ - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: "DCOS", - DcosConfig: &DcosConfig{ - BootstrapProfile: &BootstrapProfile{ - StaticIP: "0.0.0.0.0.0", - }, - }, - }, - }, - expectedError: "DcosConfig.BootstrapProfile.StaticIP '0.0.0.0.0.0' is an invalid IP address", - }, - "should error when DcosConfig populated for non-Kubernetes OrchestratorType 1": { - properties: &Properties{ - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: "Kubernetes", - DcosConfig: &DcosConfig{ - DcosWindowsBootstrapURL: "http://www.microsoft.com", - }, - }, - }, - expectedError: "DcosConfig can be specified only when OrchestratorType is DCOS", - }, - "should error when DcosConfig populated for non-Kubernetes OrchestratorType 2": { - properties: &Properties{ - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: "Kubernetes", - DcosConfig: &DcosConfig{ - DcosWindowsBootstrapURL: "http://www.microsoft.com", - DcosBootstrapURL: "http://www.microsoft.com", - }, - }, - }, - expectedError: "DcosConfig can be specified only when OrchestratorType is DCOS", - }, "kubernetes should have failed on old patch version": { properties: &Properties{ OrchestratorProfile: &OrchestratorProfile{ @@ -235,51 +178,6 @@ func Test_OrchestratorProfile_Validate(t *testing.T) { }, }, }, - "openshift should have failed on old version": { - properties: &Properties{ - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: OpenShift, - OrchestratorVersion: "v1.0", - }, - }, - expectedError: "OrchestratorProfile is not able to be rationalized, check supported Release or Version", - }, - "openshift should not have failed on old version if update": { - properties: &Properties{ - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: OpenShift, - OrchestratorVersion: "v1.0", - }, - }, - isUpdate: true, - }, - "openshift should not have failed on good version": { - properties: &Properties{ - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: OpenShift, - OrchestratorVersion: "3.9.0", - OpenShiftConfig: validOpenShiftConifg(), - }, - }, - }, - "openshift should not have failed on good version with v prefix": { - properties: &Properties{ - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: OpenShift, - OrchestratorVersion: "v3.9.0", - OpenShiftConfig: validOpenShiftConifg(), - }, - }, - }, - "openshift fails with unset config": { - properties: &Properties{ - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: OpenShift, - OrchestratorVersion: "v3.9.0", - }, - }, - expectedError: "OpenShiftConfig must be specified for OpenShift orchestrator", - }, } for testName, test := range tests { @@ -306,58 +204,6 @@ func Test_OrchestratorProfile_Validate(t *testing.T) { } } -func Test_OpenShiftConfig_Validate(t *testing.T) { - tests := map[string]struct { - properties *Properties - expectedError string - isUpdate bool - }{ - "openshift config requires username": { - properties: &Properties{ - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: OpenShift, - OrchestratorVersion: "v3.9.0", - OpenShiftConfig: &OpenShiftConfig{ClusterPassword: "foo"}, - }, - }, - expectedError: "ClusterUsername and ClusterPassword must both be specified", - }, - "openshift config requires password": { - properties: &Properties{ - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: OpenShift, - OrchestratorVersion: "v3.9.0", - OpenShiftConfig: &OpenShiftConfig{ClusterUsername: "foo"}, - }, - }, - expectedError: "ClusterUsername and ClusterPassword must both be specified", - }, - } - - for testName, test := range tests { - test := test - t.Run(testName, func(t *testing.T) { - t.Parallel() - err := test.properties.validateOrchestratorProfile(test.isUpdate) - - if test.expectedError == "" && err == nil { - return - } - if test.expectedError == "" && err != nil { - t.Errorf("%s expected no error but received: %s", testName, err.Error()) - return - } - if test.expectedError != "" && err == nil { - t.Errorf("%s expected error: %s, but received no error", testName, test.expectedError) - return - } - if !strings.Contains(err.Error(), test.expectedError) { - t.Errorf("%s expected error to container %s but received: %s", testName, test.expectedError, err.Error()) - } - }) - } -} - func Test_KubernetesConfig_Validate(t *testing.T) { // Tests that should pass across all versions for _, k8sVersion := range common.GetAllSupportedKubernetesVersions(true, false) { @@ -966,60 +812,6 @@ func Test_AadProfile_Validate(t *testing.T) { } } }) - - t.Run("aadProfiles should not be supported non-Kubernetes orchestrators", func(t *testing.T) { - t.Parallel() - properties := getK8sDefaultProperties(false) - properties.OrchestratorProfile = &OrchestratorProfile{ - OrchestratorType: OpenShift, - } - properties.AADProfile = &AADProfile{ - ClientAppID: "92444486-5bc3-4291-818b-d53ae480991b", - ServerAppID: "403f018b-4d89-495b-b548-0cf9868cdb0a", - } - expectedMsg := "'aadProfile' is only supported by orchestrator 'Kubernetes'" - if err := properties.validateAADProfile(); err == nil || err.Error() != expectedMsg { - t.Errorf("error should have occurred with msg : %s, but got : %s", expectedMsg, err.Error()) - } - }) -} - -func TestValidateProperties_AzProfile(t *testing.T) { - t.Run("It returns error for unsupported orchestratorTypes", func(t *testing.T) { - t.Parallel() - p := getK8sDefaultProperties(false) - p.OrchestratorProfile = &OrchestratorProfile{ - OrchestratorType: Kubernetes, - } - p.AzProfile = &AzProfile{ - TenantID: "tenant_id", - SubscriptionID: "sub_id", - ResourceGroup: "rg1", - } - expectedMsg := "'azProfile' is only supported by orchestrator 'OpenShift'" - if err := p.Validate(false); err == nil || err.Error() != expectedMsg { - t.Errorf("expected error to be thrown with message : %s", expectedMsg) - } - }) - - t.Run("It should return an error for incomplete azProfile details", func(t *testing.T) { - t.Parallel() - p := getK8sDefaultProperties(false) - p.OrchestratorProfile = &OrchestratorProfile{ - OrchestratorType: OpenShift, - OpenShiftConfig: validOpenShiftConifg(), - } - p.AzProfile = &AzProfile{ - TenantID: "tenant_id", - SubscriptionID: "sub_id", - ResourceGroup: "", - } - expectedMsg := "'azProfile' must be supplied in full for orchestrator 'OpenShift'" - if err := p.validateAzProfile(); err == nil || err.Error() != expectedMsg { - t.Errorf("expected error to be thrown with message : %s", err.Error()) - } - }) - } func TestProperties_ValidateInvalidStruct(t *testing.T) { @@ -1443,7 +1235,7 @@ func TestProperties_ValidateManagedIdentity(t *testing.T) { name: "use managed identity with master vmss", orchestratorRelease: "1.11", useManagedIdentity: true, - userAssignedID: "utacsenginetestid", + userAssignedID: "utaksenginetestid", masterProfile: MasterProfile{ DNSPrefix: "dummy", Count: 3, @@ -1479,7 +1271,7 @@ func TestProperties_ValidateManagedIdentity(t *testing.T) { name: "use user assigned identity with master vmas", orchestratorRelease: "1.11", useManagedIdentity: true, - userAssignedID: "acsenginetestid", + userAssignedID: "aksenginetestid", masterProfile: MasterProfile{ DNSPrefix: "dummy", Count: 3, @@ -1570,45 +1362,6 @@ func TestMasterProfileValidate(t *testing.T) { Count: 3, }, }, - { - name: "Master Profile with valid DNS Prefix 3", - orchestratorType: OpenShift, - masterProfile: MasterProfile{ - DNSPrefix: "dummy", - Count: 1, - StorageProfile: ManagedDisks, - }, - }, - { - name: "Openshift Master Profile with invalid DNS prefix config", - orchestratorType: OpenShift, - masterProfile: MasterProfile{ - DNSPrefix: "dummy", - Count: 3, - }, - expectedErr: "openshift can only deployed with one master", - }, - { // test existing vnet: run with only specifying vnetsubnetid - name: "Master Profile with empty firstconsecutivestaticip and non-empty vnetsubnetid", - orchestratorType: OpenShift, - masterProfile: MasterProfile{ - VnetSubnetID: "testvnetstring", - Count: 1, - StorageProfile: ManagedDisks, - }, - expectedErr: "when specifying a vnetsubnetid the firstconsecutivestaticip is required", - }, - { // test existing vnet: run with specifying both vnetsubnetid and firstconsecutivestaticip - name: "Master Profile with non-empty firstconsecutivestaticip and non-empty vnetsubnetid", - orchestratorType: OpenShift, - masterProfile: MasterProfile{ - DNSPrefix: "dummy", - VnetSubnetID: "testvnetstring", - FirstConsecutiveStaticIP: "10.0.0.1", - Count: 1, - StorageProfile: ManagedDisks, - }, - }, { name: "Master Profile with empty imageName and non-empty imageResourceGroup", orchestratorType: Kubernetes, @@ -2203,169 +1956,6 @@ func TestProperties_ValidateVNET(t *testing.T) { } } -func TestOpenshiftValidate(t *testing.T) { - tests := []struct { - name string - properties *Properties - isUpgrade bool - - expectedErr error - }{ - { - name: "valid", - - properties: &Properties{ - AzProfile: &AzProfile{ - Location: "eastus", - ResourceGroup: "group", - SubscriptionID: "sub_id", - TenantID: "tenant_id", - }, - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: OpenShift, - OpenShiftConfig: &OpenShiftConfig{ - ClusterUsername: "user", - ClusterPassword: "pass", - }, - }, - MasterProfile: &MasterProfile{ - Count: 1, - DNSPrefix: "mydns", - VMSize: "Standard_D4s_v3", - StorageProfile: ManagedDisks, - }, - AgentPoolProfiles: []*AgentPoolProfile{ - { - Name: "compute", - Count: 1, - VMSize: "Standard_D4s_v3", - StorageProfile: ManagedDisks, - AvailabilityProfile: AvailabilitySet, - }, - { - Name: "infra", - Role: "infra", - Count: 1, - VMSize: "Standard_D4s_v3", - StorageProfile: ManagedDisks, - AvailabilityProfile: AvailabilitySet, - }, - }, - LinuxProfile: &LinuxProfile{ - AdminUsername: "admin", - SSH: struct { - PublicKeys []PublicKey `json:"publicKeys" validate:"required,len=1"` - }{ - PublicKeys: []PublicKey{ - {KeyData: "ssh-key"}, - }, - }, - }, - }, - isUpgrade: false, - - expectedErr: nil, - }, - { - name: "invalid - masterProfile.storageProfile needs to be ManagedDisks", - - properties: &Properties{ - AzProfile: &AzProfile{ - Location: "eastus", - ResourceGroup: "group", - SubscriptionID: "sub_id", - TenantID: "tenant_id", - }, - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: OpenShift, - OpenShiftConfig: &OpenShiftConfig{ - ClusterUsername: "user", - ClusterPassword: "pass", - }, - }, - MasterProfile: &MasterProfile{ - Count: 1, - DNSPrefix: "mydns", - VMSize: "Standard_D4s_v3", - StorageProfile: StorageAccount, - }, - LinuxProfile: &LinuxProfile{ - AdminUsername: "admin", - SSH: struct { - PublicKeys []PublicKey `json:"publicKeys" validate:"required,len=1"` - }{ - PublicKeys: []PublicKey{ - {KeyData: "ssh-key"}, - }, - }, - }, - }, - isUpgrade: false, - - expectedErr: errors.New("OpenShift orchestrator supports only ManagedDisks"), - }, - { - name: "invalid - agentPoolProfile[0].storageProfile needs to be ManagedDisks", - - properties: &Properties{ - AzProfile: &AzProfile{ - Location: "eastus", - ResourceGroup: "group", - SubscriptionID: "sub_id", - TenantID: "tenant_id", - }, - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: OpenShift, - OpenShiftConfig: &OpenShiftConfig{ - ClusterUsername: "user", - ClusterPassword: "pass", - }, - }, - MasterProfile: &MasterProfile{ - Count: 1, - DNSPrefix: "mydns", - VMSize: "Standard_D4s_v3", - StorageProfile: ManagedDisks, - }, - AgentPoolProfiles: []*AgentPoolProfile{ - { - Name: "compute", - Count: 1, - VMSize: "Standard_D4s_v3", - StorageProfile: StorageAccount, - AvailabilityProfile: AvailabilitySet, - }, - }, - LinuxProfile: &LinuxProfile{ - AdminUsername: "admin", - SSH: struct { - PublicKeys []PublicKey `json:"publicKeys" validate:"required,len=1"` - }{ - PublicKeys: []PublicKey{ - {KeyData: "ssh-key"}, - }, - }, - }, - }, - isUpgrade: false, - - expectedErr: errors.New("OpenShift orchestrator supports only ManagedDisks"), - }, - } - - for _, test := range tests { - test := test - t.Run(test.name, func(t *testing.T) { - t.Parallel() - gotErr := test.properties.Validate(test.isUpgrade) - if !helpers.EqualError(gotErr, test.expectedErr) { - t.Logf("running scenario %q", test.name) - t.Errorf("expected error: %v\ngot error: %v", test.expectedErr, gotErr) - } - }) - } -} - func TestWindowsProfile_Validate(t *testing.T) { tests := []struct { name string @@ -2379,7 +1969,7 @@ func TestWindowsProfile_Validate(t *testing.T) { w: &WindowsProfile{ WindowsImageSourceURL: "http://fakeWindowsImageSourceURL", }, - expectedMsg: "Windows Custom Images are only supported if the Orchestrator Type is DCOS or Kubernetes", + expectedMsg: "Windows Custom Images are only supported if the Orchestrator Type is Kubernetes", }, { name: "empty adminUsername", @@ -2391,16 +1981,6 @@ func TestWindowsProfile_Validate(t *testing.T) { }, expectedMsg: "WindowsProfile.AdminUsername is required, when agent pool specifies windows", }, - { - name: "empty password", - orchestratorType: "DCOS", - w: &WindowsProfile{ - WindowsImageSourceURL: "http://fakeWindowsImageSourceURL", - AdminUsername: "azure", - AdminPassword: "", - }, - expectedMsg: "WindowsProfile.AdminPassword is required, when agent pool specifies windows", - }, } for _, test := range tests { @@ -2415,100 +1995,6 @@ func TestWindowsProfile_Validate(t *testing.T) { } } -// validOpenShiftConifg returns a valid OpenShift config that can be use for validation tests. -func validOpenShiftConifg() *OpenShiftConfig { - return &OpenShiftConfig{ - ClusterUsername: "foo", - ClusterPassword: "bar", - } -} - -func TestValidateAgentPoolProfiles(t *testing.T) { - tests := []struct { - name string - properties *Properties - expectedErr error - }{ - { - name: "valid", - properties: &Properties{ - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: OpenShift, - }, - AgentPoolProfiles: []*AgentPoolProfile{ - { - Name: "compute", - StorageProfile: ManagedDisks, - AvailabilityProfile: AvailabilitySet, - }, - { - Name: "infra", - Role: "infra", - StorageProfile: ManagedDisks, - AvailabilityProfile: AvailabilitySet, - }, - }, - }, - expectedErr: nil, - }, - { - name: "invalid - role wrong", - properties: &Properties{ - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: OpenShift, - }, - AgentPoolProfiles: []*AgentPoolProfile{ - { - Name: "compute", - StorageProfile: ManagedDisks, - AvailabilityProfile: AvailabilitySet, - }, - { - Name: "infra", - StorageProfile: ManagedDisks, - AvailabilityProfile: AvailabilitySet, - }, - }, - }, - expectedErr: errors.New("OpenShift requires that the 'infra' agent pool profile, and no other, should have role 'infra'"), - }, - { - name: "invalid - profiles misnamed", - properties: &Properties{ - OrchestratorProfile: &OrchestratorProfile{ - OrchestratorType: OpenShift, - }, - AgentPoolProfiles: []*AgentPoolProfile{ - { - Name: "bad", - StorageProfile: ManagedDisks, - AvailabilityProfile: AvailabilitySet, - }, - { - Name: "infra", - Role: "infra", - StorageProfile: ManagedDisks, - AvailabilityProfile: AvailabilitySet, - }, - }, - }, - expectedErr: errors.New("OpenShift requires exactly two agent pool profiles: compute and infra"), - }, - } - - for _, test := range tests { - test := test - t.Run(test.name, func(t *testing.T) { - t.Parallel() - gotErr := test.properties.validateAgentPoolProfiles(true) - if !helpers.EqualError(gotErr, test.expectedErr) { - t.Logf("running scenario %q", test.name) - t.Errorf("expected error: %v\ngot error: %v", test.expectedErr, gotErr) - } - }) - } -} - func TestValidate_VaultKeySecrets(t *testing.T) { tests := []struct { @@ -2623,84 +2109,6 @@ func TestValidateProperties_OrchestratorSpecificProperties(t *testing.T) { t.Errorf("expected error with message : %s, but got %s", expectedMsg, err.Error()) } }) - - t.Run("Should contain a valid DNS prefix", func(t *testing.T) { - t.Parallel() - p := getK8sDefaultProperties(false) - p.OrchestratorProfile.OrchestratorType = OpenShift - agentPoolProfiles := p.AgentPoolProfiles - agentPoolProfiles[0].DNSPrefix = "invalid_prefix" - expectedMsg := "DNSPrefix 'invalid_prefix' is invalid. The DNSPrefix must contain between 3 and 45 characters and can contain only letters, numbers, and hyphens. It must start with a letter and must end with a letter or a number. (length was 14)" - if err := p.validateAgentPoolProfiles(true); err.Error() != expectedMsg { - t.Errorf("expected error with message : %s, but got %s", expectedMsg, err.Error()) - } - }) - - t.Run("Should not contain ports when DNS prefix is empty", func(t *testing.T) { - t.Parallel() - p := getK8sDefaultProperties(false) - p.OrchestratorProfile.OrchestratorType = OpenShift - agentPoolProfiles := p.AgentPoolProfiles - agentPoolProfiles[0].Ports = []int{80, 443} - expectedMsg := "AgentPoolProfile.Ports must be empty when AgentPoolProfile.DNSPrefix is empty for Orchestrator: OpenShift" - if err := p.validateAgentPoolProfiles(true); err.Error() != expectedMsg { - t.Errorf("expected error with message : %s, but got %s", expectedMsg, err.Error()) - } - }) - - t.Run("Should contain unique ports", func(t *testing.T) { - t.Parallel() - p := getK8sDefaultProperties(false) - p.OrchestratorProfile.OrchestratorType = OpenShift - agentPoolProfiles := p.AgentPoolProfiles - agentPoolProfiles[0].Ports = []int{80, 443, 80} - agentPoolProfiles[0].DNSPrefix = "sampleprefix" - expectedMsg := "agent profile 'agentpool' has duplicate port '80', ports must be unique" - if err := p.validateAgentPoolProfiles(true); err.Error() != expectedMsg { - t.Errorf("expected error with message : %s, but got %s", expectedMsg, err.Error()) - } - }) - - t.Run("Should contain valid Storage Profile", func(t *testing.T) { - t.Parallel() - p := getK8sDefaultProperties(false) - p.OrchestratorProfile.OrchestratorType = OpenShift - agentPoolProfiles := p.AgentPoolProfiles - agentPoolProfiles[0].DiskSizesGB = []int{512, 256, 768} - agentPoolProfiles[0].DNSPrefix = "sampleprefix" - expectedMsg := "property 'StorageProfile' must be set to either 'StorageAccount' or 'ManagedDisks' when attaching disks" - if err := p.validateAgentPoolProfiles(true); err.Error() != expectedMsg { - t.Errorf("expected error with message : %s, but got %s", expectedMsg, err.Error()) - } - }) - - t.Run("Should contain valid Availability Profile", func(t *testing.T) { - t.Parallel() - p := getK8sDefaultProperties(false) - p.OrchestratorProfile.OrchestratorType = OpenShift - agentPoolProfiles := p.AgentPoolProfiles - agentPoolProfiles[0].DiskSizesGB = []int{512, 256, 768} - agentPoolProfiles[0].StorageProfile = "ManagedDisks" - agentPoolProfiles[0].AvailabilityProfile = "InvalidAvailabilityProfile" - expectedMsg := "property 'AvailabilityProfile' must be set to either 'VirtualMachineScaleSets' or 'AvailabilitySet' when attaching disks" - if err := p.validateAgentPoolProfiles(true); err.Error() != expectedMsg { - t.Errorf("expected error with message : %s, but got %s", expectedMsg, err.Error()) - } - }) - - t.Run("Should not support both VirtualMachineScaleSets and StorageAccount", func(t *testing.T) { - t.Parallel() - p := getK8sDefaultProperties(false) - p.OrchestratorProfile.OrchestratorType = OpenShift - agentPoolProfiles := p.AgentPoolProfiles - agentPoolProfiles[0].DiskSizesGB = []int{512, 256, 768} - agentPoolProfiles[0].StorageProfile = "StorageAccount" - agentPoolProfiles[0].AvailabilityProfile = "VirtualMachineScaleSets" - expectedMsg := "VirtualMachineScaleSets does not support storage account attached disks. Instead specify 'StorageAccount': 'ManagedDisks' or specify AvailabilityProfile 'AvailabilitySet'" - if err := p.validateAgentPoolProfiles(true); err.Error() != expectedMsg { - t.Errorf("expected error with message : %s, but got %s", expectedMsg, err.Error()) - } - }) } func TestValidateProperties_CustomNodeLabels(t *testing.T) { @@ -2731,15 +2139,15 @@ func TestValidateProperties_CustomNodeLabels(t *testing.T) { } }) - t.Run("Should not support orchestratorTypes other than Kubernetes/DCOS", func(t *testing.T) { + t.Run("Should not support orchestratorTypes other than Kubernetes", func(t *testing.T) { t.Parallel() p := getK8sDefaultProperties(false) - p.OrchestratorProfile.OrchestratorType = SwarmMode + p.OrchestratorProfile.OrchestratorType = "Bogus" agentPoolProfiles := p.AgentPoolProfiles agentPoolProfiles[0].CustomNodeLabels = map[string]string{ "foo": "bar", } - expectedMsg := "Agent CustomNodeLabels are only supported for DCOS and Kubernetes" + expectedMsg := "Agent CustomNodeLabels are only supported for Kubernetes" if err := p.validateAgentPoolProfiles(true); err.Error() != expectedMsg { t.Errorf("expected error with message : %s, but got %s", expectedMsg, err.Error()) } @@ -2757,16 +2165,4 @@ func TestAgentPoolProfile_ValidateAvailabilityProfile(t *testing.T) { t.Errorf("expected error with message : %s, but got %s", expectedMsg, err.Error()) } }) - - t.Run("Should fail when using VirtualMachineScalesets with Openshift", func(t *testing.T) { - t.Parallel() - p := getK8sDefaultProperties(false) - p.OrchestratorProfile.OrchestratorType = OpenShift - agentPoolProfiles := p.AgentPoolProfiles - agentPoolProfiles[0].AvailabilityProfile = VirtualMachineScaleSets - expectedMsg := "Only AvailabilityProfile: AvailabilitySet is supported for Orchestrator 'OpenShift'" - if err := p.validateAgentPoolProfiles(true); err.Error() != expectedMsg { - t.Errorf("expected error with message : %s, but got %s", expectedMsg, err.Error()) - } - }) } diff --git a/pkg/armhelpers/azureclient.go b/pkg/armhelpers/azureclient.go index a94acdd6d2..ac353ab770 100644 --- a/pkg/armhelpers/azureclient.go +++ b/pkg/armhelpers/azureclient.go @@ -13,6 +13,7 @@ import ( "strings" "time" + "github.com/Azure/aks-engine/pkg/engine" "github.com/Azure/azure-sdk-for-go/services/apimanagement/mgmt/2017-03-01/apimanagement" "github.com/Azure/azure-sdk-for-go/services/authorization/mgmt/2015-07-01/authorization" "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-04-01/compute" @@ -28,21 +29,19 @@ import ( "github.com/mitchellh/go-homedir" "github.com/pkg/errors" log "github.com/sirupsen/logrus" - - "github.com/Azure/acs-engine/pkg/acsengine" ) const ( // ApplicationDir is the name of the dir where the token is cached - ApplicationDir = ".acsengine" + ApplicationDir = ".aksengine" ) var ( - // RequiredResourceProviders is the list of Azure Resource Providers needed for ACS-Engine to function + // RequiredResourceProviders is the list of Azure Resource Providers needed for AKS Engine to function RequiredResourceProviders = []string{"Microsoft.Compute", "Microsoft.Storage", "Microsoft.Network"} ) -// AzureClient implements the `ACSEngineClient` interface. +// AzureClient implements the `AKSEngineClient` interface. // This client is backed by real Azure clients talking to an ARM endpoint. type AzureClient struct { acceptLanguages []string @@ -75,14 +74,14 @@ func NewAzureClientWithDeviceAuth(env azure.Environment, subscriptionID string) return nil, err } - // AcsEngineClientID is the AAD ClientID for the CLI native application - acsEngineClientID := getAcsEngineClientID(env.Name) + // AKSEngineClientID is the AAD ClientID for the CLI native application + AKSEngineClientID := getAKSEngineClientID(env.Name) home, err := homedir.Dir() if err != nil { return nil, errors.Wrap(err, "Failed to get user home directory to look for cached token") } - cachePath := filepath.Join(home, ApplicationDir, "cache", fmt.Sprintf("%s_%s.token.json", tenantID, acsEngineClientID)) + cachePath := filepath.Join(home, ApplicationDir, "cache", fmt.Sprintf("%s_%s.token.json", tenantID, AKSEngineClientID)) rawToken, err := tryLoadCachedToken(cachePath) if err != nil { @@ -91,7 +90,7 @@ func NewAzureClientWithDeviceAuth(env azure.Environment, subscriptionID string) var armSpt *adal.ServicePrincipalToken if rawToken != nil { - armSpt, err = adal.NewServicePrincipalTokenFromManualToken(*oauthConfig, acsEngineClientID, env.ServiceManagementEndpoint, *rawToken, tokenCallback(cachePath)) + armSpt, err = adal.NewServicePrincipalTokenFromManualToken(*oauthConfig, AKSEngineClientID, env.ServiceManagementEndpoint, *rawToken, tokenCallback(cachePath)) if err != nil { return nil, err } @@ -99,7 +98,7 @@ func NewAzureClientWithDeviceAuth(env azure.Environment, subscriptionID string) if err != nil { log.Warnf("Refresh token failed. Will fallback to device auth. %q", err) } else { - graphSpt, err := adal.NewServicePrincipalTokenFromManualToken(*oauthConfig, acsEngineClientID, env.GraphEndpoint, armSpt.Token()) + graphSpt, err := adal.NewServicePrincipalTokenFromManualToken(*oauthConfig, AKSEngineClientID, env.GraphEndpoint, armSpt.Token()) if err != nil { return nil, err } @@ -113,7 +112,7 @@ func NewAzureClientWithDeviceAuth(env azure.Environment, subscriptionID string) PollingDuration: DefaultARMOperationTimeout, } - deviceCode, err := adal.InitiateDeviceAuth(client, *oauthConfig, acsEngineClientID, env.ServiceManagementEndpoint) + deviceCode, err := adal.InitiateDeviceAuth(client, *oauthConfig, AKSEngineClientID, env.ServiceManagementEndpoint) if err != nil { return nil, err } @@ -123,7 +122,7 @@ func NewAzureClientWithDeviceAuth(env azure.Environment, subscriptionID string) return nil, err } - armSpt, err = adal.NewServicePrincipalTokenFromManualToken(*oauthConfig, acsEngineClientID, env.ServiceManagementEndpoint, *deviceToken, tokenCallback(cachePath)) + armSpt, err = adal.NewServicePrincipalTokenFromManualToken(*oauthConfig, AKSEngineClientID, env.ServiceManagementEndpoint, *deviceToken, tokenCallback(cachePath)) if err != nil { return nil, err } @@ -131,7 +130,7 @@ func NewAzureClientWithDeviceAuth(env azure.Environment, subscriptionID string) adRawToken := armSpt.Token() adRawToken.Resource = env.GraphEndpoint - graphSpt, err := adal.NewServicePrincipalTokenFromManualToken(*oauthConfig, acsEngineClientID, env.GraphEndpoint, adRawToken) + graphSpt, err := adal.NewServicePrincipalTokenFromManualToken(*oauthConfig, AKSEngineClientID, env.GraphEndpoint, adRawToken) if err != nil { return nil, err } @@ -279,7 +278,7 @@ func tryLoadCachedToken(cachePath string) (*adal.Token, error) { } func getOAuthConfig(env azure.Environment, subscriptionID string) (*adal.OAuthConfig, string, error) { - tenantID, err := acsengine.GetTenantID(env.ResourceManagerEndpoint, subscriptionID) + tenantID, err := engine.GetTenantID(env.ResourceManagerEndpoint, subscriptionID) if err != nil { return nil, "", err } @@ -292,7 +291,7 @@ func getOAuthConfig(env azure.Environment, subscriptionID string) (*adal.OAuthCo return oauthConfig, tenantID, nil } -func getAcsEngineClientID(envName string) string { +func getAKSEngineClientID(envName string) string { switch envName { case "AzureUSGovernmentCloud": return "e8b7f94b-85c9-47f4-964a-98dafd7fc2d8" diff --git a/pkg/armhelpers/azureclient_test.go b/pkg/armhelpers/azureclient_test.go index c04f5a0ab6..a514225197 100644 --- a/pkg/armhelpers/azureclient_test.go +++ b/pkg/armhelpers/azureclient_test.go @@ -7,7 +7,7 @@ import ( "github.com/Azure/go-autorest/autorest" - . "github.com/Azure/acs-engine/pkg/test" + . "github.com/Azure/aks-engine/pkg/test" . "github.com/onsi/gomega" "github.com/Azure/go-autorest/autorest/azure" diff --git a/pkg/armhelpers/deploymentError.go b/pkg/armhelpers/deploymentError.go index 6eb16708e7..b188a5d008 100644 --- a/pkg/armhelpers/deploymentError.go +++ b/pkg/armhelpers/deploymentError.go @@ -7,7 +7,7 @@ import ( "fmt" "strings" - "github.com/Azure/acs-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/api" "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-05-01/resources" "github.com/sirupsen/logrus" ) @@ -57,7 +57,7 @@ func (e *DeploymentValidationError) Error() string { } // DeployTemplateSync deploys the template and returns ArmError -func DeployTemplateSync(az ACSEngineClient, logger *logrus.Entry, resourceGroupName, deploymentName string, template map[string]interface{}, parameters map[string]interface{}) error { +func DeployTemplateSync(az AKSEngineClient, logger *logrus.Entry, resourceGroupName, deploymentName string, template map[string]interface{}, parameters map[string]interface{}) error { ctx, cancel := context.WithTimeout(context.Background(), DefaultARMOperationTimeout) defer cancel() deploymentExtended, err := az.DeployTemplate(ctx, resourceGroupName, deploymentName, template, parameters) diff --git a/pkg/armhelpers/deploymentError_test.go b/pkg/armhelpers/deploymentError_test.go index c5b631e359..6d574a1f5d 100644 --- a/pkg/armhelpers/deploymentError_test.go +++ b/pkg/armhelpers/deploymentError_test.go @@ -3,11 +3,10 @@ package armhelpers import ( "testing" - . "github.com/Azure/acs-engine/pkg/test" - . "github.com/onsi/gomega" - + . "github.com/Azure/aks-engine/pkg/test" "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-05-01/resources" . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" "github.com/pkg/errors" log "github.com/sirupsen/logrus" ) @@ -19,7 +18,7 @@ func TestUpgradeCluster(t *testing.T) { var _ = Describe("Template deployment tests", func() { It("Should return InternalOperationError error code", func() { - mockClient := &MockACSEngineClient{} + mockClient := &MockAKSEngineClient{} mockClient.FailDeployTemplate = true logger := log.NewEntry(log.New()) @@ -35,7 +34,7 @@ var _ = Describe("Template deployment tests", func() { }) It("Should return QuotaExceeded error code, specified in details", func() { - mockClient := &MockACSEngineClient{} + mockClient := &MockAKSEngineClient{} mockClient.FailDeployTemplateQuota = true logger := log.NewEntry(log.New()) @@ -51,7 +50,7 @@ var _ = Describe("Template deployment tests", func() { }) It("Should return Conflict error code, specified in details", func() { - mockClient := &MockACSEngineClient{} + mockClient := &MockAKSEngineClient{} mockClient.FailDeployTemplateConflict = true logger := log.NewEntry(log.New()) @@ -67,7 +66,7 @@ var _ = Describe("Template deployment tests", func() { }) It("Should return deployment error with Operations Lists", func() { - mockClient := &MockACSEngineClient{} + mockClient := &MockAKSEngineClient{} mockClient.FailDeployTemplateWithProperties = true logger := log.NewEntry(log.New()) @@ -83,7 +82,7 @@ var _ = Describe("Template deployment tests", func() { }) It("Should return nil on success", func() { - mockClient := &MockACSEngineClient{} + mockClient := &MockAKSEngineClient{} logger := log.NewEntry(log.New()) err := DeployTemplateSync(mockClient, logger, "rg1", "agentvm", map[string]interface{}{}, map[string]interface{}{}) Expect(err).To(BeNil()) diff --git a/pkg/armhelpers/interfaces.go b/pkg/armhelpers/interfaces.go index 6764f7f284..ceae143fea 100644 --- a/pkg/armhelpers/interfaces.go +++ b/pkg/armhelpers/interfaces.go @@ -39,10 +39,10 @@ type RoleAssignmentListResultPage interface { Values() []authorization.RoleAssignment } -// ACSEngineClient is the interface used to talk to an Azure environment. +// AKSEngineClient is the interface used to talk to an Azure environment. // This interface exposes just the subset of Azure APIs and clients needed for -// ACS-Engine. -type ACSEngineClient interface { +// AKS Engine. +type AKSEngineClient interface { //AddAcceptLanguages sets the list of languages to accept on this request AddAcceptLanguages(languages []string) @@ -87,7 +87,7 @@ type ACSEngineClient interface { // GetStorageClient uses SRP to retrieve keys, and then an authenticated client for talking to the specified storage // account. - GetStorageClient(ctx context.Context, resourceGroup, accountName string) (ACSStorageClient, error) + GetStorageClient(ctx context.Context, resourceGroup, accountName string) (AKSStorageClient, error) // // NETWORK @@ -130,8 +130,8 @@ type ACSEngineClient interface { ListDeploymentOperations(ctx context.Context, resourceGroupName string, deploymentName string, top *int32) (result DeploymentOperationsListResultPage, err error) } -// ACSStorageClient interface models the azure storage client -type ACSStorageClient interface { +// AKSStorageClient interface models the azure storage client +type AKSStorageClient interface { // DeleteBlob deletes the specified blob in the specified container. DeleteBlob(containerName, blobName string, options *azStorage.DeleteBlobOptions) error // CreateContainer creates the CloudBlobContainer if it does not exist diff --git a/pkg/armhelpers/mockclients.go b/pkg/armhelpers/mockclients.go index 37c60fa800..8873dbdb9d 100644 --- a/pkg/armhelpers/mockclients.go +++ b/pkg/armhelpers/mockclients.go @@ -9,8 +9,7 @@ import ( "net/http" "time" - "github.com/Azure/acs-engine/pkg/helpers" - + "github.com/Azure/aks-engine/pkg/helpers" "github.com/Azure/azure-sdk-for-go/services/authorization/mgmt/2015-07-01/authorization" "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-04-01/compute" "github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac" @@ -22,8 +21,8 @@ import ( "k8s.io/api/core/v1" ) -//MockACSEngineClient is an implementation of ACSEngineClient where all requests error out -type MockACSEngineClient struct { +//MockAKSEngineClient is an implementation of AKSEngineClient where all requests error out +type MockAKSEngineClient struct { FailDeployTemplate bool FailDeployTemplateQuota bool FailDeployTemplateConflict bool @@ -270,13 +269,13 @@ func (msc *MockStorageClient) SaveBlockBlob(container, blob string, b []byte, op } //AddAcceptLanguages mock -func (mc *MockACSEngineClient) AddAcceptLanguages(languages []string) {} +func (mc *MockAKSEngineClient) AddAcceptLanguages(languages []string) {} // AddAuxiliaryTokens mock -func (mc *MockACSEngineClient) AddAuxiliaryTokens(tokens []string) {} +func (mc *MockAKSEngineClient) AddAuxiliaryTokens(tokens []string) {} //DeployTemplate mock -func (mc *MockACSEngineClient) DeployTemplate(ctx context.Context, resourceGroup, name string, template, parameters map[string]interface{}) (de resources.DeploymentExtended, err error) { +func (mc *MockAKSEngineClient) DeployTemplate(ctx context.Context, resourceGroup, name string, template, parameters map[string]interface{}) (de resources.DeploymentExtended, err error) { switch { case mc.FailDeployTemplate: return de, errors.New("DeployTemplate failed") @@ -350,7 +349,7 @@ func (mc *MockACSEngineClient) DeployTemplate(ctx context.Context, resourceGroup } //EnsureResourceGroup mock -func (mc *MockACSEngineClient) EnsureResourceGroup(ctx context.Context, resourceGroup, location string, managedBy *string) (*resources.Group, error) { +func (mc *MockAKSEngineClient) EnsureResourceGroup(ctx context.Context, resourceGroup, location string, managedBy *string) (*resources.Group, error) { if mc.FailEnsureResourceGroup { return nil, errors.New("EnsureResourceGroup failed") } @@ -359,7 +358,7 @@ func (mc *MockACSEngineClient) EnsureResourceGroup(ctx context.Context, resource } //ListVirtualMachines mock -func (mc *MockACSEngineClient) ListVirtualMachines(ctx context.Context, resourceGroup string) (VirtualMachineListResultPage, error) { +func (mc *MockAKSEngineClient) ListVirtualMachines(ctx context.Context, resourceGroup string) (VirtualMachineListResultPage, error) { if mc.FailListVirtualMachines { return &MockVirtualMachineListResultPage{ Vmlr: compute.VirtualMachineListResult{ @@ -422,7 +421,7 @@ func (mc *MockACSEngineClient) ListVirtualMachines(ctx context.Context, resource } //ListVirtualMachineScaleSets mock -func (mc *MockACSEngineClient) ListVirtualMachineScaleSets(ctx context.Context, resourceGroup string) (compute.VirtualMachineScaleSetListResultPage, error) { +func (mc *MockAKSEngineClient) ListVirtualMachineScaleSets(ctx context.Context, resourceGroup string) (compute.VirtualMachineScaleSetListResultPage, error) { if mc.FailListVirtualMachineScaleSets { return compute.VirtualMachineScaleSetListResultPage{}, errors.New("ListVirtualMachines failed") } @@ -431,7 +430,7 @@ func (mc *MockACSEngineClient) ListVirtualMachineScaleSets(ctx context.Context, } //GetVirtualMachine mock -func (mc *MockACSEngineClient) GetVirtualMachine(ctx context.Context, resourceGroup, name string) (compute.VirtualMachine, error) { +func (mc *MockAKSEngineClient) GetVirtualMachine(ctx context.Context, resourceGroup, name string) (compute.VirtualMachine, error) { if mc.FailGetVirtualMachine { return compute.VirtualMachine{}, errors.New("GetVirtualMachine failed") } @@ -485,7 +484,7 @@ func (mc *MockACSEngineClient) GetVirtualMachine(ctx context.Context, resourceGr } //DeleteVirtualMachine mock -func (mc *MockACSEngineClient) DeleteVirtualMachine(ctx context.Context, resourceGroup, name string) error { +func (mc *MockAKSEngineClient) DeleteVirtualMachine(ctx context.Context, resourceGroup, name string) error { if mc.FailDeleteVirtualMachine { return errors.New("DeleteVirtualMachine failed") } @@ -494,7 +493,7 @@ func (mc *MockACSEngineClient) DeleteVirtualMachine(ctx context.Context, resourc } //DeleteVirtualMachineScaleSetVM mock -func (mc *MockACSEngineClient) DeleteVirtualMachineScaleSetVM(ctx context.Context, resourceGroup, virtualMachineScaleSet, instanceID string) error { +func (mc *MockAKSEngineClient) DeleteVirtualMachineScaleSetVM(ctx context.Context, resourceGroup, virtualMachineScaleSet, instanceID string) error { if mc.FailDeleteVirtualMachineScaleSetVM { return errors.New("DeleteVirtualMachineScaleSetVM failed") } @@ -503,7 +502,7 @@ func (mc *MockACSEngineClient) DeleteVirtualMachineScaleSetVM(ctx context.Contex } //SetVirtualMachineScaleSetCapacity mock -func (mc *MockACSEngineClient) SetVirtualMachineScaleSetCapacity(ctx context.Context, resourceGroup, virtualMachineScaleSet string, sku compute.Sku, location string) error { +func (mc *MockAKSEngineClient) SetVirtualMachineScaleSetCapacity(ctx context.Context, resourceGroup, virtualMachineScaleSet string, sku compute.Sku, location string) error { if mc.FailSetVirtualMachineScaleSetCapacity { return errors.New("SetVirtualMachineScaleSetCapacity failed") } @@ -512,7 +511,7 @@ func (mc *MockACSEngineClient) SetVirtualMachineScaleSetCapacity(ctx context.Con } //ListVirtualMachineScaleSetVMs mock -func (mc *MockACSEngineClient) ListVirtualMachineScaleSetVMs(ctx context.Context, resourceGroup, virtualMachineScaleSet string) (compute.VirtualMachineScaleSetVMListResultPage, error) { +func (mc *MockAKSEngineClient) ListVirtualMachineScaleSetVMs(ctx context.Context, resourceGroup, virtualMachineScaleSet string) (compute.VirtualMachineScaleSetVMListResultPage, error) { if mc.FailDeleteVirtualMachineScaleSetVM { return compute.VirtualMachineScaleSetVMListResultPage{}, errors.New("DeleteVirtualMachineScaleSetVM failed") } @@ -521,7 +520,7 @@ func (mc *MockACSEngineClient) ListVirtualMachineScaleSetVMs(ctx context.Context } //GetStorageClient mock -func (mc *MockACSEngineClient) GetStorageClient(ctx context.Context, resourceGroup, accountName string) (ACSStorageClient, error) { +func (mc *MockAKSEngineClient) GetStorageClient(ctx context.Context, resourceGroup, accountName string) (AKSStorageClient, error) { if mc.FailGetStorageClient { return nil, errors.New("GetStorageClient failed") } @@ -530,7 +529,7 @@ func (mc *MockACSEngineClient) GetStorageClient(ctx context.Context, resourceGro } //DeleteNetworkInterface mock -func (mc *MockACSEngineClient) DeleteNetworkInterface(ctx context.Context, resourceGroup, nicName string) error { +func (mc *MockAKSEngineClient) DeleteNetworkInterface(ctx context.Context, resourceGroup, nicName string) error { if mc.FailDeleteNetworkInterface { return errors.New("DeleteNetworkInterface failed") } @@ -547,58 +546,58 @@ var validNicResourceName = "/subscriptions/DEC923E3-1EF1-4745-9516-37906D56DEC4/ // Graph Mocks // CreateGraphApplication creates an application via the graphrbac client -func (mc *MockACSEngineClient) CreateGraphApplication(ctx context.Context, applicationCreateParameters graphrbac.ApplicationCreateParameters) (graphrbac.Application, error) { +func (mc *MockAKSEngineClient) CreateGraphApplication(ctx context.Context, applicationCreateParameters graphrbac.ApplicationCreateParameters) (graphrbac.Application, error) { return graphrbac.Application{}, nil } // CreateGraphPrincipal creates a service principal via the graphrbac client -func (mc *MockACSEngineClient) CreateGraphPrincipal(ctx context.Context, servicePrincipalCreateParameters graphrbac.ServicePrincipalCreateParameters) (graphrbac.ServicePrincipal, error) { +func (mc *MockAKSEngineClient) CreateGraphPrincipal(ctx context.Context, servicePrincipalCreateParameters graphrbac.ServicePrincipalCreateParameters) (graphrbac.ServicePrincipal, error) { return graphrbac.ServicePrincipal{}, nil } // CreateApp is a simpler method for creating an application -func (mc *MockACSEngineClient) CreateApp(ctx context.Context, applicationName, applicationURL string, replyURLs *[]string, requiredResourceAccess *[]graphrbac.RequiredResourceAccess) (result graphrbac.Application, servicePrincipalObjectID, secret string, err error) { +func (mc *MockAKSEngineClient) CreateApp(ctx context.Context, applicationName, applicationURL string, replyURLs *[]string, requiredResourceAccess *[]graphrbac.RequiredResourceAccess) (result graphrbac.Application, servicePrincipalObjectID, secret string, err error) { return graphrbac.Application{ AppID: helpers.PointerToString("app-id"), }, "client-id", "client-secret", nil } // DeleteApp is a simpler method for deleting an application -func (mc *MockACSEngineClient) DeleteApp(ctx context.Context, appName, applicationObjectID string) (response autorest.Response, err error) { +func (mc *MockAKSEngineClient) DeleteApp(ctx context.Context, appName, applicationObjectID string) (response autorest.Response, err error) { return response, nil } // User Assigned MSI //CreateUserAssignedID - Creates a user assigned msi. -func (mc *MockACSEngineClient) CreateUserAssignedID(location string, resourceGroup string, userAssignedID string) (*msi.Identity, error) { +func (mc *MockAKSEngineClient) CreateUserAssignedID(location string, resourceGroup string, userAssignedID string) (*msi.Identity, error) { return &msi.Identity{}, nil } // RBAC Mocks // CreateRoleAssignment creates a role assignment via the authorization client -func (mc *MockACSEngineClient) CreateRoleAssignment(ctx context.Context, scope string, roleAssignmentName string, parameters authorization.RoleAssignmentCreateParameters) (authorization.RoleAssignment, error) { +func (mc *MockAKSEngineClient) CreateRoleAssignment(ctx context.Context, scope string, roleAssignmentName string, parameters authorization.RoleAssignmentCreateParameters) (authorization.RoleAssignment, error) { return authorization.RoleAssignment{}, nil } // CreateRoleAssignmentSimple is a wrapper around RoleAssignmentsClient.Create -func (mc *MockACSEngineClient) CreateRoleAssignmentSimple(ctx context.Context, applicationID, roleID string) error { +func (mc *MockAKSEngineClient) CreateRoleAssignmentSimple(ctx context.Context, applicationID, roleID string) error { return nil } // DeleteManagedDisk is a wrapper around disksClient.Delete -func (mc *MockACSEngineClient) DeleteManagedDisk(ctx context.Context, resourceGroupName string, diskName string) error { +func (mc *MockAKSEngineClient) DeleteManagedDisk(ctx context.Context, resourceGroupName string, diskName string) error { return nil } // ListManagedDisksByResourceGroup is a wrapper around disksClient.ListManagedDisksByResourceGroup -func (mc *MockACSEngineClient) ListManagedDisksByResourceGroup(ctx context.Context, resourceGroupName string) (result compute.DiskListPage, err error) { +func (mc *MockAKSEngineClient) ListManagedDisksByResourceGroup(ctx context.Context, resourceGroupName string) (result compute.DiskListPage, err error) { return compute.DiskListPage{}, nil } //GetKubernetesClient mock -func (mc *MockACSEngineClient) GetKubernetesClient(masterURL, kubeConfig string, interval, timeout time.Duration) (KubernetesClient, error) { +func (mc *MockAKSEngineClient) GetKubernetesClient(masterURL, kubeConfig string, interval, timeout time.Duration) (KubernetesClient, error) { if mc.FailGetKubernetesClient { return nil, errors.New("GetKubernetesClient failed") } @@ -610,7 +609,7 @@ func (mc *MockACSEngineClient) GetKubernetesClient(masterURL, kubeConfig string, } // ListProviders mock -func (mc *MockACSEngineClient) ListProviders(ctx context.Context) (resources.ProviderListResultPage, error) { +func (mc *MockAKSEngineClient) ListProviders(ctx context.Context) (resources.ProviderListResultPage, error) { if mc.FailListProviders { return resources.ProviderListResultPage{}, errors.New("ListProviders failed") } @@ -619,7 +618,7 @@ func (mc *MockACSEngineClient) ListProviders(ctx context.Context) (resources.Pro } // ListDeploymentOperations gets all deployments operations for a deployment. -func (mc *MockACSEngineClient) ListDeploymentOperations(ctx context.Context, resourceGroupName string, deploymentName string, top *int32) (result DeploymentOperationsListResultPage, err error) { +func (mc *MockAKSEngineClient) ListDeploymentOperations(ctx context.Context, resourceGroupName string, deploymentName string, top *int32) (result DeploymentOperationsListResultPage, err error) { resp := `{ "properties": { "provisioningState":"Failed", @@ -682,12 +681,12 @@ func (mc *MockACSEngineClient) ListDeploymentOperations(ctx context.Context, res } // ListDeploymentOperationsNextResults retrieves the next set of results, if any. -func (mc *MockACSEngineClient) ListDeploymentOperationsNextResults(lastResults resources.DeploymentOperationsListResult) (result resources.DeploymentOperationsListResult, err error) { +func (mc *MockAKSEngineClient) ListDeploymentOperationsNextResults(lastResults resources.DeploymentOperationsListResult) (result resources.DeploymentOperationsListResult, err error) { return resources.DeploymentOperationsListResult{}, nil } // DeleteRoleAssignmentByID deletes a roleAssignment via its unique identifier -func (mc *MockACSEngineClient) DeleteRoleAssignmentByID(ctx context.Context, roleAssignmentID string) (authorization.RoleAssignment, error) { +func (mc *MockAKSEngineClient) DeleteRoleAssignmentByID(ctx context.Context, roleAssignmentID string) (authorization.RoleAssignment, error) { if mc.FailDeleteRoleAssignment { return authorization.RoleAssignment{}, errors.New("DeleteRoleAssignmentByID failed") } @@ -696,7 +695,7 @@ func (mc *MockACSEngineClient) DeleteRoleAssignmentByID(ctx context.Context, rol } // ListRoleAssignmentsForPrincipal (e.g. a VM) via the scope and the unique identifier of the principal -func (mc *MockACSEngineClient) ListRoleAssignmentsForPrincipal(ctx context.Context, scope string, principalID string) (RoleAssignmentListResultPage, error) { +func (mc *MockAKSEngineClient) ListRoleAssignmentsForPrincipal(ctx context.Context, scope string, principalID string) (RoleAssignmentListResultPage, error) { roleAssignments := []authorization.RoleAssignment{} if mc.ShouldSupportVMIdentity { diff --git a/pkg/armhelpers/storage.go b/pkg/armhelpers/storage.go index 311009a336..13ce9bb167 100644 --- a/pkg/armhelpers/storage.go +++ b/pkg/armhelpers/storage.go @@ -15,7 +15,7 @@ type AzureStorageClient struct { } // GetStorageClient returns an authenticated client for the specified account. -func (az *AzureClient) GetStorageClient(ctx context.Context, resourceGroup, accountName string) (ACSStorageClient, error) { +func (az *AzureClient) GetStorageClient(ctx context.Context, resourceGroup, accountName string) (AKSStorageClient, error) { keys, err := az.getStorageKeys(ctx, resourceGroup, accountName) if err != nil { return nil, err diff --git a/pkg/armhelpers/storage_test.go b/pkg/armhelpers/storage_test.go index 2aa3245386..2b579d3291 100644 --- a/pkg/armhelpers/storage_test.go +++ b/pkg/armhelpers/storage_test.go @@ -3,7 +3,7 @@ package armhelpers import ( "testing" - . "github.com/Azure/acs-engine/pkg/test" + . "github.com/Azure/aks-engine/pkg/test" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) diff --git a/pkg/armhelpers/utils/util.go b/pkg/armhelpers/utils/util.go index d8a6b7f3b7..7518641790 100644 --- a/pkg/armhelpers/utils/util.go +++ b/pkg/armhelpers/utils/util.go @@ -6,7 +6,7 @@ import ( "strconv" "strings" - "github.com/Azure/acs-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/api" "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-04-01/compute" "github.com/pkg/errors" log "github.com/sirupsen/logrus" diff --git a/pkg/armhelpers/utils/util_test.go b/pkg/armhelpers/utils/util_test.go index cfd5aa6f96..bddbc3f96d 100644 --- a/pkg/armhelpers/utils/util_test.go +++ b/pkg/armhelpers/utils/util_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/Azure/acs-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/api" "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-04-01/compute" ) @@ -65,7 +65,7 @@ func Test_VmssNameParts(t *testing.T) { } for _, el := range data { - vmssName := fmt.Sprintf("swarmm-%s-%s-vmss", el.poolIdentifier, el.nameSuffix) + vmssName := fmt.Sprintf("kuberm-%s-%s-vmss", el.poolIdentifier, el.nameSuffix) poolIdentifier, nameSuffix, err := VmssNameParts(vmssName) if err != nil { t.Fatalf("unexpected error: %s", err) diff --git a/pkg/acsengine/artifacts.go b/pkg/engine/artifacts.go similarity index 98% rename from pkg/acsengine/artifacts.go rename to pkg/engine/artifacts.go index 528f479718..1ebe9a01d6 100644 --- a/pkg/acsengine/artifacts.go +++ b/pkg/engine/artifacts.go @@ -1,12 +1,12 @@ -package acsengine +package engine import ( "fmt" "strings" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/helpers" ) type kubernetesFeatureSetting struct { diff --git a/pkg/acsengine/const.go b/pkg/engine/const.go similarity index 73% rename from pkg/acsengine/const.go rename to pkg/engine/const.go index a84d4e1660..e61cb94db2 100644 --- a/pkg/acsengine/const.go +++ b/pkg/engine/const.go @@ -1,4 +1,4 @@ -package acsengine +package engine const ( // DefaultVNETCIDR is the default CIDR block for the VNET @@ -67,7 +67,7 @@ const ( // DefaultELBSVCAddonName is the name of the elb service addon deployment DefaultELBSVCAddonName = "elb-svc" // DefaultGeneratorCode specifies the source generator of the cluster template. - DefaultGeneratorCode = "acsengine" + DefaultGeneratorCode = "aksengine" // DefaultReschedulerAddonName is the name of the rescheduler addon deployment DefaultReschedulerAddonName = "rescheduler" // DefaultMetricsServerAddonName is the name of the kubernetes Metrics server addon deployment @@ -92,7 +92,7 @@ const ( const ( //DefaultExtensionsRootURL Root URL for extensions - DefaultExtensionsRootURL = "https://raw.githubusercontent.com/Azure/acs-engine/master/" + DefaultExtensionsRootURL = "https://raw.githubusercontent.com/Azure/aks-engine/master/" // DefaultDockerEngineRepo for grabbing docker engine packages DefaultDockerEngineRepo = "https://download.docker.com/linux/ubuntu" // DefaultDockerComposeURL for grabbing docker images @@ -101,7 +101,7 @@ const ( const ( //DefaultConfigurationScriptRootURL Root URL for configuration script (used for script extension on RHEL) - DefaultConfigurationScriptRootURL = "https://raw.githubusercontent.com/Azure/acs-engine/master/parts/" + DefaultConfigurationScriptRootURL = "https://raw.githubusercontent.com/Azure/aks-engine/master/parts/" ) const ( @@ -124,55 +124,13 @@ const ( kubernetesWindowsKubeletFunctionsPS1 = "k8s/windowskubeletfunc.ps1" kubernetesWindowsCniFunctionsPS1 = "k8s/windowscnifunc.ps1" kubernetesWindowsAzureCniFunctionsPS1 = "k8s/windowsazurecnifunc.ps1" - // OpenShift custom scripts - openshiftNodeScript = "openshift/unstable/openshiftnodescript.sh" - openshiftMasterScript = "openshift/unstable/openshiftmasterscript.sh" - openshift39NodeScript = "openshift/release-3.9/openshiftnodescript.sh" - openshift39MasterScript = "openshift/release-3.9/openshiftmasterscript.sh" - sshdConfig = "k8s/sshd_config" - systemConf = "k8s/system.conf" -) - -const ( - dcosCustomData188 = "dcos/dcoscustomdata188.t" - dcosCustomData190 = "dcos/dcoscustomdata190.t" - dcosCustomData198 = "dcos/dcoscustomdata198.t" - dcosCustomData110 = "dcos/dcoscustomdata110.t" - dcosProvision = "dcos/dcosprovision.sh" - dcosWindowsProvision = "dcos/dcosWindowsProvision.ps1" - dcosProvisionSource = "dcos/dcosprovisionsource.sh" - dcos2Provision = "dcos/bstrap/dcosprovision.sh" - dcos2BootstrapProvision = "dcos/bstrap/bootstrapprovision.sh" - dcos2CustomData1110 = "dcos/bstrap/dcos1.11.0.customdata.t" - dcos2CustomData1112 = "dcos/bstrap/dcos1.11.2.customdata.t" -) - -const ( - swarmProvision = "swarm/configure-swarm-cluster.sh" - swarmWindowsProvision = "swarm/Install-ContainerHost-And-Join-Swarm.ps1" - swarmModeProvision = "swarm/configure-swarmmode-cluster.sh" - swarmModeWindowsProvision = "swarm/Join-SwarmMode-cluster.ps1" + sshdConfig = "k8s/sshd_config" + systemConf = "k8s/system.conf" ) const ( agentOutputs = "agentoutputs.t" agentParams = "agentparams.t" - dcosAgentResourcesVMAS = "dcos/dcosagentresourcesvmas.t" - dcosWindowsAgentResourcesVMAS = "dcos/dcosWindowsAgentResourcesVmas.t" - dcosAgentResourcesVMSS = "dcos/dcosagentresourcesvmss.t" - dcosWindowsAgentResourcesVMSS = "dcos/dcosWindowsAgentResourcesVmss.t" - dcosAgentVars = "dcos/dcosagentvars.t" - dcosBaseFile = "dcos/dcosbase.t" - dcosParams = "dcos/dcosparams.t" - dcosMasterResources = "dcos/dcosmasterresources.t" - dcosMasterVars = "dcos/dcosmastervars.t" - dcos2BaseFile = "dcos/bstrap/dcosbase.t" - dcos2BootstrapVars = "dcos/bstrap/bootstrapvars.t" - dcos2BootstrapParams = "dcos/bstrap/bootstrapparams.t" - dcos2BootstrapResources = "dcos/bstrap/bootstrapresources.t" - dcos2BootstrapCustomdata = "dcos/bstrap/bootstrapcustomdata.yml" - dcos2MasterVars = "dcos/bstrap/dcosmastervars.t" - dcos2MasterResources = "dcos/bstrap/dcosmasterresources.t" iaasOutputs = "iaasoutputs.t" kubernetesBaseFile = "k8s/kubernetesbase.t" kubernetesAgentResourcesVMAS = "k8s/kubernetesagentresourcesvmas.t" @@ -186,15 +144,5 @@ const ( kubernetesWinAgentVarsVMSS = "k8s/kuberneteswinagentresourcesvmss.t" masterOutputs = "masteroutputs.t" masterParams = "masterparams.t" - openshiftInfraResources = "openshift/infraresources.t" - swarmBaseFile = "swarm/swarmbase.t" - swarmParams = "swarm/swarmparams.t" - swarmAgentResourcesVMAS = "swarm/swarmagentresourcesvmas.t" - swarmAgentResourcesVMSS = "swarm/swarmagentresourcesvmss.t" - swarmAgentVars = "swarm/swarmagentvars.t" - swarmMasterResources = "swarm/swarmmasterresources.t" - swarmMasterVars = "swarm/swarmmastervars.t" - swarmWinAgentResourcesVMAS = "swarm/swarmwinagentresourcesvmas.t" - swarmWinAgentResourcesVMSS = "swarm/swarmwinagentresourcesvmss.t" windowsParams = "windowsparams.t" ) diff --git a/pkg/acsengine/customfiles.go b/pkg/engine/customfiles.go similarity index 96% rename from pkg/acsengine/customfiles.go rename to pkg/engine/customfiles.go index e37b09e11c..5e7a3458ec 100644 --- a/pkg/acsengine/customfiles.go +++ b/pkg/engine/customfiles.go @@ -1,4 +1,4 @@ -package acsengine +package engine import ( "bytes" @@ -7,7 +7,7 @@ import ( "os" "strings" - "github.com/Azure/acs-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/api" ) // CustomFileReader takes represents the source text of a file as an io.Reader and diff --git a/pkg/acsengine/customfiles_test.go b/pkg/engine/customfiles_test.go similarity index 97% rename from pkg/acsengine/customfiles_test.go rename to pkg/engine/customfiles_test.go index be4cf0e355..be7e77d8db 100644 --- a/pkg/acsengine/customfiles_test.go +++ b/pkg/engine/customfiles_test.go @@ -1,11 +1,11 @@ -package acsengine +package engine import ( "fmt" "strings" "testing" - "github.com/Azure/acs-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/api" ) func TestCustomFilesIntoReadersNonExistingFile(t *testing.T) { diff --git a/pkg/engine/doc.go b/pkg/engine/doc.go new file mode 100644 index 0000000000..e3125175ad --- /dev/null +++ b/pkg/engine/doc.go @@ -0,0 +1,2 @@ +// Package engine takes an AKS cluster model and generates the corresponding template +package engine diff --git a/pkg/acsengine/engine.go b/pkg/engine/engine.go similarity index 67% rename from pkg/acsengine/engine.go rename to pkg/engine/engine.go index 836639375f..a90094240a 100644 --- a/pkg/acsengine/engine.go +++ b/pkg/engine/engine.go @@ -1,4 +1,4 @@ -package acsengine +package engine import ( "bytes" @@ -14,30 +14,15 @@ import ( "sort" "strconv" "strings" - "text/template" + "text/template" //log "github.com/sirupsen/logrus" - //log "github.com/sirupsen/logrus" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/helpers" - "github.com/ghodss/yaml" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/helpers" "github.com/pkg/errors" ) var commonTemplateFiles = []string{agentOutputs, agentParams, masterOutputs, iaasOutputs, masterParams, windowsParams} -var dcosTemplateFiles = []string{dcosBaseFile, dcosAgentResourcesVMAS, dcosAgentResourcesVMSS, dcosAgentVars, dcosMasterResources, dcosMasterVars, dcosParams, dcosWindowsAgentResourcesVMAS, dcosWindowsAgentResourcesVMSS} -var dcos2TemplateFiles = []string{dcos2BaseFile, dcosAgentResourcesVMAS, dcosAgentResourcesVMSS, dcosAgentVars, dcos2MasterResources, dcos2BootstrapResources, dcos2MasterVars, dcosParams, dcosWindowsAgentResourcesVMAS, dcosWindowsAgentResourcesVMSS, dcos2BootstrapVars, dcos2BootstrapParams} var kubernetesTemplateFiles = []string{kubernetesBaseFile, kubernetesAgentResourcesVMAS, kubernetesAgentResourcesVMSS, kubernetesAgentVars, kubernetesMasterResourcesVMAS, kubernetesMasterResourcesVMSS, kubernetesMasterVars, kubernetesParams, kubernetesWinAgentVars, kubernetesWinAgentVarsVMSS} -var swarmTemplateFiles = []string{swarmBaseFile, swarmParams, swarmAgentResourcesVMAS, swarmAgentVars, swarmAgentResourcesVMSS, swarmBaseFile, swarmMasterResources, swarmMasterVars, swarmWinAgentResourcesVMAS, swarmWinAgentResourcesVMSS} -var swarmModeTemplateFiles = []string{swarmBaseFile, swarmParams, swarmAgentResourcesVMAS, swarmAgentVars, swarmAgentResourcesVMSS, swarmBaseFile, swarmMasterResources, swarmMasterVars, swarmWinAgentResourcesVMAS, swarmWinAgentResourcesVMSS} -var openshiftTemplateFiles = append( - kubernetesTemplateFiles, - openshiftInfraResources, - openshiftNodeScript, - openshiftMasterScript, - openshift39NodeScript, - openshift39MasterScript, -) var keyvaultSecretPathRe *regexp.Regexp @@ -106,15 +91,13 @@ func GenerateKubeConfig(properties *api.Properties, location string) (string, er // validateDistro checks if the requested orchestrator type is supported on the requested Linux distro. func validateDistro(cs *api.ContainerService) bool { // Check Master distro - if cs.Properties.MasterProfile != nil && cs.Properties.MasterProfile.Distro == api.RHEL && - (cs.Properties.OrchestratorProfile.OrchestratorType != api.SwarmMode && cs.Properties.OrchestratorProfile.OrchestratorType != api.OpenShift) { + if cs.Properties.MasterProfile != nil && cs.Properties.MasterProfile.Distro == api.RHEL { log.Fatalf("Orchestrator type %s not suported on RHEL Master", cs.Properties.OrchestratorProfile.OrchestratorType) return false } // Check Agent distros for _, agentProfile := range cs.Properties.AgentPoolProfiles { - if agentProfile.Distro == api.RHEL && - (cs.Properties.OrchestratorProfile.OrchestratorType != api.SwarmMode && cs.Properties.OrchestratorProfile.OrchestratorType != api.OpenShift) { + if agentProfile.Distro == api.RHEL { log.Fatalf("Orchestrator type %s not suported on RHEL Agent", cs.Properties.OrchestratorProfile.OrchestratorType) return false } @@ -122,40 +105,6 @@ func validateDistro(cs *api.ContainerService) bool { return true } -func getOpenshiftMasterShAsset(version string) string { - switch version { - case common.OpenShiftVersion3Dot9Dot0: - return openshift39MasterScript - case common.OpenShiftVersionUnstable: - return openshiftMasterScript - default: - panic(fmt.Sprintf("BUG: invalid OpenShift version %s", version)) - } -} - -func getOpenshiftNodeShAsset(version string) string { - switch version { - case common.OpenShiftVersion3Dot9Dot0: - return openshift39NodeScript - case common.OpenShiftVersionUnstable: - return openshiftNodeScript - default: - panic(fmt.Sprintf("BUG: invalid OpenShift version %s", version)) - } -} - -func generateIPList(count int, firstAddr string) []string { - ipaddr := net.ParseIP(firstAddr).To4() - if ipaddr == nil { - panic(fmt.Sprintf("IPAddr '%s' is an invalid IP address", firstAddr)) - } - ret := make([]string, count) - for i := 0; i < count; i++ { - ret[i] = fmt.Sprintf("%d.%d.%d.%d", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]+byte(i)) - } - return ret -} - func addValue(m paramsMap, k string, v interface{}) { m[k] = paramsMap{ "value": v, @@ -207,7 +156,7 @@ func getStorageAccountType(sizeName string) (string, error) { func makeMasterExtensionScriptCommands(cs *api.ContainerService) string { copyIndex := "',copyIndex(),'" - if cs.Properties.OrchestratorProfile.IsKubernetes() || cs.Properties.OrchestratorProfile.IsOpenShift() { + if cs.Properties.OrchestratorProfile.IsKubernetes() { copyIndex = "',copyIndex(variables('masterOffset')),'" } return makeExtensionScriptCommands(cs.Properties.MasterProfile.PreprovisionExtension, @@ -266,171 +215,6 @@ func makeWindowsExtensionScriptCommands(extension *api.Extension, extensionProfi return fmt.Sprintf("New-Item -ItemType Directory -Force -Path \"%s\" ; Invoke-WebRequest -Uri \"%s\" -OutFile \"%s\" ; powershell \"%s %s\"\n", scriptFileDir, scriptURL, scriptFilePath, scriptFilePath, "$preprovisionExtensionParams") } -func getDCOSWindowsAgentPreprovisionParameters(cs *api.ContainerService, profile *api.AgentPoolProfile) string { - extension := profile.PreprovisionExtension - - var extensionProfile *api.ExtensionProfile - - for _, eP := range cs.Properties.ExtensionProfiles { - if strings.EqualFold(eP.Name, extension.Name) { - extensionProfile = eP - break - } - } - - parms := extensionProfile.ExtensionParameters - return parms -} - -func getDCOSDefaultBootstrapInstallerURL(profile *api.OrchestratorProfile) string { - if profile.OrchestratorType == api.DCOS { - switch profile.OrchestratorVersion { - case common.DCOSVersion1Dot11Dot2: - return "https://dcos-mirror.azureedge.net/dcos-1-11-2/dcos_generate_config.sh" - case common.DCOSVersion1Dot11Dot0: - return "https://dcos-mirror.azureedge.net/dcos-1-11-0/dcos_generate_config.sh" - } - } - return "" -} - -func getDCOSDefaultWindowsBootstrapInstallerURL(profile *api.OrchestratorProfile) string { - if profile.OrchestratorType == api.DCOS { - switch profile.OrchestratorVersion { - case common.DCOSVersion1Dot11Dot2: - return "https://dcos-mirror.azureedge.net/dcos-windows/1-11-2" - case common.DCOSVersion1Dot11Dot0: - return "https://dcos-mirror.azureedge.net/dcos-windows/1-11-0" - } - } - return "" -} - -func getDCOSDefaultProviderPackageGUID(orchestratorType string, orchestratorVersion string, masterCount int) string { - if orchestratorType == api.DCOS { - switch orchestratorVersion { - case common.DCOSVersion1Dot10Dot0: - switch masterCount { - case 1: - return "c4ec6210f396b8e435177b82e3280a2cef0ce721" - case 3: - return "08197947cb57d479eddb077a429fa15c139d7d20" - case 5: - return "f286ad9d3641da5abb622e4a8781f73ecd8492fa" - } - case common.DCOSVersion1Dot9Dot0: - switch masterCount { - case 1: - return "bcc883b7a3191412cf41824bdee06c1142187a0b" - case 3: - return "dcff7e24c0c1827bebeb7f1a806f558054481b33" - case 5: - return "b41bfa84137a6374b2ff5eb1655364d7302bd257" - } - case common.DCOSVersion1Dot9Dot8: - switch masterCount { - case 1: - return "e8b0e3fc4a16394dc6dd5b19fc54bf1543bff429" - case 3: - return "2d36c3f570d9dd7d187c699f9a322ed9d95e7dfa" - case 5: - return "c03c9587f88929f310b80af4f448b7b51654f1c8" - } - case common.DCOSVersion1Dot8Dot8: - switch masterCount { - case 1: - return "441385ce2f5942df7e29075c12fb38fa5e92cbba" - case 3: - return "b1cd359287504efb780257bd12cc3a63704e42d4" - case 5: - return "d9b61156dfcc9383e014851529738aa550ef57d9" - } - } - } - return "" -} - -func getDCOSDefaultRepositoryURL(orchestratorType string, orchestratorVersion string) string { - if orchestratorType == api.DCOS { - switch orchestratorVersion { - case common.DCOSVersion1Dot10Dot0: - return "https://dcosio.azureedge.net/dcos/stable/1.10.0" - case common.DCOSVersion1Dot9Dot8: - return "https://dcosio.azureedge.net/dcos/stable/1.9.8" - default: - return "https://dcosio.azureedge.net/dcos/stable" - } - } - return "" -} - -func getDCOSCustomDataPublicIPStr(orchestratorType string, masterCount int) string { - if orchestratorType == api.DCOS { - var buf bytes.Buffer - for i := 0; i < masterCount; i++ { - buf.WriteString(fmt.Sprintf("reference(variables('masterVMNic')[%d]).ipConfigurations[0].properties.privateIPAddress,", i)) - if i < (masterCount - 1) { - buf.WriteString(`'\\\", \\\"', `) - } - } - return buf.String() - } - return "" -} - -func getDCOSMasterCustomNodeLabels() string { - // return empty string for DCOS since no attribtutes needed on master - return "" -} - -func getDCOSAgentCustomNodeLabels(profile *api.AgentPoolProfile) string { - var buf bytes.Buffer - var attrstring string - buf.WriteString("") - // always write MESOS_ATTRIBUTES because - // the provision script will add FD/UD attributes - // at node provisioning time - if len(profile.OSType) > 0 { - attrstring = fmt.Sprintf("MESOS_ATTRIBUTES=\"os:%s", profile.OSType) - } else { - attrstring = fmt.Sprintf("MESOS_ATTRIBUTES=\"os:%s", api.Linux) - } - - if len(profile.Ports) > 0 { - attrstring += ";public_ip:yes" - } - - buf.WriteString(attrstring) - if len(profile.CustomNodeLabels) > 0 { - for k, v := range profile.CustomNodeLabels { - buf.WriteString(fmt.Sprintf(";%s:%s", k, v)) - } - } - buf.WriteString("\"") - return buf.String() -} - -func getDCOSWindowsAgentCustomAttributes(profile *api.AgentPoolProfile) string { - var buf bytes.Buffer - var attrstring string - buf.WriteString("") - if len(profile.OSType) > 0 { - attrstring = fmt.Sprintf("os:%s", profile.OSType) - } else { - attrstring = fmt.Sprintf("os:windows") - } - if len(profile.Ports) > 0 { - attrstring += ";public_ip:yes" - } - buf.WriteString(attrstring) - if len(profile.CustomNodeLabels) > 0 { - for k, v := range profile.CustomNodeLabels { - buf.WriteString(fmt.Sprintf(";%s:%s", k, v)) - } - } - return buf.String() -} - func getVNETAddressPrefixes(properties *api.Properties) string { visitedSubnets := make(map[string]bool) var buf bytes.Buffer @@ -678,21 +462,6 @@ func getBase64CustomScriptFromStr(str string) string { return base64.StdEncoding.EncodeToString(gzipB.Bytes()) } -func getDCOSProvisionScript(script string) string { - // add the provision script - bp, err := Asset(script) - if err != nil { - panic(fmt.Sprintf("BUG: %s", err.Error())) - } - - provisionScript := string(bp) - if strings.Contains(provisionScript, "'") { - panic(fmt.Sprintf("BUG: %s may not contain character '", script)) - } - - return strings.Replace(strings.Replace(provisionScript, "\r\n", "\n", -1), "\n", "\n\n ", -1) -} - func getAddonFuncMap(addon api.KubernetesAddon) template.FuncMap { return template.FuncMap{ "ContainerImage": func(name string) string { @@ -765,163 +534,6 @@ func getContainerAddonsString(properties *api.Properties, sourcePath string) str return result } -func getDCOSAgentProvisionScript(profile *api.AgentPoolProfile, orchProfile *api.OrchestratorProfile, bootstrapIP string) string { - // add the provision script - scriptname := dcos2Provision - if orchProfile.DcosConfig == nil || orchProfile.DcosConfig.BootstrapProfile == nil { - if profile.OSType == api.Windows { - scriptname = dcosWindowsProvision - } else { - scriptname = dcosProvision - } - } - - bp, err := Asset(scriptname) - if err != nil { - panic(fmt.Sprintf("BUG: %s", err.Error())) - } - - provisionScript := string(bp) - if strings.Contains(provisionScript, "'") { - panic(fmt.Sprintf("BUG: %s may not contain character '", dcosProvision)) - } - - // the embedded roleFileContents - var roleFileContents string - if len(profile.Ports) > 0 { - // public agents - roleFileContents = "touch /etc/mesosphere/roles/slave_public" - } else { - roleFileContents = "touch /etc/mesosphere/roles/slave" - } - provisionScript = strings.Replace(provisionScript, "ROLESFILECONTENTS", roleFileContents, -1) - provisionScript = strings.Replace(provisionScript, "BOOTSTRAP_IP", bootstrapIP, -1) - - var b bytes.Buffer - b.WriteString(provisionScript) - b.WriteString("\n") - - if len(orchProfile.DcosConfig.Registry) == 0 { - b.WriteString("rm /etc/docker.tar.gz\n") - } - - return strings.Replace(strings.Replace(b.String(), "\r\n", "\n", -1), "\n", "\n\n ", -1) -} - -func getDCOSMasterProvisionScript(orchProfile *api.OrchestratorProfile, bootstrapIP string) string { - scriptname := dcos2Provision - if orchProfile.DcosConfig == nil || orchProfile.DcosConfig.BootstrapProfile == nil { - scriptname = dcosProvision - } - - // add the provision script - bp, err := Asset(scriptname) - if err != nil { - panic(fmt.Sprintf("BUG: %s", err.Error())) - } - - provisionScript := string(bp) - if strings.Contains(provisionScript, "'") { - panic(fmt.Sprintf("BUG: %s may not contain character '", scriptname)) - } - - // the embedded roleFileContents - roleFileContents := `touch /etc/mesosphere/roles/master -touch /etc/mesosphere/roles/azure_master` - provisionScript = strings.Replace(provisionScript, "ROLESFILECONTENTS", roleFileContents, -1) - provisionScript = strings.Replace(provisionScript, "BOOTSTRAP_IP", bootstrapIP, -1) - - var b bytes.Buffer - b.WriteString(provisionScript) - b.WriteString("\n") - - return strings.Replace(strings.Replace(b.String(), "\r\n", "\n", -1), "\n", "\n\n ", -1) -} - -func getDCOSCustomDataTemplate(orchestratorType, orchestratorVersion string) string { - switch orchestratorType { - case api.DCOS: - switch orchestratorVersion { - case common.DCOSVersion1Dot8Dot8: - return dcosCustomData188 - case common.DCOSVersion1Dot9Dot0: - return dcosCustomData190 - case common.DCOSVersion1Dot9Dot8: - return dcosCustomData198 - case common.DCOSVersion1Dot10Dot0: - return dcosCustomData110 - case common.DCOSVersion1Dot11Dot0: - return dcos2CustomData1110 - case common.DCOSVersion1Dot11Dot2: - return dcos2CustomData1112 - } - default: - // it is a bug to get here - panic(fmt.Sprintf("BUG: invalid orchestrator %s", orchestratorType)) - } - return "" -} - -// getSingleLineForTemplate returns the file as a single line for embedding in an arm template -func getSingleLineDCOSCustomData(orchestratorType, yamlFilename string, masterCount int, replaceMap map[string]string) string { - b, err := Asset(yamlFilename) - if err != nil { - panic(fmt.Sprintf("BUG getting yaml custom data file: %s", err.Error())) - } - yamlStr := string(b) - for k, v := range replaceMap { - yamlStr = strings.Replace(yamlStr, k, v, -1) - } - - // convert to json - jsonBytes, err4 := yaml.YAMLToJSON([]byte(yamlStr)) - if err4 != nil { - panic(fmt.Sprintf("BUG: %s", err4.Error())) - } - yamlStr = string(jsonBytes) - - // convert to one line - yamlStr = strings.Replace(yamlStr, "\\", "\\\\", -1) - yamlStr = strings.Replace(yamlStr, "\r\n", "\\n", -1) - yamlStr = strings.Replace(yamlStr, "\n", "\\n", -1) - yamlStr = strings.Replace(yamlStr, "\"", "\\\"", -1) - - // variable replacement - rVariable, e1 := regexp.Compile("{{{([^}]*)}}}") - if e1 != nil { - panic(fmt.Sprintf("BUG: %s", e1.Error())) - } - yamlStr = rVariable.ReplaceAllString(yamlStr, "',variables('$1'),'") - - // replace the internal values - publicIPStr := getDCOSCustomDataPublicIPStr(orchestratorType, masterCount) - yamlStr = strings.Replace(yamlStr, "DCOSCUSTOMDATAPUBLICIPSTR", publicIPStr, -1) - - return yamlStr -} - -func buildYamlFileWithWriteFiles(files []string) string { - clusterYamlFile := `#cloud-config - -write_files: -%s -` - writeFileBlock := ` - encoding: gzip - content: !!binary | - %s - path: /opt/azure/containers/%s - permissions: "0744" -` - - filelines := "" - for _, file := range files { - b64GzipString := getBase64CustomScript(file) - fileNoPath := strings.TrimPrefix(file, "swarm/") - filelines = filelines + fmt.Sprintf(writeFileBlock, b64GzipString, fileNoPath) - } - return fmt.Sprintf(clusterYamlFile, filelines) -} - func getKubernetesSubnets(properties *api.Properties) string { subnetString := `{ "name": "podCIDR%d", @@ -1008,13 +620,9 @@ func getLinkedTemplatesForExtensions(properties *api.Properties) string { func getMasterLinkedTemplateText(masterProfile *api.MasterProfile, orchestratorType string, extensionProfile *api.ExtensionProfile, singleOrAll string) (string, error) { extTargetVMNamePrefix := "variables('masterVMNamePrefix')" - loopCount := "[variables('masterCount')]" - loopOffset := "" - if orchestratorType == api.Kubernetes || orchestratorType == api.OpenShift { - // Due to upgrade k8s sometimes needs to install just some of the nodes. - loopCount = "[sub(variables('masterCount'), variables('masterOffset'))]" - loopOffset = "variables('masterOffset')" - } + // Due to upgrade k8s sometimes needs to install just some of the nodes. + loopCount := "[sub(variables('masterCount'), variables('masterOffset'))]" + loopOffset := "variables('masterOffset')" if strings.EqualFold(singleOrAll, "single") { loopCount = "1" @@ -1155,7 +763,3 @@ func stringInSlice(a string, list []string) bool { } return false } - -func getSwarmVersions(orchestratorVersion, dockerComposeVersion string) string { - return fmt.Sprintf("\"orchestratorVersion\": \"%s\",\n\"dockerComposeVersion\": \"%s\",\n", orchestratorVersion, dockerComposeVersion) -} diff --git a/pkg/acsengine/engine_test.go b/pkg/engine/engine_test.go similarity index 93% rename from pkg/acsengine/engine_test.go rename to pkg/engine/engine_test.go index eaf774cf9c..bb38d5d2b4 100644 --- a/pkg/acsengine/engine_test.go +++ b/pkg/engine/engine_test.go @@ -1,4 +1,4 @@ -package acsengine +package engine import ( "bytes" @@ -10,19 +10,18 @@ import ( "strings" "testing" - "github.com/Azure/acs-engine/pkg/acsengine/transform" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/api/v20160330" - "github.com/Azure/acs-engine/pkg/api/vlabs" - "github.com/Azure/acs-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/api/vlabs" + "github.com/Azure/aks-engine/pkg/engine/transform" + "github.com/Azure/aks-engine/pkg/i18n" "github.com/leonelquinteros/gotext" "github.com/pkg/errors" ) const ( TestDataDir = "./testdata" - TestACSEngineVersion = "1.0.0" + TestAKSEngineVersion = "1.0.0" ) func TestExpected(t *testing.T) { @@ -49,11 +48,10 @@ func TestExpected(t *testing.T) { continue } - if version != vlabs.APIVersion && version != v20160330.APIVersion { + if version != vlabs.APIVersion { // Set CertificateProfile here to avoid a new one generated. // Kubernetes template needs certificate profile to match expected template // API versions other than vlabs don't expose CertificateProfile - // API versions after v20160330 supports Kubernetes containerService.Properties.CertificateProfile = &api.CertificateProfile{} addTestCertificateProfile(containerService.Properties.CertificateProfile) } @@ -75,7 +73,7 @@ func TestExpected(t *testing.T) { certsGenerated, err := containerService.SetPropertiesDefaults(false, false) - armTemplate, params, err := templateGenerator.GenerateTemplate(containerService, DefaultGeneratorCode, TestACSEngineVersion) + armTemplate, params, err := templateGenerator.GenerateTemplate(containerService, DefaultGeneratorCode, TestAKSEngineVersion) if err != nil { t.Error(errors.Errorf("error in file %s: %s", tuple.APIModelFilename, err.Error())) continue @@ -100,7 +98,7 @@ func TestExpected(t *testing.T) { for i := 0; i < 3; i++ { certsGenerated, err = containerService.SetPropertiesDefaults(false, false) - armTemplate, params, err := templateGenerator.GenerateTemplate(containerService, DefaultGeneratorCode, TestACSEngineVersion) + armTemplate, params, err := templateGenerator.GenerateTemplate(containerService, DefaultGeneratorCode, TestAKSEngineVersion) if err != nil { t.Error(errors.Errorf("error in file %s: %s", tuple.APIModelFilename, err.Error())) continue @@ -145,11 +143,10 @@ func TestExpected(t *testing.T) { if err != nil { t.Error(err) } - if version != vlabs.APIVersion && version != v20160330.APIVersion { + if version != vlabs.APIVersion { // Set CertificateProfile here to avoid a new one generated. // Kubernetes template needs certificate profile to match expected template // API versions other than vlabs don't expose CertificateProfile - // API versions after v20160330 supports Kubernetes containerService.Properties.CertificateProfile = &api.CertificateProfile{} addTestCertificateProfile(containerService.Properties.CertificateProfile) } @@ -294,7 +291,7 @@ func TestTemplateOutputPresence(t *testing.T) { t.Fatalf("Failed to load container service from file: %v", err) } containerService.SetPropertiesDefaults(false, false) - armTemplate, _, err := templateGenerator.GenerateTemplate(containerService, DefaultGeneratorCode, TestACSEngineVersion) + armTemplate, _, err := templateGenerator.GenerateTemplate(containerService, DefaultGeneratorCode, TestAKSEngineVersion) if err != nil { t.Fatalf("Failed to generate arm template: %v", err) } @@ -510,21 +507,6 @@ func TestIsNSeriesSKU(t *testing.T) { } } -func TestGenerateIpList(t *testing.T) { - count := 3 - forth := 240 - ipList := generateIPList(count, fmt.Sprintf("10.0.0.%d", forth)) - if len(ipList) != 3 { - t.Fatalf("IP list size should be %d", count) - } - for i, ip := range ipList { - expected := fmt.Sprintf("10.0.0.%d", forth+i) - if ip != expected { - t.Fatalf("wrong IP %s. Expected %s", ip, expected) - } - } -} - func TestGenerateKubeConfig(t *testing.T) { locale := gotext.NewLocale(path.Join("..", "..", "translations"), "en_US") i18n.Initialize(locale) diff --git a/pkg/acsengine/fileloader.go b/pkg/engine/fileloader.go similarity index 94% rename from pkg/acsengine/fileloader.go rename to pkg/engine/fileloader.go index 9c3918027b..6c6f8bb7fb 100644 --- a/pkg/acsengine/fileloader.go +++ b/pkg/engine/fileloader.go @@ -1,4 +1,4 @@ -package acsengine +package engine //go:generate go-bindata -nometadata -pkg $GOPACKAGE -prefix ../../parts/ -o templates.go ../../parts/... //go:generate gofmt -s -l -w templates.go diff --git a/pkg/acsengine/output.go b/pkg/engine/output.go similarity index 85% rename from pkg/acsengine/output.go rename to pkg/engine/output.go index 21d59f5d95..4a3b4d51a6 100644 --- a/pkg/acsengine/output.go +++ b/pkg/engine/output.go @@ -1,15 +1,13 @@ -package acsengine +package engine import ( "fmt" - "io/ioutil" "path" - "path/filepath" "strconv" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/helpers" - "github.com/Azure/acs-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/i18n" "github.com/pkg/errors" ) @@ -128,15 +126,6 @@ func (w *ArtifactWriter) WriteTLSArtifacts(containerService *api.ContainerServic return e } } - } else if properties.OrchestratorProfile.IsOpenShift() { - masterTarballPath := filepath.Join(artifactsDir, "master.tar.gz") - masterBundle := properties.OrchestratorProfile.OpenShiftConfig.ConfigBundles["master"] - if err := ioutil.WriteFile(masterTarballPath, masterBundle, 0644); err != nil { - return err - } - nodeTarballPath := filepath.Join(artifactsDir, "node.tar.gz") - nodeBundle := properties.OrchestratorProfile.OpenShiftConfig.ConfigBundles["bootstrap"] - return ioutil.WriteFile(nodeTarballPath, nodeBundle, 0644) } return nil diff --git a/pkg/acsengine/output_test.go b/pkg/engine/output_test.go similarity index 95% rename from pkg/acsengine/output_test.go rename to pkg/engine/output_test.go index 30e9ae9686..252fe2c310 100644 --- a/pkg/acsengine/output_test.go +++ b/pkg/engine/output_test.go @@ -1,4 +1,4 @@ -package acsengine +package engine import ( "fmt" @@ -6,9 +6,9 @@ import ( "path" "testing" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/helpers" - "github.com/Azure/acs-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/i18n" ) func TestWriteTLSArtifacts(t *testing.T) { diff --git a/pkg/acsengine/params.go b/pkg/engine/params.go similarity index 59% rename from pkg/acsengine/params.go rename to pkg/engine/params.go index 1ca7d0622d..00f996c849 100644 --- a/pkg/acsengine/params.go +++ b/pkg/engine/params.go @@ -1,23 +1,20 @@ -package acsengine +package engine import ( - "encoding/base64" "fmt" - "strings" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/helpers" ) -func getParameters(cs *api.ContainerService, generatorCode string, acsengineVersion string) (paramsMap, error) { +func getParameters(cs *api.ContainerService, generatorCode string, aksengineVersion string) (paramsMap, error) { properties := cs.Properties location := cs.Location parametersMap := paramsMap{} cloudSpecConfig := cs.GetCloudSpecConfig() - // acsengine Parameters - addValue(parametersMap, "acsengineVersion", acsengineVersion) + // aksengine Parameters + addValue(parametersMap, "aksengineVersion", aksengineVersion) // Master Parameters addValue(parametersMap, "location", location) @@ -33,8 +30,6 @@ func getParameters(cs *api.ContainerService, generatorCode string, acsengineVers addValue(parametersMap, "osImageResourceGroup", properties.MasterProfile.ImageRef.ResourceGroup) } } - // TODO: Choose the correct image config based on the version - // for the openshift orchestrator addValue(parametersMap, "fqdnEndpointSuffix", cloudSpecConfig.EndpointConfig.ResourceManagerVMDNSSuffix) addValue(parametersMap, "targetEnvironment", helpers.GetCloudTargetEnv(cs.Location)) @@ -47,7 +42,7 @@ func getParameters(cs *api.ContainerService, generatorCode string, acsengineVers if properties.LinuxProfile.CustomNodesDNS != nil { addValue(parametersMap, "dnsServer", properties.LinuxProfile.CustomNodesDNS.DNSServer) } - // masterEndpointDNSNamePrefix is the basis for storage account creation across dcos, swarm, and k8s + // masterEndpointDNSNamePrefix is the basis for storage account creation in k8s if properties.MasterProfile != nil { // MasterProfile exists, uses master DNS prefix addValue(parametersMap, "masterEndpointDNSNamePrefix", properties.MasterProfile.DNSPrefix) @@ -61,7 +56,7 @@ func getParameters(cs *api.ContainerService, generatorCode string, acsengineVers if properties.MasterProfile.IsVirtualMachineScaleSets() { addValue(parametersMap, "agentVnetSubnetID", properties.MasterProfile.AgentVnetSubnetID) } - if properties.OrchestratorProfile.IsKubernetes() || properties.OrchestratorProfile.IsOpenShift() { + if properties.OrchestratorProfile.IsKubernetes() { addValue(parametersMap, "vnetCidr", properties.MasterProfile.VnetCidr) } } else { @@ -85,98 +80,11 @@ func getParameters(cs *api.ContainerService, generatorCode string, acsengineVers } } - //Swarm and SwarmMode Parameters - if properties.OrchestratorProfile.OrchestratorType == api.Swarm || properties.OrchestratorProfile.OrchestratorType == api.SwarmMode { - var dockerEngineRepo, dockerComposeDownloadURL string - if cloudSpecConfig.DockerSpecConfig.DockerEngineRepo == "" { - dockerEngineRepo = DefaultDockerEngineRepo - } else { - dockerEngineRepo = cloudSpecConfig.DockerSpecConfig.DockerEngineRepo - } - if cloudSpecConfig.DockerSpecConfig.DockerComposeDownloadURL == "" { - dockerComposeDownloadURL = DefaultDockerComposeURL - } else { - dockerComposeDownloadURL = cloudSpecConfig.DockerSpecConfig.DockerComposeDownloadURL - } - addValue(parametersMap, "dockerEngineDownloadRepo", dockerEngineRepo) - addValue(parametersMap, "dockerComposeDownloadURL", dockerComposeDownloadURL) - } - // Kubernetes Parameters - if properties.OrchestratorProfile.IsKubernetes() || - properties.OrchestratorProfile.IsOpenShift() { + if properties.OrchestratorProfile.IsKubernetes() { assignKubernetesParameters(properties, parametersMap, cloudSpecConfig, generatorCode) } - if strings.HasPrefix(properties.OrchestratorProfile.OrchestratorType, api.DCOS) { - dcosBootstrapURL := cloudSpecConfig.DCOSSpecConfig.DCOS188BootstrapDownloadURL - dcosWindowsBootstrapURL := cloudSpecConfig.DCOSSpecConfig.DCOSWindowsBootstrapDownloadURL - dcosRepositoryURL := cloudSpecConfig.DCOSSpecConfig.DcosRepositoryURL - dcosClusterPackageListID := cloudSpecConfig.DCOSSpecConfig.DcosClusterPackageListID - dcosProviderPackageID := cloudSpecConfig.DCOSSpecConfig.DcosProviderPackageID - - switch properties.OrchestratorProfile.OrchestratorType { - case api.DCOS: - switch properties.OrchestratorProfile.OrchestratorVersion { - case common.DCOSVersion1Dot8Dot8: - dcosBootstrapURL = cloudSpecConfig.DCOSSpecConfig.DCOS188BootstrapDownloadURL - case common.DCOSVersion1Dot9Dot0: - dcosBootstrapURL = cloudSpecConfig.DCOSSpecConfig.DCOS190BootstrapDownloadURL - case common.DCOSVersion1Dot9Dot8: - dcosBootstrapURL = cloudSpecConfig.DCOSSpecConfig.DCOS198BootstrapDownloadURL - case common.DCOSVersion1Dot10Dot0: - dcosBootstrapURL = cloudSpecConfig.DCOSSpecConfig.DCOS110BootstrapDownloadURL - default: - dcosBootstrapURL = getDCOSDefaultBootstrapInstallerURL(properties.OrchestratorProfile) - dcosWindowsBootstrapURL = getDCOSDefaultWindowsBootstrapInstallerURL(properties.OrchestratorProfile) - } - } - - if properties.OrchestratorProfile.DcosConfig != nil { - if properties.OrchestratorProfile.DcosConfig.DcosWindowsBootstrapURL != "" { - dcosWindowsBootstrapURL = properties.OrchestratorProfile.DcosConfig.DcosWindowsBootstrapURL - } - if properties.OrchestratorProfile.DcosConfig.DcosBootstrapURL != "" { - dcosBootstrapURL = properties.OrchestratorProfile.DcosConfig.DcosBootstrapURL - } - if len(properties.OrchestratorProfile.DcosConfig.Registry) > 0 { - addValue(parametersMap, "registry", properties.OrchestratorProfile.DcosConfig.Registry) - addValue(parametersMap, "registryKey", base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", properties.OrchestratorProfile.DcosConfig.RegistryUser, properties.OrchestratorProfile.DcosConfig.RegistryPass)))) - } - if properties.OrchestratorProfile.DcosConfig.DcosRepositoryURL != "" { - dcosRepositoryURL = properties.OrchestratorProfile.DcosConfig.DcosRepositoryURL - } else { - dcosRepositoryURL = getDCOSDefaultRepositoryURL( - properties.OrchestratorProfile.OrchestratorType, - properties.OrchestratorProfile.OrchestratorVersion) - } - - if properties.OrchestratorProfile.DcosConfig.DcosClusterPackageListID != "" { - dcosClusterPackageListID = properties.OrchestratorProfile.DcosConfig.DcosClusterPackageListID - } - - if properties.OrchestratorProfile.DcosConfig.DcosProviderPackageID != "" { - dcosProviderPackageID = properties.OrchestratorProfile.DcosConfig.DcosProviderPackageID - } else { - dcosProviderPackageID = getDCOSDefaultProviderPackageGUID( - properties.OrchestratorProfile.OrchestratorType, - properties.OrchestratorProfile.OrchestratorVersion, - properties.MasterProfile.Count) - } - } - - addValue(parametersMap, "dcosBootstrapURL", dcosBootstrapURL) - addValue(parametersMap, "dcosWindowsBootstrapURL", dcosWindowsBootstrapURL) - addValue(parametersMap, "dcosRepositoryURL", dcosRepositoryURL) - addValue(parametersMap, "dcosClusterPackageListID", dcosClusterPackageListID) - addValue(parametersMap, "dcosProviderPackageID", dcosProviderPackageID) - - if properties.OrchestratorProfile.DcosConfig != nil && properties.OrchestratorProfile.DcosConfig.BootstrapProfile != nil { - addValue(parametersMap, "bootstrapStaticIP", properties.OrchestratorProfile.DcosConfig.BootstrapProfile.StaticIP) - addValue(parametersMap, "bootstrapVMSize", properties.OrchestratorProfile.DcosConfig.BootstrapProfile.VMSize) - } - } - // Agent parameters for _, agentProfile := range properties.AgentPoolProfiles { addValue(parametersMap, fmt.Sprintf("%sCount", agentProfile.Name), agentProfile.Count) @@ -229,6 +137,27 @@ func getParameters(cs *api.ContainerService, generatorCode string, acsengineVers addValue(parametersMap, "windowsDockerVersion", properties.WindowsProfile.GetWindowsDockerVersion()) + if properties.OrchestratorProfile.IsKubernetes() { + k8sVersion := properties.OrchestratorProfile.OrchestratorVersion + + if properties.OrchestratorProfile.KubernetesConfig != nil { + + // Kubernetes packages as zip file as created by scripts/build-windows-k8s.sh + // will be removed in future release as if gets phased out (https://github.com/Azure/aks-engine/issues/3851) + kubeBinariesSASURL := properties.OrchestratorProfile.KubernetesConfig.CustomWindowsPackageURL + if kubeBinariesSASURL == "" { + kubeBinariesSASURL = cloudSpecConfig.KubernetesSpecConfig.KubeBinariesSASURLBase + api.K8sComponentsByVersionMap[k8sVersion]["windowszip"] + } + addValue(parametersMap, "kubeBinariesSASURL", kubeBinariesSASURL) + + // Kubernetes node binaries as packaged by upstream kubernetes + // example at https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.11.md#node-binaries-1 + addValue(parametersMap, "windowsKubeBinariesURL", properties.OrchestratorProfile.KubernetesConfig.WindowsNodeBinariesURL) + + addValue(parametersMap, "kubeBinariesVersion", k8sVersion) + addValue(parametersMap, "windowsTelemetryGUID", cloudSpecConfig.KubernetesSpecConfig.WindowsTelemetryGUID) + } + } for i, s := range properties.WindowsProfile.Secrets { addValue(parametersMap, fmt.Sprintf("windowsKeyVaultID%d", i), s.SourceVault.ID) for j, c := range s.VaultCertificates { diff --git a/pkg/acsengine/params_k8s.go b/pkg/engine/params_k8s.go similarity index 98% rename from pkg/acsengine/params_k8s.go rename to pkg/engine/params_k8s.go index 5bbf88a652..d6ebc4a604 100644 --- a/pkg/acsengine/params_k8s.go +++ b/pkg/engine/params_k8s.go @@ -1,4 +1,4 @@ -package acsengine +package engine import ( "fmt" @@ -7,9 +7,9 @@ import ( "strings" "time" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/helpers" ) func assignKubernetesParameters(properties *api.Properties, parametersMap paramsMap, @@ -18,8 +18,7 @@ func assignKubernetesParameters(properties *api.Properties, parametersMap params orchestratorProfile := properties.OrchestratorProfile - if orchestratorProfile.IsKubernetes() || - orchestratorProfile.IsOpenShift() { + if orchestratorProfile.IsKubernetes() { k8sVersion := orchestratorProfile.OrchestratorVersion k8sComponents := api.K8sComponentsByVersionMap[k8sVersion] diff --git a/pkg/acsengine/params_k8s_test.go b/pkg/engine/params_k8s_test.go similarity index 86% rename from pkg/acsengine/params_k8s_test.go rename to pkg/engine/params_k8s_test.go index b0422c9084..03b0b0a70c 100644 --- a/pkg/acsengine/params_k8s_test.go +++ b/pkg/engine/params_k8s_test.go @@ -1,11 +1,11 @@ -package acsengine +package engine import ( "path" "testing" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/i18n" "github.com/leonelquinteros/gotext" ) @@ -46,8 +46,3 @@ func TestAssignKubernetesParameters(t *testing.T) { } } } - -func isKeyPresent(key string, paramMap map[string]interface{}) bool { - _, ok := paramMap[key] - return ok -} diff --git a/pkg/acsengine/params_test.go b/pkg/engine/params_test.go similarity index 92% rename from pkg/acsengine/params_test.go rename to pkg/engine/params_test.go index 20e8c3e2d2..e307075133 100644 --- a/pkg/acsengine/params_test.go +++ b/pkg/engine/params_test.go @@ -1,11 +1,11 @@ -package acsengine +package engine import ( "path" "testing" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/i18n" "github.com/leonelquinteros/gotext" ) diff --git a/pkg/acsengine/template_generator.go b/pkg/engine/template_generator.go similarity index 67% rename from pkg/acsengine/template_generator.go rename to pkg/engine/template_generator.go index ddfaff057b..8f89bea9d3 100644 --- a/pkg/acsengine/template_generator.go +++ b/pkg/engine/template_generator.go @@ -1,4 +1,4 @@ -package acsengine +package engine import ( "archive/zip" @@ -11,10 +11,10 @@ import ( "strings" "text/template" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/pkg/helpers" - "github.com/Azure/acs-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/i18n" "github.com/pkg/errors" log "github.com/sirupsen/logrus" ) @@ -38,7 +38,7 @@ func InitializeTemplateGenerator(ctx Context) (*TemplateGenerator, error) { } // GenerateTemplate generates the template from the API Model -func (t *TemplateGenerator) GenerateTemplate(containerService *api.ContainerService, generatorCode string, acsengineVersion string) (templateRaw string, parametersRaw string, err error) { +func (t *TemplateGenerator) GenerateTemplate(containerService *api.ContainerService, generatorCode string, aksengineVersion string) (templateRaw string, parametersRaw string, err error) { // named return values are used in order to set err in case of a panic templateRaw = "" parametersRaw = "" @@ -95,7 +95,7 @@ func (t *TemplateGenerator) GenerateTemplate(containerService *api.ContainerServ templateRaw = b.String() var parametersMap paramsMap - if parametersMap, err = getParameters(containerService, generatorCode, acsengineVersion); err != nil { + if parametersMap, err = getParameters(containerService, generatorCode, aksengineVersion); err != nil { return templateRaw, parametersRaw, err } @@ -110,11 +110,7 @@ func (t *TemplateGenerator) GenerateTemplate(containerService *api.ContainerServ func (t *TemplateGenerator) verifyFiles() error { allFiles := commonTemplateFiles - allFiles = append(allFiles, dcosTemplateFiles...) - allFiles = append(allFiles, dcos2TemplateFiles...) allFiles = append(allFiles, kubernetesTemplateFiles...) - allFiles = append(allFiles, openshiftTemplateFiles...) - allFiles = append(allFiles, swarmTemplateFiles...) for _, file := range allFiles { if _, err := Asset(file); err != nil { return t.Translator.Errorf("template file %s does not exist", file) @@ -124,34 +120,8 @@ func (t *TemplateGenerator) verifyFiles() error { } func (t *TemplateGenerator) prepareTemplateFiles(properties *api.Properties) ([]string, string, error) { - var files []string - var baseFile string - switch properties.OrchestratorProfile.OrchestratorType { - case api.DCOS: - if properties.OrchestratorProfile.DcosConfig == nil || properties.OrchestratorProfile.DcosConfig.BootstrapProfile == nil { - files = append(commonTemplateFiles, dcosTemplateFiles...) - baseFile = dcosBaseFile - } else { - files = append(commonTemplateFiles, dcos2TemplateFiles...) - baseFile = dcos2BaseFile - } - case api.Swarm: - files = append(commonTemplateFiles, swarmTemplateFiles...) - baseFile = swarmBaseFile - case api.Kubernetes: - files = append(commonTemplateFiles, kubernetesTemplateFiles...) - baseFile = kubernetesBaseFile - case api.SwarmMode: - files = append(commonTemplateFiles, swarmModeTemplateFiles...) - baseFile = swarmBaseFile - case api.OpenShift: - files = append(commonTemplateFiles, openshiftTemplateFiles...) - baseFile = kubernetesBaseFile - default: - return nil, "", t.Translator.Errorf("orchestrator '%s' is unsupported", properties.OrchestratorProfile.OrchestratorType) - } - - return files, baseFile, nil + var files = append(commonTemplateFiles, kubernetesTemplateFiles...) + return files, kubernetesBaseFile, nil } func (t *TemplateGenerator) getMasterCustomData(cs *api.ContainerService, textFilename string, profile *api.Properties) string { @@ -210,11 +180,6 @@ func (t *TemplateGenerator) getTemplateFuncMap(cs *api.ContainerService) templat "IsHostedMaster": func() bool { return cs.Properties.IsHostedMasterProfile() }, - "IsDCOS19": func() bool { - return cs.Properties.OrchestratorProfile.OrchestratorType == api.DCOS && - (cs.Properties.OrchestratorProfile.OrchestratorVersion == common.DCOSVersion1Dot9Dot0 || - cs.Properties.OrchestratorProfile.OrchestratorVersion == common.DCOSVersion1Dot9Dot8) - }, "IsKubernetesVersionGe": func(version string) bool { return cs.Properties.OrchestratorProfile.IsKubernetes() && common.IsKubernetesVersionGe(cs.Properties.OrchestratorProfile.OrchestratorVersion, version) }, @@ -300,23 +265,14 @@ func (t *TemplateGenerator) getTemplateFuncMap(cs *api.ContainerService) templat return strings.TrimSuffix(buf.String(), ", ") }, "HasPrivateRegistry": func() bool { - if cs.Properties.OrchestratorProfile.DcosConfig != nil { - return len(cs.Properties.OrchestratorProfile.DcosConfig.Registry) > 0 - } return false }, "RequiresFakeAgentOutput": func() bool { - return cs.Properties.OrchestratorProfile.IsKubernetes() || cs.Properties.OrchestratorProfile.IsOpenShift() - }, - "IsSwarmMode": func() bool { - return cs.Properties.OrchestratorProfile.IsSwarmMode() + return cs.Properties.OrchestratorProfile.IsKubernetes() }, "IsKubernetes": func() bool { return cs.Properties.OrchestratorProfile.IsKubernetes() }, - "IsOpenShift": func() bool { - return cs.Properties.OrchestratorProfile.IsOpenShift() - }, "IsPublic": func(ports []int) bool { return len(ports) > 0 }, @@ -418,7 +374,7 @@ func (t *TemplateGenerator) getTemplateFuncMap(cs *api.ContainerService) templat return getDataDisks(profile) }, "HasBootstrap": func() bool { - return cs.Properties.OrchestratorProfile.DcosConfig != nil && cs.Properties.OrchestratorProfile.DcosConfig.BootstrapProfile != nil + return false }, "HasBootstrapPublicIP": func() bool { return false @@ -438,128 +394,18 @@ func (t *TemplateGenerator) getTemplateFuncMap(cs *api.ContainerService) templat } return false }, - "GetDCOSBootstrapCustomData": func() string { - masterIPList := generateIPList(cs.Properties.MasterProfile.Count, cs.Properties.MasterProfile.FirstConsecutiveStaticIP) - for i, v := range masterIPList { - masterIPList[i] = " - " + v - } - - str := getSingleLineDCOSCustomData( - cs.Properties.OrchestratorProfile.OrchestratorType, - dcos2BootstrapCustomdata, 0, - map[string]string{ - "PROVISION_SOURCE_STR": getDCOSProvisionScript(dcosProvisionSource), - "PROVISION_STR": getDCOSProvisionScript(dcos2BootstrapProvision), - "MASTER_IP_LIST": strings.Join(masterIPList, "\n"), - "BOOTSTRAP_IP": cs.Properties.OrchestratorProfile.DcosConfig.BootstrapProfile.StaticIP, - "BOOTSTRAP_OAUTH_ENABLED": strconv.FormatBool(cs.Properties.OrchestratorProfile.DcosConfig.BootstrapProfile.OAuthEnabled)}) - - return fmt.Sprintf("\"customData\": \"[base64(concat('#cloud-config\\n\\n', '%s'))]\",", str) - }, - "GetDCOSMasterCustomData": func() string { - masterAttributeContents := getDCOSMasterCustomNodeLabels() - masterPreprovisionExtension := "" - if cs.Properties.MasterProfile.PreprovisionExtension != nil { - masterPreprovisionExtension += "\n" - masterPreprovisionExtension += makeMasterExtensionScriptCommands(cs) - } - var bootstrapIP string - if cs.Properties.OrchestratorProfile.DcosConfig != nil && cs.Properties.OrchestratorProfile.DcosConfig.BootstrapProfile != nil { - bootstrapIP = cs.Properties.OrchestratorProfile.DcosConfig.BootstrapProfile.StaticIP - } - - str := getSingleLineDCOSCustomData( - cs.Properties.OrchestratorProfile.OrchestratorType, - getDCOSCustomDataTemplate(cs.Properties.OrchestratorProfile.OrchestratorType, cs.Properties.OrchestratorProfile.OrchestratorVersion), - cs.Properties.MasterProfile.Count, - map[string]string{ - "PROVISION_SOURCE_STR": getDCOSProvisionScript(dcosProvisionSource), - "PROVISION_STR": getDCOSMasterProvisionScript(cs.Properties.OrchestratorProfile, bootstrapIP), - "ATTRIBUTES_STR": masterAttributeContents, - "PREPROVISION_EXTENSION": masterPreprovisionExtension, - "ROLENAME": "master"}) - - return fmt.Sprintf("\"customData\": \"[base64(concat('#cloud-config\\n\\n', '%s'))]\",", str) - }, - "GetDCOSAgentCustomData": func(profile *api.AgentPoolProfile) string { - attributeContents := getDCOSAgentCustomNodeLabels(profile) - agentPreprovisionExtension := "" - if profile.PreprovisionExtension != nil { - agentPreprovisionExtension += "\n" - agentPreprovisionExtension += makeAgentExtensionScriptCommands(cs, profile) - } - var agentRoleName, bootstrapIP string - if len(profile.Ports) > 0 { - agentRoleName = "slave_public" - } else { - agentRoleName = "slave" - } - if cs.Properties.OrchestratorProfile.DcosConfig != nil && cs.Properties.OrchestratorProfile.DcosConfig.BootstrapProfile != nil { - bootstrapIP = cs.Properties.OrchestratorProfile.DcosConfig.BootstrapProfile.StaticIP - } - - str := getSingleLineDCOSCustomData( - cs.Properties.OrchestratorProfile.OrchestratorType, - getDCOSCustomDataTemplate(cs.Properties.OrchestratorProfile.OrchestratorType, cs.Properties.OrchestratorProfile.OrchestratorVersion), - cs.Properties.MasterProfile.Count, - map[string]string{ - "PROVISION_SOURCE_STR": getDCOSProvisionScript(dcosProvisionSource), - "PROVISION_STR": getDCOSAgentProvisionScript(profile, cs.Properties.OrchestratorProfile, bootstrapIP), - "ATTRIBUTES_STR": attributeContents, - "PREPROVISION_EXTENSION": agentPreprovisionExtension, - "ROLENAME": agentRoleName}) - - return fmt.Sprintf("\"customData\": \"[base64(concat('#cloud-config\\n\\n', '%s'))]\",", str) - }, - "GetDCOSWindowsAgentCustomData": func(profile *api.AgentPoolProfile) string { - agentPreprovisionExtension := "" - if profile.PreprovisionExtension != nil { - agentPreprovisionExtension += "\n" - agentPreprovisionExtension += makeAgentExtensionScriptCommands(cs, profile) - } - b, err := Asset(dcosWindowsProvision) - if err != nil { - // this should never happen and this is a bug - panic(fmt.Sprintf("BUG: %s", err.Error())) - } - // translate the parameters - csStr := string(b) - csStr = strings.Replace(csStr, "PREPROVISION_EXTENSION", agentPreprovisionExtension, -1) - csStr = strings.Replace(csStr, "\r\n", "\n", -1) - str := getBase64CustomScriptFromStr(csStr) - return fmt.Sprintf("\"customData\": \"%s\"", str) - }, - "GetDCOSWindowsAgentCustomNodeAttributes": func(profile *api.AgentPoolProfile) string { - return getDCOSWindowsAgentCustomAttributes(profile) - }, - "GetDCOSWindowsAgentPreprovisionParameters": func(profile *api.AgentPoolProfile) string { - agentPreprovisionExtensionParameters := "" - if profile.PreprovisionExtension != nil { - agentPreprovisionExtensionParameters = getDCOSWindowsAgentPreprovisionParameters(cs, profile) - } - return agentPreprovisionExtensionParameters - }, "GetMasterAllowedSizes": func() string { - if cs.Properties.OrchestratorProfile.OrchestratorType == api.DCOS { - return helpers.GetDCOSMasterAllowedSizes() - } return helpers.GetMasterAgentAllowedSizes() }, "GetDefaultVNETCIDR": func() string { return DefaultVNETCIDR }, "GetAgentAllowedSizes": func() string { - if cs.Properties.OrchestratorProfile.IsKubernetes() || cs.Properties.OrchestratorProfile.IsOpenShift() { + if cs.Properties.OrchestratorProfile.IsKubernetes() { return helpers.GetKubernetesAgentAllowedSizes() } return helpers.GetMasterAgentAllowedSizes() }, - "getSwarmVersions": func() string { - return getSwarmVersions(api.SwarmVersion, api.SwarmDockerComposeVersion) - }, - "GetSwarmModeVersions": func() string { - return getSwarmVersions(api.DockerCEVersion, api.DockerCEDockerComposeVersion) - }, "GetSizeMap": func() string { return helpers.GetSizeMap() }, @@ -649,41 +495,9 @@ func (t *TemplateGenerator) getTemplateFuncMap(cs *api.ContainerService) templat } return str }, - "GetMasterSwarmCustomData": func() string { - files := []string{swarmProvision} - str := buildYamlFileWithWriteFiles(files) - if cs.Properties.MasterProfile.PreprovisionExtension != nil { - extensionStr := makeMasterExtensionScriptCommands(cs) - str += "'runcmd:\n" + extensionStr + "\n\n'" - } - str = escapeSingleLine(str) - return fmt.Sprintf("\"customData\": \"[base64(concat('%s'))]\",", str) - }, - "GetAgentSwarmCustomData": func(profile *api.AgentPoolProfile) string { - files := []string{swarmProvision} - str := buildYamlFileWithWriteFiles(files) - str = escapeSingleLine(str) - return fmt.Sprintf("\"customData\": \"[base64(concat('%s',variables('%sRunCmdFile'),variables('%sRunCmd')))]\",", str, profile.Name, profile.Name) - }, - "GetSwarmAgentPreprovisionExtensionCommands": func(profile *api.AgentPoolProfile) string { - str := "" - if profile.PreprovisionExtension != nil { - makeAgentExtensionScriptCommands(cs, profile) - } - str = escapeSingleLine(str) - return str - }, "GetLocation": func() string { return cs.Location }, - "GetWinAgentSwarmCustomData": func() string { - str := getBase64CustomScript(swarmWindowsProvision) - return fmt.Sprintf("\"customData\": \"%s\"", str) - }, - "GetWinAgentSwarmModeCustomData": func() string { - str := getBase64CustomScript(swarmModeWindowsProvision) - return fmt.Sprintf("\"customData\": \"%s\"", str) - }, "GetKubernetesWindowsAgentFunctions": func() string { // Collect all the parts into a zip var parts = []string{ @@ -734,22 +548,6 @@ func (t *TemplateGenerator) getTemplateFuncMap(cs *api.ContainerService) templat return fmt.Sprintf("\"customData\": \"[base64(concat('%s'))]\",", str) }, - "GetMasterSwarmModeCustomData": func() string { - files := []string{swarmModeProvision} - str := buildYamlFileWithWriteFiles(files) - if cs.Properties.MasterProfile.PreprovisionExtension != nil { - extensionStr := makeMasterExtensionScriptCommands(cs) - str += "runcmd:\n" + extensionStr + "\n\n" - } - str = escapeSingleLine(str) - return fmt.Sprintf("\"customData\": \"[base64(concat('%s'))]\",", str) - }, - "GetAgentSwarmModeCustomData": func(profile *api.AgentPoolProfile) string { - files := []string{swarmModeProvision} - str := buildYamlFileWithWriteFiles(files) - str = escapeSingleLine(str) - return fmt.Sprintf("\"customData\": \"[base64(concat('%s',variables('%sRunCmdFile'),variables('%sRunCmd')))]\",", str, profile.Name, profile.Name) - }, "GetKubernetesSubnets": func() string { return getKubernetesSubnets(cs.Properties) }, @@ -912,52 +710,6 @@ func (t *TemplateGenerator) getTemplateFuncMap(cs *api.ContainerService) templat "EnablePodSecurityPolicy": func() bool { return helpers.IsTrueBoolPointer(cs.Properties.OrchestratorProfile.KubernetesConfig.EnablePodSecurityPolicy) }, - "OpenShiftGetMasterSh": func() (string, error) { - masterShAsset := getOpenshiftMasterShAsset(cs.Properties.OrchestratorProfile.OrchestratorVersion) - tb := MustAsset(masterShAsset) - t, err := template.New("master").Funcs(template.FuncMap{ - "quote": strconv.Quote, - "shellQuote": helpers.ShellQuote, - }).Parse(string(tb)) - if err != nil { - return "", err - } - b := &bytes.Buffer{} - err = t.Execute(b, struct { - ConfigBundle string - ExternalMasterHostname string - RouterLBHostname string - Location string - MasterIP string - }{ - ConfigBundle: base64.StdEncoding.EncodeToString(cs.Properties.OrchestratorProfile.OpenShiftConfig.ConfigBundles["master"]), - ExternalMasterHostname: fmt.Sprintf("%s.%s.cloudapp.azure.com", cs.Properties.MasterProfile.DNSPrefix, cs.Properties.AzProfile.Location), - RouterLBHostname: fmt.Sprintf("%s-router.%s.cloudapp.azure.com", cs.Properties.MasterProfile.DNSPrefix, cs.Properties.AzProfile.Location), - Location: cs.Properties.AzProfile.Location, - MasterIP: cs.Properties.MasterProfile.FirstConsecutiveStaticIP, - }) - return b.String(), err - }, - "OpenShiftGetNodeSh": func(profile *api.AgentPoolProfile) (string, error) { - nodeShAsset := getOpenshiftNodeShAsset(cs.Properties.OrchestratorProfile.OrchestratorVersion) - tb := MustAsset(nodeShAsset) - t, err := template.New("node").Funcs(template.FuncMap{ - "quote": strconv.Quote, - "shellQuote": helpers.ShellQuote, - }).Parse(string(tb)) - if err != nil { - return "", err - } - b := &bytes.Buffer{} - err = t.Execute(b, struct { - ConfigBundle string - Role api.AgentPoolProfileRole - }{ - ConfigBundle: base64.StdEncoding.EncodeToString(cs.Properties.OrchestratorProfile.OpenShiftConfig.ConfigBundles["bootstrap"]), - Role: profile.Role, - }) - return b.String(), err - }, // inspired by http://stackoverflow.com/questions/18276173/calling-a-template-with-several-pipeline-parameters/18276968#18276968 "dict": func(values ...interface{}) (map[string]interface{}, error) { if len(values)%2 != 0 { diff --git a/pkg/acsengine/tenantid.go b/pkg/engine/tenantid.go similarity index 99% rename from pkg/acsengine/tenantid.go rename to pkg/engine/tenantid.go index 37a01d98ef..38f56873eb 100644 --- a/pkg/acsengine/tenantid.go +++ b/pkg/engine/tenantid.go @@ -1,4 +1,4 @@ -package acsengine +package engine import ( "context" diff --git a/pkg/acsengine/tenantid_test.go b/pkg/engine/tenantid_test.go similarity index 99% rename from pkg/acsengine/tenantid_test.go rename to pkg/engine/tenantid_test.go index bbc29c1bbe..f4a29bee52 100644 --- a/pkg/acsengine/tenantid_test.go +++ b/pkg/engine/tenantid_test.go @@ -1,4 +1,4 @@ -package acsengine +package engine import ( "net/http" diff --git a/pkg/acsengine/testdata/addons/kubernetes-custom-psp.json b/pkg/engine/testdata/addons/kubernetes-custom-psp.json similarity index 100% rename from pkg/acsengine/testdata/addons/kubernetes-custom-psp.json rename to pkg/engine/testdata/addons/kubernetes-custom-psp.json diff --git a/pkg/acsengine/testdata/addons/kubernetes-kube-proxy.json b/pkg/engine/testdata/addons/kubernetes-kube-proxy.json similarity index 100% rename from pkg/acsengine/testdata/addons/kubernetes-kube-proxy.json rename to pkg/engine/testdata/addons/kubernetes-kube-proxy.json diff --git a/pkg/acsengine/testdata/addons/kubernetes.json b/pkg/engine/testdata/addons/kubernetes.json similarity index 100% rename from pkg/acsengine/testdata/addons/kubernetes.json rename to pkg/engine/testdata/addons/kubernetes.json diff --git a/pkg/acsengine/testdata/agentPoolOnly/v20170831/agents.json b/pkg/engine/testdata/agentPoolOnly/v20170831/agents.json similarity index 100% rename from pkg/acsengine/testdata/agentPoolOnly/v20170831/agents.json rename to pkg/engine/testdata/agentPoolOnly/v20170831/agents.json diff --git a/pkg/acsengine/testdata/agentPoolOnly/v20180331/agents.json b/pkg/engine/testdata/agentPoolOnly/v20180331/agents.json similarity index 100% rename from pkg/acsengine/testdata/agentPoolOnly/v20180331/agents.json rename to pkg/engine/testdata/agentPoolOnly/v20180331/agents.json diff --git a/pkg/acsengine/testdata/agentPoolOnly/v20180331/agentsWithFullNetworkProfile.json b/pkg/engine/testdata/agentPoolOnly/v20180331/agentsWithFullNetworkProfile.json similarity index 100% rename from pkg/acsengine/testdata/agentPoolOnly/v20180331/agentsWithFullNetworkProfile.json rename to pkg/engine/testdata/agentPoolOnly/v20180331/agentsWithFullNetworkProfile.json diff --git a/pkg/acsengine/testdata/agentPoolOnly/v20180331/agentsWithFullNetworkProfileV2.json b/pkg/engine/testdata/agentPoolOnly/v20180331/agentsWithFullNetworkProfileV2.json similarity index 100% rename from pkg/acsengine/testdata/agentPoolOnly/v20180331/agentsWithFullNetworkProfileV2.json rename to pkg/engine/testdata/agentPoolOnly/v20180331/agentsWithFullNetworkProfileV2.json diff --git a/pkg/acsengine/testdata/agentPoolOnly/v20180331/agentsWithOnlyNetworkPlugin.json b/pkg/engine/testdata/agentPoolOnly/v20180331/agentsWithOnlyNetworkPlugin.json similarity index 100% rename from pkg/acsengine/testdata/agentPoolOnly/v20180331/agentsWithOnlyNetworkPlugin.json rename to pkg/engine/testdata/agentPoolOnly/v20180331/agentsWithOnlyNetworkPlugin.json diff --git a/pkg/acsengine/testdata/disks-managed/kubernetes-vmas.json b/pkg/engine/testdata/disks-managed/kubernetes-vmas.json similarity index 100% rename from pkg/acsengine/testdata/disks-managed/kubernetes-vmas.json rename to pkg/engine/testdata/disks-managed/kubernetes-vmas.json diff --git a/pkg/acsengine/testdata/disks-managed/kubernetes-vmss.json b/pkg/engine/testdata/disks-managed/kubernetes-vmss.json similarity index 100% rename from pkg/acsengine/testdata/disks-managed/kubernetes-vmss.json rename to pkg/engine/testdata/disks-managed/kubernetes-vmss.json diff --git a/pkg/acsengine/testdata/disks-storageaccount/kubernetes.json b/pkg/engine/testdata/disks-storageaccount/kubernetes.json similarity index 100% rename from pkg/acsengine/testdata/disks-storageaccount/kubernetes.json rename to pkg/engine/testdata/disks-storageaccount/kubernetes.json diff --git a/pkg/acsengine/testdata/etcd-versions/kubernetes.json b/pkg/engine/testdata/etcd-versions/kubernetes.json similarity index 100% rename from pkg/acsengine/testdata/etcd-versions/kubernetes.json rename to pkg/engine/testdata/etcd-versions/kubernetes.json diff --git a/pkg/acsengine/testdata/extensions/kubernetes.json b/pkg/engine/testdata/extensions/kubernetes.json similarity index 97% rename from pkg/acsengine/testdata/extensions/kubernetes.json rename to pkg/engine/testdata/extensions/kubernetes.json index 4a1dfe06c3..58d4c37b4c 100644 --- a/pkg/acsengine/testdata/extensions/kubernetes.json +++ b/pkg/engine/testdata/extensions/kubernetes.json @@ -49,7 +49,7 @@ { "name": "hello-world-k8s", "version": "v1", - "rootURL": "https://raw.githubusercontent.com/Azure/acs-engine/master/" + "rootURL": "https://raw.githubusercontent.com/Azure/aks-engine/master/" } ], "servicePrincipalProfile": { diff --git a/pkg/acsengine/testdata/key-vault-certs/kubernetes.json b/pkg/engine/testdata/key-vault-certs/kubernetes.json similarity index 100% rename from pkg/acsengine/testdata/key-vault-certs/kubernetes.json rename to pkg/engine/testdata/key-vault-certs/kubernetes.json diff --git a/pkg/acsengine/testdata/key-vault-params/kubernetes.json b/pkg/engine/testdata/key-vault-params/kubernetes.json similarity index 100% rename from pkg/acsengine/testdata/key-vault-params/kubernetes.json rename to pkg/engine/testdata/key-vault-params/kubernetes.json diff --git a/pkg/acsengine/testdata/kubernetesversions/kubernetes1.7.9.json b/pkg/engine/testdata/kubernetesversions/kubernetes1.7.9.json similarity index 100% rename from pkg/acsengine/testdata/kubernetesversions/kubernetes1.7.9.json rename to pkg/engine/testdata/kubernetesversions/kubernetes1.7.9.json diff --git a/pkg/acsengine/testdata/kubernetesversions/kubernetes1.8.2.json b/pkg/engine/testdata/kubernetesversions/kubernetes1.8.2.json similarity index 100% rename from pkg/acsengine/testdata/kubernetesversions/kubernetes1.8.2.json rename to pkg/engine/testdata/kubernetesversions/kubernetes1.8.2.json diff --git a/pkg/acsengine/testdata/largeclusters/kubernetes-vmss.json b/pkg/engine/testdata/largeclusters/kubernetes-vmss.json similarity index 100% rename from pkg/acsengine/testdata/largeclusters/kubernetes-vmss.json rename to pkg/engine/testdata/largeclusters/kubernetes-vmss.json diff --git a/pkg/acsengine/testdata/largeclusters/kubernetes.json b/pkg/engine/testdata/largeclusters/kubernetes.json similarity index 100% rename from pkg/acsengine/testdata/largeclusters/kubernetes.json rename to pkg/engine/testdata/largeclusters/kubernetes.json diff --git a/pkg/acsengine/testdata/location/kubernetes.json b/pkg/engine/testdata/location/kubernetes.json similarity index 100% rename from pkg/acsengine/testdata/location/kubernetes.json rename to pkg/engine/testdata/location/kubernetes.json diff --git a/pkg/acsengine/testdata/rename.sh b/pkg/engine/testdata/rename.sh similarity index 100% rename from pkg/acsengine/testdata/rename.sh rename to pkg/engine/testdata/rename.sh diff --git a/pkg/acsengine/testdata/simple/kubernetes.json b/pkg/engine/testdata/simple/kubernetes.json similarity index 100% rename from pkg/acsengine/testdata/simple/kubernetes.json rename to pkg/engine/testdata/simple/kubernetes.json diff --git a/pkg/acsengine/testdata/v20160930/kubernetes.json b/pkg/engine/testdata/v20160930/kubernetes.json similarity index 100% rename from pkg/acsengine/testdata/v20160930/kubernetes.json rename to pkg/engine/testdata/v20160930/kubernetes.json diff --git a/pkg/acsengine/testdata/v20170131/kubernetes-win.json b/pkg/engine/testdata/v20170131/kubernetes-win.json similarity index 100% rename from pkg/acsengine/testdata/v20170131/kubernetes-win.json rename to pkg/engine/testdata/v20170131/kubernetes-win.json diff --git a/pkg/acsengine/testdata/v20170131/kubernetes.json b/pkg/engine/testdata/v20170131/kubernetes.json similarity index 100% rename from pkg/acsengine/testdata/v20170131/kubernetes.json rename to pkg/engine/testdata/v20170131/kubernetes.json diff --git a/pkg/acsengine/testdata/v20170701/kubernetes-default-version.json b/pkg/engine/testdata/v20170701/kubernetes-default-version.json similarity index 100% rename from pkg/acsengine/testdata/v20170701/kubernetes-default-version.json rename to pkg/engine/testdata/v20170701/kubernetes-default-version.json diff --git a/pkg/acsengine/testdata/v20170701/kubernetes-keyvault-secret.json b/pkg/engine/testdata/v20170701/kubernetes-keyvault-secret.json similarity index 100% rename from pkg/acsengine/testdata/v20170701/kubernetes-keyvault-secret.json rename to pkg/engine/testdata/v20170701/kubernetes-keyvault-secret.json diff --git a/pkg/acsengine/testdata/v20170701/kubernetes-win-default-version.json b/pkg/engine/testdata/v20170701/kubernetes-win-default-version.json similarity index 100% rename from pkg/acsengine/testdata/v20170701/kubernetes-win-default-version.json rename to pkg/engine/testdata/v20170701/kubernetes-win-default-version.json diff --git a/pkg/acsengine/testdata/v20170701/kubernetes.json b/pkg/engine/testdata/v20170701/kubernetes.json similarity index 100% rename from pkg/acsengine/testdata/v20170701/kubernetes.json rename to pkg/engine/testdata/v20170701/kubernetes.json diff --git a/pkg/acsengine/testdata/vnet/kubernetesvnet.json b/pkg/engine/testdata/vnet/kubernetesvnet.json similarity index 100% rename from pkg/acsengine/testdata/vnet/kubernetesvnet.json rename to pkg/engine/testdata/vnet/kubernetesvnet.json diff --git a/pkg/acsengine/testdata/windows/kubernetes-hybrid.json b/pkg/engine/testdata/windows/kubernetes-hybrid.json similarity index 100% rename from pkg/acsengine/testdata/windows/kubernetes-hybrid.json rename to pkg/engine/testdata/windows/kubernetes-hybrid.json diff --git a/pkg/acsengine/testdata/windows/kubernetes-kubernetesconfig.json b/pkg/engine/testdata/windows/kubernetes-kubernetesconfig.json similarity index 100% rename from pkg/acsengine/testdata/windows/kubernetes-kubernetesconfig.json rename to pkg/engine/testdata/windows/kubernetes-kubernetesconfig.json diff --git a/pkg/acsengine/testdata/windows/kubernetes-vmss.json b/pkg/engine/testdata/windows/kubernetes-vmss.json similarity index 100% rename from pkg/acsengine/testdata/windows/kubernetes-vmss.json rename to pkg/engine/testdata/windows/kubernetes-vmss.json diff --git a/pkg/acsengine/testdata/windows/kubernetes.json b/pkg/engine/testdata/windows/kubernetes.json similarity index 100% rename from pkg/acsengine/testdata/windows/kubernetes.json rename to pkg/engine/testdata/windows/kubernetes.json diff --git a/pkg/acsengine/transform/apimodel_merger.go b/pkg/engine/transform/apimodel_merger.go similarity index 100% rename from pkg/acsengine/transform/apimodel_merger.go rename to pkg/engine/transform/apimodel_merger.go diff --git a/pkg/acsengine/transform/apimodel_merger_test.go b/pkg/engine/transform/apimodel_merger_test.go similarity index 100% rename from pkg/acsengine/transform/apimodel_merger_test.go rename to pkg/engine/transform/apimodel_merger_test.go diff --git a/pkg/acsengine/transform/json.go b/pkg/engine/transform/json.go similarity index 98% rename from pkg/acsengine/transform/json.go rename to pkg/engine/transform/json.go index 30f639ddbd..d775441527 100644 --- a/pkg/acsengine/transform/json.go +++ b/pkg/engine/transform/json.go @@ -5,7 +5,7 @@ import ( "encoding/json" "strings" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/helpers" ) // PrettyPrintArmTemplate will pretty print the arm template ensuring ordered by params, vars, resources, and outputs diff --git a/pkg/acsengine/transform/transform.go b/pkg/engine/transform/transform.go similarity index 90% rename from pkg/acsengine/transform/transform.go rename to pkg/engine/transform/transform.go index 1244d114a3..71532d8b92 100644 --- a/pkg/acsengine/transform/transform.go +++ b/pkg/engine/transform/transform.go @@ -3,7 +3,6 @@ package transform import ( "fmt" "log" - "runtime" "sort" "strings" @@ -29,7 +28,6 @@ const ( createOptionFieldName = "createOption" tagsFieldName = "tags" managedDiskFieldName = "managedDisk" - outputsFieldName = "outputs" // ARM resource Types nsgResourceType = "Microsoft.Network/networkSecurityGroups" @@ -101,55 +99,6 @@ func (t *Transformer) NormalizeForVMSSScaling(logger *logrus.Entry, templateMap return nil } -// NormalizeForOpenShiftVMASScalingUp takes a template and removes elements that -// are unwanted in a OpenShift VMAS scale up/down case -func (t *Transformer) NormalizeForOpenShiftVMASScalingUp(logger *logrus.Entry, agentPoolName string, templateMap map[string]interface{}) (err error) { - defer func() { - // catch a failed type assertion and return it as an error. This saves - // needing to write `if foo, ok := bar.(*Baz); ok` everywhere below. - if r := recover(); r != nil { - e, ok := r.(*runtime.TypeAssertionError) - if ok { - err = e - } else { - panic(r) - } - } - }() - - isNeeded := func(name interface{}) bool { - return strings.Contains(name.(string), agentPoolName+"VMNamePrefix") - } - - // only include resources including VMNamePrefix in their - // name (VM, VM extension, NIC). - resources := []interface{}{} - for _, res := range templateMap[resourcesFieldName].([]interface{}) { - res := res.(map[string]interface{}) - - if !isNeeded(res[nameFieldName]) { - continue - } - - // remove dependencies to removed resources - depends := []interface{}{} - for _, depend := range res[dependsOnFieldName].([]interface{}) { - if isNeeded(depend) { - depends = append(depends, depend) - } - } - res[dependsOnFieldName] = depends - - resources = append(resources, res) - } - templateMap[resourcesFieldName] = resources - - // remove all outputs: they may depend on deleted resources - templateMap[outputsFieldName] = map[string]interface{}{} - - return -} - // NormalizeForK8sVMASScalingUp takes a template and removes elements that are unwanted in a K8s VMAS scale up/down case func (t *Transformer) NormalizeForK8sVMASScalingUp(logger *logrus.Entry, templateMap map[string]interface{}) error { if err := t.NormalizeMasterResourcesForScaling(logger, templateMap); err != nil { diff --git a/pkg/acsengine/transform/transform_test.go b/pkg/engine/transform/transform_test.go similarity index 64% rename from pkg/acsengine/transform/transform_test.go rename to pkg/engine/transform/transform_test.go index 9ed9677528..2ccd15ed5f 100644 --- a/pkg/acsengine/transform/transform_test.go +++ b/pkg/engine/transform/transform_test.go @@ -6,30 +6,12 @@ import ( "io/ioutil" "testing" - "github.com/Azure/acs-engine/pkg/helpers" - "github.com/Azure/acs-engine/pkg/i18n" - . "github.com/onsi/ginkgo" + "github.com/Azure/aks-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/i18n" . "github.com/onsi/gomega" "github.com/sirupsen/logrus" ) -func TestNormalizeForVMSSScaling(t *testing.T) { - RegisterTestingT(t) - logger := logrus.New().WithField("testName", "TestNormalizeForVMSSScaling") - fileContents, e := ioutil.ReadFile("./transformtestfiles/dcos_template.json") - Expect(e).To(BeNil()) - expectedFileContents, e := ioutil.ReadFile("./transformtestfiles/dcos_scale_template.json") - Expect(e).To(BeNil()) - templateJSON := string(fileContents) - var template interface{} - json.Unmarshal([]byte(templateJSON), &template) - templateMap := template.(map[string]interface{}) - transformer := Transformer{} - e = transformer.NormalizeForVMSSScaling(logger, templateMap) - Expect(e).To(BeNil()) - ValidateTemplate(templateMap, expectedFileContents, "TestNormalizeForVMSSScaling") -} - func TestNormalizeForK8sVMASScalingUp(t *testing.T) { RegisterTestingT(t) logger := logrus.New().WithField("testName", "TestNormalizeForK8sVMASScalingUp") @@ -64,69 +46,6 @@ func TestNormalizeForK8sVMASScalingUpWithVnet(t *testing.T) { ValidateTemplate(templateMap, expectedFileContents, "TestNormalizeForK8sVMASScalingUpWithVnet") } -func TestNormalizeForOpenShiftVMASScalingUp(t *testing.T) { - RegisterTestingT(t) - - tests := []struct { - agentPoolName string - templateMap map[string]interface{} - expectedTemplateMap map[string]interface{} - expectedErr bool - }{ - { - // a badly constructed input should result in an error, not a panic - expectedErr: true, - }, - { - agentPoolName: "compute", - templateMap: map[string]interface{}{ - "resources": []interface{}{ - map[string]interface{}{ - "name": "foo", - }, - map[string]interface{}{ - "name": "barVMNamePrefix", - "dependsOn": []interface{}{ - "foo", - }, - }, - map[string]interface{}{ - "name": "computeVMNamePrefix", - "dependsOn": []interface{}{ - "foo", - "barVMNamePrefix", - "computeVMNamePrefix", - }, - }, - }, - "outputs": map[string]interface{}{ - "junk": "junk", - }, - }, - expectedTemplateMap: map[string]interface{}{ - "resources": []interface{}{ - map[string]interface{}{ - "name": "computeVMNamePrefix", - "dependsOn": []interface{}{ - "computeVMNamePrefix", - }, - }, - }, - "outputs": map[string]interface{}{}, - }, - }, - } - - transformer := &Transformer{} - - for i, test := range tests { - fmt.Fprintf(GinkgoWriter, "test %d\n", i) - err := transformer.NormalizeForOpenShiftVMASScalingUp(nil, test.agentPoolName, test.templateMap) - Expect(err != nil).To(Equal(test.expectedErr)) - Expect(test.templateMap).To(BeEquivalentTo(test.expectedTemplateMap)) - } -} - func TestNormalizeResourcesForK8sMasterUpgrade(t *testing.T) { RegisterTestingT(t) logger := logrus.New().WithField("testName", "TestNormalizeResourcesForK8sMasterUpgrade") diff --git a/pkg/acsengine/transform/transformtestfiles/k8s_agent_upgrade_template.json b/pkg/engine/transform/transformtestfiles/k8s_agent_upgrade_template.json similarity index 99% rename from pkg/acsengine/transform/transformtestfiles/k8s_agent_upgrade_template.json rename to pkg/engine/transform/transformtestfiles/k8s_agent_upgrade_template.json index e8a1997fcb..361abccdd0 100644 --- a/pkg/acsengine/transform/transformtestfiles/k8s_agent_upgrade_template.json +++ b/pkg/engine/transform/transformtestfiles/k8s_agent_upgrade_template.json @@ -807,7 +807,7 @@ "type": "string" }, "generatorCode": { - "defaultValue": "acsengine", + "defaultValue": "aksengine", "metadata": { "description": "The generator code used to identify the generator" }, @@ -1998,7 +1998,7 @@ } }, "tags": { - "creationSource": "[concat('acsengine-', variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]", + "creationSource": "[concat('aksengine-', variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]", "orchestrator": "[variables('orchestratorNameVersionTag')]", "resourceNameSuffix": "[parameters('nameSuffix')]" }, diff --git a/pkg/acsengine/transform/transformtestfiles/k8s_master_upgrade_template.json b/pkg/engine/transform/transformtestfiles/k8s_master_upgrade_template.json similarity index 99% rename from pkg/acsengine/transform/transformtestfiles/k8s_master_upgrade_template.json rename to pkg/engine/transform/transformtestfiles/k8s_master_upgrade_template.json index fc806cfcb0..540249216c 100644 --- a/pkg/acsengine/transform/transformtestfiles/k8s_master_upgrade_template.json +++ b/pkg/engine/transform/transformtestfiles/k8s_master_upgrade_template.json @@ -786,7 +786,7 @@ "type": "string" }, "generatorCode": { - "defaultValue": "acsengine", + "defaultValue": "aksengine", "metadata": { "description": "The generator code used to identify the generator" }, @@ -1817,7 +1817,7 @@ } }, "tags": { - "creationSource": "[concat('acsengine-', variables('agentpool2VMNamePrefix'), copyIndex(variables('agentpool2Offset')))]", + "creationSource": "[concat('aksengine-', variables('agentpool2VMNamePrefix'), copyIndex(variables('agentpool2Offset')))]", "orchestrator": "[variables('orchestratorNameVersionTag')]", "poolName": "agentpool2", "resourceNameSuffix": "[parameters('nameSuffix')]" @@ -2156,7 +2156,7 @@ "osProfile": { "adminUsername": "[parameters('linuxAdminUsername')]", "computername": "[concat(variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]", - "customData": "[base64(concat('#cloud-config\n\npackages:\n - etcd\n - jq\n - traceroute\n\nwrite_files:\n- path: \"/etc/systemd/system/docker.service.d/clear_mount_propagation_flags.conf\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n [Service]\n MountFlags=shared\n\n- path: \"/etc/systemd/system/docker.service.d/exec_start.conf\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n [Service]\n ExecStart=\n ExecStart=/usr/bin/docker daemon -H fd:// --storage-driver=overlay --bip=',parameters('dockerBridgeCidr'),'\n\n- path: \"/etc/docker/daemon.json\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n {\n \"live-restore\": true,\n \"log-driver\": \"json-file\",\n \"log-opts\": {\n \"max-size\": \"50m\",\n \"max-file\": \"5\"\n }\n }\n\n- path: \"/etc/kubernetes/certs/ca.crt\"\n permissions: \"0644\"\n encoding: \"base64\"\n owner: \"root\"\n content: |\n ',parameters('caCertificate'),'\n\n- path: \"/etc/kubernetes/certs/apiserver.crt\"\n permissions: \"0644\"\n encoding: \"base64\"\n owner: \"root\"\n content: |\n ',parameters('apiServerCertificate'),'\n\n- path: \"/etc/kubernetes/certs/client.crt\"\n permissions: \"0644\"\n encoding: \"base64\"\n owner: \"root\"\n content: |\n ',parameters('clientCertificate'),'\n\n- path: \"/var/lib/kubelet/kubeconfig\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n apiVersion: v1\n kind: Config\n clusters:\n - name: localcluster\n cluster:\n certificate-authority: /etc/kubernetes/certs/ca.crt\n server: ',concat('https://', variables('masterPrivateIpAddrs')[copyIndex(variables('masterOffset'))], ':443'),'\n users:\n - name: client\n user:\n client-certificate: /etc/kubernetes/certs/client.crt\n client-key: /etc/kubernetes/certs/client.key\n contexts:\n - context:\n cluster: localcluster\n user: client\n name: localclustercontext\n current-context: localclustercontext\n\n- path: /etc/kubernetes/manifests/kube-apiserver.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/6RUy27jOgzd5ysMr6O67S1wC6MuUPQWuAXaTqYBZs9IjKOJXkPRLjJfP5DzttMHMMlKOjxH5CFNCPoHUtTelVneXuSjpXaqzPKJV/nIIoMChnKUZQ4sllm+bGYoIOiI1CLlGyAGkDs0riKjTZCBGZqY2FnGGqnMpHdM3ohgwGF3L70N3qHjMjvWHsWAMnEXPvIL8punZZkxNYmXdEA7pI26eD+/9NMW6oTeJJgcMsb/VwEpHacB5e02UHprIRmwOSflvFhsY/PD68Er3a0QoKyOyVGxqbZ62Vr0pOcoV9Lg+Elbza/gaqTxFKnVEu+k9I3j8X84h8bwlD1BjfcGYhy/YvQNSfzeeIbBe4owxur8rPv3UWP8mwikW22wRtWDtYsoG0IRPHF1fX7d5x/CV1f/9FBpfKNEIN9qhVTB74bwZIj0bq7rqkCWxb4JRUc4+xm9GzzbeSKkaSIjCR0EJbeqroUbx+61otseEVkqse5LrBbMoSyKi8t/O28uyhsLSe6Bpbo3Gh1PPPFJiV+Np8YKQlBVGrqB6S0S64g7+w9m627yOO0yeJz0tdlEIZFYzLXBgR0JicVusM4k8Ql+aiYwiiWuviazxNWgKal4IeEjAQknEtg2BtbT+jdJxPWEixnIJTpVJd8vezFtdXV0c+Dyg4OZwdcZ7D/f1pvG4nNKbLMYjpYDshR7/l43y2yiTIAXZZb3CsmHOi2QMHrWaRnkd4VaoMLoWTGI2ynZqD9lvwHU6Lh4Bgc1qkeFjjWvxBSZtauP6kjj+s2Z1W5Rrh3pb8nTRqRF2z2+EwwfOPKZG++rnbRlK2ej/rLA5878CQAA//8KCj673wYAAA==\n\n- path: /etc/kubernetes/manifests/kube-controller-manager.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/6SUTW/bPAyA7/kVhu+q8b5Ho+6l6PtxSBe0w+6MxLpaJNGjaHfZrx/oJE3jxMuA+Wbq4UOJ+oDOf0HOnlJdlMNf5WLjk6uLckWuXEQUcCBQL4oiQcS6KDf9Go2lJEwhIJsICVrkck/kDuw7lrdZMOpQgDWGrJqiEI9cF3uF6QIkHOOWYkcJk9TFTJFF7tCq5JWyPKK8EW/qQrhXgeLgE/K+jPmNGevnI7SK3SrHCQXzf9sOWX+fO7R3B9BSjKC92f9ribJ6PbDlx/B8uXHYGM2wlF5821QDcBX8utJYQKmOY5MkCIEsCJpEDo31jnNzewg+ksN7Dd1NsmzosyCPfDOu8n4XUXoO1t41txH0559vLq0YX/z3c5p6ZzqmwTvkBn70jBeRw1JRbHXsczUm3HzNlCZZTCTGgnnxAc+yLLLkysKNZZmZfvZt8qk1iv6xZIPbK44NbieOjDx4iwaspT6J6dgPunNXXNB5zUS+oAwIDtlgQCuNHvqT8Q/H9yHBOuDTGux0v4bm70lkPEmRkhdi0zJYNB2yJ9d8EN4Lh2XLesKWO/RfJVcjOK3RkTM4eCuekhEfkXq5IFuRe9hTn3fQVMTUCxrWq2B98DAKZyf3pPTTCTyZ30Chj7jU7cgnl3j/TqBYc9QeJ1MUUXNWIK91UU72rTz3DMAm+LXZX+dZ0eTan5ti9tdy3wBaTFItx0fG/e8wiZeteUYRn9qTVTCC+5TC9v3F3DVk+lxeboO+uGPxd2H3i35c68W87WJTzhtyXXC9Mz8DAAD//8PhLmf6BgAA\n\n- path: /etc/kubernetes/manifests/kube-scheduler.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/4SSQY/bIBCF7/kViDtC7RE1PbeHbVdaqfcxTG0UGBCMvfK/r0ideOMka988b97HzNNA9n+wVJ/ICDl9kYeTJ2eEfE1OHiIyOGAwByEIIhohT2OHqtoB3RiwyEWoGeyqzpUxNilAh6E2txDssRhhE3FJQeUAhOe6TTEnQmIjbtmHmtE275Aq/0J+T+VkBJex+RoHPGFZ6Or5fO3zEfqmfmtyIWSsP+aMpf2+ZbTfL402xQjkzPLbwFIPl1b5sXz3yLmqVGu0if76/qgnKDr4TrdaQNartjEFBIdFYUDLx7bjRp+OXy+VKYUx4ksaievHOZcAkK1at1wxQsRmeQUejJAa2epHbVfOBEUF36ll9KegzYr3pFj9nvcdoEdi/QIEPbqfDok9z+oNmT31N1sUBPebwnw9hf95bO/gcQztlM6PX4H5kzz2snhOexjKfSD7gP1k/gUAAP//FKERJ8EDAAA=\n\n- path: /etc/kubernetes/manifests/kube-addon-manager.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/4yRsW7zMAyEdz8Fkd3w/w9ZhKJAxw5pAwTozkiEIySiXJFy4LcvZMdOWjRtR5LH43cSdv6NkvjIBvr/1dGzM7CNrgqk6FDRVACMgQwc855qdC5yHZCxpXQZSYd2nssgSqEC6G9cpSNbfA5R9IX0HNPRgKZMFYCNrOiZkhRF/dMtAB+wJQMPZZyYlOSpaDaTZNeRfRx1iSTmZGn0nBrvmUSXGsB22cA6LHWgENNgYP1v48dmH0850CZmntdmuJFLLpuhCLaoBwOrhtQ2V7ZmEq4WBnSvfBqW6FfHIP47ux5Tc/L75ozYEmsz5XTPjli9DvWOVD239y9MGT697A18+Y7x1GW9+y3FV9x7Bn/n/ggAAP//ovMbJ38CAAA=\n\n- path: /etc/kubernetes/addons/kube-dns-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8xXS2/jNhC+61cQ7pl+JMhuINQLBOugG2yTGnXa+4QcW0QokuHDjffXF5RkWS+7dg7FyidzOA9+38xHCYz4G60TWqVkO0teheIpWaHdCoZ3jOmgfJKjBw4e0oQQBTmm5DW8IOXKVQvOANuvup3zmCeESHhB6aIPKSxWoUc3FnrCZHAeLXVlmpSMvA04KnYC51rloGCDdtx2yzXHlPyJTCsmJCaU0uRU+a26W9XcOgrGtI5xSY3tnSUi38MLLp5WFyDkDLJYT5XpYZmS2XQcf7NpQojR1hf10irivs5oSMnNdfnHaq+Zlin5a7Fsb6aemVMOz1+jg0OJzGt7DJkuyGCMm2xnL+hhD/cCjdS7HDud8jH+h7nZ1hxfTXsQ08PiCZgtGikYuJRc9Y6dg2fZ7416j9XRq8RjbiR4rOI0jl80s1Lagxda1XEJcSxDHiTaMUiTQafJmRVeMJDUaJ6S0ahyk63ijpd3CdQDxyFkD1dR/notlPC7Q1qj+Z3y4q5niI2Fa7QW+SJYoTar8pRCbR42StfL9+/IQgSk6UrJPyg2mY8DMG2sl/mqXM9o87RlrFBZtahsPgWt9+/GonNtDg6ZX3GX7tHsmQnRBi3E4ORBDZi3IAMOxC0id5kpH6+Nlnqz+14kbpGVaedjFyf7nTImb1Ze1fu1apK7KJbuDyV3Sb/g+3fhfN22WoYcG3E6I8S0WotNHaX8+wimebSesB1yxiJBpiQ2V1KH8CAU2kZSsJsGWJSMKOU6B6HmVZ+OpWYgx6POHuVoFLH5bDq9ue4Yt/OrzkpZPOXCziedAx52ihw2mJJfDwxUCr4yyL7U26TYokLnlla/YBOMNQgZLD5nFl2mJU/JTcOaeW9+Q99uDAM+S8lokiFIn/2gMTVXbtTp+CjWt9Pb9iBE0Yjof3t+XjYMcTIEyAVK2K3ixchdSj41XV1gDJ1r1DlrWL3IUQdfux7OcCC7yXV9Ke3hrlleFnUXBPVaJuJfENuSi/bFdXFAz8yJoOXlVj4WgYtBEk/SVLsdIWj2YYKup2dRYNHpYFlbX6TIhe8oTo65truUzD5PH0XDYvEtoOvuZiYUuOaDMVohStV4jC+BLdZPiwchefRYFjh2J/CUFjBgGVInfmCc9GlnrJWmERG57azHqw3tfHb1uXx5+mVIJapNE6EocG7HYA1MznQxn87ZLvWGroEJKfxuTk8JzeJp9QjurS00dWPn4N7Onrfh2bh8zI7P2H9M1zCPOZ8rJ7V+DaZ5xXFcQ5B+7LZs3BJ8UkNLvkw4bicqSNnBN1g5r6Wzwqkr/B/PmxaUnpm9J9zFluKGisLdWX8LAv2pfojvRN/K0P/f5dNDkPx0l09V6tnD0Kn72GVwoajeXKCpw5LaiMCVW2op2C5+NRVNWRlc64v7aehNS2mO/Xfd+CHW+YTQLiVSqPCe/BsAAP//MQMKdd0PAAA=\n\n- path: /etc/kubernetes/addons/kube-proxy-daemonset.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/5RUzW7bPBC8+ykI3RkmVyH+gA9ugV7aBgjQ+5qa2ET4oy6Xrv32BaU6kpzETXkSZoezszsCqXc/wNml2CocBbF+ZnO420LobvXsYteqT4SQ4iNkFSDUkVC7UsrTFj7XL6WeyxYcIcg3LhnrSxawzuCDs2hVI1zQDEybQp8iorTDJd1zOp6Gijhwq2LqsFIqUsAFo0K5J3vG8ykLwir3sNWEIPSeBKOhudF65mav23hlRalzi/FiFHIR/CKmq1ig2E3qWjVmf+rBVbuZwcs2WjVaV4pN8cnt1uZAbLzbmop5iJlqzfLSecPWdby+r7TNiGxcx/9dkJ9AUhh6R4K8/nzswS4gCvkNO3GW/EPq/o8xCYlLcT2FVY8LtKsR3k8ZfzmP9tjDzrq9Edp4GDkVtpgFUMGfBVkWmFK2L626u70NL2iGLezktElRcJQ5vWd3cB47dK2qrl9Kh+RLwNdU4lxfq1CRB5J9qxoDsSZnbyxYcjOTHefI2euhpPcpy8I4dd+jP130fEN9WtlreYjVU/2f5T/yq8wTGWt/a1Mn/Qb5lfh5gY/7nP3ylThYmafxx1rJbPKeGMbSsEH35CwtlnBlw9e1PzL2O0NfF34vrith1ffhER5WEk+S9eG8Wb6HKbfKu1iOq98BAAD//028PJBvBQAA\n\n- path: /etc/kubernetes/addons/kubernetes-dashboard-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8xUQW/bPAy9+1cQuTtt8V1a4cOArgV6GQqjGXanJS7RIouCRGf1fv0gt3HsJE2DYQWmk0DRj4+Pj8Zgv1FMlr2CzVWxtt4oWFDcWE23WnPrpWhI0KCgKgAc1uRSvgGsr1OJIShYtzVFT0KpNJhWNWM0LxnDw9zyhXZtEopleoFXMJPY0qzPRGPYN+hxSXE+/axhQwqeSLPX1lEB4LGhN6vmxxRQv2aUqUtCTVGWZTFuNtao59jKiqP9hWLZz9fXfb3NVU2CWy3uXkg/saPP1hvrlxM9TlL5B8SK7OiJvmcOGOxD5Dac6L0AOOh6aHLLCE1jfZHa+gdpSaoo4ahr/s6Y9j35thnPVu+9SfwJ7RRIZx6Bo/SEyv6q4PqyrykYlyRVH7q5vMnBRI60cDzPHtIFUvDIhjLIgUz0LOTzNe3Z956C466hU2v8MUv6sUJHCs5qTAquDrRsUPTqy6jDM+SlJjgUegUYKZWPm2Cds8tbmvlo9oLWUxwQSsC4TAoGQNvgkhT8v8O738ItAulP08Sqda5iZ3Wn4Nb9xC4N785uyFNKVeSadoQBViLhgWQcAggoKwWzi9k0OnbpUNhbsejuyWG3yFM2ScF/4wyxDXErxx5PDnpXdKRwuVOtOkYnRBbW7BR8vate42ny/3l8r6ZnQ4uJb/LJu7NnbU4KnPXtMxS/AwAA//+MY7+tLgcAAA==\n\n- path: /etc/kubernetes/addons/kube-heapster-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8xWW2tjNxB+P79C+F1ep92AK+pCmk3bh2Y3JFAoLISxNOujWrfq4rX31xfpHNvnYgcTNlC9WGdGo2/mm4sMTv6FPkhrGNlcVWtpBCNP6DeS4w3nNplYaYwgIAKrCDGgkZEawYWIvhUEBxwZWacl0rALEXVFiIIlqpBtSNF4gxHDVNp3XKVsTEMDw8gk+oSTchKEsEaDgRX6ad9MW4GMPCK3hkuFFaW06rrvl8CnkGJtvfwGUVozXc+L5eZqiRH20d028I9W4YnQGv/ZPkL6VcaaGjBm93Yx3ZmQPN5tZYih8klhYBUl4OTv3iZX8CjBbUSTIw3lE5zLG4/BJs+xPSTQKbvTaGJWbtAvW8UKY/lVMjSbrxB5XXbJCYhYtq4IR9CTyRgJNy0IPZZA+2lFu3NWXObGd0jlr9IIaVb/y4xahY/4JYPsiX0hxIqQcZ1eEEtIy3+Qx1I6J9v48uYdpmM4GHokv47B/snGsT/6jl3iaXDIM7SzPrYllreMzGcFJoJfYXxoRfMfKkICKuTR+tbjeaDgXAcrB99E++HQTD02jo14qMazfIxuf8s6e2EYD/jc0+bRKckhMHI1YkbnzvyzE8zpcCJqpyBia9QhIi/Vsz9HCCFgjI2lCzqHA69RJIV+CsrVMCCAexklB0WdFawZUYTsAyu5twp9/05K1rhj5LY1vcn0hk9G7Q6Y1mUb6xk5kFru7bXSx2F15sWtiSAN+g6a1LBCRn4+er6v8SeH/JcDKrdagxHH0CmZvNvfP+lKKW2m8KJDRkhag989g5Ps8+Tz5GgwaqNm9Ub5UfhvwhB7MkK4S7lzdE+oUVu/Y+Tq/exedjRKavnqC06xVRL0iEF+u4gxZ8VzGYYDyrhLi/lMD6S4jR6Kbja9HiobDxfFwZN27YH3I3WsPYbaKrG4HmiOj/PiTG4PNXTugLNKUYdeWrH4cZbX0LkQpc4FvMCtswZNlKDOFcThFXxdWVyfyepPF1bFRfZoNt0kb0Al/M1b3b/vi0Ql2jd2JH+AWLPDaJpmDjrHGkru/35++PTh+ePN/d33Rysj+SXIp4eb2z1u/vv01JvEeeV3ZjAAbWBESZO21X8BAAD//0SxZ2rFCwAA\n\n- path: /etc/kubernetes/addons/azure-storage-classes.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8yQTUs0MRCE7/kVzd4zL3t7ydWrgrjgVXon5RJmkgzdnQH99TIfLqhXFzx3nkrVw1N6hmiqJZBaFb6gG/5rl+q/+XiG8dENqcRAp+14N7KqyzCObBwcUeGMQBGv3EZzRFxKNbZUiy5n+oztF7JbIruhnSEFhvWfpH6n/fom0MGk4eCIRj5j3GO+Qv3Y1CBeIXPqcWUmqXNa5kDCN4Tfm8DHpIPz3rvfWp658AXRT4KcWv5p4FYjJhbOMMiavXV92Mq4q3Xu+9qK2duEQI9bxZf7p9NNFKhxiSzxLzs47R1XCR8BAAD//1fQzbL+AgAA\n\n- path: /etc/kubernetes/addons/kube-tiller-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8yUW0scPxjG7+dTvHg/q8tf4U8oBasigsriSm9LNvPUTc2pyZvB7acvM9sZ52BFC4XmapL38PzyJBkZ9GfEpL0TVC+LR+0qQWvEWiucKuWz48KCZSVZioLISQtBrI1B/DVNQSoIeswblGmXGLYgMnIDk5oKaiPRgZEW2h8qkxMjlmkvIuiAY8ZBUZZlMaSJG6kWMvPWR/1DsvZu8fh/26FebsCygz3b97vzBp+0q7R7eA34/VzRG9zha1Mig76MPodX4AqiGVZP0UnIympXpLz5BsVJFCW96Ptb3Z46Nz3HkR9DA2QIgrYwtp1NxN7qz7iwrBCM3/0eNgWoRj34yC1GORduYoKOj5f/HbdzlvEBvGpX+7QEA8U+vmErvAvoT+RqNTMMTwzXfKbJ3TpvN2MxeQT/iocMG4xk7EmGhM0YUs5JX6TtGrffo8t4O00lUt6x1A6x1ygJrn4W7E72/ur6+uLuy+3pzcV6dXp20ScQ1dLk2b9jP7SVDxD04dnB+1Z9HaA+9llG13BIaRX9BmLQecscLsHDJaIgeSvosCsax/pLdzJY106zluYcRu7WUN5VSdBykMDawmd+ITZzt1NJQ4t6F1eTS/9KkwhZ6Xfvuq/6u9uOSD5HhTSEiPiekTiNwVTIgk6O7GjRwvq4E7Q8ObrRg4jRVv9xA+crrEc/jGY0T30xfqE+CTLa5afiZwAAAP//2LvwXhoHAAA=\n\n\n\n- path: \"/etc/systemd/system/kubectl-extract.service\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n [Unit]\n Description=Kubectl extraction\n Requires=docker.service\n After=docker.service\n ConditionPathExists=!/usr/local/bin/kubectl\n\n [Service]\n TimeoutStartSec=0\n Restart=on-failure\n RestartSec=5s\n ExecStartPre=/bin/mkdir -p /tmp/kubectldir\n ExecStartPre=/usr/bin/docker pull ',parameters('kubernetesHyperkubeSpec'),'\n ExecStartPre=/usr/bin/docker run --rm -v /tmp/kubectldir:/opt/kubectldir ',parameters('kubernetesHyperkubeSpec'),' /bin/bash -c \"cp /hyperkube /opt/kubectldir/\"\n ExecStartPre=/bin/mv /tmp/kubectldir/hyperkube /usr/local/bin/kubectl\n ExecStart=/bin/chmod a+x /usr/local/bin/kubectl\n\n [Install]\n WantedBy=multi-user.target\n\n- path: \"/etc/default/kubelet\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n KUBELET_CLUSTER_DNS=',parameters('kubeDNSServiceIP'),'\n KUBELET_API_SERVERS=',concat('https://', variables('masterPrivateIpAddrs')[copyIndex(variables('masterOffset'))], ':443'),'\n KUBELET_IMAGE=',parameters('kubernetesHyperkubeSpec'),'\n KUBELET_NETWORK_PLUGIN=\n DOCKER_OPTS=\n KUBELET_REGISTER_WITH_TAINTS=',variables('registerWithTaints'),'\n KUBELET_NODE_LABELS=role=master\n KUBELET_POD_INFRA_CONTAINER_IMAGE=',parameters('kubernetesPodInfraContainerSpec'),'\n \n- path: \"/etc/systemd/system/kubelet.service\"\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/5RVX2/bNhB/16cg3D5sD7SaNNg6F3pwYiUz4tqZZaMY0sCgxbPEhSK149Gut/a7D5KVxLKdYYMAgfzd/e4/yfu5UfQQDMClqEpS1kS3fgkaKJjCn14huEja9BGw6wDXKoWgvyLAQzC4T3arh2AKjgRSJPRGbF0Qm7VCawowdK00RCFQGkpYCa8pfGx8JT5Nwbn4q6KEBHkXnV28D+KvkCaVrTuEKFwqEy6Fy1loSwrFXx4hTK0hoQygezLVdfkJXvEoFTJesnAtMNRq+ez5FR88ZR21Yvfs7Q+F9YbYN5YhlOxL59DClw77xjYp4/pHxjWwd+yBfWSUg2E71zWd86Uy8sj9MfCRrVTnVAaNmUI8Ane5QDi2Frxhs1w5phwTrBRISmi2sfgo0HojGVlGldyXjhBEwapWowGCiuM89II3jOVEpeuFYaYo98tuaova/k5vf1lTXHhx9svZT2/qTWqLqs/8/dn5xfmHn9+fHSTiqkzc1qWkGd8wA9RV5fqiS2m5QCBU4M6jD20S37FgSWKpwTFOzIiqElo5Oqmqyn9XjULvsC7qbogZesO+BIxxboCi3DpqtqWSrS2qtdKQgWwALJrF2mpfQBRKWPeq3wHstq5X/9AeSKoOoje95wVuTmhUPd7FGvYOgNcJzVDsMRqk14zPCZrNes+LI8PVwd1rf+8AOE7O4bpNaAMV4e1gcnUbTxeTu1nySh4bITIwFH4SRmQghxIMKdryBIiUyVzvv2s2ETL29u/b+WU8imeL4af+Tfy9gRkL820JWMXInk7kk6iKrcJSa1YqO67zi6xFwd01yl8Rl1ZyZVYo+PNdxlUhMog6L0HeTQaL4fh62l9cTcaz/nAcT5vAOy1jQkoE56J33fpry7S2m70Rjgg9tDTAVMeGV1c64CmJhKXPMmUyngsjNaA7SqUQRq3AES8F5Ucj8yRt81LtHQFyaVz0kvPVaJ7M4uliME6+n1a3hVAmarZdbVOhDyqfqVrTpTlIr6sc9hxM45th7SG5+jUezEf9y1Hc9mSsBK7FErTb78Z4MogXo/5lPEoO6p9q6yUv0a6VBIzqN+qEwtMEHVSnVu/+4axpN66C96ZjlxZu/6eZXCgsleGFlRCVaAvlUm+940tUMmuHaYCqZ4OX2mfK7NVsHM8+T6a3i7vR/GY4PlEtV7/e3JdSEPBVNfxg0m10UL1k1p/Nk8X8btCfxYvrafzbPB5f/d42uI7O9w7qddyfzafx4qY/i5PvQXA/NI6E1g/BZ2EI5OU2Krwmxb0D7JLADCj4JwAA//9Myf113wgAAA==\n\n- path: \"/opt/azure/containers/kubelet.sh\"\n permissions: \"0755\"\n owner: \"root\"\n content: |\n #!/bin/bash\n set -e\n\n\n # Azure does not support two LoadBalancers(LB) sharing the same nic and backend port.\n # As a workaround, the Internal LB(ILB) listens for apiserver traffic on port 4443 and the External LB(ELB) on port 443\n # This IPTable rule then redirects ILB traffic to port 443 in the prerouting chain\n iptables -t nat -A PREROUTING -p tcp --dport 4443 -j REDIRECT --to-port 443\n\n\n sed -i \"s|\u003ckubernetesAddonManagerSpec\u003e|',parameters('kubernetesAddonManagerSpec'),'|g\" \"/etc/kubernetes/manifests/kube-addon-manager.yaml\"\n sed -i \"s|\u003ckubernetesHyperkubeSpec\u003e|',parameters('kubernetesHyperkubeSpec'),'|g; s|\u003ckubeServiceCidr\u003e|',parameters('kubeServiceCidr'),'|g; s|\u003cmasterEtcdClientPort\u003e|',variables('masterEtcdClientPort'),'|g; s|\u003ckubernetesAPIServerIP\u003e|',variables('kubernetesAPIServerIP'),'|g\" \"/etc/kubernetes/manifests/kube-apiserver.yaml\"\n sed -i \"s|\u003ckubernetesHyperkubeSpec\u003e|',parameters('kubernetesHyperkubeSpec'),'|g; s|\u003cmasterFqdnPrefix\u003e|',variables('masterFqdnPrefix'),'|g; s|\u003callocateNodeCidrs\u003e|',variables('allocateNodeCidrs'),'|g; s|\u003ckubeClusterCidr\u003e|',parameters('kubeClusterCidr'),'|g; s|\u003ckubernetesCtrlMgrNodeMonitorGracePeriod\u003e|',variables('kubernetesCtrlMgrNodeMonitorGracePeriod'),'|g; s|\u003ckubernetesCtrlMgrPodEvictionTimeout\u003e|',variables('kubernetesCtrlMgrPodEvictionTimeout'),'|g; s|\u003ckubernetesCtrlMgrRouteReconciliationPeriod\u003e|',variables('kubernetesCtrlMgrRouteReconciliationPeriod'),'|g\" \"/etc/kubernetes/manifests/kube-controller-manager.yaml\"\n sed -i \"s|\u003ckubernetesHyperkubeSpec\u003e|',parameters('kubernetesHyperkubeSpec'),'|g\" \"/etc/kubernetes/manifests/kube-scheduler.yaml\"\n sed -i \"s|\u003ckubernetesHyperkubeSpec\u003e|',parameters('kubernetesHyperkubeSpec'),'|g; s|\u003ckubeClusterCidr\u003e|',parameters('kubeClusterCidr'),'|g\" \"/etc/kubernetes/addons/kube-proxy-daemonset.yaml\"\n sed -i \"s|\u003ckubernetesKubeDNSSpec\u003e|',parameters('kubernetesKubeDNSSpec'),'|g; s|\u003ckubernetesDNSMasqSpec\u003e|',parameters('kubernetesDNSMasqSpec'),'|g; s|\u003ckubernetesExecHealthzSpec\u003e|',parameters('kubernetesExecHealthzSpec'),'|g\" \"/etc/kubernetes/addons/kube-dns-deployment.yaml\"\n sed -i \"s|\u003ckubernetesHeapsterSpec\u003e|',parameters('kubernetesHeapsterSpec'),'|g; s|\u003ckubernetesAddonResizerSpec\u003e|',parameters('kubernetesAddonResizerSpec'),'|g\" \"/etc/kubernetes/addons/kube-heapster-deployment.yaml\"\n sed -i \"s|\u003ckubernetesDashboardSpec\u003e|',parameters('kubernetesDashboardSpec'),'|g\" \"/etc/kubernetes/addons/kubernetes-dashboard-deployment.yaml\"\n sed -i \"s|\u003ckubernetesTillerSpec\u003e|',parameters('kubernetesTillerSpec'),'|g\" \"/etc/kubernetes/addons/kube-tiller-deployment.yaml\"\n\n\n sed -i \"/\u003ckubernetesEnableRbac\u003e/d\" \"/etc/kubernetes/manifests/kube-apiserver.yaml\"\n sed -i \"/\u003ckubernetesEnableRbac\u003e/d\" \"/etc/kubernetes/manifests/kube-controller-manager.yaml\"\n\n\n\n\n- path: \"/opt/azure/containers/provision.sh\"\n permissions: \"0744\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n ',variables('provisionScript'),'\n\n- path: \"/opt/azure/containers/mountetcd.sh\"\n permissions: \"0744\"\n owner: \"root\"\n content: |\n #!/bin/bash\n # Mounting is done here instead of etcd because of bug https://bugs.launchpad.net/cloud-init/+bug/1692093\n # Once the bug is fixed, replace the below with the cloud init changes replaced in https://github.com/Azure/acs-engine/pull/661.\n set -x\n DISK=/dev/sdc\n PARTITION=${DISK}1\n MOUNTPOINT=/var/lib/etcddisk\n udevadm settle\n mkdir -p $MOUNTPOINT\n mount | grep $MOUNTPOINT\n if [ $? -eq 0 ]\n then\n echo \"disk is already mounted\"\n exit 0\n fi\n # fill /etc/fstab\n grep \"/dev/sdc1\" /etc/fstab\n if [ $? -ne 0 ]\n then\n echo \"$PARTITION $MOUNTPOINT auto defaults,nofail 0 2\" \u003e\u003e /etc/fstab\n fi\n # check if partition exists\n ls $PARTITION\n if [ $? -ne 0 ]\n then\n # partition does not exist\n /sbin/sgdisk --new 1 $DISK\n /sbin/mkfs.ext4 $PARTITION -L etcd_disk -F -E lazy_itable_init=1,lazy_journal_init=1\n fi\n mount $MOUNTPOINT\n\nruncmd:\n- /bin/echo DAEMON_ARGS=--name \"',variables('masterVMNames')[copyIndex(variables('masterOffset'))],'\" --initial-advertise-peer-urls \"',variables('masterEtcdPeerURLs')[copyIndex(variables('masterOffset'))],'\" --listen-peer-urls \"',variables('masterEtcdPeerURLs')[copyIndex(variables('masterOffset'))],'\" --advertise-client-urls \"',variables('masterEtcdClientURLs')[copyIndex(variables('masterOffset'))],'\" --listen-client-urls \"',concat(variables('masterEtcdClientURLs')[copyIndex(variables('masterOffset'))], ',http://127.0.0.1:', variables('masterEtcdClientPort')),'\" --initial-cluster-token \"k8s-etcd-cluster\" --initial-cluster \"',variables('masterEtcdClusterStates')[div(variables('masterCount'), 2)],' --data-dir \"/var/lib/etcddisk\"\" --initial-cluster-state \"new\" | tee -a /etc/default/etcd\n- sudo /bin/chown -R etcd:etcd /var/lib/etcd/default\n- /opt/azure/containers/mountetcd.sh\n- sudo /bin/chown -R etcd:etcd /var/lib/etcddisk\n- systemctl stop etcd\n- sudo -u etcd rm -rf /var/lib/etcd/default\n- systemctl restart etcd\n- for i in $(seq 1 20); do curl --max-time 60 http://127.0.0.1:2379/v2/machines; [ $? -eq 0 ] \u0026\u0026 break || sleep 5; done\n- retrycmd_if_failure() { for i in 1 2 3 4 5; do $@; [ $? -eq 0 ] \u0026\u0026 break || sleep 5; done ; }\n- retrycmd_if_failure apt-get update\n- retrycmd_if_failure apt-get install -y apt-transport-https ca-certificates\n- retrycmd_if_failure curl --max-time 60 -fsSL https://aptdocker.azureedge.net/gpg | apt-key add -\n- echo \"deb ',parameters('dockerEngineDownloadRepo'),' ubuntu-xenial main\" | sudo tee /etc/apt/sources.list.d/docker.list\n- \"echo \\\"Package: docker-engine\\nPin: version ',parameters('dockerEngineVersion'),'\\nPin-Priority: 550\\n\\\" \u003e /etc/apt/preferences.d/docker.pref\"\n- retrycmd_if_failure apt-get update\n- retrycmd_if_failure apt-get install -y ebtables\n- retrycmd_if_failure apt-get install -y docker-engine\n- systemctl restart docker\n- mkdir -p /etc/kubernetes/manifests\n- usermod -aG docker ',parameters('linuxAdminUsername'),'\n- /usr/lib/apt/apt.systemd.daily\n- touch /opt/azure/containers/runcmd.complete\n'))]", + "customData": "[base64(concat('#cloud-config\n\npackages:\n - etcd\n - jq\n - traceroute\n\nwrite_files:\n- path: \"/etc/systemd/system/docker.service.d/clear_mount_propagation_flags.conf\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n [Service]\n MountFlags=shared\n\n- path: \"/etc/systemd/system/docker.service.d/exec_start.conf\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n [Service]\n ExecStart=\n ExecStart=/usr/bin/docker daemon -H fd:// --storage-driver=overlay --bip=',parameters('dockerBridgeCidr'),'\n\n- path: \"/etc/docker/daemon.json\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n {\n \"live-restore\": true,\n \"log-driver\": \"json-file\",\n \"log-opts\": {\n \"max-size\": \"50m\",\n \"max-file\": \"5\"\n }\n }\n\n- path: \"/etc/kubernetes/certs/ca.crt\"\n permissions: \"0644\"\n encoding: \"base64\"\n owner: \"root\"\n content: |\n ',parameters('caCertificate'),'\n\n- path: \"/etc/kubernetes/certs/apiserver.crt\"\n permissions: \"0644\"\n encoding: \"base64\"\n owner: \"root\"\n content: |\n ',parameters('apiServerCertificate'),'\n\n- path: \"/etc/kubernetes/certs/client.crt\"\n permissions: \"0644\"\n encoding: \"base64\"\n owner: \"root\"\n content: |\n ',parameters('clientCertificate'),'\n\n- path: \"/var/lib/kubelet/kubeconfig\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n apiVersion: v1\n kind: Config\n clusters:\n - name: localcluster\n cluster:\n certificate-authority: /etc/kubernetes/certs/ca.crt\n server: ',concat('https://', variables('masterPrivateIpAddrs')[copyIndex(variables('masterOffset'))], ':443'),'\n users:\n - name: client\n user:\n client-certificate: /etc/kubernetes/certs/client.crt\n client-key: /etc/kubernetes/certs/client.key\n contexts:\n - context:\n cluster: localcluster\n user: client\n name: localclustercontext\n current-context: localclustercontext\n\n- path: /etc/kubernetes/manifests/kube-apiserver.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/6RUy27jOgzd5ysMr6O67S1wC6MuUPQWuAXaTqYBZs9IjKOJXkPRLjJfP5DzttMHMMlKOjxH5CFNCPoHUtTelVneXuSjpXaqzPKJV/nIIoMChnKUZQ4sllm+bGYoIOiI1CLlGyAGkDs0riKjTZCBGZqY2FnGGqnMpHdM3ohgwGF3L70N3qHjMjvWHsWAMnEXPvIL8punZZkxNYmXdEA7pI26eD+/9NMW6oTeJJgcMsb/VwEpHacB5e02UHprIRmwOSflvFhsY/PD68Er3a0QoKyOyVGxqbZ62Vr0pOcoV9Lg+Elbza/gaqTxFKnVEu+k9I3j8X84h8bwlD1BjfcGYhy/YvQNSfzeeIbBe4owxur8rPv3UWP8mwikW22wRtWDtYsoG0IRPHF1fX7d5x/CV1f/9FBpfKNEIN9qhVTB74bwZIj0bq7rqkCWxb4JRUc4+xm9GzzbeSKkaSIjCR0EJbeqroUbx+61otseEVkqse5LrBbMoSyKi8t/O28uyhsLSe6Bpbo3Gh1PPPFJiV+Np8YKQlBVGrqB6S0S64g7+w9m627yOO0yeJz0tdlEIZFYzLXBgR0JicVusM4k8Ql+aiYwiiWuviazxNWgKal4IeEjAQknEtg2BtbT+jdJxPWEixnIJTpVJd8vezFtdXV0c+Dyg4OZwdcZ7D/f1pvG4nNKbLMYjpYDshR7/l43y2yiTIAXZZb3CsmHOi2QMHrWaRnkd4VaoMLoWTGI2ynZqD9lvwHU6Lh4Bgc1qkeFjjWvxBSZtauP6kjj+s2Z1W5Rrh3pb8nTRqRF2z2+EwwfOPKZG++rnbRlK2ej/rLA5878CQAA//8KCj673wYAAA==\n\n- path: /etc/kubernetes/manifests/kube-controller-manager.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/6SUTW/bPAyA7/kVhu+q8b5Ho+6l6PtxSBe0w+6MxLpaJNGjaHfZrx/oJE3jxMuA+Wbq4UOJ+oDOf0HOnlJdlMNf5WLjk6uLckWuXEQUcCBQL4oiQcS6KDf9Go2lJEwhIJsICVrkck/kDuw7lrdZMOpQgDWGrJqiEI9cF3uF6QIkHOOWYkcJk9TFTJFF7tCq5JWyPKK8EW/qQrhXgeLgE/K+jPmNGevnI7SK3SrHCQXzf9sOWX+fO7R3B9BSjKC92f9ribJ6PbDlx/B8uXHYGM2wlF5821QDcBX8utJYQKmOY5MkCIEsCJpEDo31jnNzewg+ksN7Dd1NsmzosyCPfDOu8n4XUXoO1t41txH0559vLq0YX/z3c5p6ZzqmwTvkBn70jBeRw1JRbHXsczUm3HzNlCZZTCTGgnnxAc+yLLLkysKNZZmZfvZt8qk1iv6xZIPbK44NbieOjDx4iwaspT6J6dgPunNXXNB5zUS+oAwIDtlgQCuNHvqT8Q/H9yHBOuDTGux0v4bm70lkPEmRkhdi0zJYNB2yJ9d8EN4Lh2XLesKWO/RfJVcjOK3RkTM4eCuekhEfkXq5IFuRe9hTn3fQVMTUCxrWq2B98DAKZyf3pPTTCTyZ30Chj7jU7cgnl3j/TqBYc9QeJ1MUUXNWIK91UU72rTz3DMAm+LXZX+dZ0eTan5ti9tdy3wBaTFItx0fG/e8wiZeteUYRn9qTVTCC+5TC9v3F3DVk+lxeboO+uGPxd2H3i35c68W87WJTzhtyXXC9Mz8DAAD//8PhLmf6BgAA\n\n- path: /etc/kubernetes/manifests/kube-scheduler.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/4SSQY/bIBCF7/kViDtC7RE1PbeHbVdaqfcxTG0UGBCMvfK/r0ideOMka988b97HzNNA9n+wVJ/ICDl9kYeTJ2eEfE1OHiIyOGAwByEIIhohT2OHqtoB3RiwyEWoGeyqzpUxNilAh6E2txDssRhhE3FJQeUAhOe6TTEnQmIjbtmHmtE275Aq/0J+T+VkBJex+RoHPGFZ6Or5fO3zEfqmfmtyIWSsP+aMpf2+ZbTfL402xQjkzPLbwFIPl1b5sXz3yLmqVGu0if76/qgnKDr4TrdaQNartjEFBIdFYUDLx7bjRp+OXy+VKYUx4ksaievHOZcAkK1at1wxQsRmeQUejJAa2epHbVfOBEUF36ll9KegzYr3pFj9nvcdoEdi/QIEPbqfDok9z+oNmT31N1sUBPebwnw9hf95bO/gcQztlM6PX4H5kzz2snhOexjKfSD7gP1k/gUAAP//FKERJ8EDAAA=\n\n- path: /etc/kubernetes/manifests/kube-addon-manager.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/4yRsW7zMAyEdz8Fkd3w/w9ZhKJAxw5pAwTozkiEIySiXJFy4LcvZMdOWjRtR5LH43cSdv6NkvjIBvr/1dGzM7CNrgqk6FDRVACMgQwc855qdC5yHZCxpXQZSYd2nssgSqEC6G9cpSNbfA5R9IX0HNPRgKZMFYCNrOiZkhRF/dMtAB+wJQMPZZyYlOSpaDaTZNeRfRx1iSTmZGn0nBrvmUSXGsB22cA6LHWgENNgYP1v48dmH0850CZmntdmuJFLLpuhCLaoBwOrhtQ2V7ZmEq4WBnSvfBqW6FfHIP47ux5Tc/L75ozYEmsz5XTPjli9DvWOVD239y9MGT697A18+Y7x1GW9+y3FV9x7Bn/n/ggAAP//ovMbJ38CAAA=\n\n- path: /etc/kubernetes/addons/kube-dns-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8xXS2/jNhC+61cQ7pl+JMhuINQLBOugG2yTGnXa+4QcW0QokuHDjffXF5RkWS+7dg7FyidzOA9+38xHCYz4G60TWqVkO0teheIpWaHdCoZ3jOmgfJKjBw4e0oQQBTmm5DW8IOXKVQvOANuvup3zmCeESHhB6aIPKSxWoUc3FnrCZHAeLXVlmpSMvA04KnYC51rloGCDdtx2yzXHlPyJTCsmJCaU0uRU+a26W9XcOgrGtI5xSY3tnSUi38MLLp5WFyDkDLJYT5XpYZmS2XQcf7NpQojR1hf10irivs5oSMnNdfnHaq+Zlin5a7Fsb6aemVMOz1+jg0OJzGt7DJkuyGCMm2xnL+hhD/cCjdS7HDud8jH+h7nZ1hxfTXsQ08PiCZgtGikYuJRc9Y6dg2fZ7416j9XRq8RjbiR4rOI0jl80s1Lagxda1XEJcSxDHiTaMUiTQafJmRVeMJDUaJ6S0ahyk63ijpd3CdQDxyFkD1dR/notlPC7Q1qj+Z3y4q5niI2Fa7QW+SJYoTar8pRCbR42StfL9+/IQgSk6UrJPyg2mY8DMG2sl/mqXM9o87RlrFBZtahsPgWt9+/GonNtDg6ZX3GX7tHsmQnRBi3E4ORBDZi3IAMOxC0id5kpH6+Nlnqz+14kbpGVaedjFyf7nTImb1Ze1fu1apK7KJbuDyV3Sb/g+3fhfN22WoYcG3E6I8S0WotNHaX8+wimebSesB1yxiJBpiQ2V1KH8CAU2kZSsJsGWJSMKOU6B6HmVZ+OpWYgx6POHuVoFLH5bDq9ue4Yt/OrzkpZPOXCziedAx52ihw2mJJfDwxUCr4yyL7U26TYokLnlla/YBOMNQgZLD5nFl2mJU/JTcOaeW9+Q99uDAM+S8lokiFIn/2gMTVXbtTp+CjWt9Pb9iBE0Yjof3t+XjYMcTIEyAVK2K3ixchdSj41XV1gDJ1r1DlrWL3IUQdfux7OcCC7yXV9Ke3hrlleFnUXBPVaJuJfENuSi/bFdXFAz8yJoOXlVj4WgYtBEk/SVLsdIWj2YYKup2dRYNHpYFlbX6TIhe8oTo65truUzD5PH0XDYvEtoOvuZiYUuOaDMVohStV4jC+BLdZPiwchefRYFjh2J/CUFjBgGVInfmCc9GlnrJWmERG57azHqw3tfHb1uXx5+mVIJapNE6EocG7HYA1MznQxn87ZLvWGroEJKfxuTk8JzeJp9QjurS00dWPn4N7Onrfh2bh8zI7P2H9M1zCPOZ8rJ7V+DaZ5xXFcQ5B+7LZs3BJ8UkNLvkw4bicqSNnBN1g5r6Wzwqkr/B/PmxaUnpm9J9zFluKGisLdWX8LAv2pfojvRN/K0P/f5dNDkPx0l09V6tnD0Kn72GVwoajeXKCpw5LaiMCVW2op2C5+NRVNWRlc64v7aehNS2mO/Xfd+CHW+YTQLiVSqPCe/BsAAP//MQMKdd0PAAA=\n\n- path: /etc/kubernetes/addons/kube-proxy-daemonset.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/5RUzW7bPBC8+ykI3RkmVyH+gA9ugV7aBgjQ+5qa2ET4oy6Xrv32BaU6kpzETXkSZoezszsCqXc/wNml2CocBbF+ZnO420LobvXsYteqT4SQ4iNkFSDUkVC7UsrTFj7XL6WeyxYcIcg3LhnrSxawzuCDs2hVI1zQDEybQp8iorTDJd1zOp6Gijhwq2LqsFIqUsAFo0K5J3vG8ykLwir3sNWEIPSeBKOhudF65mav23hlRalzi/FiFHIR/CKmq1ig2E3qWjVmf+rBVbuZwcs2WjVaV4pN8cnt1uZAbLzbmop5iJlqzfLSecPWdby+r7TNiGxcx/9dkJ9AUhh6R4K8/nzswS4gCvkNO3GW/EPq/o8xCYlLcT2FVY8LtKsR3k8ZfzmP9tjDzrq9Edp4GDkVtpgFUMGfBVkWmFK2L626u70NL2iGLezktElRcJQ5vWd3cB47dK2qrl9Kh+RLwNdU4lxfq1CRB5J9qxoDsSZnbyxYcjOTHefI2euhpPcpy8I4dd+jP130fEN9WtlreYjVU/2f5T/yq8wTGWt/a1Mn/Qb5lfh5gY/7nP3ylThYmafxx1rJbPKeGMbSsEH35CwtlnBlw9e1PzL2O0NfF34vrith1ffhER5WEk+S9eG8Wb6HKbfKu1iOq98BAAD//028PJBvBQAA\n\n- path: /etc/kubernetes/addons/kubernetes-dashboard-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8xUQW/bPAy9+1cQuTtt8V1a4cOArgV6GQqjGXanJS7RIouCRGf1fv0gt3HsJE2DYQWmk0DRj4+Pj8Zgv1FMlr2CzVWxtt4oWFDcWE23WnPrpWhI0KCgKgAc1uRSvgGsr1OJIShYtzVFT0KpNJhWNWM0LxnDw9zyhXZtEopleoFXMJPY0qzPRGPYN+hxSXE+/axhQwqeSLPX1lEB4LGhN6vmxxRQv2aUqUtCTVGWZTFuNtao59jKiqP9hWLZz9fXfb3NVU2CWy3uXkg/saPP1hvrlxM9TlL5B8SK7OiJvmcOGOxD5Dac6L0AOOh6aHLLCE1jfZHa+gdpSaoo4ahr/s6Y9j35thnPVu+9SfwJ7RRIZx6Bo/SEyv6q4PqyrykYlyRVH7q5vMnBRI60cDzPHtIFUvDIhjLIgUz0LOTzNe3Z956C466hU2v8MUv6sUJHCs5qTAquDrRsUPTqy6jDM+SlJjgUegUYKZWPm2Cds8tbmvlo9oLWUxwQSsC4TAoGQNvgkhT8v8O738ItAulP08Sqda5iZ3Wn4Nb9xC4N785uyFNKVeSadoQBViLhgWQcAggoKwWzi9k0OnbpUNhbsejuyWG3yFM2ScF/4wyxDXErxx5PDnpXdKRwuVOtOkYnRBbW7BR8vate42ny/3l8r6ZnQ4uJb/LJu7NnbU4KnPXtMxS/AwAA//+MY7+tLgcAAA==\n\n- path: /etc/kubernetes/addons/kube-heapster-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8xWW2tjNxB+P79C+F1ep92AK+pCmk3bh2Y3JFAoLISxNOujWrfq4rX31xfpHNvnYgcTNlC9WGdGo2/mm4sMTv6FPkhrGNlcVWtpBCNP6DeS4w3nNplYaYwgIAKrCDGgkZEawYWIvhUEBxwZWacl0rALEXVFiIIlqpBtSNF4gxHDVNp3XKVsTEMDw8gk+oSTchKEsEaDgRX6ad9MW4GMPCK3hkuFFaW06rrvl8CnkGJtvfwGUVozXc+L5eZqiRH20d028I9W4YnQGv/ZPkL6VcaaGjBm93Yx3ZmQPN5tZYih8klhYBUl4OTv3iZX8CjBbUSTIw3lE5zLG4/BJs+xPSTQKbvTaGJWbtAvW8UKY/lVMjSbrxB5XXbJCYhYtq4IR9CTyRgJNy0IPZZA+2lFu3NWXObGd0jlr9IIaVb/y4xahY/4JYPsiX0hxIqQcZ1eEEtIy3+Qx1I6J9v48uYdpmM4GHokv47B/snGsT/6jl3iaXDIM7SzPrYllreMzGcFJoJfYXxoRfMfKkICKuTR+tbjeaDgXAcrB99E++HQTD02jo14qMazfIxuf8s6e2EYD/jc0+bRKckhMHI1YkbnzvyzE8zpcCJqpyBia9QhIi/Vsz9HCCFgjI2lCzqHA69RJIV+CsrVMCCAexklB0WdFawZUYTsAyu5twp9/05K1rhj5LY1vcn0hk9G7Q6Y1mUb6xk5kFru7bXSx2F15sWtiSAN+g6a1LBCRn4+er6v8SeH/JcDKrdagxHH0CmZvNvfP+lKKW2m8KJDRkhag989g5Ps8+Tz5GgwaqNm9Ub5UfhvwhB7MkK4S7lzdE+oUVu/Y+Tq/exedjRKavnqC06xVRL0iEF+u4gxZ8VzGYYDyrhLi/lMD6S4jR6Kbja9HiobDxfFwZN27YH3I3WsPYbaKrG4HmiOj/PiTG4PNXTugLNKUYdeWrH4cZbX0LkQpc4FvMCtswZNlKDOFcThFXxdWVyfyepPF1bFRfZoNt0kb0Al/M1b3b/vi0Ql2jd2JH+AWLPDaJpmDjrHGkru/35++PTh+ePN/d33Rysj+SXIp4eb2z1u/vv01JvEeeV3ZjAAbWBESZO21X8BAAD//0SxZ2rFCwAA\n\n- path: /etc/kubernetes/addons/azure-storage-classes.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8yQTUs0MRCE7/kVzd4zL3t7ydWrgrjgVXon5RJmkgzdnQH99TIfLqhXFzx3nkrVw1N6hmiqJZBaFb6gG/5rl+q/+XiG8dENqcRAp+14N7KqyzCObBwcUeGMQBGv3EZzRFxKNbZUiy5n+oztF7JbIruhnSEFhvWfpH6n/fom0MGk4eCIRj5j3GO+Qv3Y1CBeIXPqcWUmqXNa5kDCN4Tfm8DHpIPz3rvfWp658AXRT4KcWv5p4FYjJhbOMMiavXV92Mq4q3Xu+9qK2duEQI9bxZf7p9NNFKhxiSzxLzs47R1XCR8BAAD//1fQzbL+AgAA\n\n- path: /etc/kubernetes/addons/kube-tiller-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8yUW0scPxjG7+dTvHg/q8tf4U8oBasigsriSm9LNvPUTc2pyZvB7acvM9sZ52BFC4XmapL38PzyJBkZ9GfEpL0TVC+LR+0qQWvEWiucKuWz48KCZSVZioLISQtBrI1B/DVNQSoIeswblGmXGLYgMnIDk5oKaiPRgZEW2h8qkxMjlmkvIuiAY8ZBUZZlMaSJG6kWMvPWR/1DsvZu8fh/26FebsCygz3b97vzBp+0q7R7eA34/VzRG9zha1Mig76MPodX4AqiGVZP0UnIympXpLz5BsVJFCW96Ptb3Z46Nz3HkR9DA2QIgrYwtp1NxN7qz7iwrBCM3/0eNgWoRj34yC1GORduYoKOj5f/HbdzlvEBvGpX+7QEA8U+vmErvAvoT+RqNTMMTwzXfKbJ3TpvN2MxeQT/iocMG4xk7EmGhM0YUs5JX6TtGrffo8t4O00lUt6x1A6x1ygJrn4W7E72/ur6+uLuy+3pzcV6dXp20ScQ1dLk2b9jP7SVDxD04dnB+1Z9HaA+9llG13BIaRX9BmLQecscLsHDJaIgeSvosCsax/pLdzJY106zluYcRu7WUN5VSdBykMDawmd+ITZzt1NJQ4t6F1eTS/9KkwhZ6Xfvuq/6u9uOSD5HhTSEiPiekTiNwVTIgk6O7GjRwvq4E7Q8ObrRg4jRVv9xA+crrEc/jGY0T30xfqE+CTLa5afiZwAAAP//2LvwXhoHAAA=\n\n\n\n- path: \"/etc/systemd/system/kubectl-extract.service\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n [Unit]\n Description=Kubectl extraction\n Requires=docker.service\n After=docker.service\n ConditionPathExists=!/usr/local/bin/kubectl\n\n [Service]\n TimeoutStartSec=0\n Restart=on-failure\n RestartSec=5s\n ExecStartPre=/bin/mkdir -p /tmp/kubectldir\n ExecStartPre=/usr/bin/docker pull ',parameters('kubernetesHyperkubeSpec'),'\n ExecStartPre=/usr/bin/docker run --rm -v /tmp/kubectldir:/opt/kubectldir ',parameters('kubernetesHyperkubeSpec'),' /bin/bash -c \"cp /hyperkube /opt/kubectldir/\"\n ExecStartPre=/bin/mv /tmp/kubectldir/hyperkube /usr/local/bin/kubectl\n ExecStart=/bin/chmod a+x /usr/local/bin/kubectl\n\n [Install]\n WantedBy=multi-user.target\n\n- path: \"/etc/default/kubelet\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n KUBELET_CLUSTER_DNS=',parameters('kubeDNSServiceIP'),'\n KUBELET_API_SERVERS=',concat('https://', variables('masterPrivateIpAddrs')[copyIndex(variables('masterOffset'))], ':443'),'\n KUBELET_IMAGE=',parameters('kubernetesHyperkubeSpec'),'\n KUBELET_NETWORK_PLUGIN=\n DOCKER_OPTS=\n KUBELET_REGISTER_WITH_TAINTS=',variables('registerWithTaints'),'\n KUBELET_NODE_LABELS=role=master\n KUBELET_POD_INFRA_CONTAINER_IMAGE=',parameters('kubernetesPodInfraContainerSpec'),'\n \n- path: \"/etc/systemd/system/kubelet.service\"\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/5RVX2/bNhB/16cg3D5sD7SaNNg6F3pwYiUz4tqZZaMY0sCgxbPEhSK149Gut/a7D5KVxLKdYYMAgfzd/e4/yfu5UfQQDMClqEpS1kS3fgkaKJjCn14huEja9BGw6wDXKoWgvyLAQzC4T3arh2AKjgRSJPRGbF0Qm7VCawowdK00RCFQGkpYCa8pfGx8JT5Nwbn4q6KEBHkXnV28D+KvkCaVrTuEKFwqEy6Fy1loSwrFXx4hTK0hoQygezLVdfkJXvEoFTJesnAtMNRq+ez5FR88ZR21Yvfs7Q+F9YbYN5YhlOxL59DClw77xjYp4/pHxjWwd+yBfWSUg2E71zWd86Uy8sj9MfCRrVTnVAaNmUI8Ane5QDi2Frxhs1w5phwTrBRISmi2sfgo0HojGVlGldyXjhBEwapWowGCiuM89II3jOVEpeuFYaYo98tuaova/k5vf1lTXHhx9svZT2/qTWqLqs/8/dn5xfmHn9+fHSTiqkzc1qWkGd8wA9RV5fqiS2m5QCBU4M6jD20S37FgSWKpwTFOzIiqElo5Oqmqyn9XjULvsC7qbogZesO+BIxxboCi3DpqtqWSrS2qtdKQgWwALJrF2mpfQBRKWPeq3wHstq5X/9AeSKoOoje95wVuTmhUPd7FGvYOgNcJzVDsMRqk14zPCZrNes+LI8PVwd1rf+8AOE7O4bpNaAMV4e1gcnUbTxeTu1nySh4bITIwFH4SRmQghxIMKdryBIiUyVzvv2s2ETL29u/b+WU8imeL4af+Tfy9gRkL820JWMXInk7kk6iKrcJSa1YqO67zi6xFwd01yl8Rl1ZyZVYo+PNdxlUhMog6L0HeTQaL4fh62l9cTcaz/nAcT5vAOy1jQkoE56J33fpry7S2m70Rjgg9tDTAVMeGV1c64CmJhKXPMmUyngsjNaA7SqUQRq3AES8F5Ucj8yRt81LtHQFyaVz0kvPVaJ7M4uliME6+n1a3hVAmarZdbVOhDyqfqVrTpTlIr6sc9hxM45th7SG5+jUezEf9y1Hc9mSsBK7FErTb78Z4MogXo/5lPEoO6p9q6yUv0a6VBIzqN+qEwtMEHVSnVu/+4axpN66C96ZjlxZu/6eZXCgsleGFlRCVaAvlUm+940tUMmuHaYCqZ4OX2mfK7NVsHM8+T6a3i7vR/GY4PlEtV7/e3JdSEPBVNfxg0m10UL1k1p/Nk8X8btCfxYvrafzbPB5f/d42uI7O9w7qddyfzafx4qY/i5PvQXA/NI6E1g/BZ2EI5OU2Krwmxb0D7JLADCj4JwAA//9Myf113wgAAA==\n\n- path: \"/opt/azure/containers/kubelet.sh\"\n permissions: \"0755\"\n owner: \"root\"\n content: |\n #!/bin/bash\n set -e\n\n\n # Azure does not support two LoadBalancers(LB) sharing the same nic and backend port.\n # As a workaround, the Internal LB(ILB) listens for apiserver traffic on port 4443 and the External LB(ELB) on port 443\n # This IPTable rule then redirects ILB traffic to port 443 in the prerouting chain\n iptables -t nat -A PREROUTING -p tcp --dport 4443 -j REDIRECT --to-port 443\n\n\n sed -i \"s|\u003ckubernetesAddonManagerSpec\u003e|',parameters('kubernetesAddonManagerSpec'),'|g\" \"/etc/kubernetes/manifests/kube-addon-manager.yaml\"\n sed -i \"s|\u003ckubernetesHyperkubeSpec\u003e|',parameters('kubernetesHyperkubeSpec'),'|g; s|\u003ckubeServiceCidr\u003e|',parameters('kubeServiceCidr'),'|g; s|\u003cmasterEtcdClientPort\u003e|',variables('masterEtcdClientPort'),'|g; s|\u003ckubernetesAPIServerIP\u003e|',variables('kubernetesAPIServerIP'),'|g\" \"/etc/kubernetes/manifests/kube-apiserver.yaml\"\n sed -i \"s|\u003ckubernetesHyperkubeSpec\u003e|',parameters('kubernetesHyperkubeSpec'),'|g; s|\u003cmasterFqdnPrefix\u003e|',variables('masterFqdnPrefix'),'|g; s|\u003callocateNodeCidrs\u003e|',variables('allocateNodeCidrs'),'|g; s|\u003ckubeClusterCidr\u003e|',parameters('kubeClusterCidr'),'|g; s|\u003ckubernetesCtrlMgrNodeMonitorGracePeriod\u003e|',variables('kubernetesCtrlMgrNodeMonitorGracePeriod'),'|g; s|\u003ckubernetesCtrlMgrPodEvictionTimeout\u003e|',variables('kubernetesCtrlMgrPodEvictionTimeout'),'|g; s|\u003ckubernetesCtrlMgrRouteReconciliationPeriod\u003e|',variables('kubernetesCtrlMgrRouteReconciliationPeriod'),'|g\" \"/etc/kubernetes/manifests/kube-controller-manager.yaml\"\n sed -i \"s|\u003ckubernetesHyperkubeSpec\u003e|',parameters('kubernetesHyperkubeSpec'),'|g\" \"/etc/kubernetes/manifests/kube-scheduler.yaml\"\n sed -i \"s|\u003ckubernetesHyperkubeSpec\u003e|',parameters('kubernetesHyperkubeSpec'),'|g; s|\u003ckubeClusterCidr\u003e|',parameters('kubeClusterCidr'),'|g\" \"/etc/kubernetes/addons/kube-proxy-daemonset.yaml\"\n sed -i \"s|\u003ckubernetesKubeDNSSpec\u003e|',parameters('kubernetesKubeDNSSpec'),'|g; s|\u003ckubernetesDNSMasqSpec\u003e|',parameters('kubernetesDNSMasqSpec'),'|g; s|\u003ckubernetesExecHealthzSpec\u003e|',parameters('kubernetesExecHealthzSpec'),'|g\" \"/etc/kubernetes/addons/kube-dns-deployment.yaml\"\n sed -i \"s|\u003ckubernetesHeapsterSpec\u003e|',parameters('kubernetesHeapsterSpec'),'|g; s|\u003ckubernetesAddonResizerSpec\u003e|',parameters('kubernetesAddonResizerSpec'),'|g\" \"/etc/kubernetes/addons/kube-heapster-deployment.yaml\"\n sed -i \"s|\u003ckubernetesDashboardSpec\u003e|',parameters('kubernetesDashboardSpec'),'|g\" \"/etc/kubernetes/addons/kubernetes-dashboard-deployment.yaml\"\n sed -i \"s|\u003ckubernetesTillerSpec\u003e|',parameters('kubernetesTillerSpec'),'|g\" \"/etc/kubernetes/addons/kube-tiller-deployment.yaml\"\n\n\n sed -i \"/\u003ckubernetesEnableRbac\u003e/d\" \"/etc/kubernetes/manifests/kube-apiserver.yaml\"\n sed -i \"/\u003ckubernetesEnableRbac\u003e/d\" \"/etc/kubernetes/manifests/kube-controller-manager.yaml\"\n\n\n\n\n- path: \"/opt/azure/containers/provision.sh\"\n permissions: \"0744\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n ',variables('provisionScript'),'\n\n- path: \"/opt/azure/containers/mountetcd.sh\"\n permissions: \"0744\"\n owner: \"root\"\n content: |\n #!/bin/bash\n # Mounting is done here instead of etcd because of bug https://bugs.launchpad.net/cloud-init/+bug/1692093\n # Once the bug is fixed, replace the below with the cloud init changes replaced in https://github.com/Azure/aks-engine/pull/661.\n set -x\n DISK=/dev/sdc\n PARTITION=${DISK}1\n MOUNTPOINT=/var/lib/etcddisk\n udevadm settle\n mkdir -p $MOUNTPOINT\n mount | grep $MOUNTPOINT\n if [ $? -eq 0 ]\n then\n echo \"disk is already mounted\"\n exit 0\n fi\n # fill /etc/fstab\n grep \"/dev/sdc1\" /etc/fstab\n if [ $? -ne 0 ]\n then\n echo \"$PARTITION $MOUNTPOINT auto defaults,nofail 0 2\" \u003e\u003e /etc/fstab\n fi\n # check if partition exists\n ls $PARTITION\n if [ $? -ne 0 ]\n then\n # partition does not exist\n /sbin/sgdisk --new 1 $DISK\n /sbin/mkfs.ext4 $PARTITION -L etcd_disk -F -E lazy_itable_init=1,lazy_journal_init=1\n fi\n mount $MOUNTPOINT\n\nruncmd:\n- /bin/echo DAEMON_ARGS=--name \"',variables('masterVMNames')[copyIndex(variables('masterOffset'))],'\" --initial-advertise-peer-urls \"',variables('masterEtcdPeerURLs')[copyIndex(variables('masterOffset'))],'\" --listen-peer-urls \"',variables('masterEtcdPeerURLs')[copyIndex(variables('masterOffset'))],'\" --advertise-client-urls \"',variables('masterEtcdClientURLs')[copyIndex(variables('masterOffset'))],'\" --listen-client-urls \"',concat(variables('masterEtcdClientURLs')[copyIndex(variables('masterOffset'))], ',http://127.0.0.1:', variables('masterEtcdClientPort')),'\" --initial-cluster-token \"k8s-etcd-cluster\" --initial-cluster \"',variables('masterEtcdClusterStates')[div(variables('masterCount'), 2)],' --data-dir \"/var/lib/etcddisk\"\" --initial-cluster-state \"new\" | tee -a /etc/default/etcd\n- sudo /bin/chown -R etcd:etcd /var/lib/etcd/default\n- /opt/azure/containers/mountetcd.sh\n- sudo /bin/chown -R etcd:etcd /var/lib/etcddisk\n- systemctl stop etcd\n- sudo -u etcd rm -rf /var/lib/etcd/default\n- systemctl restart etcd\n- for i in $(seq 1 20); do curl --max-time 60 http://127.0.0.1:2379/v2/machines; [ $? -eq 0 ] \u0026\u0026 break || sleep 5; done\n- retrycmd_if_failure() { for i in 1 2 3 4 5; do $@; [ $? -eq 0 ] \u0026\u0026 break || sleep 5; done ; }\n- retrycmd_if_failure apt-get update\n- retrycmd_if_failure apt-get install -y apt-transport-https ca-certificates\n- retrycmd_if_failure curl --max-time 60 -fsSL https://aptdocker.azureedge.net/gpg | apt-key add -\n- echo \"deb ',parameters('dockerEngineDownloadRepo'),' ubuntu-xenial main\" | sudo tee /etc/apt/sources.list.d/docker.list\n- \"echo \\\"Package: docker-engine\\nPin: version ',parameters('dockerEngineVersion'),'\\nPin-Priority: 550\\n\\\" \u003e /etc/apt/preferences.d/docker.pref\"\n- retrycmd_if_failure apt-get update\n- retrycmd_if_failure apt-get install -y ebtables\n- retrycmd_if_failure apt-get install -y docker-engine\n- systemctl restart docker\n- mkdir -p /etc/kubernetes/manifests\n- usermod -aG docker ',parameters('linuxAdminUsername'),'\n- /usr/lib/apt/apt.systemd.daily\n- touch /opt/azure/containers/runcmd.complete\n'))]", "linuxConfiguration": { "disablePasswordAuthentication": "true", "ssh": { @@ -2191,7 +2191,7 @@ } }, "tags": { - "creationSource": "[concat('acsengine-', variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]", + "creationSource": "[concat('aksengine-', variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]", "orchestrator": "[variables('orchestratorNameVersionTag')]", "resourceNameSuffix": "[parameters('nameSuffix')]" }, diff --git a/pkg/acsengine/transform/transformtestfiles/k8s_scale_template.json b/pkg/engine/transform/transformtestfiles/k8s_scale_template.json similarity index 99% rename from pkg/acsengine/transform/transformtestfiles/k8s_scale_template.json rename to pkg/engine/transform/transformtestfiles/k8s_scale_template.json index a52ca27069..dd5dd16fa4 100644 --- a/pkg/acsengine/transform/transformtestfiles/k8s_scale_template.json +++ b/pkg/engine/transform/transformtestfiles/k8s_scale_template.json @@ -807,7 +807,7 @@ "type": "string" }, "generatorCode": { - "defaultValue": "acsengine", + "defaultValue": "aksengine", "metadata": { "description": "The generator code used to identify the generator" }, @@ -1763,7 +1763,7 @@ } }, "tags": { - "creationSource": "[concat('acsengine-', variables('agentppol1VMNamePrefix'), copyIndex(variables('agentppol1Offset')))]", + "creationSource": "[concat('aksengine-', variables('agentppol1VMNamePrefix'), copyIndex(variables('agentppol1Offset')))]", "orchestrator": "[variables('orchestratorNameVersionTag')]", "poolName": "agentppol1", "resourceNameSuffix": "[parameters('nameSuffix')]" @@ -1902,7 +1902,7 @@ } }, "tags": { - "creationSource": "[concat('acsengine-', variables('agentpool2VMNamePrefix'), copyIndex(variables('agentpool2Offset')))]", + "creationSource": "[concat('aksengine-', variables('agentpool2VMNamePrefix'), copyIndex(variables('agentpool2Offset')))]", "orchestrator": "[variables('orchestratorNameVersionTag')]", "poolName": "agentpool2", "resourceNameSuffix": "[parameters('nameSuffix')]" @@ -2180,7 +2180,7 @@ } }, "tags": { - "creationSource": "[concat('acsengine-', variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]", + "creationSource": "[concat('aksengine-', variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]", "orchestrator": "[variables('orchestratorNameVersionTag')]", "resourceNameSuffix": "[parameters('nameSuffix')]" }, diff --git a/pkg/acsengine/transform/transformtestfiles/k8s_template.json b/pkg/engine/transform/transformtestfiles/k8s_template.json similarity index 99% rename from pkg/acsengine/transform/transformtestfiles/k8s_template.json rename to pkg/engine/transform/transformtestfiles/k8s_template.json index da37cd7792..67f5b89caf 100644 --- a/pkg/acsengine/transform/transformtestfiles/k8s_template.json +++ b/pkg/engine/transform/transformtestfiles/k8s_template.json @@ -786,7 +786,7 @@ "type": "string" }, "generatorCode": { - "defaultValue": "acsengine", + "defaultValue": "aksengine", "metadata": { "description": "The generator code used to identify the generator" }, @@ -1766,7 +1766,7 @@ } }, "tags": { - "creationSource": "[concat('acsengine-', variables('agentppol1VMNamePrefix'), copyIndex(variables('agentppol1Offset')))]", + "creationSource": "[concat('aksengine-', variables('agentppol1VMNamePrefix'), copyIndex(variables('agentppol1Offset')))]", "orchestrator": "[variables('orchestratorNameVersionTag')]", "poolName": "agentppol1", "resourceNameSuffix": "[parameters('nameSuffix')]" @@ -1908,7 +1908,7 @@ } }, "tags": { - "creationSource": "[concat('acsengine-', variables('agentpool2VMNamePrefix'), copyIndex(variables('agentpool2Offset')))]", + "creationSource": "[concat('aksengine-', variables('agentpool2VMNamePrefix'), copyIndex(variables('agentpool2Offset')))]", "orchestrator": "[variables('orchestratorNameVersionTag')]", "poolName": "agentpool2", "resourceNameSuffix": "[parameters('nameSuffix')]" @@ -2247,7 +2247,7 @@ "osProfile": { "adminUsername": "[parameters('linuxAdminUsername')]", "computername": "[concat(variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]", - "customData": "[base64(concat('#cloud-config\n\npackages:\n - etcd\n - jq\n - traceroute\n\nwrite_files:\n- path: \"/etc/systemd/system/docker.service.d/clear_mount_propagation_flags.conf\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n [Service]\n MountFlags=shared\n\n- path: \"/etc/systemd/system/docker.service.d/exec_start.conf\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n [Service]\n ExecStart=\n ExecStart=/usr/bin/docker daemon -H fd:// --storage-driver=overlay --bip=',parameters('dockerBridgeCidr'),'\n\n- path: \"/etc/docker/daemon.json\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n {\n \"live-restore\": true,\n \"log-driver\": \"json-file\",\n \"log-opts\": {\n \"max-size\": \"50m\",\n \"max-file\": \"5\"\n }\n }\n\n- path: \"/etc/kubernetes/certs/ca.crt\"\n permissions: \"0644\"\n encoding: \"base64\"\n owner: \"root\"\n content: |\n ',parameters('caCertificate'),'\n\n- path: \"/etc/kubernetes/certs/apiserver.crt\"\n permissions: \"0644\"\n encoding: \"base64\"\n owner: \"root\"\n content: |\n ',parameters('apiServerCertificate'),'\n\n- path: \"/etc/kubernetes/certs/client.crt\"\n permissions: \"0644\"\n encoding: \"base64\"\n owner: \"root\"\n content: |\n ',parameters('clientCertificate'),'\n\n- path: \"/var/lib/kubelet/kubeconfig\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n apiVersion: v1\n kind: Config\n clusters:\n - name: localcluster\n cluster:\n certificate-authority: /etc/kubernetes/certs/ca.crt\n server: ',concat('https://', variables('masterPrivateIpAddrs')[copyIndex(variables('masterOffset'))], ':443'),'\n users:\n - name: client\n user:\n client-certificate: /etc/kubernetes/certs/client.crt\n client-key: /etc/kubernetes/certs/client.key\n contexts:\n - context:\n cluster: localcluster\n user: client\n name: localclustercontext\n current-context: localclustercontext\n\n- path: /etc/kubernetes/manifests/kube-apiserver.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/6RUy27jOgzd5ysMr6O67S1wC6MuUPQWuAXaTqYBZs9IjKOJXkPRLjJfP5DzttMHMMlKOjxH5CFNCPoHUtTelVneXuSjpXaqzPKJV/nIIoMChnKUZQ4sllm+bGYoIOiI1CLlGyAGkDs0riKjTZCBGZqY2FnGGqnMpHdM3ohgwGF3L70N3qHjMjvWHsWAMnEXPvIL8punZZkxNYmXdEA7pI26eD+/9NMW6oTeJJgcMsb/VwEpHacB5e02UHprIRmwOSflvFhsY/PD68Er3a0QoKyOyVGxqbZ62Vr0pOcoV9Lg+Elbza/gaqTxFKnVEu+k9I3j8X84h8bwlD1BjfcGYhy/YvQNSfzeeIbBe4owxur8rPv3UWP8mwikW22wRtWDtYsoG0IRPHF1fX7d5x/CV1f/9FBpfKNEIN9qhVTB74bwZIj0bq7rqkCWxb4JRUc4+xm9GzzbeSKkaSIjCR0EJbeqroUbx+61otseEVkqse5LrBbMoSyKi8t/O28uyhsLSe6Bpbo3Gh1PPPFJiV+Np8YKQlBVGrqB6S0S64g7+w9m627yOO0yeJz0tdlEIZFYzLXBgR0JicVusM4k8Ql+aiYwiiWuviazxNWgKal4IeEjAQknEtg2BtbT+jdJxPWEixnIJTpVJd8vezFtdXV0c+Dyg4OZwdcZ7D/f1pvG4nNKbLMYjpYDshR7/l43y2yiTIAXZZb3CsmHOi2QMHrWaRnkd4VaoMLoWTGI2ynZqD9lvwHU6Lh4Bgc1qkeFjjWvxBSZtauP6kjj+s2Z1W5Rrh3pb8nTRqRF2z2+EwwfOPKZG++rnbRlK2ej/rLA5878CQAA//8KCj673wYAAA==\n\n- path: /etc/kubernetes/manifests/kube-controller-manager.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/6SUTW/bPAyA7/kVhu+q8b5Ho+6l6PtxSBe0w+6MxLpaJNGjaHfZrx/oJE3jxMuA+Wbq4UOJ+oDOf0HOnlJdlMNf5WLjk6uLckWuXEQUcCBQL4oiQcS6KDf9Go2lJEwhIJsICVrkck/kDuw7lrdZMOpQgDWGrJqiEI9cF3uF6QIkHOOWYkcJk9TFTJFF7tCq5JWyPKK8EW/qQrhXgeLgE/K+jPmNGevnI7SK3SrHCQXzf9sOWX+fO7R3B9BSjKC92f9ribJ6PbDlx/B8uXHYGM2wlF5821QDcBX8utJYQKmOY5MkCIEsCJpEDo31jnNzewg+ksN7Dd1NsmzosyCPfDOu8n4XUXoO1t41txH0559vLq0YX/z3c5p6ZzqmwTvkBn70jBeRw1JRbHXsczUm3HzNlCZZTCTGgnnxAc+yLLLkysKNZZmZfvZt8qk1iv6xZIPbK44NbieOjDx4iwaspT6J6dgPunNXXNB5zUS+oAwIDtlgQCuNHvqT8Q/H9yHBOuDTGux0v4bm70lkPEmRkhdi0zJYNB2yJ9d8EN4Lh2XLesKWO/RfJVcjOK3RkTM4eCuekhEfkXq5IFuRe9hTn3fQVMTUCxrWq2B98DAKZyf3pPTTCTyZ30Chj7jU7cgnl3j/TqBYc9QeJ1MUUXNWIK91UU72rTz3DMAm+LXZX+dZ0eTan5ti9tdy3wBaTFItx0fG/e8wiZeteUYRn9qTVTCC+5TC9v3F3DVk+lxeboO+uGPxd2H3i35c68W87WJTzhtyXXC9Mz8DAAD//8PhLmf6BgAA\n\n- path: /etc/kubernetes/manifests/kube-scheduler.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/4SSQY/bIBCF7/kViDtC7RE1PbeHbVdaqfcxTG0UGBCMvfK/r0ideOMka988b97HzNNA9n+wVJ/ICDl9kYeTJ2eEfE1OHiIyOGAwByEIIhohT2OHqtoB3RiwyEWoGeyqzpUxNilAh6E2txDssRhhE3FJQeUAhOe6TTEnQmIjbtmHmtE275Aq/0J+T+VkBJex+RoHPGFZ6Or5fO3zEfqmfmtyIWSsP+aMpf2+ZbTfL402xQjkzPLbwFIPl1b5sXz3yLmqVGu0if76/qgnKDr4TrdaQNartjEFBIdFYUDLx7bjRp+OXy+VKYUx4ksaievHOZcAkK1at1wxQsRmeQUejJAa2epHbVfOBEUF36ll9KegzYr3pFj9nvcdoEdi/QIEPbqfDok9z+oNmT31N1sUBPebwnw9hf95bO/gcQztlM6PX4H5kzz2snhOexjKfSD7gP1k/gUAAP//FKERJ8EDAAA=\n\n- path: /etc/kubernetes/manifests/kube-addon-manager.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/4yRsW7zMAyEdz8Fkd3w/w9ZhKJAxw5pAwTozkiEIySiXJFy4LcvZMdOWjRtR5LH43cSdv6NkvjIBvr/1dGzM7CNrgqk6FDRVACMgQwc855qdC5yHZCxpXQZSYd2nssgSqEC6G9cpSNbfA5R9IX0HNPRgKZMFYCNrOiZkhRF/dMtAB+wJQMPZZyYlOSpaDaTZNeRfRx1iSTmZGn0nBrvmUSXGsB22cA6LHWgENNgYP1v48dmH0850CZmntdmuJFLLpuhCLaoBwOrhtQ2V7ZmEq4WBnSvfBqW6FfHIP47ux5Tc/L75ozYEmsz5XTPjli9DvWOVD239y9MGT697A18+Y7x1GW9+y3FV9x7Bn/n/ggAAP//ovMbJ38CAAA=\n\n- path: /etc/kubernetes/addons/kube-dns-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8xXS2/jNhC+61cQ7pl+JMhuINQLBOugG2yTGnXa+4QcW0QokuHDjffXF5RkWS+7dg7FyidzOA9+38xHCYz4G60TWqVkO0teheIpWaHdCoZ3jOmgfJKjBw4e0oQQBTmm5DW8IOXKVQvOANuvup3zmCeESHhB6aIPKSxWoUc3FnrCZHAeLXVlmpSMvA04KnYC51rloGCDdtx2yzXHlPyJTCsmJCaU0uRU+a26W9XcOgrGtI5xSY3tnSUi38MLLp5WFyDkDLJYT5XpYZmS2XQcf7NpQojR1hf10irivs5oSMnNdfnHaq+Zlin5a7Fsb6aemVMOz1+jg0OJzGt7DJkuyGCMm2xnL+hhD/cCjdS7HDud8jH+h7nZ1hxfTXsQ08PiCZgtGikYuJRc9Y6dg2fZ7416j9XRq8RjbiR4rOI0jl80s1Lagxda1XEJcSxDHiTaMUiTQafJmRVeMJDUaJ6S0ahyk63ijpd3CdQDxyFkD1dR/notlPC7Q1qj+Z3y4q5niI2Fa7QW+SJYoTar8pRCbR42StfL9+/IQgSk6UrJPyg2mY8DMG2sl/mqXM9o87RlrFBZtahsPgWt9+/GonNtDg6ZX3GX7tHsmQnRBi3E4ORBDZi3IAMOxC0id5kpH6+Nlnqz+14kbpGVaedjFyf7nTImb1Ze1fu1apK7KJbuDyV3Sb/g+3fhfN22WoYcG3E6I8S0WotNHaX8+wimebSesB1yxiJBpiQ2V1KH8CAU2kZSsJsGWJSMKOU6B6HmVZ+OpWYgx6POHuVoFLH5bDq9ue4Yt/OrzkpZPOXCziedAx52ihw2mJJfDwxUCr4yyL7U26TYokLnlla/YBOMNQgZLD5nFl2mJU/JTcOaeW9+Q99uDAM+S8lokiFIn/2gMTVXbtTp+CjWt9Pb9iBE0Yjof3t+XjYMcTIEyAVK2K3ixchdSj41XV1gDJ1r1DlrWL3IUQdfux7OcCC7yXV9Ke3hrlleFnUXBPVaJuJfENuSi/bFdXFAz8yJoOXlVj4WgYtBEk/SVLsdIWj2YYKup2dRYNHpYFlbX6TIhe8oTo65truUzD5PH0XDYvEtoOvuZiYUuOaDMVohStV4jC+BLdZPiwchefRYFjh2J/CUFjBgGVInfmCc9GlnrJWmERG57azHqw3tfHb1uXx5+mVIJapNE6EocG7HYA1MznQxn87ZLvWGroEJKfxuTk8JzeJp9QjurS00dWPn4N7Onrfh2bh8zI7P2H9M1zCPOZ8rJ7V+DaZ5xXFcQ5B+7LZs3BJ8UkNLvkw4bicqSNnBN1g5r6Wzwqkr/B/PmxaUnpm9J9zFluKGisLdWX8LAv2pfojvRN/K0P/f5dNDkPx0l09V6tnD0Kn72GVwoajeXKCpw5LaiMCVW2op2C5+NRVNWRlc64v7aehNS2mO/Xfd+CHW+YTQLiVSqPCe/BsAAP//MQMKdd0PAAA=\n\n- path: /etc/kubernetes/addons/kube-proxy-daemonset.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/5RUzW7bPBC8+ykI3RkmVyH+gA9ugV7aBgjQ+5qa2ET4oy6Xrv32BaU6kpzETXkSZoezszsCqXc/wNml2CocBbF+ZnO420LobvXsYteqT4SQ4iNkFSDUkVC7UsrTFj7XL6WeyxYcIcg3LhnrSxawzuCDs2hVI1zQDEybQp8iorTDJd1zOp6Gijhwq2LqsFIqUsAFo0K5J3vG8ykLwir3sNWEIPSeBKOhudF65mav23hlRalzi/FiFHIR/CKmq1ig2E3qWjVmf+rBVbuZwcs2WjVaV4pN8cnt1uZAbLzbmop5iJlqzfLSecPWdby+r7TNiGxcx/9dkJ9AUhh6R4K8/nzswS4gCvkNO3GW/EPq/o8xCYlLcT2FVY8LtKsR3k8ZfzmP9tjDzrq9Edp4GDkVtpgFUMGfBVkWmFK2L626u70NL2iGLezktElRcJQ5vWd3cB47dK2qrl9Kh+RLwNdU4lxfq1CRB5J9qxoDsSZnbyxYcjOTHefI2euhpPcpy8I4dd+jP130fEN9WtlreYjVU/2f5T/yq8wTGWt/a1Mn/Qb5lfh5gY/7nP3ylThYmafxx1rJbPKeGMbSsEH35CwtlnBlw9e1PzL2O0NfF34vrith1ffhER5WEk+S9eG8Wb6HKbfKu1iOq98BAAD//028PJBvBQAA\n\n- path: /etc/kubernetes/addons/kubernetes-dashboard-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8xUQW/bPAy9+1cQuTtt8V1a4cOArgV6GQqjGXanJS7RIouCRGf1fv0gt3HsJE2DYQWmk0DRj4+Pj8Zgv1FMlr2CzVWxtt4oWFDcWE23WnPrpWhI0KCgKgAc1uRSvgGsr1OJIShYtzVFT0KpNJhWNWM0LxnDw9zyhXZtEopleoFXMJPY0qzPRGPYN+hxSXE+/axhQwqeSLPX1lEB4LGhN6vmxxRQv2aUqUtCTVGWZTFuNtao59jKiqP9hWLZz9fXfb3NVU2CWy3uXkg/saPP1hvrlxM9TlL5B8SK7OiJvmcOGOxD5Dac6L0AOOh6aHLLCE1jfZHa+gdpSaoo4ahr/s6Y9j35thnPVu+9SfwJ7RRIZx6Bo/SEyv6q4PqyrykYlyRVH7q5vMnBRI60cDzPHtIFUvDIhjLIgUz0LOTzNe3Z956C466hU2v8MUv6sUJHCs5qTAquDrRsUPTqy6jDM+SlJjgUegUYKZWPm2Cds8tbmvlo9oLWUxwQSsC4TAoGQNvgkhT8v8O738ItAulP08Sqda5iZ3Wn4Nb9xC4N785uyFNKVeSadoQBViLhgWQcAggoKwWzi9k0OnbpUNhbsejuyWG3yFM2ScF/4wyxDXErxx5PDnpXdKRwuVOtOkYnRBbW7BR8vate42ny/3l8r6ZnQ4uJb/LJu7NnbU4KnPXtMxS/AwAA//+MY7+tLgcAAA==\n\n- path: /etc/kubernetes/addons/kube-heapster-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8xWW2tjNxB+P79C+F1ep92AK+pCmk3bh2Y3JFAoLISxNOujWrfq4rX31xfpHNvnYgcTNlC9WGdGo2/mm4sMTv6FPkhrGNlcVWtpBCNP6DeS4w3nNplYaYwgIAKrCDGgkZEawYWIvhUEBxwZWacl0rALEXVFiIIlqpBtSNF4gxHDVNp3XKVsTEMDw8gk+oSTchKEsEaDgRX6ad9MW4GMPCK3hkuFFaW06rrvl8CnkGJtvfwGUVozXc+L5eZqiRH20d028I9W4YnQGv/ZPkL6VcaaGjBm93Yx3ZmQPN5tZYih8klhYBUl4OTv3iZX8CjBbUSTIw3lE5zLG4/BJs+xPSTQKbvTaGJWbtAvW8UKY/lVMjSbrxB5XXbJCYhYtq4IR9CTyRgJNy0IPZZA+2lFu3NWXObGd0jlr9IIaVb/y4xahY/4JYPsiX0hxIqQcZ1eEEtIy3+Qx1I6J9v48uYdpmM4GHokv47B/snGsT/6jl3iaXDIM7SzPrYllreMzGcFJoJfYXxoRfMfKkICKuTR+tbjeaDgXAcrB99E++HQTD02jo14qMazfIxuf8s6e2EYD/jc0+bRKckhMHI1YkbnzvyzE8zpcCJqpyBia9QhIi/Vsz9HCCFgjI2lCzqHA69RJIV+CsrVMCCAexklB0WdFawZUYTsAyu5twp9/05K1rhj5LY1vcn0hk9G7Q6Y1mUb6xk5kFru7bXSx2F15sWtiSAN+g6a1LBCRn4+er6v8SeH/JcDKrdagxHH0CmZvNvfP+lKKW2m8KJDRkhag989g5Ps8+Tz5GgwaqNm9Ub5UfhvwhB7MkK4S7lzdE+oUVu/Y+Tq/exedjRKavnqC06xVRL0iEF+u4gxZ8VzGYYDyrhLi/lMD6S4jR6Kbja9HiobDxfFwZN27YH3I3WsPYbaKrG4HmiOj/PiTG4PNXTugLNKUYdeWrH4cZbX0LkQpc4FvMCtswZNlKDOFcThFXxdWVyfyepPF1bFRfZoNt0kb0Al/M1b3b/vi0Ql2jd2JH+AWLPDaJpmDjrHGkru/35++PTh+ePN/d33Rysj+SXIp4eb2z1u/vv01JvEeeV3ZjAAbWBESZO21X8BAAD//0SxZ2rFCwAA\n\n- path: /etc/kubernetes/addons/azure-storage-classes.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8yQTUs0MRCE7/kVzd4zL3t7ydWrgrjgVXon5RJmkgzdnQH99TIfLqhXFzx3nkrVw1N6hmiqJZBaFb6gG/5rl+q/+XiG8dENqcRAp+14N7KqyzCObBwcUeGMQBGv3EZzRFxKNbZUiy5n+oztF7JbIruhnSEFhvWfpH6n/fom0MGk4eCIRj5j3GO+Qv3Y1CBeIXPqcWUmqXNa5kDCN4Tfm8DHpIPz3rvfWp658AXRT4KcWv5p4FYjJhbOMMiavXV92Mq4q3Xu+9qK2duEQI9bxZf7p9NNFKhxiSzxLzs47R1XCR8BAAD//1fQzbL+AgAA\n\n- path: /etc/kubernetes/addons/kube-tiller-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8yUW0scPxjG7+dTvHg/q8tf4U8oBasigsriSm9LNvPUTc2pyZvB7acvM9sZ52BFC4XmapL38PzyJBkZ9GfEpL0TVC+LR+0qQWvEWiucKuWz48KCZSVZioLISQtBrI1B/DVNQSoIeswblGmXGLYgMnIDk5oKaiPRgZEW2h8qkxMjlmkvIuiAY8ZBUZZlMaSJG6kWMvPWR/1DsvZu8fh/26FebsCygz3b97vzBp+0q7R7eA34/VzRG9zha1Mig76MPodX4AqiGVZP0UnIympXpLz5BsVJFCW96Ptb3Z46Nz3HkR9DA2QIgrYwtp1NxN7qz7iwrBCM3/0eNgWoRj34yC1GORduYoKOj5f/HbdzlvEBvGpX+7QEA8U+vmErvAvoT+RqNTMMTwzXfKbJ3TpvN2MxeQT/iocMG4xk7EmGhM0YUs5JX6TtGrffo8t4O00lUt6x1A6x1ygJrn4W7E72/ur6+uLuy+3pzcV6dXp20ScQ1dLk2b9jP7SVDxD04dnB+1Z9HaA+9llG13BIaRX9BmLQecscLsHDJaIgeSvosCsax/pLdzJY106zluYcRu7WUN5VSdBykMDawmd+ITZzt1NJQ4t6F1eTS/9KkwhZ6Xfvuq/6u9uOSD5HhTSEiPiekTiNwVTIgk6O7GjRwvq4E7Q8ObrRg4jRVv9xA+crrEc/jGY0T30xfqE+CTLa5afiZwAAAP//2LvwXhoHAAA=\n\n\n\n- path: \"/etc/systemd/system/kubectl-extract.service\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n [Unit]\n Description=Kubectl extraction\n Requires=docker.service\n After=docker.service\n ConditionPathExists=!/usr/local/bin/kubectl\n\n [Service]\n TimeoutStartSec=0\n Restart=on-failure\n RestartSec=5s\n ExecStartPre=/bin/mkdir -p /tmp/kubectldir\n ExecStartPre=/usr/bin/docker pull ',parameters('kubernetesHyperkubeSpec'),'\n ExecStartPre=/usr/bin/docker run --rm -v /tmp/kubectldir:/opt/kubectldir ',parameters('kubernetesHyperkubeSpec'),' /bin/bash -c \"cp /hyperkube /opt/kubectldir/\"\n ExecStartPre=/bin/mv /tmp/kubectldir/hyperkube /usr/local/bin/kubectl\n ExecStart=/bin/chmod a+x /usr/local/bin/kubectl\n\n [Install]\n WantedBy=multi-user.target\n\n- path: \"/etc/default/kubelet\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n KUBELET_CLUSTER_DNS=',parameters('kubeDNSServiceIP'),'\n KUBELET_API_SERVERS=',concat('https://', variables('masterPrivateIpAddrs')[copyIndex(variables('masterOffset'))], ':443'),'\n KUBELET_IMAGE=',parameters('kubernetesHyperkubeSpec'),'\n KUBELET_NETWORK_PLUGIN=\n DOCKER_OPTS=\n KUBELET_REGISTER_WITH_TAINTS=',variables('registerWithTaints'),'\n KUBELET_NODE_LABELS=role=master\n KUBELET_POD_INFRA_CONTAINER_IMAGE=',parameters('kubernetesPodInfraContainerSpec'),'\n \n- path: \"/etc/systemd/system/kubelet.service\"\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/5RVX2/bNhB/16cg3D5sD7SaNNg6F3pwYiUz4tqZZaMY0sCgxbPEhSK149Gut/a7D5KVxLKdYYMAgfzd/e4/yfu5UfQQDMClqEpS1kS3fgkaKJjCn14huEja9BGw6wDXKoWgvyLAQzC4T3arh2AKjgRSJPRGbF0Qm7VCawowdK00RCFQGkpYCa8pfGx8JT5Nwbn4q6KEBHkXnV28D+KvkCaVrTuEKFwqEy6Fy1loSwrFXx4hTK0hoQygezLVdfkJXvEoFTJesnAtMNRq+ez5FR88ZR21Yvfs7Q+F9YbYN5YhlOxL59DClw77xjYp4/pHxjWwd+yBfWSUg2E71zWd86Uy8sj9MfCRrVTnVAaNmUI8Ane5QDi2Frxhs1w5phwTrBRISmi2sfgo0HojGVlGldyXjhBEwapWowGCiuM89II3jOVEpeuFYaYo98tuaova/k5vf1lTXHhx9svZT2/qTWqLqs/8/dn5xfmHn9+fHSTiqkzc1qWkGd8wA9RV5fqiS2m5QCBU4M6jD20S37FgSWKpwTFOzIiqElo5Oqmqyn9XjULvsC7qbogZesO+BIxxboCi3DpqtqWSrS2qtdKQgWwALJrF2mpfQBRKWPeq3wHstq5X/9AeSKoOoje95wVuTmhUPd7FGvYOgNcJzVDsMRqk14zPCZrNes+LI8PVwd1rf+8AOE7O4bpNaAMV4e1gcnUbTxeTu1nySh4bITIwFH4SRmQghxIMKdryBIiUyVzvv2s2ETL29u/b+WU8imeL4af+Tfy9gRkL820JWMXInk7kk6iKrcJSa1YqO67zi6xFwd01yl8Rl1ZyZVYo+PNdxlUhMog6L0HeTQaL4fh62l9cTcaz/nAcT5vAOy1jQkoE56J33fpry7S2m70Rjgg9tDTAVMeGV1c64CmJhKXPMmUyngsjNaA7SqUQRq3AES8F5Ucj8yRt81LtHQFyaVz0kvPVaJ7M4uliME6+n1a3hVAmarZdbVOhDyqfqVrTpTlIr6sc9hxM45th7SG5+jUezEf9y1Hc9mSsBK7FErTb78Z4MogXo/5lPEoO6p9q6yUv0a6VBIzqN+qEwtMEHVSnVu/+4axpN66C96ZjlxZu/6eZXCgsleGFlRCVaAvlUm+940tUMmuHaYCqZ4OX2mfK7NVsHM8+T6a3i7vR/GY4PlEtV7/e3JdSEPBVNfxg0m10UL1k1p/Nk8X8btCfxYvrafzbPB5f/d42uI7O9w7qddyfzafx4qY/i5PvQXA/NI6E1g/BZ2EI5OU2Krwmxb0D7JLADCj4JwAA//9Myf113wgAAA==\n\n- path: \"/opt/azure/containers/kubelet.sh\"\n permissions: \"0755\"\n owner: \"root\"\n content: |\n #!/bin/bash\n set -e\n\n\n # Azure does not support two LoadBalancers(LB) sharing the same nic and backend port.\n # As a workaround, the Internal LB(ILB) listens for apiserver traffic on port 4443 and the External LB(ELB) on port 443\n # This IPTable rule then redirects ILB traffic to port 443 in the prerouting chain\n iptables -t nat -A PREROUTING -p tcp --dport 4443 -j REDIRECT --to-port 443\n\n\n sed -i \"s||',parameters('kubernetesAddonManagerSpec'),'|g\" \"/etc/kubernetes/manifests/kube-addon-manager.yaml\"\n sed -i \"s||',parameters('kubernetesHyperkubeSpec'),'|g; s||',parameters('kubeServiceCidr'),'|g; s||',variables('masterEtcdClientPort'),'|g; s||',variables('kubernetesAPIServerIP'),'|g\" \"/etc/kubernetes/manifests/kube-apiserver.yaml\"\n sed -i \"s||',parameters('kubernetesHyperkubeSpec'),'|g; s||',variables('masterFqdnPrefix'),'|g; s||',variables('allocateNodeCidrs'),'|g; s||',parameters('kubeClusterCidr'),'|g; s||',variables('kubernetesCtrlMgrNodeMonitorGracePeriod'),'|g; s||',variables('kubernetesCtrlMgrPodEvictionTimeout'),'|g; s||',variables('kubernetesCtrlMgrRouteReconciliationPeriod'),'|g\" \"/etc/kubernetes/manifests/kube-controller-manager.yaml\"\n sed -i \"s||',parameters('kubernetesHyperkubeSpec'),'|g\" \"/etc/kubernetes/manifests/kube-scheduler.yaml\"\n sed -i \"s||',parameters('kubernetesHyperkubeSpec'),'|g; s||',parameters('kubeClusterCidr'),'|g\" \"/etc/kubernetes/addons/kube-proxy-daemonset.yaml\"\n sed -i \"s||',parameters('kubernetesKubeDNSSpec'),'|g; s||',parameters('kubernetesDNSMasqSpec'),'|g; s||',parameters('kubernetesExecHealthzSpec'),'|g\" \"/etc/kubernetes/addons/kube-dns-deployment.yaml\"\n sed -i \"s||',parameters('kubernetesHeapsterSpec'),'|g; s||',parameters('kubernetesAddonResizerSpec'),'|g\" \"/etc/kubernetes/addons/kube-heapster-deployment.yaml\"\n sed -i \"s||',parameters('kubernetesDashboardSpec'),'|g\" \"/etc/kubernetes/addons/kubernetes-dashboard-deployment.yaml\"\n sed -i \"s||',parameters('kubernetesTillerSpec'),'|g\" \"/etc/kubernetes/addons/kube-tiller-deployment.yaml\"\n\n\n sed -i \"//d\" \"/etc/kubernetes/manifests/kube-apiserver.yaml\"\n sed -i \"//d\" \"/etc/kubernetes/manifests/kube-controller-manager.yaml\"\n\n\n\n\n- path: \"/opt/azure/containers/provision.sh\"\n permissions: \"0744\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n ',variables('provisionScript'),'\n\n- path: \"/opt/azure/containers/mountetcd.sh\"\n permissions: \"0744\"\n owner: \"root\"\n content: |\n #!/bin/bash\n # Mounting is done here instead of etcd because of bug https://bugs.launchpad.net/cloud-init/+bug/1692093\n # Once the bug is fixed, replace the below with the cloud init changes replaced in https://github.com/Azure/acs-engine/pull/661.\n set -x\n DISK=/dev/sdc\n PARTITION=${DISK}1\n MOUNTPOINT=/var/lib/etcddisk\n udevadm settle\n mkdir -p $MOUNTPOINT\n mount | grep $MOUNTPOINT\n if [ $? -eq 0 ]\n then\n echo \"disk is already mounted\"\n exit 0\n fi\n # fill /etc/fstab\n grep \"/dev/sdc1\" /etc/fstab\n if [ $? -ne 0 ]\n then\n echo \"$PARTITION $MOUNTPOINT auto defaults,nofail 0 2\" >> /etc/fstab\n fi\n # check if partition exists\n ls $PARTITION\n if [ $? -ne 0 ]\n then\n # partition does not exist\n /sbin/sgdisk --new 1 $DISK\n /sbin/mkfs.ext4 $PARTITION -L etcd_disk -F -E lazy_itable_init=1,lazy_journal_init=1\n fi\n mount $MOUNTPOINT\n\nruncmd:\n- /bin/echo DAEMON_ARGS=--name \"',variables('masterVMNames')[copyIndex(variables('masterOffset'))],'\" --initial-advertise-peer-urls \"',variables('masterEtcdPeerURLs')[copyIndex(variables('masterOffset'))],'\" --listen-peer-urls \"',variables('masterEtcdPeerURLs')[copyIndex(variables('masterOffset'))],'\" --advertise-client-urls \"',variables('masterEtcdClientURLs')[copyIndex(variables('masterOffset'))],'\" --listen-client-urls \"',concat(variables('masterEtcdClientURLs')[copyIndex(variables('masterOffset'))], ',http://127.0.0.1:', variables('masterEtcdClientPort')),'\" --initial-cluster-token \"k8s-etcd-cluster\" --initial-cluster \"',variables('masterEtcdClusterStates')[div(variables('masterCount'), 2)],' --data-dir \"/var/lib/etcddisk\"\" --initial-cluster-state \"new\" | tee -a /etc/default/etcd\n- sudo /bin/chown -R etcd:etcd /var/lib/etcd/default\n- /opt/azure/containers/mountetcd.sh\n- sudo /bin/chown -R etcd:etcd /var/lib/etcddisk\n- systemctl stop etcd\n- sudo -u etcd rm -rf /var/lib/etcd/default\n- systemctl restart etcd\n- for i in $(seq 1 20); do curl --max-time 60 http://127.0.0.1:2379/v2/machines; [ $? -eq 0 ] && break || sleep 5; done\n- retrycmd_if_failure() { for i in 1 2 3 4 5; do $@; [ $? -eq 0 ] && break || sleep 5; done ; }\n- retrycmd_if_failure apt-get update\n- retrycmd_if_failure apt-get install -y apt-transport-https ca-certificates\n- retrycmd_if_failure curl --max-time 60 -fsSL https://aptdocker.azureedge.net/gpg | apt-key add -\n- echo \"deb ',parameters('dockerEngineDownloadRepo'),' ubuntu-xenial main\" | sudo tee /etc/apt/sources.list.d/docker.list\n- \"echo \\\"Package: docker-engine\\nPin: version ',parameters('dockerEngineVersion'),'\\nPin-Priority: 550\\n\\\" > /etc/apt/preferences.d/docker.pref\"\n- retrycmd_if_failure apt-get update\n- retrycmd_if_failure apt-get install -y ebtables\n- retrycmd_if_failure apt-get install -y docker-engine\n- systemctl restart docker\n- mkdir -p /etc/kubernetes/manifests\n- usermod -aG docker ',parameters('linuxAdminUsername'),'\n- /usr/lib/apt/apt.systemd.daily\n- touch /opt/azure/containers/runcmd.complete\n'))]", + "customData": "[base64(concat('#cloud-config\n\npackages:\n - etcd\n - jq\n - traceroute\n\nwrite_files:\n- path: \"/etc/systemd/system/docker.service.d/clear_mount_propagation_flags.conf\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n [Service]\n MountFlags=shared\n\n- path: \"/etc/systemd/system/docker.service.d/exec_start.conf\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n [Service]\n ExecStart=\n ExecStart=/usr/bin/docker daemon -H fd:// --storage-driver=overlay --bip=',parameters('dockerBridgeCidr'),'\n\n- path: \"/etc/docker/daemon.json\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n {\n \"live-restore\": true,\n \"log-driver\": \"json-file\",\n \"log-opts\": {\n \"max-size\": \"50m\",\n \"max-file\": \"5\"\n }\n }\n\n- path: \"/etc/kubernetes/certs/ca.crt\"\n permissions: \"0644\"\n encoding: \"base64\"\n owner: \"root\"\n content: |\n ',parameters('caCertificate'),'\n\n- path: \"/etc/kubernetes/certs/apiserver.crt\"\n permissions: \"0644\"\n encoding: \"base64\"\n owner: \"root\"\n content: |\n ',parameters('apiServerCertificate'),'\n\n- path: \"/etc/kubernetes/certs/client.crt\"\n permissions: \"0644\"\n encoding: \"base64\"\n owner: \"root\"\n content: |\n ',parameters('clientCertificate'),'\n\n- path: \"/var/lib/kubelet/kubeconfig\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n apiVersion: v1\n kind: Config\n clusters:\n - name: localcluster\n cluster:\n certificate-authority: /etc/kubernetes/certs/ca.crt\n server: ',concat('https://', variables('masterPrivateIpAddrs')[copyIndex(variables('masterOffset'))], ':443'),'\n users:\n - name: client\n user:\n client-certificate: /etc/kubernetes/certs/client.crt\n client-key: /etc/kubernetes/certs/client.key\n contexts:\n - context:\n cluster: localcluster\n user: client\n name: localclustercontext\n current-context: localclustercontext\n\n- path: /etc/kubernetes/manifests/kube-apiserver.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/6RUy27jOgzd5ysMr6O67S1wC6MuUPQWuAXaTqYBZs9IjKOJXkPRLjJfP5DzttMHMMlKOjxH5CFNCPoHUtTelVneXuSjpXaqzPKJV/nIIoMChnKUZQ4sllm+bGYoIOiI1CLlGyAGkDs0riKjTZCBGZqY2FnGGqnMpHdM3ohgwGF3L70N3qHjMjvWHsWAMnEXPvIL8punZZkxNYmXdEA7pI26eD+/9NMW6oTeJJgcMsb/VwEpHacB5e02UHprIRmwOSflvFhsY/PD68Er3a0QoKyOyVGxqbZ62Vr0pOcoV9Lg+Elbza/gaqTxFKnVEu+k9I3j8X84h8bwlD1BjfcGYhy/YvQNSfzeeIbBe4owxur8rPv3UWP8mwikW22wRtWDtYsoG0IRPHF1fX7d5x/CV1f/9FBpfKNEIN9qhVTB74bwZIj0bq7rqkCWxb4JRUc4+xm9GzzbeSKkaSIjCR0EJbeqroUbx+61otseEVkqse5LrBbMoSyKi8t/O28uyhsLSe6Bpbo3Gh1PPPFJiV+Np8YKQlBVGrqB6S0S64g7+w9m627yOO0yeJz0tdlEIZFYzLXBgR0JicVusM4k8Ql+aiYwiiWuviazxNWgKal4IeEjAQknEtg2BtbT+jdJxPWEixnIJTpVJd8vezFtdXV0c+Dyg4OZwdcZ7D/f1pvG4nNKbLMYjpYDshR7/l43y2yiTIAXZZb3CsmHOi2QMHrWaRnkd4VaoMLoWTGI2ynZqD9lvwHU6Lh4Bgc1qkeFjjWvxBSZtauP6kjj+s2Z1W5Rrh3pb8nTRqRF2z2+EwwfOPKZG++rnbRlK2ej/rLA5878CQAA//8KCj673wYAAA==\n\n- path: /etc/kubernetes/manifests/kube-controller-manager.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/6SUTW/bPAyA7/kVhu+q8b5Ho+6l6PtxSBe0w+6MxLpaJNGjaHfZrx/oJE3jxMuA+Wbq4UOJ+oDOf0HOnlJdlMNf5WLjk6uLckWuXEQUcCBQL4oiQcS6KDf9Go2lJEwhIJsICVrkck/kDuw7lrdZMOpQgDWGrJqiEI9cF3uF6QIkHOOWYkcJk9TFTJFF7tCq5JWyPKK8EW/qQrhXgeLgE/K+jPmNGevnI7SK3SrHCQXzf9sOWX+fO7R3B9BSjKC92f9ribJ6PbDlx/B8uXHYGM2wlF5821QDcBX8utJYQKmOY5MkCIEsCJpEDo31jnNzewg+ksN7Dd1NsmzosyCPfDOu8n4XUXoO1t41txH0559vLq0YX/z3c5p6ZzqmwTvkBn70jBeRw1JRbHXsczUm3HzNlCZZTCTGgnnxAc+yLLLkysKNZZmZfvZt8qk1iv6xZIPbK44NbieOjDx4iwaspT6J6dgPunNXXNB5zUS+oAwIDtlgQCuNHvqT8Q/H9yHBOuDTGux0v4bm70lkPEmRkhdi0zJYNB2yJ9d8EN4Lh2XLesKWO/RfJVcjOK3RkTM4eCuekhEfkXq5IFuRe9hTn3fQVMTUCxrWq2B98DAKZyf3pPTTCTyZ30Chj7jU7cgnl3j/TqBYc9QeJ1MUUXNWIK91UU72rTz3DMAm+LXZX+dZ0eTan5ti9tdy3wBaTFItx0fG/e8wiZeteUYRn9qTVTCC+5TC9v3F3DVk+lxeboO+uGPxd2H3i35c68W87WJTzhtyXXC9Mz8DAAD//8PhLmf6BgAA\n\n- path: /etc/kubernetes/manifests/kube-scheduler.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/4SSQY/bIBCF7/kViDtC7RE1PbeHbVdaqfcxTG0UGBCMvfK/r0ideOMka988b97HzNNA9n+wVJ/ICDl9kYeTJ2eEfE1OHiIyOGAwByEIIhohT2OHqtoB3RiwyEWoGeyqzpUxNilAh6E2txDssRhhE3FJQeUAhOe6TTEnQmIjbtmHmtE275Aq/0J+T+VkBJex+RoHPGFZ6Or5fO3zEfqmfmtyIWSsP+aMpf2+ZbTfL402xQjkzPLbwFIPl1b5sXz3yLmqVGu0if76/qgnKDr4TrdaQNartjEFBIdFYUDLx7bjRp+OXy+VKYUx4ksaievHOZcAkK1at1wxQsRmeQUejJAa2epHbVfOBEUF36ll9KegzYr3pFj9nvcdoEdi/QIEPbqfDok9z+oNmT31N1sUBPebwnw9hf95bO/gcQztlM6PX4H5kzz2snhOexjKfSD7gP1k/gUAAP//FKERJ8EDAAA=\n\n- path: /etc/kubernetes/manifests/kube-addon-manager.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/4yRsW7zMAyEdz8Fkd3w/w9ZhKJAxw5pAwTozkiEIySiXJFy4LcvZMdOWjRtR5LH43cSdv6NkvjIBvr/1dGzM7CNrgqk6FDRVACMgQwc855qdC5yHZCxpXQZSYd2nssgSqEC6G9cpSNbfA5R9IX0HNPRgKZMFYCNrOiZkhRF/dMtAB+wJQMPZZyYlOSpaDaTZNeRfRx1iSTmZGn0nBrvmUSXGsB22cA6LHWgENNgYP1v48dmH0850CZmntdmuJFLLpuhCLaoBwOrhtQ2V7ZmEq4WBnSvfBqW6FfHIP47ux5Tc/L75ozYEmsz5XTPjli9DvWOVD239y9MGT697A18+Y7x1GW9+y3FV9x7Bn/n/ggAAP//ovMbJ38CAAA=\n\n- path: /etc/kubernetes/addons/kube-dns-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8xXS2/jNhC+61cQ7pl+JMhuINQLBOugG2yTGnXa+4QcW0QokuHDjffXF5RkWS+7dg7FyidzOA9+38xHCYz4G60TWqVkO0teheIpWaHdCoZ3jOmgfJKjBw4e0oQQBTmm5DW8IOXKVQvOANuvup3zmCeESHhB6aIPKSxWoUc3FnrCZHAeLXVlmpSMvA04KnYC51rloGCDdtx2yzXHlPyJTCsmJCaU0uRU+a26W9XcOgrGtI5xSY3tnSUi38MLLp5WFyDkDLJYT5XpYZmS2XQcf7NpQojR1hf10irivs5oSMnNdfnHaq+Zlin5a7Fsb6aemVMOz1+jg0OJzGt7DJkuyGCMm2xnL+hhD/cCjdS7HDud8jH+h7nZ1hxfTXsQ08PiCZgtGikYuJRc9Y6dg2fZ7416j9XRq8RjbiR4rOI0jl80s1Lagxda1XEJcSxDHiTaMUiTQafJmRVeMJDUaJ6S0ahyk63ijpd3CdQDxyFkD1dR/notlPC7Q1qj+Z3y4q5niI2Fa7QW+SJYoTar8pRCbR42StfL9+/IQgSk6UrJPyg2mY8DMG2sl/mqXM9o87RlrFBZtahsPgWt9+/GonNtDg6ZX3GX7tHsmQnRBi3E4ORBDZi3IAMOxC0id5kpH6+Nlnqz+14kbpGVaedjFyf7nTImb1Ze1fu1apK7KJbuDyV3Sb/g+3fhfN22WoYcG3E6I8S0WotNHaX8+wimebSesB1yxiJBpiQ2V1KH8CAU2kZSsJsGWJSMKOU6B6HmVZ+OpWYgx6POHuVoFLH5bDq9ue4Yt/OrzkpZPOXCziedAx52ihw2mJJfDwxUCr4yyL7U26TYokLnlla/YBOMNQgZLD5nFl2mJU/JTcOaeW9+Q99uDAM+S8lokiFIn/2gMTVXbtTp+CjWt9Pb9iBE0Yjof3t+XjYMcTIEyAVK2K3ixchdSj41XV1gDJ1r1DlrWL3IUQdfux7OcCC7yXV9Ke3hrlleFnUXBPVaJuJfENuSi/bFdXFAz8yJoOXlVj4WgYtBEk/SVLsdIWj2YYKup2dRYNHpYFlbX6TIhe8oTo65truUzD5PH0XDYvEtoOvuZiYUuOaDMVohStV4jC+BLdZPiwchefRYFjh2J/CUFjBgGVInfmCc9GlnrJWmERG57azHqw3tfHb1uXx5+mVIJapNE6EocG7HYA1MznQxn87ZLvWGroEJKfxuTk8JzeJp9QjurS00dWPn4N7Onrfh2bh8zI7P2H9M1zCPOZ8rJ7V+DaZ5xXFcQ5B+7LZs3BJ8UkNLvkw4bicqSNnBN1g5r6Wzwqkr/B/PmxaUnpm9J9zFluKGisLdWX8LAv2pfojvRN/K0P/f5dNDkPx0l09V6tnD0Kn72GVwoajeXKCpw5LaiMCVW2op2C5+NRVNWRlc64v7aehNS2mO/Xfd+CHW+YTQLiVSqPCe/BsAAP//MQMKdd0PAAA=\n\n- path: /etc/kubernetes/addons/kube-proxy-daemonset.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/5RUzW7bPBC8+ykI3RkmVyH+gA9ugV7aBgjQ+5qa2ET4oy6Xrv32BaU6kpzETXkSZoezszsCqXc/wNml2CocBbF+ZnO420LobvXsYteqT4SQ4iNkFSDUkVC7UsrTFj7XL6WeyxYcIcg3LhnrSxawzuCDs2hVI1zQDEybQp8iorTDJd1zOp6Gijhwq2LqsFIqUsAFo0K5J3vG8ykLwir3sNWEIPSeBKOhudF65mav23hlRalzi/FiFHIR/CKmq1ig2E3qWjVmf+rBVbuZwcs2WjVaV4pN8cnt1uZAbLzbmop5iJlqzfLSecPWdby+r7TNiGxcx/9dkJ9AUhh6R4K8/nzswS4gCvkNO3GW/EPq/o8xCYlLcT2FVY8LtKsR3k8ZfzmP9tjDzrq9Edp4GDkVtpgFUMGfBVkWmFK2L626u70NL2iGLezktElRcJQ5vWd3cB47dK2qrl9Kh+RLwNdU4lxfq1CRB5J9qxoDsSZnbyxYcjOTHefI2euhpPcpy8I4dd+jP130fEN9WtlreYjVU/2f5T/yq8wTGWt/a1Mn/Qb5lfh5gY/7nP3ylThYmafxx1rJbPKeGMbSsEH35CwtlnBlw9e1PzL2O0NfF34vrith1ffhER5WEk+S9eG8Wb6HKbfKu1iOq98BAAD//028PJBvBQAA\n\n- path: /etc/kubernetes/addons/kubernetes-dashboard-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8xUQW/bPAy9+1cQuTtt8V1a4cOArgV6GQqjGXanJS7RIouCRGf1fv0gt3HsJE2DYQWmk0DRj4+Pj8Zgv1FMlr2CzVWxtt4oWFDcWE23WnPrpWhI0KCgKgAc1uRSvgGsr1OJIShYtzVFT0KpNJhWNWM0LxnDw9zyhXZtEopleoFXMJPY0qzPRGPYN+hxSXE+/axhQwqeSLPX1lEB4LGhN6vmxxRQv2aUqUtCTVGWZTFuNtao59jKiqP9hWLZz9fXfb3NVU2CWy3uXkg/saPP1hvrlxM9TlL5B8SK7OiJvmcOGOxD5Dac6L0AOOh6aHLLCE1jfZHa+gdpSaoo4ahr/s6Y9j35thnPVu+9SfwJ7RRIZx6Bo/SEyv6q4PqyrykYlyRVH7q5vMnBRI60cDzPHtIFUvDIhjLIgUz0LOTzNe3Z956C466hU2v8MUv6sUJHCs5qTAquDrRsUPTqy6jDM+SlJjgUegUYKZWPm2Cds8tbmvlo9oLWUxwQSsC4TAoGQNvgkhT8v8O738ItAulP08Sqda5iZ3Wn4Nb9xC4N785uyFNKVeSadoQBViLhgWQcAggoKwWzi9k0OnbpUNhbsejuyWG3yFM2ScF/4wyxDXErxx5PDnpXdKRwuVOtOkYnRBbW7BR8vate42ny/3l8r6ZnQ4uJb/LJu7NnbU4KnPXtMxS/AwAA//+MY7+tLgcAAA==\n\n- path: /etc/kubernetes/addons/kube-heapster-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8xWW2tjNxB+P79C+F1ep92AK+pCmk3bh2Y3JFAoLISxNOujWrfq4rX31xfpHNvnYgcTNlC9WGdGo2/mm4sMTv6FPkhrGNlcVWtpBCNP6DeS4w3nNplYaYwgIAKrCDGgkZEawYWIvhUEBxwZWacl0rALEXVFiIIlqpBtSNF4gxHDVNp3XKVsTEMDw8gk+oSTchKEsEaDgRX6ad9MW4GMPCK3hkuFFaW06rrvl8CnkGJtvfwGUVozXc+L5eZqiRH20d028I9W4YnQGv/ZPkL6VcaaGjBm93Yx3ZmQPN5tZYih8klhYBUl4OTv3iZX8CjBbUSTIw3lE5zLG4/BJs+xPSTQKbvTaGJWbtAvW8UKY/lVMjSbrxB5XXbJCYhYtq4IR9CTyRgJNy0IPZZA+2lFu3NWXObGd0jlr9IIaVb/y4xahY/4JYPsiX0hxIqQcZ1eEEtIy3+Qx1I6J9v48uYdpmM4GHokv47B/snGsT/6jl3iaXDIM7SzPrYllreMzGcFJoJfYXxoRfMfKkICKuTR+tbjeaDgXAcrB99E++HQTD02jo14qMazfIxuf8s6e2EYD/jc0+bRKckhMHI1YkbnzvyzE8zpcCJqpyBia9QhIi/Vsz9HCCFgjI2lCzqHA69RJIV+CsrVMCCAexklB0WdFawZUYTsAyu5twp9/05K1rhj5LY1vcn0hk9G7Q6Y1mUb6xk5kFru7bXSx2F15sWtiSAN+g6a1LBCRn4+er6v8SeH/JcDKrdagxHH0CmZvNvfP+lKKW2m8KJDRkhag989g5Ps8+Tz5GgwaqNm9Ub5UfhvwhB7MkK4S7lzdE+oUVu/Y+Tq/exedjRKavnqC06xVRL0iEF+u4gxZ8VzGYYDyrhLi/lMD6S4jR6Kbja9HiobDxfFwZN27YH3I3WsPYbaKrG4HmiOj/PiTG4PNXTugLNKUYdeWrH4cZbX0LkQpc4FvMCtswZNlKDOFcThFXxdWVyfyepPF1bFRfZoNt0kb0Al/M1b3b/vi0Ql2jd2JH+AWLPDaJpmDjrHGkru/35++PTh+ePN/d33Rysj+SXIp4eb2z1u/vv01JvEeeV3ZjAAbWBESZO21X8BAAD//0SxZ2rFCwAA\n\n- path: /etc/kubernetes/addons/azure-storage-classes.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8yQTUs0MRCE7/kVzd4zL3t7ydWrgrjgVXon5RJmkgzdnQH99TIfLqhXFzx3nkrVw1N6hmiqJZBaFb6gG/5rl+q/+XiG8dENqcRAp+14N7KqyzCObBwcUeGMQBGv3EZzRFxKNbZUiy5n+oztF7JbIruhnSEFhvWfpH6n/fom0MGk4eCIRj5j3GO+Qv3Y1CBeIXPqcWUmqXNa5kDCN4Tfm8DHpIPz3rvfWp658AXRT4KcWv5p4FYjJhbOMMiavXV92Mq4q3Xu+9qK2duEQI9bxZf7p9NNFKhxiSzxLzs47R1XCR8BAAD//1fQzbL+AgAA\n\n- path: /etc/kubernetes/addons/kube-tiller-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8yUW0scPxjG7+dTvHg/q8tf4U8oBasigsriSm9LNvPUTc2pyZvB7acvM9sZ52BFC4XmapL38PzyJBkZ9GfEpL0TVC+LR+0qQWvEWiucKuWz48KCZSVZioLISQtBrI1B/DVNQSoIeswblGmXGLYgMnIDk5oKaiPRgZEW2h8qkxMjlmkvIuiAY8ZBUZZlMaSJG6kWMvPWR/1DsvZu8fh/26FebsCygz3b97vzBp+0q7R7eA34/VzRG9zha1Mig76MPodX4AqiGVZP0UnIympXpLz5BsVJFCW96Ptb3Z46Nz3HkR9DA2QIgrYwtp1NxN7qz7iwrBCM3/0eNgWoRj34yC1GORduYoKOj5f/HbdzlvEBvGpX+7QEA8U+vmErvAvoT+RqNTMMTwzXfKbJ3TpvN2MxeQT/iocMG4xk7EmGhM0YUs5JX6TtGrffo8t4O00lUt6x1A6x1ygJrn4W7E72/ur6+uLuy+3pzcV6dXp20ScQ1dLk2b9jP7SVDxD04dnB+1Z9HaA+9llG13BIaRX9BmLQecscLsHDJaIgeSvosCsax/pLdzJY106zluYcRu7WUN5VSdBykMDawmd+ITZzt1NJQ4t6F1eTS/9KkwhZ6Xfvuq/6u9uOSD5HhTSEiPiekTiNwVTIgk6O7GjRwvq4E7Q8ObrRg4jRVv9xA+crrEc/jGY0T30xfqE+CTLa5afiZwAAAP//2LvwXhoHAAA=\n\n\n\n- path: \"/etc/systemd/system/kubectl-extract.service\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n [Unit]\n Description=Kubectl extraction\n Requires=docker.service\n After=docker.service\n ConditionPathExists=!/usr/local/bin/kubectl\n\n [Service]\n TimeoutStartSec=0\n Restart=on-failure\n RestartSec=5s\n ExecStartPre=/bin/mkdir -p /tmp/kubectldir\n ExecStartPre=/usr/bin/docker pull ',parameters('kubernetesHyperkubeSpec'),'\n ExecStartPre=/usr/bin/docker run --rm -v /tmp/kubectldir:/opt/kubectldir ',parameters('kubernetesHyperkubeSpec'),' /bin/bash -c \"cp /hyperkube /opt/kubectldir/\"\n ExecStartPre=/bin/mv /tmp/kubectldir/hyperkube /usr/local/bin/kubectl\n ExecStart=/bin/chmod a+x /usr/local/bin/kubectl\n\n [Install]\n WantedBy=multi-user.target\n\n- path: \"/etc/default/kubelet\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n KUBELET_CLUSTER_DNS=',parameters('kubeDNSServiceIP'),'\n KUBELET_API_SERVERS=',concat('https://', variables('masterPrivateIpAddrs')[copyIndex(variables('masterOffset'))], ':443'),'\n KUBELET_IMAGE=',parameters('kubernetesHyperkubeSpec'),'\n KUBELET_NETWORK_PLUGIN=\n DOCKER_OPTS=\n KUBELET_REGISTER_WITH_TAINTS=',variables('registerWithTaints'),'\n KUBELET_NODE_LABELS=role=master\n KUBELET_POD_INFRA_CONTAINER_IMAGE=',parameters('kubernetesPodInfraContainerSpec'),'\n \n- path: \"/etc/systemd/system/kubelet.service\"\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/5RVX2/bNhB/16cg3D5sD7SaNNg6F3pwYiUz4tqZZaMY0sCgxbPEhSK149Gut/a7D5KVxLKdYYMAgfzd/e4/yfu5UfQQDMClqEpS1kS3fgkaKJjCn14huEja9BGw6wDXKoWgvyLAQzC4T3arh2AKjgRSJPRGbF0Qm7VCawowdK00RCFQGkpYCa8pfGx8JT5Nwbn4q6KEBHkXnV28D+KvkCaVrTuEKFwqEy6Fy1loSwrFXx4hTK0hoQygezLVdfkJXvEoFTJesnAtMNRq+ez5FR88ZR21Yvfs7Q+F9YbYN5YhlOxL59DClw77xjYp4/pHxjWwd+yBfWSUg2E71zWd86Uy8sj9MfCRrVTnVAaNmUI8Ane5QDi2Frxhs1w5phwTrBRISmi2sfgo0HojGVlGldyXjhBEwapWowGCiuM89II3jOVEpeuFYaYo98tuaova/k5vf1lTXHhx9svZT2/qTWqLqs/8/dn5xfmHn9+fHSTiqkzc1qWkGd8wA9RV5fqiS2m5QCBU4M6jD20S37FgSWKpwTFOzIiqElo5Oqmqyn9XjULvsC7qbogZesO+BIxxboCi3DpqtqWSrS2qtdKQgWwALJrF2mpfQBRKWPeq3wHstq5X/9AeSKoOoje95wVuTmhUPd7FGvYOgNcJzVDsMRqk14zPCZrNes+LI8PVwd1rf+8AOE7O4bpNaAMV4e1gcnUbTxeTu1nySh4bITIwFH4SRmQghxIMKdryBIiUyVzvv2s2ETL29u/b+WU8imeL4af+Tfy9gRkL820JWMXInk7kk6iKrcJSa1YqO67zi6xFwd01yl8Rl1ZyZVYo+PNdxlUhMog6L0HeTQaL4fh62l9cTcaz/nAcT5vAOy1jQkoE56J33fpry7S2m70Rjgg9tDTAVMeGV1c64CmJhKXPMmUyngsjNaA7SqUQRq3AES8F5Ucj8yRt81LtHQFyaVz0kvPVaJ7M4uliME6+n1a3hVAmarZdbVOhDyqfqVrTpTlIr6sc9hxM45th7SG5+jUezEf9y1Hc9mSsBK7FErTb78Z4MogXo/5lPEoO6p9q6yUv0a6VBIzqN+qEwtMEHVSnVu/+4axpN66C96ZjlxZu/6eZXCgsleGFlRCVaAvlUm+940tUMmuHaYCqZ4OX2mfK7NVsHM8+T6a3i7vR/GY4PlEtV7/e3JdSEPBVNfxg0m10UL1k1p/Nk8X8btCfxYvrafzbPB5f/d42uI7O9w7qddyfzafx4qY/i5PvQXA/NI6E1g/BZ2EI5OU2Krwmxb0D7JLADCj4JwAA//9Myf113wgAAA==\n\n- path: \"/opt/azure/containers/kubelet.sh\"\n permissions: \"0755\"\n owner: \"root\"\n content: |\n #!/bin/bash\n set -e\n\n\n # Azure does not support two LoadBalancers(LB) sharing the same nic and backend port.\n # As a workaround, the Internal LB(ILB) listens for apiserver traffic on port 4443 and the External LB(ELB) on port 443\n # This IPTable rule then redirects ILB traffic to port 443 in the prerouting chain\n iptables -t nat -A PREROUTING -p tcp --dport 4443 -j REDIRECT --to-port 443\n\n\n sed -i \"s||',parameters('kubernetesAddonManagerSpec'),'|g\" \"/etc/kubernetes/manifests/kube-addon-manager.yaml\"\n sed -i \"s||',parameters('kubernetesHyperkubeSpec'),'|g; s||',parameters('kubeServiceCidr'),'|g; s||',variables('masterEtcdClientPort'),'|g; s||',variables('kubernetesAPIServerIP'),'|g\" \"/etc/kubernetes/manifests/kube-apiserver.yaml\"\n sed -i \"s||',parameters('kubernetesHyperkubeSpec'),'|g; s||',variables('masterFqdnPrefix'),'|g; s||',variables('allocateNodeCidrs'),'|g; s||',parameters('kubeClusterCidr'),'|g; s||',variables('kubernetesCtrlMgrNodeMonitorGracePeriod'),'|g; s||',variables('kubernetesCtrlMgrPodEvictionTimeout'),'|g; s||',variables('kubernetesCtrlMgrRouteReconciliationPeriod'),'|g\" \"/etc/kubernetes/manifests/kube-controller-manager.yaml\"\n sed -i \"s||',parameters('kubernetesHyperkubeSpec'),'|g\" \"/etc/kubernetes/manifests/kube-scheduler.yaml\"\n sed -i \"s||',parameters('kubernetesHyperkubeSpec'),'|g; s||',parameters('kubeClusterCidr'),'|g\" \"/etc/kubernetes/addons/kube-proxy-daemonset.yaml\"\n sed -i \"s||',parameters('kubernetesKubeDNSSpec'),'|g; s||',parameters('kubernetesDNSMasqSpec'),'|g; s||',parameters('kubernetesExecHealthzSpec'),'|g\" \"/etc/kubernetes/addons/kube-dns-deployment.yaml\"\n sed -i \"s||',parameters('kubernetesHeapsterSpec'),'|g; s||',parameters('kubernetesAddonResizerSpec'),'|g\" \"/etc/kubernetes/addons/kube-heapster-deployment.yaml\"\n sed -i \"s||',parameters('kubernetesDashboardSpec'),'|g\" \"/etc/kubernetes/addons/kubernetes-dashboard-deployment.yaml\"\n sed -i \"s||',parameters('kubernetesTillerSpec'),'|g\" \"/etc/kubernetes/addons/kube-tiller-deployment.yaml\"\n\n\n sed -i \"//d\" \"/etc/kubernetes/manifests/kube-apiserver.yaml\"\n sed -i \"//d\" \"/etc/kubernetes/manifests/kube-controller-manager.yaml\"\n\n\n\n\n- path: \"/opt/azure/containers/provision.sh\"\n permissions: \"0744\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n ',variables('provisionScript'),'\n\n- path: \"/opt/azure/containers/mountetcd.sh\"\n permissions: \"0744\"\n owner: \"root\"\n content: |\n #!/bin/bash\n # Mounting is done here instead of etcd because of bug https://bugs.launchpad.net/cloud-init/+bug/1692093\n # Once the bug is fixed, replace the below with the cloud init changes replaced in https://github.com/Azure/aks-engine/pull/661.\n set -x\n DISK=/dev/sdc\n PARTITION=${DISK}1\n MOUNTPOINT=/var/lib/etcddisk\n udevadm settle\n mkdir -p $MOUNTPOINT\n mount | grep $MOUNTPOINT\n if [ $? -eq 0 ]\n then\n echo \"disk is already mounted\"\n exit 0\n fi\n # fill /etc/fstab\n grep \"/dev/sdc1\" /etc/fstab\n if [ $? -ne 0 ]\n then\n echo \"$PARTITION $MOUNTPOINT auto defaults,nofail 0 2\" >> /etc/fstab\n fi\n # check if partition exists\n ls $PARTITION\n if [ $? -ne 0 ]\n then\n # partition does not exist\n /sbin/sgdisk --new 1 $DISK\n /sbin/mkfs.ext4 $PARTITION -L etcd_disk -F -E lazy_itable_init=1,lazy_journal_init=1\n fi\n mount $MOUNTPOINT\n\nruncmd:\n- /bin/echo DAEMON_ARGS=--name \"',variables('masterVMNames')[copyIndex(variables('masterOffset'))],'\" --initial-advertise-peer-urls \"',variables('masterEtcdPeerURLs')[copyIndex(variables('masterOffset'))],'\" --listen-peer-urls \"',variables('masterEtcdPeerURLs')[copyIndex(variables('masterOffset'))],'\" --advertise-client-urls \"',variables('masterEtcdClientURLs')[copyIndex(variables('masterOffset'))],'\" --listen-client-urls \"',concat(variables('masterEtcdClientURLs')[copyIndex(variables('masterOffset'))], ',http://127.0.0.1:', variables('masterEtcdClientPort')),'\" --initial-cluster-token \"k8s-etcd-cluster\" --initial-cluster \"',variables('masterEtcdClusterStates')[div(variables('masterCount'), 2)],' --data-dir \"/var/lib/etcddisk\"\" --initial-cluster-state \"new\" | tee -a /etc/default/etcd\n- sudo /bin/chown -R etcd:etcd /var/lib/etcd/default\n- /opt/azure/containers/mountetcd.sh\n- sudo /bin/chown -R etcd:etcd /var/lib/etcddisk\n- systemctl stop etcd\n- sudo -u etcd rm -rf /var/lib/etcd/default\n- systemctl restart etcd\n- for i in $(seq 1 20); do curl --max-time 60 http://127.0.0.1:2379/v2/machines; [ $? -eq 0 ] && break || sleep 5; done\n- retrycmd_if_failure() { for i in 1 2 3 4 5; do $@; [ $? -eq 0 ] && break || sleep 5; done ; }\n- retrycmd_if_failure apt-get update\n- retrycmd_if_failure apt-get install -y apt-transport-https ca-certificates\n- retrycmd_if_failure curl --max-time 60 -fsSL https://aptdocker.azureedge.net/gpg | apt-key add -\n- echo \"deb ',parameters('dockerEngineDownloadRepo'),' ubuntu-xenial main\" | sudo tee /etc/apt/sources.list.d/docker.list\n- \"echo \\\"Package: docker-engine\\nPin: version ',parameters('dockerEngineVersion'),'\\nPin-Priority: 550\\n\\\" > /etc/apt/preferences.d/docker.pref\"\n- retrycmd_if_failure apt-get update\n- retrycmd_if_failure apt-get install -y ebtables\n- retrycmd_if_failure apt-get install -y docker-engine\n- systemctl restart docker\n- mkdir -p /etc/kubernetes/manifests\n- usermod -aG docker ',parameters('linuxAdminUsername'),'\n- /usr/lib/apt/apt.systemd.daily\n- touch /opt/azure/containers/runcmd.complete\n'))]", "linuxConfiguration": { "disablePasswordAuthentication": "true", "ssh": { @@ -2282,7 +2282,7 @@ } }, "tags": { - "creationSource": "[concat('acsengine-', variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]", + "creationSource": "[concat('aksengine-', variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]", "orchestrator": "[variables('orchestratorNameVersionTag')]", "resourceNameSuffix": "[parameters('nameSuffix')]" }, diff --git a/pkg/acsengine/transform/transformtestfiles/k8s_vnet_scale_template.json b/pkg/engine/transform/transformtestfiles/k8s_vnet_scale_template.json similarity index 99% rename from pkg/acsengine/transform/transformtestfiles/k8s_vnet_scale_template.json rename to pkg/engine/transform/transformtestfiles/k8s_vnet_scale_template.json index e912b6f468..9753cc6720 100644 --- a/pkg/acsengine/transform/transformtestfiles/k8s_vnet_scale_template.json +++ b/pkg/engine/transform/transformtestfiles/k8s_vnet_scale_template.json @@ -805,7 +805,7 @@ "type": "string" }, "generatorCode": { - "defaultValue": "acsengine", + "defaultValue": "aksengine", "metadata": { "description": "The generator code used to identify the generator" }, @@ -1759,7 +1759,7 @@ } }, "tags": { - "creationSource": "[concat('acsengine-', variables('agentpriVMNamePrefix'), copyIndex(variables('agentpriOffset')))]", + "creationSource": "[concat('aksengine-', variables('agentpriVMNamePrefix'), copyIndex(variables('agentpriOffset')))]", "orchestrator": "[variables('orchestratorNameVersionTag')]", "poolName": "agentpri", "resourceNameSuffix": "[parameters('nameSuffix')]" @@ -1901,7 +1901,7 @@ } }, "tags": { - "creationSource": "[concat('acsengine-', variables('agentpri2VMNamePrefix'), copyIndex(variables('agentpri2Offset')))]", + "creationSource": "[concat('aksengine-', variables('agentpri2VMNamePrefix'), copyIndex(variables('agentpri2Offset')))]", "orchestrator": "[variables('orchestratorNameVersionTag')]", "poolName": "agentpri2", "resourceNameSuffix": "[parameters('nameSuffix')]" @@ -2124,7 +2124,7 @@ } }, "tags": { - "creationSource": "[concat('acsengine-', variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]", + "creationSource": "[concat('aksengine-', variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]", "orchestrator": "[variables('orchestratorNameVersionTag')]", "resourceNameSuffix": "[parameters('nameSuffix')]" }, diff --git a/pkg/acsengine/transform/transformtestfiles/k8s_vnet_template.json b/pkg/engine/transform/transformtestfiles/k8s_vnet_template.json similarity index 99% rename from pkg/acsengine/transform/transformtestfiles/k8s_vnet_template.json rename to pkg/engine/transform/transformtestfiles/k8s_vnet_template.json index f326901bbf..4a5e8bad05 100644 --- a/pkg/acsengine/transform/transformtestfiles/k8s_vnet_template.json +++ b/pkg/engine/transform/transformtestfiles/k8s_vnet_template.json @@ -784,7 +784,7 @@ "type": "string" }, "generatorCode": { - "defaultValue": "acsengine", + "defaultValue": "aksengine", "metadata": { "description": "The generator code used to identify the generator" }, @@ -1762,7 +1762,7 @@ } }, "tags": { - "creationSource": "[concat('acsengine-', variables('agentpriVMNamePrefix'), copyIndex(variables('agentpriOffset')))]", + "creationSource": "[concat('aksengine-', variables('agentpriVMNamePrefix'), copyIndex(variables('agentpriOffset')))]", "orchestrator": "[variables('orchestratorNameVersionTag')]", "poolName": "agentpri", "resourceNameSuffix": "[parameters('nameSuffix')]" @@ -1907,7 +1907,7 @@ } }, "tags": { - "creationSource": "[concat('acsengine-', variables('agentpri2VMNamePrefix'), copyIndex(variables('agentpri2Offset')))]", + "creationSource": "[concat('aksengine-', variables('agentpri2VMNamePrefix'), copyIndex(variables('agentpri2Offset')))]", "orchestrator": "[variables('orchestratorNameVersionTag')]", "poolName": "agentpri2", "resourceNameSuffix": "[parameters('nameSuffix')]" @@ -2157,7 +2157,7 @@ "osProfile": { "adminUsername": "[parameters('linuxAdminUsername')]", "computername": "[concat(variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]", - "customData": "[base64(concat('#cloud-config\n\npackages:\n - etcd\n - jq\n - traceroute\n\nwrite_files:\n- path: \"/etc/systemd/system/docker.service.d/clear_mount_propagation_flags.conf\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n [Service]\n MountFlags=shared\n\n- path: \"/etc/systemd/system/docker.service.d/exec_start.conf\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n [Service]\n ExecStart=\n ExecStart=/usr/bin/docker daemon -H fd:// --storage-driver=overlay --bip=',parameters('dockerBridgeCidr'),'\n\n- path: \"/etc/docker/daemon.json\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n {\n \"live-restore\": true,\n \"log-driver\": \"json-file\",\n \"log-opts\": {\n \"max-size\": \"50m\",\n \"max-file\": \"5\"\n }\n }\n\n- path: \"/etc/kubernetes/certs/ca.crt\"\n permissions: \"0644\"\n encoding: \"base64\"\n owner: \"root\"\n content: |\n ',parameters('caCertificate'),'\n\n- path: \"/etc/kubernetes/certs/apiserver.crt\"\n permissions: \"0644\"\n encoding: \"base64\"\n owner: \"root\"\n content: |\n ',parameters('apiServerCertificate'),'\n\n- path: \"/etc/kubernetes/certs/client.crt\"\n permissions: \"0644\"\n encoding: \"base64\"\n owner: \"root\"\n content: |\n ',parameters('clientCertificate'),'\n\n- path: \"/var/lib/kubelet/kubeconfig\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n apiVersion: v1\n kind: Config\n clusters:\n - name: localcluster\n cluster:\n certificate-authority: /etc/kubernetes/certs/ca.crt\n server: ',concat('https://', variables('masterPrivateIpAddrs')[copyIndex(variables('masterOffset'))], ':443'),'\n users:\n - name: client\n user:\n client-certificate: /etc/kubernetes/certs/client.crt\n client-key: /etc/kubernetes/certs/client.key\n contexts:\n - context:\n cluster: localcluster\n user: client\n name: localclustercontext\n current-context: localclustercontext\n\n- path: /etc/kubernetes/manifests/kube-apiserver.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/6RUy27jOgzd5ysMr6O67S1wC6MuUPQWuAXaTqYBZs9IjKOJXkPRLjJfP5DzttMHMMlKOjxH5CFNCPoHUtTelVneXuSjpXaqzPKJV/nIIoMChnKUZQ4sllm+bGYoIOiI1CLlGyAGkDs0riKjTZCBGZqY2FnGGqnMpHdM3ohgwGF3L70N3qHjMjvWHsWAMnEXPvIL8punZZkxNYmXdEA7pI26eD+/9NMW6oTeJJgcMsb/VwEpHacB5e02UHprIRmwOSflvFhsY/PD68Er3a0QoKyOyVGxqbZ62Vr0pOcoV9Lg+Elbza/gaqTxFKnVEu+k9I3j8X84h8bwlD1BjfcGYhy/YvQNSfzeeIbBe4owxur8rPv3UWP8mwikW22wRtWDtYsoG0IRPHF1fX7d5x/CV1f/9FBpfKNEIN9qhVTB74bwZIj0bq7rqkCWxb4JRUc4+xm9GzzbeSKkaSIjCR0EJbeqroUbx+61otseEVkqse5LrBbMoSyKi8t/O28uyhsLSe6Bpbo3Gh1PPPFJiV+Np8YKQlBVGrqB6S0S64g7+w9m627yOO0yeJz0tdlEIZFYzLXBgR0JicVusM4k8Ql+aiYwiiWuviazxNWgKal4IeEjAQknEtg2BtbT+jdJxPWEixnIJTpVJd8vezFtdXV0c+Dyg4OZwdcZ7D/f1pvG4nNKbLMYjpYDshR7/l43y2yiTIAXZZb3CsmHOi2QMHrWaRnkd4VaoMLoWTGI2ynZqD9lvwHU6Lh4Bgc1qkeFjjWvxBSZtauP6kjj+s2Z1W5Rrh3pb8nTRqRF2z2+EwwfOPKZG++rnbRlK2ej/rLA5878CQAA//8KCj673wYAAA==\n\n- path: /etc/kubernetes/manifests/kube-controller-manager.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/6SUTW/bPAyA7/kVhu+q8b5Ho+6l6PtxSBe0w+6MxLpaJNGjaHfZrx/oJE3jxMuA+Wbq4UOJ+oDOf0HOnlJdlMNf5WLjk6uLckWuXEQUcCBQL4oiQcS6KDf9Go2lJEwhIJsICVrkck/kDuw7lrdZMOpQgDWGrJqiEI9cF3uF6QIkHOOWYkcJk9TFTJFF7tCq5JWyPKK8EW/qQrhXgeLgE/K+jPmNGevnI7SK3SrHCQXzf9sOWX+fO7R3B9BSjKC92f9ribJ6PbDlx/B8uXHYGM2wlF5821QDcBX8utJYQKmOY5MkCIEsCJpEDo31jnNzewg+ksN7Dd1NsmzosyCPfDOu8n4XUXoO1t41txH0559vLq0YX/z3c5p6ZzqmwTvkBn70jBeRw1JRbHXsczUm3HzNlCZZTCTGgnnxAc+yLLLkysKNZZmZfvZt8qk1iv6xZIPbK44NbieOjDx4iwaspT6J6dgPunNXXNB5zUS+oAwIDtlgQCuNHvqT8Q/H9yHBOuDTGux0v4bm70lkPEmRkhdi0zJYNB2yJ9d8EN4Lh2XLesKWO/RfJVcjOK3RkTM4eCuekhEfkXq5IFuRe9hTn3fQVMTUCxrWq2B98DAKZyf3pPTTCTyZ30Chj7jU7cgnl3j/TqBYc9QeJ1MUUXNWIK91UU72rTz3DMAm+LXZX+dZ0eTan5ti9tdy3wBaTFItx0fG/e8wiZeteUYRn9qTVTCC+5TC9v3F3DVk+lxeboO+uGPxd2H3i35c68W87WJTzhtyXXC9Mz8DAAD//8PhLmf6BgAA\n\n- path: /etc/kubernetes/manifests/kube-scheduler.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/4SSQY/bIBCF7/kViDtC7RE1PbeHbVdaqfcxTG0UGBCMvfK/r0ideOMka988b97HzNNA9n+wVJ/ICDl9kYeTJ2eEfE1OHiIyOGAwByEIIhohT2OHqtoB3RiwyEWoGeyqzpUxNilAh6E2txDssRhhE3FJQeUAhOe6TTEnQmIjbtmHmtE275Aq/0J+T+VkBJex+RoHPGFZ6Or5fO3zEfqmfmtyIWSsP+aMpf2+ZbTfL402xQjkzPLbwFIPl1b5sXz3yLmqVGu0if76/qgnKDr4TrdaQNartjEFBIdFYUDLx7bjRp+OXy+VKYUx4ksaievHOZcAkK1at1wxQsRmeQUejJAa2epHbVfOBEUF36ll9KegzYr3pFj9nvcdoEdi/QIEPbqfDok9z+oNmT31N1sUBPebwnw9hf95bO/gcQztlM6PX4H5kzz2snhOexjKfSD7gP1k/gUAAP//FKERJ8EDAAA=\n\n- path: /etc/kubernetes/manifests/kube-addon-manager.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/4yRsW7zMAyEdz8Fkd3w/w9ZhKJAxw5pAwTozkiEIySiXJFy4LcvZMdOWjRtR5LH43cSdv6NkvjIBvr/1dGzM7CNrgqk6FDRVACMgQwc855qdC5yHZCxpXQZSYd2nssgSqEC6G9cpSNbfA5R9IX0HNPRgKZMFYCNrOiZkhRF/dMtAB+wJQMPZZyYlOSpaDaTZNeRfRx1iSTmZGn0nBrvmUSXGsB22cA6LHWgENNgYP1v48dmH0850CZmntdmuJFLLpuhCLaoBwOrhtQ2V7ZmEq4WBnSvfBqW6FfHIP47ux5Tc/L75ozYEmsz5XTPjli9DvWOVD239y9MGT697A18+Y7x1GW9+y3FV9x7Bn/n/ggAAP//ovMbJ38CAAA=\n\n- path: /etc/kubernetes/addons/kube-dns-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8xXS2/jNhC+61cQ7pl+JMhuINQLBOugG2yTGnXa+4QcW0QokuHDjffXF5RkWS+7dg7FyidzOA9+38xHCYz4G60TWqVkO0teheIpWaHdCoZ3jOmgfJKjBw4e0oQQBTmm5DW8IOXKVQvOANuvup3zmCeESHhB6aIPKSxWoUc3FnrCZHAeLXVlmpSMvA04KnYC51rloGCDdtx2yzXHlPyJTCsmJCaU0uRU+a26W9XcOgrGtI5xSY3tnSUi38MLLp5WFyDkDLJYT5XpYZmS2XQcf7NpQojR1hf10irivs5oSMnNdfnHaq+Zlin5a7Fsb6aemVMOz1+jg0OJzGt7DJkuyGCMm2xnL+hhD/cCjdS7HDud8jH+h7nZ1hxfTXsQ08PiCZgtGikYuJRc9Y6dg2fZ7416j9XRq8RjbiR4rOI0jl80s1Lagxda1XEJcSxDHiTaMUiTQafJmRVeMJDUaJ6S0ahyk63ijpd3CdQDxyFkD1dR/notlPC7Q1qj+Z3y4q5niI2Fa7QW+SJYoTar8pRCbR42StfL9+/IQgSk6UrJPyg2mY8DMG2sl/mqXM9o87RlrFBZtahsPgWt9+/GonNtDg6ZX3GX7tHsmQnRBi3E4ORBDZi3IAMOxC0id5kpH6+Nlnqz+14kbpGVaedjFyf7nTImb1Ze1fu1apK7KJbuDyV3Sb/g+3fhfN22WoYcG3E6I8S0WotNHaX8+wimebSesB1yxiJBpiQ2V1KH8CAU2kZSsJsGWJSMKOU6B6HmVZ+OpWYgx6POHuVoFLH5bDq9ue4Yt/OrzkpZPOXCziedAx52ihw2mJJfDwxUCr4yyL7U26TYokLnlla/YBOMNQgZLD5nFl2mJU/JTcOaeW9+Q99uDAM+S8lokiFIn/2gMTVXbtTp+CjWt9Pb9iBE0Yjof3t+XjYMcTIEyAVK2K3ixchdSj41XV1gDJ1r1DlrWL3IUQdfux7OcCC7yXV9Ke3hrlleFnUXBPVaJuJfENuSi/bFdXFAz8yJoOXlVj4WgYtBEk/SVLsdIWj2YYKup2dRYNHpYFlbX6TIhe8oTo65truUzD5PH0XDYvEtoOvuZiYUuOaDMVohStV4jC+BLdZPiwchefRYFjh2J/CUFjBgGVInfmCc9GlnrJWmERG57azHqw3tfHb1uXx5+mVIJapNE6EocG7HYA1MznQxn87ZLvWGroEJKfxuTk8JzeJp9QjurS00dWPn4N7Onrfh2bh8zI7P2H9M1zCPOZ8rJ7V+DaZ5xXFcQ5B+7LZs3BJ8UkNLvkw4bicqSNnBN1g5r6Wzwqkr/B/PmxaUnpm9J9zFluKGisLdWX8LAv2pfojvRN/K0P/f5dNDkPx0l09V6tnD0Kn72GVwoajeXKCpw5LaiMCVW2op2C5+NRVNWRlc64v7aehNS2mO/Xfd+CHW+YTQLiVSqPCe/BsAAP//MQMKdd0PAAA=\n\n- path: /etc/kubernetes/addons/kube-proxy-daemonset.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/5RUzW7bPBC8+ykI3RkmVyH+gA9ugV7aBgjQ+5qa2ET4oy6Xrv32BaU6kpzETXkSZoezszsCqXc/wNml2CocBbF+ZnO420LobvXsYteqT4SQ4iNkFSDUkVC7UsrTFj7XL6WeyxYcIcg3LhnrSxawzuCDs2hVI1zQDEybQp8iorTDJd1zOp6Gijhwq2LqsFIqUsAFo0K5J3vG8ykLwir3sNWEIPSeBKOhudF65mav23hlRalzi/FiFHIR/CKmq1ig2E3qWjVmf+rBVbuZwcs2WjVaV4pN8cnt1uZAbLzbmop5iJlqzfLSecPWdby+r7TNiGxcx/9dkJ9AUhh6R4K8/nzswS4gCvkNO3GW/EPq/o8xCYlLcT2FVY8LtKsR3k8ZfzmP9tjDzrq9Edp4GDkVtpgFUMGfBVkWmFK2L626u70NL2iGLezktElRcJQ5vWd3cB47dK2qrl9Kh+RLwNdU4lxfq1CRB5J9qxoDsSZnbyxYcjOTHefI2euhpPcpy8I4dd+jP130fEN9WtlreYjVU/2f5T/yq8wTGWt/a1Mn/Qb5lfh5gY/7nP3ylThYmafxx1rJbPKeGMbSsEH35CwtlnBlw9e1PzL2O0NfF34vrith1ffhER5WEk+S9eG8Wb6HKbfKu1iOq98BAAD//028PJBvBQAA\n\n- path: /etc/kubernetes/addons/kubernetes-dashboard-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8xUQW/bPAy9+1cQuTtt8V1a4cOArgV6GQqjGXanJS7RIouCRGf1fv0gt3HsJE2DYQWmk0DRj4+Pj8Zgv1FMlr2CzVWxtt4oWFDcWE23WnPrpWhI0KCgKgAc1uRSvgGsr1OJIShYtzVFT0KpNJhWNWM0LxnDw9zyhXZtEopleoFXMJPY0qzPRGPYN+hxSXE+/axhQwqeSLPX1lEB4LGhN6vmxxRQv2aUqUtCTVGWZTFuNtao59jKiqP9hWLZz9fXfb3NVU2CWy3uXkg/saPP1hvrlxM9TlL5B8SK7OiJvmcOGOxD5Dac6L0AOOh6aHLLCE1jfZHa+gdpSaoo4ahr/s6Y9j35thnPVu+9SfwJ7RRIZx6Bo/SEyv6q4PqyrykYlyRVH7q5vMnBRI60cDzPHtIFUvDIhjLIgUz0LOTzNe3Z956C466hU2v8MUv6sUJHCs5qTAquDrRsUPTqy6jDM+SlJjgUegUYKZWPm2Cds8tbmvlo9oLWUxwQSsC4TAoGQNvgkhT8v8O738ItAulP08Sqda5iZ3Wn4Nb9xC4N785uyFNKVeSadoQBViLhgWQcAggoKwWzi9k0OnbpUNhbsejuyWG3yFM2ScF/4wyxDXErxx5PDnpXdKRwuVOtOkYnRBbW7BR8vate42ny/3l8r6ZnQ4uJb/LJu7NnbU4KnPXtMxS/AwAA//+MY7+tLgcAAA==\n\n- path: /etc/kubernetes/addons/kube-heapster-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8xWW2tjNxB+P79C+F1ep92AK+pCmk3bh2Y3JFAoLISxNOujWrfq4rX31xfpHNvnYgcTNlC9WGdGo2/mm4sMTv6FPkhrGNlcVWtpBCNP6DeS4w3nNplYaYwgIAKrCDGgkZEawYWIvhUEBxwZWacl0rALEXVFiIIlqpBtSNF4gxHDVNp3XKVsTEMDw8gk+oSTchKEsEaDgRX6ad9MW4GMPCK3hkuFFaW06rrvl8CnkGJtvfwGUVozXc+L5eZqiRH20d028I9W4YnQGv/ZPkL6VcaaGjBm93Yx3ZmQPN5tZYih8klhYBUl4OTv3iZX8CjBbUSTIw3lE5zLG4/BJs+xPSTQKbvTaGJWbtAvW8UKY/lVMjSbrxB5XXbJCYhYtq4IR9CTyRgJNy0IPZZA+2lFu3NWXObGd0jlr9IIaVb/y4xahY/4JYPsiX0hxIqQcZ1eEEtIy3+Qx1I6J9v48uYdpmM4GHokv47B/snGsT/6jl3iaXDIM7SzPrYllreMzGcFJoJfYXxoRfMfKkICKuTR+tbjeaDgXAcrB99E++HQTD02jo14qMazfIxuf8s6e2EYD/jc0+bRKckhMHI1YkbnzvyzE8zpcCJqpyBia9QhIi/Vsz9HCCFgjI2lCzqHA69RJIV+CsrVMCCAexklB0WdFawZUYTsAyu5twp9/05K1rhj5LY1vcn0hk9G7Q6Y1mUb6xk5kFru7bXSx2F15sWtiSAN+g6a1LBCRn4+er6v8SeH/JcDKrdagxHH0CmZvNvfP+lKKW2m8KJDRkhag989g5Ps8+Tz5GgwaqNm9Ub5UfhvwhB7MkK4S7lzdE+oUVu/Y+Tq/exedjRKavnqC06xVRL0iEF+u4gxZ8VzGYYDyrhLi/lMD6S4jR6Kbja9HiobDxfFwZN27YH3I3WsPYbaKrG4HmiOj/PiTG4PNXTugLNKUYdeWrH4cZbX0LkQpc4FvMCtswZNlKDOFcThFXxdWVyfyepPF1bFRfZoNt0kb0Al/M1b3b/vi0Ql2jd2JH+AWLPDaJpmDjrHGkru/35++PTh+ePN/d33Rysj+SXIp4eb2z1u/vv01JvEeeV3ZjAAbWBESZO21X8BAAD//0SxZ2rFCwAA\n\n- path: /etc/kubernetes/addons/azure-storage-classes.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8yQTUs0MRCE7/kVzd4zL3t7ydWrgrjgVXon5RJmkgzdnQH99TIfLqhXFzx3nkrVw1N6hmiqJZBaFb6gG/5rl+q/+XiG8dENqcRAp+14N7KqyzCObBwcUeGMQBGv3EZzRFxKNbZUiy5n+oztF7JbIruhnSEFhvWfpH6n/fom0MGk4eCIRj5j3GO+Qv3Y1CBeIXPqcWUmqXNa5kDCN4Tfm8DHpIPz3rvfWp658AXRT4KcWv5p4FYjJhbOMMiavXV92Mq4q3Xu+9qK2duEQI9bxZf7p9NNFKhxiSzxLzs47R1XCR8BAAD//1fQzbL+AgAA\n\n- path: /etc/kubernetes/addons/kube-tiller-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8yUW0scPxjG7+dTvHg/q8tf4U8oBasigsriSm9LNvPUTc2pyZvB7acvM9sZ52BFC4XmapL38PzyJBkZ9GfEpL0TVC+LR+0qQWvEWiucKuWz48KCZSVZioLISQtBrI1B/DVNQSoIeswblGmXGLYgMnIDk5oKaiPRgZEW2h8qkxMjlmkvIuiAY8ZBUZZlMaSJG6kWMvPWR/1DsvZu8fh/26FebsCygz3b97vzBp+0q7R7eA34/VzRG9zha1Mig76MPodX4AqiGVZP0UnIympXpLz5BsVJFCW96Ptb3Z46Nz3HkR9DA2QIgrYwtp1NxN7qz7iwrBCM3/0eNgWoRj34yC1GORduYoKOj5f/HbdzlvEBvGpX+7QEA8U+vmErvAvoT+RqNTMMTwzXfKbJ3TpvN2MxeQT/iocMG4xk7EmGhM0YUs5JX6TtGrffo8t4O00lUt6x1A6x1ygJrn4W7E72/ur6+uLuy+3pzcV6dXp20ScQ1dLk2b9jP7SVDxD04dnB+1Z9HaA+9llG13BIaRX9BmLQecscLsHDJaIgeSvosCsax/pLdzJY106zluYcRu7WUN5VSdBykMDawmd+ITZzt1NJQ4t6F1eTS/9KkwhZ6Xfvuq/6u9uOSD5HhTSEiPiekTiNwVTIgk6O7GjRwvq4E7Q8ObrRg4jRVv9xA+crrEc/jGY0T30xfqE+CTLa5afiZwAAAP//2LvwXhoHAAA=\n\n\n\n- path: \"/etc/systemd/system/kubectl-extract.service\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n [Unit]\n Description=Kubectl extraction\n Requires=docker.service\n After=docker.service\n ConditionPathExists=!/usr/local/bin/kubectl\n\n [Service]\n TimeoutStartSec=0\n Restart=on-failure\n RestartSec=5s\n ExecStartPre=/bin/mkdir -p /tmp/kubectldir\n ExecStartPre=/usr/bin/docker pull ',parameters('kubernetesHyperkubeSpec'),'\n ExecStartPre=/usr/bin/docker run --rm -v /tmp/kubectldir:/opt/kubectldir ',parameters('kubernetesHyperkubeSpec'),' /bin/bash -c \"cp /hyperkube /opt/kubectldir/\"\n ExecStartPre=/bin/mv /tmp/kubectldir/hyperkube /usr/local/bin/kubectl\n ExecStart=/bin/chmod a+x /usr/local/bin/kubectl\n\n [Install]\n WantedBy=multi-user.target\n\n- path: \"/etc/default/kubelet\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n KUBELET_CLUSTER_DNS=',parameters('kubeDNSServiceIP'),'\n KUBELET_API_SERVERS=',concat('https://', variables('masterPrivateIpAddrs')[copyIndex(variables('masterOffset'))], ':443'),'\n KUBELET_IMAGE=',parameters('kubernetesHyperkubeSpec'),'\n KUBELET_NETWORK_PLUGIN=\n DOCKER_OPTS=\n KUBELET_REGISTER_WITH_TAINTS=',variables('registerWithTaints'),'\n KUBELET_NODE_LABELS=role=master\n KUBELET_POD_INFRA_CONTAINER_IMAGE=',parameters('kubernetesPodInfraContainerSpec'),'\n\n- path: \"/etc/systemd/system/kubelet.service\"\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/5RVX2/bNhB/16cg3D5sD7SaNNg6F3pwYiUz4tqZZaMY0sCgxbPEhSK149Gut/a7D5KVxLKdYYMAgfzd/e4/yfu5UfQQDMClqEpS1kS3fgkaKJjCn14huEja9BGw6wDXKoWgvyLAQzC4T3arh2AKjgRSJPRGbF0Qm7VCawowdK00RCFQGkpYCa8pfGx8JT5Nwbn4q6KEBHkXnV28D+KvkCaVrTuEKFwqEy6Fy1loSwrFXx4hTK0hoQygezLVdfkJXvEoFTJesnAtMNRq+ez5FR88ZR21Yvfs7Q+F9YbYN5YhlOxL59DClw77xjYp4/pHxjWwd+yBfWSUg2E71zWd86Uy8sj9MfCRrVTnVAaNmUI8Ane5QDi2Frxhs1w5phwTrBRISmi2sfgo0HojGVlGldyXjhBEwapWowGCiuM89II3jOVEpeuFYaYo98tuaova/k5vf1lTXHhx9svZT2/qTWqLqs/8/dn5xfmHn9+fHSTiqkzc1qWkGd8wA9RV5fqiS2m5QCBU4M6jD20S37FgSWKpwTFOzIiqElo5Oqmqyn9XjULvsC7qbogZesO+BIxxboCi3DpqtqWSrS2qtdKQgWwALJrF2mpfQBRKWPeq3wHstq5X/9AeSKoOoje95wVuTmhUPd7FGvYOgNcJzVDsMRqk14zPCZrNes+LI8PVwd1rf+8AOE7O4bpNaAMV4e1gcnUbTxeTu1nySh4bITIwFH4SRmQghxIMKdryBIiUyVzvv2s2ETL29u/b+WU8imeL4af+Tfy9gRkL820JWMXInk7kk6iKrcJSa1YqO67zi6xFwd01yl8Rl1ZyZVYo+PNdxlUhMog6L0HeTQaL4fh62l9cTcaz/nAcT5vAOy1jQkoE56J33fpry7S2m70Rjgg9tDTAVMeGV1c64CmJhKXPMmUyngsjNaA7SqUQRq3AES8F5Ucj8yRt81LtHQFyaVz0kvPVaJ7M4uliME6+n1a3hVAmarZdbVOhDyqfqVrTpTlIr6sc9hxM45th7SG5+jUezEf9y1Hc9mSsBK7FErTb78Z4MogXo/5lPEoO6p9q6yUv0a6VBIzqN+qEwtMEHVSnVu/+4axpN66C96ZjlxZu/6eZXCgsleGFlRCVaAvlUm+940tUMmuHaYCqZ4OX2mfK7NVsHM8+T6a3i7vR/GY4PlEtV7/e3JdSEPBVNfxg0m10UL1k1p/Nk8X8btCfxYvrafzbPB5f/d42uI7O9w7qddyfzafx4qY/i5PvQXA/NI6E1g/BZ2EI5OU2Krwmxb0D7JLADCj4JwAA//9Myf113wgAAA==\n\n- path: \"/opt/azure/containers/kubelet.sh\"\n permissions: \"0755\"\n owner: \"root\"\n content: |\n #!/bin/bash\n set -e\n\n\n\n sed -i \"s||',parameters('kubernetesAddonManagerSpec'),'|g\" \"/etc/kubernetes/manifests/kube-addon-manager.yaml\"\n sed -i \"s||',parameters('kubernetesHyperkubeSpec'),'|g; s||',parameters('kubeServiceCidr'),'|g; s||',variables('masterEtcdClientPort'),'|g; s||',variables('kubernetesAPIServerIP'),'|g\" \"/etc/kubernetes/manifests/kube-apiserver.yaml\"\n sed -i \"s||',parameters('kubernetesHyperkubeSpec'),'|g; s||',variables('masterFqdnPrefix'),'|g; s||',variables('allocateNodeCidrs'),'|g; s||',parameters('kubeClusterCidr'),'|g; s||',variables('kubernetesCtrlMgrNodeMonitorGracePeriod'),'|g; s||',variables('kubernetesCtrlMgrPodEvictionTimeout'),'|g; s||',variables('kubernetesCtrlMgrRouteReconciliationPeriod'),'|g\" \"/etc/kubernetes/manifests/kube-controller-manager.yaml\"\n sed -i \"s||',parameters('kubernetesHyperkubeSpec'),'|g\" \"/etc/kubernetes/manifests/kube-scheduler.yaml\"\n sed -i \"s||',parameters('kubernetesHyperkubeSpec'),'|g; s||',parameters('kubeClusterCidr'),'|g\" \"/etc/kubernetes/addons/kube-proxy-daemonset.yaml\"\n sed -i \"s||',parameters('kubernetesKubeDNSSpec'),'|g; s||',parameters('kubernetesDNSMasqSpec'),'|g; s||',parameters('kubernetesExecHealthzSpec'),'|g\" \"/etc/kubernetes/addons/kube-dns-deployment.yaml\"\n sed -i \"s||',parameters('kubernetesHeapsterSpec'),'|g; s||',parameters('kubernetesAddonResizerSpec'),'|g\" \"/etc/kubernetes/addons/kube-heapster-deployment.yaml\"\n sed -i \"s||',parameters('kubernetesDashboardSpec'),'|g\" \"/etc/kubernetes/addons/kubernetes-dashboard-deployment.yaml\"\n sed -i \"s||',parameters('kubernetesTillerSpec'),'|g\" \"/etc/kubernetes/addons/kube-tiller-deployment.yaml\"\n\n\n sed -i \"//d\" \"/etc/kubernetes/manifests/kube-apiserver.yaml\"\n sed -i \"//d\" \"/etc/kubernetes/manifests/kube-controller-manager.yaml\"\n\n\n\n\n- path: \"/opt/azure/containers/provision.sh\"\n permissions: \"0744\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n ',variables('provisionScript'),'\n\n- path: \"/opt/azure/containers/mountetcd.sh\"\n permissions: \"0744\"\n owner: \"root\"\n content: |\n #!/bin/bash\n # Mounting is done here instead of etcd because of bug https://bugs.launchpad.net/cloud-init/+bug/1692093\n # Once the bug is fixed, replace the below with the cloud init changes replaced in https://github.com/Azure/acs-engine/pull/661.\n set -x\n DISK=/dev/sdc\n PARTITION=${DISK}1\n MOUNTPOINT=/var/lib/etcddisk\n udevadm settle\n mkdir -p $MOUNTPOINT\n mount | grep $MOUNTPOINT\n if [ $? -eq 0 ]\n then\n echo \"disk is already mounted\"\n exit 0\n fi\n # fill /etc/fstab\n grep \"/dev/sdc1\" /etc/fstab\n if [ $? -ne 0 ]\n then\n echo \"$PARTITION $MOUNTPOINT auto defaults,nofail 0 2\" >> /etc/fstab\n fi\n # check if partition exists\n ls $PARTITION\n if [ $? -ne 0 ]\n then\n # partition does not exist\n /sbin/sgdisk --new 1 $DISK\n /sbin/mkfs.ext4 $PARTITION -L etcd_disk -F -E lazy_itable_init=1,lazy_journal_init=1\n fi\n mount $MOUNTPOINT\n\nruncmd:\n- /bin/echo DAEMON_ARGS=--name \"',variables('masterVMNames')[copyIndex(variables('masterOffset'))],'\" --initial-advertise-peer-urls \"',variables('masterEtcdPeerURLs')[copyIndex(variables('masterOffset'))],'\" --listen-peer-urls \"',variables('masterEtcdPeerURLs')[copyIndex(variables('masterOffset'))],'\" --advertise-client-urls \"',variables('masterEtcdClientURLs')[copyIndex(variables('masterOffset'))],'\" --listen-client-urls \"',concat(variables('masterEtcdClientURLs')[copyIndex(variables('masterOffset'))], ',http://127.0.0.1:', variables('masterEtcdClientPort')),'\" --initial-cluster-token \"k8s-etcd-cluster\" --initial-cluster \"',variables('masterEtcdClusterStates')[div(variables('masterCount'), 2)],' --data-dir \"/var/lib/etcddisk\"\" --initial-cluster-state \"new\" | tee -a /etc/default/etcd\n- sudo /bin/chown -R etcd:etcd /var/lib/etcd/default\n- /opt/azure/containers/mountetcd.sh\n- sudo /bin/chown -R etcd:etcd /var/lib/etcddisk\n- systemctl stop etcd\n- sudo -u etcd rm -rf /var/lib/etcd/default\n- systemctl restart etcd\n- for i in $(seq 1 20); do curl --max-time 60 http://127.0.0.1:2379/v2/machines; [ $? -eq 0 ] && break || sleep 5; done\n- retrycmd_if_failure() { for i in 1 2 3 4 5; do $@; [ $? -eq 0 ] && break || sleep 5; done ; }\n- retrycmd_if_failure apt-get update\n- retrycmd_if_failure apt-get install -y apt-transport-https ca-certificates\n- retrycmd_if_failure curl --max-time 60 -fsSL https://aptdocker.azureedge.net/gpg | apt-key add -\n- echo \"deb ',parameters('dockerEngineDownloadRepo'),' ubuntu-xenial main\" | sudo tee /etc/apt/sources.list.d/docker.list\n- \"echo \\\"Package: docker-engine\\nPin: version ',parameters('dockerEngineVersion'),'\\nPin-Priority: 550\\n\\\" > /etc/apt/preferences.d/docker.pref\"\n- retrycmd_if_failure apt-get update\n- retrycmd_if_failure apt-get install -y ebtables\n- retrycmd_if_failure apt-get install -y docker-engine\n- systemctl restart docker\n- mkdir -p /etc/kubernetes/manifests\n- usermod -aG docker ',parameters('linuxAdminUsername'),'\n- /usr/lib/apt/apt.systemd.daily\n- touch /opt/azure/containers/runcmd.complete\n'))]", + "customData": "[base64(concat('#cloud-config\n\npackages:\n - etcd\n - jq\n - traceroute\n\nwrite_files:\n- path: \"/etc/systemd/system/docker.service.d/clear_mount_propagation_flags.conf\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n [Service]\n MountFlags=shared\n\n- path: \"/etc/systemd/system/docker.service.d/exec_start.conf\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n [Service]\n ExecStart=\n ExecStart=/usr/bin/docker daemon -H fd:// --storage-driver=overlay --bip=',parameters('dockerBridgeCidr'),'\n\n- path: \"/etc/docker/daemon.json\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n {\n \"live-restore\": true,\n \"log-driver\": \"json-file\",\n \"log-opts\": {\n \"max-size\": \"50m\",\n \"max-file\": \"5\"\n }\n }\n\n- path: \"/etc/kubernetes/certs/ca.crt\"\n permissions: \"0644\"\n encoding: \"base64\"\n owner: \"root\"\n content: |\n ',parameters('caCertificate'),'\n\n- path: \"/etc/kubernetes/certs/apiserver.crt\"\n permissions: \"0644\"\n encoding: \"base64\"\n owner: \"root\"\n content: |\n ',parameters('apiServerCertificate'),'\n\n- path: \"/etc/kubernetes/certs/client.crt\"\n permissions: \"0644\"\n encoding: \"base64\"\n owner: \"root\"\n content: |\n ',parameters('clientCertificate'),'\n\n- path: \"/var/lib/kubelet/kubeconfig\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n apiVersion: v1\n kind: Config\n clusters:\n - name: localcluster\n cluster:\n certificate-authority: /etc/kubernetes/certs/ca.crt\n server: ',concat('https://', variables('masterPrivateIpAddrs')[copyIndex(variables('masterOffset'))], ':443'),'\n users:\n - name: client\n user:\n client-certificate: /etc/kubernetes/certs/client.crt\n client-key: /etc/kubernetes/certs/client.key\n contexts:\n - context:\n cluster: localcluster\n user: client\n name: localclustercontext\n current-context: localclustercontext\n\n- path: /etc/kubernetes/manifests/kube-apiserver.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/6RUy27jOgzd5ysMr6O67S1wC6MuUPQWuAXaTqYBZs9IjKOJXkPRLjJfP5DzttMHMMlKOjxH5CFNCPoHUtTelVneXuSjpXaqzPKJV/nIIoMChnKUZQ4sllm+bGYoIOiI1CLlGyAGkDs0riKjTZCBGZqY2FnGGqnMpHdM3ohgwGF3L70N3qHjMjvWHsWAMnEXPvIL8punZZkxNYmXdEA7pI26eD+/9NMW6oTeJJgcMsb/VwEpHacB5e02UHprIRmwOSflvFhsY/PD68Er3a0QoKyOyVGxqbZ62Vr0pOcoV9Lg+Elbza/gaqTxFKnVEu+k9I3j8X84h8bwlD1BjfcGYhy/YvQNSfzeeIbBe4owxur8rPv3UWP8mwikW22wRtWDtYsoG0IRPHF1fX7d5x/CV1f/9FBpfKNEIN9qhVTB74bwZIj0bq7rqkCWxb4JRUc4+xm9GzzbeSKkaSIjCR0EJbeqroUbx+61otseEVkqse5LrBbMoSyKi8t/O28uyhsLSe6Bpbo3Gh1PPPFJiV+Np8YKQlBVGrqB6S0S64g7+w9m627yOO0yeJz0tdlEIZFYzLXBgR0JicVusM4k8Ql+aiYwiiWuviazxNWgKal4IeEjAQknEtg2BtbT+jdJxPWEixnIJTpVJd8vezFtdXV0c+Dyg4OZwdcZ7D/f1pvG4nNKbLMYjpYDshR7/l43y2yiTIAXZZb3CsmHOi2QMHrWaRnkd4VaoMLoWTGI2ynZqD9lvwHU6Lh4Bgc1qkeFjjWvxBSZtauP6kjj+s2Z1W5Rrh3pb8nTRqRF2z2+EwwfOPKZG++rnbRlK2ej/rLA5878CQAA//8KCj673wYAAA==\n\n- path: /etc/kubernetes/manifests/kube-controller-manager.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/6SUTW/bPAyA7/kVhu+q8b5Ho+6l6PtxSBe0w+6MxLpaJNGjaHfZrx/oJE3jxMuA+Wbq4UOJ+oDOf0HOnlJdlMNf5WLjk6uLckWuXEQUcCBQL4oiQcS6KDf9Go2lJEwhIJsICVrkck/kDuw7lrdZMOpQgDWGrJqiEI9cF3uF6QIkHOOWYkcJk9TFTJFF7tCq5JWyPKK8EW/qQrhXgeLgE/K+jPmNGevnI7SK3SrHCQXzf9sOWX+fO7R3B9BSjKC92f9ribJ6PbDlx/B8uXHYGM2wlF5821QDcBX8utJYQKmOY5MkCIEsCJpEDo31jnNzewg+ksN7Dd1NsmzosyCPfDOu8n4XUXoO1t41txH0559vLq0YX/z3c5p6ZzqmwTvkBn70jBeRw1JRbHXsczUm3HzNlCZZTCTGgnnxAc+yLLLkysKNZZmZfvZt8qk1iv6xZIPbK44NbieOjDx4iwaspT6J6dgPunNXXNB5zUS+oAwIDtlgQCuNHvqT8Q/H9yHBOuDTGux0v4bm70lkPEmRkhdi0zJYNB2yJ9d8EN4Lh2XLesKWO/RfJVcjOK3RkTM4eCuekhEfkXq5IFuRe9hTn3fQVMTUCxrWq2B98DAKZyf3pPTTCTyZ30Chj7jU7cgnl3j/TqBYc9QeJ1MUUXNWIK91UU72rTz3DMAm+LXZX+dZ0eTan5ti9tdy3wBaTFItx0fG/e8wiZeteUYRn9qTVTCC+5TC9v3F3DVk+lxeboO+uGPxd2H3i35c68W87WJTzhtyXXC9Mz8DAAD//8PhLmf6BgAA\n\n- path: /etc/kubernetes/manifests/kube-scheduler.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/4SSQY/bIBCF7/kViDtC7RE1PbeHbVdaqfcxTG0UGBCMvfK/r0ideOMka988b97HzNNA9n+wVJ/ICDl9kYeTJ2eEfE1OHiIyOGAwByEIIhohT2OHqtoB3RiwyEWoGeyqzpUxNilAh6E2txDssRhhE3FJQeUAhOe6TTEnQmIjbtmHmtE275Aq/0J+T+VkBJex+RoHPGFZ6Or5fO3zEfqmfmtyIWSsP+aMpf2+ZbTfL402xQjkzPLbwFIPl1b5sXz3yLmqVGu0if76/qgnKDr4TrdaQNartjEFBIdFYUDLx7bjRp+OXy+VKYUx4ksaievHOZcAkK1at1wxQsRmeQUejJAa2epHbVfOBEUF36ll9KegzYr3pFj9nvcdoEdi/QIEPbqfDok9z+oNmT31N1sUBPebwnw9hf95bO/gcQztlM6PX4H5kzz2snhOexjKfSD7gP1k/gUAAP//FKERJ8EDAAA=\n\n- path: /etc/kubernetes/manifests/kube-addon-manager.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/4yRsW7zMAyEdz8Fkd3w/w9ZhKJAxw5pAwTozkiEIySiXJFy4LcvZMdOWjRtR5LH43cSdv6NkvjIBvr/1dGzM7CNrgqk6FDRVACMgQwc855qdC5yHZCxpXQZSYd2nssgSqEC6G9cpSNbfA5R9IX0HNPRgKZMFYCNrOiZkhRF/dMtAB+wJQMPZZyYlOSpaDaTZNeRfRx1iSTmZGn0nBrvmUSXGsB22cA6LHWgENNgYP1v48dmH0850CZmntdmuJFLLpuhCLaoBwOrhtQ2V7ZmEq4WBnSvfBqW6FfHIP47ux5Tc/L75ozYEmsz5XTPjli9DvWOVD239y9MGT697A18+Y7x1GW9+y3FV9x7Bn/n/ggAAP//ovMbJ38CAAA=\n\n- path: /etc/kubernetes/addons/kube-dns-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8xXS2/jNhC+61cQ7pl+JMhuINQLBOugG2yTGnXa+4QcW0QokuHDjffXF5RkWS+7dg7FyidzOA9+38xHCYz4G60TWqVkO0teheIpWaHdCoZ3jOmgfJKjBw4e0oQQBTmm5DW8IOXKVQvOANuvup3zmCeESHhB6aIPKSxWoUc3FnrCZHAeLXVlmpSMvA04KnYC51rloGCDdtx2yzXHlPyJTCsmJCaU0uRU+a26W9XcOgrGtI5xSY3tnSUi38MLLp5WFyDkDLJYT5XpYZmS2XQcf7NpQojR1hf10irivs5oSMnNdfnHaq+Zlin5a7Fsb6aemVMOz1+jg0OJzGt7DJkuyGCMm2xnL+hhD/cCjdS7HDud8jH+h7nZ1hxfTXsQ08PiCZgtGikYuJRc9Y6dg2fZ7416j9XRq8RjbiR4rOI0jl80s1Lagxda1XEJcSxDHiTaMUiTQafJmRVeMJDUaJ6S0ahyk63ijpd3CdQDxyFkD1dR/notlPC7Q1qj+Z3y4q5niI2Fa7QW+SJYoTar8pRCbR42StfL9+/IQgSk6UrJPyg2mY8DMG2sl/mqXM9o87RlrFBZtahsPgWt9+/GonNtDg6ZX3GX7tHsmQnRBi3E4ORBDZi3IAMOxC0id5kpH6+Nlnqz+14kbpGVaedjFyf7nTImb1Ze1fu1apK7KJbuDyV3Sb/g+3fhfN22WoYcG3E6I8S0WotNHaX8+wimebSesB1yxiJBpiQ2V1KH8CAU2kZSsJsGWJSMKOU6B6HmVZ+OpWYgx6POHuVoFLH5bDq9ue4Yt/OrzkpZPOXCziedAx52ihw2mJJfDwxUCr4yyL7U26TYokLnlla/YBOMNQgZLD5nFl2mJU/JTcOaeW9+Q99uDAM+S8lokiFIn/2gMTVXbtTp+CjWt9Pb9iBE0Yjof3t+XjYMcTIEyAVK2K3ixchdSj41XV1gDJ1r1DlrWL3IUQdfux7OcCC7yXV9Ke3hrlleFnUXBPVaJuJfENuSi/bFdXFAz8yJoOXlVj4WgYtBEk/SVLsdIWj2YYKup2dRYNHpYFlbX6TIhe8oTo65truUzD5PH0XDYvEtoOvuZiYUuOaDMVohStV4jC+BLdZPiwchefRYFjh2J/CUFjBgGVInfmCc9GlnrJWmERG57azHqw3tfHb1uXx5+mVIJapNE6EocG7HYA1MznQxn87ZLvWGroEJKfxuTk8JzeJp9QjurS00dWPn4N7Onrfh2bh8zI7P2H9M1zCPOZ8rJ7V+DaZ5xXFcQ5B+7LZs3BJ8UkNLvkw4bicqSNnBN1g5r6Wzwqkr/B/PmxaUnpm9J9zFluKGisLdWX8LAv2pfojvRN/K0P/f5dNDkPx0l09V6tnD0Kn72GVwoajeXKCpw5LaiMCVW2op2C5+NRVNWRlc64v7aehNS2mO/Xfd+CHW+YTQLiVSqPCe/BsAAP//MQMKdd0PAAA=\n\n- path: /etc/kubernetes/addons/kube-proxy-daemonset.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/5RUzW7bPBC8+ykI3RkmVyH+gA9ugV7aBgjQ+5qa2ET4oy6Xrv32BaU6kpzETXkSZoezszsCqXc/wNml2CocBbF+ZnO420LobvXsYteqT4SQ4iNkFSDUkVC7UsrTFj7XL6WeyxYcIcg3LhnrSxawzuCDs2hVI1zQDEybQp8iorTDJd1zOp6Gijhwq2LqsFIqUsAFo0K5J3vG8ykLwir3sNWEIPSeBKOhudF65mav23hlRalzi/FiFHIR/CKmq1ig2E3qWjVmf+rBVbuZwcs2WjVaV4pN8cnt1uZAbLzbmop5iJlqzfLSecPWdby+r7TNiGxcx/9dkJ9AUhh6R4K8/nzswS4gCvkNO3GW/EPq/o8xCYlLcT2FVY8LtKsR3k8ZfzmP9tjDzrq9Edp4GDkVtpgFUMGfBVkWmFK2L626u70NL2iGLezktElRcJQ5vWd3cB47dK2qrl9Kh+RLwNdU4lxfq1CRB5J9qxoDsSZnbyxYcjOTHefI2euhpPcpy8I4dd+jP130fEN9WtlreYjVU/2f5T/yq8wTGWt/a1Mn/Qb5lfh5gY/7nP3ylThYmafxx1rJbPKeGMbSsEH35CwtlnBlw9e1PzL2O0NfF34vrith1ffhER5WEk+S9eG8Wb6HKbfKu1iOq98BAAD//028PJBvBQAA\n\n- path: /etc/kubernetes/addons/kubernetes-dashboard-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8xUQW/bPAy9+1cQuTtt8V1a4cOArgV6GQqjGXanJS7RIouCRGf1fv0gt3HsJE2DYQWmk0DRj4+Pj8Zgv1FMlr2CzVWxtt4oWFDcWE23WnPrpWhI0KCgKgAc1uRSvgGsr1OJIShYtzVFT0KpNJhWNWM0LxnDw9zyhXZtEopleoFXMJPY0qzPRGPYN+hxSXE+/axhQwqeSLPX1lEB4LGhN6vmxxRQv2aUqUtCTVGWZTFuNtao59jKiqP9hWLZz9fXfb3NVU2CWy3uXkg/saPP1hvrlxM9TlL5B8SK7OiJvmcOGOxD5Dac6L0AOOh6aHLLCE1jfZHa+gdpSaoo4ahr/s6Y9j35thnPVu+9SfwJ7RRIZx6Bo/SEyv6q4PqyrykYlyRVH7q5vMnBRI60cDzPHtIFUvDIhjLIgUz0LOTzNe3Z956C466hU2v8MUv6sUJHCs5qTAquDrRsUPTqy6jDM+SlJjgUegUYKZWPm2Cds8tbmvlo9oLWUxwQSsC4TAoGQNvgkhT8v8O738ItAulP08Sqda5iZ3Wn4Nb9xC4N785uyFNKVeSadoQBViLhgWQcAggoKwWzi9k0OnbpUNhbsejuyWG3yFM2ScF/4wyxDXErxx5PDnpXdKRwuVOtOkYnRBbW7BR8vate42ny/3l8r6ZnQ4uJb/LJu7NnbU4KnPXtMxS/AwAA//+MY7+tLgcAAA==\n\n- path: /etc/kubernetes/addons/kube-heapster-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8xWW2tjNxB+P79C+F1ep92AK+pCmk3bh2Y3JFAoLISxNOujWrfq4rX31xfpHNvnYgcTNlC9WGdGo2/mm4sMTv6FPkhrGNlcVWtpBCNP6DeS4w3nNplYaYwgIAKrCDGgkZEawYWIvhUEBxwZWacl0rALEXVFiIIlqpBtSNF4gxHDVNp3XKVsTEMDw8gk+oSTchKEsEaDgRX6ad9MW4GMPCK3hkuFFaW06rrvl8CnkGJtvfwGUVozXc+L5eZqiRH20d028I9W4YnQGv/ZPkL6VcaaGjBm93Yx3ZmQPN5tZYih8klhYBUl4OTv3iZX8CjBbUSTIw3lE5zLG4/BJs+xPSTQKbvTaGJWbtAvW8UKY/lVMjSbrxB5XXbJCYhYtq4IR9CTyRgJNy0IPZZA+2lFu3NWXObGd0jlr9IIaVb/y4xahY/4JYPsiX0hxIqQcZ1eEEtIy3+Qx1I6J9v48uYdpmM4GHokv47B/snGsT/6jl3iaXDIM7SzPrYllreMzGcFJoJfYXxoRfMfKkICKuTR+tbjeaDgXAcrB99E++HQTD02jo14qMazfIxuf8s6e2EYD/jc0+bRKckhMHI1YkbnzvyzE8zpcCJqpyBia9QhIi/Vsz9HCCFgjI2lCzqHA69RJIV+CsrVMCCAexklB0WdFawZUYTsAyu5twp9/05K1rhj5LY1vcn0hk9G7Q6Y1mUb6xk5kFru7bXSx2F15sWtiSAN+g6a1LBCRn4+er6v8SeH/JcDKrdagxHH0CmZvNvfP+lKKW2m8KJDRkhag989g5Ps8+Tz5GgwaqNm9Ub5UfhvwhB7MkK4S7lzdE+oUVu/Y+Tq/exedjRKavnqC06xVRL0iEF+u4gxZ8VzGYYDyrhLi/lMD6S4jR6Kbja9HiobDxfFwZN27YH3I3WsPYbaKrG4HmiOj/PiTG4PNXTugLNKUYdeWrH4cZbX0LkQpc4FvMCtswZNlKDOFcThFXxdWVyfyepPF1bFRfZoNt0kb0Al/M1b3b/vi0Ql2jd2JH+AWLPDaJpmDjrHGkru/35++PTh+ePN/d33Rysj+SXIp4eb2z1u/vv01JvEeeV3ZjAAbWBESZO21X8BAAD//0SxZ2rFCwAA\n\n- path: /etc/kubernetes/addons/azure-storage-classes.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8yQTUs0MRCE7/kVzd4zL3t7ydWrgrjgVXon5RJmkgzdnQH99TIfLqhXFzx3nkrVw1N6hmiqJZBaFb6gG/5rl+q/+XiG8dENqcRAp+14N7KqyzCObBwcUeGMQBGv3EZzRFxKNbZUiy5n+oztF7JbIruhnSEFhvWfpH6n/fom0MGk4eCIRj5j3GO+Qv3Y1CBeIXPqcWUmqXNa5kDCN4Tfm8DHpIPz3rvfWp658AXRT4KcWv5p4FYjJhbOMMiavXV92Mq4q3Xu+9qK2duEQI9bxZf7p9NNFKhxiSzxLzs47R1XCR8BAAD//1fQzbL+AgAA\n\n- path: /etc/kubernetes/addons/kube-tiller-deployment.yaml\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/8yUW0scPxjG7+dTvHg/q8tf4U8oBasigsriSm9LNvPUTc2pyZvB7acvM9sZ52BFC4XmapL38PzyJBkZ9GfEpL0TVC+LR+0qQWvEWiucKuWz48KCZSVZioLISQtBrI1B/DVNQSoIeswblGmXGLYgMnIDk5oKaiPRgZEW2h8qkxMjlmkvIuiAY8ZBUZZlMaSJG6kWMvPWR/1DsvZu8fh/26FebsCygz3b97vzBp+0q7R7eA34/VzRG9zha1Mig76MPodX4AqiGVZP0UnIympXpLz5BsVJFCW96Ptb3Z46Nz3HkR9DA2QIgrYwtp1NxN7qz7iwrBCM3/0eNgWoRj34yC1GORduYoKOj5f/HbdzlvEBvGpX+7QEA8U+vmErvAvoT+RqNTMMTwzXfKbJ3TpvN2MxeQT/iocMG4xk7EmGhM0YUs5JX6TtGrffo8t4O00lUt6x1A6x1ygJrn4W7E72/ur6+uLuy+3pzcV6dXp20ScQ1dLk2b9jP7SVDxD04dnB+1Z9HaA+9llG13BIaRX9BmLQecscLsHDJaIgeSvosCsax/pLdzJY106zluYcRu7WUN5VSdBykMDawmd+ITZzt1NJQ4t6F1eTS/9KkwhZ6Xfvuq/6u9uOSD5HhTSEiPiekTiNwVTIgk6O7GjRwvq4E7Q8ObrRg4jRVv9xA+crrEc/jGY0T30xfqE+CTLa5afiZwAAAP//2LvwXhoHAAA=\n\n\n\n- path: \"/etc/systemd/system/kubectl-extract.service\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n [Unit]\n Description=Kubectl extraction\n Requires=docker.service\n After=docker.service\n ConditionPathExists=!/usr/local/bin/kubectl\n\n [Service]\n TimeoutStartSec=0\n Restart=on-failure\n RestartSec=5s\n ExecStartPre=/bin/mkdir -p /tmp/kubectldir\n ExecStartPre=/usr/bin/docker pull ',parameters('kubernetesHyperkubeSpec'),'\n ExecStartPre=/usr/bin/docker run --rm -v /tmp/kubectldir:/opt/kubectldir ',parameters('kubernetesHyperkubeSpec'),' /bin/bash -c \"cp /hyperkube /opt/kubectldir/\"\n ExecStartPre=/bin/mv /tmp/kubectldir/hyperkube /usr/local/bin/kubectl\n ExecStart=/bin/chmod a+x /usr/local/bin/kubectl\n\n [Install]\n WantedBy=multi-user.target\n\n- path: \"/etc/default/kubelet\"\n permissions: \"0644\"\n owner: \"root\"\n content: |\n KUBELET_CLUSTER_DNS=',parameters('kubeDNSServiceIP'),'\n KUBELET_API_SERVERS=',concat('https://', variables('masterPrivateIpAddrs')[copyIndex(variables('masterOffset'))], ':443'),'\n KUBELET_IMAGE=',parameters('kubernetesHyperkubeSpec'),'\n KUBELET_NETWORK_PLUGIN=\n DOCKER_OPTS=\n KUBELET_REGISTER_WITH_TAINTS=',variables('registerWithTaints'),'\n KUBELET_NODE_LABELS=role=master\n KUBELET_POD_INFRA_CONTAINER_IMAGE=',parameters('kubernetesPodInfraContainerSpec'),'\n\n- path: \"/etc/systemd/system/kubelet.service\"\n permissions: \"0644\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n H4sIAAAAAAAA/5RVX2/bNhB/16cg3D5sD7SaNNg6F3pwYiUz4tqZZaMY0sCgxbPEhSK149Gut/a7D5KVxLKdYYMAgfzd/e4/yfu5UfQQDMClqEpS1kS3fgkaKJjCn14huEja9BGw6wDXKoWgvyLAQzC4T3arh2AKjgRSJPRGbF0Qm7VCawowdK00RCFQGkpYCa8pfGx8JT5Nwbn4q6KEBHkXnV28D+KvkCaVrTuEKFwqEy6Fy1loSwrFXx4hTK0hoQygezLVdfkJXvEoFTJesnAtMNRq+ez5FR88ZR21Yvfs7Q+F9YbYN5YhlOxL59DClw77xjYp4/pHxjWwd+yBfWSUg2E71zWd86Uy8sj9MfCRrVTnVAaNmUI8Ane5QDi2Frxhs1w5phwTrBRISmi2sfgo0HojGVlGldyXjhBEwapWowGCiuM89II3jOVEpeuFYaYo98tuaova/k5vf1lTXHhx9svZT2/qTWqLqs/8/dn5xfmHn9+fHSTiqkzc1qWkGd8wA9RV5fqiS2m5QCBU4M6jD20S37FgSWKpwTFOzIiqElo5Oqmqyn9XjULvsC7qbogZesO+BIxxboCi3DpqtqWSrS2qtdKQgWwALJrF2mpfQBRKWPeq3wHstq5X/9AeSKoOoje95wVuTmhUPd7FGvYOgNcJzVDsMRqk14zPCZrNes+LI8PVwd1rf+8AOE7O4bpNaAMV4e1gcnUbTxeTu1nySh4bITIwFH4SRmQghxIMKdryBIiUyVzvv2s2ETL29u/b+WU8imeL4af+Tfy9gRkL820JWMXInk7kk6iKrcJSa1YqO67zi6xFwd01yl8Rl1ZyZVYo+PNdxlUhMog6L0HeTQaL4fh62l9cTcaz/nAcT5vAOy1jQkoE56J33fpry7S2m70Rjgg9tDTAVMeGV1c64CmJhKXPMmUyngsjNaA7SqUQRq3AES8F5Ucj8yRt81LtHQFyaVz0kvPVaJ7M4uliME6+n1a3hVAmarZdbVOhDyqfqVrTpTlIr6sc9hxM45th7SG5+jUezEf9y1Hc9mSsBK7FErTb78Z4MogXo/5lPEoO6p9q6yUv0a6VBIzqN+qEwtMEHVSnVu/+4axpN66C96ZjlxZu/6eZXCgsleGFlRCVaAvlUm+940tUMmuHaYCqZ4OX2mfK7NVsHM8+T6a3i7vR/GY4PlEtV7/e3JdSEPBVNfxg0m10UL1k1p/Nk8X8btCfxYvrafzbPB5f/d42uI7O9w7qddyfzafx4qY/i5PvQXA/NI6E1g/BZ2EI5OU2Krwmxb0D7JLADCj4JwAA//9Myf113wgAAA==\n\n- path: \"/opt/azure/containers/kubelet.sh\"\n permissions: \"0755\"\n owner: \"root\"\n content: |\n #!/bin/bash\n set -e\n\n\n\n sed -i \"s||',parameters('kubernetesAddonManagerSpec'),'|g\" \"/etc/kubernetes/manifests/kube-addon-manager.yaml\"\n sed -i \"s||',parameters('kubernetesHyperkubeSpec'),'|g; s||',parameters('kubeServiceCidr'),'|g; s||',variables('masterEtcdClientPort'),'|g; s||',variables('kubernetesAPIServerIP'),'|g\" \"/etc/kubernetes/manifests/kube-apiserver.yaml\"\n sed -i \"s||',parameters('kubernetesHyperkubeSpec'),'|g; s||',variables('masterFqdnPrefix'),'|g; s||',variables('allocateNodeCidrs'),'|g; s||',parameters('kubeClusterCidr'),'|g; s||',variables('kubernetesCtrlMgrNodeMonitorGracePeriod'),'|g; s||',variables('kubernetesCtrlMgrPodEvictionTimeout'),'|g; s||',variables('kubernetesCtrlMgrRouteReconciliationPeriod'),'|g\" \"/etc/kubernetes/manifests/kube-controller-manager.yaml\"\n sed -i \"s||',parameters('kubernetesHyperkubeSpec'),'|g\" \"/etc/kubernetes/manifests/kube-scheduler.yaml\"\n sed -i \"s||',parameters('kubernetesHyperkubeSpec'),'|g; s||',parameters('kubeClusterCidr'),'|g\" \"/etc/kubernetes/addons/kube-proxy-daemonset.yaml\"\n sed -i \"s||',parameters('kubernetesKubeDNSSpec'),'|g; s||',parameters('kubernetesDNSMasqSpec'),'|g; s||',parameters('kubernetesExecHealthzSpec'),'|g\" \"/etc/kubernetes/addons/kube-dns-deployment.yaml\"\n sed -i \"s||',parameters('kubernetesHeapsterSpec'),'|g; s||',parameters('kubernetesAddonResizerSpec'),'|g\" \"/etc/kubernetes/addons/kube-heapster-deployment.yaml\"\n sed -i \"s||',parameters('kubernetesDashboardSpec'),'|g\" \"/etc/kubernetes/addons/kubernetes-dashboard-deployment.yaml\"\n sed -i \"s||',parameters('kubernetesTillerSpec'),'|g\" \"/etc/kubernetes/addons/kube-tiller-deployment.yaml\"\n\n\n sed -i \"//d\" \"/etc/kubernetes/manifests/kube-apiserver.yaml\"\n sed -i \"//d\" \"/etc/kubernetes/manifests/kube-controller-manager.yaml\"\n\n\n\n\n- path: \"/opt/azure/containers/provision.sh\"\n permissions: \"0744\"\n encoding: gzip\n owner: \"root\"\n content: !!binary |\n ',variables('provisionScript'),'\n\n- path: \"/opt/azure/containers/mountetcd.sh\"\n permissions: \"0744\"\n owner: \"root\"\n content: |\n #!/bin/bash\n # Mounting is done here instead of etcd because of bug https://bugs.launchpad.net/cloud-init/+bug/1692093\n # Once the bug is fixed, replace the below with the cloud init changes replaced in https://github.com/Azure/aks-engine/pull/661.\n set -x\n DISK=/dev/sdc\n PARTITION=${DISK}1\n MOUNTPOINT=/var/lib/etcddisk\n udevadm settle\n mkdir -p $MOUNTPOINT\n mount | grep $MOUNTPOINT\n if [ $? -eq 0 ]\n then\n echo \"disk is already mounted\"\n exit 0\n fi\n # fill /etc/fstab\n grep \"/dev/sdc1\" /etc/fstab\n if [ $? -ne 0 ]\n then\n echo \"$PARTITION $MOUNTPOINT auto defaults,nofail 0 2\" >> /etc/fstab\n fi\n # check if partition exists\n ls $PARTITION\n if [ $? -ne 0 ]\n then\n # partition does not exist\n /sbin/sgdisk --new 1 $DISK\n /sbin/mkfs.ext4 $PARTITION -L etcd_disk -F -E lazy_itable_init=1,lazy_journal_init=1\n fi\n mount $MOUNTPOINT\n\nruncmd:\n- /bin/echo DAEMON_ARGS=--name \"',variables('masterVMNames')[copyIndex(variables('masterOffset'))],'\" --initial-advertise-peer-urls \"',variables('masterEtcdPeerURLs')[copyIndex(variables('masterOffset'))],'\" --listen-peer-urls \"',variables('masterEtcdPeerURLs')[copyIndex(variables('masterOffset'))],'\" --advertise-client-urls \"',variables('masterEtcdClientURLs')[copyIndex(variables('masterOffset'))],'\" --listen-client-urls \"',concat(variables('masterEtcdClientURLs')[copyIndex(variables('masterOffset'))], ',http://127.0.0.1:', variables('masterEtcdClientPort')),'\" --initial-cluster-token \"k8s-etcd-cluster\" --initial-cluster \"',variables('masterEtcdClusterStates')[div(variables('masterCount'), 2)],' --data-dir \"/var/lib/etcddisk\"\" --initial-cluster-state \"new\" | tee -a /etc/default/etcd\n- sudo /bin/chown -R etcd:etcd /var/lib/etcd/default\n- /opt/azure/containers/mountetcd.sh\n- sudo /bin/chown -R etcd:etcd /var/lib/etcddisk\n- systemctl stop etcd\n- sudo -u etcd rm -rf /var/lib/etcd/default\n- systemctl restart etcd\n- for i in $(seq 1 20); do curl --max-time 60 http://127.0.0.1:2379/v2/machines; [ $? -eq 0 ] && break || sleep 5; done\n- retrycmd_if_failure() { for i in 1 2 3 4 5; do $@; [ $? -eq 0 ] && break || sleep 5; done ; }\n- retrycmd_if_failure apt-get update\n- retrycmd_if_failure apt-get install -y apt-transport-https ca-certificates\n- retrycmd_if_failure curl --max-time 60 -fsSL https://aptdocker.azureedge.net/gpg | apt-key add -\n- echo \"deb ',parameters('dockerEngineDownloadRepo'),' ubuntu-xenial main\" | sudo tee /etc/apt/sources.list.d/docker.list\n- \"echo \\\"Package: docker-engine\\nPin: version ',parameters('dockerEngineVersion'),'\\nPin-Priority: 550\\n\\\" > /etc/apt/preferences.d/docker.pref\"\n- retrycmd_if_failure apt-get update\n- retrycmd_if_failure apt-get install -y ebtables\n- retrycmd_if_failure apt-get install -y docker-engine\n- systemctl restart docker\n- mkdir -p /etc/kubernetes/manifests\n- usermod -aG docker ',parameters('linuxAdminUsername'),'\n- /usr/lib/apt/apt.systemd.daily\n- touch /opt/azure/containers/runcmd.complete\n'))]", "linuxConfiguration": { "disablePasswordAuthentication": "true", "ssh": { @@ -2192,7 +2192,7 @@ } }, "tags": { - "creationSource": "[concat('acsengine-', variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]", + "creationSource": "[concat('aksengine-', variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]", "orchestrator": "[variables('orchestratorNameVersionTag')]", "resourceNameSuffix": "[parameters('nameSuffix')]" }, diff --git a/pkg/acsengine/types.go b/pkg/engine/types.go similarity index 61% rename from pkg/acsengine/types.go rename to pkg/engine/types.go index bc22becd16..930cafbc7c 100644 --- a/pkg/acsengine/types.go +++ b/pkg/engine/types.go @@ -1,47 +1,25 @@ -package acsengine +package engine import ( - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/api/v20160330" - "github.com/Azure/acs-engine/pkg/api/vlabs" - "github.com/Azure/acs-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/api/vlabs" + "github.com/Azure/aks-engine/pkg/i18n" ) // VlabsContainerService is the type we read and write from file -// needed because the json that is sent to ARM and acs-engine +// needed because the json that is sent to ARM and aks-engine // is different from the json that the ACS RP Api gets from ARM type VlabsContainerService struct { api.TypeMeta *vlabs.ContainerService } -// V20160330ContainerService is the type we read and write from file -// needed because the json that is sent to ARM and acs-engine -// is different from the json that the ACS RP Api gets from ARM -type V20160330ContainerService struct { - api.TypeMeta - *v20160330.ContainerService -} - //DockerSpecConfig is the configurations of docker type DockerSpecConfig struct { DockerEngineRepo string DockerComposeDownloadURL string } -//DCOSSpecConfig is the configurations of DCOS -type DCOSSpecConfig struct { - DCOS188BootstrapDownloadURL string - DCOS190BootstrapDownloadURL string - DCOS198BootstrapDownloadURL string - DCOS110BootstrapDownloadURL string - DCOS111BootstrapDownloadURL string - DCOSWindowsBootstrapDownloadURL string - DcosRepositoryURL string // For custom install, for example CI, need these three addributes - DcosClusterPackageListID string // the id of the package list file - DcosProviderPackageID string // the id of the dcos-provider-xxx package -} - //KubernetesSpecConfig is the kubernetes container images used. type KubernetesSpecConfig struct { KubernetesImageBase string diff --git a/pkg/helpers/Get-AzureConstants.py b/pkg/helpers/Get-AzureConstants.py index 24042a9048..d567f9ee44 100644 --- a/pkg/helpers/Get-AzureConstants.py +++ b/pkg/helpers/Get-AzureConstants.py @@ -22,20 +22,7 @@ def getAllSizes(): return sizeMap -min_cores_dcos = 2 min_cores_k8s = 1 -dcos_masters_ephemeral_disk_min = 16384 - -def getDcosMasterMap(sizeMap): - masterMap = {} - - for key in sizeMap.keys(): - size = sizeMap[key] - if size['numberOfCores'] >= min_cores_dcos and \ - size['resourceDiskSizeInMb'] >= dcos_masters_ephemeral_disk_min: - masterMap[size['name']] = size - - return masterMap def getMasterAgentMap(sizeMap): agentMap = {} @@ -71,7 +58,7 @@ def getStorageAccountType(sizeName): else: return "Standard_LRS" -def getFileContents(dcosMasterMap, masterAgentMap, kubernetesAgentMap, sizeMap, locations): +def getFileContents(masterAgentMap, kubernetesAgentMap, sizeMap, locations): text = r"""package helpers // AUTOGENERATED FILE """ @@ -101,19 +88,6 @@ def getFileContents(dcosMasterMap, masterAgentMap, kubernetesAgentMap, sizeMap, } } -// GetDCOSMasterAllowedSizes returns the master allowed sizes -func GetDCOSMasterAllowedSizes() string { - return ` "allowedValues": [ -""" - dcosMasterMapKeys = sorted(dcosMasterMap.keys()) - for key in dcosMasterMapKeys[:-1]: - text += ' "' + key + '",\n' - text += ' "' + dcosMasterMapKeys[-1] + '"\n' - - text += r""" ], -` -} - // GetMasterAgentAllowedSizes returns the agent allowed sizes func GetMasterAgentAllowedSizes() string { return ` "allowedValues": [ @@ -202,11 +176,10 @@ def getFileContents(dcosMasterMap, masterAgentMap, kubernetesAgentMap, sizeMap, def main(): outfile = 'pkg/helpers/azureconst.go' allSizes = getAllSizes() - dcosMasterMap = getDcosMasterMap(allSizes) masterAgentMap = getMasterAgentMap(allSizes) kubernetesAgentMap = allSizes locations = getLocations() - text = getFileContents(dcosMasterMap, masterAgentMap, kubernetesAgentMap, allSizes, locations) + text = getFileContents(masterAgentMap, kubernetesAgentMap, allSizes, locations) with open(outfile, 'w') as f: f.write(text) diff --git a/pkg/helpers/azureconst.go b/pkg/helpers/azureconst.go index 0d5d3242b9..b201555bef 100644 --- a/pkg/helpers/azureconst.go +++ b/pkg/helpers/azureconst.go @@ -57,206 +57,6 @@ func GetAzureLocations() []string { } } -// GetDCOSMasterAllowedSizes returns the master allowed sizes -func GetDCOSMasterAllowedSizes() string { - return ` "allowedValues": [ - "Standard_A10", - "Standard_A11", - "Standard_A2", - "Standard_A2_v2", - "Standard_A2m_v2", - "Standard_A3", - "Standard_A4", - "Standard_A4_v2", - "Standard_A4m_v2", - "Standard_A5", - "Standard_A6", - "Standard_A7", - "Standard_A8", - "Standard_A8_v2", - "Standard_A8m_v2", - "Standard_A9", - "Standard_B2ms", - "Standard_B4ms", - "Standard_B8ms", - "Standard_D11", - "Standard_D11_v2", - "Standard_D11_v2_Promo", - "Standard_D12", - "Standard_D12_v2", - "Standard_D12_v2_Promo", - "Standard_D13", - "Standard_D13_v2", - "Standard_D13_v2_Promo", - "Standard_D14", - "Standard_D14_v2", - "Standard_D14_v2_Promo", - "Standard_D15_v2", - "Standard_D16_v3", - "Standard_D16s_v3", - "Standard_D2", - "Standard_D2_v2", - "Standard_D2_v2_Promo", - "Standard_D2_v3", - "Standard_D2s_v3", - "Standard_D3", - "Standard_D32_v3", - "Standard_D32s_v3", - "Standard_D3_v2", - "Standard_D3_v2_Promo", - "Standard_D4", - "Standard_D4_v2", - "Standard_D4_v2_Promo", - "Standard_D4_v3", - "Standard_D4s_v3", - "Standard_D5_v2", - "Standard_D5_v2_Promo", - "Standard_D64_v3", - "Standard_D64s_v3", - "Standard_D8_v3", - "Standard_D8s_v3", - "Standard_DC2s", - "Standard_DC4s", - "Standard_DS11", - "Standard_DS11-1_v2", - "Standard_DS11_v2", - "Standard_DS11_v2_Promo", - "Standard_DS12", - "Standard_DS12-1_v2", - "Standard_DS12-2_v2", - "Standard_DS12_v2", - "Standard_DS12_v2_Promo", - "Standard_DS13", - "Standard_DS13-2_v2", - "Standard_DS13-4_v2", - "Standard_DS13_v2", - "Standard_DS13_v2_Promo", - "Standard_DS14", - "Standard_DS14-4_v2", - "Standard_DS14-8_v2", - "Standard_DS14_v2", - "Standard_DS14_v2_Promo", - "Standard_DS15_v2", - "Standard_DS3", - "Standard_DS3_v2", - "Standard_DS3_v2_Promo", - "Standard_DS4", - "Standard_DS4_v2", - "Standard_DS4_v2_Promo", - "Standard_DS5_v2", - "Standard_DS5_v2_Promo", - "Standard_E16-4s_v3", - "Standard_E16-8s_v3", - "Standard_E16_v3", - "Standard_E16s_v3", - "Standard_E20_v3", - "Standard_E20s_v3", - "Standard_E2_v3", - "Standard_E2s_v3", - "Standard_E32-16s_v3", - "Standard_E32-8s_v3", - "Standard_E32_v3", - "Standard_E32s_v3", - "Standard_E4-2s_v3", - "Standard_E4_v3", - "Standard_E4s_v3", - "Standard_E64-16s_v3", - "Standard_E64-32s_v3", - "Standard_E64_v3", - "Standard_E64i_v3", - "Standard_E64is_v3", - "Standard_E64s_v3", - "Standard_E8-2s_v3", - "Standard_E8-4s_v3", - "Standard_E8_v3", - "Standard_E8s_v3", - "Standard_F16", - "Standard_F16s", - "Standard_F16s_v2", - "Standard_F2", - "Standard_F2s_v2", - "Standard_F32s_v2", - "Standard_F4", - "Standard_F4s", - "Standard_F4s_v2", - "Standard_F64s_v2", - "Standard_F72s_v2", - "Standard_F8", - "Standard_F8s", - "Standard_F8s_v2", - "Standard_G1", - "Standard_G2", - "Standard_G3", - "Standard_G4", - "Standard_G5", - "Standard_GS1", - "Standard_GS2", - "Standard_GS3", - "Standard_GS4", - "Standard_GS4-4", - "Standard_GS4-8", - "Standard_GS5", - "Standard_GS5-16", - "Standard_GS5-8", - "Standard_H16", - "Standard_H16m", - "Standard_H16mr", - "Standard_H16r", - "Standard_H8", - "Standard_H8m", - "Standard_L16s", - "Standard_L16s_v2", - "Standard_L32s", - "Standard_L4s", - "Standard_L8s", - "Standard_L8s_v2", - "Standard_M128", - "Standard_M128-32ms", - "Standard_M128-64ms", - "Standard_M128m", - "Standard_M128ms", - "Standard_M128s", - "Standard_M16-4ms", - "Standard_M16-8ms", - "Standard_M16ms", - "Standard_M32-16ms", - "Standard_M32-8ms", - "Standard_M32ls", - "Standard_M32ms", - "Standard_M32ts", - "Standard_M64", - "Standard_M64-16ms", - "Standard_M64-32ms", - "Standard_M64ls", - "Standard_M64m", - "Standard_M64ms", - "Standard_M64s", - "Standard_M8-2ms", - "Standard_M8-4ms", - "Standard_M8ms", - "Standard_NC12", - "Standard_NC12s_v2", - "Standard_NC12s_v3", - "Standard_NC24", - "Standard_NC24r", - "Standard_NC24rs_v2", - "Standard_NC24rs_v3", - "Standard_NC24s_v2", - "Standard_NC24s_v3", - "Standard_NC6", - "Standard_NC6s_v2", - "Standard_NC6s_v3", - "Standard_ND12s", - "Standard_ND24rs", - "Standard_ND24s", - "Standard_ND6s", - "Standard_NV12", - "Standard_NV24", - "Standard_NV6" - ], -` -} - // GetMasterAgentAllowedSizes returns the agent allowed sizes func GetMasterAgentAllowedSizes() string { return ` "allowedValues": [ diff --git a/pkg/helpers/filesaver.go b/pkg/helpers/filesaver.go index a63dd9776a..8573a76ade 100644 --- a/pkg/helpers/filesaver.go +++ b/pkg/helpers/filesaver.go @@ -5,7 +5,7 @@ import ( "os" "path" - "github.com/Azure/acs-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/i18n" log "github.com/sirupsen/logrus" ) diff --git a/pkg/helpers/helpers.go b/pkg/helpers/helpers.go index 9d925ee99f..1e35e4ffbc 100644 --- a/pkg/helpers/helpers.go +++ b/pkg/helpers/helpers.go @@ -12,7 +12,7 @@ import ( "runtime" "strings" - "github.com/Azure/acs-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/i18n" "golang.org/x/crypto/ssh" ) diff --git a/pkg/helpers/helpers_test.go b/pkg/helpers/helpers_test.go index e1f34d83e0..42cbb18f0b 100644 --- a/pkg/helpers/helpers_test.go +++ b/pkg/helpers/helpers_test.go @@ -11,7 +11,7 @@ import ( "strings" "testing" - "github.com/Azure/acs-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/i18n" "github.com/pkg/errors" ) diff --git a/pkg/i18n/README.md b/pkg/i18n/README.md index 5ff5dd1592..603eadcf62 100644 --- a/pkg/i18n/README.md +++ b/pkg/i18n/README.md @@ -1,13 +1,13 @@ -# Translation and Internationalization in acs-engine -The translation process in acs-engine borrows some approach from [Kubernetes translation](https://github.com/kubernetes/kubernetes/tree/master/translations). +# Translation and Internationalization in aks-engine +The translation process in aks-engine borrows some approach from [Kubernetes translation](https://github.com/kubernetes/kubernetes/tree/master/translations). The strings to be localized are mainly the error message strings under `pkg` directory. Those error message strings are also consumed by other components such as ACS RP. -The localization in acs-engine depends on github.com/leonelquinteros/gotext, a GNU gettext utility for Go. The package supports concurrency in translating strings in multiple goroutines, e.g., the same acs-engine API called from multiple requests at the same time. +The localization in aks-engine depends on github.com/leonelquinteros/gotext, a GNU gettext utility for Go. The package supports concurrency in translating strings in multiple goroutines, e.g., the same aks-engine API called from multiple requests at the same time. -The translation files containing resource strings are packaged into acs-engine binary using go-bindata. At runtime, the translation files are recreated on disk in the same directory as acs-engine binary, for gotext to load. +The translation files containing resource strings are packaged into aks-engine binary using go-bindata. At runtime, the translation files are recreated on disk in the same directory as aks-engine binary, for gotext to load. ## How to add new string to be localized -When a new error string needs to be localized, it needs to use translation function Errorf in `pkg/i18n/i18n.go`. The locale is passed to acs-engine API from acs-engine command or any other component calls it. If the locale is nil, then it falls back to en-us as in the Go source file. +When a new error string needs to be localized, it needs to use translation function Errorf in `pkg/i18n/i18n.go`. The locale is passed to aks-engine API from aks-engine command or any other component calls it. If the locale is nil, then it falls back to en-us as in the Go source file. Once the Go source file is modified, `scripts/update-translation.sh` needs to be run to extract the resource strings. The script generates PO file according to the locale specified. An example of running the script is: ``` diff --git a/pkg/i18n/const.go b/pkg/i18n/const.go index 3f60e73674..dd6d6b7500 100644 --- a/pkg/i18n/const.go +++ b/pkg/i18n/const.go @@ -2,7 +2,7 @@ package i18n const ( defaultLanguage = "en_US" - defaultDomain = "acsengine" + defaultDomain = "aksengine" defaultLocalDir = "translations" defaultMessageDir = "LC_MESSAGES" ) diff --git a/pkg/i18n/translations/en_US/LC_MESSAGES/acsengine.mo b/pkg/i18n/translations/en_US/LC_MESSAGES/aksengine.mo similarity index 100% rename from pkg/i18n/translations/en_US/LC_MESSAGES/acsengine.mo rename to pkg/i18n/translations/en_US/LC_MESSAGES/aksengine.mo diff --git a/pkg/i18n/translations/en_US/LC_MESSAGES/acsengine.po b/pkg/i18n/translations/en_US/LC_MESSAGES/aksengine.po similarity index 93% rename from pkg/i18n/translations/en_US/LC_MESSAGES/acsengine.po rename to pkg/i18n/translations/en_US/LC_MESSAGES/aksengine.po index e8283edc67..a634725707 100644 --- a/pkg/i18n/translations/en_US/LC_MESSAGES/acsengine.po +++ b/pkg/i18n/translations/en_US/LC_MESSAGES/aksengine.po @@ -1,10 +1,10 @@ -# Test translations for acsengine package. +# Test translations for aksengine package. # Copyright (C) 2017 # Jiangtian Li , 2017. # msgid "" msgstr "" -"Project-Id-Version: acsengine\n" +"Project-Id-Version: aksengine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-05-18 00:31+0000\n" "PO-Revision-Date: 2017-05-17 17:35-0700\n" diff --git a/pkg/openshift/OWNERS b/pkg/openshift/OWNERS deleted file mode 100644 index 4e1cf8514f..0000000000 --- a/pkg/openshift/OWNERS +++ /dev/null @@ -1,4 +0,0 @@ -approvers: -- jim-minter -- kargakis -- pweil- diff --git a/pkg/openshift/certgen/release39/config.go b/pkg/openshift/certgen/release39/config.go deleted file mode 100644 index ea6167d238..0000000000 --- a/pkg/openshift/certgen/release39/config.go +++ /dev/null @@ -1,113 +0,0 @@ -package release39 - -import ( - "crypto/rsa" - "crypto/x509" - "math/big" - "net" - "sync" - - "github.com/Azure/acs-engine/pkg/openshift/filesystem" -) - -// Config represents an OpenShift configuration -type Config struct { - ExternalMasterHostname string - serial serial - cas map[string]CertAndKey - AuthSecret string - EncSecret string - Master *Master - Bootstrap KubeConfig - ClusterUsername string - ClusterPassword string - EnableAADAuthentication bool - AzureConfig AzureConfig -} - -// AzureConfig represents the azure.conf configuration -type AzureConfig struct { - TenantID string - SubscriptionID string - AADClientID string - AADClientSecret string - ResourceGroup string - Location string - SecurityGroupName string - PrimaryAvailabilitySetName string -} - -// Master represents an OpenShift master configuration -type Master struct { - Hostname string - IPs []net.IP - Port int16 - - certs map[string]CertAndKey - etcdcerts map[string]CertAndKey - kubeconfigs map[string]KubeConfig -} - -// CertAndKey is a certificate and key -type CertAndKey struct { - cert *x509.Certificate - key *rsa.PrivateKey -} - -type serial struct { - m sync.Mutex - i int64 -} - -func (s *serial) Get() *big.Int { - s.m.Lock() - defer s.m.Unlock() - - s.i++ - return big.NewInt(s.i) -} - -// WriteMaster writes the config files for a Master node to a Filesystem. -func (c *Config) WriteMaster(fs filesystem.Writer) error { - err := c.WriteMasterCerts(fs) - if err != nil { - return err - } - - err = c.WriteMasterKeypair(fs) - if err != nil { - return err - } - - err = c.WriteMasterKubeConfigs(fs) - if err != nil { - return err - } - - err = c.WriteMasterFiles(fs) - if err != nil { - return err - } - - err = c.WriteBootstrapCerts(fs) - if err != nil { - return err - } - - return c.WriteNodeFiles(fs) -} - -// WriteNode writes the config files for bootstrapping a node to a Filesystem. -func (c *Config) WriteNode(fs filesystem.Writer) error { - err := c.WriteBootstrapCerts(fs) - if err != nil { - return err - } - - err = c.WriteBootstrapKubeConfig(fs) - if err != nil { - return err - } - - return c.WriteNodeFiles(fs) -} diff --git a/pkg/openshift/certgen/release39/config_test.go b/pkg/openshift/certgen/release39/config_test.go deleted file mode 100644 index e3524814c2..0000000000 --- a/pkg/openshift/certgen/release39/config_test.go +++ /dev/null @@ -1,90 +0,0 @@ -package release39 - -import ( - "fmt" - "net" - "os" - "strings" - "testing" - - "github.com/Azure/acs-engine/pkg/openshift/filesystem" -) - -type fakefilesystem map[string]filesystem.Fileinfo - -func (f fakefilesystem) WriteFile(filename string, data []byte, fi filesystem.Fileinfo) error { - f[filename] = fi - // fmt.Printf("Filename: %v User: %s Group: %s Permissions: %04o string: %v\n", filename, fi.User, fi.Group, fi.Mode, fi.Mode.String()) - return nil -} - -func (f fakefilesystem) Mkdir(filename string, fi filesystem.Fileinfo) error { - // fmt.Printf("Filename: %v User: %s Group: %s Permissions: %04o string: %v\n", filename, fi.User, fi.Group, fi.Mode, fi.Mode.String()) - f[filename] = fi - return nil -} - -func (fakefilesystem) Close() error { - return nil -} - -var _ filesystem.Writer = &fakefilesystem{} - -func TestConfigFilePermissions(t *testing.T) { - c := Config{ - Master: &Master{ - Hostname: fmt.Sprintf("%s-master-%s-0", "test", "test"), - IPs: []net.IP{ - net.ParseIP("10.0.0.1"), - }, - }, - } - - err := c.PrepareMasterCerts() - if err != nil { - t.Fatal(err) - } - err = c.PrepareMasterKubeConfigs() - if err != nil { - t.Fatal(err) - } - err = c.PrepareMasterFiles() - if err != nil { - t.Fatal(err) - } - - err = c.PrepareBootstrapKubeConfig() - if err != nil { - t.Fatal(err) - } - - // create mock filesystem - fs := fakefilesystem{} - - err = c.WriteMaster(fs) - if err != nil { - t.Fatal(err) - } - - for fname, finfo := range fs { - fi := GetFileInfo(fname) - // fmt.Printf("fname=>[%s]\n", fname) - // Verify ownership and permissions are as expected - if fi.User != finfo.User { - t.Errorf("File: %s User does not match. user: %s expected: %s", fname, finfo.User, fi.User) - } - if fi.Group != finfo.Group { - t.Errorf("File: %s Group does not match. group: %s expected: %s", fname, finfo.Group, fi.Group) - } - if fi.Mode != 0 && fi.Mode != finfo.Mode { - t.Errorf("File: %s Mode does not match. mode: %04o expected: %04o", fname, finfo.Mode, fi.Mode) - } - // Check for .key does _not_ have read or write - if strings.HasSuffix(fname, ".key") && finfo.Mode&077 != 0 { - t.Errorf("File: %s Found Read or Write on key file. mode: %04o expected: 0600", fname, finfo.Mode) - } - if fname == "tmp" && fi.Mode != os.FileMode(01777) { - t.Errorf("File: %s /tmp should have 1777 file mode.", fname) - } - } -} diff --git a/pkg/openshift/certgen/release39/defaults.go b/pkg/openshift/certgen/release39/defaults.go deleted file mode 100644 index 67afc0a0b0..0000000000 --- a/pkg/openshift/certgen/release39/defaults.go +++ /dev/null @@ -1,63 +0,0 @@ -package release39 - -import ( - "bytes" - - "github.com/Azure/acs-engine/pkg/openshift/filesystem" -) - -// OpenShiftSetDefaultCerts sets default certificate and configuration properties in the -// openshift orchestrator for 3.9. -func OpenShiftSetDefaultCerts(c *Config) ([]byte, []byte, error) { - - err := c.PrepareMasterCerts() - if err != nil { - return nil, nil, err - } - err = c.PrepareMasterKubeConfigs() - if err != nil { - return nil, nil, err - } - err = c.PrepareMasterFiles() - if err != nil { - return nil, nil, err - } - - err = c.PrepareBootstrapKubeConfig() - if err != nil { - return nil, nil, err - } - - masterBundle, err := getConfigBundle(c.WriteMaster) - if err != nil { - return nil, nil, err - } - nodeBundle, err := getConfigBundle(c.WriteNode) - if err != nil { - return nil, nil, err - } - return masterBundle, nodeBundle, nil -} - -type writeFn func(filesystem.Writer) error - -func getConfigBundle(write writeFn) ([]byte, error) { - b := &bytes.Buffer{} - - fs, err := filesystem.NewTGZWriter(b) - if err != nil { - return nil, err - } - - err = write(fs) - if err != nil { - return nil, err - } - - err = fs.Close() - if err != nil { - return nil, err - } - - return b.Bytes(), nil -} diff --git a/pkg/openshift/certgen/release39/doc.go b/pkg/openshift/certgen/release39/doc.go deleted file mode 100644 index 702b817799..0000000000 --- a/pkg/openshift/certgen/release39/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -// Package release39 provides utilities related -// to generating all the necessary artifacts -// for an OpenShift deployment. -package release39 diff --git a/pkg/openshift/certgen/release39/files.go b/pkg/openshift/certgen/release39/files.go deleted file mode 100644 index c6ea18d53c..0000000000 --- a/pkg/openshift/certgen/release39/files.go +++ /dev/null @@ -1,179 +0,0 @@ -package release39 - -import ( - "bytes" - "crypto/rand" - "encoding/base64" - "os" - "regexp" - "strconv" - "strings" - "text/template" - - "github.com/Azure/acs-engine/pkg/openshift/certgen/release39/templates" - "github.com/Azure/acs-engine/pkg/openshift/filesystem" - "golang.org/x/crypto/bcrypt" -) - -type modeinfo struct { - path *regexp.Regexp - mode os.FileMode - user string - group string -} - -// These ownerships are processed in order -var ownerships = []modeinfo{ - // etc/etcd directory - {path: regexp.MustCompile(`^etc/etcd$`), mode: 0755, user: "etcd", group: "etcd"}, - // tmp directory - {path: regexp.MustCompile(`^tmp$`), mode: 01777, user: "root", group: "root"}, - //start files - {path: regexp.MustCompile(`^etc/etcd/.*\.key$`), mode: 0600, user: "etcd", group: "etcd"}, - {path: regexp.MustCompile(`^etc/etcd/.*$`), user: "etcd", group: "etcd"}, - {path: regexp.MustCompile(`.*\.key$`), mode: 0600}, - {path: regexp.MustCompile(`.*\.kubeconfig$`), mode: 0600}, - {path: regexp.MustCompile(`^etc/origin/master/htpasswd$`), mode: 0600}, -} - -// GetFileInfo returns the permissions and ownership of the file if defined -func GetFileInfo(filename string) filesystem.Fileinfo { - // If filename matches a specific path then set the correct User, Group, and Mode - f := filesystem.Fileinfo{User: "root", Group: "root", Mode: 0644} - for _, owner := range ownerships { - - if owner.path.MatchString(filename) { - if owner.user != "" { - f.User = owner.user - } - if owner.group != "" { - f.Group = owner.group - } - if owner.mode != 0 { - f.Mode = owner.mode - } - break - } - } - - return f -} - -// PrepareMasterFiles creates the shared authentication and encryption secrets -func (c *Config) PrepareMasterFiles() error { - b := make([]byte, 24) - _, err := rand.Read(b) - if err != nil { - return err - } - c.AuthSecret = base64.StdEncoding.EncodeToString(b) - - _, err = rand.Read(b) - if err != nil { - return err - } - c.EncSecret = base64.StdEncoding.EncodeToString(b) - - return nil -} - -// WriteMasterFiles writes the templated master config -func (c *Config) WriteMasterFiles(fs filesystem.Writer) error { - - // create special case directories - specialCaseDirs := map[string]filesystem.Fileinfo{ - "tmp": { - User: "root", - Group: "root", - Mode: os.FileMode(01777), - }, - "etc/etcd": { - Mode: os.FileMode(0755), - User: "etcd", - Group: "etcd", - }, - } - - for na, fi := range specialCaseDirs { - err := fs.Mkdir(na, fi) - if err != nil { - return err - } - } - - for _, name := range templates.AssetNames() { - if !strings.HasPrefix(name, "master/") { - continue - } - tb := templates.MustAsset(name) - - t, err := template.New("template").Funcs(template.FuncMap{ - "QuoteMeta": regexp.QuoteMeta, - "Bcrypt": func(password string) (string, error) { - h, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) - return string(h), err - }, - "quote": strconv.Quote, - "shellQuote": func(s string) string { - return `'` + strings.Replace(s, `'`, `'\''`, -1) + `'` - }, - }).Parse(string(tb)) - if err != nil { - return err - } - - b := &bytes.Buffer{} - err = t.Execute(b, c) - if err != nil { - return err - } - - fname := strings.TrimPrefix(name, "master/") - fi := GetFileInfo(fname) - - err = fs.WriteFile(fname, b.Bytes(), fi) - if err != nil { - return err - } - } - - return nil -} - -// WriteNodeFiles writes the templated node config -func (c *Config) WriteNodeFiles(fs filesystem.Writer) error { - for _, name := range templates.AssetNames() { - if !strings.HasPrefix(name, "node/") { - continue - } - - tb := templates.MustAsset(name) - - t, err := template.New("template").Funcs(template.FuncMap{ - "QuoteMeta": regexp.QuoteMeta, - "quote": strconv.Quote, - "shellQuote": func(s string) string { - return `'` + strings.Replace(s, `'`, `'\''`, -1) + `'` - }, - }).Parse(string(tb)) - if err != nil { - return err - } - - b := &bytes.Buffer{} - err = t.Execute(b, c) - if err != nil { - return err - } - - fname := strings.TrimPrefix(name, "node/") - fi := GetFileInfo(fname) - - err = fs.WriteFile(fname, b.Bytes(), fi) - if err != nil { - return err - } - } - - return nil -} diff --git a/pkg/openshift/certgen/release39/kubeconfig.go b/pkg/openshift/certgen/release39/kubeconfig.go deleted file mode 100644 index d4a05f604c..0000000000 --- a/pkg/openshift/certgen/release39/kubeconfig.go +++ /dev/null @@ -1,288 +0,0 @@ -package release39 - -import ( - "encoding/base64" - "fmt" - "os" - "strings" - - "github.com/Azure/acs-engine/pkg/openshift/filesystem" - yaml "gopkg.in/yaml.v2" -) - -// KubeConfig represents a kubeconfig -type KubeConfig struct { - APIVersion string `yaml:"apiVersion,omitempty"` - Kind string `yaml:"kind,omitempty"` - Clusters []Cluster `yaml:"clusters,omitempty"` - Contexts []Context `yaml:"contexts,omitempty"` - CurrentContext string `yaml:"current-context,omitempty"` - Preferences map[string]interface{} `yaml:"preferences,omitempty"` - Users []User `yaml:"users,omitempty"` -} - -// Cluster represents a kubeconfig cluster -type Cluster struct { - Name string `yaml:"name,omitempty"` - Cluster ClusterInfo `yaml:"cluster,omitempty"` -} - -// ClusterInfo represents a kubeconfig clusterinfo -type ClusterInfo struct { - Server string `yaml:"server,omitempty"` - CertificateAuthorityData string `yaml:"certificate-authority-data,omitempty"` -} - -// Context represents a kubeconfig context -type Context struct { - Name string `yaml:"name,omitempty"` - Context ContextInfo `yaml:"context,omitempty"` -} - -// ContextInfo represents a kubeconfig contextinfo -type ContextInfo struct { - Cluster string `yaml:"cluster,omitempty"` - Namespace string `yaml:"namespace,omitempty"` - User string `yaml:"user,omitempty"` -} - -// User represents a kubeconfig user -type User struct { - Name string `yaml:"name,omitempty"` - User UserInfo `yaml:"user,omitempty"` -} - -// UserInfo represents a kubeconfig userinfo -type UserInfo struct { - ClientCertificateData string `yaml:"client-certificate-data,omitempty"` - ClientKeyData string `yaml:"client-key-data,omitempty"` -} - -// PrepareMasterKubeConfigs creates the master kubeconfigs -func (c *Config) PrepareMasterKubeConfigs() error { - endpoint := fmt.Sprintf("%s:%d", c.Master.Hostname, c.Master.Port) - endpointName := strings.Replace(endpoint, ".", "-", -1) - - externalEndpoint := fmt.Sprintf("%s:%d", c.ExternalMasterHostname, c.Master.Port) - externalEndpointName := strings.Replace(externalEndpoint, ".", "-", -1) - - localhostEndpoint := fmt.Sprintf("localhost:%d", c.Master.Port) - localhostEndpointName := strings.Replace(localhostEndpoint, ".", "-", -1) - - cacert, err := certAsBytes(c.cas["etc/origin/master/ca"].cert) - if err != nil { - return err - } - admincert, err := certAsBytes(c.Master.certs["etc/origin/master/admin"].cert) - if err != nil { - return err - } - adminkey, err := privateKeyAsBytes(c.Master.certs["etc/origin/master/admin"].key) - if err != nil { - return err - } - mastercert, err := certAsBytes(c.Master.certs["etc/origin/master/openshift-master"].cert) - if err != nil { - return err - } - masterkey, err := privateKeyAsBytes(c.Master.certs["etc/origin/master/openshift-master"].key) - if err != nil { - return err - } - aggregatorcert, err := certAsBytes(c.Master.certs["etc/origin/master/aggregator-front-proxy"].cert) - if err != nil { - return err - } - aggregatorkey, err := privateKeyAsBytes(c.Master.certs["etc/origin/master/aggregator-front-proxy"].key) - if err != nil { - return err - } - - c.Master.kubeconfigs = map[string]KubeConfig{ - "etc/origin/master/admin.kubeconfig": { - APIVersion: "v1", - Kind: "Config", - Clusters: []Cluster{ - { - Name: externalEndpointName, - Cluster: ClusterInfo{ - Server: fmt.Sprintf("https://%s", externalEndpoint), - CertificateAuthorityData: base64.StdEncoding.EncodeToString(cacert), - }, - }, - }, - Contexts: []Context{ - { - Name: fmt.Sprintf("default/%s/system:admin", externalEndpointName), - Context: ContextInfo{ - Cluster: externalEndpointName, - Namespace: "default", - User: fmt.Sprintf("system:admin/%s", externalEndpointName), - }, - }, - }, - CurrentContext: fmt.Sprintf("default/%s/system:admin", externalEndpointName), - Users: []User{ - { - Name: fmt.Sprintf("system:admin/%s", externalEndpointName), - User: UserInfo{ - ClientCertificateData: base64.StdEncoding.EncodeToString(admincert), - ClientKeyData: base64.StdEncoding.EncodeToString(adminkey), - }, - }, - }, - }, - "etc/origin/master/aggregator-front-proxy.kubeconfig": { - APIVersion: "v1", - Kind: "Config", - Clusters: []Cluster{ - { - Name: localhostEndpointName, - Cluster: ClusterInfo{ - Server: fmt.Sprintf("https://%s", localhostEndpoint), - CertificateAuthorityData: base64.StdEncoding.EncodeToString(cacert), - }, - }, - }, - Contexts: []Context{ - { - Name: fmt.Sprintf("default/%s/aggregator-front-proxy", localhostEndpointName), - Context: ContextInfo{ - Cluster: localhostEndpointName, - Namespace: "default", - User: fmt.Sprintf("aggregator-front-proxy/%s", localhostEndpointName), - }, - }, - }, - CurrentContext: fmt.Sprintf("default/%s/aggregator-front-proxy", localhostEndpointName), - Users: []User{ - { - Name: fmt.Sprintf("aggregator-front-proxy/%s", localhostEndpointName), - User: UserInfo{ - ClientCertificateData: base64.StdEncoding.EncodeToString(aggregatorcert), - ClientKeyData: base64.StdEncoding.EncodeToString(aggregatorkey), - }, - }, - }, - }, - "etc/origin/master/openshift-master.kubeconfig": { - APIVersion: "v1", - Kind: "Config", - Clusters: []Cluster{ - { - Name: endpointName, - Cluster: ClusterInfo{ - Server: fmt.Sprintf("https://%s", endpoint), - CertificateAuthorityData: base64.StdEncoding.EncodeToString(cacert), - }, - }, - }, - Contexts: []Context{ - { - Name: fmt.Sprintf("default/%s/system:openshift-master", endpointName), - Context: ContextInfo{ - Cluster: endpointName, - Namespace: "default", - User: fmt.Sprintf("system:openshift-master/%s", endpointName), - }, - }, - }, - CurrentContext: fmt.Sprintf("default/%s/system:openshift-master", endpointName), - Users: []User{ - { - Name: fmt.Sprintf("system:openshift-master/%s", endpointName), - User: UserInfo{ - ClientCertificateData: base64.StdEncoding.EncodeToString(mastercert), - ClientKeyData: base64.StdEncoding.EncodeToString(masterkey), - }, - }, - }, - }, - } - - c.Master.kubeconfigs["etc/origin/node/bootstrap.kubeconfig"] = c.Master.kubeconfigs["etc/origin/master/admin.kubeconfig"] - - return nil -} - -// PrepareBootstrapKubeConfig creates the node bootstrap kubeconfig -func (c *Config) PrepareBootstrapKubeConfig() error { - ep := fmt.Sprintf("%s:%d", c.ExternalMasterHostname, c.Master.Port) - epName := strings.Replace(ep, ".", "-", -1) - - cacert, err := certAsBytes(c.cas["etc/origin/master/ca"].cert) - if err != nil { - return err - } - - bootstrapCert, err := certAsBytes(c.Master.certs["etc/origin/master/node-bootstrapper"].cert) - if err != nil { - return err - } - bootstrapKey, err := privateKeyAsBytes(c.Master.certs["etc/origin/master/node-bootstrapper"].key) - if err != nil { - return err - } - - c.Bootstrap = KubeConfig{ - APIVersion: "v1", - Kind: "Config", - Clusters: []Cluster{ - { - Name: epName, - Cluster: ClusterInfo{ - Server: fmt.Sprintf("https://%s", ep), - CertificateAuthorityData: base64.StdEncoding.EncodeToString(cacert), - }, - }, - }, - Contexts: []Context{ - { - Name: fmt.Sprintf("default/%s/system:serviceaccount:openshift-infra:node-bootstrapper", epName), - Context: ContextInfo{ - Cluster: epName, - Namespace: "default", - User: fmt.Sprintf("system:serviceaccount:openshift-infra:node-bootstrapper/%s", epName), - }, - }, - }, - CurrentContext: fmt.Sprintf("default/%s/system:serviceaccount:openshift-infra:node-bootstrapper", epName), - Users: []User{ - { - Name: fmt.Sprintf("system:serviceaccount:openshift-infra:node-bootstrapper/%s", epName), - User: UserInfo{ - ClientCertificateData: base64.StdEncoding.EncodeToString(bootstrapCert), - ClientKeyData: base64.StdEncoding.EncodeToString(bootstrapKey), - }, - }, - }, - } - - return nil -} - -// WriteMasterKubeConfigs writes the master kubeconfigs -func (c *Config) WriteMasterKubeConfigs(fs filesystem.Writer) error { - for filename, kubeconfig := range c.Master.kubeconfigs { - b, err := yaml.Marshal(&kubeconfig) - if err != nil { - return err - } - err = fs.WriteFile(filename, b, filesystem.Fileinfo{User: "root", Group: "root", Mode: os.FileMode(0600)}) - if err != nil { - return err - } - } - - return nil -} - -// WriteBootstrapKubeConfig writes the node bootstrap kubeconfig -func (c *Config) WriteBootstrapKubeConfig(fs filesystem.Writer) error { - b, err := yaml.Marshal(&c.Bootstrap) - if err != nil { - return err - } - - return fs.WriteFile("etc/origin/node/bootstrap.kubeconfig", b, filesystem.Fileinfo{User: "root", Group: "root", Mode: os.FileMode(0600)}) -} diff --git a/pkg/openshift/certgen/release39/templates/bindata.go b/pkg/openshift/certgen/release39/templates/bindata.go deleted file mode 100644 index 6a82082af2..0000000000 --- a/pkg/openshift/certgen/release39/templates/bindata.go +++ /dev/null @@ -1,560 +0,0 @@ -// Code generated by go-bindata. DO NOT EDIT. @generated -// sources: -// master/etc/etcd/etcd.conf -// master/etc/origin/master/htpasswd -// master/etc/origin/master/master-config.yaml -// master/etc/origin/master/scheduler.json -// master/etc/origin/master/session-secrets.yaml -// master/tmp/ansible/ansible.sh -// master/tmp/ansible/azure-local-master-inventory.yml -// master/tmp/ansible/azure-ocp-deploy.yml -// master/tmp/bootstrapconfigs/compute-config.yaml -// master/tmp/bootstrapconfigs/infra-config.yaml -// master/tmp/bootstrapconfigs/master-config.yaml -// node/etc/azure/azure.conf -// node/etc/origin/node/node-dnsmasq.conf -// node/etc/origin/node/resolv.conf -// DO NOT EDIT! - -package templates - -import ( - "bytes" - "compress/gzip" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - "time" -) - -func bindataRead(data []byte, name string) ([]byte, error) { - gz, err := gzip.NewReader(bytes.NewBuffer(data)) - if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) - } - - var buf bytes.Buffer - _, err = io.Copy(&buf, gz) - clErr := gz.Close() - - if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) - } - if clErr != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -type asset struct { - bytes []byte - info os.FileInfo -} - -type bindataFileInfo struct { - name string - size int64 - mode os.FileMode - modTime time.Time -} - -func (fi bindataFileInfo) Name() string { - return fi.name -} -func (fi bindataFileInfo) Size() int64 { - return fi.size -} -func (fi bindataFileInfo) Mode() os.FileMode { - return fi.mode -} -func (fi bindataFileInfo) ModTime() time.Time { - return fi.modTime -} -func (fi bindataFileInfo) IsDir() bool { - return false -} -func (fi bindataFileInfo) Sys() interface{} { - return nil -} - -var _masterEtcEtcdEtcdConf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x54\x5d\x6f\xea\x38\x10\x7d\xcf\xaf\x88\xcc\xcb\xee\xc3\x85\x94\xdb\x8f\xa5\x92\x1f\x8c\x33\x80\x85\x49\x52\xdb\x81\xa2\xaa\xb2\x28\x0d\x34\xda\x14\x50\x12\xba\xad\xba\xfd\xef\x2b\x27\x81\xd0\xc2\xae\x56\xba\xea\x1b\xcc\x1c\xcf\x9c\x39\x73\x26\xa0\xa8\xab\x3d\x32\x02\xfc\xfe\x6e\x37\x47\xb3\x2c\x8f\xd2\xe6\x60\x9d\xe5\xab\xd9\x73\x64\xff\x6d\x67\x4f\x51\x92\xdc\x6c\xd7\x79\x64\x7f\x7c\x58\x05\x9a\x33\xa9\xc0\xd3\x01\x80\xd0\xa1\xe0\xd2\xbc\xdc\xa4\xf1\x2a\xb7\xd1\x53\x9e\x6f\xb2\xeb\x56\x0b\xd9\xbf\xc5\xab\xc7\xe8\x75\x5f\x91\x05\x99\xed\xfc\xde\x94\x79\x1a\xaf\x96\x36\xba\x6e\xff\xfc\xc3\x41\xa7\xcb\xbb\x44\x11\xed\x32\x81\x5b\x2f\xb3\xb4\x95\xc4\x0f\xad\x28\x9f\x3f\xb6\xac\x46\x91\x9d\x10\x5e\x24\x11\xaa\x02\xd2\x23\x81\x1c\xf8\x4a\x53\x3f\xf4\x14\x3e\x73\x1c\xc7\x29\x0b\x0d\x80\x08\xd5\x05\xa2\x34\xf3\x14\x88\x31\xe1\xf8\x62\x97\x03\x0e\x54\x31\xdf\xd3\x8a\x8d\xc0\x0f\x15\x6e\xef\x53\xd5\x78\x94\x33\xf0\xd4\x2f\x0c\x78\xd5\x39\x1e\xb0\xa4\x3c\x22\xb7\x7b\xda\x12\x5f\x1c\x44\x27\x84\xd7\x01\xea\x0b\x89\x2d\xcb\x6a\xdc\xcd\x93\xad\x69\x72\x5f\x12\x64\x1e\x53\x8c\x70\x4d\xdc\x31\x08\xc5\x24\x7c\xdb\x2a\x76\x9d\x28\x0f\xa5\x02\x51\x57\x3f\x32\x0a\xc2\xdf\xd0\x4f\x4b\x45\x14\xe0\x55\xf4\xd7\xe9\xb4\xf2\x87\xe0\x61\xe3\x8e\x1f\x95\x42\x3f\xce\x2a\xed\x5c\x26\xa9\x3f\x06\x31\xc5\x5f\x03\x5a\x8a\xf1\x71\xb0\x47\x38\xef\x12\x3a\xc4\x9b\x74\xfd\xfa\x76\x94\x0e\x84\x7f\x3b\xc5\x25\x8b\x5a\xf6\x6f\xb4\x88\x54\x82\x51\xa5\x05\x50\xdf\xeb\xb1\xbe\xa6\x03\xa0\x43\x8c\x16\xb3\x24\x8b\x76\xce\x27\xa1\xf2\x35\xf5\x47\x01\x29\xad\x2c\x40\x81\x67\x7e\x61\xe4\xec\x30\xe0\x91\x2e\x07\x3d\x6e\x63\x94\xa7\xdb\x08\x95\x23\xdc\x84\xbe\x22\xda\xcc\x0b\x9e\xab\xbb\x53\x05\x12\x9f\xb7\x3b\xe7\x9d\xcb\xab\x76\xe7\xd2\x38\xae\x90\xe1\xbe\x2a\x52\x4e\xbf\x5e\x2c\x0e\xff\xeb\x1e\x61\x3c\x14\xa0\x27\x84\x29\x8c\x2e\x1c\x67\xdf\xb4\xcc\x0b\xe8\x09\x90\x83\xfa\xf8\xd0\x4f\xe7\x08\xe4\x9a\x7d\xee\x6e\x10\x9d\x1d\xe5\x27\x82\x29\xa8\x01\xa7\xba\x10\xb7\xce\x3b\xc8\x90\xcf\xa2\xf9\x36\x8d\xf3\xb7\xea\x5e\x94\x30\x76\x71\x35\x25\xba\xc7\x38\x60\xf3\x3d\x29\xbf\x29\xf3\x59\x73\x9e\xe6\x25\xaa\x5a\x26\x05\xa1\x8c\xb2\x83\x4f\x82\x15\xd1\x2f\x8f\xb3\x28\x7d\x89\xd2\xba\xc0\x10\xa6\xff\x02\xf9\x33\x7a\x3b\x5c\x99\xe2\x72\xbf\xc9\x72\x12\x73\xbe\xff\x8f\x65\x01\xfd\x4f\xaa\x25\xe2\x04\xdf\x4d\x74\xc8\xb6\x80\x9d\xa0\x5c\xa0\x6a\xc2\x05\xec\x88\xb5\xd5\xb8\x4b\xd6\xcb\x65\xbc\x5a\x56\x12\xbb\xd0\x0d\xfb\x18\xf5\x0e\x86\xe2\x7e\x5f\x07\x84\x0e\x49\x1f\x34\x87\x31\x98\xe7\xa6\x43\xa9\x09\x2e\x5e\xa0\xca\x6a\x8b\x38\x29\x6a\x7d\xf2\x6c\x10\x08\xbf\xf7\xc5\xf2\x23\x30\x77\x21\x31\x7a\x98\x65\xf1\x1c\x59\x0d\xab\x71\x37\xdb\xe6\x4f\xf7\xb5\xbe\x83\xea\xb3\x80\xb2\xf8\x79\x93\x44\xc8\xfa\x27\x00\x00\xff\xff\x6b\x4e\x0b\x40\xe2\x06\x00\x00") - -func masterEtcEtcdEtcdConfBytes() ([]byte, error) { - return bindataRead( - _masterEtcEtcdEtcdConf, - "master/etc/etcd/etcd.conf", - ) -} - -func masterEtcEtcdEtcdConf() (*asset, error) { - bytes, err := masterEtcEtcdEtcdConfBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/etc/etcd/etcd.conf", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterEtcOriginMasterHtpasswd = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xaa\xae\x56\xd0\x73\xce\x29\x2d\x2e\x49\x2d\x0a\x2d\x4e\x2d\xca\x4b\xcc\x4d\x55\xa8\xad\xb5\xaa\xae\x56\x70\x4a\x2e\xaa\x2c\x28\x81\xcb\x06\x24\x16\x17\x97\xe7\x17\xa5\x28\xd4\xd6\x72\x01\x02\x00\x00\xff\xff\x48\x7d\x31\x4a\x35\x00\x00\x00") - -func masterEtcOriginMasterHtpasswdBytes() ([]byte, error) { - return bindataRead( - _masterEtcOriginMasterHtpasswd, - "master/etc/origin/master/htpasswd", - ) -} - -func masterEtcOriginMasterHtpasswd() (*asset, error) { - bytes, err := masterEtcOriginMasterHtpasswdBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/etc/origin/master/htpasswd", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterEtcOriginMasterMasterConfigYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x59\x6b\x6f\x1b\xbb\xd1\xfe\xae\x5f\x41\xe8\x4b\x92\x17\xef\xae\x64\x3b\xd7\x05\x8a\x42\xb5\x9d\x13\xe3\xd8\xb1\x2a\x3b\x45\x81\xba\x08\x28\x72\xb4\x62\xc4\x25\x37\xbc\x28\x56\x72\xf2\xdf\x0b\x5e\x76\x97\xbb\x92\x93\x20\xcd\x41\x9d\x20\x91\xc8\x99\xe1\x70\xe6\xe1\xdc\x8c\x69\xc5\xb4\x66\x52\x9c\x4a\xb1\x62\x65\x31\x42\xa8\xe6\xb6\x64\xc9\x77\x84\xfe\x66\x19\xa7\x67\xb0\xc2\x96\x1b\x1d\x96\x10\x22\x9e\xc0\x2a\x6c\x98\x14\xcd\x22\x42\xb8\x66\xff\x00\xe5\x24\x16\x68\x7b\xd4\x2e\x83\xd8\x16\xe8\x5f\xff\x6e\xbf\x6f\x98\xa0\x45\x5f\x70\x38\xb1\xa5\x50\xa0\xa5\x55\x04\x74\x27\x1b\x21\xce\x2a\x66\x74\x81\xbe\x7c\x4d\x16\x15\x7c\xb4\xa0\x93\x65\x2f\xf6\x7a\x0b\x4a\x31\x0a\x3f\xa9\x70\xa2\x60\x2b\x29\xd1\x70\x2e\xe9\x5c\x81\x06\xf3\x73\xd2\x29\xd3\x78\xc9\xa1\x40\x2b\xcc\x35\x0c\x0e\x8d\x06\x99\xf5\x5d\xe3\x89\x64\x0d\x42\xaf\xd9\xca\xe4\x4c\x4e\x2e\x2a\x5c\xc2\x5c\x72\x46\x76\x3f\xe9\x94\x7b\x20\xd6\x51\x2e\x2c\x4f\xed\x9c\xa1\x0a\x1b\xb2\xf6\xf2\x67\x42\x48\xe3\xc5\xf5\x1c\x91\xa1\x0d\xec\x0a\xc4\x1c\x89\xce\x7b\x6a\x51\x10\xbb\xac\x15\x9d\xf0\x20\xb4\xc5\xdc\x42\x81\x1e\x19\x65\xe1\x51\xb2\x23\x70\x05\x45\xa7\x4e\x46\x41\x30\xa0\x09\x81\x14\x8b\x43\x70\xc8\x5a\x94\x14\xa8\x96\x54\x3f\xb0\xb5\x74\x5e\xd4\x3d\xc4\x7c\x00\x62\x0a\xe4\xf4\x48\x96\xf5\x86\xd5\xd7\xfe\x24\xee\xf5\x78\x8d\x19\xb7\x0a\x06\x74\xc1\x49\x89\xf1\xa3\x7f\x70\x59\x2a\x28\xb1\x91\x2a\x79\x4b\x4a\xde\xef\x4e\x39\x03\x61\x2e\xc4\x4a\x06\xdd\x09\x28\xf3\x9a\x39\xef\x77\x2c\xd9\x4a\x49\x61\x32\x4f\x9f\x13\x65\x3c\xe1\x06\x76\xdf\xa4\xdb\xc0\x6e\x84\x6b\x76\x09\x5b\xe0\xba\x18\x65\xce\xb7\x03\x57\x63\x6b\xd6\x9d\x3a\xf1\xa5\xbc\x01\x4c\x41\x45\x65\xbc\x72\xa7\xb3\x02\x25\x92\x33\x82\x5b\x25\x22\x81\xac\x2a\x29\xde\xe2\xaa\x71\x40\xf6\x80\x52\xa3\x00\x2c\xa3\x70\x38\x65\xae\x60\xc5\xee\x3b\xae\x7f\x66\x0b\xa8\xa4\x81\xec\xdc\xd1\x64\x7e\xb5\x54\xd2\xd6\x81\x7c\x9f\xee\x37\xb7\xe9\x17\xad\x06\xe5\x90\xf2\x10\xe5\x3b\x0d\x6a\x44\xa4\x30\x4a\x72\x0e\x89\x17\x80\x03\xe9\x1e\x04\x97\x64\xf3\xd6\x03\xae\x85\x6d\x56\x61\x6d\x40\x65\x1d\xb3\x43\x8b\x06\xb5\x65\x04\x6e\xdc\x7f\xa2\x3c\x05\x15\x1f\xbb\x66\xa5\x68\xcc\x97\x7a\x33\xd2\x67\x61\xbf\x35\x60\xe2\xc7\x01\x85\xf3\x5f\x72\x64\x81\x1e\xfd\xdf\xa3\x11\x91\x4a\xcf\x38\x97\x9f\x80\x5e\x2b\x56\x32\xe1\x3d\xfb\xf8\xaf\xec\xc9\x64\x72\x74\xfc\xe2\x2e\x9f\xfa\xbf\x47\x8f\x8b\x3f\xee\x3e\x3f\x69\xb7\xb8\x24\x98\xaf\xa5\x36\xed\xfa\x97\x2f\xa8\x56\x4c\x18\x34\x0e\x14\x63\xf4\xf8\xef\x56\x1a\xb8\x02\x83\xd1\x63\x26\x28\xdc\xa3\xfc\xca\x5f\x3c\xbf\x98\x6b\x34\x7d\x92\xdf\x18\xc5\x44\xf9\x04\x8d\x9d\x90\xbb\xcf\x4f\xc6\xe8\x0f\xf4\xd1\xf1\xa0\xaf\x5f\xdb\x93\x36\x76\x09\x4a\x80\x01\x7d\x97\xd3\x10\xaa\x06\xba\x1c\xa0\xb8\xcb\xf5\x96\xdc\xe5\x84\x5b\x77\xde\x5d\xee\xd5\x7d\x90\xed\xc7\xee\x90\x9f\xdf\x1b\x87\x08\x1e\x2e\xf1\x46\x6a\xe3\xe0\xf1\x1d\xf5\x5b\xa7\xef\x6b\xff\xed\xd3\xa2\xa9\x7e\xfa\x18\x6f\x82\x1f\xb4\xd4\x80\xec\xe8\xc5\xf1\x5d\x7e\x72\xd8\xf1\x0f\x1c\xf4\x1d\x5b\xb7\x5c\x71\x9d\x0a\xdd\xbd\x97\x25\x13\x74\x46\xa9\x02\xad\x0b\x34\xcd\xfd\x9f\xe2\xe5\xf4\xd9\x49\xdc\x7b\x0b\xe6\x93\x54\x9b\x02\x19\x52\x3f\x1d\x81\x21\xb4\x1f\xe2\x08\x2e\x50\x78\x51\xb9\xdb\xec\xa2\x49\xf7\x56\x7a\xdb\x9e\x39\x92\xb4\x6f\xe5\x00\x85\x7b\x2f\x08\x59\xc5\xfd\xdb\x4f\xfd\xb5\x36\xa6\xd6\x85\xf3\xd8\xd0\x4d\x68\x5c\x1c\x9f\xbc\x78\xd5\xf3\x91\x93\x79\x63\xa4\xc2\x25\x74\x97\xee\x5c\x11\xb7\x42\xe4\x2a\x92\x8d\x9c\xc9\x43\x84\xfd\xd4\xea\x2c\x7b\xe3\x2c\x3b\x10\x93\xe6\xc8\x03\x64\xa9\x10\x9f\x55\x3b\xcd\x56\x52\x55\xd8\x14\xe8\x6a\x76\x73\x7b\xbe\x78\x7f\xbd\x38\xff\xed\xfd\xbb\xc5\xe5\x08\x21\x8e\x0d\x68\xd3\x54\x11\x6c\x98\x92\x1c\x33\x13\xe1\x8d\x2c\xa0\x64\xda\xa8\x5d\x63\x97\x02\x51\x49\x36\xa0\x32\x15\x37\x1a\xf4\x38\xf0\x14\xcf\xa6\xd3\xe9\x28\x24\xba\x60\xcf\x98\xe3\xdc\xdd\x39\x98\x7d\x77\x13\x9c\x2d\xad\xa0\x1c\x1e\xf2\x74\xe4\xfc\xb6\xb3\x07\x44\xc1\xdf\xb5\x54\xa6\x40\x47\xd3\xe3\x67\xd3\x51\x67\xfb\x54\x2d\xa7\x04\xae\x99\x0b\xd4\xa0\x66\xaa\xb4\x15\x88\xa6\x50\x55\x56\x18\x56\x41\x46\x92\x7a\x36\x73\xd4\x7a\xa2\xc1\x18\x26\x4a\x9d\x6f\x5e\x3a\xd7\x4e\xb6\x47\x98\xd7\x6b\x7c\xf4\x97\x36\xdd\xeb\xe0\x9b\x6c\x89\xc9\x06\x04\x6d\xb8\x1d\x7e\x4e\x7a\x04\x15\x50\x86\x33\xb3\xab\xa1\x3b\xa1\xe6\x8c\xf8\xc2\x69\xb2\x15\x34\x4f\x50\x54\x2b\x69\xe4\xd2\xae\x62\x7a\x95\x96\xba\xd4\xb9\x65\x6d\x4e\xce\xd0\x18\x7f\xb6\x0a\xc6\x09\x45\x5f\xff\xf1\x04\x0c\x99\x78\xa2\xf0\x6f\xee\xf6\x1d\x7d\x97\x4f\x06\x86\x88\xe1\xc0\xe7\x1e\x26\xca\xcc\x79\x28\x5b\x39\xeb\xf7\x64\x4a\x9f\x73\x26\xc1\x21\x93\xf0\x72\xc7\x07\x05\x6c\x60\xf7\x23\xfc\x1b\xd8\x8d\xff\x94\x9b\x56\x11\x01\x56\x38\x78\xb4\x0b\x17\xf3\xc2\x05\x86\x6f\x25\xb8\x34\x16\x38\x7c\xd1\xf3\x2d\xf3\x05\xc2\x2d\xab\x40\x5a\x53\x20\x61\x39\xff\x7e\xf9\x16\x51\x1b\x4b\xa6\x14\xd8\xfb\xd0\xee\x11\x05\x60\x6b\xb2\x06\x6a\x7b\x9e\x6a\x0e\x6e\xb7\x02\xc0\x83\xa4\x03\xf6\x6d\xe9\xf2\x0f\xda\xd7\xda\xb1\xc2\xd0\x6f\x25\x85\xb9\x54\x66\x81\x45\xe9\x2a\xee\x47\xc9\xde\x8d\x5d\x0a\x70\x36\x7b\x71\x9c\x9f\xf8\xe0\x3e\x39\x7a\xee\xf6\x5d\x9d\x4f\x1c\x67\xa8\xf3\x5c\xbf\x16\x8d\xec\xd5\xf6\x40\x82\x98\x73\x7f\x6f\xf1\x7c\x1a\x0b\x44\x21\x42\x95\x35\x68\xbc\x30\x21\x50\xbb\x6d\x03\xc2\xdc\xee\x6a\x27\xf8\x07\x1e\xc7\xff\xa7\x34\xf1\x72\x08\x2d\xad\x72\xf1\xee\xe9\x74\x3a\x8a\xed\x4e\x23\xf5\x87\x84\x7a\xa6\x8f\xb5\x2e\xd0\xb1\x97\xb0\x7f\x19\xf7\x29\x06\x95\x60\xb4\x36\x6c\x5f\x4a\x59\xbb\x38\xf0\x3f\xb8\xee\xf3\xff\xfa\xba\x27\x5e\xc2\xde\x5d\xd2\xdb\x0e\x8b\x61\x2f\x30\xbc\xc5\x88\x82\xb9\x5d\x72\x46\xde\x2d\x2e\x8b\xc3\x99\xf7\x70\x39\x86\xc6\x45\x97\x95\x1d\x24\xd3\xd7\x27\x42\x25\xd1\x85\xf1\x18\x64\x62\x85\x71\x7a\x71\xb6\x70\xa1\x3f\x3f\x3a\x7e\x19\x70\xfa\x74\x8f\x26\xd6\x02\x84\x51\xb5\x4f\x8a\x90\x2b\x89\x03\xe0\x2f\x41\x94\x66\x5d\xa0\x57\x89\xe3\x2f\xe6\xc9\x49\x51\x52\x2c\x78\x26\xce\x62\x87\xb9\xa3\xd6\x73\x3f\x28\x09\xad\x84\x02\xba\xc6\xa6\x2b\xab\x32\xb9\xd5\x99\xf6\x9c\xdd\xcb\xeb\xdf\xaa\xf7\xfa\x64\xbf\x51\xc3\x5a\x83\xf9\x55\xf6\x1e\x4f\x88\x14\x5a\x72\x98\x8c\xfb\x91\xaf\x54\xd8\x23\xb9\x0d\xb7\x15\x98\xb5\xa4\x05\xc2\xd6\xb8\x1a\x85\x51\x10\x86\x99\xdd\x3c\xc6\x6c\x5d\x8c\xbe\x7c\xc9\x10\x5b\xa1\xfc\x5c\xe0\x25\x87\xd9\xec\x6c\x66\xcd\xda\x51\x05\x24\x7a\xb1\x59\xec\xe7\x67\x2e\x5c\xa3\xd9\x59\xc0\xee\x1a\x73\x0e\x3e\x18\x75\x33\x0f\x2e\x4b\x26\x92\xf6\xba\xc2\x75\xcd\x44\x79\x15\xd5\x20\x1c\xb3\xca\x6f\xf4\xb3\xc6\x03\x03\x8d\x50\xaf\x5c\xd7\x20\x2e\xce\x2e\x06\xaa\x37\xcd\x5a\x88\xe5\x67\xde\xa2\xb9\x57\x30\xdc\x3f\x9f\xcd\xce\x62\xa0\x3f\xeb\x1b\xa9\x63\xbb\x01\xa2\x5c\xdc\x7c\x90\x35\x10\x1c\x62\xc7\xac\x4a\x06\x17\x8c\xa6\xb3\x16\x6d\x97\xed\xb7\x5a\xc1\x0a\x94\x02\xfa\x2e\xf6\xba\x29\xa1\x15\xec\xa3\x85\xf7\x6e\xb9\x5d\x1d\xd2\xf4\x36\xa1\xc2\x8c\xa7\xbb\x7e\x21\x7e\x6f\xca\xe8\x68\x50\x6b\xd6\x52\xb1\xcf\x70\x08\x6b\xde\x4d\x79\xc5\x88\x92\x5a\xae\x8c\x14\x9c\x09\x97\x87\x2b\x87\xc2\xd4\x12\xb7\x20\xb0\xb7\xe0\x78\xe2\x01\x7d\x3c\x69\xe5\x8e\xf7\xcd\x82\x90\x91\x1b\x10\xbf\xf8\x44\x2f\xb3\x77\x9a\xc3\x2c\x08\xda\xc3\xe6\xa5\xeb\x89\x50\x8d\xb5\xfe\x24\x15\x1d\x22\xb4\x05\xe4\xaf\x05\xe8\xea\xa1\x34\xbe\x36\x5e\x13\xda\x03\xf2\x9b\xdb\xb9\x5f\x9c\x47\x25\x0f\x40\x3a\x66\xe7\xd9\x7e\xfd\xfd\xa7\x45\xec\x46\xf4\x2f\x16\xaa\x61\x30\x85\x6e\x97\xae\xf0\xfd\xac\x84\x1b\x97\x8a\xa8\xcb\x64\x4d\x32\x8c\xdb\x21\xfc\x6a\x2d\xd2\xc5\xf0\x10\xf5\xc3\x65\x53\x20\xcb\x74\xa0\xcb\x77\xb8\x72\xcf\xc2\x43\x27\x55\xc1\x25\x73\xad\x6f\xdd\xf2\x40\x8d\x97\xcf\x9b\x1a\xa4\x45\xf8\x21\xb2\x67\xd3\xe9\xa8\xc6\x56\x3b\xb8\x76\x63\x9e\x10\x00\xeb\x41\xa7\xb6\x94\xd2\x68\xa3\x70\x1d\x5a\xb8\x07\x95\x0f\x7c\x4d\xc1\xd7\x66\x9c\x0b\xb1\x52\x58\x1b\x65\x89\xb1\x2a\x54\x70\x35\x26\xbd\x29\x17\x73\x24\x29\xcf\xcd\x1a\x2b\xa0\xed\x68\xf5\x10\xd3\xa8\x56\xf2\x03\x90\x24\x4d\xc4\x3e\xd1\xd5\x89\x37\x7e\xb2\x26\x55\x81\x84\xa4\x90\x29\xc9\x21\xef\xb5\xcb\x13\x22\xab\xda\x1a\x68\x5a\xaa\x28\x6c\x11\xe6\x90\x57\xa0\x35\x6e\xcb\xd3\xfe\xde\x2d\x54\xb5\x6b\x6f\xdb\xda\x95\x58\xc5\xcc\x6e\xc6\xb9\x24\xd8\x1d\x19\xde\x23\xd1\xed\x4a\x2c\x75\xf5\xb4\x98\x1c\x37\x9b\x97\x78\x09\x5c\xcf\x41\xcd\x83\xf0\x02\x3d\x0b\xa3\x44\x46\x87\x7c\x47\xd3\xe6\x27\x3b\x7a\xd5\xfc\x4c\xfc\xea\x48\x49\xeb\x3a\xc5\xce\x06\xda\x2e\xa9\xac\xb0\x8b\x0d\xb7\xe7\x57\xf3\xc5\xf5\xbb\xdb\xf3\xc5\xc5\x3c\x17\xac\x76\xed\x7d\xcc\xf7\x33\x42\x5c\x77\xd2\xb1\xf9\x5f\x5f\x04\x70\x2e\x5c\xa0\x07\x41\x40\x77\x09\xb1\xc2\x02\x97\x40\xdb\x29\x6b\xd6\xd8\xda\x7f\xf6\x53\x6c\xff\xec\xdd\x7a\xcd\xe5\xee\x3b\x31\xa0\x56\x6c\x8b\x0d\xfc\x3e\x98\x3e\xe2\xa0\x95\x2b\x13\xfd\x7e\xd3\x66\xfb\x58\x11\x89\xe3\xf1\x7b\x1c\x9e\xc6\x33\xe8\x30\x15\x6d\xda\xa2\xde\xc8\xa8\x0b\x0b\xcd\xf0\xe8\x5b\x4f\x7f\x7f\xa2\x74\xa0\xc7\xd2\xbe\xb7\x6f\x86\x0b\xed\xcc\xba\x9d\x2c\x0d\xdb\xad\x48\x1f\xae\x56\xe1\xfb\x88\x2a\x7d\x21\x5e\x73\x56\xae\x4d\x78\x9a\xed\x44\x3c\x36\x7e\xfd\x28\xb3\x95\xdc\x56\xc9\x1c\x86\xee\x04\xae\x18\xf1\xf1\xd7\x85\x0f\x26\xca\x50\x06\xd1\x98\x21\xfe\x13\x00\x00\xff\xff\x1a\x08\x1e\xd4\x4d\x1b\x00\x00") - -func masterEtcOriginMasterMasterConfigYamlBytes() ([]byte, error) { - return bindataRead( - _masterEtcOriginMasterMasterConfigYaml, - "master/etc/origin/master/master-config.yaml", - ) -} - -func masterEtcOriginMasterMasterConfigYaml() (*asset, error) { - bytes, err := masterEtcOriginMasterMasterConfigYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/etc/origin/master/master-config.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterEtcOriginMasterSchedulerJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x55\xc1\x6e\xda\x40\x10\xbd\xf3\x15\x96\xcf\x39\x90\x1e\xb9\x01\x89\xa2\x4a\x0d\x5a\x41\x94\x43\xab\x1c\xb6\xbb\x0f\x18\xb1\xec\xd0\xd9\x35\x2d\x89\xf8\xf7\x6a\xed\xc6\x2d\x90\x2a\xb6\xe5\xf8\x64\xbd\x7d\xef\xed\xee\x8c\xdf\xf8\x65\x90\x65\x59\x96\xeb\x1d\x3d\x42\x02\xb1\xcf\x47\x59\xbe\xbf\xce\xaf\x2a\x7c\x43\xde\x26\x44\xb1\x23\x73\x78\x45\x77\x02\x4b\x46\x47\x84\x7c\x94\x7d\x2b\xb1\xf4\xbc\xd4\x6f\x25\xcb\xeb\x2d\x92\x76\xc6\x8f\xec\x8a\x2d\xbe\xb2\xc7\x94\xfd\xd2\x91\x89\x79\x4d\x3d\x5e\xbd\xa7\xbf\xd7\xbf\x6e\x27\x8b\xca\x63\xca\x85\x6f\x2b\xbe\x9b\xde\xaa\x9b\xee\xf2\xf1\x73\x21\xb8\xa1\xb0\xe9\x6c\x11\xcd\xfa\xb3\x8f\x10\xc5\x76\xbc\x5c\x92\xa7\x78\x68\x63\x30\xe3\xb4\x7b\x97\xca\xdd\xc1\x43\xb4\x53\x7f\xdb\xd5\x42\xac\xd8\x3e\xb0\x83\x24\xdd\x8c\x2d\x1e\x34\xf9\xd8\xca\x61\xba\x86\xd9\x24\xe9\x3d\xb6\x2c\x07\x25\x08\xa1\x10\x74\xb2\x48\x25\xe8\x6c\x50\x75\x6e\x42\xde\x92\x5f\x35\x51\x6b\x59\x15\x5b\xf8\x98\x8f\xce\x56\xca\xd5\x00\xd9\x93\x41\xdd\xcb\xb7\x48\x25\xd1\xe9\xef\x70\xa7\x19\xb9\xe0\x08\x56\x29\x75\x6f\x12\x9e\x2e\xd0\xe3\x09\xf2\xcf\x05\x4e\x2e\x3d\x3f\xf3\xac\x54\x4f\x75\x7a\x89\x85\x22\x35\x4b\xef\x02\x0e\x26\xb2\x2c\x76\x02\x6d\x55\xa5\x7d\x9d\x04\x35\xfb\x27\x68\xb5\x4e\xe5\xba\x6e\xd1\x9b\xf3\x50\xf4\x6a\xfe\x05\x3a\xc4\x39\x7e\x14\x08\x11\xfd\x9e\x7b\xa2\x9d\xf6\x06\x76\x8e\xc0\x85\x18\x8c\x9d\x63\xa3\x63\x2a\x79\x1f\xf6\xe9\x73\x57\x82\x25\x64\xbc\x67\xb2\x8a\x6d\x78\xff\xf8\xc3\xe1\x70\xd8\x72\x8f\x0f\x29\x7b\x39\x25\xfe\xcc\x0d\x62\xdf\x8b\x77\xb3\x34\xfa\x48\x0d\x13\x99\xce\xf9\xcc\x1e\x97\xa1\x6b\x16\xaf\xf4\x23\xfb\xef\x85\x3e\x9d\xa7\x6e\x70\x1c\xfc\x0e\x00\x00\xff\xff\xaa\x29\xaf\x2a\x65\x07\x00\x00") - -func masterEtcOriginMasterSchedulerJsonBytes() ([]byte, error) { - return bindataRead( - _masterEtcOriginMasterSchedulerJson, - "master/etc/origin/master/scheduler.json", - ) -} - -func masterEtcOriginMasterSchedulerJson() (*asset, error) { - bytes, err := masterEtcOriginMasterSchedulerJsonBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/etc/origin/master/scheduler.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterEtcOriginMasterSessionSecretsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\x2c\xc8\x0c\x4b\x2d\x2a\xce\xcc\xcf\xb3\x52\x28\x33\xe4\xca\xce\xcc\x4b\xb1\x52\x08\x4e\x2d\x06\x89\x04\xa7\x26\x17\xa5\x96\x14\x73\x15\x43\x68\x2b\x2e\x5d\x85\xc4\xd2\x92\x8c\xd4\xbc\x92\xcc\xe4\xc4\x12\xb0\x96\xea\x6a\x05\x3d\xc7\xd2\x92\x0c\x88\x52\x85\x1a\x85\xc2\xd2\xfc\x92\x54\x85\xda\x5a\x2e\x05\x85\xd4\xbc\xe4\xa2\xca\x02\x84\x3a\xd7\xbc\x64\x4c\x65\x80\x00\x00\x00\xff\xff\xc1\xc1\xc9\xa5\x80\x00\x00\x00") - -func masterEtcOriginMasterSessionSecretsYamlBytes() ([]byte, error) { - return bindataRead( - _masterEtcOriginMasterSessionSecretsYaml, - "master/etc/origin/master/session-secrets.yaml", - ) -} - -func masterEtcOriginMasterSessionSecretsYaml() (*asset, error) { - bytes, err := masterEtcOriginMasterSessionSecretsYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/etc/origin/master/session-secrets.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterTmpAnsibleAnsibleSh = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x53\xd1\x6e\xdc\x36\x10\x7c\xd7\x57\x4c\xee\x8a\xa6\x05\x2c\x29\xe7\x22\x0e\x70\x45\x53\xa4\x88\x8b\x06\x48\xea\xa2\xf1\x43\x1f\x0a\x18\x14\xb9\x77\x62\x4d\x71\x89\xdd\xd5\x5d\xd4\xc0\xff\x5e\x48\x3e\x3b\x45\xfd\x54\xe9\x85\xa2\x66\x67\x77\x86\xc3\xf5\xb3\xb6\x8b\xb9\xed\x9c\xf6\xa8\xe9\x53\x55\xad\x71\x7d\xf5\xf6\x6a\x8b\xc0\xb0\x3e\xea\x19\x5c\x0e\x18\x58\x08\xdf\x08\xed\xa3\x9a\x4c\xf0\x9c\x95\x13\x9d\xc1\x69\xf7\xed\x19\xac\x27\x14\xe1\x42\x82\xa3\x9b\x66\x8a\x23\x61\x4f\x86\x55\x88\x2e\xc1\x7c\xd9\x22\x31\xdf\x8e\x05\x3b\xe6\x86\x9c\xda\xa8\x8d\x4f\x3c\x06\x57\x4a\xe3\xfe\x1e\x85\x1a\xcf\x03\x38\x63\xf3\xa2\x99\xdf\xcd\x66\xfb\xf2\xbb\x2d\x84\x5c\xa8\xd6\x18\x43\xc1\xe6\xd5\x79\xb3\x79\xd5\xbc\x68\xce\xb7\x2f\x2f\x2e\x2e\xce\xeb\xd7\x4f\xa1\x5b\x64\x86\xf0\x68\x04\x63\xf4\xac\x06\x12\x61\xd1\x15\x9c\x55\x6b\xa8\x39\xb1\x7a\x2c\x5b\x1c\x5d\x34\x8c\xd9\x62\x9a\xa7\x57\x82\x8e\x9d\xc6\x40\x4d\x75\xec\x63\x22\x3c\x03\x7b\x1c\x48\x34\x72\xc6\xd7\xaf\xdb\x40\x87\x36\x8f\x29\x7d\x8f\xc0\x15\xa0\x89\xa8\x60\x53\x05\xce\x54\x55\x3b\x96\x59\xff\x5f\xe4\x0d\x31\x23\xd0\xce\x8d\xc9\xc0\x85\xb2\xf6\x71\x67\x75\xcc\x3b\x71\xa7\x52\xf6\x28\xce\x7c\xff\x58\xf1\xd5\xc3\xa2\x2e\x78\xfe\x79\x35\x90\xb9\xe0\xcc\xad\xb6\x9f\x57\x2e\x67\x36\x67\x91\xb3\xce\x9f\x8f\x84\x4d\xe4\x36\x73\xa0\x5a\x29\x91\x37\x96\xd5\x16\xab\xd5\xdd\xdd\xdd\xf3\xd3\x44\x6b\xfc\xfc\xee\x8f\x0f\x97\xa8\x71\xdd\x47\x85\xf6\x3c\xa6\x80\x8e\xd0\xbb\x1c\x12\x05\x74\xd3\x72\x6a\x5f\x46\x74\x59\x63\x97\x08\x25\xb9\xa9\x63\xbe\xd5\xd9\x41\xca\x3a\x0a\x55\x6b\x3c\x3c\x0e\x21\xca\xd2\x71\x42\x34\x64\xa2\xb0\x00\x8f\x12\xef\x3d\xa7\x4f\x51\x4d\xd1\xd1\x6e\x4e\x8c\x33\xa3\xa1\x58\xcc\xfb\x47\xd0\xbf\xc8\x8c\x11\xad\x1a\x6e\x43\x94\x59\x7b\x4b\xe6\x5b\x96\xb8\x8f\xb9\x1d\x9c\x1a\x49\x9b\xdd\x40\xe1\xc6\x93\x58\xdc\x45\xef\x8c\x74\x96\xf6\x96\x4a\xe2\x09\x2e\x25\x2c\xc6\xc2\xf3\x50\x38\x53\x36\x85\xd0\xa8\x73\x3b\xa1\x44\x07\x97\x0d\xc5\x89\x29\x76\x32\xa7\xeb\xbf\x62\xab\x37\xbf\x7e\x7c\xf7\xd3\xfb\xcb\x9b\xdf\xaf\xde\x5f\x7e\xbc\xf9\xed\xcd\xf5\x2f\x3f\xb4\xa3\x4a\xab\xbd\x13\x6a\x4f\xa8\xf6\x49\x5d\x2b\x9c\x48\x5b\xfc\x59\x01\xa7\xad\xfa\xc1\xb7\x79\xaf\xfe\x80\xff\x41\x93\x62\x77\x33\x5a\x4c\xcb\x4a\x9c\x4c\x0b\x6f\xed\x91\xd8\xbb\x84\xe5\x76\xd4\xec\x4b\x1d\x16\xdd\xcd\x34\xa4\x7b\x44\x3c\xfd\x5b\x70\xf5\xbd\x65\x75\xcc\x07\xca\xf3\xf9\xcc\xb8\x2f\xb7\xb9\xb0\xce\x3d\xa7\xfb\xe0\xf7\x24\x84\x39\xb5\x9e\xf3\x81\x64\x4f\xd9\xd3\x8f\xd5\x3f\x01\x00\x00\xff\xff\x19\x22\x4a\x18\x0b\x04\x00\x00") - -func masterTmpAnsibleAnsibleShBytes() ([]byte, error) { - return bindataRead( - _masterTmpAnsibleAnsibleSh, - "master/tmp/ansible/ansible.sh", - ) -} - -func masterTmpAnsibleAnsibleSh() (*asset, error) { - bytes, err := masterTmpAnsibleAnsibleShBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/tmp/ansible/ansible.sh", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterTmpAnsibleAzureLocalMasterInventoryYml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x9c\x58\xeb\x6f\xdb\xc8\x11\xff\xee\xbf\x62\xa0\x14\x50\x8b\x9e\xa4\x26\x39\xa0\x3d\x02\xf9\xa0\xf3\x31\xb1\x71\xb1\x65\x48\x72\x91\xb4\x28\x88\x25\x77\x28\x6e\xbd\xda\x61\x76\x97\x92\x75\x69\xfe\xf7\x62\xb8\x4b\x3d\xe8\x47\x8c\xe8\x93\x28\xce\xfe\xe6\xf5\x9b\xc7\x6a\x34\x1a\x9d\xbd\x82\xf7\x97\x9f\xae\xd2\x04\xa6\x66\xe7\x2b\x65\x56\x90\xa3\xa6\x2d\x28\x03\x42\xeb\x51\x21\x6a\x07\x95\x70\xa0\xfc\xd0\xc1\x46\xe8\x06\xc1\x62\xad\x45\x81\x12\xf2\x1d\x38\x94\x2c\xea\x2b\x3c\x7b\x05\xf1\x43\x35\x1a\x57\xa9\xd2\xaf\x85\xf3\x68\x5d\x61\x55\xed\xc7\xae\x82\x6d\xa5\x8a\x0a\x94\x03\x43\x1e\x94\x44\xa1\x7f\x82\x2d\x82\xab\xa8\xd1\x12\x4a\x75\x0f\xbe\x12\x7e\x7c\xa6\xa9\x10\x3a\x1c\x4e\xce\x00\x2a\x72\xde\xf1\x17\x80\xf6\x0d\x3f\x9f\x01\x6c\x84\x8d\xbf\x0a\xe3\x54\xae\x31\x2b\xc8\x18\x2c\xbc\x22\x93\x04\xc9\x93\xb7\xf5\xce\x57\x64\x32\x65\x3c\xda\xda\x22\x83\xc3\xa4\x71\x76\x92\x2b\x33\x09\x2f\xdf\x9c\x9d\x9d\x38\x90\x29\xc7\xa0\x5e\x28\x83\x56\xfd\x81\x32\x81\xf7\x42\x3b\xec\x49\x15\x5a\xa1\xf1\x59\xae\x8c\xb0\xbb\x23\x50\x2a\x1e\xe0\xad\xc5\x0a\x33\x2f\x56\x09\x0c\x36\xff\x4c\xe7\x8b\xcb\xd9\xf5\x20\x08\xbd\x82\xeb\xd9\x32\x4d\x60\x59\x29\x07\x45\x25\xcc\x0a\x1d\x87\xf6\xed\xf8\xf5\xdf\xfe\x0a\xc2\xc8\x90\x02\xa1\x35\x14\xb4\xce\x95\x69\x23\xef\x09\x04\x38\x65\x56\x1a\x39\x20\x4a\xe4\x1a\x23\x5c\xf8\x34\x46\xa2\xe5\xfc\x80\x11\x6b\x3c\x32\x65\x8b\x39\xfb\xe6\x48\x63\x34\x8b\x05\x7a\xf6\x1e\x0b\xd5\x16\x4b\x75\x9f\xc0\xe0\xf2\x6a\xfa\x21\xcd\x6e\xe6\xe9\xfb\xcb\x4f\x93\xc1\x33\x27\x0e\xb0\xfb\x53\xcb\xcf\x37\xe9\x68\x8b\xf9\x28\xca\x3c\x77\x7c\x83\xd6\xb5\xb9\xec\x87\x8a\x2c\xae\xb2\xc6\xea\x2c\x72\x04\x86\x57\xd3\xc5\x32\x9d\x67\xb3\x79\xfa\x21\xbb\x9d\x7f\x1c\xf6\x50\x83\x5c\x26\xb1\x14\x8d\xf6\x99\x6b\x72\x49\x6b\xa1\x4c\x02\xc3\x65\x7a\x75\x33\x9f\xdd\x2e\xd3\xf9\xe5\xcd\xd8\xa8\x7a\xac\x68\xd8\x25\xa4\xad\x8c\xf8\xbd\x4d\x4b\x64\x6a\x8e\xe0\x77\x35\xbe\x53\xa6\xb4\xe2\x27\xc8\x1b\xcf\x34\xae\xc4\x06\xc1\x13\x68\xb5\x41\xd8\x2a\x5f\x81\xc5\x95\x22\x13\xc4\xa0\x24\x0b\x86\xb6\x11\x2e\xc7\x42\x34\x0e\x81\x4a\xd0\xb8\x12\xc5\x0e\x2c\x0a\x47\xc6\xf5\x2c\xb7\xd4\xb0\xe5\x0e\x35\x16\x9e\xd8\xd5\x63\xd0\xbe\x9f\xfc\xce\x79\xbb\x7b\x5e\xfe\x15\x5c\x53\x5b\x7e\xb0\xad\x76\xe0\xd9\x31\xe5\x40\x80\x54\x65\x89\x16\x8d\x07\x29\xbc\x68\x5d\x0c\xce\x29\x0f\xaa\x6f\x58\x6d\x69\x8d\xbe\xc2\xc6\x65\x86\x24\x1e\x69\xfc\x1a\x55\x0e\x13\x18\x06\xad\xdf\xba\x80\x2e\xd0\xc3\xf4\x8f\xc6\x22\xb8\x1a\x0b\x55\xaa\x22\xa8\xe2\xd8\x70\x55\xa3\x84\xce\x85\x9e\xba\xf0\xf6\xc8\x41\x4f\x96\xc9\x55\x5b\xda\x28\xc9\x1c\x18\x08\x06\xce\x72\x4d\x79\x9f\x54\x4f\x1d\xbe\x53\x46\x26\x30\xa0\xfc\xbf\x58\xf8\x97\x1e\x3a\xa8\xc9\x44\x51\x50\x63\x7c\x20\xf8\x70\x9e\x7e\xb8\x5c\x2c\xe7\x9f\xb3\xc5\x72\x36\x67\xae\x4f\xff\x75\x3b\x4f\xb3\xe9\xf9\xf9\xec\xf6\x7a\x79\x3d\xbd\x4a\xfb\xe9\x7a\xb9\x8a\x3b\xdc\x7d\x57\xc3\xef\xe9\xe7\x1f\x50\xb0\x6f\x6f\x09\x0c\x3a\xb9\x1f\x08\x85\x45\xa1\xd7\x09\x0c\x0a\xb2\x38\xde\x2a\x23\x69\xeb\xc6\x06\xfd\xe0\x91\x5a\x8a\xbf\x5c\x08\x2b\xa1\x20\x89\x81\x82\xb1\x3e\xc6\x27\x32\xe7\x8d\x65\x42\xea\x5d\xdb\xc1\x0a\xdd\x70\x1d\x83\xf3\xc2\x23\x08\x0f\x12\x6b\x4d\xbb\x35\x53\xd6\xab\x35\x82\x24\x0c\xc3\x25\xd4\x22\x37\x3d\x92\xe8\x22\x58\xb0\x1f\x2d\x4a\x2e\x53\x7e\x1b\xfa\x42\x28\x56\x2d\x72\xd4\x0e\x44\x5d\x6b\x85\xb2\x6d\xb8\x16\x85\xdc\xb1\x6c\x8e\xf0\xa5\x41\xab\x50\x46\x28\xb1\x12\xca\x38\xcf\x36\x30\x4e\x4d\xca\xf8\x76\x0e\xb2\x15\x61\x1e\x46\xe3\xda\x91\x16\x84\xb4\xd8\xe5\x44\x77\x0e\x6c\x63\xc6\x30\xd5\x8e\x7e\x8a\x70\xfc\x3a\x54\x7a\x3b\x5c\x55\x21\xa0\x4d\x3b\xc4\x8e\x05\x83\x52\x68\xed\x20\x17\xc5\xdd\x80\x0d\x7a\xcd\x76\x5a\xaa\xad\x12\x1e\xf5\x0e\xb6\x15\x5a\x04\xe1\x8e\xf1\x62\xb6\xf6\x88\x9a\x56\x5c\x6f\x31\x44\x63\x58\xb6\x67\xb6\x82\x67\x8a\x23\x90\xca\x15\x8d\xe3\x86\x0b\x22\x27\xae\xfa\x32\xa2\x85\xb9\x73\xd0\xc7\x06\x48\x0a\x59\x8b\x7d\xae\xd5\xe0\xe0\xdd\x3b\x08\xcd\xae\x0d\xfb\xbe\xc9\x31\x40\xc4\xaa\xd1\x96\x58\x70\x42\x4b\x14\xed\x5c\x66\xb4\x36\x5d\xc2\x1c\x1d\x8e\xfe\x57\x6a\x55\xb5\xe3\x4b\x74\x31\x75\xca\xee\xb3\xd0\xe9\x3d\xe5\xcc\x1c\x37\xca\x29\x0f\x5a\x70\x3c\xff\x5c\x93\x63\x3d\x3b\x6e\x70\x02\xd7\x64\x1c\x7a\x20\x0b\x7f\x22\x5f\xa1\xfd\xcb\x13\x54\x0f\x6d\xb7\x53\x90\xc0\xeb\xef\x94\xc4\xb1\xe4\xd3\x9d\xb2\x25\x6e\x02\x83\xda\xa2\x43\xf3\xa0\xe5\xf4\x7b\x2a\xde\xd7\x64\xd9\x8e\x30\x48\xf7\xf3\x70\x78\x33\x9f\x5d\xa5\xcb\x8b\xf4\x76\x91\xa5\x9f\x6e\x66\x73\x9e\x7d\x71\x44\x0e\xfb\xea\x4f\x06\xb2\x71\x5e\x68\x9d\xc0\xd2\x36\xf8\x8c\x9d\x41\xdf\xcb\x06\xfe\xa1\x06\x33\x9e\x18\x09\x0c\xa7\xd7\x8b\xcb\x5f\x3f\xa6\xd9\x6f\xe9\xcd\xc7\xd9\xe7\x76\xe4\x47\xab\xba\x55\xcc\xa1\xdd\xa8\x02\xb3\xdc\xd2\x1d\xbb\x77\x62\xd6\x29\x7c\x27\x5a\x08\x2f\x34\xad\x9e\x35\xed\x68\xc5\xe8\x5b\xf9\x38\xcc\x21\xa2\x9b\x7d\xf8\x1e\xdd\x1c\xd0\x17\x92\x37\x0e\x97\xc0\xbf\x07\x95\xf7\xb5\x4b\x26\x93\x8b\xd9\xa2\x6d\xeb\xc9\x9b\xb7\x7f\xff\x65\xf0\x9f\xe0\xa2\xc7\x75\xcd\xcc\xeb\xfb\xf8\x5c\x30\x9f\x3a\xf3\xd4\xfe\xd4\xc9\x8f\xa2\xfc\x28\xc8\x3f\x0f\xf6\xe4\x36\x75\xb2\x78\x2a\x07\x16\x65\x63\xa4\x30\x3e\x0c\x7f\x8b\x5f\x1a\x15\x7b\x66\x25\x8c\xe4\x45\x33\x40\x81\xbb\xc3\x2d\xe4\xe8\xb7\x88\xe6\x64\xe9\xdc\xc7\x6f\x14\x33\xce\x3d\x71\x66\xd5\x8a\x6f\x15\x46\xc2\xec\xfc\xa6\x17\x67\xbc\x17\xeb\x5a\x63\x58\xb7\x99\x4b\x47\xe6\x2e\x2e\x66\xf3\x25\xf3\x7b\xd0\xa7\x6c\x41\xc5\x5d\xad\x3a\x0e\x1e\x47\xf9\x7c\x76\xfe\xfb\xcd\xe5\xf2\x29\xd2\x3e\x38\x98\x0b\x87\x31\xd0\xdd\xd1\x5f\xa7\x8b\x94\xd3\xfb\xdd\xb3\x07\x53\xbb\xa3\x8f\x07\xf8\x37\x6a\x67\x93\xc4\x52\x19\xfc\x6e\xcf\x01\x47\x87\xd9\xe1\x85\xbb\x83\x52\xed\x77\xfb\x20\x3b\xde\xad\x35\x28\xe3\x94\x0c\xc3\xae\x0f\x09\x96\x34\x42\x69\x69\xfd\x48\x46\xb6\x4a\xeb\x6e\x9a\x35\x9e\x6a\xaa\x1b\xa6\x0d\x2f\x7b\x0d\x5f\x28\x1e\x45\xec\xef\xa3\x6d\x36\x79\x34\xee\x94\x59\x1d\x0d\x1f\xd3\xac\x73\xb4\xbc\xdd\x1e\xcd\x83\x3e\xdd\x0e\x37\x16\x17\x2f\x9d\xc2\x32\x53\x3c\x5a\x23\x34\xf3\xed\xa1\xd5\xac\x6f\x8b\x43\x7b\x7a\xc9\x09\x5b\x60\x34\x7a\x0d\xed\x60\xe3\x9b\xd1\x86\x94\x6c\xed\x51\xa6\xe0\x4d\x82\xf7\x0d\xe7\xd9\xac\x52\x14\x1e\x4a\x65\x64\x67\xf7\x5e\x55\xb8\x52\x02\x5f\xb2\xd6\x64\xba\x27\x7e\x36\xa5\x5a\xb5\x44\x49\x60\x82\xbe\x98\x50\x4b\xe8\xc9\x5e\xe2\x85\x1c\x0e\xc2\x87\xeb\x6d\x74\xa1\xc9\xb5\x2a\xf6\x9d\xba\xb1\x3a\x81\xaf\x5f\xa1\xb6\xbc\x59\xec\x5b\xce\x00\xc6\xe9\x7d\x88\xcf\x55\x0b\x70\x41\xae\xdd\x3f\x61\x90\xfc\xe3\xe7\x9f\xdf\x4e\xba\x6b\x15\xfc\x0f\xbe\x34\xe4\x11\xbe\x7d\xeb\xab\x10\xb5\xfa\x51\xf8\x47\x61\x5f\xd2\x1b\xe1\x55\xfc\x97\xe1\x9a\x40\x93\x59\xa1\x05\x83\x28\x79\xcf\x72\x9c\x8e\x07\x89\x1e\xbd\x1d\xff\x32\x7e\xf3\x66\xf4\x3a\xde\xae\x86\x16\xdb\xe2\x21\x13\x8a\xa2\x6b\x41\x3b\xf4\xd1\x10\xa6\xd8\x21\x9c\xfc\x14\xf7\xf2\xce\x94\xe1\xd9\x19\x51\x6c\xe8\x2e\xf3\x94\x85\x8c\x3e\xf9\x0f\xc3\xff\x03\x00\x00\xff\xff\xf9\xbe\x22\x8b\x1e\x11\x00\x00") - -func masterTmpAnsibleAzureLocalMasterInventoryYmlBytes() ([]byte, error) { - return bindataRead( - _masterTmpAnsibleAzureLocalMasterInventoryYml, - "master/tmp/ansible/azure-local-master-inventory.yml", - ) -} - -func masterTmpAnsibleAzureLocalMasterInventoryYml() (*asset, error) { - bytes, err := masterTmpAnsibleAzureLocalMasterInventoryYmlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/tmp/ansible/azure-local-master-inventory.yml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterTmpAnsibleAzureOcpDeployYml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x95\x31\x8f\xdb\x38\x10\x85\x7b\xfd\x8a\x87\xbd\xc2\xcd\x79\xbd\x8b\xeb\x04\xdc\x55\x97\x00\x5b\x04\x29\x92\x22\x40\x10\x08\x14\x35\xb6\x08\x53\xa4\xc0\x19\xae\x63\x60\x7f\x7c\x40\x89\x92\x17\x0b\x7b\x6d\x21\x45\x3a\x9b\xd2\xbc\xf7\x71\xe6\x89\x5c\xc3\xa9\x8e\x4a\xfc\x4f\xbd\xf5\x47\x7c\xee\xc9\x7d\x69\xcd\x56\x60\xdc\x36\x28\x96\x10\xb5\xc4\x40\x38\xf8\xb0\xb7\x5e\x35\x05\xd0\x7a\x16\x2e\x61\xbd\x56\xb6\x53\x2c\x14\x0a\x60\xa7\xa4\xa5\x50\x6d\x95\x4e\xcf\xb6\xca\x32\x15\x05\x20\x8a\xf7\x5c\x16\x00\x30\x39\x3d\x75\xbd\x0f\x02\xdf\x93\xe3\xe4\x54\xd5\xde\x0b\x4b\x50\x7d\xa5\xa2\x78\xd5\xf7\xc1\x3f\x53\x40\xf0\x96\xb0\x0d\xbe\x3b\xbd\xba\x56\x8e\x4d\x6d\x09\xe2\xd1\x8c\xc0\xce\x37\x84\x59\x01\x49\x01\x93\xc4\x60\x0b\x98\xc1\xb0\x4a\x7a\x65\x5e\x42\x66\xb9\x06\x51\x9c\x23\x57\xae\x41\x64\x42\xf0\x51\x28\x0c\x5b\xc4\xd6\x5c\x86\x3d\x99\xa4\xce\x51\x33\xec\x6c\x09\xdb\x58\x36\x3f\x1e\x7a\x5a\x25\xb3\x32\x33\xdc\x1f\x3b\xfb\x3e\x2a\xed\x0c\x4b\x38\xfe\x61\xd8\x4c\x71\x11\xf7\xa4\x72\xa0\xba\xd2\xde\x71\xca\xc0\x6d\x41\x38\x50\x8d\x5c\xb1\x04\xf7\x95\xd1\x88\xf4\x17\x3e\x3e\x7d\xfb\xf4\x01\x6b\x7c\x6d\x29\xd0\x8a\xa1\x10\x94\xa6\x24\xde\x18\x31\xde\xe1\x90\x1e\x40\x5a\x1a\x3f\x12\x58\x55\x93\x85\x61\xb7\x92\x94\x3d\x6b\xa8\x81\xf8\xac\x36\x37\x62\x7e\x7d\x88\x6c\x13\x83\x71\x3b\x68\x1b\xd3\x07\x84\x7a\xf8\x17\x7b\x18\xf7\xa6\xee\x5a\x44\xff\x86\xb4\x86\x61\x18\x7d\xf0\xb5\xa5\x4e\x89\xd1\xa8\x49\xab\x34\x78\x69\xe9\xa2\x5e\x1f\x7c\x47\xd2\x52\xe4\xb1\xc5\xba\x25\xbd\xe7\xd4\x52\x72\x1c\xc7\x1d\x06\x4a\xca\x99\xf9\x60\xa4\xbd\xb8\x2b\x26\x4b\x5a\x7c\x40\xec\x37\xea\x59\x19\xab\x6a\x4b\x1b\xd6\x2d\x35\x71\xf8\x7d\x9f\x27\xce\x2d\x59\x5b\x62\xb5\x89\x1c\x36\xb5\x71\x1b\xaf\xb1\x23\x19\x2c\x18\x6b\x8b\xbb\x94\x13\xef\xfe\x1d\x74\xef\xf0\x82\x83\xc6\xda\xae\xf2\x08\xc7\x10\x51\x48\x71\xe2\x68\x25\x2f\x47\x27\xc6\x4e\x6b\xf7\x2c\x8d\x8f\x52\x59\xe3\x88\xbf\x3f\xfc\x78\x31\x4e\xf0\x1f\x1e\x67\x09\x09\x86\xb8\xc4\x3f\x0f\x79\xa5\x21\xab\x8e\x25\x1e\x1f\x8a\x2b\xb9\x7c\xdb\xb3\xab\xb1\x3c\x15\x2c\x49\xe5\xab\xaa\xf7\x79\x98\xc2\xb3\xd1\x54\x69\x25\xca\xfa\xdd\x8d\x50\x69\x6a\xb9\x12\xb9\x72\x09\xdd\x1b\xd3\x0b\x27\xcf\x60\x3a\xbf\x5b\x07\xbf\xbf\xf9\x50\x4f\x7c\xd3\xea\xc4\x39\x0a\x5c\xc7\x3c\x6f\x7c\x96\x51\xa8\xeb\xad\x92\xdf\x80\x9c\x14\x16\x53\x5e\xb0\xbe\x32\x6d\xfa\xa9\xba\xde\xd2\xad\xd9\x4b\x84\x53\xc9\x92\xf9\xce\x35\xef\xd3\x8c\x27\x7d\x35\x6d\x65\x09\x55\xbe\x5b\xe6\xd2\xe5\x17\xcc\xc9\xf6\x2c\xa5\xf6\x7a\xdf\x1b\xa9\xa2\x59\x40\x35\xdf\x92\x37\xdf\x23\xd9\x66\x1d\x4d\xf1\x2b\x00\x00\xff\xff\x57\x93\xda\x47\x49\x09\x00\x00") - -func masterTmpAnsibleAzureOcpDeployYmlBytes() ([]byte, error) { - return bindataRead( - _masterTmpAnsibleAzureOcpDeployYml, - "master/tmp/ansible/azure-ocp-deploy.yml", - ) -} - -func masterTmpAnsibleAzureOcpDeployYml() (*asset, error) { - bytes, err := masterTmpAnsibleAzureOcpDeployYmlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/tmp/ansible/azure-ocp-deploy.yml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterTmpBootstrapconfigsComputeConfigYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x53\x4d\x6f\x1c\x37\x0c\xbd\xeb\x57\x10\x9b\x6b\x77\x3e\xd6\x4d\x03\x08\xc8\xc1\xf5\x47\x1a\xb4\x89\xdd\xb5\xdb\x6b\xa0\x91\x38\xbb\xea\x6a\x44\x95\x92\xc6\xde\xfe\xfa\x42\x9a\xf5\x17\x7a\x69\x2e\x03\x0c\xf9\xf8\xf8\xf8\x44\x2a\xe7\xe8\xe1\xd2\x46\x35\x38\x34\x97\xa4\x0f\xc8\x12\x46\xe5\x22\x0a\x15\xec\x9f\xc8\xd1\x92\x97\x30\xf7\xc2\xf8\xf8\xb3\xf5\xe6\xdc\x18\xc6\x18\x25\xf4\x9b\x0f\x4d\xd7\x74\x4d\x2f\xdf\x9f\x95\xe4\x16\x75\xe6\x68\x67\xdc\x62\x24\x37\x5f\x90\x1f\x25\xb4\x98\x74\x4b\x6c\x77\xd6\xb7\x9e\x0c\xb6\x5c\x93\x8d\x26\x3f\x96\xa2\x4b\x9a\x94\xf5\x12\xb4\xcb\x31\x21\x37\x8e\xb4\x72\x25\xf1\xf9\x56\x42\xff\x61\xd3\xf4\xa5\x49\x2f\x4c\x55\x56\x38\xed\x4e\x0a\x00\x7c\x44\xfd\x8b\xf2\xc6\x21\x7f\x55\x13\x4a\x58\xad\x84\x0d\xa9\x4c\x11\xef\x8e\x5e\xdf\x22\x5b\x32\x12\x56\x67\x5d\x5c\x09\x3b\xa9\x1d\xbe\x14\x8f\xc4\x93\x4a\x12\xbe\x9c\xdf\xdd\x5f\x6d\xbf\xdd\x6c\xaf\x3e\x7d\xfb\x63\xfb\x9b\x00\x70\x2a\x61\x4c\x12\xae\xab\x01\x07\xeb\x8d\x84\xaf\x64\x4e\xb5\xe2\x90\x07\x74\x98\xce\x79\x97\x27\xf4\x29\x16\xb2\x32\xd5\xda\xa9\x01\x5d\xfd\x5d\x2f\x01\x26\x87\x4d\x81\xb3\xc7\x84\xb1\xb1\xd4\x6a\x9a\x42\x4e\xf8\x31\x71\xc6\x0a\x64\xdc\x59\xf2\x1f\x03\xdb\x49\xf1\x51\x00\x68\x47\xd9\xac\x03\xd3\x6c\x0d\xf2\xc2\xb6\x52\xff\x64\xc6\xd5\x73\x56\x3f\x4f\xb1\x86\x55\x75\xb7\x02\x96\x6f\xb5\x75\x25\x26\x55\xbc\xbc\x70\x16\x7d\xba\x20\xef\x51\x27\x4b\xfe\x66\x46\x66\x6b\xb0\xca\x54\x5a\x63\x28\xc9\x84\x3e\xdd\x1f\x03\x46\x09\x2a\x04\x67\xb5\x2a\xd8\x76\xf6\xe6\xb5\xfc\xc0\x94\x68\xc8\xe3\x0f\xaf\x31\x7f\x45\xf2\x45\xd7\x0b\xc9\xff\xe2\x10\x00\x43\xe6\xe2\xf2\xa6\xeb\x04\xc0\xdf\xa1\x2c\x53\xd7\x9d\x64\xff\x9a\x87\xa7\xa7\xaa\x56\x56\x8a\x65\x6a\xe1\x31\x3d\x10\x1f\x6e\x5d\xde\x59\xbf\xbc\x3b\xa3\xd9\xab\xd4\x52\x40\x1f\xf7\x76\x4c\x6b\x9a\xe3\x3a\xe6\xc1\x63\x12\xef\xe0\x54\xb0\xf0\x41\x4c\x9c\x75\x02\xeb\x13\x93\xc9\x1a\x0d\x58\x0f\xcb\x72\x42\xdf\x74\xcd\x4f\xa0\xbc\x81\x9b\xbb\x2b\x38\x6b\xba\x66\x03\x0f\x7b\xab\xf7\xe2\x1d\x18\x0c\x8c\xba\xac\x06\xfc\x47\x01\xa8\x81\x66\x6c\xe0\x7e\x8f\x90\x1e\x08\xe2\x9e\xb2\x33\x30\xa9\xa4\xf7\x8d\x78\xd3\xbf\xf8\x3e\xa5\x2c\xa1\xff\xf1\x7d\x19\xfc\x3b\xa7\x09\x64\xbe\x28\x6f\x47\x8c\xe9\x89\x2f\x22\xcf\xd6\xef\x3e\xfb\x91\x0a\xf9\xf0\xfa\x3c\xbb\x7a\x9c\x9d\xec\xbb\x4d\xed\xa6\x91\xd3\xb5\x75\x28\xa1\x54\x21\x37\x9a\x53\xdd\xaa\xba\x25\xe7\x12\xb4\x3a\x85\x0e\x78\x7c\x03\x3c\xe0\x51\xcc\xe4\xf2\x84\x97\x96\x51\x27\xe2\xa3\x84\x76\x56\xdc\x3a\x3b\x3c\x1d\xf7\xb3\xe4\xe5\x84\x9b\xa5\x20\x8a\xc0\xf4\x78\x7c\x73\x30\x35\xb2\x9e\xc8\x60\xf9\x83\xb2\xc8\x4f\x97\x7b\x6a\xf3\x62\x57\xe5\xfa\x3d\x53\x52\x0b\x36\x20\x5f\xdf\x7d\x62\xca\x41\x8a\x7f\x03\x00\x00\xff\xff\xbb\x3a\x11\x32\xba\x04\x00\x00") - -func masterTmpBootstrapconfigsComputeConfigYamlBytes() ([]byte, error) { - return bindataRead( - _masterTmpBootstrapconfigsComputeConfigYaml, - "master/tmp/bootstrapconfigs/compute-config.yaml", - ) -} - -func masterTmpBootstrapconfigsComputeConfigYaml() (*asset, error) { - bytes, err := masterTmpBootstrapconfigsComputeConfigYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/tmp/bootstrapconfigs/compute-config.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterTmpBootstrapconfigsInfraConfigYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x53\x4d\x8f\x1b\x37\x0c\xbd\xeb\x57\x10\xce\xb5\x9e\x0f\x6f\xd3\x00\x02\x7a\xd8\xee\x47\x1a\xb4\xc9\x6e\xbd\xdb\x5e\x03\x8d\xc4\xb1\x55\x6b\xc8\x29\x25\xcd\xc6\xfd\xf5\x85\x66\xec\xfd\x40\x2f\xed\x45\x80\x44\xf2\x91\xef\x89\xcf\x84\xc0\x4f\xd7\x3e\x9a\x2e\xa0\xbb\x66\x7b\x40\xd1\xd0\x9b\x10\x51\x99\xd1\xff\x81\x12\x3d\x93\x86\xa9\x55\x8e\xe2\x4f\x9e\xdc\xa5\x73\x82\x31\x6a\x68\x37\x1f\xaa\xa6\x6a\xaa\x56\xbf\xbf\x28\xc1\x2d\xda\x2c\xd1\x4f\xb8\xc5\xc8\x61\xba\x62\xea\x35\xd4\x98\x6c\xcd\xe2\x77\x9e\x6a\x62\x87\xb5\xcc\xc1\xca\x32\xf5\xa5\xe8\x9a\x07\xe3\x49\x83\x0d\x39\x26\x94\x2a\xb0\x35\xa1\x04\x3e\xdd\x6b\x68\x3f\x6c\xaa\xb6\x34\x69\x95\x9b\x27\x2b\x98\x7e\xa7\x15\x00\x7e\x43\xfb\xb3\x21\x17\x50\xbe\x98\x01\x35\xac\x56\xca\x8f\xa9\xb0\x88\x0f\x47\xb2\xf7\x28\x9e\x9d\x86\xd5\x45\x13\x57\xca\x0f\x66\x87\x2f\xc5\x3d\xcb\x60\x92\x86\xcf\x97\x0f\x8f\x37\xdb\xaf\x77\xdb\x9b\x8f\x5f\x7f\xdf\xfe\xaa\x00\x82\x49\x18\x93\x86\xdb\x59\x80\x83\x27\xa7\xe1\x0b\xbb\x53\xad\x3a\xe4\x0e\x03\xa6\x4b\xd9\xe5\x01\x29\xc5\x02\x56\x58\xad\x83\xe9\x30\xcc\xd7\x35\x08\xee\x3c\xd3\x8f\x9e\x7a\x31\x0a\xc0\x06\xce\x6e\x3d\x0a\x4f\xde\xa1\x2c\x29\x2b\xf3\x77\x16\x5c\x3d\x47\xed\xf3\x68\x6b\x58\xcd\x92\xcd\x09\xcb\x39\x6b\xb5\x52\x83\x29\x02\x5d\x05\x8f\x94\xae\x98\x08\x6d\xf2\x4c\x77\x13\x8a\x78\x87\x73\x6f\x63\x2d\x8e\x25\x98\x90\xd2\xe3\x71\xc4\xa8\xc1\x8c\x63\xf0\xd6\x94\xdc\x7a\x22\x57\x15\x0a\x42\x98\x30\x56\xa3\x70\xe2\x2e\xf7\xdf\xbd\xce\xf9\x33\x32\x95\xb9\x5e\x40\xfe\x13\x86\x02\xe8\xb2\x14\xe9\x36\x4d\xa3\x00\xfe\x1a\xcb\x86\x34\xcd\x69\xec\x5f\x72\x77\xd6\x7f\x16\x6c\x86\x58\x58\x2b\xc2\xf4\xc4\x72\xb8\x0f\x79\xe7\x69\xf9\x4c\x41\xb7\x37\xa9\xe6\x11\x29\xee\x7d\x9f\xd6\x3c\xc5\x75\xcc\x1d\x61\x52\xef\xe0\x54\xb0\xe0\x41\x4c\x92\x6d\x02\x4f\x49\xd8\x65\x8b\x0e\x3c\xc1\xb2\x71\xd0\x56\x4d\xf5\x03\x18\x72\x70\xf7\x70\x03\x17\x55\x53\x6d\xe0\x69\xef\xed\x5e\xbd\x03\x87\xa3\xa0\x2d\xff\x0d\xff\x9a\x00\x4c\xc7\x13\x56\xf0\xb8\x47\x48\x4f\x0c\x71\xcf\x39\x38\x18\x4c\xb2\xfb\x4a\xbd\xe9\x5f\x74\x1f\x52\xd6\xd0\x7e\xff\xbe\x10\xff\x9f\x6c\x46\x76\x9f\x0d\xf9\x1e\x63\x3a\xe3\x45\x94\xc9\xd3\xee\x13\xf5\x5c\xc0\xbb\xd7\x9e\x6b\x66\xc7\x35\xba\x6d\x36\x73\x37\x8b\x92\x6e\x7d\x40\x0d\xa5\x0a\xa5\xb2\x92\xe6\xad\x9a\xb7\xe4\x52\x83\x35\xa7\xa7\x03\x1e\xdf\x24\x1e\xf0\xa8\x26\x0e\x79\xc0\x6b\x2f\x68\x13\xcb\x51\x43\x3d\x19\xa9\x83\xef\xce\x8e\x7d\x1e\x79\xf1\x65\xb5\x14\x44\x35\x0a\x7f\x3b\xbe\x71\xc1\xfc\xb2\x1e\xd8\x61\xb9\x41\x59\xe4\xb3\x1d\x4f\x6d\x5e\xe4\x9a\xb1\x7e\xcb\x9c\xcc\x92\x3b\xa2\xdc\x3e\x7c\x14\xce\xa3\x56\xff\x04\x00\x00\xff\xff\x74\xc9\xde\x4f\x8f\x04\x00\x00") - -func masterTmpBootstrapconfigsInfraConfigYamlBytes() ([]byte, error) { - return bindataRead( - _masterTmpBootstrapconfigsInfraConfigYaml, - "master/tmp/bootstrapconfigs/infra-config.yaml", - ) -} - -func masterTmpBootstrapconfigsInfraConfigYaml() (*asset, error) { - bytes, err := masterTmpBootstrapconfigsInfraConfigYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/tmp/bootstrapconfigs/infra-config.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterTmpBootstrapconfigsMasterConfigYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x53\x4d\x6f\x1b\x37\x10\xbd\xf3\x57\x0c\x94\x6b\xb5\x1f\x72\xd3\x00\x04\x72\x70\xfd\x91\x06\x6d\x62\x57\x76\x7b\x0d\xb8\xe4\xac\xc4\x8a\xcb\x61\x87\xe4\xda\xea\xaf\x2f\xc8\x95\xbf\xd0\x4b\x73\x11\xb0\x9c\x37\x6f\xe6\x3d\xbd\x51\xce\xd1\xc3\xa5\x8d\x6a\x70\x68\x2e\x49\x1f\x90\x25\x8c\xca\x45\x14\x2a\xd8\x3f\x91\xa3\x25\x2f\x61\xee\x85\xf1\xf1\x67\xeb\xcd\xb9\x31\x8c\x31\x4a\xe8\x37\x1f\x9a\xae\xe9\x9a\x5e\xbe\x3f\x2b\xc5\x2d\xea\xcc\xd1\xce\xb8\xc5\x48\x6e\xbe\x20\x3f\x4a\x68\x31\xe9\x96\xd8\xee\xac\x6f\x3d\x19\x6c\xb9\x16\x1b\x4d\x7e\x2c\x4d\x97\x34\x29\xeb\x25\x68\x97\x63\x42\x6e\x1c\x69\xe5\x4a\xe1\xf3\xad\x84\xfe\xc3\xa6\xe9\xcb\x90\x5e\x98\xba\x59\xe1\xb4\x3b\x29\x00\xf0\x11\xf5\x2f\xca\x1b\x87\xfc\x55\x4d\x28\x61\xb5\x12\x36\xa4\xa2\x22\xde\x1d\xbd\xbe\x45\xb6\x64\x24\xac\xce\xba\xb8\x12\x76\x52\x3b\x7c\x69\x1e\x89\x27\x95\x24\x7c\x39\xbf\xbb\xbf\xda\x7e\xbb\xd9\x5e\x7d\xfa\xf6\xc7\xf6\x37\x01\xe0\x54\xc2\x98\x24\x5c\x57\x03\x0e\xd6\x1b\x09\x5f\xc9\x9c\x7a\xc5\x21\x0f\xe8\x30\x9d\xf3\x2e\x4f\xe8\x53\x2c\x64\x45\xd5\xda\xa9\x01\x5d\xfd\x5c\x2f\x0f\x4c\x0e\x9b\x02\x67\x8f\x09\x63\x63\xa9\x9d\x54\x51\xf8\x31\x71\xc6\x8a\xa3\x80\x3e\xee\xed\x98\xd6\xd6\x8f\xac\x3e\xaa\x60\x23\xf2\x8c\x2c\x00\xb4\xa3\x6c\xd6\x81\x69\xb6\x06\x79\xe1\x5d\xa9\x7f\x32\xe3\xea\xb9\xaa\x9f\xf5\xac\x61\x55\x7d\xae\x80\xe5\xb7\x1a\xbc\x12\xcb\xcc\x0b\x67\xd1\xa7\x0b\xf2\x1e\x75\xb2\xe4\x6f\x66\x64\xb6\x06\xeb\xc2\x4a\x6b\x0c\xa5\x98\xd0\xa7\xfb\x63\xc0\x28\x41\x85\xe0\xac\x56\x05\xdb\xce\xde\xbc\x16\x12\x98\x12\x0d\x79\xfc\xe1\x35\xe6\xaf\x48\xbe\xec\xf5\x42\xf2\xbf\x38\x04\xc0\x90\xb9\xf8\xbd\xe9\x3a\x01\xf0\x77\x28\xb1\xea\xba\xd3\xda\xbf\xe6\xe1\xe9\x4f\xab\xa6\x56\x8a\x45\xb5\xf0\x98\x1e\x88\x0f\xb7\x2e\xef\xac\x5f\x12\xc0\x68\xf6\x2a\xb5\x2f\xb6\xd2\x1c\xd7\x31\x0f\x1e\x93\x78\x07\xa7\x86\x85\x0f\x62\xe2\xac\x13\x58\x9f\x98\x4c\xd6\x68\xc0\x7a\x58\x62\x0a\x7d\xd3\x35\x3f\x81\xf2\x06\x6e\xee\xae\xe0\xac\xe9\x9a\x0d\x3c\xec\xad\xde\x8b\x77\x60\x30\x30\xea\x12\x12\xf8\xcf\x06\xa0\x06\x9a\xb1\x81\xfb\x3d\x42\x7a\x20\x88\x7b\xca\xce\xc0\xa4\x92\xde\x37\xe2\xcd\xfc\xe2\xfb\x94\xb2\x84\xfe\xc7\xf7\x45\xf8\x77\xaa\x09\x64\xbe\x28\x6f\x47\x8c\xe9\x89\xaf\x24\xc7\xfa\xdd\x67\x3f\x52\x21\x1f\x5e\x1f\x6a\x57\xcf\xb4\x93\x7d\xb7\xa9\xd3\x34\x72\xba\xb6\x0e\x25\x2c\x79\x6b\x34\xa7\x9a\xaa\x9a\x92\x73\x09\x5a\x9d\x9e\x0e\x78\x7c\x03\x3c\xe0\x51\xcc\xe4\xf2\x84\x97\x96\x51\x27\xe2\xa3\x84\x76\x56\xdc\x3a\x3b\x3c\x9d\xf9\xf3\xca\xcb\x31\x37\x4b\x43\x14\x81\xe9\xf1\xf8\xe6\x74\xea\xcb\x7a\x22\x83\xe5\x0b\x4a\x90\x9f\x6e\xf8\x34\xe6\xc5\xae\xca\xf5\x7b\xa6\xa4\x16\x6c\x40\xbe\xbe\xfb\xc4\x94\x83\x14\xff\x06\x00\x00\xff\xff\x9a\x3c\x85\xf3\xc4\x04\x00\x00") - -func masterTmpBootstrapconfigsMasterConfigYamlBytes() ([]byte, error) { - return bindataRead( - _masterTmpBootstrapconfigsMasterConfigYaml, - "master/tmp/bootstrapconfigs/master-config.yaml", - ) -} - -func masterTmpBootstrapconfigsMasterConfigYaml() (*asset, error) { - bytes, err := masterTmpBootstrapconfigsMasterConfigYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/tmp/bootstrapconfigs/master-config.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _nodeEtcAzureAzureConf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x90\x51\x8a\x83\x30\x10\x86\xdf\xf7\x14\x39\x81\x07\xd8\xb7\xa0\xb0\x2c\x2c\xcb\xb2\x7a\x81\x31\x4e\xcb\x40\x4c\xec\x38\x29\x58\xeb\xdd\x4b\xab\x0f\x51\xd3\x42\x9f\xbf\xff\xfb\x87\xf9\x05\x1d\x38\xf9\x6e\x3e\xd5\x38\xaa\x4c\x5f\x02\x63\xee\xdd\x81\x8e\x59\x35\x93\x42\x5d\xd5\x29\x78\x41\x35\x4d\x1f\x7d\xa8\x7b\xc3\xd4\x09\x79\x97\x72\xca\x98\xaf\x4c\x80\x26\xb7\x84\xe9\x53\x5a\x17\x0b\x4c\x3b\x25\x1a\x46\x79\xe1\xcd\x81\x8d\x5b\xbd\xf5\x1a\x63\xef\x03\x1b\xfc\x62\x1f\xba\xbd\xf2\x1f\xe3\xd8\xb3\xde\xc0\xfd\xdd\xbd\xf2\xb3\x90\xd5\x80\x68\x02\x93\x0c\x8f\x9a\x5f\x68\x31\xb1\xe1\x36\x12\xfb\x1d\x53\x0b\x3c\xe8\x33\x90\x85\x9a\x2c\xc9\x50\xa2\xa4\x8b\xfe\x9e\x66\xe3\xc6\x5b\x00\x00\x00\xff\xff\x34\x7d\xff\xaa\x01\x02\x00\x00") - -func nodeEtcAzureAzureConfBytes() ([]byte, error) { - return bindataRead( - _nodeEtcAzureAzureConf, - "node/etc/azure/azure.conf", - ) -} - -func nodeEtcAzureAzureConf() (*asset, error) { - bytes, err := nodeEtcAzureAzureConfBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "node/etc/azure/azure.conf", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _nodeEtcOriginNodeNodeDnsmasqConf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2a\x4e\x2d\x2a\x4b\x2d\xb2\xd5\xcf\xcc\xd3\x4d\x4c\x49\x29\xd2\x4b\x2c\x2a\x48\xd4\x37\x34\x32\xd7\x33\xd0\x33\xd0\x33\xe4\x82\x49\x27\xe7\x94\x16\x97\xa4\x16\xe9\xe5\xe4\x27\x27\xe6\x20\xc9\x03\x02\x00\x00\xff\xff\x87\xc4\xbf\xc2\x3f\x00\x00\x00") - -func nodeEtcOriginNodeNodeDnsmasqConfBytes() ([]byte, error) { - return bindataRead( - _nodeEtcOriginNodeNodeDnsmasqConf, - "node/etc/origin/node/node-dnsmasq.conf", - ) -} - -func nodeEtcOriginNodeNodeDnsmasqConf() (*asset, error) { - bytes, err := nodeEtcOriginNodeNodeDnsmasqConfBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "node/etc/origin/node/node-dnsmasq.conf", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _nodeEtcOriginNodeResolvConf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xca\x4b\xcc\x4d\x2d\x4e\x2d\x2a\x4b\x2d\x52\x30\x34\xb3\xd0\x33\x33\xd6\x33\x34\xb2\xd4\x33\x34\xe3\x02\x04\x00\x00\xff\xff\x77\xaa\x94\x8c\x19\x00\x00\x00") - -func nodeEtcOriginNodeResolvConfBytes() ([]byte, error) { - return bindataRead( - _nodeEtcOriginNodeResolvConf, - "node/etc/origin/node/resolv.conf", - ) -} - -func nodeEtcOriginNodeResolvConf() (*asset, error) { - bytes, err := nodeEtcOriginNodeResolvConfBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "node/etc/origin/node/resolv.conf", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -// Asset loads and returns the asset for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func Asset(name string) ([]byte, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) - } - return a.bytes, nil - } - return nil, fmt.Errorf("Asset %s not found", name) -} - -// MustAsset is like Asset but panics when Asset would return an error. -// It simplifies safe initialization of global variables. -func MustAsset(name string) []byte { - a, err := Asset(name) - if err != nil { - panic("asset: Asset(" + name + "): " + err.Error()) - } - - return a -} - -// AssetInfo loads and returns the asset info for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func AssetInfo(name string) (os.FileInfo, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) - } - return a.info, nil - } - return nil, fmt.Errorf("AssetInfo %s not found", name) -} - -// AssetNames returns the names of the assets. -func AssetNames() []string { - names := make([]string, 0, len(_bindata)) - for name := range _bindata { - names = append(names, name) - } - return names -} - -// _bindata is a table, holding each asset generator, mapped to its name. -var _bindata = map[string]func() (*asset, error){ - "master/etc/etcd/etcd.conf": masterEtcEtcdEtcdConf, - "master/etc/origin/master/htpasswd": masterEtcOriginMasterHtpasswd, - "master/etc/origin/master/master-config.yaml": masterEtcOriginMasterMasterConfigYaml, - "master/etc/origin/master/scheduler.json": masterEtcOriginMasterSchedulerJson, - "master/etc/origin/master/session-secrets.yaml": masterEtcOriginMasterSessionSecretsYaml, - "master/tmp/ansible/ansible.sh": masterTmpAnsibleAnsibleSh, - "master/tmp/ansible/azure-local-master-inventory.yml": masterTmpAnsibleAzureLocalMasterInventoryYml, - "master/tmp/ansible/azure-ocp-deploy.yml": masterTmpAnsibleAzureOcpDeployYml, - "master/tmp/bootstrapconfigs/compute-config.yaml": masterTmpBootstrapconfigsComputeConfigYaml, - "master/tmp/bootstrapconfigs/infra-config.yaml": masterTmpBootstrapconfigsInfraConfigYaml, - "master/tmp/bootstrapconfigs/master-config.yaml": masterTmpBootstrapconfigsMasterConfigYaml, - "node/etc/azure/azure.conf": nodeEtcAzureAzureConf, - "node/etc/origin/node/node-dnsmasq.conf": nodeEtcOriginNodeNodeDnsmasqConf, - "node/etc/origin/node/resolv.conf": nodeEtcOriginNodeResolvConf, -} - -// AssetDir returns the file names below a certain -// directory embedded in the file by go-bindata. -// For example if you run go-bindata on data/... and data contains the -// following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png -// then AssetDir("data") would return []string{"foo.txt", "img"} -// AssetDir("data/img") would return []string{"a.png", "b.png"} -// AssetDir("foo.txt") and AssetDir("notexist") would return an error -// AssetDir("") will return []string{"data"}. -func AssetDir(name string) ([]string, error) { - node := _bintree - if len(name) != 0 { - cannonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(cannonicalName, "/") - for _, p := range pathList { - node = node.Children[p] - if node == nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - } - } - if node.Func != nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - rv := make([]string, 0, len(node.Children)) - for childName := range node.Children { - rv = append(rv, childName) - } - return rv, nil -} - -type bintree struct { - Func func() (*asset, error) - Children map[string]*bintree -} - -var _bintree = &bintree{nil, map[string]*bintree{ - "master": {nil, map[string]*bintree{ - "etc": {nil, map[string]*bintree{ - "etcd": {nil, map[string]*bintree{ - "etcd.conf": {masterEtcEtcdEtcdConf, map[string]*bintree{}}, - }}, - "origin": {nil, map[string]*bintree{ - "master": {nil, map[string]*bintree{ - "htpasswd": {masterEtcOriginMasterHtpasswd, map[string]*bintree{}}, - "master-config.yaml": {masterEtcOriginMasterMasterConfigYaml, map[string]*bintree{}}, - "scheduler.json": {masterEtcOriginMasterSchedulerJson, map[string]*bintree{}}, - "session-secrets.yaml": {masterEtcOriginMasterSessionSecretsYaml, map[string]*bintree{}}, - }}, - }}, - }}, - "tmp": {nil, map[string]*bintree{ - "ansible": {nil, map[string]*bintree{ - "ansible.sh": {masterTmpAnsibleAnsibleSh, map[string]*bintree{}}, - "azure-local-master-inventory.yml": {masterTmpAnsibleAzureLocalMasterInventoryYml, map[string]*bintree{}}, - "azure-ocp-deploy.yml": {masterTmpAnsibleAzureOcpDeployYml, map[string]*bintree{}}, - }}, - "bootstrapconfigs": {nil, map[string]*bintree{ - "compute-config.yaml": {masterTmpBootstrapconfigsComputeConfigYaml, map[string]*bintree{}}, - "infra-config.yaml": {masterTmpBootstrapconfigsInfraConfigYaml, map[string]*bintree{}}, - "master-config.yaml": {masterTmpBootstrapconfigsMasterConfigYaml, map[string]*bintree{}}, - }}, - }}, - }}, - "node": {nil, map[string]*bintree{ - "etc": {nil, map[string]*bintree{ - "azure": {nil, map[string]*bintree{ - "azure.conf": {nodeEtcAzureAzureConf, map[string]*bintree{}}, - }}, - "origin": {nil, map[string]*bintree{ - "node": {nil, map[string]*bintree{ - "node-dnsmasq.conf": {nodeEtcOriginNodeNodeDnsmasqConf, map[string]*bintree{}}, - "resolv.conf": {nodeEtcOriginNodeResolvConf, map[string]*bintree{}}, - }}, - }}, - }}, - }}, -}} - -// RestoreAsset restores an asset under the given directory -func RestoreAsset(dir, name string) error { - data, err := Asset(name) - if err != nil { - return err - } - info, err := AssetInfo(name) - if err != nil { - return err - } - err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) - if err != nil { - return err - } - err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) - if err != nil { - return err - } - err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) - if err != nil { - return err - } - return nil -} - -// RestoreAssets restores an asset under the given directory recursively -func RestoreAssets(dir, name string) error { - children, err := AssetDir(name) - // File - if err != nil { - return RestoreAsset(dir, name) - } - // Dir - for _, child := range children { - err = RestoreAssets(dir, filepath.Join(name, child)) - if err != nil { - return err - } - } - return nil -} - -func _filePath(dir, name string) string { - cannonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) -} diff --git a/pkg/openshift/certgen/release39/templates/master/etc/etcd/etcd.conf b/pkg/openshift/certgen/release39/templates/master/etc/etcd/etcd.conf deleted file mode 100644 index c148e25cc3..0000000000 --- a/pkg/openshift/certgen/release39/templates/master/etc/etcd/etcd.conf +++ /dev/null @@ -1,58 +0,0 @@ -ETCD_NAME={{ .Master.Hostname | shellQuote }} -ETCD_LISTEN_PEER_URLS={{ print "https://" (index .Master.IPs 0).String ":2380" | shellQuote }} -ETCD_DATA_DIR=/var/lib/etcd/ -#ETCD_WAL_DIR="" -#ETCD_SNAPSHOT_COUNT=10000 -ETCD_HEARTBEAT_INTERVAL=500 -ETCD_ELECTION_TIMEOUT=2500 -ETCD_LISTEN_CLIENT_URLS={{ print "https://" (index .Master.IPs 0).String ":2379" | shellQuote }} -#ETCD_MAX_SNAPSHOTS=5 -#ETCD_MAX_WALS=5 -#ETCD_CORS= - - -#[cluster] -ETCD_INITIAL_ADVERTISE_PEER_URLS={{ print "https://" (index .Master.IPs 0).String ":2380" | shellQuote }} -ETCD_INITIAL_CLUSTER={{ print .Master.Hostname "=https://" (index .Master.IPs 0).String ":2380" | shellQuote }} -ETCD_INITIAL_CLUSTER_STATE=new -ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster-1 -#ETCD_DISCOVERY= -#ETCD_DISCOVERY_SRV= -#ETCD_DISCOVERY_FALLBACK=proxy -#ETCD_DISCOVERY_PROXY= -ETCD_ADVERTISE_CLIENT_URLS={{ print "https://" (index .Master.IPs 0).String ":2379" | shellQuote }} -#ETCD_STRICT_RECONFIG_CHECK="false" -#ETCD_AUTO_COMPACTION_RETENTION="0" -#ETCD_ENABLE_V2="true" -ETCD_QUOTA_BACKEND_BYTES=4294967296 - -#[proxy] -#ETCD_PROXY=off -#ETCD_PROXY_FAILURE_WAIT="5000" -#ETCD_PROXY_REFRESH_INTERVAL="30000" -#ETCD_PROXY_DIAL_TIMEOUT="1000" -#ETCD_PROXY_WRITE_TIMEOUT="5000" -#ETCD_PROXY_READ_TIMEOUT="0" - -#[security] -ETCD_TRUSTED_CA_FILE=/etc/etcd/ca.crt -ETCD_CLIENT_CERT_AUTH="true" -ETCD_CERT_FILE=/etc/etcd/server.crt -ETCD_KEY_FILE=/etc/etcd/server.key -#ETCD_AUTO_TLS="false" -ETCD_PEER_TRUSTED_CA_FILE=/etc/etcd/ca.crt -ETCD_PEER_CLIENT_CERT_AUTH="true" -ETCD_PEER_CERT_FILE=/etc/etcd/peer.crt -ETCD_PEER_KEY_FILE=/etc/etcd/peer.key -#ETCD_PEER_AUTO_TLS="false" - -#[logging] -ETCD_DEBUG="False" -ETCD_LOG_PACKAGE_LEVELS="etcdserver=DEBUG" - -#[profiling] -#ETCD_ENABLE_PPROF="false" -#ETCD_METRICS="basic" -# -#[auth] -#ETCD_AUTH_TOKEN="simple" diff --git a/pkg/openshift/certgen/release39/templates/master/etc/origin/master/htpasswd b/pkg/openshift/certgen/release39/templates/master/etc/origin/master/htpasswd deleted file mode 100644 index 893fd8848e..0000000000 --- a/pkg/openshift/certgen/release39/templates/master/etc/origin/master/htpasswd +++ /dev/null @@ -1 +0,0 @@ -{{ .ClusterUsername }}:{{ Bcrypt .ClusterPassword }} diff --git a/pkg/openshift/certgen/release39/templates/master/etc/origin/master/master-config.yaml b/pkg/openshift/certgen/release39/templates/master/etc/origin/master/master-config.yaml deleted file mode 100644 index 1fe7ec8623..0000000000 --- a/pkg/openshift/certgen/release39/templates/master/etc/origin/master/master-config.yaml +++ /dev/null @@ -1,236 +0,0 @@ -admissionConfig: - pluginConfig: - BuildDefaults: - configuration: - apiVersion: v1 - env: [] - kind: BuildDefaultsConfig - resources: - limits: {} - requests: {} - BuildOverrides: - configuration: - apiVersion: v1 - kind: BuildOverridesConfig - PodPreset: - configuration: - apiVersion: v1 - disable: false - kind: DefaultAdmissionConfig - openshift.io/ImagePolicy: - configuration: - apiVersion: v1 - executionRules: - - matchImageAnnotations: - - key: images.openshift.io/deny-execution - value: 'true' - name: execution-denied - onResources: - - resource: pods - - resource: builds - reject: true - skipOnResolutionFailure: true - kind: ImagePolicyConfig -aggregatorConfig: - proxyClientInfo: - certFile: aggregator-front-proxy.crt - keyFile: aggregator-front-proxy.key -apiLevels: -- v1 -apiVersion: v1 -authConfig: - requestHeader: - clientCA: front-proxy-ca.crt - clientCommonNames: - - aggregator-front-proxy - extraHeaderPrefixes: - - X-Remote-Extra- - groupHeaders: - - X-Remote-Group - usernameHeaders: - - X-Remote-User -controllerConfig: - election: - lockName: openshift-master-controllers - serviceServingCert: - signer: - certFile: service-signer.crt - keyFile: service-signer.key -controllers: '*' -corsAllowedOrigins: -- (?i)//127\.0\.0\.1(:|\z) -- (?i)//localhost(:|\z) -- {{ print "(?i)//" (QuoteMeta (index .Master.IPs 0).String) "(:|\\z)" | quote }} -- (?i)//kubernetes\.default(:|\z) -- (?i)//kubernetes\.default\.svc\.cluster\.local(:|\z) -- (?i)//kubernetes(:|\z) -- {{ print "(?i)//" (QuoteMeta .ExternalMasterHostname) "(:|\\z)" | quote }} -- (?i)//openshift\.default(:|\z) -- {{ print "(?i)//" (QuoteMeta .Master.Hostname) "(:|\\z)" | quote }} -- (?i)//openshift\.default\.svc(:|\z) -- (?i)//kubernetes\.default\.svc(:|\z) -- (?i)//172\.30\.0\.1(:|\z) -- (?i)//openshift\.default\.svc\.cluster\.local(:|\z) -- (?i)//openshift(:|\z) -dnsConfig: - bindAddress: 0.0.0.0:8053 - bindNetwork: tcp4 -etcdClientInfo: - ca: master.etcd-ca.crt - certFile: master.etcd-client.crt - keyFile: master.etcd-client.key - urls: - - {{ print "https://" .Master.Hostname ":2379" | quote }} -etcdStorageConfig: - kubernetesStoragePrefix: kubernetes.io - kubernetesStorageVersion: v1 - openShiftStoragePrefix: openshift.io - openShiftStorageVersion: v1 -imageConfig: - format: MASTER_OREG_URL - latest: false -imagePolicyConfig: - internalRegistryHostname: docker-registry.default.svc:5000 -kind: MasterConfig -kubeletClientInfo: - ca: ca-bundle.crt - certFile: master.kubelet-client.crt - keyFile: master.kubelet-client.key - port: 10250 -kubernetesMasterConfig: - apiServerArguments: - runtime-config: - - apis/settings.k8s.io/v1alpha1=true - storage-backend: - - etcd3 - storage-media-type: - - application/vnd.kubernetes.protobuf - cloud-provider: - - "azure" - cloud-config: - - "/etc/azure/azure.conf" - controllerArguments: - cluster-signing-cert-file: - - "/etc/origin/master/ca.crt" - cluster-signing-key-file: - - "/etc/origin/master/ca.key" - cloud-provider: - - "azure" - cloud-config: - - "/etc/azure/azure.conf" - masterCount: 1 - masterIP: {{ (index .Master.IPs 0).String | quote }} - podEvictionTimeout: null - proxyClientInfo: - certFile: master.proxy-client.crt - keyFile: master.proxy-client.key - schedulerArguments: null - schedulerConfigFile: /etc/origin/master/scheduler.json - servicesNodePortRange: '' - servicesSubnet: 172.30.0.0/16 - staticNodeNames: [] -masterClients: - externalKubernetesClientConnectionOverrides: - acceptContentTypes: application/vnd.kubernetes.protobuf,application/json - burst: 400 - contentType: application/vnd.kubernetes.protobuf - qps: 200 - externalKubernetesKubeConfig: '' - openshiftLoopbackClientConnectionOverrides: - acceptContentTypes: application/vnd.kubernetes.protobuf,application/json - burst: 600 - contentType: application/vnd.kubernetes.protobuf - qps: 300 - openshiftLoopbackKubeConfig: openshift-master.kubeconfig -masterPublicURL: {{ print "https://" .ExternalMasterHostname ":" .Master.Port | quote }} -networkConfig: - clusterNetworkCIDR: 10.128.0.0/14 - clusterNetworks: - - cidr: 10.128.0.0/14 - hostSubnetLength: 9 - externalIPNetworkCIDRs: - - 0.0.0.0/0 - hostSubnetLength: 9 - networkPluginName: redhat/openshift-ovs-subnet - serviceNetworkCIDR: 172.30.0.0/16 -oauthConfig: - assetPublicURL: {{ print "https://" .ExternalMasterHostname ":" .Master.Port "/console/" | quote }} - grantConfig: - method: auto - identityProviders: -{{- if .EnableAADAuthentication}} - - name: Azure AD - challenge: false - login: true - mappingMethod: claim - provider: - apiVersion: v1 - kind: OpenIDIdentityProvider - clientID: {{ .AzureConfig.AADClientID | quote }} - clientSecret: {{ .AzureConfig.AADClientSecret | quote }} - claims: - id: - - sub - preferredUsername: - - unique_name - name: - - name - email: - - email - urls: - authorize: {{ print "https://login.microsoftonline.com/" .AzureConfig.TenantID "/oauth2/authorize" | quote }} - token: {{ print "https://login.microsoftonline.com/" .AzureConfig.TenantID "/oauth2/token" | quote }} -{{- end}} - - name: Local password - challenge: true - login: true - mappingMethod: claim - provider: - apiVersion: v1 - file: /etc/origin/master/htpasswd - kind: HTPasswdPasswordIdentityProvider - masterCA: ca-bundle.crt - masterPublicURL: {{ print "https://" .ExternalMasterHostname ":" .Master.Port | quote }} - masterURL: {{ print "https://" .ExternalMasterHostname ":" .Master.Port | quote }} - sessionConfig: - sessionMaxAgeSeconds: 3600 - sessionName: ssn - sessionSecretsFile: /etc/origin/master/session-secrets.yaml - tokenConfig: - accessTokenMaxAgeSeconds: 86400 - authorizeTokenMaxAgeSeconds: 500 -pauseControllers: false -policyConfig: - bootstrapPolicyFile: /etc/origin/master/policy.json - openshiftInfrastructureNamespace: openshift-infra - openshiftSharedResourcesNamespace: openshift -projectConfig: - defaultNodeSelector: node-role.kubernetes.io/compute=true - projectRequestMessage: '' - projectRequestTemplate: '' - securityAllocator: - mcsAllocatorRange: s0:/2 - mcsLabelsPerProject: 5 - uidAllocatorRange: 1000000000-1999999999/10000 -routingConfig: - subdomain: TEMPROUTERIP.nip.io -serviceAccountConfig: - limitSecretReferences: false - managedNames: - - default - - builder - - deployer - masterCA: ca-bundle.crt - privateKeyFile: serviceaccounts.private.key - publicKeyFiles: - - serviceaccounts.public.key -servingInfo: - bindAddress: {{ print "0.0.0.0:" .Master.Port | quote }} - bindNetwork: tcp4 - certFile: master.server.crt - clientCA: ca.crt - keyFile: master.server.key - maxRequestsInFlight: 500 - requestTimeoutSeconds: 3600 -volumeConfig: - dynamicProvisioningEnabled: true diff --git a/pkg/openshift/certgen/release39/templates/master/etc/origin/master/scheduler.json b/pkg/openshift/certgen/release39/templates/master/etc/origin/master/scheduler.json deleted file mode 100644 index c67f1b3b9b..0000000000 --- a/pkg/openshift/certgen/release39/templates/master/etc/origin/master/scheduler.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "apiVersion": "v1", - "kind": "Policy", - "predicates": [ - { - "name": "NoVolumeZoneConflict" - }, - { - "name": "MaxEBSVolumeCount" - }, - { - "name": "MaxGCEPDVolumeCount" - }, - { - "name": "MaxAzureDiskVolumeCount" - }, - { - "name": "MatchInterPodAffinity" - }, - { - "name": "NoDiskConflict" - }, - { - "name": "GeneralPredicates" - }, - { - "name": "PodToleratesNodeTaints" - }, - { - "name": "CheckNodeMemoryPressure" - }, - { - "name": "CheckNodeDiskPressure" - }, - { - "name": "CheckVolumeBinding" - }, - { - "argument": { - "serviceAffinity": { - "labels": [ - "region" - ] - } - }, - "name": "Region" - } - ], - "priorities": [ - { - "name": "SelectorSpreadPriority", - "weight": 1 - }, - { - "name": "InterPodAffinityPriority", - "weight": 1 - }, - { - "name": "LeastRequestedPriority", - "weight": 1 - }, - { - "name": "BalancedResourceAllocation", - "weight": 1 - }, - { - "name": "NodePreferAvoidPodsPriority", - "weight": 10000 - }, - { - "name": "NodeAffinityPriority", - "weight": 1 - }, - { - "name": "TaintTolerationPriority", - "weight": 1 - }, - { - "argument": { - "serviceAntiAffinity": { - "label": "zone" - } - }, - "name": "Zone", - "weight": 2 - } - ] -} diff --git a/pkg/openshift/certgen/release39/templates/master/etc/origin/master/session-secrets.yaml b/pkg/openshift/certgen/release39/templates/master/etc/origin/master/session-secrets.yaml deleted file mode 100644 index d440e83292..0000000000 --- a/pkg/openshift/certgen/release39/templates/master/etc/origin/master/session-secrets.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -kind: SessionSecrets -secrets: -- authentication: {{ .AuthSecret | quote }} - encryption: {{ .EncSecret | quote }} diff --git a/pkg/openshift/certgen/release39/templates/master/tmp/ansible/ansible.sh b/pkg/openshift/certgen/release39/templates/master/tmp/ansible/ansible.sh deleted file mode 100644 index 68e987341e..0000000000 --- a/pkg/openshift/certgen/release39/templates/master/tmp/ansible/ansible.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -ex - -# TODO: do this, and more (registry console, asb), the proper way - -# we get "dial tcp: lookup foo.eastus.cloudapp.azure.com on 10.0.0.11:53: read -# udp 172.17.0.2:56662->10.0.0.11:53: read: no route to host errors" at -# start-up: wait until these subside. -while ! oc version &>/dev/null; do - sleep 1 -done - -for project in default openshift-infra; do - oc patch project $project -p '{"metadata":{"annotations":{"openshift.io/node-selector": ""}}}' -done - -# FIXME - This should be handled by the openshift-ansible playbooks to ensure -# a directory it needs to write to exists before attempting to write -# to it -mkdir -p /etc/origin/master/named_certificates - -# Deploy all infra components reusing relevant parts from openshift-ansible -ANSIBLE_ROLES_PATH=/usr/share/ansible/openshift-ansible/roles/ \ - ansible-playbook\ - -M /usr/share/ansible/openshift-ansible/roles/lib_utils/library \ - -c local azure-ocp-deploy.yml \ - -i azure-local-master-inventory.yml - -# TODO: possibly wait here for convergence? diff --git a/pkg/openshift/certgen/release39/templates/master/tmp/ansible/azure-local-master-inventory.yml b/pkg/openshift/certgen/release39/templates/master/tmp/ansible/azure-local-master-inventory.yml deleted file mode 100644 index 23d5ebda4b..0000000000 --- a/pkg/openshift/certgen/release39/templates/master/tmp/ansible/azure-local-master-inventory.yml +++ /dev/null @@ -1,103 +0,0 @@ ---- -# FIXME: Anything below in all-caps has it's value replaced by sed in the -# openshiftmasterscript.sh which is not ideal, we should fix that. -localmaster: - hosts: - localhost - vars: - ansible_connection: local - ansible_python_interpreter: /usr/bin/python2 - - openshift_is_containerized: False - openshift_client_binary: /usr/bin/oc - - openshift_image_tag: "vVERSION" - - # NOTE: This changes in 3.10+ and it's all combined into a single variable - # under the name openshift_web_console_image_name - openshift_web_console_prefix: "IMAGE_PREFIX/" - openshift_web_console_image_name: "IMAGE_TYPE-web-console" - openshift_web_console_version: "vVERSION" - - oreg_url_master: 'MASTER_OREG_URL' - openshift_master_default_subdomain: 'TEMPROUTERIP.nip.io' - - # FIXME - # This should be type=infra, but we have to live with region=infra for now - # because of legacy reasons - openshift_router_selector: 'region=infra' - openshift_registry_selector: 'region=infra' - # No idea why this is a different data type, but it is - openshift_prometheus_node_selector: {'region': 'infra'} - - # Set Azure specific data for hosted registry - openshift_hosted_registry_storage_provider: "azure_blob" - openshift_hosted_registry_storage_kind: "object" - openshift_hosted_registry_storage_azure_blob_accountname: 'REGISTRY_STORAGE_AZURE_ACCOUNTNAME' - openshift_hosted_registry_storage_azure_blob_accountkey: 'REGISTRY_STORAGE_AZURE_ACCOUNTKEY' - openshift_hosted_registry_storage_azure_blob_container: "registry" - openshift_hosted_registry_storage_azure_blob_realm: "core.windows.net" - - # FIXME - # - # Hard code this for now. - # - # Currently the cluster state at deployment time does not have the nodes - # registered to the master with labels applied and ready to be queried - # against at the point in time in the deploy that the playbooks run. Also, - # the router replica count default "falls back" to 1 appropriately where as - # the registry replica logic does not. There was also discussion about if - # it's appropriate to do this with replicas == infra nodes because it's - # perfectly feasible to have an infra node count higher than the desired - # replicas. - # - # Revisit later (possibly a daemonset or $other) - openshift_hosted_router_replicas: 1 - openshift_hosted_registry_replicas: 1 - - openshift_prometheus_state: "present" - openshift_prometheus_node_exporter_image_version: 'PROMETHEUS_EXPORTER_VERSION' - - openshift_web_console_install: True - - openshift_prometheus_image_prefix: "IMAGE_PREFIX/" - openshift_deployment_type: 'ANSIBLE_DEPLOY_TYPE' - - ansible_service_broker_install: True - openshift_service_catalog_image_prefix: "IMAGE_PREFIX/IMAGE_TYPE-" - openshift_service_catalog_image_version: 'vVERSION' - openshift_master_etcd_urls: ["https://HOSTNAME:2379"] - - template_service_broker_prefix: "IMAGE_PREFIX/" - template_service_broker_image_name: "IMAGE_TYPE-template-service-broker" - template_service_broker_version: "vVERSION" - - # NOTE: This is redundant, but required to handle version skew between - # openshift-ansible in Origin and OCP - openshift_examples_content_version: "vSHORT_VER" - - openshift_cockpit_deployer_prefix: "COCKPIT_PREFIX/" - openshift_cockpit_deployer_basename: "COCKPIT_BASENAME" - openshift_cockpit_deployer_version: "COCKPIT_VERSION" - - # NOTE: Do not define openshift_hosted_router_replicas so that the task file - # router.yml inside the openshift_hosted role from openshift-ansible will - # autopopulate it using the openshift_hosted_router_selector and querying - # the number of infra nodes - - # NOTE: The variables below are internal to openshift-ansible and we're - # providing them here to avoid the incurred cost of fact finding - openshift: - common: - config_base: /etc/origin/ - examples_content_version: "vSHORT_VER" - master: - public_console_url: {{ print "https://" .ExternalMasterHostname ":8443/console" | quote }} - public_api_url: {{ print "https://" .ExternalMasterHostname ":8443" | quote }} - etcd_urls: ["https://HOSTNAME:2379"] #FIXME: No longer needed as of openshift-ansible-3.9.22-1 but we're not on that version yet - node: - nodename: 'HOSTNAME' - -oo_masters_to_config: - hosts: - localhost diff --git a/pkg/openshift/certgen/release39/templates/master/tmp/ansible/azure-ocp-deploy.yml b/pkg/openshift/certgen/release39/templates/master/tmp/ansible/azure-ocp-deploy.yml deleted file mode 100644 index 326d9093cb..0000000000 --- a/pkg/openshift/certgen/release39/templates/master/tmp/ansible/azure-ocp-deploy.yml +++ /dev/null @@ -1,62 +0,0 @@ -- name: Deploy OpenShift infrastructure workload - hosts: localmaster - gather_facts: false - - tasks: - - name: Import openshift_bootstrap_autoapprover role from openshift-ansible to deploy node bootstrap auto approver - import_role: - name: openshift_bootstrap_autoapprover - - - name: Import and use router task file from openshift-ansible openshift_hosted role - import_role: - name: openshift_hosted - tasks_from: router.yml - - - name: Import and use registry task file from openshift-ansible openshift_hosted role - import_role: - name: openshift_hosted - tasks_from: registry.yml - - - name: Import openshift_web_console role from openshift-ansible to deploy web console - import_role: - name: openshift_web_console - - # FIXME - There's a race condition where the infra label isn't applied to - # the infra node during cluster bring up in - # openshift_bootstrap_autoapprover, this is problematic because the - # openshift_prometheus role checks to ensure there is a node with - # the infra selector up/available/schedulable. - - shell: '/usr/bin/oc get nodes -l "region=infra" | wc -l' - register: result - until: result.stdout_lines[0]|int > 1 - retries: 30 - delay: 10 - - - - name: Import openshift_prometheus role from openshift-ansible to deploy prometheus - import_role: - name: openshift_prometheus - - - name: Import openshift_service_catalog role from openshift-ansible to deploy the service catalog - import_role: - name: openshift_service_catalog - - - name: Import ansible_service_broker role from openshift-ansible to deploy the ansible service broker - import_role: - name: ansible_service_broker - - - name: Import template_service_broker role from openshift-ansible to deploy the template service broker - import_role: - name: template_service_broker - - - name: Import openshift_examples role from openshift-ansible to deploy the examples - import_role: - name: openshift_examples - - - name: Import openshift_hosted_templates role from openshift-ansible to deploy the hosted templates - import_role: - name: openshift_hosted_templates - - - name: Import cockpit_ui role from openshift-ansible to deploy the registry console - import_role: - name: cockpit-ui diff --git a/pkg/openshift/certgen/release39/templates/master/tmp/bootstrapconfigs/compute-config.yaml b/pkg/openshift/certgen/release39/templates/master/tmp/bootstrapconfigs/compute-config.yaml deleted file mode 100644 index c7937c710e..0000000000 --- a/pkg/openshift/certgen/release39/templates/master/tmp/bootstrapconfigs/compute-config.yaml +++ /dev/null @@ -1,46 +0,0 @@ -allowDisabledDocker: false -apiVersion: v1 -dnsBindAddress: 127.0.0.1:53 -dnsRecursiveResolvConf: /etc/origin/node/resolv.conf -dnsDomain: cluster.local -dnsIP: 172.17.0.1 -dockerConfig: - execHandlerName: "" -iptablesSyncPeriod: "30s" -imageConfig: - format: MASTER_OREG_URL - latest: False -kind: NodeConfig -kubeletArguments: - node-labels: - - node-role.kubernetes.io/compute=true - - region=primary - cloud-provider: - - "azure" - cloud-config: - - "/etc/azure/azure.conf" -masterClientConnectionOverrides: - acceptContentTypes: application/vnd.kubernetes.protobuf,application/json - contentType: application/vnd.kubernetes.protobuf - burst: 200 - qps: 100 -masterKubeConfig: node.kubeconfig -networkPluginName: redhat/openshift-ovs-subnet -# networkConfig struct introduced in origin 1.0.6 and OSE 3.0.2 which -# deprecates networkPluginName above. The two should match. -networkConfig: - mtu: 1450 - networkPluginName: redhat/openshift-ovs-subnet -podManifestConfig: -servingInfo: - bindAddress: 0.0.0.0:10250 - certFile: server.crt - clientCA: ca.crt - keyFile: server.key -volumeDirectory: /var/lib/origin/openshift.local.volumes -proxyArguments: - proxy-mode: - - iptables -volumeConfig: - localQuota: - perFSGroup: diff --git a/pkg/openshift/certgen/release39/templates/master/tmp/bootstrapconfigs/infra-config.yaml b/pkg/openshift/certgen/release39/templates/master/tmp/bootstrapconfigs/infra-config.yaml deleted file mode 100644 index 293703fab6..0000000000 --- a/pkg/openshift/certgen/release39/templates/master/tmp/bootstrapconfigs/infra-config.yaml +++ /dev/null @@ -1,45 +0,0 @@ -allowDisabledDocker: false -apiVersion: v1 -dnsBindAddress: 127.0.0.1:53 -dnsRecursiveResolvConf: /etc/origin/node/resolv.conf -dnsDomain: cluster.local -dnsIP: 172.17.0.1 -dockerConfig: - execHandlerName: "" -iptablesSyncPeriod: "30s" -imageConfig: - format: MASTER_OREG_URL - latest: False -kind: NodeConfig -kubeletArguments: - node-labels: - - region=infra - cloud-provider: - - "azure" - cloud-config: - - "/etc/azure/azure.conf" -masterClientConnectionOverrides: - acceptContentTypes: application/vnd.kubernetes.protobuf,application/json - contentType: application/vnd.kubernetes.protobuf - burst: 200 - qps: 100 -masterKubeConfig: node.kubeconfig -networkPluginName: redhat/openshift-ovs-subnet -# networkConfig struct introduced in origin 1.0.6 and OSE 3.0.2 which -# deprecates networkPluginName above. The two should match. -networkConfig: - mtu: 1450 - networkPluginName: redhat/openshift-ovs-subnet -podManifestConfig: -servingInfo: - bindAddress: 0.0.0.0:10250 - certFile: server.crt - clientCA: ca.crt - keyFile: server.key -volumeDirectory: /var/lib/origin/openshift.local.volumes -proxyArguments: - proxy-mode: - - iptables -volumeConfig: - localQuota: - perFSGroup: diff --git a/pkg/openshift/certgen/release39/templates/master/tmp/bootstrapconfigs/master-config.yaml b/pkg/openshift/certgen/release39/templates/master/tmp/bootstrapconfigs/master-config.yaml deleted file mode 100644 index 75c2b50154..0000000000 --- a/pkg/openshift/certgen/release39/templates/master/tmp/bootstrapconfigs/master-config.yaml +++ /dev/null @@ -1,46 +0,0 @@ -allowDisabledDocker: false -apiVersion: v1 -dnsBindAddress: 127.0.0.1:53 -dnsRecursiveResolvConf: /etc/origin/node/resolv.conf -dnsDomain: cluster.local -dnsIP: 172.17.0.1 -dockerConfig: - execHandlerName: "" -iptablesSyncPeriod: "30s" -imageConfig: - format: MASTER_OREG_URL - latest: False -kind: NodeConfig -kubeletArguments: - node-labels: - - node-role.kubernetes.io/master=true - - openshift-infra=apiserver - cloud-provider: - - "azure" - cloud-config: - - "/etc/azure/azure.conf" -masterClientConnectionOverrides: - acceptContentTypes: application/vnd.kubernetes.protobuf,application/json - contentType: application/vnd.kubernetes.protobuf - burst: 200 - qps: 100 -masterKubeConfig: node.kubeconfig -networkPluginName: redhat/openshift-ovs-subnet -# networkConfig struct introduced in origin 1.0.6 and OSE 3.0.2 which -# deprecates networkPluginName above. The two should match. -networkConfig: - mtu: 1450 - networkPluginName: redhat/openshift-ovs-subnet -podManifestConfig: -servingInfo: - bindAddress: 0.0.0.0:10250 - certFile: server.crt - clientCA: ca.crt - keyFile: server.key -volumeDirectory: /var/lib/origin/openshift.local.volumes -proxyArguments: - proxy-mode: - - iptables -volumeConfig: - localQuota: - perFSGroup: diff --git a/pkg/openshift/certgen/release39/templates/node/etc/azure/azure.conf b/pkg/openshift/certgen/release39/templates/node/etc/azure/azure.conf deleted file mode 100644 index 870b2aad1d..0000000000 --- a/pkg/openshift/certgen/release39/templates/node/etc/azure/azure.conf +++ /dev/null @@ -1,9 +0,0 @@ -tenantId: {{ .AzureConfig.TenantID | quote }} -subscriptionId: {{ .AzureConfig.SubscriptionID | quote }} -aadClientId: {{ .AzureConfig.AADClientID | quote }} -aadClientSecret: {{ .AzureConfig.AADClientSecret | quote }} -aadTenantId: {{ .AzureConfig.TenantID | quote }} -resourceGroup: {{ .AzureConfig.ResourceGroup | quote }} -location: {{ .AzureConfig.Location | quote }} -securityGroupName: {{ .AzureConfig.SecurityGroupName | quote }} -primaryAvailabilitySetName: {{ .AzureConfig.PrimaryAvailabilitySetName | quote }} diff --git a/pkg/openshift/certgen/release39/templates/node/etc/origin/node/node-dnsmasq.conf b/pkg/openshift/certgen/release39/templates/node/etc/origin/node/node-dnsmasq.conf deleted file mode 100644 index 95b5433760..0000000000 --- a/pkg/openshift/certgen/release39/templates/node/etc/origin/node/node-dnsmasq.conf +++ /dev/null @@ -1,2 +0,0 @@ -server=/in-addr.arpa/127.0.0.1 -server=/cluster.local/127.0.0.1 diff --git a/pkg/openshift/certgen/release39/templates/node/etc/origin/node/resolv.conf b/pkg/openshift/certgen/release39/templates/node/etc/origin/node/resolv.conf deleted file mode 100644 index 265bc1d427..0000000000 --- a/pkg/openshift/certgen/release39/templates/node/etc/origin/node/resolv.conf +++ /dev/null @@ -1 +0,0 @@ -nameserver 168.63.129.16 diff --git a/pkg/openshift/certgen/release39/templates/templates.go b/pkg/openshift/certgen/release39/templates/templates.go deleted file mode 100644 index dac8432fde..0000000000 --- a/pkg/openshift/certgen/release39/templates/templates.go +++ /dev/null @@ -1 +0,0 @@ -package templates diff --git a/pkg/openshift/certgen/release39/tls.go b/pkg/openshift/certgen/release39/tls.go deleted file mode 100644 index 72d8119996..0000000000 --- a/pkg/openshift/certgen/release39/tls.go +++ /dev/null @@ -1,504 +0,0 @@ -package release39 - -import ( - "bytes" - "crypto/rand" - "crypto/rsa" - "crypto/sha1" - "crypto/x509" - "crypto/x509/pkix" - "encoding/asn1" - "encoding/pem" - "fmt" - "math/big" - "net" - "time" - - "github.com/Azure/acs-engine/pkg/openshift/filesystem" -) - -type authKeyID struct { - KeyIdentifier []byte `asn1:"optional,tag:0"` - AuthorityCertIssuer generalName `asn1:"optional,tag:1"` - AuthorityCertSerialNumber *big.Int `asn1:"optional,tag:2"` -} - -type generalName struct { - DirectoryName pkix.RDNSequence `asn1:"optional,explicit,tag:4"` -} - -func newCertAndKey(filename string, template, signingcert *x509.Certificate, signingkey *rsa.PrivateKey, etcdcaspecial, etcdclientspecial bool) (CertAndKey, error) { - bits := 2048 - if etcdcaspecial { - bits = 4096 - } - - key, err := rsa.GenerateKey(rand.Reader, bits) - if err != nil { - return CertAndKey{}, err - } - - if signingcert == nil { - // make it self-signed - signingcert = template - signingkey = key - } - - if etcdcaspecial { - template.SubjectKeyId = intsha1(key.N) - ext := pkix.Extension{ - Id: []int{2, 5, 29, 35}, - } - var err error - ext.Value, err = asn1.Marshal(authKeyID{ - AuthorityCertIssuer: generalName{DirectoryName: signingcert.Subject.ToRDNSequence()}, - AuthorityCertSerialNumber: signingcert.SerialNumber, - }) - if err != nil { - return CertAndKey{}, err - } - template.ExtraExtensions = append(template.Extensions, ext) - template.MaxPathLenZero = true - } - - if etcdclientspecial { - template.SubjectKeyId = intsha1(key.N) - ext := pkix.Extension{ - Id: []int{2, 5, 29, 35}, - } - var err error - ext.Value, err = asn1.Marshal(authKeyID{ - KeyIdentifier: intsha1(signingkey.N), - AuthorityCertIssuer: generalName{DirectoryName: signingcert.Subject.ToRDNSequence()}, - AuthorityCertSerialNumber: signingcert.SerialNumber, - }) - if err != nil { - return CertAndKey{}, err - } - template.ExtraExtensions = append(template.Extensions, ext) - } - - b, err := x509.CreateCertificate(rand.Reader, template, signingcert, key.Public(), signingkey) - if err != nil { - return CertAndKey{}, err - } - - cert, err := x509.ParseCertificate(b) - if err != nil { - return CertAndKey{}, err - } - - return CertAndKey{cert: cert, key: key}, nil -} - -func certAsBytes(cert *x509.Certificate) ([]byte, error) { - buf := &bytes.Buffer{} - - err := pem.Encode(buf, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}) - if err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -func writeCert(fs filesystem.Writer, filename string, cert *x509.Certificate) error { - b, err := certAsBytes(cert) - if err != nil { - return err - } - fi := GetFileInfo(filename) - return fs.WriteFile(filename, b, fi) -} - -func privateKeyAsBytes(key *rsa.PrivateKey) ([]byte, error) { - buf := &bytes.Buffer{} - - err := pem.Encode(buf, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}) - if err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -func writePrivateKey(fs filesystem.Writer, filename string, key *rsa.PrivateKey) error { - b, err := privateKeyAsBytes(key) - if err != nil { - return err - } - - fi := GetFileInfo(filename) - return fs.WriteFile(filename, b, fi) -} - -func writePublicKey(fs filesystem.Writer, filename string, key *rsa.PublicKey) error { - buf := &bytes.Buffer{} - - b, err := x509.MarshalPKIXPublicKey(key) - if err != nil { - return err - } - - err = pem.Encode(buf, &pem.Block{Type: "PUBLIC KEY", Bytes: b}) - if err != nil { - return err - } - fi := GetFileInfo(filename) - return fs.WriteFile(filename, buf.Bytes(), fi) -} - -// PrepareMasterCerts creates the master certs -func (c *Config) PrepareMasterCerts() error { - if c.cas == nil { - c.cas = map[string]CertAndKey{} - } - - if c.Master.certs == nil { - c.Master.certs = map[string]CertAndKey{} - } - - if c.Master.etcdcerts == nil { - c.Master.etcdcerts = map[string]CertAndKey{} - } - - ips := append([]net.IP{}, c.Master.IPs...) - ips = append(ips, net.ParseIP("172.30.0.1")) - - dns := []string{ - c.ExternalMasterHostname, "kubernetes", "kubernetes.default", "kubernetes.default.svc", - "kubernetes.default.svc.cluster.local", c.Master.Hostname, "openshift", - "openshift.default", "openshift.default.svc", - "openshift.default.svc.cluster.local", - } - for _, ip := range ips { - dns = append(dns, ip.String()) - } - - now := time.Now() - - cacerts := []struct { - filename string - template *x509.Certificate - }{ - { - filename: "etc/origin/master/ca", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: fmt.Sprintf("openshift-signer@%d", now.Unix())}, - }, - }, - { - filename: "etc/origin/master/front-proxy-ca", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: fmt.Sprintf("openshift-signer@%d", now.Unix())}, - }, - }, - { - filename: "etc/origin/master/frontproxy-ca", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: fmt.Sprintf("aggregator-proxy-car@%d", now.Unix())}, - }, - }, - { - filename: "etc/origin/master/master.etcd-ca", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: fmt.Sprintf("etcd-signer@%d", now.Unix())}, - }, - }, - { - filename: "etc/origin/master/service-signer", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: fmt.Sprintf("openshift-service-serving-signer@%d", now.Unix())}, - }, - }, - { - filename: "etc/origin/service-catalog/ca", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: "service-catalog-signer"}, - }, - }, - } - - for _, cacert := range cacerts { - template := &x509.Certificate{ - SerialNumber: c.serial.Get(), - NotBefore: now, - NotAfter: now.AddDate(5, 0, 0), - KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign, - BasicConstraintsValid: true, - IsCA: true, - } - template.Subject = cacert.template.Subject - - certAndKey, err := newCertAndKey(cacert.filename, template, nil, nil, cacert.filename == "etc/origin/master/master.etcd-ca", false) - if err != nil { - return err - } - - c.cas[cacert.filename] = certAndKey - } - - certs := []struct { - filename string - template *x509.Certificate - signer string - }{ - { - filename: "etc/origin/master/admin", - template: &x509.Certificate{ - Subject: pkix.Name{Organization: []string{"system:cluster-admins", "system:masters"}, CommonName: "system:admin"}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - }, - }, - { - filename: "etc/origin/master/aggregator-front-proxy", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: "aggregator-front-proxy"}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - }, - signer: "etc/origin/master/front-proxy-ca", - }, - { - filename: "etc/origin/master/etcd.server", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: c.Master.IPs[0].String()}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - DNSNames: dns, - IPAddresses: ips, - }, - }, - { - filename: "etc/origin/master/master.etcd-client", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: c.Master.Hostname}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - DNSNames: []string{c.Master.Hostname}, // TODO - IPAddresses: []net.IP{c.Master.IPs[0]}, // TODO - }, - signer: "etc/origin/master/master.etcd-ca", - }, - { - filename: "etc/origin/master/master.kubelet-client", - template: &x509.Certificate{ - Subject: pkix.Name{Organization: []string{"system:node-admins"}, CommonName: "system:openshift-node-admin"}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - }, - }, - { - filename: "etc/origin/master/master.proxy-client", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: "system:master-proxy"}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - }, - }, - { - filename: "etc/origin/master/master.server", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: c.Master.IPs[0].String()}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - DNSNames: dns, - IPAddresses: ips, - }, - }, - { - filename: "etc/origin/master/openshift-aggregator", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: "system:openshift-aggregator"}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - }, - signer: "etc/origin/master/frontproxy-ca", - }, - { - filename: "etc/origin/master/openshift-master", - template: &x509.Certificate{ - Subject: pkix.Name{Organization: []string{"system:masters", "system:openshift-master"}, CommonName: "system:openshift-master"}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - }, - }, - { - filename: "etc/origin/master/node-bootstrapper", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: "system:serviceaccount:openshift-infra:node-bootstrapper"}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - }, - }, - { - filename: "etc/origin/service-catalog/apiserver", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: "apiserver.kube-service-catalog"}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - DNSNames: []string{"apiserver.kube-service-catalog", "apiserver.kube-service-catalog.svc", "apiserver.kube-service-catalog.svc.cluster.local"}, - }, - signer: "etc/origin/service-catalog/ca", - }, - // TODO: registry cert - } - - for _, cert := range certs { - template := &x509.Certificate{ - SerialNumber: c.serial.Get(), - NotBefore: now, - NotAfter: now.AddDate(2, 0, 0), - KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, - BasicConstraintsValid: true, - } - template.Subject = cert.template.Subject - template.ExtKeyUsage = cert.template.ExtKeyUsage - template.DNSNames = cert.template.DNSNames - template.IPAddresses = cert.template.IPAddresses - - if cert.signer == "" { - cert.signer = "etc/origin/master/ca" - } - - certAndKey, err := newCertAndKey(cert.filename, template, c.cas[cert.signer].cert, c.cas[cert.signer].key, false, cert.filename == "etc/origin/master/master.etcd-client") - if err != nil { - return err - } - - c.Master.certs[cert.filename] = certAndKey - } - - etcdcerts := []struct { - filename string - template *x509.Certificate - signer string - }{ - { - filename: "etc/etcd/peer", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: c.Master.Hostname}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, - DNSNames: []string{c.Master.Hostname}, // TODO - IPAddresses: []net.IP{c.Master.IPs[0]}, // TODO - }, - signer: "etc/origin/master/master.etcd-ca", - }, - { - filename: "etc/etcd/server", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: c.Master.Hostname}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - DNSNames: []string{c.Master.Hostname}, // TODO - IPAddresses: []net.IP{c.Master.IPs[0]}, // TODO - }, - signer: "etc/origin/master/master.etcd-ca", - }, - } - - for _, cert := range etcdcerts { - template := &x509.Certificate{ - SerialNumber: c.serial.Get(), - NotBefore: now, - NotAfter: now.AddDate(5, 0, 0), - KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, - BasicConstraintsValid: true, - } - template.Subject = cert.template.Subject - template.ExtKeyUsage = cert.template.ExtKeyUsage - template.DNSNames = cert.template.DNSNames - template.IPAddresses = cert.template.IPAddresses - - certAndKey, err := newCertAndKey(cert.filename, template, c.cas[cert.signer].cert, c.cas[cert.signer].key, false, true) - if err != nil { - return err - } - - c.Master.etcdcerts[cert.filename] = certAndKey - } - - return nil -} - -// WriteMasterCerts writes the master certs -func (c *Config) WriteMasterCerts(fs filesystem.Writer) error { - for filename, ca := range c.cas { - err := writeCert(fs, fmt.Sprintf("%s.crt", filename), ca.cert) - if err != nil { - return err - } - - err = writePrivateKey(fs, fmt.Sprintf("%s.key", filename), ca.key) - if err != nil { - return err - } - } - - err := writeCert(fs, "etc/origin/master/ca-bundle.crt", c.cas["etc/origin/master/ca"].cert) - if err != nil { - return err - } - - err = writeCert(fs, "etc/origin/master/client-ca-bundle.crt", c.cas["etc/origin/master/ca"].cert) // TODO: confirm if needed - if err != nil { - return err - } - - err = writeCert(fs, "etc/etcd/ca.crt", c.cas["etc/origin/master/master.etcd-ca"].cert) - if err != nil { - return err - } - - for filename, cert := range c.Master.certs { - err := writeCert(fs, fmt.Sprintf("%s.crt", filename), cert.cert) - if err != nil { - return err - } - - err = writePrivateKey(fs, fmt.Sprintf("%s.key", filename), cert.key) - if err != nil { - return err - } - } - - for filename, cert := range c.Master.etcdcerts { - err := writeCert(fs, fmt.Sprintf("%s.crt", filename), cert.cert) - if err != nil { - return err - } - - err = writePrivateKey(fs, fmt.Sprintf("%s.key", filename), cert.key) - if err != nil { - return err - } - } - fname := "etc/origin/master/ca.serial.txt" - fi := GetFileInfo(fname) - return fs.WriteFile(fname, []byte(fmt.Sprintf("%02X\n", c.serial.Get())), fi) -} - -// WriteBootstrapCerts writes the node bootstrap certs -func (c *Config) WriteBootstrapCerts(fs filesystem.Writer) error { - err := writeCert(fs, "etc/origin/node/ca.crt", c.cas["etc/origin/master/ca"].cert) - if err != nil { - return err - } - - err = writeCert(fs, "etc/origin/node/node-bootstrapper.crt", c.Master.certs["etc/origin/master/node-bootstrapper"].cert) - if err != nil { - return err - } - - return writePrivateKey(fs, "etc/origin/node/node-bootstrapper.key", c.Master.certs["etc/origin/master/node-bootstrapper"].key) -} - -// WriteMasterKeypair writes the master service account keypair -func (c *Config) WriteMasterKeypair(fs filesystem.Writer) error { - key, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { - return err - } - - err = writePrivateKey(fs, "etc/origin/master/serviceaccounts.private.key", key) - if err != nil { - return err - } - - return writePublicKey(fs, "etc/origin/master/serviceaccounts.public.key", &key.PublicKey) -} - -func intsha1(n *big.Int) []byte { - h := sha1.New() - h.Write(n.Bytes()) - return h.Sum(nil) -} diff --git a/pkg/openshift/certgen/unstable/config.go b/pkg/openshift/certgen/unstable/config.go deleted file mode 100644 index f7fe5d8739..0000000000 --- a/pkg/openshift/certgen/unstable/config.go +++ /dev/null @@ -1,113 +0,0 @@ -package unstable - -import ( - "crypto/rsa" - "crypto/x509" - "math/big" - "net" - "sync" - - "github.com/Azure/acs-engine/pkg/openshift/filesystem" -) - -// Config represents an OpenShift configuration -type Config struct { - ExternalMasterHostname string - serial serial - cas map[string]CertAndKey - AuthSecret string - EncSecret string - Master *Master - Bootstrap KubeConfig - ClusterUsername string - ClusterPassword string - EnableAADAuthentication bool - AzureConfig AzureConfig -} - -// AzureConfig represents the azure.conf configuration -type AzureConfig struct { - TenantID string - SubscriptionID string - AADClientID string - AADClientSecret string - ResourceGroup string - Location string - SecurityGroupName string - PrimaryAvailabilitySetName string -} - -// Master represents an OpenShift master configuration -type Master struct { - Hostname string - IPs []net.IP - Port int16 - - certs map[string]CertAndKey - etcdcerts map[string]CertAndKey - kubeconfigs map[string]KubeConfig -} - -// CertAndKey is a certificate and key -type CertAndKey struct { - cert *x509.Certificate - key *rsa.PrivateKey -} - -type serial struct { - m sync.Mutex - i int64 -} - -func (s *serial) Get() *big.Int { - s.m.Lock() - defer s.m.Unlock() - - s.i++ - return big.NewInt(s.i) -} - -// WriteMaster writes the config files for a Master node to a Filesystem. -func (c *Config) WriteMaster(fs filesystem.Writer) error { - err := c.WriteMasterCerts(fs) - if err != nil { - return err - } - - err = c.WriteMasterKeypair(fs) - if err != nil { - return err - } - - err = c.WriteMasterKubeConfigs(fs) - if err != nil { - return err - } - - err = c.WriteMasterFiles(fs) - if err != nil { - return err - } - - err = c.WriteBootstrapCerts(fs) - if err != nil { - return err - } - - return c.WriteNodeFiles(fs) -} - -// WriteNode writes the config files for bootstrapping a node to a Filesystem. -func (c *Config) WriteNode(fs filesystem.Writer) error { - err := c.WriteBootstrapCerts(fs) - if err != nil { - return err - } - - err = c.WriteBootstrapKubeConfig(fs) - if err != nil { - return err - } - - return c.WriteNodeFiles(fs) -} diff --git a/pkg/openshift/certgen/unstable/config_test.go b/pkg/openshift/certgen/unstable/config_test.go deleted file mode 100644 index 7912f74af0..0000000000 --- a/pkg/openshift/certgen/unstable/config_test.go +++ /dev/null @@ -1,90 +0,0 @@ -package unstable - -import ( - "fmt" - "net" - "os" - "strings" - "testing" - - "github.com/Azure/acs-engine/pkg/openshift/filesystem" -) - -type fakefilesystem map[string]filesystem.Fileinfo - -func (f fakefilesystem) WriteFile(filename string, data []byte, fi filesystem.Fileinfo) error { - f[filename] = fi - // fmt.Printf("Filename: %v User: %s Group: %s Permissions: %04o string: %v\n", filename, fi.User, fi.Group, fi.Mode, fi.Mode.String()) - return nil -} - -func (f fakefilesystem) Mkdir(filename string, fi filesystem.Fileinfo) error { - // fmt.Printf("Filename: %v User: %s Group: %s Permissions: %04o string: %v\n", filename, fi.User, fi.Group, fi.Mode, fi.Mode.String()) - f[filename] = fi - return nil -} - -func (fakefilesystem) Close() error { - return nil -} - -var _ filesystem.Writer = &fakefilesystem{} - -func TestConfigFilePermissions(t *testing.T) { - c := Config{ - Master: &Master{ - Hostname: fmt.Sprintf("%s-master-%s-0", "test", "test"), - IPs: []net.IP{ - net.ParseIP("10.0.0.1"), - }, - }, - } - - err := c.PrepareMasterCerts() - if err != nil { - t.Fatal(err) - } - err = c.PrepareMasterKubeConfigs() - if err != nil { - t.Fatal(err) - } - err = c.PrepareMasterFiles() - if err != nil { - t.Fatal(err) - } - - err = c.PrepareBootstrapKubeConfig() - if err != nil { - t.Fatal(err) - } - - // create mock filesystem - fs := fakefilesystem{} - - err = c.WriteMaster(fs) - if err != nil { - t.Fatal(err) - } - - for fname, finfo := range fs { - fi := GetFileInfo(fname) - // fmt.Printf("fname=>[%s]\n", fname) - // Verify ownership and permissions are as expected - if fi.User != finfo.User { - t.Errorf("File: %s User does not match. user: %s expected: %s", fname, finfo.User, fi.User) - } - if fi.Group != finfo.Group { - t.Errorf("File: %s Group does not match. group: %s expected: %s", fname, finfo.Group, fi.Group) - } - if fi.Mode != 0 && fi.Mode != finfo.Mode { - t.Errorf("File: %s Mode does not match. mode: %04o expected: %04o", fname, finfo.Mode, fi.Mode) - } - // Check for .key does _not_ have read or write - if strings.HasSuffix(fname, ".key") && finfo.Mode&077 != 0 { - t.Errorf("File: %s Found Read or Write on key file. mode: %04o expected: 0600", fname, finfo.Mode) - } - if fname == "tmp" && fi.Mode != os.FileMode(01777) { - t.Errorf("File: %s /tmp should have 1777 file mode.", fname) - } - } -} diff --git a/pkg/openshift/certgen/unstable/defaults.go b/pkg/openshift/certgen/unstable/defaults.go deleted file mode 100644 index 076b93b01f..0000000000 --- a/pkg/openshift/certgen/unstable/defaults.go +++ /dev/null @@ -1,64 +0,0 @@ -package unstable - -import ( - "bytes" - - "github.com/Azure/acs-engine/pkg/openshift/filesystem" -) - -// OpenShiftSetDefaultCerts sets default certificate and configuration properties in the -// openshift orchestrator. -func OpenShiftSetDefaultCerts(c *Config) ([]byte, []byte, error) { - err := c.PrepareMasterCerts() - if err != nil { - return nil, nil, err - } - err = c.PrepareMasterKubeConfigs() - if err != nil { - return nil, nil, err - } - err = c.PrepareMasterFiles() - if err != nil { - return nil, nil, err - } - - err = c.PrepareBootstrapKubeConfig() - if err != nil { - return nil, nil, err - } - - masterBundle, err := getConfigBundle(c.WriteMaster) - if err != nil { - return nil, nil, err - } - - nodeBundle, err := getConfigBundle(c.WriteNode) - if err != nil { - return nil, nil, err - } - - return masterBundle, nodeBundle, nil -} - -type writeFn func(filesystem.Writer) error - -func getConfigBundle(write writeFn) ([]byte, error) { - b := &bytes.Buffer{} - - fs, err := filesystem.NewTGZWriter(b) - if err != nil { - return nil, err - } - - err = write(fs) - if err != nil { - return nil, err - } - - err = fs.Close() - if err != nil { - return nil, err - } - - return b.Bytes(), nil -} diff --git a/pkg/openshift/certgen/unstable/doc.go b/pkg/openshift/certgen/unstable/doc.go deleted file mode 100644 index 129c7c8031..0000000000 --- a/pkg/openshift/certgen/unstable/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -// Package unstable provides utilities related -// to generating all the necessary artifacts -// for an OpenShift deployment. -package unstable diff --git a/pkg/openshift/certgen/unstable/files.go b/pkg/openshift/certgen/unstable/files.go deleted file mode 100644 index 6fd5525989..0000000000 --- a/pkg/openshift/certgen/unstable/files.go +++ /dev/null @@ -1,179 +0,0 @@ -package unstable - -import ( - "bytes" - "crypto/rand" - "encoding/base64" - "os" - "regexp" - "strconv" - "strings" - "text/template" - - "github.com/Azure/acs-engine/pkg/openshift/certgen/unstable/templates" - "github.com/Azure/acs-engine/pkg/openshift/filesystem" - "golang.org/x/crypto/bcrypt" -) - -type modeinfo struct { - path *regexp.Regexp - mode os.FileMode - user string - group string -} - -// These ownerships are processed in order -var ownerships = []modeinfo{ - // etc/etcd directory - {path: regexp.MustCompile(`^etc/etcd$`), mode: 0755, user: "etcd", group: "etcd"}, - // tmp directory - {path: regexp.MustCompile(`^tmp$`), mode: 01777, user: "root", group: "root"}, - //start files - {path: regexp.MustCompile(`^etc/etcd/.*\.key$`), mode: 0600, user: "etcd", group: "etcd"}, - {path: regexp.MustCompile(`^etc/etcd/.*$`), user: "etcd", group: "etcd"}, - {path: regexp.MustCompile(`.*\.key$`), mode: 0600}, - {path: regexp.MustCompile(`.*\.kubeconfig$`), mode: 0600}, - {path: regexp.MustCompile(`^etc/origin/master/htpasswd$`), mode: 0600}, -} - -// GetFileInfo returns the permissions and ownership of the file if defined -func GetFileInfo(filename string) filesystem.Fileinfo { - // If filename matches a specific path then set the correct User, Group, and Mode - f := filesystem.Fileinfo{User: "root", Group: "root", Mode: 0644} - for _, owner := range ownerships { - - if owner.path.MatchString(filename) { - if owner.user != "" { - f.User = owner.user - } - if owner.group != "" { - f.Group = owner.group - } - if owner.mode != 0 { - f.Mode = owner.mode - } - break - } - } - - return f -} - -// PrepareMasterFiles creates the shared authentication and encryption secrets -func (c *Config) PrepareMasterFiles() error { - b := make([]byte, 24) - _, err := rand.Read(b) - if err != nil { - return err - } - c.AuthSecret = base64.StdEncoding.EncodeToString(b) - - _, err = rand.Read(b) - if err != nil { - return err - } - c.EncSecret = base64.StdEncoding.EncodeToString(b) - - return nil -} - -// WriteMasterFiles writes the templated master config -func (c *Config) WriteMasterFiles(fs filesystem.Writer) error { - - // create special case directories - specialCaseDirs := map[string]filesystem.Fileinfo{ - "tmp": { - User: "root", - Group: "root", - Mode: os.FileMode(01777), - }, - "etc/etcd": { - Mode: os.FileMode(0755), - User: "etcd", - Group: "etcd", - }, - } - - for na, fi := range specialCaseDirs { - err := fs.Mkdir(na, fi) - if err != nil { - return err - } - } - - for _, name := range templates.AssetNames() { - if !strings.HasPrefix(name, "master/") { - continue - } - tb := templates.MustAsset(name) - - t, err := template.New("template").Funcs(template.FuncMap{ - "QuoteMeta": regexp.QuoteMeta, - "Bcrypt": func(password string) (string, error) { - h, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) - return string(h), err - }, - "quote": strconv.Quote, - "shellQuote": func(s string) string { - return `'` + strings.Replace(s, `'`, `'\''`, -1) + `'` - }, - }).Parse(string(tb)) - if err != nil { - return err - } - - b := &bytes.Buffer{} - err = t.Execute(b, c) - if err != nil { - return err - } - - fname := strings.TrimPrefix(name, "master/") - fi := GetFileInfo(fname) - - err = fs.WriteFile(fname, b.Bytes(), fi) - if err != nil { - return err - } - } - - return nil -} - -// WriteNodeFiles writes the templated node config -func (c *Config) WriteNodeFiles(fs filesystem.Writer) error { - for _, name := range templates.AssetNames() { - if !strings.HasPrefix(name, "node/") { - continue - } - - tb := templates.MustAsset(name) - - t, err := template.New("template").Funcs(template.FuncMap{ - "QuoteMeta": regexp.QuoteMeta, - "quote": strconv.Quote, - "shellQuote": func(s string) string { - return `'` + strings.Replace(s, `'`, `'\''`, -1) + `'` - }, - }).Parse(string(tb)) - if err != nil { - return err - } - - b := &bytes.Buffer{} - err = t.Execute(b, c) - if err != nil { - return err - } - - fname := strings.TrimPrefix(name, "node/") - fi := GetFileInfo(fname) - - err = fs.WriteFile(fname, b.Bytes(), fi) - if err != nil { - return err - } - } - - return nil -} diff --git a/pkg/openshift/certgen/unstable/kubeconfig.go b/pkg/openshift/certgen/unstable/kubeconfig.go deleted file mode 100644 index 3582ef8947..0000000000 --- a/pkg/openshift/certgen/unstable/kubeconfig.go +++ /dev/null @@ -1,288 +0,0 @@ -package unstable - -import ( - "encoding/base64" - "fmt" - "os" - "strings" - - "github.com/Azure/acs-engine/pkg/openshift/filesystem" - yaml "gopkg.in/yaml.v2" -) - -// KubeConfig represents a kubeconfig -type KubeConfig struct { - APIVersion string `yaml:"apiVersion,omitempty"` - Kind string `yaml:"kind,omitempty"` - Clusters []Cluster `yaml:"clusters,omitempty"` - Contexts []Context `yaml:"contexts,omitempty"` - CurrentContext string `yaml:"current-context,omitempty"` - Preferences map[string]interface{} `yaml:"preferences,omitempty"` - Users []User `yaml:"users,omitempty"` -} - -// Cluster represents a kubeconfig cluster -type Cluster struct { - Name string `yaml:"name,omitempty"` - Cluster ClusterInfo `yaml:"cluster,omitempty"` -} - -// ClusterInfo represents a kubeconfig clusterinfo -type ClusterInfo struct { - Server string `yaml:"server,omitempty"` - CertificateAuthorityData string `yaml:"certificate-authority-data,omitempty"` -} - -// Context represents a kubeconfig context -type Context struct { - Name string `yaml:"name,omitempty"` - Context ContextInfo `yaml:"context,omitempty"` -} - -// ContextInfo represents a kubeconfig contextinfo -type ContextInfo struct { - Cluster string `yaml:"cluster,omitempty"` - Namespace string `yaml:"namespace,omitempty"` - User string `yaml:"user,omitempty"` -} - -// User represents a kubeconfig user -type User struct { - Name string `yaml:"name,omitempty"` - User UserInfo `yaml:"user,omitempty"` -} - -// UserInfo represents a kubeconfig userinfo -type UserInfo struct { - ClientCertificateData string `yaml:"client-certificate-data,omitempty"` - ClientKeyData string `yaml:"client-key-data,omitempty"` -} - -// PrepareMasterKubeConfigs creates the master kubeconfigs -func (c *Config) PrepareMasterKubeConfigs() error { - endpoint := fmt.Sprintf("%s:%d", c.Master.Hostname, c.Master.Port) - endpointName := strings.Replace(endpoint, ".", "-", -1) - - externalEndpoint := fmt.Sprintf("%s:%d", c.ExternalMasterHostname, c.Master.Port) - externalEndpointName := strings.Replace(externalEndpoint, ".", "-", -1) - - localhostEndpoint := fmt.Sprintf("localhost:%d", c.Master.Port) - localhostEndpointName := strings.Replace(localhostEndpoint, ".", "-", -1) - - cacert, err := certAsBytes(c.cas["etc/origin/master/ca"].cert) - if err != nil { - return err - } - admincert, err := certAsBytes(c.Master.certs["etc/origin/master/admin"].cert) - if err != nil { - return err - } - adminkey, err := privateKeyAsBytes(c.Master.certs["etc/origin/master/admin"].key) - if err != nil { - return err - } - mastercert, err := certAsBytes(c.Master.certs["etc/origin/master/openshift-master"].cert) - if err != nil { - return err - } - masterkey, err := privateKeyAsBytes(c.Master.certs["etc/origin/master/openshift-master"].key) - if err != nil { - return err - } - aggregatorcert, err := certAsBytes(c.Master.certs["etc/origin/master/aggregator-front-proxy"].cert) - if err != nil { - return err - } - aggregatorkey, err := privateKeyAsBytes(c.Master.certs["etc/origin/master/aggregator-front-proxy"].key) - if err != nil { - return err - } - - c.Master.kubeconfigs = map[string]KubeConfig{ - "etc/origin/master/admin.kubeconfig": { - APIVersion: "v1", - Kind: "Config", - Clusters: []Cluster{ - { - Name: externalEndpointName, - Cluster: ClusterInfo{ - Server: fmt.Sprintf("https://%s", externalEndpoint), - CertificateAuthorityData: base64.StdEncoding.EncodeToString(cacert), - }, - }, - }, - Contexts: []Context{ - { - Name: fmt.Sprintf("default/%s/system:admin", externalEndpointName), - Context: ContextInfo{ - Cluster: externalEndpointName, - Namespace: "default", - User: fmt.Sprintf("system:admin/%s", externalEndpointName), - }, - }, - }, - CurrentContext: fmt.Sprintf("default/%s/system:admin", externalEndpointName), - Users: []User{ - { - Name: fmt.Sprintf("system:admin/%s", externalEndpointName), - User: UserInfo{ - ClientCertificateData: base64.StdEncoding.EncodeToString(admincert), - ClientKeyData: base64.StdEncoding.EncodeToString(adminkey), - }, - }, - }, - }, - "etc/origin/master/aggregator-front-proxy.kubeconfig": { - APIVersion: "v1", - Kind: "Config", - Clusters: []Cluster{ - { - Name: localhostEndpointName, - Cluster: ClusterInfo{ - Server: fmt.Sprintf("https://%s", localhostEndpoint), - CertificateAuthorityData: base64.StdEncoding.EncodeToString(cacert), - }, - }, - }, - Contexts: []Context{ - { - Name: fmt.Sprintf("default/%s/aggregator-front-proxy", localhostEndpointName), - Context: ContextInfo{ - Cluster: localhostEndpointName, - Namespace: "default", - User: fmt.Sprintf("aggregator-front-proxy/%s", localhostEndpointName), - }, - }, - }, - CurrentContext: fmt.Sprintf("default/%s/aggregator-front-proxy", localhostEndpointName), - Users: []User{ - { - Name: fmt.Sprintf("aggregator-front-proxy/%s", localhostEndpointName), - User: UserInfo{ - ClientCertificateData: base64.StdEncoding.EncodeToString(aggregatorcert), - ClientKeyData: base64.StdEncoding.EncodeToString(aggregatorkey), - }, - }, - }, - }, - "etc/origin/master/openshift-master.kubeconfig": { - APIVersion: "v1", - Kind: "Config", - Clusters: []Cluster{ - { - Name: endpointName, - Cluster: ClusterInfo{ - Server: fmt.Sprintf("https://%s", endpoint), - CertificateAuthorityData: base64.StdEncoding.EncodeToString(cacert), - }, - }, - }, - Contexts: []Context{ - { - Name: fmt.Sprintf("default/%s/system:openshift-master", endpointName), - Context: ContextInfo{ - Cluster: endpointName, - Namespace: "default", - User: fmt.Sprintf("system:openshift-master/%s", endpointName), - }, - }, - }, - CurrentContext: fmt.Sprintf("default/%s/system:openshift-master", endpointName), - Users: []User{ - { - Name: fmt.Sprintf("system:openshift-master/%s", endpointName), - User: UserInfo{ - ClientCertificateData: base64.StdEncoding.EncodeToString(mastercert), - ClientKeyData: base64.StdEncoding.EncodeToString(masterkey), - }, - }, - }, - }, - } - - c.Master.kubeconfigs["etc/origin/node/bootstrap.kubeconfig"] = c.Master.kubeconfigs["etc/origin/master/admin.kubeconfig"] - - return nil -} - -// PrepareBootstrapKubeConfig creates the node bootstrap kubeconfig -func (c *Config) PrepareBootstrapKubeConfig() error { - ep := fmt.Sprintf("%s:%d", c.ExternalMasterHostname, c.Master.Port) - epName := strings.Replace(ep, ".", "-", -1) - - cacert, err := certAsBytes(c.cas["etc/origin/master/ca"].cert) - if err != nil { - return err - } - - bootstrapCert, err := certAsBytes(c.Master.certs["etc/origin/master/node-bootstrapper"].cert) - if err != nil { - return err - } - bootstrapKey, err := privateKeyAsBytes(c.Master.certs["etc/origin/master/node-bootstrapper"].key) - if err != nil { - return err - } - - c.Bootstrap = KubeConfig{ - APIVersion: "v1", - Kind: "Config", - Clusters: []Cluster{ - { - Name: epName, - Cluster: ClusterInfo{ - Server: fmt.Sprintf("https://%s", ep), - CertificateAuthorityData: base64.StdEncoding.EncodeToString(cacert), - }, - }, - }, - Contexts: []Context{ - { - Name: fmt.Sprintf("default/%s/system:serviceaccount:openshift-infra:node-bootstrapper", epName), - Context: ContextInfo{ - Cluster: epName, - Namespace: "default", - User: fmt.Sprintf("system:serviceaccount:openshift-infra:node-bootstrapper/%s", epName), - }, - }, - }, - CurrentContext: fmt.Sprintf("default/%s/system:serviceaccount:openshift-infra:node-bootstrapper", epName), - Users: []User{ - { - Name: fmt.Sprintf("system:serviceaccount:openshift-infra:node-bootstrapper/%s", epName), - User: UserInfo{ - ClientCertificateData: base64.StdEncoding.EncodeToString(bootstrapCert), - ClientKeyData: base64.StdEncoding.EncodeToString(bootstrapKey), - }, - }, - }, - } - - return nil -} - -// WriteMasterKubeConfigs writes the master kubeconfigs -func (c *Config) WriteMasterKubeConfigs(fs filesystem.Writer) error { - for filename, kubeconfig := range c.Master.kubeconfigs { - b, err := yaml.Marshal(&kubeconfig) - if err != nil { - return err - } - err = fs.WriteFile(filename, b, filesystem.Fileinfo{User: "root", Group: "root", Mode: os.FileMode(0600)}) - if err != nil { - return err - } - } - - return nil -} - -// WriteBootstrapKubeConfig writes the node bootstrap kubeconfig -func (c *Config) WriteBootstrapKubeConfig(fs filesystem.Writer) error { - b, err := yaml.Marshal(&c.Bootstrap) - if err != nil { - return err - } - - return fs.WriteFile("etc/origin/node/bootstrap.kubeconfig", b, filesystem.Fileinfo{User: "root", Group: "root", Mode: os.FileMode(0600)}) -} diff --git a/pkg/openshift/certgen/unstable/templates/bindata.go b/pkg/openshift/certgen/unstable/templates/bindata.go deleted file mode 100644 index 619d0ee65a..0000000000 --- a/pkg/openshift/certgen/unstable/templates/bindata.go +++ /dev/null @@ -1,535 +0,0 @@ -// Code generated by go-bindata. DO NOT EDIT. @generated -// sources: -// master/etc/etcd/etcd.conf -// master/etc/origin/master/htpasswd -// master/etc/origin/master/master-config.yaml -// master/etc/origin/master/scheduler.json -// master/etc/origin/master/session-secrets.yaml -// master/tmp/ansible/ansible.sh -// master/tmp/ansible/azure-local-master-inventory.yml -// master/tmp/ansible/azure-ocp-deploy.yml -// master/tmp/bootstrapconfigs/compute-config.yaml -// master/tmp/bootstrapconfigs/infra-config.yaml -// master/tmp/bootstrapconfigs/master-config.yaml -// node/etc/origin/cloudprovider/azure.conf -// node/etc/origin/node/resolv.conf -package templates - -import ( - "bytes" - "compress/gzip" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - "time" -) - -func bindataRead(data []byte, name string) ([]byte, error) { - gz, err := gzip.NewReader(bytes.NewBuffer(data)) - if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) - } - - var buf bytes.Buffer - _, err = io.Copy(&buf, gz) - clErr := gz.Close() - - if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) - } - if clErr != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -type asset struct { - bytes []byte - info os.FileInfo -} - -type bindataFileInfo struct { - name string - size int64 - mode os.FileMode - modTime time.Time -} - -func (fi bindataFileInfo) Name() string { - return fi.name -} -func (fi bindataFileInfo) Size() int64 { - return fi.size -} -func (fi bindataFileInfo) Mode() os.FileMode { - return fi.mode -} -func (fi bindataFileInfo) ModTime() time.Time { - return fi.modTime -} -func (fi bindataFileInfo) IsDir() bool { - return false -} -func (fi bindataFileInfo) Sys() interface{} { - return nil -} - -var _masterEtcEtcdEtcdConf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x54\x5d\x6f\xea\x38\x10\x7d\xcf\xaf\x88\xcc\xcb\xee\xc3\x85\x94\xdb\x8f\xa5\x92\x1f\x8c\x33\x80\x85\x49\x52\xdb\x81\xa2\xaa\xb2\x28\x0d\x34\xda\x14\x50\x12\xba\xad\xba\xfd\xef\x2b\x27\x81\xd0\xc2\xae\x56\xba\xea\x1b\xcc\x1c\xcf\x9c\x39\x73\x26\xa0\xa8\xab\x3d\x32\x02\xfc\xfe\x6e\x37\x47\xb3\x2c\x8f\xd2\xe6\x60\x9d\xe5\xab\xd9\x73\x64\xff\x6d\x67\x4f\x51\x92\xdc\x6c\xd7\x79\x64\x7f\x7c\x58\x05\x9a\x33\xa9\xc0\xd3\x01\x80\xd0\xa1\xe0\xd2\xbc\xdc\xa4\xf1\x2a\xb7\xd1\x53\x9e\x6f\xb2\xeb\x56\x0b\xd9\xbf\xc5\xab\xc7\xe8\x75\x5f\x91\x05\x99\xed\xfc\xde\x94\x79\x1a\xaf\x96\x36\xba\x6e\xff\xfc\xc3\x41\xa7\xcb\xbb\x44\x11\xed\x32\x81\x5b\x2f\xb3\xb4\x95\xc4\x0f\xad\x28\x9f\x3f\xb6\xac\x46\x91\x9d\x10\x5e\x24\x11\xaa\x02\xd2\x23\x81\x1c\xf8\x4a\x53\x3f\xf4\x14\x3e\x73\x1c\xc7\x29\x0b\x0d\x80\x08\xd5\x05\xa2\x34\xf3\x14\x88\x31\xe1\xf8\x62\x97\x03\x0e\x54\x31\xdf\xd3\x8a\x8d\xc0\x0f\x15\x6e\xef\x53\xd5\x78\x94\x33\xf0\xd4\x2f\x0c\x78\xd5\x39\x1e\xb0\xa4\x3c\x22\xb7\x7b\xda\x12\x5f\x1c\x44\x27\x84\xd7\x01\xea\x0b\x89\x2d\xcb\x6a\xdc\xcd\x93\xad\x69\x72\x5f\x12\x64\x1e\x53\x8c\x70\x4d\xdc\x31\x08\xc5\x24\x7c\xdb\x2a\x76\x9d\x28\x0f\xa5\x02\x51\x57\x3f\x32\x0a\xc2\xdf\xd0\x4f\x4b\x45\x14\xe0\x55\xf4\xd7\xe9\xb4\xf2\x87\xe0\x61\xe3\x8e\x1f\x95\x42\x3f\xce\x2a\xed\x5c\x26\xa9\x3f\x06\x31\xc5\x5f\x03\x5a\x8a\xf1\x71\xb0\x47\x38\xef\x12\x3a\xc4\x9b\x74\xfd\xfa\x76\x94\x0e\x84\x7f\x3b\xc5\x25\x8b\x5a\xf6\x6f\xb4\x88\x54\x82\x51\xa5\x05\x50\xdf\xeb\xb1\xbe\xa6\x03\xa0\x43\x8c\x16\xb3\x24\x8b\x76\xce\x27\xa1\xf2\x35\xf5\x47\x01\x29\xad\x2c\x40\x81\x67\x7e\x61\xe4\xec\x30\xe0\x91\x2e\x07\x3d\x6e\x63\x94\xa7\xdb\x08\x95\x23\xdc\x84\xbe\x22\xda\xcc\x0b\x9e\xab\xbb\x53\x05\x12\x9f\xb7\x3b\xe7\x9d\xcb\xab\x76\xe7\xd2\x38\xae\x90\xe1\xbe\x2a\x52\x4e\xbf\x5e\x2c\x0e\xff\xeb\x1e\x61\x3c\x14\xa0\x27\x84\x29\x8c\x2e\x1c\x67\xdf\xb4\xcc\x0b\xe8\x09\x90\x83\xfa\xf8\xd0\x4f\xe7\x08\xe4\x9a\x7d\xee\x6e\x10\x9d\x1d\xe5\x27\x82\x29\xa8\x01\xa7\xba\x10\xb7\xce\x3b\xc8\x90\xcf\xa2\xf9\x36\x8d\xf3\xb7\xea\x5e\x94\x30\x76\x71\x35\x25\xba\xc7\x38\x60\xf3\x3d\x29\xbf\x29\xf3\x59\x73\x9e\xe6\x25\xaa\x5a\x26\x05\xa1\x8c\xb2\x83\x4f\x82\x15\xd1\x2f\x8f\xb3\x28\x7d\x89\xd2\xba\xc0\x10\xa6\xff\x02\xf9\x33\x7a\x3b\x5c\x99\xe2\x72\xbf\xc9\x72\x12\x73\xbe\xff\x8f\x65\x01\xfd\x4f\xaa\x25\xe2\x04\xdf\x4d\x74\xc8\xb6\x80\x9d\xa0\x5c\xa0\x6a\xc2\x05\xec\x88\xb5\xd5\xb8\x4b\xd6\xcb\x65\xbc\x5a\x56\x12\xbb\xd0\x0d\xfb\x18\xf5\x0e\x86\xe2\x7e\x5f\x07\x84\x0e\x49\x1f\x34\x87\x31\x98\xe7\xa6\x43\xa9\x09\x2e\x5e\xa0\xca\x6a\x8b\x38\x29\x6a\x7d\xf2\x6c\x10\x08\xbf\xf7\xc5\xf2\x23\x30\x77\x21\x31\x7a\x98\x65\xf1\x1c\x59\x0d\xab\x71\x37\xdb\xe6\x4f\xf7\xb5\xbe\x83\xea\xb3\x80\xb2\xf8\x79\x93\x44\xc8\xfa\x27\x00\x00\xff\xff\x6b\x4e\x0b\x40\xe2\x06\x00\x00") - -func masterEtcEtcdEtcdConfBytes() ([]byte, error) { - return bindataRead( - _masterEtcEtcdEtcdConf, - "master/etc/etcd/etcd.conf", - ) -} - -func masterEtcEtcdEtcdConf() (*asset, error) { - bytes, err := masterEtcEtcdEtcdConfBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/etc/etcd/etcd.conf", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterEtcOriginMasterHtpasswd = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xaa\xae\x56\xd0\x73\xce\x29\x2d\x2e\x49\x2d\x0a\x2d\x4e\x2d\xca\x4b\xcc\x4d\x55\xa8\xad\xb5\xaa\xae\x56\x70\x4a\x2e\xaa\x2c\x28\x81\xcb\x06\x24\x16\x17\x97\xe7\x17\xa5\x28\xd4\xd6\x72\x01\x02\x00\x00\xff\xff\x48\x7d\x31\x4a\x35\x00\x00\x00") - -func masterEtcOriginMasterHtpasswdBytes() ([]byte, error) { - return bindataRead( - _masterEtcOriginMasterHtpasswd, - "master/etc/origin/master/htpasswd", - ) -} - -func masterEtcOriginMasterHtpasswd() (*asset, error) { - bytes, err := masterEtcOriginMasterHtpasswdBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/etc/origin/master/htpasswd", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterEtcOriginMasterMasterConfigYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x59\x6b\x6f\x1b\xbb\xd1\xfe\xae\x5f\x41\xe8\x4b\x92\x17\xef\xae\x64\x3b\xd7\x05\x8a\x42\xb5\x9d\x13\xe3\xd8\xb1\x2a\x3b\x45\x81\xba\x08\x28\x72\xb4\x62\xc4\x25\x37\xbc\x28\x56\x72\xf2\xdf\x0b\x5e\x76\x97\xbb\x92\x93\x20\x4d\x5b\x27\x40\xbc\xe4\xcc\x70\x38\xf3\x70\x6e\xc1\xb4\x62\x5a\x33\x29\x4e\xa5\x58\xb1\xb2\x18\x21\x54\x73\x5b\xb2\xe4\x1b\xa1\xbf\x58\xc6\xe9\x19\xac\xb0\xe5\x46\x87\x25\x84\x88\x27\xb0\x0a\x1b\x26\x45\xb3\x88\x10\xae\xd9\xdf\x40\x39\x89\x05\xda\x1e\xb5\xcb\x20\xb6\x05\xfa\xc7\x3f\xdb\xef\x0d\x13\xb4\xe8\x0b\x0e\x27\xb6\x14\x0a\xb4\xb4\x8a\x80\xee\x64\x23\xc4\x59\xc5\x8c\x2e\xd0\x97\xaf\xc9\xa2\x82\x8f\x16\x74\xb2\xec\xc5\x5e\x6f\x41\x29\x46\xe1\x27\x15\x4e\x14\x6c\x25\x25\x1a\xce\x25\x9d\x2b\xd0\x60\x7e\x4e\x3a\x65\x1a\x2f\x39\x14\x68\x85\xb9\x86\xc1\xa1\xd1\x20\xb3\xbe\x6b\x3c\x91\xac\x41\xe8\x35\x5b\x99\x9c\xc9\xc9\x45\x85\x4b\x98\x4b\xce\xc8\xee\x27\x9d\x72\x0f\xc4\x3a\xca\x85\xe5\xa9\x9d\x33\x54\x61\x43\xd6\x5e\xfe\x4c\x08\x69\xbc\xb8\x9e\x23\x32\xb4\x81\x5d\x81\x98\x23\xd1\x79\x4f\x2d\x0a\x62\x97\xb5\xa2\x13\x1e\x84\xb6\x98\x5b\x28\xd0\x23\xa3\x2c\x3c\x4a\x76\x04\xae\xa0\xe8\xd4\xc9\x28\x08\x06\x34\x21\x90\x62\x71\x08\x0e\x59\x8b\x92\x02\xd5\x92\xea\x07\xb6\x96\xce\x8b\xba\x87\x98\x0f\x40\x4c\x81\x9c\x1e\xc9\xb2\xde\xb0\xfa\xda\x9f\xc4\xbd\x1e\xaf\x31\xe3\x56\xc1\x80\x2e\x38\x29\x31\x7e\xf4\x0f\x2e\x4b\x05\x25\x36\x52\x25\x6f\x49\xc9\xfb\xdd\x29\x67\x20\xcc\x85\x58\xc9\xa0\x3b\x01\x65\x5e\x33\xe7\xfd\x8e\x25\x5b\x29\x29\x4c\xe6\xe9\x73\xa2\x8c\x27\xdc\xc0\xee\x9b\x74\x1b\xd8\x8d\x70\xcd\x2e\x61\x0b\x5c\x17\xa3\xcc\xf9\x76\xe0\x6a\x6c\xcd\xba\x53\x27\xbe\x94\x37\x80\x29\xa8\xa8\x8c\x57\xee\x74\x56\xa0\x44\x72\x46\x70\xab\x44\x24\x90\x55\x25\xc5\x5b\x5c\x35\x0e\xc8\x1e\x50\x6a\x14\x80\x65\x14\x0e\xa7\xcc\x15\xac\xd8\x7d\xc7\xf5\xf7\x6c\x01\x95\x34\x90\x9d\x3b\x9a\xcc\xaf\x96\x4a\xda\x3a\x90\xef\xd3\xfd\xe6\x36\xfd\xa2\xd5\xa0\x1c\x52\x1e\xa2\x7c\xa7\x41\x8d\x88\x14\x46\x49\xce\x21\xf1\x02\x70\x20\xdd\x83\xe0\x92\x6c\xde\x7a\xc0\xb5\xb0\xcd\x2a\xac\x0d\xa8\xac\x63\x76\x68\xd1\xa0\xb6\x8c\xc0\x8d\xfb\x47\x94\xa7\xa0\xe2\x63\xd7\xac\x14\x8d\xf9\x52\x6f\x46\xfa\x2c\xec\xb7\x06\x4c\xfc\x38\xa0\x70\xfe\x4b\x8e\x2c\xd0\xa3\xff\x7b\x34\x22\x52\xe9\x19\xe7\xf2\x13\xd0\x6b\xc5\x4a\x26\xbc\x67\x1f\xff\x99\x3d\x99\x4c\x8e\x8e\x5f\xdc\xe5\x53\xff\xf7\xe8\x71\xf1\xc7\xdd\xe7\x27\xed\x16\x97\x04\xf3\xb5\xd4\xa6\x5d\xff\xf2\x05\xd5\x8a\x09\x83\xc6\x81\x62\x8c\x1e\xff\xd5\x4a\x03\x57\x60\x30\x7a\xcc\x04\x85\x7b\x94\x5f\xf9\x8b\xe7\x17\x73\x8d\xa6\x4f\xf2\x1b\xa3\x98\x28\x9f\xa0\xb1\x13\x72\xf7\xf9\xc9\x18\xfd\x81\x3e\x3a\x1e\xf4\xf5\x6b\x7b\xd2\xc6\x2e\x41\x09\x30\xa0\xef\x72\x1a\x42\xd5\x40\x97\x03\x14\x77\xb9\xde\x92\xbb\x9c\x70\xeb\xce\xbb\xcb\xbd\xba\x0f\xb2\xfd\xd8\x1d\xf2\xf3\x7b\xe3\x10\xc1\xc3\x25\xde\x48\x6d\x1c\x3c\xbe\xa3\x7e\xeb\xf4\x7d\xed\xbf\x7d\x5a\x34\xd5\x4f\x1f\xe3\x4d\xf0\x83\x96\x1a\x90\x1d\xbd\x38\xbe\xcb\x4f\x0e\x3b\xfe\x81\x83\xbe\x63\xeb\x96\x2b\xae\x53\xa1\xbb\xf7\xb2\x64\x82\xce\x28\x55\xa0\x75\x81\xa6\xb9\xff\x53\xbc\x9c\x3e\x3b\x89\x7b\x6f\xc1\x7c\x92\x6a\x53\x20\x43\xea\xa7\x23\x30\x84\xf6\x43\x1c\xc1\x05\x0a\x2f\x2a\x77\x9b\x5d\x34\xe9\xde\x4a\x6f\xdb\x33\x47\x92\xf6\xad\x1c\xa0\x70\xef\x05\x21\xab\xb8\x7f\xfb\xa9\xbf\xd6\xc6\xd4\xba\x70\x1e\x1b\xba\x09\x8d\x8b\xe3\x93\x17\xaf\x7a\x3e\x72\x32\x6f\x8c\x54\xb8\x84\xee\xd2\x9d\x2b\xe2\x56\x88\x5c\x45\xb2\x91\x33\x79\x88\xb0\x9f\x5a\x9d\x65\x6f\x9c\x65\x07\x62\xd2\x1c\x79\x80\x2c\x15\xe2\xb3\x6a\xa7\xd9\x4a\xaa\x0a\x9b\x02\x5d\xcd\x6e\x6e\xcf\x17\xef\xaf\x17\xe7\xbf\xbd\x7f\xb7\xb8\x1c\x21\xc4\xb1\x01\x6d\x9a\x2a\x82\x0d\x53\x92\x63\x66\x22\xbc\x91\x05\x94\x4c\x1b\xb5\x6b\xec\x52\x20\x2a\xc9\x06\x54\xa6\xe2\x46\x83\x1e\x07\x9e\xe2\xd9\x74\x3a\x1d\x85\x44\x17\xec\x19\x73\x9c\xbb\x3b\x07\xb3\xef\x6e\x82\xb3\xa5\x15\x94\xc3\x43\x9e\x8e\x9c\xdf\x76\xf6\x80\x28\xf8\xbb\x96\xca\x14\xe8\x68\x7a\xfc\x6c\x3a\xea\x6c\x9f\xaa\xe5\x94\xc0\x35\x73\x81\x1a\xd4\x4c\x95\xb6\x02\xd1\x14\xaa\xca\x0a\xc3\x2a\xc8\x48\x52\xcf\x66\x8e\x5a\x4f\x34\x18\xc3\x44\xa9\xf3\xcd\x4b\xe7\xda\xc9\xf6\x08\xf3\x7a\x8d\x8f\xfe\xd4\xa6\x7b\x1d\x7c\x93\x2d\x31\xd9\x80\xa0\x0d\xb7\xc3\xcf\x49\x8f\xa0\x02\xca\x70\x66\x76\x35\x74\x27\xd4\x9c\x11\x5f\x38\x4d\xb6\x82\xe6\x09\x8a\x6a\x25\x8d\x5c\xda\x55\x4c\xaf\xd2\x52\x97\x3a\xb7\xac\xcd\xc9\x19\x1a\xe3\xcf\x56\xc1\x38\xa1\xe8\xeb\x3f\x9e\x80\x21\x13\xe9\xf3\xc3\xc4\x13\x34\x12\x26\x9e\x33\x77\xe4\x8e\xbd\x4b\x2f\x03\xbb\xc4\xe8\xe0\x53\x11\x13\x65\xe6\x1c\x96\xad\x9c\x33\x0e\x1d\x11\xfc\x33\x09\x0f\x79\x7c\x50\xc0\x06\x76\x3f\xc2\xbf\x81\xdd\xf8\xbf\x71\xf1\x2a\xe2\xc3\x0a\x07\x9e\x76\xe1\x62\x5e\xb8\xb0\xf1\xad\xf4\x97\x46\x0a\x87\x3e\x7a\xbe\x65\xbe\x7c\xb8\x65\x15\x48\x6b\x0a\x24\x2c\xe7\xdf\x2f\xee\x22\xa6\x63\x41\x95\xc2\x7e\x1f\xf8\x3d\xa2\x00\x7b\x4d\xd6\x40\x6d\xcf\x71\xcd\xc1\xed\x56\x80\x7f\x90\x74\xc0\xdc\x2d\x5d\xfe\x41\xfb\x4a\x3c\xd6\x1f\xfa\xad\xa4\x30\x97\xca\x2c\xb0\x28\x5d\x3d\xfe\x28\xd9\xbb\xb1\x4b\x01\xce\x66\x2f\x8e\xf3\x13\x1f\xfa\x27\x47\xcf\xdd\xbe\xeb\x02\x88\xe3\x0c\x55\xa0\xeb\xe6\xa2\x91\xbd\xda\x1e\x57\x10\x33\xf2\xef\x2d\xda\x4f\x63\xf9\x28\x44\xa8\xc1\x06\x6d\x19\x26\x04\x6a\xb7\x6d\x40\x98\xdb\x5d\xed\x04\xff\xc0\xd3\xf9\xff\x94\x26\x5e\x0e\xa1\xa5\x55\x2e\x1a\x3e\x9d\x4e\x47\xb1\x19\x6a\xa4\xfe\x90\x50\xcf\xf4\xb1\xd6\x05\x3a\xf6\x12\xf6\x2f\xe3\x7e\x8b\x21\x27\x18\xad\x0d\xea\x97\x52\xd6\x2e\x4a\xfc\x0f\xae\xfb\xfc\xdf\xbe\xee\x89\x97\xb0\x77\x97\xf4\xb6\xc3\x52\xd9\x0b\x0c\x4f\x33\xa2\x60\x6e\x97\x9c\x91\x77\x8b\xcb\xe2\x70\x5e\x3e\x5c\xac\xa1\x71\xd1\xe5\x6c\x07\xc9\xf4\xf5\x89\x50\x67\x74\x41\x3e\xc6\x9c\x58\x7f\x9c\x5e\x9c\x2d\x5c\x62\xc8\x8f\x8e\x5f\x06\x9c\x3e\xdd\xa3\x89\x95\x02\x61\x54\xed\x93\x22\xe4\x0a\xe6\x00\xf8\x4b\x10\xa5\x59\x17\xe8\x55\xe2\xf8\x8b\x79\x72\x52\x94\x14\xcb\xa1\x89\xb3\xd8\x61\xee\xa8\xf5\xdc\x8f\x51\x42\xa3\xa1\x80\xae\xb1\xe9\x8a\xae\x4c\x6e\x75\xa6\x3d\x67\xf7\xf2\xfa\xb7\xea\xbd\x3e\xd9\x6f\xe3\xb0\xd6\x60\x7e\x95\xbd\xc7\x13\x22\x85\x96\x1c\x26\xe3\x7e\xe4\x2b\x15\xf6\x48\x6e\xa3\x6f\x05\x66\x2d\x69\x81\xb0\x35\xae\x82\x61\x14\x84\x61\x66\x37\x8f\x01\x58\x17\xa3\x2f\x5f\x32\xc4\x56\x28\x3f\x17\x78\xc9\x61\x36\x3b\x9b\x59\xb3\x76\x54\x01\x89\x5e\x6c\x16\xbb\xfd\x99\x0b\xd7\x68\x76\x16\xb0\xbb\xc6\x9c\x83\x0f\x46\xdd\x44\x84\xcb\x92\x89\xa4\xf9\xae\x70\x5d\x33\x51\x5e\x45\x35\x08\xc7\xac\xf2\x1b\xfd\x24\xf2\xc0\xb8\x23\x54\x33\xd7\x35\x88\x8b\xb3\x8b\x81\xea\x4d\x2b\x17\x62\xf9\x99\xb7\x68\xee\x15\x0c\xf7\xcf\x67\xb3\xb3\x18\xe8\xcf\xfa\x46\xea\xd8\x6e\x80\x28\x17\x37\x1f\x64\x0d\x04\x87\xd8\x31\xab\x92\xb1\x06\xa3\xe9\x24\x46\xdb\x65\xfb\x55\x2b\x58\x81\x52\x40\xdf\xc5\x4e\x38\x25\xb4\x82\x7d\xb4\xf0\xde\x2d\xb7\xab\x43\x9a\xde\x26\x54\x98\xf1\x74\xd7\x2f\xc4\xef\xa6\xc8\x8e\x06\xb5\x66\x2d\x15\xfb\x0c\x87\xb0\xe6\xdd\x94\x57\x8c\x28\xa9\xe5\xca\x48\xc1\x99\x70\x79\xb8\x72\x28\x4c\x2d\x71\x0b\x02\x7b\x0b\x8e\x27\x1e\xd0\xc7\x93\x56\xee\x78\xdf\x2c\x08\x19\xb9\x01\xf1\x8b\x4f\xf4\x32\x7b\xa7\x39\xcc\x82\xa0\x3d\x6c\x5e\xba\x8e\x09\xd5\x58\xeb\x4f\x52\xd1\x21\x42\x5b\x40\xfe\x5a\x80\xae\x1e\x4a\xe3\x6b\xe3\x35\xa1\x3d\x20\xbf\xb9\x9d\xfb\xc5\x79\x54\xf2\x00\xa4\x63\x76\x9e\xed\x57\xe7\xff\xb1\x88\xdd\x88\xfe\xc5\x42\x35\x0c\x66\xd4\xed\xd2\x15\xbe\x9f\x95\x70\xe3\x52\x11\x75\x99\xac\x49\x86\x71\x3b\x84\x5f\xad\x45\xba\x18\x1e\xa2\x7e\xb8\x6c\x0a\x64\x99\x0e\x74\xf9\x0e\x57\xee\x59\x78\xe8\xa4\x2a\xb8\x64\xae\xf5\xad\x5b\x1e\xa8\xf1\xf2\x79\x53\x83\xb4\x08\x3f\x44\xf6\x6c\x3a\x1d\xd5\xd8\x6a\x07\xd7\x6e\x08\x14\x02\x60\x3d\xe8\xe3\x96\x52\x1a\x6d\x14\xae\x43\x83\xf7\xa0\xf2\x81\xaf\x29\xf8\xda\x8c\x73\x21\x56\x0a\x6b\xa3\x2c\x31\x56\x85\x0a\xae\xc6\xa4\x37\x03\x63\x8e\x24\xe5\xb9\x59\x63\x05\xb4\x1d\xbc\x1e\x62\x1a\xd5\x4a\x7e\x00\x92\xa4\x89\xd8\x45\xba\x3a\xf1\xc6\xcf\xdd\xa4\x2a\x90\x90\x14\x32\x25\x39\xe4\xbd\x66\x7a\x42\x64\x55\x5b\x03\x4d\xc3\x15\x85\x2d\xc2\x94\xf2\x0a\xb4\xc6\x6d\x79\xda\xdf\xbb\x85\xaa\x76\xcd\x6f\x5b\xbb\x12\xab\x98\xd9\xcd\x38\x97\x04\xbb\x23\xc3\x7b\x24\xba\x5d\x89\xa5\xae\x9e\x16\x93\xe3\x66\xf3\x12\x2f\x81\xeb\x39\xa8\x79\x10\x5e\xa0\x67\x61\xd0\xc8\xe8\x90\xef\x68\xda\xfc\x64\x47\xaf\x9a\x9f\x89\x5f\x1d\x29\x69\x5d\x1f\xd9\xd9\x40\xdb\x25\x95\x15\x76\xb1\xe1\xf6\xfc\x6a\xbe\xb8\x7e\x77\x7b\xbe\xb8\x98\xe7\x82\xd5\xae\xf9\x8f\xf9\x7e\x46\x88\xeb\x4e\x3a\x36\xff\x9f\x1b\x01\x9c\x0b\x17\xe8\x41\x10\xd0\x5d\x42\xac\xb0\xc0\x25\xd0\x76\x06\x9b\x35\xb6\xf6\xbf\xfb\x19\xb7\x7f\xf6\x6e\xbd\xe6\x72\xf7\x9d\x18\x50\x2b\xb6\xc5\x06\x7e\x1f\xcc\x26\x71\xd0\xca\x95\x89\x7e\xbf\x69\xc2\x7d\xac\x88\xc4\xf1\xf8\x3d\x0e\x4f\xe3\x19\x74\x98\x99\x36\x6d\x51\x6f\xa0\xd4\x85\x85\x66\xb4\xf4\xad\xa7\xbf\x3f\x6f\x3a\xd0\x63\x69\xdf\xf9\x37\xa3\x87\x76\xa2\xdd\xce\x9d\x86\xed\x56\xa4\x0f\x57\xab\xf0\x7d\x44\x95\xbe\x10\xaf\x39\x2b\xd7\x26\x3c\xcd\x76\x5e\x1e\x1b\xbf\x7e\x94\xd9\x4a\x6e\xab\x64\x4a\x43\x77\x02\x57\x8c\xf8\xf8\xeb\xc2\x07\x13\x65\x28\x83\x68\xcc\x10\xff\x0a\x00\x00\xff\xff\xf1\xb0\xdf\xf1\x6b\x1b\x00\x00") - -func masterEtcOriginMasterMasterConfigYamlBytes() ([]byte, error) { - return bindataRead( - _masterEtcOriginMasterMasterConfigYaml, - "master/etc/origin/master/master-config.yaml", - ) -} - -func masterEtcOriginMasterMasterConfigYaml() (*asset, error) { - bytes, err := masterEtcOriginMasterMasterConfigYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/etc/origin/master/master-config.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterEtcOriginMasterSchedulerJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x55\xc1\x6e\xda\x40\x10\xbd\xf3\x15\x96\xcf\x39\x90\x1e\xb9\x01\x89\xa2\x4a\x0d\x5a\x41\x94\x43\xab\x1c\xb6\xbb\x0f\x18\xb1\xec\xd0\xd9\x35\x2d\x89\xf8\xf7\x6a\xed\xc6\x2d\x90\x2a\xb6\xe5\xf8\x64\xbd\x7d\xef\xed\xee\x8c\xdf\xf8\x65\x90\x65\x59\x96\xeb\x1d\x3d\x42\x02\xb1\xcf\x47\x59\xbe\xbf\xce\xaf\x2a\x7c\x43\xde\x26\x44\xb1\x23\x73\x78\x45\x77\x02\x4b\x46\x47\x84\x7c\x94\x7d\x2b\xb1\xf4\xbc\xd4\x6f\x25\xcb\xeb\x2d\x92\x76\xc6\x8f\xec\x8a\x2d\xbe\xb2\xc7\x94\xfd\xd2\x91\x89\x79\x4d\x3d\x5e\xbd\xa7\xbf\xd7\xbf\x6e\x27\x8b\xca\x63\xca\x85\x6f\x2b\xbe\x9b\xde\xaa\x9b\xee\xf2\xf1\x73\x21\xb8\xa1\xb0\xe9\x6c\x11\xcd\xfa\xb3\x8f\x10\xc5\x76\xbc\x5c\x92\xa7\x78\x68\x63\x30\xe3\xb4\x7b\x97\xca\xdd\xc1\x43\xb4\x53\x7f\xdb\xd5\x42\xac\xd8\x3e\xb0\x83\x24\xdd\x8c\x2d\x1e\x34\xf9\xd8\xca\x61\xba\x86\xd9\x24\xe9\x3d\xb6\x2c\x07\x25\x08\xa1\x10\x74\xb2\x48\x25\xe8\x6c\x50\x75\x6e\x42\xde\x92\x5f\x35\x51\x6b\x59\x15\x5b\xf8\x98\x8f\xce\x56\xca\xd5\x00\xd9\x93\x41\xdd\xcb\xb7\x48\x25\xd1\xe9\xef\x70\xa7\x19\xb9\xe0\x08\x56\x29\x75\x6f\x12\x9e\x2e\xd0\xe3\x09\xf2\xcf\x05\x4e\x2e\x3d\x3f\xf3\xac\x54\x4f\x75\x7a\x89\x85\x22\x35\x4b\xef\x02\x0e\x26\xb2\x2c\x76\x02\x6d\x55\xa5\x7d\x9d\x04\x35\xfb\x27\x68\xb5\x4e\xe5\xba\x6e\xd1\x9b\xf3\x50\xf4\x6a\xfe\x05\x3a\xc4\x39\x7e\x14\x08\x11\xfd\x9e\x7b\xa2\x9d\xf6\x06\x76\x8e\xc0\x85\x18\x8c\x9d\x63\xa3\x63\x2a\x79\x1f\xf6\xe9\x73\x57\x82\x25\x64\xbc\x67\xb2\x8a\x6d\x78\xff\xf8\xc3\xe1\x70\xd8\x72\x8f\x0f\x29\x7b\x39\x25\xfe\xcc\x0d\x62\xdf\x8b\x77\xb3\x34\xfa\x48\x0d\x13\x99\xce\xf9\xcc\x1e\x97\xa1\x6b\x16\xaf\xf4\x23\xfb\xef\x85\x3e\x9d\xa7\x6e\x70\x1c\xfc\x0e\x00\x00\xff\xff\xaa\x29\xaf\x2a\x65\x07\x00\x00") - -func masterEtcOriginMasterSchedulerJsonBytes() ([]byte, error) { - return bindataRead( - _masterEtcOriginMasterSchedulerJson, - "master/etc/origin/master/scheduler.json", - ) -} - -func masterEtcOriginMasterSchedulerJson() (*asset, error) { - bytes, err := masterEtcOriginMasterSchedulerJsonBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/etc/origin/master/scheduler.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterEtcOriginMasterSessionSecretsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\x2c\xc8\x0c\x4b\x2d\x2a\xce\xcc\xcf\xb3\x52\x28\x33\xe4\xca\xce\xcc\x4b\xb1\x52\x08\x4e\x2d\x06\x89\x04\xa7\x26\x17\xa5\x96\x14\x73\x15\x43\x68\x2b\x2e\x5d\x85\xc4\xd2\x92\x8c\xd4\xbc\x92\xcc\xe4\xc4\x12\xb0\x96\xea\x6a\x05\x3d\xc7\xd2\x92\x0c\x88\x52\x85\x1a\x85\xc2\xd2\xfc\x92\x54\x85\xda\x5a\x2e\x05\x85\xd4\xbc\xe4\xa2\xca\x02\x84\x3a\xd7\xbc\x64\x4c\x65\x80\x00\x00\x00\xff\xff\xc1\xc1\xc9\xa5\x80\x00\x00\x00") - -func masterEtcOriginMasterSessionSecretsYamlBytes() ([]byte, error) { - return bindataRead( - _masterEtcOriginMasterSessionSecretsYaml, - "master/etc/origin/master/session-secrets.yaml", - ) -} - -func masterEtcOriginMasterSessionSecretsYaml() (*asset, error) { - bytes, err := masterEtcOriginMasterSessionSecretsYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/etc/origin/master/session-secrets.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterTmpAnsibleAnsibleSh = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x53\xd1\x6e\xdc\x36\x10\x7c\xd7\x57\x4c\xee\x8a\xa6\x05\x2c\x29\xe7\x22\x0e\x70\x45\x53\xa4\x88\x8b\x06\x48\xea\xa2\xf1\x43\x1f\x0a\x18\x14\xb9\x77\x62\x4d\x71\x89\xdd\xd5\x5d\xd4\xc0\xff\x5e\x48\x3e\x3b\x45\xfd\x54\xe9\x85\xa2\x66\x67\x77\x86\xc3\xf5\xb3\xb6\x8b\xb9\xed\x9c\xf6\xa8\xe9\x53\x55\xad\x71\x7d\xf5\xf6\x6a\x8b\xc0\xb0\x3e\xea\x19\x5c\x0e\x18\x58\x08\xdf\x08\xed\xa3\x9a\x4c\xf0\x9c\x95\x13\x9d\xc1\x69\xf7\xed\x19\xac\x27\x14\xe1\x42\x82\xa3\x9b\x66\x8a\x23\x61\x4f\x86\x55\x88\x2e\xc1\x7c\xd9\x22\x31\xdf\x8e\x05\x3b\xe6\x86\x9c\xda\xa8\x8d\x4f\x3c\x06\x57\x4a\xe3\xfe\x1e\x85\x1a\xcf\x03\x38\x63\xf3\xa2\x99\xdf\xcd\x66\xfb\xf2\xbb\x2d\x84\x5c\xa8\xd6\x18\x43\xc1\xe6\xd5\x79\xb3\x79\xd5\xbc\x68\xce\xb7\x2f\x2f\x2e\x2e\xce\xeb\xd7\x4f\xa1\x5b\x64\x86\xf0\x68\x04\x63\xf4\xac\x06\x12\x61\xd1\x15\x9c\x55\x6b\xa8\x39\xb1\x7a\x2c\x5b\x1c\x5d\x34\x8c\xd9\x62\x9a\xa7\x57\x82\x8e\x9d\xc6\x40\x4d\x75\xec\x63\x22\x3c\x03\x7b\x1c\x48\x34\x72\xc6\xd7\xaf\xdb\x40\x87\x36\x8f\x29\x7d\x8f\xc0\x15\xa0\x89\xa8\x60\x53\x05\xce\x54\x55\x3b\x96\x59\xff\x5f\xe4\x0d\x31\x23\xd0\xce\x8d\xc9\xc0\x85\xb2\xf6\x71\x67\x75\xcc\x3b\x71\xa7\x52\xf6\x28\xce\x7c\xff\x58\xf1\xd5\xc3\xa2\x2e\x78\xfe\x79\x35\x90\xb9\xe0\xcc\xad\xb6\x9f\x57\x2e\x67\x36\x67\x91\xb3\xce\x9f\x8f\x84\x4d\xe4\x36\x73\xa0\x5a\x29\x91\x37\x96\xd5\x16\xab\xd5\xdd\xdd\xdd\xf3\xd3\x44\x6b\xfc\xfc\xee\x8f\x0f\x97\xa8\x71\xdd\x47\x85\xf6\x3c\xa6\x80\x8e\xd0\xbb\x1c\x12\x05\x74\xd3\x72\x6a\x5f\x46\x74\x59\x63\x97\x08\x25\xb9\xa9\x63\xbe\xd5\xd9\x41\xca\x3a\x0a\x55\x6b\x3c\x3c\x0e\x21\xca\xd2\x71\x42\x34\x64\xa2\xb0\x00\x8f\x12\xef\x3d\xa7\x4f\x51\x4d\xd1\xd1\x6e\x4e\x8c\x33\xa3\xa1\x58\xcc\xfb\x47\xd0\xbf\xc8\x8c\x11\xad\x1a\x6e\x43\x94\x59\x7b\x4b\xe6\x5b\x96\xb8\x8f\xb9\x1d\x9c\x1a\x49\x9b\xdd\x40\xe1\xc6\x93\x58\xdc\x45\xef\x8c\x74\x96\xf6\x96\x4a\xe2\x09\x2e\x25\x2c\xc6\xc2\xf3\x50\x38\x53\x36\x85\xd0\xa8\x73\x3b\xa1\x44\x07\x97\x0d\xc5\x89\x29\x76\x32\xa7\xeb\xbf\x62\xab\x37\xbf\x7e\x7c\xf7\xd3\xfb\xcb\x9b\xdf\xaf\xde\x5f\x7e\xbc\xf9\xed\xcd\xf5\x2f\x3f\xb4\xa3\x4a\xab\xbd\x13\x6a\x4f\xa8\xf6\x49\x5d\x2b\x9c\x48\x5b\xfc\x59\x01\xa7\xad\xfa\xc1\xb7\x79\xaf\xfe\x80\xff\x41\x93\x62\x77\x33\x5a\x4c\xcb\x4a\x9c\x4c\x0b\x6f\xed\x91\xd8\xbb\x84\xe5\x76\xd4\xec\x4b\x1d\x16\xdd\xcd\x34\xa4\x7b\x44\x3c\xfd\x5b\x70\xf5\xbd\x65\x75\xcc\x07\xca\xf3\xf9\xcc\xb8\x2f\xb7\xb9\xb0\xce\x3d\xa7\xfb\xe0\xf7\x24\x84\x39\xb5\x9e\xf3\x81\x64\x4f\xd9\xd3\x8f\xd5\x3f\x01\x00\x00\xff\xff\x19\x22\x4a\x18\x0b\x04\x00\x00") - -func masterTmpAnsibleAnsibleShBytes() ([]byte, error) { - return bindataRead( - _masterTmpAnsibleAnsibleSh, - "master/tmp/ansible/ansible.sh", - ) -} - -func masterTmpAnsibleAnsibleSh() (*asset, error) { - bytes, err := masterTmpAnsibleAnsibleShBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/tmp/ansible/ansible.sh", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterTmpAnsibleAzureLocalMasterInventoryYml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x9c\x57\x6d\x6f\xdb\x38\x12\xfe\xee\x5f\x31\x50\x0f\xf0\x1d\x50\xdb\x68\xbb\xc0\xdd\x0a\xe8\x07\x6f\x56\x6d\x82\x6d\x62\xc3\x76\x0e\xed\x2d\x16\x5a\x4a\x1a\x59\xbc\xd0\x1c\x95\xa4\xec\x78\x73\xf9\xef\x87\x11\x29\xc7\x51\xe2\x36\x68\x3e\x45\xe6\xbc\x3c\x9c\x79\xe6\x85\xa3\xd1\x68\xf0\x0a\x3e\x5c\x7c\xbe\x4c\x62\x98\xea\xbd\xab\xa4\x5e\x43\x86\x8a\x76\x20\x35\x08\xa5\x46\xb9\xa8\x2d\x54\xc2\x82\x74\x43\x0b\x5b\xa1\x1a\x04\x83\xb5\x12\x39\x16\x90\xed\xc1\x62\xc1\xa2\xae\xc2\xc1\x2b\x08\x7f\x54\xa3\xb6\x95\x2c\xdd\x46\x58\x87\xc6\xe6\x46\xd6\x6e\x6c\x2b\xd8\x55\x32\xaf\x40\x5a\xd0\xe4\x40\x16\x28\xd4\x6b\xd8\x21\xd8\x8a\x1a\x55\x40\x29\x6f\xc1\x55\xc2\x8d\x07\x8a\x72\xa1\xbc\x72\x3c\x00\xa8\xc8\x3a\xcb\xff\x00\xb4\x27\xfc\x3d\x00\xd8\x0a\x13\x7e\x15\xda\xca\x4c\x61\x9a\x93\xd6\x98\x3b\x49\x3a\xf6\x92\x8f\x4e\xeb\xbd\xab\x48\xa7\x52\x3b\x34\xb5\x41\x36\x0e\x93\xc6\x9a\x49\x26\xf5\xc4\x1f\xbe\x1d\x0c\x1e\x5d\x20\x95\x96\x8d\x3a\x21\x35\x1a\xf9\x17\x16\x31\x7c\x10\xca\x62\x4f\x2a\x57\x12\xb5\x4b\x33\xa9\x85\xd9\x1f\x19\xa5\xfc\x89\xbd\x8d\x58\x63\xea\xc4\x3a\x86\x68\xfb\xef\x64\xb1\xbc\x98\x5d\x45\x7d\xa1\x1d\x66\xec\xd5\x92\xc2\xa0\xa0\xc5\x06\x63\x88\x2e\x2e\xa7\x1f\x93\x74\xbe\x48\x3e\x5c\x7c\x9e\xf8\x8f\xd5\x97\x79\x32\xda\x61\x36\x0a\x0a\x71\xdf\xaa\xc1\x75\xda\x18\x15\xc3\xf0\x72\xba\x5c\x25\x8b\x74\xb6\x48\x3e\xa6\xd7\x8b\x4f\xc3\x9e\x57\x1f\xef\xb4\xc0\x52\x34\xca\xa5\xb6\xc9\x0a\xda\x08\xa9\x63\x18\xae\x92\xcb\xf9\x62\x76\xbd\x4a\x16\x17\xf3\xb1\x96\xf5\x58\xd2\xd0\x9b\x0f\xec\x09\xff\xaf\x2a\x69\xbb\x6c\x66\x08\x6e\x5f\xe3\x7b\xa9\x4b\x23\x5e\x43\xd6\x38\x4e\x75\x25\xb6\x08\x8e\x40\xc9\x2d\xc2\x4e\xba\x0a\x0c\xae\x25\x69\x2f\x06\x25\x19\xd0\xb4\x0b\xe6\x32\xcc\x45\x63\x11\xa8\x04\x85\x6b\x91\xef\xc1\xa0\xb0\xa4\x6d\x0f\xb9\xa1\x86\x91\x5b\x54\x98\x3b\x32\x31\x0c\x8f\x8d\xf6\xef\xc9\x67\xd6\x99\xfd\xb7\xe5\x5f\xc1\x15\xb5\x14\x85\x5d\xb5\x07\xc7\x17\x93\x16\x04\x14\xb2\x2c\xd1\xa0\x76\x50\x08\x27\xda\x2b\xfa\xcb\x49\x07\xb2\x0f\xac\x36\xb4\x41\x57\x61\x63\x53\x4d\x05\x1e\x79\xbc\x0b\x2e\x87\x31\x0c\xbd\xd7\xfb\x2e\xa0\x4b\x74\x30\xfd\xab\x31\x08\xb6\xc6\x5c\x96\x32\xf7\xae\x38\x36\xcc\x7c\x2c\xa0\xbb\x42\xcf\x9d\x3f\x3d\xba\xa0\x23\xc3\xec\xa9\x0d\x6d\x65\xc1\x74\x8f\x04\x1b\x4e\x33\x45\x59\xf4\x42\xe5\x1b\xa9\x8b\x18\x22\xca\xfe\x8b\xb9\x7b\xa9\xd2\x83\x9b\x54\xe4\x39\x35\xda\x79\x06\x0f\x17\xc9\xc7\x8b\xe5\x6a\xf1\x25\x5d\xae\x66\x0b\xe6\xef\xf4\x3f\xd7\x8b\x24\x9d\x9e\x9d\xcd\xae\xaf\x56\x57\xd3\xcb\xa4\x9f\xae\x97\xbb\xb8\xc1\xfd\x77\x3d\xfc\x96\x7c\xf9\x01\x07\x87\x16\x10\x43\xd4\xc9\xfd\x40\x28\x0c\x0a\xb5\x89\x21\xca\xc9\xe0\x78\x27\x75\x41\x3b\x3b\xd6\xe8\xa2\x67\x6a\x29\xfc\x72\x2e\x4c\x01\x39\x15\xe8\x29\x18\xea\x63\xfc\x48\xe6\xac\x31\x4c\x48\xc5\x34\x45\xc8\x55\xc3\x75\x0c\xd6\x09\x87\x20\x1c\x14\x58\x2b\xda\x6f\x98\xb2\x4e\x6e\x10\x0a\x42\xdf\x80\x7d\x2d\x56\x08\xcc\x4d\x1b\x8c\x79\xfc\x68\xb0\xe0\x32\xe5\x53\xdf\x17\x7c\xb1\x2a\x91\xa1\xb2\x20\xea\x5a\x49\x2c\x40\x68\xe6\xa2\x28\xf6\x2c\x9b\x21\x7c\x6d\xd0\x48\x2c\x82\x29\xb1\x16\x52\x5b\xc7\x18\xd8\x4e\x4d\x52\xbb\x76\x56\x30\x0a\x3f\x33\x02\xb8\xb6\xed\x7b\x21\x25\xf6\x19\xd1\x8d\x05\xd3\xe8\x31\x4c\x95\xa5\xd7\xc1\x1c\x1f\xfb\x4a\x6f\x07\x90\xcc\x05\xb4\x69\x87\xd0\xb1\x20\x2a\x85\x52\x16\x32\x91\xdf\x44\x0c\xe8\x0d\xe3\x34\x54\x1b\x29\x1c\xaa\x3d\xec\x2a\x34\x08\xc2\x1e\xdb\x0b\xd9\x3a\x58\x54\xb4\xe6\x7a\x0b\x21\x1a\xc3\xaa\xd5\xd9\x09\x0b\x42\x59\x82\x42\xda\xbc\xb1\x56\x92\x06\x91\x11\x57\x7d\x19\xac\xb5\xe3\xf1\xc8\x1f\x03\x28\xc8\x67\x2d\xf4\xb9\xd6\x83\x85\xf7\xef\xc1\x37\xbb\x36\xec\x87\x26\xc7\x06\x82\xad\x1a\x4d\x89\x39\x27\xb4\x44\xd1\xce\x2e\xb6\xd6\xa6\x4b\xe8\x23\xe5\x70\xff\x4a\xae\x2b\x34\x1c\xc3\x2e\xa6\x56\x9a\x43\x16\x3a\xbf\x8f\x39\xb3\xc0\xad\xb4\xd2\x81\x12\x1c\xcf\xbf\xd7\x64\xd9\xcf\x9e\x1b\x9c\xc0\x0d\x69\x8b\x0e\xc8\xc0\xdf\xc8\x55\x68\xfe\x71\x82\xea\xbe\xed\x76\x0e\x62\x78\xf3\x9d\x92\x38\x96\x3c\xdd\x29\x5b\xe2\xc6\x10\xd5\x06\x2d\xea\x27\x2d\xa7\xdf\x53\xf1\xb6\x26\xc3\x38\xfc\xa4\xdc\xa2\xb1\xed\xfc\x1f\xce\x17\xb3\xcb\x64\x75\x9e\x5c\x2f\xd3\xe4\xf3\x7c\xb6\xe0\xd9\x17\x66\xe3\xf0\x9b\x13\x57\x5b\x27\x94\x8a\x61\x65\x1a\xfc\x06\x4e\xef\xaf\x36\x58\xca\xdb\xfe\x6c\xee\x83\x7e\xa8\xc1\x94\x27\x46\x0c\xc3\xe9\xd5\xf2\xe2\x97\x4f\x49\xfa\x6b\x32\xff\x34\xfb\xd2\x8e\xf1\x80\xaa\x5b\x57\x2c\x9a\xad\xcc\x31\xcd\x0c\xdd\xf0\xf5\x1e\xc1\xfa\x96\x20\xe3\x8a\x01\xee\xee\xfe\x8c\xee\xee\x40\xa5\xc2\x66\x87\xa9\xde\x1e\xda\xb4\x90\xb9\xfb\xfd\x24\xbc\x3f\x40\x96\xa7\xc1\x33\x81\x87\x64\xe4\x5a\xea\x21\xa0\xb2\x18\x5c\xf8\x78\x34\x46\xc1\xfd\x7d\xf4\xe7\xfd\x7d\x2f\x04\x1d\xca\x5c\x38\xa1\x68\xdd\xc1\x3c\xb9\xd3\x04\xf9\x51\x90\x3f\xda\x6b\x9e\x5d\x5b\xd0\xe5\x05\x3b\xb7\x31\xfc\x1e\x55\xce\xd5\x36\x9e\x4c\xce\x67\xcb\x76\xa6\xc4\x6f\xdf\xfd\xf3\xe7\xe8\x0f\x1f\x5f\x87\x9b\x9a\x69\x7f\x22\x6e\x27\x01\x75\x7a\x07\x64\x5e\xaf\xbf\x70\xbd\x82\xab\xd9\x2a\x89\xfd\x2e\x24\x2d\x18\x2c\x1a\x5d\x08\xed\xfc\x9a\x60\xf0\x6b\x23\x43\x77\xad\x84\x2e\x14\x42\xa0\x2c\xd8\x1b\xdc\x41\x86\x6e\x87\xa8\x83\xa9\xde\x3e\x3d\x0a\x29\xe7\xee\x39\x6b\x33\xd0\xb6\xe0\xd9\xd9\xbc\x17\x14\xbc\x15\x9b\x5a\xa1\x5f\x5e\x39\x71\x87\xb2\x88\xb6\xcb\xf3\xd9\x62\xc5\x95\xf0\x64\xef\xcc\x29\xbf\xa9\x65\x97\x70\x34\x0f\xe4\x3e\x9b\x9d\xfd\x36\xbf\x58\x9d\xa2\xf7\x13\xc5\x4c\x58\x0c\x3b\x6b\xa7\xfa\xcb\x74\x99\x70\x2e\xbe\xab\xfb\x00\xb5\x53\x7d\x3e\xc0\xbf\x52\x3b\xc5\x0a\x2c\xa5\xc6\xef\x76\x27\xb0\xf4\x30\x65\x9c\xb0\x37\x50\x4a\x85\x5d\x8f\x6c\x65\xc7\xfb\x8d\x02\xa9\xad\x2c\xfc\x58\xec\x9b\x04\x43\x0a\xa1\x34\xb4\x79\x26\x23\x3b\xa9\x54\x37\xf7\x1a\x47\x35\xd5\x0d\x93\x85\xd7\xc2\xc6\xf2\xab\xea\x39\x8b\xfd\xcd\xb5\xcd\x26\x0f\xd1\xbd\xd4\xeb\xa3\x31\xa5\x9b\x4d\x86\x86\xf7\xe0\xa3\xc9\xd1\xa7\x1b\xf2\x83\x48\x8a\x4c\xb5\x43\x85\x9f\x70\xc2\x30\x53\x1c\x1a\x2d\x14\xf3\xed\x29\x6a\xf6\xb7\xc3\xa1\xc1\x47\x7c\xf3\xfb\x62\x00\xbd\x81\x76\x04\x3a\x02\xb1\x25\x59\xb4\x78\xa4\xce\x79\xe7\xe0\xcd\xc4\x3a\x86\x55\x8a\xdc\x41\x29\x75\xd1\xe1\x3e\xb8\xf2\x0f\x34\x80\x9c\x36\x1b\xd2\xdd\x17\x7f\xeb\x52\xae\x5b\xa2\xc4\x30\x41\x97\x4f\x7c\x4b\x99\x1c\x24\x5e\xc8\x61\x2f\xfc\xf0\x58\x0c\x57\x68\x32\x25\xf3\x43\x4f\x6f\x1f\x40\x77\x77\x50\x1b\xde\x41\x0e\xfd\x21\x82\x71\x72\xeb\xe3\x73\xd9\x1a\x38\x27\xdb\x6e\xaa\x10\xc5\xff\xfa\xe9\xa7\x77\x93\xa0\x1f\xc1\xff\xe0\x6b\x43\x0e\x21\xb4\xb5\x23\x17\xa2\x96\x3f\x6a\xfe\x59\xb3\x2f\x69\x64\xf0\x2a\xbc\xd9\xaf\x08\x14\xe9\x35\x1a\xd0\x88\x05\x6f\x64\x96\xd3\xf1\x24\xd1\xa3\x77\xe3\x9f\xc7\x6f\xdf\x8e\xde\x84\x77\xd8\xd0\x60\x5b\x3c\xa4\x7d\x51\x74\x2d\x68\x8f\x2e\x00\x61\x8a\x3d\x84\x93\xbf\xc2\x06\xdf\x41\x19\x0e\x06\x44\xa1\xfb\xda\xd4\x51\xea\x33\x7a\xf2\xbd\xfe\xff\x00\x00\x00\xff\xff\x7f\xf9\xc0\x98\x6c\x10\x00\x00") - -func masterTmpAnsibleAzureLocalMasterInventoryYmlBytes() ([]byte, error) { - return bindataRead( - _masterTmpAnsibleAzureLocalMasterInventoryYml, - "master/tmp/ansible/azure-local-master-inventory.yml", - ) -} - -func masterTmpAnsibleAzureLocalMasterInventoryYml() (*asset, error) { - bytes, err := masterTmpAnsibleAzureLocalMasterInventoryYmlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/tmp/ansible/azure-local-master-inventory.yml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterTmpAnsibleAzureOcpDeployYml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x96\x41\x8b\x23\x37\x10\x85\xef\xfe\x15\x8f\xdd\xc3\x5c\xe2\x99\x59\x72\x33\x24\xa7\x24\xb0\x87\x90\x43\x72\x08\x84\xd0\xa8\xd5\x65\xb7\xb0\x5a\x25\x54\xa5\x71\x0c\xfb\xe3\x83\xd4\xed\xf6\xcc\x60\x8f\xdd\xe4\x90\x9b\x51\xab\x5e\x7d\x55\x7a\x2a\x79\x8d\x60\x06\xda\xe0\x27\x8a\x9e\x8f\xf8\x2d\x52\xf8\xbd\x77\x5b\x85\x0b\xdb\x64\x44\x53\xb6\x9a\x13\xe1\xc0\x69\xef\xd9\x74\x2b\xa0\x67\x51\xd9\xc0\xb3\x35\x7e\x30\xa2\x94\x56\xc0\xce\x68\x4f\xa9\xd9\x1a\x5b\xbe\x6d\x8d\x17\x5a\xad\x80\xcf\x38\x10\x02\x51\x87\x17\x93\x9c\x69\x3d\x09\xb6\x89\x07\x70\xa4\x20\x25\xd1\x18\x02\x65\xb4\x04\x17\x20\x96\x23\xad\x80\xc4\x9e\x64\xb3\x02\x80\xf5\xfb\xdd\x45\x39\xb2\x68\xa3\x46\xf6\xf3\xa6\xb1\x90\x36\xb9\xb0\x43\x8e\xd0\x9e\x20\x5d\xa8\x1f\x01\x37\x44\x4e\xda\x14\xd5\xcd\xb4\x84\x29\xe2\x2c\x5e\xb6\xbf\x11\x13\xd2\x1c\x61\x39\x6c\xdd\x0e\x72\x0c\x16\x9d\xa1\x81\x83\x90\x2e\xd1\x0d\xdc\x51\xb3\x4b\x9c\xe3\xbc\xa5\x92\x37\xa5\x15\x9b\x2a\xfc\x36\xef\xd7\xaa\xfa\x4a\xa1\x65\x56\xd1\x64\x62\x63\xb2\xb2\x89\x31\xf1\x0b\xa5\xda\xa4\x77\xfd\x5c\x9b\x20\xae\xf5\x54\x3a\xda\x8d\x87\x5a\xd2\x63\x56\x40\x51\xc0\x49\x62\x49\x19\x97\x21\x2e\x92\x9b\xd0\x21\x0b\x21\x71\x56\x4a\xb5\x5a\x6c\xdd\x75\xd8\x73\x92\xe2\x2e\xea\x6a\x65\x4b\xd8\xc6\xb0\x8b\xed\x1d\x19\x1e\x8f\x83\xff\x18\x95\x76\x4e\x34\x1d\xff\x67\xd8\x89\xe2\x2a\xee\x59\xe5\x40\x6d\x63\x39\x48\xf1\xc0\x7d\x46\x38\x50\x8b\x29\x62\x09\xee\xab\x44\x23\xd2\x67\xfc\xf2\xf5\xcf\x5f\x7f\xc6\x1a\x7f\xf4\x94\xe8\x41\x60\x90\x8c\xa5\x22\xde\x39\x75\x1c\x70\x28\x1f\xea\x1d\xac\x83\x04\xde\xb4\xe4\xe1\x24\x3c\x68\xf1\x9e\x77\xd4\x41\x79\x52\x9b\x1b\x31\x6f\xaf\x96\xed\x72\xbd\xcb\xd6\xe7\x32\x64\xce\x37\xdb\x85\x77\x71\xb7\x2c\xfa\x1d\xb4\x77\x02\x27\x88\x89\x5b\x4f\x83\x51\x67\xd1\x92\x35\xe5\xe0\xb5\xa7\xab\x7a\x31\xf1\x40\xda\x53\x96\xb1\xc5\xb6\x27\xbb\xaf\xd3\x8a\x82\xe4\xb1\xc2\x44\x45\x79\x62\x3e\x38\xed\xaf\x56\x25\xe4\xc9\x2a\x27\xe4\xf8\x64\x5e\x8c\xf3\x65\x20\x3e\x89\xed\xa9\xcb\xf5\xf7\xe3\x74\xe2\xd2\x93\xf7\x1b\x3c\x3c\x65\x49\x4f\xad\x0b\x4f\x6c\xb1\x23\xad\x29\x04\x6b\x8f\x4f\xc5\x27\x1c\x7e\xa8\xba\x9f\xf0\x0d\x07\x8b\xb5\x7f\x98\x8e\x70\x34\x11\xa5\x62\x27\xc9\xfe\x34\xab\x72\x50\xe7\x4f\x6b\x8f\xa2\x1d\x67\x6d\xbc\x0b\x24\x7f\x3d\xff\xfd\xcd\x05\xc5\x8f\xf8\x32\x4b\x68\x72\x24\x1b\x7c\xff\x3c\xad\x74\xe4\xcd\x71\x83\x2f\xcf\xab\x1b\xbe\x7c\xdf\xb3\x9b\xb6\x3c\x07\x2c\x71\xe5\xab\xa8\x8f\x79\x84\xd2\x8b\xb3\xd4\x58\xa3\xc6\xf3\xee\x4e\xa8\xfa\x7c\x8c\x91\x98\x22\x17\x3d\x25\x6f\x93\x5e\x99\x3c\x35\xe9\xbc\xb7\x4d\xbc\xbf\x7b\xa8\x17\xbe\xd3\xea\x89\x73\x14\xb8\x8d\x79\x39\xf1\x45\x46\xa5\x21\x7a\xa3\xff\x01\xf2\xa4\xb0\x98\xf2\x4a\xea\x1b\xa7\x4d\xff\x98\x21\x96\xbf\x19\xf7\x13\x9e\x42\x96\x9c\xef\x1c\xf3\x31\xcd\x38\xe9\x9b\x53\x29\x4b\xa8\xa6\xb7\x65\x0e\x5d\xfe\xc0\x9c\xd3\x5e\xa4\xb4\x6c\xf7\xd1\x69\x93\xdd\x02\xaa\xf9\x95\xbc\xfb\x1d\x99\xd2\xac\xb3\x5b\xfd\x1b\x00\x00\xff\xff\x41\xe4\xce\x7e\x6d\x0a\x00\x00") - -func masterTmpAnsibleAzureOcpDeployYmlBytes() ([]byte, error) { - return bindataRead( - _masterTmpAnsibleAzureOcpDeployYml, - "master/tmp/ansible/azure-ocp-deploy.yml", - ) -} - -func masterTmpAnsibleAzureOcpDeployYml() (*asset, error) { - bytes, err := masterTmpAnsibleAzureOcpDeployYmlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/tmp/ansible/azure-ocp-deploy.yml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterTmpBootstrapconfigsComputeConfigYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x54\x4d\x73\x1b\x37\x0c\xbd\xf3\x57\x60\x94\x43\x2e\xd9\x0f\x39\x49\x33\xb3\x33\x39\xb8\x71\x92\x66\xda\xd8\xae\xe4\xf6\x9a\xa1\x48\x48\xcb\x9a\x4b\xb0\x20\xb8\x8e\xfb\xeb\x3b\xdc\x5d\x5b\x72\x93\xce\xb4\x27\x69\x89\x87\x87\xc7\x47\x00\xda\x7b\xba\xbb\x70\x49\xef\x3c\xda\x0b\x32\xb7\xc8\x1d\xec\xb5\x4f\xa8\x74\x74\xbf\x23\x27\x47\xa1\x83\x71\xad\x6c\x48\x3f\xba\x60\xcf\xad\x65\x4c\xa9\x83\xf5\xd9\x9b\xba\xad\xdb\x7a\xdd\xbd\x7e\x59\x82\x1b\x34\x99\x93\x1b\x71\x83\x89\xfc\xf8\x8e\xc2\xbe\x83\x06\xc5\x34\xc4\xee\xe0\x42\x13\xc8\x62\xc3\x53\xb0\x36\x14\xf6\x25\xe9\x82\x06\xed\x42\x07\xc6\xe7\x24\xc8\xb5\x27\xa3\x7d\x09\x7c\xba\xee\x60\xfd\xe6\xac\x5e\x97\x22\x6b\x65\x27\x65\x85\xd3\x1d\x3a\x05\x30\x7f\x6f\x7b\x37\x6c\x88\xe4\xc2\x31\x1a\x21\xbe\xef\xa0\x19\x35\x37\xde\xed\x9a\x19\x91\x7a\x37\x3c\x81\x6f\xcb\x3f\x59\x70\x9c\xc3\x09\xae\x4e\x64\x6e\x15\x00\x7e\x45\xf3\x93\x0e\xd6\x23\x5f\xea\x01\x3b\x08\x5a\xdc\x88\xca\x45\x29\x2e\xa5\xed\x7d\x30\xd7\xc8\x8e\x6c\x07\xab\x97\x6d\x5a\x29\x37\xe8\x03\x1e\xc5\xed\x89\x07\x2d\x1d\x7c\x3e\xdf\xde\xbc\xdf\x7c\xb9\xda\xbc\xff\xf8\xe5\xb7\xcd\x2f\x0a\xc0\x6b\xc1\x24\x1d\x7c\x98\x0c\xbe\x75\xc1\x76\x70\x49\x76\xc9\x55\xb7\x79\x87\x1e\xe5\x9c\x0f\x79\xc0\x20\xa9\x90\x45\xb2\xd5\xa0\x83\xdb\x63\x92\x2a\x6a\xe9\xcb\x61\xf5\xad\xb1\x91\x6c\x52\x00\x3b\x22\x49\xc2\x3a\x56\x85\xcc\x3c\x6a\xfa\x4e\xc6\x23\xb4\x3e\x42\x8b\x7a\xd4\x92\x19\xab\x43\xd1\x3a\xa7\x6e\x48\xb4\xe0\xcf\xb3\xba\x77\xde\x61\x90\x77\xc8\xe2\xf6\xce\x68\xc1\xb7\xc2\x19\x5f\x3c\xc1\x6c\x91\x47\xe4\x7f\x62\x14\x00\x4f\xa8\xca\x1c\x23\x4b\x89\x55\x01\xac\x14\x40\x09\x55\xd6\xf1\xbf\x88\x3e\xcd\x2c\x6f\x15\xca\x93\x54\x86\x82\x30\x79\x8f\x5c\x69\x11\x6d\xfa\xca\x62\xf9\x99\x49\x9e\x17\xee\xe7\x0a\xa0\x30\x54\x5e\xef\xd0\x2f\x55\xa7\x03\x26\x8f\x93\x05\x1c\x50\x30\xd5\x8e\x1a\x43\x43\xcc\x47\xd5\x15\x30\x1e\x1c\x85\xb7\x91\xdd\xa0\xf9\xbe\xc8\xf4\x94\x6d\x15\x99\x46\x67\x71\x11\xbb\xd2\x7f\x65\x9e\x2f\x31\x45\x4f\xdd\x5f\x9d\xde\x64\x0a\x3f\xe4\x36\x53\xd6\x34\x11\x2b\x35\xe8\x32\x06\x8b\xc5\x14\x02\x1a\x71\x14\xae\x46\x64\x76\x76\xf6\x4a\x1b\x83\xb1\x04\x05\x83\xdc\xdc\x47\x4c\x1d\xe8\x18\x7d\xf1\xc4\x51\x68\xc6\x60\x4f\x6f\x13\x99\x84\x76\x79\xff\xe2\x14\xf3\x47\xa2\x50\x64\x1e\x49\xfe\x13\x47\xe9\xaf\xcc\xa5\x81\xcf\xda\x56\x01\xfc\x19\xcb\x1e\x68\xdb\x45\x76\x79\xfc\x65\x0a\x26\x67\x4f\xfb\x2a\xa0\xdc\x11\xdf\x5e\xfb\x7c\x70\x61\x1e\x2b\x46\xdb\x6b\x69\x28\x62\x48\xbd\xdb\x4b\x45\x63\xaa\x52\xde\x05\x14\xf5\x0c\x96\x84\x99\x0f\x92\x70\x36\x02\xae\x3c\xb3\xcd\x06\x2d\xb8\x00\xb3\x9b\xb0\xae\xdb\xfa\x07\xd0\xc1\xc2\xd5\xf6\x3d\xbc\xac\xdb\xfa\x0c\xee\x7a\x67\x7a\xf5\x0c\x2c\x46\xc6\xa9\x59\xe0\x1b\x05\xa0\x77\x34\x62\x0d\x37\x3d\x82\xdc\x11\xa4\x9e\xb2\xb7\x30\x68\x31\x7d\xad\x9e\xd4\x2f\xbe\x0f\x92\x3b\x58\xbf\x7a\x5d\x2e\xfe\x3f\x6f\x13\xc9\x7e\x5e\x46\xf8\x81\x2f\x21\x8f\x2e\x1c\x3e\x85\x3d\x15\xf2\xdd\xe9\x66\x6d\xa7\xbd\xda\x76\xeb\xf6\x6c\xaa\x56\x82\x97\x73\xc5\x0e\xc4\xc4\x57\x00\x53\x8f\x4d\x4d\x72\xde\x81\xd1\xb5\x61\x51\x23\xf9\x3c\xe0\xf7\x76\xe1\xd2\x76\x8f\xda\xe6\x35\x5b\xcf\x09\x49\x45\xa6\xaf\xf7\x4f\x97\x4e\x39\xa9\x06\xb2\x58\xbe\xa0\x34\xf0\xc3\xf6\x5b\xca\x1c\x7d\x99\xb8\x7e\xcd\x24\x7a\xc6\x46\xe4\x0f\xdb\x8f\x4c\x39\x76\xea\xef\x00\x00\x00\xff\xff\x0a\xb7\x3b\xf7\x5e\x06\x00\x00") - -func masterTmpBootstrapconfigsComputeConfigYamlBytes() ([]byte, error) { - return bindataRead( - _masterTmpBootstrapconfigsComputeConfigYaml, - "master/tmp/bootstrapconfigs/compute-config.yaml", - ) -} - -func masterTmpBootstrapconfigsComputeConfigYaml() (*asset, error) { - bytes, err := masterTmpBootstrapconfigsComputeConfigYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/tmp/bootstrapconfigs/compute-config.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterTmpBootstrapconfigsInfraConfigYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x54\x4d\x73\x1b\x37\x0c\xbd\xf3\x57\x60\x94\x43\x2e\xd9\x0f\x39\x49\x33\xb3\x33\x39\xb8\xb6\x93\x66\xda\xd8\xae\xe4\xf6\x9a\xa1\x48\x48\xcb\x9a\x4b\xb0\x20\xb8\x8e\xfb\xeb\x3b\xdc\x5d\xdb\x72\x93\xce\xb4\x27\x69\x89\x87\x87\xc7\x47\x00\xda\x7b\xba\x3b\x77\x49\xef\x3c\xda\x73\x32\xb7\xc8\x1d\xec\xb5\x4f\xa8\x74\x74\xbf\x23\x27\x47\xa1\x83\x71\xad\x6c\x48\x3f\xba\x60\x4f\xad\x65\x4c\xa9\x83\xf5\xc9\xbb\xba\xad\xdb\x7a\xdd\xbd\x7d\x5d\x82\x1b\x34\x99\x93\x1b\x71\x83\x89\xfc\x78\x46\x61\xdf\x41\x83\x62\x1a\x62\x77\x70\xa1\x09\x64\xb1\xe1\x29\x58\x1b\x0a\xfb\x92\x74\x4e\x83\x76\xa1\x03\xe3\x73\x12\xe4\xda\x93\xd1\xbe\x04\x3e\x5d\x77\xb0\x7e\x77\x52\xaf\x4b\x91\xb5\xb2\x93\xb2\xc2\xe9\x0e\x9d\x02\x98\xbf\xb7\xbd\x1b\x36\x44\x72\xee\x18\x8d\x10\xdf\x77\xd0\x8c\x9a\x1b\xef\x76\xcd\x8c\x48\xbd\x1b\x9e\xc1\xb7\xe5\x9f\x2c\x38\xce\xe1\x08\x57\x27\x32\xb7\x0a\x00\xbf\xa2\xf9\x49\x07\xeb\x91\x2f\xf5\x80\x1d\x04\x2d\x6e\x44\xe5\xa2\x14\x97\xd2\xf6\x3e\x98\x6b\x64\x47\xb6\x83\xd5\xeb\x36\xad\x94\x1b\xf4\x01\x9f\xc4\xed\x89\x07\x2d\x1d\x7c\x3e\xdd\xde\x5c\x6c\xbe\x5c\x6d\x2e\x3e\x7e\xf9\x6d\xf3\x8b\x02\xf0\x5a\x30\x49\x07\x1f\x26\x83\x6f\x5d\xb0\x1d\x5c\x92\x5d\x72\xd5\x6d\xde\xa1\x47\x39\xe5\x43\x1e\x30\x48\x2a\x64\x91\x6c\x35\xe8\xe0\xf6\x98\xa4\x8a\x5a\xfa\x72\x58\x7d\x6b\x6c\x24\x9b\x14\xc0\x8e\x48\x92\xb0\x8e\x55\x21\x33\x8f\x9a\xbe\x93\xf1\x08\xad\x9f\xa0\x45\x3d\x6a\xc9\x8c\xd5\xa1\x68\x9d\x53\x37\x24\x5a\xf0\xe7\x59\xdd\x99\x77\x18\xe4\x0c\x59\xdc\xde\x19\x2d\xf8\x5e\x38\xe3\xab\x67\x98\x2d\xf2\x88\xfc\x4f\x8c\x02\xe0\x09\x55\x99\xa7\xc8\x52\x62\x55\x00\x2b\x05\x50\x42\x95\x75\xfc\x2f\xa2\x8f\x33\xcb\x5b\x85\xf2\x24\x95\xa1\x20\x4c\xde\x23\x57\x5a\x44\x9b\xbe\xb2\x58\x7e\x66\x92\x97\x85\xfb\xa5\x02\x28\x0c\x95\xd7\x3b\xf4\x4b\xd5\xe9\x80\xc9\xe3\x64\x01\x07\x14\x4c\xb5\xa3\xc6\x85\x3d\xeb\x07\xcd\x15\x30\x1e\x1c\x85\xf7\xd3\x69\x91\xe8\x29\xdb\x2a\x32\x8d\xce\xe2\x22\x74\xa5\xff\xca\x3c\x5f\x60\x8a\x1e\x3b\xbf\x3a\xbe\xc5\x14\x7e\xc8\x6d\xa6\xac\x69\x1a\x56\x6a\xd0\x65\x04\x16\x7b\x29\x04\x34\xe2\x28\x5c\x8d\xc8\xec\xec\xec\x93\x36\x06\x63\x09\x0a\x06\xb9\xb9\x8f\x98\x3a\xd0\x31\xfa\xe2\x87\xa3\xd0\x8c\xc1\x1e\xdf\x24\x32\x09\xed\xf2\xfe\xd5\x31\xe6\x8f\x44\xa1\xc8\x7c\x22\xf9\x4f\x1c\xa5\xb7\x32\x97\xe6\x3d\x69\x5b\x05\xf0\x67\x2c\x3b\xa0\x6d\x17\xd9\xe5\xe1\x97\x09\x98\x5c\x3d\xee\xa9\x80\x72\x47\x7c\x7b\xed\xf3\xc1\x85\x79\xa4\x18\x6d\xaf\xa5\xa1\x88\x21\xf5\x6e\x2f\x15\x8d\xa9\x4a\x79\x17\x50\xd4\x0b\x58\x12\x66\x3e\x48\xc2\xd9\x08\xb8\xf2\xc4\x36\x1b\xb4\xe0\x02\xcc\x6e\xc2\xba\x6e\xeb\x1f\x40\x07\x0b\x57\xdb\x0b\x78\x5d\xb7\xf5\x09\xdc\xf5\xce\xf4\xea\x05\x58\x8c\x8c\x53\xa3\xc0\x37\x0a\x40\xef\x68\xc4\x1a\x6e\x7a\x04\xb9\x23\x48\x3d\x65\x6f\x61\xd0\x62\xfa\x5a\x3d\xab\x5f\x7c\x1f\x24\x77\xb0\x7e\xf3\xb6\x5c\xfc\x7f\xde\x26\x92\xfd\xbc\x8c\xef\x03\x5f\x42\x1e\x5d\x38\x7c\x0a\x7b\x2a\xe4\xbb\xe3\xad\xda\x4e\x3b\xb5\xed\xd6\xed\xc9\x54\xad\x04\x2f\xe7\x8a\x1d\x88\x89\x6f\xa6\x0e\x9b\x5a\xe4\xb4\x03\xa3\x6b\xc3\xa2\x46\xf2\x79\xc0\xef\x6d\xc1\xa5\xe9\x1e\x95\xcd\x0b\xb6\x9e\x13\x92\x8a\x4c\x5f\xef\x9f\xaf\x9b\x72\x52\x0d\x64\xb1\x7c\x41\x69\xdf\x87\xbd\xb7\x94\x79\x72\x65\xe2\xfa\x35\x93\xe8\x19\x1b\x91\x3f\x6c\x3f\x32\xe5\xd8\xa9\xbf\x03\x00\x00\xff\xff\xcd\xd7\x9a\x63\x58\x06\x00\x00") - -func masterTmpBootstrapconfigsInfraConfigYamlBytes() ([]byte, error) { - return bindataRead( - _masterTmpBootstrapconfigsInfraConfigYaml, - "master/tmp/bootstrapconfigs/infra-config.yaml", - ) -} - -func masterTmpBootstrapconfigsInfraConfigYaml() (*asset, error) { - bytes, err := masterTmpBootstrapconfigsInfraConfigYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/tmp/bootstrapconfigs/infra-config.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _masterTmpBootstrapconfigsMasterConfigYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x54\x4d\x73\xdb\x36\x10\xbd\xe3\x57\xec\x28\x87\x5c\xc2\x0f\x39\x49\x33\xc3\x99\x1c\x5c\xdb\x49\x33\x6d\x6c\x57\x72\x7b\xcd\x40\xc0\x52\x44\x05\x62\xd1\xc5\x92\x8e\xfb\xeb\x3b\x20\x69\x4b\x6e\xd2\x99\xf6\x24\x11\xfb\xf6\xed\xdb\x87\xc5\x6a\xef\xe9\xfe\xd2\x25\xbd\xf3\x68\x2f\xc9\x1c\x90\x1b\x68\xb5\x4f\xa8\x74\x74\xbf\x23\x27\x47\xa1\x81\x71\xad\x6c\x48\x3f\xba\x60\xcf\xad\x65\x4c\xa9\x81\xf5\xd9\xbb\xb2\x2e\xeb\x72\xdd\xbc\x7d\x9d\x83\x1b\x34\x03\x27\x37\xe2\x06\x13\xf9\xf1\x82\x42\xdb\x40\x85\x62\x2a\x62\xb7\x77\xa1\x0a\x64\xb1\xe2\x29\x58\x1a\x0a\x6d\x4e\xba\xa4\x5e\xbb\xd0\x80\xf1\x43\x12\xe4\xd2\x93\xd1\x3e\x07\x3e\xdd\x36\xb0\x7e\x77\x56\xae\x73\x91\xb5\xb2\x93\xb2\xcc\xe9\xf6\x8d\x02\x98\xbf\xb7\x9d\xeb\x37\x44\x72\xe9\x18\x8d\x10\x3f\x34\x50\x8d\x9a\x2b\xef\x76\xd5\x8c\x48\x9d\xeb\x9f\xc1\xb7\xf9\x9f\x2c\x38\x1e\xc2\x09\xae\x4c\x64\x0e\x0a\x00\xbf\xa2\xf9\x49\x07\xeb\x91\xaf\x75\x8f\x0d\x04\x2d\x6e\x44\xe5\xa2\x64\x97\xd2\xf6\x21\x98\x5b\x64\x47\xb6\x81\xd5\xeb\x3a\xad\x94\xeb\xf5\x1e\x8f\xe2\x5a\xe2\x5e\x4b\x03\x9f\xcf\xb7\x77\x57\x9b\x2f\x37\x9b\xab\x8f\x5f\x7e\xdb\xfc\xa2\x00\xbc\x16\x4c\xd2\xc0\x87\xc9\xe0\x83\x0b\xb6\x81\x6b\xb2\x4b\xae\x3a\x0c\x3b\xf4\x28\xe7\xbc\x1f\x7a\x0c\x92\x32\x59\x24\x5b\xf4\x3a\xb8\x16\x93\x14\x51\x4b\x97\x0f\x8b\x6f\x8d\x8d\x64\x93\x02\xd8\x11\x49\x12\xd6\xb1\xc8\x64\xe6\x49\xd3\x77\x32\x9e\xa0\xe5\x11\x9a\xd5\xa3\x96\x81\xb1\xd8\x67\xad\x73\xea\x86\x44\x0b\xfe\x3c\xab\xbb\xf0\x0e\x83\x5c\x20\x8b\x6b\x9d\xd1\x82\xef\x85\x07\x7c\xf5\x0c\xb3\x45\x1e\x91\xff\x89\x51\x00\x3c\xa1\x0a\x73\x8c\x2c\x25\x56\x19\xb0\x52\x00\x39\x54\x58\xc7\xff\x22\xfa\x34\x33\xdf\x55\xc8\x57\x52\x18\x0a\xc2\xe4\x3d\x72\xa1\x45\xb4\xe9\x0a\x8b\xf9\x67\x26\x79\x99\xb9\x5f\x2a\x80\xcc\x50\x78\xbd\x43\xbf\x54\x9d\x0e\x98\x3c\x4e\x16\x70\x40\xc1\x54\x3a\xaa\x7a\x9d\xa7\xf1\x51\x74\x01\x14\x31\xa4\xce\xb5\x52\xb8\xd0\xb2\x7e\xaf\xa3\x4b\x53\x8b\x59\xb0\xa7\xc1\x16\x91\x69\x74\x16\x17\xd9\x2b\xfd\xd7\xc0\x73\x3b\x53\xf4\xf4\x1e\x56\xa7\x3d\x4d\xe1\xc7\xdc\x6a\xca\x9a\xde\xc6\x4a\xcd\x12\x16\xb3\x29\x04\x34\xe2\x28\xdc\x8c\xc8\xec\xec\xec\x9a\x36\x06\x63\x0e\x0a\x06\xb9\x7b\x88\x98\x1a\xd0\x31\xfa\xec\x8e\xa3\x50\x8d\xc1\x9e\xf6\x15\x99\x84\x76\x43\xfb\xea\x14\xf3\x47\xa2\x90\x65\x1e\x49\xfe\x13\x47\x9e\xb4\x81\xf3\x28\x9f\xd5\xb5\x02\xf8\x33\xe6\x8d\x50\xd7\x8b\xec\x3c\x06\xcb\x7b\x98\x3c\x3e\x9d\xb0\x80\x72\x4f\x7c\xb8\xf5\xc3\xde\x85\xf9\x81\x31\xda\x4e\x4b\x75\x74\x99\xc6\x54\xa4\x61\x17\x50\xd4\x0b\x58\x12\x66\x3e\x48\xc2\x83\x11\x70\xf9\xc2\xed\x60\xd0\x82\x0b\x30\xbb\x09\xeb\xb2\x2e\x7f\x00\x1d\x2c\xdc\x6c\xaf\xe0\x75\x59\x97\x67\x70\xdf\x39\xd3\xa9\x17\x60\x31\x32\x4e\x63\x03\xdf\x28\x00\xbd\xa3\x11\x4b\xb8\xeb\x10\xe4\x9e\x20\x75\x34\x78\x0b\xbd\x16\xd3\x95\xea\x59\xfd\xec\x7b\x2f\x43\x03\xeb\x37\x6f\x73\xe3\xff\xb3\x9b\x48\xf6\xf3\xf2\x98\x1f\xf9\xf2\x20\xb9\xb0\xff\x14\x5a\xca\xe4\xbb\xd3\x1d\x5b\x4f\x1b\xb6\x6e\xd6\xf5\xd9\x54\x2d\x07\xaf\xe7\x8a\x0d\x88\x89\x6f\xa6\x09\x9b\x46\xe4\xbc\x01\xa3\x4b\xc3\xa2\x46\xf2\x43\x8f\xdf\xdb\x89\xcb\xd0\x3d\x29\x9b\xd7\x6d\x39\x27\x24\x15\x99\xbe\x3e\x3c\x5f\x3e\xf9\xa4\xe8\xc9\x62\xfe\x82\x3c\xbe\x8f\x5b\x70\x29\x73\x74\x65\xe2\xfa\x75\x20\xd1\x33\x36\x22\x7f\xd8\x7e\x64\x1a\x62\xa3\xfe\x0e\x00\x00\xff\xff\x42\x81\xca\x0c\x66\x06\x00\x00") - -func masterTmpBootstrapconfigsMasterConfigYamlBytes() ([]byte, error) { - return bindataRead( - _masterTmpBootstrapconfigsMasterConfigYaml, - "master/tmp/bootstrapconfigs/master-config.yaml", - ) -} - -func masterTmpBootstrapconfigsMasterConfigYaml() (*asset, error) { - bytes, err := masterTmpBootstrapconfigsMasterConfigYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "master/tmp/bootstrapconfigs/master-config.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _nodeEtcOriginCloudproviderAzureConf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x90\x51\x8a\x83\x30\x10\x86\xdf\xf7\x14\x39\x81\x07\xd8\xb7\xa0\xb0\x2c\x2c\xcb\xb2\x7a\x81\x31\x4e\xcb\x40\x4c\xec\x38\x29\x58\xeb\xdd\x4b\xab\x0f\x51\xd3\x42\x9f\xbf\xff\xfb\x87\xf9\x05\x1d\x38\xf9\x6e\x3e\xd5\x38\xaa\x4c\x5f\x02\x63\xee\xdd\x81\x8e\x59\x35\x93\x42\x5d\xd5\x29\x78\x41\x35\x4d\x1f\x7d\xa8\x7b\xc3\xd4\x09\x79\x97\x72\xca\x98\xaf\x4c\x80\x26\xb7\x84\xe9\x53\x5a\x17\x0b\x4c\x3b\x25\x1a\x46\x79\xe1\xcd\x81\x8d\x5b\xbd\xf5\x1a\x63\xef\x03\x1b\xfc\x62\x1f\xba\xbd\xf2\x1f\xe3\xd8\xb3\xde\xc0\xfd\xdd\xbd\xf2\xb3\x90\xd5\x80\x68\x02\x93\x0c\x8f\x9a\x5f\x68\x31\xb1\xe1\x36\x12\xfb\x1d\x53\x0b\x3c\xe8\x33\x90\x85\x9a\x2c\xc9\x50\xa2\xa4\x8b\xfe\x9e\x66\xe3\xc6\x5b\x00\x00\x00\xff\xff\x34\x7d\xff\xaa\x01\x02\x00\x00") - -func nodeEtcOriginCloudproviderAzureConfBytes() ([]byte, error) { - return bindataRead( - _nodeEtcOriginCloudproviderAzureConf, - "node/etc/origin/cloudprovider/azure.conf", - ) -} - -func nodeEtcOriginCloudproviderAzureConf() (*asset, error) { - bytes, err := nodeEtcOriginCloudproviderAzureConfBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "node/etc/origin/cloudprovider/azure.conf", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _nodeEtcOriginNodeResolvConf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xca\x4b\xcc\x4d\x2d\x4e\x2d\x2a\x4b\x2d\x52\x30\x34\xb3\xd0\x33\x33\xd6\x33\x34\xb2\xd4\x33\x34\xe3\x02\x04\x00\x00\xff\xff\x77\xaa\x94\x8c\x19\x00\x00\x00") - -func nodeEtcOriginNodeResolvConfBytes() ([]byte, error) { - return bindataRead( - _nodeEtcOriginNodeResolvConf, - "node/etc/origin/node/resolv.conf", - ) -} - -func nodeEtcOriginNodeResolvConf() (*asset, error) { - bytes, err := nodeEtcOriginNodeResolvConfBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "node/etc/origin/node/resolv.conf", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -// Asset loads and returns the asset for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func Asset(name string) ([]byte, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) - } - return a.bytes, nil - } - return nil, fmt.Errorf("Asset %s not found", name) -} - -// MustAsset is like Asset but panics when Asset would return an error. -// It simplifies safe initialization of global variables. -func MustAsset(name string) []byte { - a, err := Asset(name) - if err != nil { - panic("asset: Asset(" + name + "): " + err.Error()) - } - - return a -} - -// AssetInfo loads and returns the asset info for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func AssetInfo(name string) (os.FileInfo, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) - } - return a.info, nil - } - return nil, fmt.Errorf("AssetInfo %s not found", name) -} - -// AssetNames returns the names of the assets. -func AssetNames() []string { - names := make([]string, 0, len(_bindata)) - for name := range _bindata { - names = append(names, name) - } - return names -} - -// _bindata is a table, holding each asset generator, mapped to its name. -var _bindata = map[string]func() (*asset, error){ - "master/etc/etcd/etcd.conf": masterEtcEtcdEtcdConf, - "master/etc/origin/master/htpasswd": masterEtcOriginMasterHtpasswd, - "master/etc/origin/master/master-config.yaml": masterEtcOriginMasterMasterConfigYaml, - "master/etc/origin/master/scheduler.json": masterEtcOriginMasterSchedulerJson, - "master/etc/origin/master/session-secrets.yaml": masterEtcOriginMasterSessionSecretsYaml, - "master/tmp/ansible/ansible.sh": masterTmpAnsibleAnsibleSh, - "master/tmp/ansible/azure-local-master-inventory.yml": masterTmpAnsibleAzureLocalMasterInventoryYml, - "master/tmp/ansible/azure-ocp-deploy.yml": masterTmpAnsibleAzureOcpDeployYml, - "master/tmp/bootstrapconfigs/compute-config.yaml": masterTmpBootstrapconfigsComputeConfigYaml, - "master/tmp/bootstrapconfigs/infra-config.yaml": masterTmpBootstrapconfigsInfraConfigYaml, - "master/tmp/bootstrapconfigs/master-config.yaml": masterTmpBootstrapconfigsMasterConfigYaml, - "node/etc/origin/cloudprovider/azure.conf": nodeEtcOriginCloudproviderAzureConf, - "node/etc/origin/node/resolv.conf": nodeEtcOriginNodeResolvConf, -} - -// AssetDir returns the file names below a certain -// directory embedded in the file by go-bindata. -// For example if you run go-bindata on data/... and data contains the -// following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png -// then AssetDir("data") would return []string{"foo.txt", "img"} -// AssetDir("data/img") would return []string{"a.png", "b.png"} -// AssetDir("foo.txt") and AssetDir("notexist") would return an error -// AssetDir("") will return []string{"data"}. -func AssetDir(name string) ([]string, error) { - node := _bintree - if len(name) != 0 { - cannonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(cannonicalName, "/") - for _, p := range pathList { - node = node.Children[p] - if node == nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - } - } - if node.Func != nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - rv := make([]string, 0, len(node.Children)) - for childName := range node.Children { - rv = append(rv, childName) - } - return rv, nil -} - -type bintree struct { - Func func() (*asset, error) - Children map[string]*bintree -} - -var _bintree = &bintree{nil, map[string]*bintree{ - "master": {nil, map[string]*bintree{ - "etc": {nil, map[string]*bintree{ - "etcd": {nil, map[string]*bintree{ - "etcd.conf": {masterEtcEtcdEtcdConf, map[string]*bintree{}}, - }}, - "origin": {nil, map[string]*bintree{ - "master": {nil, map[string]*bintree{ - "htpasswd": {masterEtcOriginMasterHtpasswd, map[string]*bintree{}}, - "master-config.yaml": {masterEtcOriginMasterMasterConfigYaml, map[string]*bintree{}}, - "scheduler.json": {masterEtcOriginMasterSchedulerJson, map[string]*bintree{}}, - "session-secrets.yaml": {masterEtcOriginMasterSessionSecretsYaml, map[string]*bintree{}}, - }}, - }}, - }}, - "tmp": {nil, map[string]*bintree{ - "ansible": {nil, map[string]*bintree{ - "ansible.sh": {masterTmpAnsibleAnsibleSh, map[string]*bintree{}}, - "azure-local-master-inventory.yml": {masterTmpAnsibleAzureLocalMasterInventoryYml, map[string]*bintree{}}, - "azure-ocp-deploy.yml": {masterTmpAnsibleAzureOcpDeployYml, map[string]*bintree{}}, - }}, - "bootstrapconfigs": {nil, map[string]*bintree{ - "compute-config.yaml": {masterTmpBootstrapconfigsComputeConfigYaml, map[string]*bintree{}}, - "infra-config.yaml": {masterTmpBootstrapconfigsInfraConfigYaml, map[string]*bintree{}}, - "master-config.yaml": {masterTmpBootstrapconfigsMasterConfigYaml, map[string]*bintree{}}, - }}, - }}, - }}, - "node": {nil, map[string]*bintree{ - "etc": {nil, map[string]*bintree{ - "origin": {nil, map[string]*bintree{ - "cloudprovider": {nil, map[string]*bintree{ - "azure.conf": {nodeEtcOriginCloudproviderAzureConf, map[string]*bintree{}}, - }}, - "node": {nil, map[string]*bintree{ - "resolv.conf": {nodeEtcOriginNodeResolvConf, map[string]*bintree{}}, - }}, - }}, - }}, - }}, -}} - -// RestoreAsset restores an asset under the given directory -func RestoreAsset(dir, name string) error { - data, err := Asset(name) - if err != nil { - return err - } - info, err := AssetInfo(name) - if err != nil { - return err - } - err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) - if err != nil { - return err - } - err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) - if err != nil { - return err - } - err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) - if err != nil { - return err - } - return nil -} - -// RestoreAssets restores an asset under the given directory recursively -func RestoreAssets(dir, name string) error { - children, err := AssetDir(name) - // File - if err != nil { - return RestoreAsset(dir, name) - } - // Dir - for _, child := range children { - err = RestoreAssets(dir, filepath.Join(name, child)) - if err != nil { - return err - } - } - return nil -} - -func _filePath(dir, name string) string { - cannonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) -} diff --git a/pkg/openshift/certgen/unstable/templates/master/etc/etcd/etcd.conf b/pkg/openshift/certgen/unstable/templates/master/etc/etcd/etcd.conf deleted file mode 100644 index c148e25cc3..0000000000 --- a/pkg/openshift/certgen/unstable/templates/master/etc/etcd/etcd.conf +++ /dev/null @@ -1,58 +0,0 @@ -ETCD_NAME={{ .Master.Hostname | shellQuote }} -ETCD_LISTEN_PEER_URLS={{ print "https://" (index .Master.IPs 0).String ":2380" | shellQuote }} -ETCD_DATA_DIR=/var/lib/etcd/ -#ETCD_WAL_DIR="" -#ETCD_SNAPSHOT_COUNT=10000 -ETCD_HEARTBEAT_INTERVAL=500 -ETCD_ELECTION_TIMEOUT=2500 -ETCD_LISTEN_CLIENT_URLS={{ print "https://" (index .Master.IPs 0).String ":2379" | shellQuote }} -#ETCD_MAX_SNAPSHOTS=5 -#ETCD_MAX_WALS=5 -#ETCD_CORS= - - -#[cluster] -ETCD_INITIAL_ADVERTISE_PEER_URLS={{ print "https://" (index .Master.IPs 0).String ":2380" | shellQuote }} -ETCD_INITIAL_CLUSTER={{ print .Master.Hostname "=https://" (index .Master.IPs 0).String ":2380" | shellQuote }} -ETCD_INITIAL_CLUSTER_STATE=new -ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster-1 -#ETCD_DISCOVERY= -#ETCD_DISCOVERY_SRV= -#ETCD_DISCOVERY_FALLBACK=proxy -#ETCD_DISCOVERY_PROXY= -ETCD_ADVERTISE_CLIENT_URLS={{ print "https://" (index .Master.IPs 0).String ":2379" | shellQuote }} -#ETCD_STRICT_RECONFIG_CHECK="false" -#ETCD_AUTO_COMPACTION_RETENTION="0" -#ETCD_ENABLE_V2="true" -ETCD_QUOTA_BACKEND_BYTES=4294967296 - -#[proxy] -#ETCD_PROXY=off -#ETCD_PROXY_FAILURE_WAIT="5000" -#ETCD_PROXY_REFRESH_INTERVAL="30000" -#ETCD_PROXY_DIAL_TIMEOUT="1000" -#ETCD_PROXY_WRITE_TIMEOUT="5000" -#ETCD_PROXY_READ_TIMEOUT="0" - -#[security] -ETCD_TRUSTED_CA_FILE=/etc/etcd/ca.crt -ETCD_CLIENT_CERT_AUTH="true" -ETCD_CERT_FILE=/etc/etcd/server.crt -ETCD_KEY_FILE=/etc/etcd/server.key -#ETCD_AUTO_TLS="false" -ETCD_PEER_TRUSTED_CA_FILE=/etc/etcd/ca.crt -ETCD_PEER_CLIENT_CERT_AUTH="true" -ETCD_PEER_CERT_FILE=/etc/etcd/peer.crt -ETCD_PEER_KEY_FILE=/etc/etcd/peer.key -#ETCD_PEER_AUTO_TLS="false" - -#[logging] -ETCD_DEBUG="False" -ETCD_LOG_PACKAGE_LEVELS="etcdserver=DEBUG" - -#[profiling] -#ETCD_ENABLE_PPROF="false" -#ETCD_METRICS="basic" -# -#[auth] -#ETCD_AUTH_TOKEN="simple" diff --git a/pkg/openshift/certgen/unstable/templates/master/etc/origin/master/htpasswd b/pkg/openshift/certgen/unstable/templates/master/etc/origin/master/htpasswd deleted file mode 100644 index 893fd8848e..0000000000 --- a/pkg/openshift/certgen/unstable/templates/master/etc/origin/master/htpasswd +++ /dev/null @@ -1 +0,0 @@ -{{ .ClusterUsername }}:{{ Bcrypt .ClusterPassword }} diff --git a/pkg/openshift/certgen/unstable/templates/master/etc/origin/master/master-config.yaml b/pkg/openshift/certgen/unstable/templates/master/etc/origin/master/master-config.yaml deleted file mode 100644 index a0df9ba806..0000000000 --- a/pkg/openshift/certgen/unstable/templates/master/etc/origin/master/master-config.yaml +++ /dev/null @@ -1,236 +0,0 @@ -admissionConfig: - pluginConfig: - BuildDefaults: - configuration: - apiVersion: v1 - env: [] - kind: BuildDefaultsConfig - resources: - limits: {} - requests: {} - BuildOverrides: - configuration: - apiVersion: v1 - kind: BuildOverridesConfig - PodPreset: - configuration: - apiVersion: v1 - disable: false - kind: DefaultAdmissionConfig - openshift.io/ImagePolicy: - configuration: - apiVersion: v1 - executionRules: - - matchImageAnnotations: - - key: images.openshift.io/deny-execution - value: 'true' - name: execution-denied - onResources: - - resource: pods - - resource: builds - reject: true - skipOnResolutionFailure: true - kind: ImagePolicyConfig -aggregatorConfig: - proxyClientInfo: - certFile: aggregator-front-proxy.crt - keyFile: aggregator-front-proxy.key -apiLevels: -- v1 -apiVersion: v1 -authConfig: - requestHeader: - clientCA: front-proxy-ca.crt - clientCommonNames: - - aggregator-front-proxy - extraHeaderPrefixes: - - X-Remote-Extra- - groupHeaders: - - X-Remote-Group - usernameHeaders: - - X-Remote-User -controllerConfig: - election: - lockName: openshift-master-controllers - serviceServingCert: - signer: - certFile: service-signer.crt - keyFile: service-signer.key -controllers: '*' -corsAllowedOrigins: -- (?i)//127\.0\.0\.1(:|\z) -- (?i)//localhost(:|\z) -- {{ print "(?i)//" (QuoteMeta (index .Master.IPs 0).String) "(:|\\z)" | quote }} -- (?i)//kubernetes\.default(:|\z) -- (?i)//kubernetes\.default\.svc\.cluster\.local(:|\z) -- (?i)//kubernetes(:|\z) -- {{ print "(?i)//" (QuoteMeta .ExternalMasterHostname) "(:|\\z)" | quote }} -- (?i)//openshift\.default(:|\z) -- {{ print "(?i)//" (QuoteMeta .Master.Hostname) "(:|\\z)" | quote }} -- (?i)//openshift\.default\.svc(:|\z) -- (?i)//kubernetes\.default\.svc(:|\z) -- (?i)//172\.30\.0\.1(:|\z) -- (?i)//openshift\.default\.svc\.cluster\.local(:|\z) -- (?i)//openshift(:|\z) -dnsConfig: - bindAddress: 0.0.0.0:8053 - bindNetwork: tcp4 -etcdClientInfo: - ca: master.etcd-ca.crt - certFile: master.etcd-client.crt - keyFile: master.etcd-client.key - urls: - - {{ print "https://" .Master.Hostname ":2379" | quote }} -etcdStorageConfig: - kubernetesStoragePrefix: kubernetes.io - kubernetesStorageVersion: v1 - openShiftStoragePrefix: openshift.io - openShiftStorageVersion: v1 -imageConfig: - format: MASTER_OREG_URL - latest: false -imagePolicyConfig: - internalRegistryHostname: docker-registry.default.svc:5000 -kind: MasterConfig -kubeletClientInfo: - ca: ca-bundle.crt - certFile: master.kubelet-client.crt - keyFile: master.kubelet-client.key - port: 10250 -kubernetesMasterConfig: - apiServerArguments: - runtime-config: - - apis/settings.k8s.io/v1alpha1=true - storage-backend: - - etcd3 - storage-media-type: - - application/vnd.kubernetes.protobuf - cloud-provider: - - "azure" - cloud-config: - - "/etc/origin/cloudprovider/azure.conf" - controllerArguments: - cluster-signing-cert-file: - - "/etc/origin/master/ca.crt" - cluster-signing-key-file: - - "/etc/origin/master/ca.key" - cloud-provider: - - "azure" - cloud-config: - - "/etc/origin/cloudprovider/azure.conf" - masterCount: 1 - masterIP: {{ (index .Master.IPs 0).String | quote }} - podEvictionTimeout: null - proxyClientInfo: - certFile: master.proxy-client.crt - keyFile: master.proxy-client.key - schedulerArguments: null - schedulerConfigFile: /etc/origin/master/scheduler.json - servicesNodePortRange: '' - servicesSubnet: 172.30.0.0/16 - staticNodeNames: [] -masterClients: - externalKubernetesClientConnectionOverrides: - acceptContentTypes: application/vnd.kubernetes.protobuf,application/json - burst: 400 - contentType: application/vnd.kubernetes.protobuf - qps: 200 - externalKubernetesKubeConfig: '' - openshiftLoopbackClientConnectionOverrides: - acceptContentTypes: application/vnd.kubernetes.protobuf,application/json - burst: 600 - contentType: application/vnd.kubernetes.protobuf - qps: 300 - openshiftLoopbackKubeConfig: openshift-master.kubeconfig -masterPublicURL: {{ print "https://" .ExternalMasterHostname ":" .Master.Port | quote }} -networkConfig: - clusterNetworkCIDR: 10.128.0.0/14 - clusterNetworks: - - cidr: 10.128.0.0/14 - hostSubnetLength: 9 - externalIPNetworkCIDRs: - - 0.0.0.0/0 - hostSubnetLength: 9 - networkPluginName: redhat/openshift-ovs-subnet - serviceNetworkCIDR: 172.30.0.0/16 -oauthConfig: - assetPublicURL: {{ print "https://" .ExternalMasterHostname ":" .Master.Port "/console/" | quote }} - grantConfig: - method: auto - identityProviders: -{{- if .EnableAADAuthentication}} - - name: Azure AD - challenge: false - login: true - mappingMethod: claim - provider: - apiVersion: v1 - kind: OpenIDIdentityProvider - clientID: {{ .AzureConfig.AADClientID | quote }} - clientSecret: {{ .AzureConfig.AADClientSecret | quote }} - claims: - id: - - sub - preferredUsername: - - unique_name - name: - - name - email: - - email - urls: - authorize: {{ print "https://login.microsoftonline.com/" .AzureConfig.TenantID "/oauth2/authorize" | quote }} - token: {{ print "https://login.microsoftonline.com/" .AzureConfig.TenantID "/oauth2/token" | quote }} -{{- end}} - - name: Local password - challenge: true - login: true - mappingMethod: claim - provider: - apiVersion: v1 - file: /etc/origin/master/htpasswd - kind: HTPasswdPasswordIdentityProvider - masterCA: ca-bundle.crt - masterPublicURL: {{ print "https://" .ExternalMasterHostname ":" .Master.Port | quote }} - masterURL: {{ print "https://" .ExternalMasterHostname ":" .Master.Port | quote }} - sessionConfig: - sessionMaxAgeSeconds: 3600 - sessionName: ssn - sessionSecretsFile: /etc/origin/master/session-secrets.yaml - tokenConfig: - accessTokenMaxAgeSeconds: 86400 - authorizeTokenMaxAgeSeconds: 500 -pauseControllers: false -policyConfig: - bootstrapPolicyFile: /etc/origin/master/policy.json - openshiftInfrastructureNamespace: openshift-infra - openshiftSharedResourcesNamespace: openshift -projectConfig: - defaultNodeSelector: node-role.kubernetes.io/compute=true - projectRequestMessage: '' - projectRequestTemplate: '' - securityAllocator: - mcsAllocatorRange: s0:/2 - mcsLabelsPerProject: 5 - uidAllocatorRange: 1000000000-1999999999/10000 -routingConfig: - subdomain: TEMPROUTERIP.nip.io -serviceAccountConfig: - limitSecretReferences: false - managedNames: - - default - - builder - - deployer - masterCA: ca-bundle.crt - privateKeyFile: serviceaccounts.private.key - publicKeyFiles: - - serviceaccounts.public.key -servingInfo: - bindAddress: {{ print "0.0.0.0:" .Master.Port | quote }} - bindNetwork: tcp4 - certFile: master.server.crt - clientCA: ca.crt - keyFile: master.server.key - maxRequestsInFlight: 500 - requestTimeoutSeconds: 3600 -volumeConfig: - dynamicProvisioningEnabled: true diff --git a/pkg/openshift/certgen/unstable/templates/master/etc/origin/master/scheduler.json b/pkg/openshift/certgen/unstable/templates/master/etc/origin/master/scheduler.json deleted file mode 100644 index c67f1b3b9b..0000000000 --- a/pkg/openshift/certgen/unstable/templates/master/etc/origin/master/scheduler.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "apiVersion": "v1", - "kind": "Policy", - "predicates": [ - { - "name": "NoVolumeZoneConflict" - }, - { - "name": "MaxEBSVolumeCount" - }, - { - "name": "MaxGCEPDVolumeCount" - }, - { - "name": "MaxAzureDiskVolumeCount" - }, - { - "name": "MatchInterPodAffinity" - }, - { - "name": "NoDiskConflict" - }, - { - "name": "GeneralPredicates" - }, - { - "name": "PodToleratesNodeTaints" - }, - { - "name": "CheckNodeMemoryPressure" - }, - { - "name": "CheckNodeDiskPressure" - }, - { - "name": "CheckVolumeBinding" - }, - { - "argument": { - "serviceAffinity": { - "labels": [ - "region" - ] - } - }, - "name": "Region" - } - ], - "priorities": [ - { - "name": "SelectorSpreadPriority", - "weight": 1 - }, - { - "name": "InterPodAffinityPriority", - "weight": 1 - }, - { - "name": "LeastRequestedPriority", - "weight": 1 - }, - { - "name": "BalancedResourceAllocation", - "weight": 1 - }, - { - "name": "NodePreferAvoidPodsPriority", - "weight": 10000 - }, - { - "name": "NodeAffinityPriority", - "weight": 1 - }, - { - "name": "TaintTolerationPriority", - "weight": 1 - }, - { - "argument": { - "serviceAntiAffinity": { - "label": "zone" - } - }, - "name": "Zone", - "weight": 2 - } - ] -} diff --git a/pkg/openshift/certgen/unstable/templates/master/etc/origin/master/session-secrets.yaml b/pkg/openshift/certgen/unstable/templates/master/etc/origin/master/session-secrets.yaml deleted file mode 100644 index d440e83292..0000000000 --- a/pkg/openshift/certgen/unstable/templates/master/etc/origin/master/session-secrets.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -kind: SessionSecrets -secrets: -- authentication: {{ .AuthSecret | quote }} - encryption: {{ .EncSecret | quote }} diff --git a/pkg/openshift/certgen/unstable/templates/master/tmp/ansible/ansible.sh b/pkg/openshift/certgen/unstable/templates/master/tmp/ansible/ansible.sh deleted file mode 100644 index 68e987341e..0000000000 --- a/pkg/openshift/certgen/unstable/templates/master/tmp/ansible/ansible.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -ex - -# TODO: do this, and more (registry console, asb), the proper way - -# we get "dial tcp: lookup foo.eastus.cloudapp.azure.com on 10.0.0.11:53: read -# udp 172.17.0.2:56662->10.0.0.11:53: read: no route to host errors" at -# start-up: wait until these subside. -while ! oc version &>/dev/null; do - sleep 1 -done - -for project in default openshift-infra; do - oc patch project $project -p '{"metadata":{"annotations":{"openshift.io/node-selector": ""}}}' -done - -# FIXME - This should be handled by the openshift-ansible playbooks to ensure -# a directory it needs to write to exists before attempting to write -# to it -mkdir -p /etc/origin/master/named_certificates - -# Deploy all infra components reusing relevant parts from openshift-ansible -ANSIBLE_ROLES_PATH=/usr/share/ansible/openshift-ansible/roles/ \ - ansible-playbook\ - -M /usr/share/ansible/openshift-ansible/roles/lib_utils/library \ - -c local azure-ocp-deploy.yml \ - -i azure-local-master-inventory.yml - -# TODO: possibly wait here for convergence? diff --git a/pkg/openshift/certgen/unstable/templates/master/tmp/ansible/azure-local-master-inventory.yml b/pkg/openshift/certgen/unstable/templates/master/tmp/ansible/azure-local-master-inventory.yml deleted file mode 100644 index 1f0d54a0d7..0000000000 --- a/pkg/openshift/certgen/unstable/templates/master/tmp/ansible/azure-local-master-inventory.yml +++ /dev/null @@ -1,97 +0,0 @@ ---- -# FIXME: Anything below in all-caps has it's value replaced by sed in the -# openshiftmasterscript.sh which is not ideal, we should fix that. -localmaster: - hosts: - localhost - vars: - ansible_connection: local - ansible_python_interpreter: /usr/bin/python2 - - openshift_is_containerized: False - openshift_client_binary: /usr/bin/oc - - openshift_image_tag: "vVERSION" - - openshift_web_console_image_name: "IMAGE_PREFIX/IMAGE_TYPE-web-console:vVERSION" - - oreg_url: 'MASTER_OREG_URL' - openshift_master_default_subdomain: 'TEMPROUTERIP.nip.io' - - # FIXME - # This should be type=infra, but we have to live with region=infra for now - # because of legacy reasons - openshift_router_selector: 'region=infra' - openshift_registry_selector: 'region=infra' - # No idea why this is a different data type, but it is - openshift_prometheus_node_selector: {'region': 'infra'} - - # Set Azure specific data for hosted registry - openshift_hosted_registry_storage_provider: "azure_blob" - openshift_hosted_registry_storage_kind: "object" - openshift_hosted_registry_storage_azure_blob_accountname: 'REGISTRY_STORAGE_AZURE_ACCOUNTNAME' - openshift_hosted_registry_storage_azure_blob_accountkey: 'REGISTRY_STORAGE_AZURE_ACCOUNTKEY' - openshift_hosted_registry_storage_azure_blob_container: "registry" - openshift_hosted_registry_storage_azure_blob_realm: "core.windows.net" - - # FIXME - # - # Hard code this for now. - # - # Currently the cluster state at deployment time does not have the nodes - # registered to the master with labels applied and ready to be queried - # against at the point in time in the deploy that the playbooks run. Also, - # the router replica count default "falls back" to 1 appropriately where as - # the registry replica logic does not. There was also discussion about if - # it's appropriate to do this with replicas == infra nodes because it's - # perfectly feasible to have an infra node count higher than the desired - # replicas. - # - # Revisit later (possibly a daemonset or $other) - openshift_hosted_router_replicas: 1 - openshift_hosted_registry_replicas: 1 - - openshift_prometheus_state: "present" - openshift_prometheus_node_exporter_image_version: 'PROMETHEUS_EXPORTER_VERSION' - - openshift_web_console_install: True - - openshift_prometheus_image_prefix: "IMAGE_PREFIX/" - openshift_deployment_type: 'ANSIBLE_DEPLOY_TYPE' - - ansible_service_broker_install: True - ansible_service_broker_image: {{`"{{ l_asb_default_images_dict[openshift_deployment_type] if openshift_deployment_type == 'origin' else l_asb_image_url }}"`}} - openshift_service_catalog_image: "IMAGE_PREFIX/IMAGE_TYPE-service-catalog:vVERSION" - openshift_master_etcd_urls: ["https://HOSTNAME:2379"] - - template_service_broker_image: "IMAGE_PREFIX/IMAGE_TYPE-template-service-broker:vVERSION" - - # NOTE: This is redundant, but required to handle version skew between - # openshift-ansible in Origin and OCP - openshift_examples_content_version: "vSHORT_VER" - - openshift_cockpit_deployer_prefix: "COCKPIT_PREFIX/" - openshift_cockpit_deployer_basename: "COCKPIT_BASENAME" - openshift_cockpit_deployer_version: "COCKPIT_VERSION" - - # NOTE: Do not define openshift_hosted_router_replicas so that the task file - # router.yml inside the openshift_hosted role from openshift-ansible will - # autopopulate it using the openshift_hosted_router_selector and querying - # the number of infra nodes - - # NOTE: The variables below are internal to openshift-ansible and we're - # providing them here to avoid the incurred cost of fact finding - openshift: - common: - config_base: /etc/origin/ - examples_content_version: "vSHORT_VER" - master: - public_console_url: {{ print "https://" .ExternalMasterHostname ":8443/console" | quote }} - public_api_url: {{ print "https://" .ExternalMasterHostname ":8443" | quote }} - etcd_urls: ["https://HOSTNAME:2379"] #FIXME: No longer needed as of openshift-ansible-3.9.22-1 but we're not on that version yet - node: - nodename: 'HOSTNAME' - -oo_masters_to_config: - hosts: - localhost diff --git a/pkg/openshift/certgen/unstable/templates/master/tmp/ansible/azure-ocp-deploy.yml b/pkg/openshift/certgen/unstable/templates/master/tmp/ansible/azure-ocp-deploy.yml deleted file mode 100644 index b339399ec1..0000000000 --- a/pkg/openshift/certgen/unstable/templates/master/tmp/ansible/azure-ocp-deploy.yml +++ /dev/null @@ -1,75 +0,0 @@ -- name: Deploy OpenShift infrastructure workload - hosts: localmaster - gather_facts: false - - # we need variables from openshift_facts to be in scope - roles: - - openshift_facts - - post_tasks: - - name: bring up the sdn - import_role: - name: openshift_sdn - - - name: setup config sync daemonset - import_role: - name: openshift_node_group - tasks_from: sync - - - name: Import openshift_bootstrap_autoapprover role from openshift-ansible to deploy node bootstrap auto approver - import_role: - name: openshift_bootstrap_autoapprover - - - name: Import and use router task file from openshift-ansible openshift_hosted role - import_role: - name: openshift_hosted - tasks_from: router.yml - - - name: Import and use registry task file from openshift-ansible openshift_hosted role - import_role: - name: openshift_hosted - tasks_from: registry.yml - - - name: Import openshift_web_console role from openshift-ansible to deploy web console - import_role: - name: openshift_web_console - - # FIXME - There's a race condition where the infra label isn't applied to - # the infra node during cluster bring up in - # openshift_bootstrap_autoapprover, this is problematic because the - # openshift_prometheus role checks to ensure there is a node with - # the infra selector up/available/schedulable. - - shell: '/usr/bin/oc get nodes -l "region=infra" | wc -l' - register: result - until: result.stdout_lines[0]|int > 1 - retries: 30 - delay: 10 - - - - name: Import openshift_prometheus role from openshift-ansible to deploy prometheus - import_role: - name: openshift_prometheus - - - name: Import openshift_service_catalog role from openshift-ansible to deploy the service catalog - import_role: - name: openshift_service_catalog - - - name: Import ansible_service_broker role from openshift-ansible to deploy the ansible service broker - import_role: - name: ansible_service_broker - - - name: Import template_service_broker role from openshift-ansible to deploy the template service broker - import_role: - name: template_service_broker - - - name: Import openshift_examples role from openshift-ansible to deploy the examples - import_role: - name: openshift_examples - - - name: Import openshift_hosted_templates role from openshift-ansible to deploy the hosted templates - import_role: - name: openshift_hosted_templates - - - name: Import cockpit_ui role from openshift-ansible to deploy the registry console - import_role: - name: cockpit-ui diff --git a/pkg/openshift/certgen/unstable/templates/master/tmp/bootstrapconfigs/compute-config.yaml b/pkg/openshift/certgen/unstable/templates/master/tmp/bootstrapconfigs/compute-config.yaml deleted file mode 100644 index cd208d4a48..0000000000 --- a/pkg/openshift/certgen/unstable/templates/master/tmp/bootstrapconfigs/compute-config.yaml +++ /dev/null @@ -1,59 +0,0 @@ -allowDisabledDocker: false -apiVersion: v1 -dnsBindAddress: 127.0.0.1:53 -dnsRecursiveResolvConf: /etc/origin/node/resolv.conf -dnsDomain: cluster.local -dnsIP: 172.17.0.1 -dockerConfig: - dockerShimRootDirectory: /var/lib/dockershim - dockerShimSocket: /var/run/dockershim.sock - execHandlerName: native -iptablesSyncPeriod: "30s" -imageConfig: - format: MASTER_OREG_URL - latest: False -kind: NodeConfig -kubeletArguments: - pod-manifest-path: - - /etc/origin/node/pods - bootstrap-kubeconfig: - - /etc/origin/node/bootstrap.kubeconfig - feature-gates: - - RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true - rotate-certificates: - - "true" - cert-dir: - - /etc/origin/node/certificates - enable-controller-attach-detach: - - 'true' - node-labels: - - node-role.kubernetes.io/compute=true - - region=primary - cloud-provider: - - "azure" - cloud-config: - - "/etc/origin/cloudprovider/azure.conf" -masterClientConnectionOverrides: - acceptContentTypes: application/vnd.kubernetes.protobuf,application/json - contentType: application/vnd.kubernetes.protobuf - burst: 200 - qps: 100 -masterKubeConfig: node.kubeconfig -networkPluginName: redhat/openshift-ovs-subnet -# networkConfig struct introduced in origin 1.0.6 and OSE 3.0.2 which -# deprecates networkPluginName above. The two should match. -networkConfig: - mtu: 1450 - networkPluginName: redhat/openshift-ovs-subnet -podManifestConfig: -servingInfo: - bindAddress: 0.0.0.0:10250 - bindNetwork: tcp4 - clientCA: ca.crt -volumeDirectory: /var/lib/origin/openshift.local.volumes -proxyArguments: - proxy-mode: - - iptables -volumeConfig: - localQuota: - perFSGroup: diff --git a/pkg/openshift/certgen/unstable/templates/master/tmp/bootstrapconfigs/infra-config.yaml b/pkg/openshift/certgen/unstable/templates/master/tmp/bootstrapconfigs/infra-config.yaml deleted file mode 100644 index e00228c60e..0000000000 --- a/pkg/openshift/certgen/unstable/templates/master/tmp/bootstrapconfigs/infra-config.yaml +++ /dev/null @@ -1,59 +0,0 @@ -allowDisabledDocker: false -apiVersion: v1 -dnsBindAddress: 127.0.0.1:53 -dnsRecursiveResolvConf: /etc/origin/node/resolv.conf -dnsDomain: cluster.local -dnsIP: 172.17.0.1 -dockerConfig: - dockerShimRootDirectory: /var/lib/dockershim - dockerShimSocket: /var/run/dockershim.sock - execHandlerName: native -iptablesSyncPeriod: "30s" -imageConfig: - format: MASTER_OREG_URL - latest: False -kind: NodeConfig -kubeletArguments: - pod-manifest-path: - - /etc/origin/node/pods - bootstrap-kubeconfig: - - /etc/origin/node/bootstrap.kubeconfig - feature-gates: - - RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true - rotate-certificates: - - "true" - cert-dir: - - /etc/origin/node/certificates - enable-controller-attach-detach: - - 'true' - node-labels: - - node-role.kubernetes.io/infra=true - - region=infra - cloud-provider: - - "azure" - cloud-config: - - "/etc/origin/cloudprovider/azure.conf" -masterClientConnectionOverrides: - acceptContentTypes: application/vnd.kubernetes.protobuf,application/json - contentType: application/vnd.kubernetes.protobuf - burst: 200 - qps: 100 -masterKubeConfig: node.kubeconfig -networkPluginName: redhat/openshift-ovs-subnet -# networkConfig struct introduced in origin 1.0.6 and OSE 3.0.2 which -# deprecates networkPluginName above. The two should match. -networkConfig: - mtu: 1450 - networkPluginName: redhat/openshift-ovs-subnet -podManifestConfig: -servingInfo: - bindAddress: 0.0.0.0:10250 - bindNetwork: tcp4 - clientCA: ca.crt -volumeDirectory: /var/lib/origin/openshift.local.volumes -proxyArguments: - proxy-mode: - - iptables -volumeConfig: - localQuota: - perFSGroup: diff --git a/pkg/openshift/certgen/unstable/templates/master/tmp/bootstrapconfigs/master-config.yaml b/pkg/openshift/certgen/unstable/templates/master/tmp/bootstrapconfigs/master-config.yaml deleted file mode 100644 index 685f35436c..0000000000 --- a/pkg/openshift/certgen/unstable/templates/master/tmp/bootstrapconfigs/master-config.yaml +++ /dev/null @@ -1,59 +0,0 @@ -allowDisabledDocker: false -apiVersion: v1 -dnsBindAddress: 127.0.0.1:53 -dnsRecursiveResolvConf: /etc/origin/node/resolv.conf -dnsDomain: cluster.local -dnsIP: 172.17.0.1 -dockerConfig: - dockerShimRootDirectory: /var/lib/dockershim - dockerShimSocket: /var/run/dockershim.sock - execHandlerName: native -iptablesSyncPeriod: "30s" -imageConfig: - format: MASTER_OREG_URL - latest: False -kind: NodeConfig -kubeletArguments: - pod-manifest-path: - - /etc/origin/node/pods - bootstrap-kubeconfig: - - /etc/origin/node/bootstrap.kubeconfig - feature-gates: - - RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true - rotate-certificates: - - "true" - cert-dir: - - /etc/origin/node/certificates - enable-controller-attach-detach: - - 'true' - node-labels: - - node-role.kubernetes.io/master=true - - openshift-infra=apiserver - cloud-provider: - - "azure" - cloud-config: - - "/etc/origin/cloudprovider/azure.conf" -masterClientConnectionOverrides: - acceptContentTypes: application/vnd.kubernetes.protobuf,application/json - contentType: application/vnd.kubernetes.protobuf - burst: 200 - qps: 100 -masterKubeConfig: node.kubeconfig -networkPluginName: redhat/openshift-ovs-subnet -# networkConfig struct introduced in origin 1.0.6 and OSE 3.0.2 which -# deprecates networkPluginName above. The two should match. -networkConfig: - mtu: 1450 - networkPluginName: redhat/openshift-ovs-subnet -podManifestConfig: -servingInfo: - bindAddress: 0.0.0.0:10250 - bindNetwork: tcp4 - clientCA: ca.crt -volumeDirectory: /var/lib/origin/openshift.local.volumes -proxyArguments: - proxy-mode: - - iptables -volumeConfig: - localQuota: - perFSGroup: diff --git a/pkg/openshift/certgen/unstable/templates/node/etc/origin/cloudprovider/azure.conf b/pkg/openshift/certgen/unstable/templates/node/etc/origin/cloudprovider/azure.conf deleted file mode 100644 index 870b2aad1d..0000000000 --- a/pkg/openshift/certgen/unstable/templates/node/etc/origin/cloudprovider/azure.conf +++ /dev/null @@ -1,9 +0,0 @@ -tenantId: {{ .AzureConfig.TenantID | quote }} -subscriptionId: {{ .AzureConfig.SubscriptionID | quote }} -aadClientId: {{ .AzureConfig.AADClientID | quote }} -aadClientSecret: {{ .AzureConfig.AADClientSecret | quote }} -aadTenantId: {{ .AzureConfig.TenantID | quote }} -resourceGroup: {{ .AzureConfig.ResourceGroup | quote }} -location: {{ .AzureConfig.Location | quote }} -securityGroupName: {{ .AzureConfig.SecurityGroupName | quote }} -primaryAvailabilitySetName: {{ .AzureConfig.PrimaryAvailabilitySetName | quote }} diff --git a/pkg/openshift/certgen/unstable/templates/node/etc/origin/node/resolv.conf b/pkg/openshift/certgen/unstable/templates/node/etc/origin/node/resolv.conf deleted file mode 100644 index 265bc1d427..0000000000 --- a/pkg/openshift/certgen/unstable/templates/node/etc/origin/node/resolv.conf +++ /dev/null @@ -1 +0,0 @@ -nameserver 168.63.129.16 diff --git a/pkg/openshift/certgen/unstable/templates/templates.go b/pkg/openshift/certgen/unstable/templates/templates.go deleted file mode 100644 index dac8432fde..0000000000 --- a/pkg/openshift/certgen/unstable/templates/templates.go +++ /dev/null @@ -1 +0,0 @@ -package templates diff --git a/pkg/openshift/certgen/unstable/tls.go b/pkg/openshift/certgen/unstable/tls.go deleted file mode 100644 index 7fda70cff6..0000000000 --- a/pkg/openshift/certgen/unstable/tls.go +++ /dev/null @@ -1,504 +0,0 @@ -package unstable - -import ( - "bytes" - "crypto/rand" - "crypto/rsa" - "crypto/sha1" - "crypto/x509" - "crypto/x509/pkix" - "encoding/asn1" - "encoding/pem" - "fmt" - "math/big" - "net" - "time" - - "github.com/Azure/acs-engine/pkg/openshift/filesystem" -) - -type authKeyID struct { - KeyIdentifier []byte `asn1:"optional,tag:0"` - AuthorityCertIssuer generalName `asn1:"optional,tag:1"` - AuthorityCertSerialNumber *big.Int `asn1:"optional,tag:2"` -} - -type generalName struct { - DirectoryName pkix.RDNSequence `asn1:"optional,explicit,tag:4"` -} - -func newCertAndKey(filename string, template, signingcert *x509.Certificate, signingkey *rsa.PrivateKey, etcdcaspecial, etcdclientspecial bool) (CertAndKey, error) { - bits := 2048 - if etcdcaspecial { - bits = 4096 - } - - key, err := rsa.GenerateKey(rand.Reader, bits) - if err != nil { - return CertAndKey{}, err - } - - if signingcert == nil { - // make it self-signed - signingcert = template - signingkey = key - } - - if etcdcaspecial { - template.SubjectKeyId = intsha1(key.N) - ext := pkix.Extension{ - Id: []int{2, 5, 29, 35}, - } - var err error - ext.Value, err = asn1.Marshal(authKeyID{ - AuthorityCertIssuer: generalName{DirectoryName: signingcert.Subject.ToRDNSequence()}, - AuthorityCertSerialNumber: signingcert.SerialNumber, - }) - if err != nil { - return CertAndKey{}, err - } - template.ExtraExtensions = append(template.Extensions, ext) - template.MaxPathLenZero = true - } - - if etcdclientspecial { - template.SubjectKeyId = intsha1(key.N) - ext := pkix.Extension{ - Id: []int{2, 5, 29, 35}, - } - var err error - ext.Value, err = asn1.Marshal(authKeyID{ - KeyIdentifier: intsha1(signingkey.N), - AuthorityCertIssuer: generalName{DirectoryName: signingcert.Subject.ToRDNSequence()}, - AuthorityCertSerialNumber: signingcert.SerialNumber, - }) - if err != nil { - return CertAndKey{}, err - } - template.ExtraExtensions = append(template.Extensions, ext) - } - - b, err := x509.CreateCertificate(rand.Reader, template, signingcert, key.Public(), signingkey) - if err != nil { - return CertAndKey{}, err - } - - cert, err := x509.ParseCertificate(b) - if err != nil { - return CertAndKey{}, err - } - - return CertAndKey{cert: cert, key: key}, nil -} - -func certAsBytes(cert *x509.Certificate) ([]byte, error) { - buf := &bytes.Buffer{} - - err := pem.Encode(buf, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}) - if err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -func writeCert(fs filesystem.Writer, filename string, cert *x509.Certificate) error { - b, err := certAsBytes(cert) - if err != nil { - return err - } - fi := GetFileInfo(filename) - return fs.WriteFile(filename, b, fi) -} - -func privateKeyAsBytes(key *rsa.PrivateKey) ([]byte, error) { - buf := &bytes.Buffer{} - - err := pem.Encode(buf, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}) - if err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -func writePrivateKey(fs filesystem.Writer, filename string, key *rsa.PrivateKey) error { - b, err := privateKeyAsBytes(key) - if err != nil { - return err - } - - fi := GetFileInfo(filename) - return fs.WriteFile(filename, b, fi) -} - -func writePublicKey(fs filesystem.Writer, filename string, key *rsa.PublicKey) error { - buf := &bytes.Buffer{} - - b, err := x509.MarshalPKIXPublicKey(key) - if err != nil { - return err - } - - err = pem.Encode(buf, &pem.Block{Type: "PUBLIC KEY", Bytes: b}) - if err != nil { - return err - } - fi := GetFileInfo(filename) - return fs.WriteFile(filename, buf.Bytes(), fi) -} - -// PrepareMasterCerts creates the master certs -func (c *Config) PrepareMasterCerts() error { - if c.cas == nil { - c.cas = map[string]CertAndKey{} - } - - if c.Master.certs == nil { - c.Master.certs = map[string]CertAndKey{} - } - - if c.Master.etcdcerts == nil { - c.Master.etcdcerts = map[string]CertAndKey{} - } - - ips := append([]net.IP{}, c.Master.IPs...) - ips = append(ips, net.ParseIP("172.30.0.1")) - - dns := []string{ - c.ExternalMasterHostname, "kubernetes", "kubernetes.default", "kubernetes.default.svc", - "kubernetes.default.svc.cluster.local", c.Master.Hostname, "openshift", - "openshift.default", "openshift.default.svc", - "openshift.default.svc.cluster.local", - } - for _, ip := range ips { - dns = append(dns, ip.String()) - } - - now := time.Now() - - cacerts := []struct { - filename string - template *x509.Certificate - }{ - { - filename: "etc/origin/master/ca", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: fmt.Sprintf("openshift-signer@%d", now.Unix())}, - }, - }, - { - filename: "etc/origin/master/front-proxy-ca", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: fmt.Sprintf("openshift-signer@%d", now.Unix())}, - }, - }, - { - filename: "etc/origin/master/frontproxy-ca", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: fmt.Sprintf("aggregator-proxy-car@%d", now.Unix())}, - }, - }, - { - filename: "etc/origin/master/master.etcd-ca", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: fmt.Sprintf("etcd-signer@%d", now.Unix())}, - }, - }, - { - filename: "etc/origin/master/service-signer", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: fmt.Sprintf("openshift-service-serving-signer@%d", now.Unix())}, - }, - }, - { - filename: "etc/origin/service-catalog/ca", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: "service-catalog-signer"}, - }, - }, - } - - for _, cacert := range cacerts { - template := &x509.Certificate{ - SerialNumber: c.serial.Get(), - NotBefore: now, - NotAfter: now.AddDate(5, 0, 0), - KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign, - BasicConstraintsValid: true, - IsCA: true, - } - template.Subject = cacert.template.Subject - - certAndKey, err := newCertAndKey(cacert.filename, template, nil, nil, cacert.filename == "etc/origin/master/master.etcd-ca", false) - if err != nil { - return err - } - - c.cas[cacert.filename] = certAndKey - } - - certs := []struct { - filename string - template *x509.Certificate - signer string - }{ - { - filename: "etc/origin/master/admin", - template: &x509.Certificate{ - Subject: pkix.Name{Organization: []string{"system:cluster-admins", "system:masters"}, CommonName: "system:admin"}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - }, - }, - { - filename: "etc/origin/master/aggregator-front-proxy", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: "aggregator-front-proxy"}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - }, - signer: "etc/origin/master/front-proxy-ca", - }, - { - filename: "etc/origin/master/etcd.server", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: c.Master.IPs[0].String()}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - DNSNames: dns, - IPAddresses: ips, - }, - }, - { - filename: "etc/origin/master/master.etcd-client", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: c.Master.Hostname}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - DNSNames: []string{c.Master.Hostname}, // TODO - IPAddresses: []net.IP{c.Master.IPs[0]}, // TODO - }, - signer: "etc/origin/master/master.etcd-ca", - }, - { - filename: "etc/origin/master/master.kubelet-client", - template: &x509.Certificate{ - Subject: pkix.Name{Organization: []string{"system:node-admins"}, CommonName: "system:openshift-node-admin"}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - }, - }, - { - filename: "etc/origin/master/master.proxy-client", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: "system:master-proxy"}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - }, - }, - { - filename: "etc/origin/master/master.server", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: c.Master.IPs[0].String()}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - DNSNames: dns, - IPAddresses: ips, - }, - }, - { - filename: "etc/origin/master/openshift-aggregator", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: "system:openshift-aggregator"}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - }, - signer: "etc/origin/master/frontproxy-ca", - }, - { - filename: "etc/origin/master/openshift-master", - template: &x509.Certificate{ - Subject: pkix.Name{Organization: []string{"system:masters", "system:openshift-master"}, CommonName: "system:openshift-master"}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - }, - }, - { - filename: "etc/origin/master/node-bootstrapper", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: "system:serviceaccount:openshift-infra:node-bootstrapper"}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - }, - }, - { - filename: "etc/origin/service-catalog/apiserver", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: "apiserver.kube-service-catalog"}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - DNSNames: []string{"apiserver.kube-service-catalog", "apiserver.kube-service-catalog.svc", "apiserver.kube-service-catalog.svc.cluster.local"}, - }, - signer: "etc/origin/service-catalog/ca", - }, - // TODO: registry cert - } - - for _, cert := range certs { - template := &x509.Certificate{ - SerialNumber: c.serial.Get(), - NotBefore: now, - NotAfter: now.AddDate(2, 0, 0), - KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, - BasicConstraintsValid: true, - } - template.Subject = cert.template.Subject - template.ExtKeyUsage = cert.template.ExtKeyUsage - template.DNSNames = cert.template.DNSNames - template.IPAddresses = cert.template.IPAddresses - - if cert.signer == "" { - cert.signer = "etc/origin/master/ca" - } - - certAndKey, err := newCertAndKey(cert.filename, template, c.cas[cert.signer].cert, c.cas[cert.signer].key, false, cert.filename == "etc/origin/master/master.etcd-client") - if err != nil { - return err - } - - c.Master.certs[cert.filename] = certAndKey - } - - etcdcerts := []struct { - filename string - template *x509.Certificate - signer string - }{ - { - filename: "etc/etcd/peer", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: c.Master.Hostname}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, - DNSNames: []string{c.Master.Hostname}, // TODO - IPAddresses: []net.IP{c.Master.IPs[0]}, // TODO - }, - signer: "etc/origin/master/master.etcd-ca", - }, - { - filename: "etc/etcd/server", - template: &x509.Certificate{ - Subject: pkix.Name{CommonName: c.Master.Hostname}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - DNSNames: []string{c.Master.Hostname}, // TODO - IPAddresses: []net.IP{c.Master.IPs[0]}, // TODO - }, - signer: "etc/origin/master/master.etcd-ca", - }, - } - - for _, cert := range etcdcerts { - template := &x509.Certificate{ - SerialNumber: c.serial.Get(), - NotBefore: now, - NotAfter: now.AddDate(5, 0, 0), - KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, - BasicConstraintsValid: true, - } - template.Subject = cert.template.Subject - template.ExtKeyUsage = cert.template.ExtKeyUsage - template.DNSNames = cert.template.DNSNames - template.IPAddresses = cert.template.IPAddresses - - certAndKey, err := newCertAndKey(cert.filename, template, c.cas[cert.signer].cert, c.cas[cert.signer].key, false, true) - if err != nil { - return err - } - - c.Master.etcdcerts[cert.filename] = certAndKey - } - - return nil -} - -// WriteMasterCerts writes the master certs -func (c *Config) WriteMasterCerts(fs filesystem.Writer) error { - for filename, ca := range c.cas { - err := writeCert(fs, fmt.Sprintf("%s.crt", filename), ca.cert) - if err != nil { - return err - } - - err = writePrivateKey(fs, fmt.Sprintf("%s.key", filename), ca.key) - if err != nil { - return err - } - } - - err := writeCert(fs, "etc/origin/master/ca-bundle.crt", c.cas["etc/origin/master/ca"].cert) - if err != nil { - return err - } - - err = writeCert(fs, "etc/origin/master/client-ca-bundle.crt", c.cas["etc/origin/master/ca"].cert) // TODO: confirm if needed - if err != nil { - return err - } - - err = writeCert(fs, "etc/etcd/ca.crt", c.cas["etc/origin/master/master.etcd-ca"].cert) - if err != nil { - return err - } - - for filename, cert := range c.Master.certs { - err := writeCert(fs, fmt.Sprintf("%s.crt", filename), cert.cert) - if err != nil { - return err - } - - err = writePrivateKey(fs, fmt.Sprintf("%s.key", filename), cert.key) - if err != nil { - return err - } - } - - for filename, cert := range c.Master.etcdcerts { - err := writeCert(fs, fmt.Sprintf("%s.crt", filename), cert.cert) - if err != nil { - return err - } - - err = writePrivateKey(fs, fmt.Sprintf("%s.key", filename), cert.key) - if err != nil { - return err - } - } - fname := "etc/origin/master/ca.serial.txt" - fi := GetFileInfo(fname) - return fs.WriteFile(fname, []byte(fmt.Sprintf("%02X\n", c.serial.Get())), fi) -} - -// WriteBootstrapCerts writes the node bootstrap certs -func (c *Config) WriteBootstrapCerts(fs filesystem.Writer) error { - err := writeCert(fs, "etc/origin/node/ca.crt", c.cas["etc/origin/master/ca"].cert) - if err != nil { - return err - } - - err = writeCert(fs, "etc/origin/node/node-bootstrapper.crt", c.Master.certs["etc/origin/master/node-bootstrapper"].cert) - if err != nil { - return err - } - - return writePrivateKey(fs, "etc/origin/node/node-bootstrapper.key", c.Master.certs["etc/origin/master/node-bootstrapper"].key) -} - -// WriteMasterKeypair writes the master service account keypair -func (c *Config) WriteMasterKeypair(fs filesystem.Writer) error { - key, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { - return err - } - - err = writePrivateKey(fs, "etc/origin/master/serviceaccounts.private.key", key) - if err != nil { - return err - } - - return writePublicKey(fs, "etc/origin/master/serviceaccounts.public.key", &key.PublicKey) -} - -func intsha1(n *big.Int) []byte { - h := sha1.New() - h.Write(n.Bytes()) - return h.Sum(nil) -} diff --git a/pkg/openshift/doc.go b/pkg/openshift/doc.go deleted file mode 100644 index 206f5206c4..0000000000 --- a/pkg/openshift/doc.go +++ /dev/null @@ -1,3 +0,0 @@ -// Package openshift provides utilities related -// to the OpenShift orchestrator. -package openshift diff --git a/pkg/openshift/examples_test.go b/pkg/openshift/examples_test.go deleted file mode 100644 index 4227dded72..0000000000 --- a/pkg/openshift/examples_test.go +++ /dev/null @@ -1,60 +0,0 @@ -package openshift - -import ( - "path" - "reflect" - "testing" - - "github.com/davecgh/go-spew/spew" - - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/i18n" -) - -func TestExamplesInSync(t *testing.T) { - baseExampleDir := "../../examples" - baseExample := "openshift.json" - - tests := []string{} - - locale, err := i18n.LoadTranslations() - if err != nil { - t.Fatalf("error loading translations %v", err) - } - - apiloader := &api.Apiloader{ - Translator: &i18n.Translator{ - Locale: locale, - }, - } - - baseExampleCS, _, err := apiloader.LoadContainerServiceFromFile( - path.Join(baseExampleDir, baseExample), - false, //don't validate - false, // not update - nil, - ) - if err != nil { - t.Fatalf("error parsing the api model: %s", err.Error()) - } - - for _, test := range tests { - testCS, _, err := apiloader.LoadContainerServiceFromFile( - path.Join(baseExampleDir, test), - false, - false, - nil, - ) - if err != nil { - t.Errorf("failed parsing %s: %#v", test, err) - continue - } - - // todo normalize where necessary (seems easier than reflect right now) - - if !reflect.DeepEqual(baseExampleCS.Properties, testCS.Properties) { - t.Errorf(spew.Sprintf("Testing %s\nExpected:\n%+v\nGot:\n%+v", test, baseExampleCS.Properties, testCS.Properties)) - } - } - -} diff --git a/pkg/openshift/filesystem/filesystem.go b/pkg/openshift/filesystem/filesystem.go deleted file mode 100644 index 44efa29ba5..0000000000 --- a/pkg/openshift/filesystem/filesystem.go +++ /dev/null @@ -1,221 +0,0 @@ -package filesystem - -import ( - "archive/tar" - "compress/gzip" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - "time" -) - -// Fileinfo is a struct that holds User, Group, and Mode -type Fileinfo struct { - User string - Group string - Mode os.FileMode -} - -// Closer implements Close() -type Closer interface { - Close() error -} - -// Reader provides read-related methods which are runnable on a bare filesystem -// or a tar.gz file -type Reader interface { - ReadFile(filename string) ([]byte, error) -} - -// Writer provides write-related methods which are runnable on a bare filesystem -// or a tar.gz file -type Writer interface { - Mkdir(filename string, fileInfo Fileinfo) error - WriteFile(filename string, data []byte, fileInfo Fileinfo) error -} - -// WriteCloser implements Writer and Closer -type WriteCloser interface { - Writer - Closer -} - -// Filesystem implements Reader, Writer and Closer -type Filesystem interface { - Reader - Writer - Closer -} - -type filesystem struct { - name string -} - -var _ Filesystem = &filesystem{} - -// NewFilesystem returns a Filesystem interface backed by a bare filesystem -func NewFilesystem(name string) (Filesystem, error) { - err := os.RemoveAll(name) - if err != nil { - return nil, err - } - - err = os.MkdirAll(name, 0777) - if err != nil { - return nil, err - } - - return &filesystem{name}, nil -} - -// Mkdir makes a directory. Note that it does not chown/chgrp as that would -// require elevated privileges -func (f *filesystem) Mkdir(name string, fileInfo Fileinfo) error { - return os.Mkdir(name, fileInfo.Mode) -} - -func (f *filesystem) mkdirAll(name string) error { - return os.MkdirAll(name, 0755) -} - -func (f *filesystem) WriteFile(filename string, data []byte, fileInfo Fileinfo) error { - filePath := filepath.Join(f.name, filename) - err := f.mkdirAll(filepath.Dir(filePath)) - if err != nil { - return err - } - - return ioutil.WriteFile(filePath, data, fileInfo.Mode) -} - -func (f *filesystem) ReadFile(filename string) ([]byte, error) { - return ioutil.ReadFile(filepath.Join(f.name, filename)) -} - -func (filesystem) Close() error { - return nil -} - -type tgzwriter struct { - gz *gzip.Writer - tw *tar.Writer - now time.Time - dirs map[string]struct{} -} - -var _ WriteCloser = &tgzwriter{} - -// NewTGZWriter returns a WriteCloser interface backed by a tar.gz file -func NewTGZWriter(w io.Writer) (WriteCloser, error) { - gz := gzip.NewWriter(w) - tw := &tgzwriter{ - gz: gz, - tw: tar.NewWriter(gz), - now: time.Now(), - dirs: map[string]struct{}{}, - } - return tw, nil -} - -func (t *tgzwriter) Mkdir(name string, fileInfo Fileinfo) error { - if _, exists := t.dirs[name]; exists { - return &os.PathError{Op: "mkdir", Path: name} - } - - err := t.tw.WriteHeader(&tar.Header{ - Name: name, - Mode: int64(fileInfo.Mode), - ModTime: t.now, - Typeflag: tar.TypeDir, - Uname: fileInfo.User, - Gname: fileInfo.Group, - }) - if err != nil { - return err - } - t.dirs[name] = struct{}{} - - return nil -} - -func (t *tgzwriter) mkdirAll(name string) error { - parts := strings.Split(name, "/") - for i := 1; i < len(parts); i++ { - name = filepath.Join(parts[:i]...) - if _, exists := t.dirs[name]; exists { - continue - } - - err := t.Mkdir(name, Fileinfo{Mode: 0755, User: "root", Group: "root"}) - if err != nil { - return err - } - } - return nil -} - -func (t *tgzwriter) WriteFile(filename string, data []byte, fileInfo Fileinfo) error { - err := t.mkdirAll(filepath.Dir(filename)) - if err != nil { - return err - } - - err = t.tw.WriteHeader(&tar.Header{ - Name: filename, - Mode: int64(fileInfo.Mode), - Size: int64(len(data)), - ModTime: t.now, - Typeflag: tar.TypeReg, - Uname: fileInfo.User, - Gname: fileInfo.Group, - }) - if err != nil { - return err - } - - _, err = t.tw.Write(data) - return err -} - -func (t *tgzwriter) Close() error { - err := t.tw.Close() - if err != nil { - return err - } - return t.gz.Close() -} - -type tgzreader struct { - r io.ReadSeeker -} - -var _ Reader = &tgzreader{} - -// NewTGZReader returns a Reader interface backed by a tar.gz file -func NewTGZReader(r io.ReadSeeker) (Reader, error) { - return &tgzreader{r: r}, nil -} - -func (t *tgzreader) ReadFile(filename string) ([]byte, error) { - _, err := t.r.Seek(0, io.SeekStart) - if err != nil { - return nil, err - } - gz, err := gzip.NewReader(t.r) - if err != nil { - return nil, err - } - tr := tar.NewReader(gz) - for { - h, err := tr.Next() - if err != nil { - return nil, err - } - - if h.Name == filename { - return ioutil.ReadAll(tr) - } - } -} diff --git a/translations/en_US/LC_MESSAGES/acsengine.mo b/pkg/openshift/translations/en_US/LC_MESSAGES/acsengine.mo similarity index 100% rename from translations/en_US/LC_MESSAGES/acsengine.mo rename to pkg/openshift/translations/en_US/LC_MESSAGES/acsengine.mo diff --git a/translations/en_US/LC_MESSAGES/acsengine.po b/pkg/openshift/translations/en_US/LC_MESSAGES/acsengine.po similarity index 100% rename from translations/en_US/LC_MESSAGES/acsengine.po rename to pkg/openshift/translations/en_US/LC_MESSAGES/acsengine.po diff --git a/pkg/operations/cordondrainvm.go b/pkg/operations/cordondrainvm.go index d37116003d..bff35394d0 100644 --- a/pkg/operations/cordondrainvm.go +++ b/pkg/operations/cordondrainvm.go @@ -4,7 +4,7 @@ import ( "strings" "time" - "github.com/Azure/acs-engine/pkg/armhelpers" + "github.com/Azure/aks-engine/pkg/armhelpers" "github.com/pkg/errors" log "github.com/sirupsen/logrus" "k8s.io/api/core/v1" @@ -31,7 +31,7 @@ type drainOperation struct { type podFilter func(v1.Pod) bool // SafelyDrainNode safely drains a node so that it can be deleted from the cluster -func SafelyDrainNode(az armhelpers.ACSEngineClient, logger *log.Entry, masterURL, kubeConfig, nodeName string, timeout time.Duration) error { +func SafelyDrainNode(az armhelpers.AKSEngineClient, logger *log.Entry, masterURL, kubeConfig, nodeName string, timeout time.Duration) error { //get client using kubeconfig client, err := az.GetKubernetesClient(masterURL, kubeConfig, interval, timeout) if err != nil { diff --git a/pkg/operations/cordondrainvm_test.go b/pkg/operations/cordondrainvm_test.go index 91ac82ee5c..d9c4ab2a35 100644 --- a/pkg/operations/cordondrainvm_test.go +++ b/pkg/operations/cordondrainvm_test.go @@ -3,7 +3,7 @@ package operations import ( "time" - "github.com/Azure/acs-engine/pkg/armhelpers" + "github.com/Azure/aks-engine/pkg/armhelpers" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/pkg/errors" @@ -14,17 +14,17 @@ import ( var _ = Describe("Safely Drain node operation tests", func() { It("Should return error messages for failure to create kubernetes client", func() { - err := SafelyDrainNode(&armhelpers.MockACSEngineClient{FailGetKubernetesClient: true}, log.NewEntry(log.New()), "http://bad.com/", "bad", "node", time.Minute) + err := SafelyDrainNode(&armhelpers.MockAKSEngineClient{FailGetKubernetesClient: true}, log.NewEntry(log.New()), "http://bad.com/", "bad", "node", time.Minute) Expect(err).Should(HaveOccurred()) }) It("Should return error messages for Failure to get node ", func() { - mockClient := &armhelpers.MockACSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} + mockClient := &armhelpers.MockAKSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} mockClient.MockKubernetesClient.FailGetNode = true err := SafelyDrainNode(mockClient, log.NewEntry(log.New()), "http://bad.com/", "bad", "node", time.Minute) Expect(err).Should(HaveOccurred()) }) It("Should retry on resource conflict when updating node ", func() { - mockClient := &armhelpers.MockACSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} + mockClient := &armhelpers.MockAKSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} i := 3 mockClient.MockKubernetesClient.UpdateNodeFunc = func(node *v1.Node) (*v1.Node, error) { if i > 0 { @@ -37,33 +37,33 @@ var _ = Describe("Safely Drain node operation tests", func() { Expect(err).ShouldNot(HaveOccurred()) }) It("Should return error messages for Failure to update node ", func() { - mockClient := &armhelpers.MockACSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} + mockClient := &armhelpers.MockAKSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} mockClient.MockKubernetesClient.FailUpdateNode = true err := SafelyDrainNode(mockClient, log.NewEntry(log.New()), "http://bad.com/", "bad", "node", time.Minute) Expect(err).Should(HaveOccurred()) }) It("Should return error messages for Failure to list pods ", func() { - mockClient := &armhelpers.MockACSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} + mockClient := &armhelpers.MockAKSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} mockClient.MockKubernetesClient.FailListPods = true err := SafelyDrainNode(mockClient, log.NewEntry(log.New()), "http://bad.com/", "bad", "node", time.Minute) Expect(err).Should(HaveOccurred()) }) It("Should return error messages for Failure to check support eviction ", func() { - mockClient := &armhelpers.MockACSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} + mockClient := &armhelpers.MockAKSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} mockClient.MockKubernetesClient.PodsList = &v1.PodList{Items: []v1.Pod{{}}} mockClient.MockKubernetesClient.FailSupportEviction = true err := SafelyDrainNode(mockClient, log.NewEntry(log.New()), "http://bad.com/", "bad", "node", time.Minute) Expect(err).Should(HaveOccurred()) }) It("Should return error messages for Failure to delete pod ", func() { - mockClient := &armhelpers.MockACSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} + mockClient := &armhelpers.MockAKSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} mockClient.MockKubernetesClient.PodsList = &v1.PodList{Items: []v1.Pod{{}}} mockClient.MockKubernetesClient.FailDeletePod = true err := SafelyDrainNode(mockClient, log.NewEntry(log.New()), "http://bad.com/", "bad", "node", time.Minute) Expect(err).Should(HaveOccurred()) }) It("Should return error messages for Failure to Evict Pod ", func() { - mockClient := &armhelpers.MockACSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} + mockClient := &armhelpers.MockAKSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} mockClient.MockKubernetesClient.PodsList = &v1.PodList{Items: []v1.Pod{{}}} mockClient.MockKubernetesClient.ShouldSupportEviction = true mockClient.MockKubernetesClient.FailEvictPod = true @@ -71,7 +71,7 @@ var _ = Describe("Safely Drain node operation tests", func() { Expect(err).Should(HaveOccurred()) }) It("Should return error messages for Failure to wait for delete in delete path ", func() { - mockClient := &armhelpers.MockACSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} + mockClient := &armhelpers.MockAKSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} mockClient.MockKubernetesClient.PodsList = &v1.PodList{Items: []v1.Pod{{}}} mockClient.MockKubernetesClient.ShouldSupportEviction = true mockClient.MockKubernetesClient.FailWaitForDelete = true @@ -79,7 +79,7 @@ var _ = Describe("Safely Drain node operation tests", func() { Expect(err).Should(HaveOccurred()) }) It("Should return error messages for Failure to wait for delete in eviction path ", func() { - mockClient := &armhelpers.MockACSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} + mockClient := &armhelpers.MockAKSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} mockClient.MockKubernetesClient.PodsList = &v1.PodList{Items: []v1.Pod{{}}} mockClient.MockKubernetesClient.ShouldSupportEviction = false mockClient.MockKubernetesClient.FailWaitForDelete = true @@ -87,14 +87,14 @@ var _ = Describe("Safely Drain node operation tests", func() { Expect(err).Should(HaveOccurred()) }) It("Should not return error in valid eviction path ", func() { - mockClient := &armhelpers.MockACSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} + mockClient := &armhelpers.MockAKSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} mockClient.MockKubernetesClient.PodsList = &v1.PodList{Items: []v1.Pod{{}}} mockClient.MockKubernetesClient.ShouldSupportEviction = true err := SafelyDrainNode(mockClient, log.NewEntry(log.New()), "http://bad.com/", "bad", "node", time.Minute) Expect(err).ShouldNot(HaveOccurred()) }) It("Should not return error in valid delete path ", func() { - mockClient := &armhelpers.MockACSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} + mockClient := &armhelpers.MockAKSEngineClient{MockKubernetesClient: &armhelpers.MockKubernetesClient{}} mockClient.MockKubernetesClient.PodsList = &v1.PodList{Items: []v1.Pod{{}}} mockClient.MockKubernetesClient.ShouldSupportEviction = false err := SafelyDrainNode(mockClient, log.NewEntry(log.New()), "http://bad.com/", "bad", "node", time.Minute) diff --git a/pkg/operations/dcosupgrade/upgradecluster.go b/pkg/operations/dcosupgrade/upgradecluster.go deleted file mode 100644 index 1ecfd7ecfd..0000000000 --- a/pkg/operations/dcosupgrade/upgradecluster.go +++ /dev/null @@ -1,50 +0,0 @@ -package dcosupgrade - -import ( - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/armhelpers" - "github.com/Azure/acs-engine/pkg/i18n" - uuid "github.com/satori/go.uuid" - "github.com/sirupsen/logrus" -) - -// ClusterTopology contains resources of the cluster the upgrade operation -// is targeting -type ClusterTopology struct { - DataModel *api.ContainerService - Location string - ResourceGroup string - CurrentDcosVersion string - NameSuffix string - SSHKey []byte -} - -// UpgradeCluster upgrades a cluster with Orchestrator version X.X to version Y.Y. -// Right now upgrades are supported for Kubernetes cluster only. -type UpgradeCluster struct { - Translator *i18n.Translator - Logger *logrus.Entry - ClusterTopology - Client armhelpers.ACSEngineClient -} - -// UpgradeCluster runs the workflow to upgrade a DCOS cluster. -func (uc *UpgradeCluster) UpgradeCluster(subscriptionID uuid.UUID, resourceGroup, currentDcosVersion string, - cs *api.ContainerService, nameSuffix string, sshKey []byte) error { - uc.ClusterTopology = ClusterTopology{} - uc.ResourceGroup = resourceGroup - uc.CurrentDcosVersion = currentDcosVersion - uc.DataModel = cs - uc.NameSuffix = nameSuffix - uc.SSHKey = sshKey - - upgradeVersion := uc.DataModel.Properties.OrchestratorProfile.OrchestratorVersion - uc.Logger.Infof("Upgrading DCOS from %s to %s", uc.CurrentDcosVersion, upgradeVersion) - - if err := uc.runUpgrade(); err != nil { - return err - } - - uc.Logger.Infof("Cluster upgraded successfully to DCOS %s", upgradeVersion) - return nil -} diff --git a/pkg/operations/dcosupgrade/upgrader.go b/pkg/operations/dcosupgrade/upgrader.go deleted file mode 100644 index 589b8ac70a..0000000000 --- a/pkg/operations/dcosupgrade/upgrader.go +++ /dev/null @@ -1,244 +0,0 @@ -package dcosupgrade - -import ( - "encoding/json" - "fmt" - "strings" - - "github.com/Azure/acs-engine/pkg/operations" - "github.com/pkg/errors" -) - -type nodeHealthReport struct { - IP string `json:"host_ip"` - Role string `json:"role"` - Health int `json:"health"` -} - -type healthReport struct { - Nodes []nodeHealthReport `json:"nodes"` -} - -var bootstrapUpgradeScript = `#!/bin/bash - -echo "Starting upgrade configuration" -if [ ! -e /opt/azure/dcos/upgrade/NEW_VERSION/upgrade_url ]; then - echo "Setting up bootstrap node" - rm -rf /opt/azure/dcos/upgrade/NEW_VERSION - mkdir -p /opt/azure/dcos/upgrade/NEW_VERSION/genconf - cp /opt/azure/dcos/genconf/config.yaml /opt/azure/dcos/genconf/ip-detect /opt/azure/dcos/upgrade/NEW_VERSION/genconf/ - cd /opt/azure/dcos/upgrade/NEW_VERSION/ - curl -s -O https://dcos-mirror.azureedge.net/dcos-NEW_DASHED_VERSION/dcos_generate_config.sh - bash dcos_generate_config.sh --generate-node-upgrade-script CURR_VERSION | tee /opt/azure/dcos/upgrade/NEW_VERSION/log - process=\$(docker ps -f ancestor=nginx -q) - if [ ! -z "\$process" ]; then - echo "Stopping nginx service \$process" - docker kill \$process - fi - echo "Starting nginx service \$process" - docker run -d -p 8086:80 -v \$PWD/genconf/serve:/usr/share/nginx/html:ro nginx - docker ps - grep 'Node upgrade script URL' /opt/azure/dcos/upgrade/NEW_VERSION/log | awk -F ': ' '{print \$2}' | cat > /opt/azure/dcos/upgrade/NEW_VERSION/upgrade_url -fi -upgrade_url=\$(cat /opt/azure/dcos/upgrade/NEW_VERSION/upgrade_url) -if [ -z \${upgrade_url} ]; then - rm -f /opt/azure/dcos/upgrade/NEW_VERSION/upgrade_url - echo "Failed to set up bootstrap node. Please try again" - exit 1 -else - echo "Setting up bootstrap node completed. Node upgrade script URL \${upgrade_url}" -fi -` - -var nodeUpgradeScript = `#!/bin/bash - -echo "Starting node upgrade" -mkdir -p /opt/azure/dcos/upgrade/NEW_VERSION -cd /opt/azure/dcos/upgrade/NEW_VERSION -curl -O UPGRADE_SCRIPT_URL -bash ./dcos_node_upgrade.sh - -` - -func (uc *UpgradeCluster) runUpgrade() error { - if uc.ClusterTopology.DataModel.Properties.OrchestratorProfile.DcosConfig == nil || - uc.ClusterTopology.DataModel.Properties.OrchestratorProfile.DcosConfig.BootstrapProfile == nil { - return errors.New("BootstrapProfile is not set") - } - - cs := uc.ClusterTopology.DataModel - newVersion := cs.Properties.OrchestratorProfile.OrchestratorVersion - dashedVersion := strings.Replace(newVersion, ".", "-", -1) - - masterDNS := cs.GetAzureProdFQDN() - masterCount := cs.Properties.MasterProfile.Count - bootstrapIP := cs.Properties.OrchestratorProfile.DcosConfig.BootstrapProfile.StaticIP - uc.Logger.Infof("masterDNS:%s masterCount:%d bootstrapIP:%s", masterDNS, masterCount, bootstrapIP) - - // copy SSH key to master - uc.Logger.Infof("Copy SSH key to master") - out, err := operations.RemoteRun("azureuser", masterDNS, 2200, uc.SSHKey, fmt.Sprintf("cat << END > .ssh/id_rsa_cluster\n%s\nEND\n", string(uc.SSHKey))) - if err != nil { - uc.Logger.Errorf(out) - return err - } - // set SSH key permissions - out, err = operations.RemoteRun("azureuser", masterDNS, 2200, uc.SSHKey, "chmod 600 .ssh/id_rsa_cluster") - if err != nil { - uc.Logger.Errorf(out) - return err - } - // upgrade bootstrap node - bootstrapScript := strings.Replace(bootstrapUpgradeScript, "CURR_VERSION", uc.CurrentDcosVersion, -1) - bootstrapScript = strings.Replace(bootstrapScript, "NEW_VERSION", newVersion, -1) - bootstrapScript = strings.Replace(bootstrapScript, "NEW_DASHED_VERSION", dashedVersion, -1) - - upgradeScriptURL, err := uc.upgradeBootstrapNode(masterDNS, bootstrapIP, bootstrapScript) - if err != nil { - return err - } - - nodeScript := strings.Replace(nodeUpgradeScript, "NEW_VERSION", newVersion, -1) - nodeScript = strings.Replace(nodeScript, "UPGRADE_SCRIPT_URL", upgradeScriptURL, -1) - - // upgrade master nodes - if err = uc.upgradeMasterNodes(masterDNS, masterCount, nodeScript); err != nil { - return err - } - - // get the node list - out, err = operations.RemoteRun("azureuser", masterDNS, 2200, uc.SSHKey, "curl -s http://localhost:1050/system/health/v1/nodes") - if err != nil { - uc.Logger.Errorf(out) - return err - } - uc.Logger.Info(out) - nodes := &healthReport{} - if err = json.Unmarshal([]byte(out), nodes); err != nil { - return err - } - // upgrade agent nodes - return uc.upgradeAgentNodes(masterDNS, nodes) -} - -func (uc *UpgradeCluster) upgradeBootstrapNode(masterDNS, bootstrapIP, bootstrapScript string) (string, error) { - // copy bootstrap script to master - uc.Logger.Infof("Copy bootstrap script to master") - out, err := operations.RemoteRun("azureuser", masterDNS, 2200, uc.SSHKey, fmt.Sprintf("cat << END > bootstrap_upgrade.sh\n%s\nEND\n", bootstrapScript)) - if err != nil { - uc.Logger.Errorf(out) - return "", err - } - // set script permissions - out, err = operations.RemoteRun("azureuser", masterDNS, 2200, uc.SSHKey, "chmod 755 ./bootstrap_upgrade.sh") - if err != nil { - uc.Logger.Errorf(out) - return "", err - } - // copy bootstrap script to the bootstrap node - uc.Logger.Infof("Copy bootstrap script to the bootstrap node") - cmd := fmt.Sprintf("scp -i .ssh/id_rsa_cluster -o ConnectTimeout=30 -o StrictHostKeyChecking=no bootstrap_upgrade.sh %s:", bootstrapIP) - out, err = operations.RemoteRun("azureuser", masterDNS, 2200, uc.SSHKey, cmd) - if err != nil { - uc.Logger.Errorf(out) - return "", err - } - // run bootstrap script - uc.Logger.Infof("Run bootstrap upgrade script") - cmd = fmt.Sprintf("ssh -i .ssh/id_rsa_cluster -o ConnectTimeout=30 -o StrictHostKeyChecking=no %s sudo ./bootstrap_upgrade.sh", bootstrapIP) - out, err = operations.RemoteRun("azureuser", masterDNS, 2200, uc.SSHKey, cmd) - if err != nil { - uc.Logger.Errorf(out) - return "", err - } - uc.Logger.Info(out) - // retrieve upgrade script URL - var url string - arr := strings.Split(out, "\n") - prefix := "Setting up bootstrap node completed. Node upgrade script URL" - for _, str := range arr { - if strings.HasPrefix(str, prefix) { - url = strings.TrimSpace(str[len(prefix):]) - break - } - } - if len(url) == 0 { - return "", errors.New("Undefined upgrade script URL") - } - return url, nil -} - -func (uc *UpgradeCluster) upgradeMasterNodes(masterDNS string, masterCount int, nodeScript string) error { - // run master upgrade script - catCmd := fmt.Sprintf("cat << END > node_upgrade.sh\n%s\nEND\n", nodeScript) - for i := 0; i < masterCount; i++ { - uc.Logger.Infof("Upgrading master node #%d", i+1) - // check current version - out, err := operations.RemoteRun("azureuser", masterDNS, 2200+i, uc.SSHKey, "grep version /opt/mesosphere/etc/dcos-version.json | cut -d '\"' -f 4") - if err != nil { - uc.Logger.Errorf(out) - return err - } - if strings.TrimSpace(out) == uc.ClusterTopology.DataModel.Properties.OrchestratorProfile.OrchestratorVersion { - uc.Logger.Infof("Master node is up-to-date. Skipping upgrade") - continue - } - // copy script to the node - out, err = operations.RemoteRun("azureuser", masterDNS, 2200+i, uc.SSHKey, catCmd) - if err != nil { - uc.Logger.Errorf(out) - return err - } - // set script permissions - out, err = operations.RemoteRun("azureuser", masterDNS, 2200+i, uc.SSHKey, "chmod 755 ./node_upgrade.sh") - if err != nil { - uc.Logger.Errorf(out) - return err - } - // run the script - out, err = operations.RemoteRun("azureuser", masterDNS, 2200+i, uc.SSHKey, "sudo ./node_upgrade.sh") - if err != nil { - uc.Logger.Errorf(out) - return err - } - uc.Logger.Info(out) - } - return nil -} - -func (uc *UpgradeCluster) upgradeAgentNodes(masterDNS string, nodes *healthReport) error { - for _, node := range nodes.Nodes { - if node.Role == "master" { - continue - } - uc.Logger.Infof("Upgrading %s %s", node.Role, node.IP) - - // check current version - cmd := fmt.Sprintf("ssh -i .ssh/id_rsa_cluster -o ConnectTimeout=30 -o StrictHostKeyChecking=no %s grep version /opt/mesosphere/etc/dcos-version.json | cut -d '\"' -f 4", node.IP) - out, err := operations.RemoteRun("azureuser", masterDNS, 2200, uc.SSHKey, cmd) - if err != nil { - uc.Logger.Errorf(out) - return err - } - if strings.TrimSpace(out) == uc.ClusterTopology.DataModel.Properties.OrchestratorProfile.OrchestratorVersion { - uc.Logger.Infof("Agent node is up-to-date. Skipping upgrade") - continue - } - // copy script to the node - cmd = fmt.Sprintf("scp -i .ssh/id_rsa_cluster -o ConnectTimeout=30 -o StrictHostKeyChecking=no node_upgrade.sh %s:", node.IP) - out, err = operations.RemoteRun("azureuser", masterDNS, 2200, uc.SSHKey, cmd) - if err != nil { - uc.Logger.Errorf(out) - return err - } - // run the script - cmd = fmt.Sprintf("ssh -i .ssh/id_rsa_cluster -o ConnectTimeout=30 -o StrictHostKeyChecking=no %s sudo ./node_upgrade.sh", node.IP) - out, err = operations.RemoteRun("azureuser", masterDNS, 2200, uc.SSHKey, cmd) - if err != nil { - uc.Logger.Errorf(out) - return err - } - uc.Logger.Info(out) - } - return nil -} diff --git a/pkg/operations/deletevm.go b/pkg/operations/deletevm.go index f4b21022f1..375a1e9574 100644 --- a/pkg/operations/deletevm.go +++ b/pkg/operations/deletevm.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/Azure/acs-engine/pkg/armhelpers" - "github.com/Azure/acs-engine/pkg/armhelpers/utils" + "github.com/Azure/aks-engine/pkg/armhelpers" + "github.com/Azure/aks-engine/pkg/armhelpers/utils" azStorage "github.com/Azure/azure-sdk-for-go/storage" "github.com/pkg/errors" log "github.com/sirupsen/logrus" @@ -17,7 +17,7 @@ const ( ) // CleanDeleteVirtualMachine deletes a VM and any associated OS disk -func CleanDeleteVirtualMachine(az armhelpers.ACSEngineClient, logger *log.Entry, subscriptionID, resourceGroup, name string) error { +func CleanDeleteVirtualMachine(az armhelpers.AKSEngineClient, logger *log.Entry, subscriptionID, resourceGroup, name string) error { ctx, cancel := context.WithTimeout(context.Background(), armhelpers.DefaultARMOperationTimeout) defer cancel() logger.Infof("fetching VM: %s/%s", resourceGroup, name) diff --git a/pkg/operations/kubernetesupgrade/upgradeagentnode.go b/pkg/operations/kubernetesupgrade/upgradeagentnode.go index 9b2de9b616..ffabe22c98 100644 --- a/pkg/operations/kubernetesupgrade/upgradeagentnode.go +++ b/pkg/operations/kubernetesupgrade/upgradeagentnode.go @@ -6,10 +6,10 @@ import ( "math/rand" "time" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/armhelpers" - "github.com/Azure/acs-engine/pkg/i18n" - "github.com/Azure/acs-engine/pkg/operations" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/armhelpers" + "github.com/Azure/aks-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/operations" "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -32,7 +32,7 @@ type UpgradeAgentNode struct { UpgradeContainerService *api.ContainerService SubscriptionID string ResourceGroup string - Client armhelpers.ACSEngineClient + Client armhelpers.AKSEngineClient kubeConfig string timeout time.Duration } diff --git a/pkg/operations/kubernetesupgrade/upgradecluster.go b/pkg/operations/kubernetesupgrade/upgradecluster.go index d9454cbc47..dc6f959af6 100644 --- a/pkg/operations/kubernetesupgrade/upgradecluster.go +++ b/pkg/operations/kubernetesupgrade/upgradecluster.go @@ -6,10 +6,10 @@ import ( "strings" "time" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/armhelpers" - "github.com/Azure/acs-engine/pkg/armhelpers/utils" - "github.com/Azure/acs-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/armhelpers" + "github.com/Azure/aks-engine/pkg/armhelpers/utils" + "github.com/Azure/aks-engine/pkg/i18n" "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-04-01/compute" "github.com/blang/semver" "github.com/pkg/errors" @@ -63,7 +63,7 @@ type UpgradeCluster struct { Translator *i18n.Translator Logger *logrus.Entry ClusterTopology - Client armhelpers.ACSEngineClient + Client armhelpers.AKSEngineClient StepTimeout *time.Duration } @@ -74,8 +74,8 @@ const MasterVMNamePrefix = "k8s-master-" const MasterPoolName = "master" // UpgradeCluster runs the workflow to upgrade a Kubernetes cluster. -func (uc *UpgradeCluster) UpgradeCluster(subscriptionID uuid.UUID, az armhelpers.ACSEngineClient, kubeConfig, resourceGroup string, - cs *api.ContainerService, nameSuffix string, agentPoolsToUpgrade []string, acsengineVersion string) error { +func (uc *UpgradeCluster) UpgradeCluster(subscriptionID uuid.UUID, az armhelpers.AKSEngineClient, kubeConfig, resourceGroup string, + cs *api.ContainerService, nameSuffix string, agentPoolsToUpgrade []string, aksengineVersion string) error { uc.ClusterTopology = ClusterTopology{} uc.SubscriptionID = subscriptionID.String() uc.ResourceGroup = resourceGroup @@ -101,17 +101,17 @@ func (uc *UpgradeCluster) UpgradeCluster(subscriptionID uuid.UUID, az armhelpers switch { case strings.HasPrefix(upgradeVersion, "1.6."): upgrader16 := &Kubernetes16upgrader{} - upgrader16.Init(uc.Translator, uc.Logger, uc.ClusterTopology, uc.Client, kubeConfig, uc.StepTimeout, acsengineVersion) + upgrader16.Init(uc.Translator, uc.Logger, uc.ClusterTopology, uc.Client, kubeConfig, uc.StepTimeout, aksengineVersion) upgrader = upgrader16 case strings.HasPrefix(upgradeVersion, "1.7."): upgrader17 := &Kubernetes17upgrader{} - upgrader17.Init(uc.Translator, uc.Logger, uc.ClusterTopology, uc.Client, kubeConfig, uc.StepTimeout, acsengineVersion) + upgrader17.Init(uc.Translator, uc.Logger, uc.ClusterTopology, uc.Client, kubeConfig, uc.StepTimeout, aksengineVersion) upgrader = upgrader17 case strings.HasPrefix(upgradeVersion, "1.8."): upgrader18 := &Kubernetes18upgrader{} - upgrader18.Init(uc.Translator, uc.Logger, uc.ClusterTopology, uc.Client, kubeConfig, uc.StepTimeout, acsengineVersion) + upgrader18.Init(uc.Translator, uc.Logger, uc.ClusterTopology, uc.Client, kubeConfig, uc.StepTimeout, aksengineVersion) upgrader = upgrader18 case strings.HasPrefix(upgradeVersion, "1.9."), @@ -120,7 +120,7 @@ func (uc *UpgradeCluster) UpgradeCluster(subscriptionID uuid.UUID, az armhelpers strings.HasPrefix(upgradeVersion, "1.12."), strings.HasPrefix(upgradeVersion, "1.13."): u := &Upgrader{} - u.Init(uc.Translator, uc.Logger, uc.ClusterTopology, uc.Client, kubeConfig, uc.StepTimeout, acsengineVersion) + u.Init(uc.Translator, uc.Logger, uc.ClusterTopology, uc.Client, kubeConfig, uc.StepTimeout, aksengineVersion) upgrader = u default: @@ -135,7 +135,7 @@ func (uc *UpgradeCluster) UpgradeCluster(subscriptionID uuid.UUID, az armhelpers return nil } -func (uc *UpgradeCluster) getClusterNodeStatus(subscriptionID uuid.UUID, az armhelpers.ACSEngineClient, resourceGroup, kubeConfig string) error { +func (uc *UpgradeCluster) getClusterNodeStatus(subscriptionID uuid.UUID, az armhelpers.AKSEngineClient, resourceGroup, kubeConfig string) error { targetOrchestratorTypeVersion := fmt.Sprintf("%s:%s", uc.DataModel.Properties.OrchestratorProfile.OrchestratorType, uc.DataModel.Properties.OrchestratorProfile.OrchestratorVersion) ctx, cancel := context.WithTimeout(context.Background(), armhelpers.DefaultARMOperationTimeout) @@ -397,16 +397,16 @@ func WriteTemplate( updatedTemplateJSON, _ := json.Marshal(templateMap) parametersJSON, _ := json.Marshal(parametersMap) - templateapp, err := acsengine.PrettyPrintArmTemplate(string(updatedTemplateJSON)) + templateapp, err := engine.PrettyPrintArmTemplate(string(updatedTemplateJSON)) if err != nil { logrus.Fatalf("error pretty printing template: %s \n", err.Error()) } - parametersapp, e := acsengine.PrettyPrintJSON(string(parametersJSON)) + parametersapp, e := engine.PrettyPrintJSON(string(parametersJSON)) if e != nil { logrus.Fatalf("error pretty printing template parameters: %s \n", e.Error()) } outputDirectory := path.Join("_output", upgradeContainerService.Properties.MasterProfile.DNSPrefix, "Upgrade") - writer := &acsengine.ArtifactWriter{ + writer := &engine.ArtifactWriter{ Translator: translator, } if err := writer.WriteTLSArtifacts(upgradeContainerService, "vlabs", templateapp, parametersapp, outputDirectory, false, false); err != nil { diff --git a/pkg/operations/kubernetesupgrade/upgradecluster_test.go b/pkg/operations/kubernetesupgrade/upgradecluster_test.go index 3dd2ef3759..fecc08fb4d 100644 --- a/pkg/operations/kubernetesupgrade/upgradecluster_test.go +++ b/pkg/operations/kubernetesupgrade/upgradecluster_test.go @@ -1,22 +1,21 @@ package kubernetesupgrade import ( + "fmt" "os" "testing" - "fmt" - - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/armhelpers" - "github.com/Azure/acs-engine/pkg/i18n" - . "github.com/Azure/acs-engine/pkg/test" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/armhelpers" + "github.com/Azure/aks-engine/pkg/i18n" + . "github.com/Azure/aks-engine/pkg/test" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/satori/go.uuid" log "github.com/sirupsen/logrus" ) -const TestACSEngineVersion = "1.0.0" +const TestAKSEngineVersion = "1.0.0" func TestUpgradeCluster(t *testing.T) { RunSpecsWithReporters(t, "kubernetesupgrade", "Server Suite") @@ -35,13 +34,13 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() { Logger: log.NewEntry(log.New()), } - mockClient := armhelpers.MockACSEngineClient{} + mockClient := armhelpers.MockAKSEngineClient{} mockClient.FailListVirtualMachinesTags = true uc.Client = &mockClient subID, _ := uuid.FromString("DEC923E3-1EF1-4745-9516-37906D56DEC4") - err := uc.UpgradeCluster(subID, &mockClient, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestACSEngineVersion) + err := uc.UpgradeCluster(subID, &mockClient, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestAKSEngineVersion) Expect(err).To(BeNil()) Expect(uc.ClusterTopology.AgentPools).NotTo(BeEmpty()) @@ -56,13 +55,13 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() { Logger: log.NewEntry(log.New()), } - mockClient := armhelpers.MockACSEngineClient{} + mockClient := armhelpers.MockAKSEngineClient{} mockClient.FailListVirtualMachines = true uc.Client = &mockClient subID, _ := uuid.FromString("DEC923E3-1EF1-4745-9516-37906D56DEC4") - err := uc.UpgradeCluster(subID, nil, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestACSEngineVersion) + err := uc.UpgradeCluster(subID, nil, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestAKSEngineVersion) Expect(err).NotTo(BeNil()) Expect(err.Error()).To(Equal("Error while querying ARM for resources: ListVirtualMachines failed")) @@ -77,13 +76,13 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() { Logger: log.NewEntry(log.New()), } - mockClient := armhelpers.MockACSEngineClient{} + mockClient := armhelpers.MockAKSEngineClient{} mockClient.FailDeleteVirtualMachine = true uc.Client = &mockClient subID, _ := uuid.FromString("DEC923E3-1EF1-4745-9516-37906D56DEC4") - err := uc.UpgradeCluster(subID, nil, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestACSEngineVersion) + err := uc.UpgradeCluster(subID, nil, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestAKSEngineVersion) Expect(err).NotTo(BeNil()) Expect(err.Error()).To(Equal("DeleteVirtualMachine failed")) }) @@ -95,13 +94,13 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() { Logger: log.NewEntry(log.New()), } - mockClient := armhelpers.MockACSEngineClient{} + mockClient := armhelpers.MockAKSEngineClient{} mockClient.FailDeployTemplate = true uc.Client = &mockClient subID, _ := uuid.FromString("DEC923E3-1EF1-4745-9516-37906D56DEC4") - err := uc.UpgradeCluster(subID, nil, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestACSEngineVersion) + err := uc.UpgradeCluster(subID, nil, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestAKSEngineVersion) Expect(err).NotTo(BeNil()) Expect(err.Error()).To(Equal("DeployTemplate failed")) }) @@ -113,13 +112,13 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() { Logger: log.NewEntry(log.New()), } - mockClient := armhelpers.MockACSEngineClient{} + mockClient := armhelpers.MockAKSEngineClient{} mockClient.FailGetVirtualMachine = true uc.Client = &mockClient subID, _ := uuid.FromString("DEC923E3-1EF1-4745-9516-37906D56DEC4") - err := uc.UpgradeCluster(subID, nil, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestACSEngineVersion) + err := uc.UpgradeCluster(subID, nil, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestAKSEngineVersion) Expect(err).NotTo(BeNil()) Expect(err.Error()).To(Equal("GetVirtualMachine failed")) }) @@ -131,13 +130,13 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() { Logger: log.NewEntry(log.New()), } - mockClient := armhelpers.MockACSEngineClient{} + mockClient := armhelpers.MockAKSEngineClient{} mockClient.FailGetStorageClient = true uc.Client = &mockClient subID, _ := uuid.FromString("DEC923E3-1EF1-4745-9516-37906D56DEC4") - err := uc.UpgradeCluster(subID, nil, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestACSEngineVersion) + err := uc.UpgradeCluster(subID, nil, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestAKSEngineVersion) Expect(err).NotTo(BeNil()) Expect(err.Error()).To(Equal("GetStorageClient failed")) }) @@ -149,13 +148,13 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() { Logger: log.NewEntry(log.New()), } - mockClient := armhelpers.MockACSEngineClient{} + mockClient := armhelpers.MockAKSEngineClient{} mockClient.FailDeleteNetworkInterface = true uc.Client = &mockClient subID, _ := uuid.FromString("DEC923E3-1EF1-4745-9516-37906D56DEC4") - err := uc.UpgradeCluster(subID, nil, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestACSEngineVersion) + err := uc.UpgradeCluster(subID, nil, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestAKSEngineVersion) Expect(err).NotTo(BeNil()) Expect(err.Error()).To(Equal("DeleteNetworkInterface failed")) }) @@ -167,12 +166,12 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() { Logger: log.NewEntry(log.New()), } - mockClient := armhelpers.MockACSEngineClient{} + mockClient := armhelpers.MockAKSEngineClient{} uc.Client = &mockClient subID, _ := uuid.FromString("DEC923E3-1EF1-4745-9516-37906D56DEC4") - err := uc.UpgradeCluster(subID, nil, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestACSEngineVersion) + err := uc.UpgradeCluster(subID, nil, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestAKSEngineVersion) Expect(err).NotTo(BeNil()) fmt.Print("GOT : ", err.Error()) Expect(err.Error()).To(ContainSubstring("Error while querying ARM for resources: Kubernetes:1.7.9 cannot be upgraded to 1.7.0")) @@ -187,14 +186,14 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() { Logger: log.NewEntry(log.New()), } - mockClient := armhelpers.MockACSEngineClient{} + mockClient := armhelpers.MockAKSEngineClient{} mockClient.FailDeleteRoleAssignment = true mockClient.ShouldSupportVMIdentity = true uc.Client = &mockClient subID, _ := uuid.FromString("DEC923E3-1EF1-4745-9516-37906D56DEC4") - err := uc.UpgradeCluster(subID, nil, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestACSEngineVersion) + err := uc.UpgradeCluster(subID, nil, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestAKSEngineVersion) Expect(err).NotTo(BeNil()) Expect(err.Error()).To(Equal("DeleteRoleAssignmentByID failed")) }) @@ -208,12 +207,12 @@ var _ = Describe("Upgrade Kubernetes cluster tests", func() { Logger: log.NewEntry(log.New()), } - mockClient := armhelpers.MockACSEngineClient{} + mockClient := armhelpers.MockAKSEngineClient{} uc.Client = &mockClient subID, _ := uuid.FromString("DEC923E3-1EF1-4745-9516-37906D56DEC4") - err := uc.UpgradeCluster(subID, nil, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestACSEngineVersion) + err := uc.UpgradeCluster(subID, nil, "kubeConfig", "TestRg", cs, "12345678", []string{"agentpool1"}, TestAKSEngineVersion) Expect(err).To(BeNil()) }) }) diff --git a/pkg/operations/kubernetesupgrade/upgrademasternode.go b/pkg/operations/kubernetesupgrade/upgrademasternode.go index 4d17c2195e..8128edc1f5 100644 --- a/pkg/operations/kubernetesupgrade/upgrademasternode.go +++ b/pkg/operations/kubernetesupgrade/upgrademasternode.go @@ -6,10 +6,10 @@ import ( "math/rand" "time" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/armhelpers" - "github.com/Azure/acs-engine/pkg/i18n" - "github.com/Azure/acs-engine/pkg/operations" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/armhelpers" + "github.com/Azure/aks-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/operations" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -26,7 +26,7 @@ type UpgradeMasterNode struct { UpgradeContainerService *api.ContainerService SubscriptionID string ResourceGroup string - Client armhelpers.ACSEngineClient + Client armhelpers.AKSEngineClient kubeConfig string timeout time.Duration } diff --git a/pkg/operations/kubernetesupgrade/upgrader.go b/pkg/operations/kubernetesupgrade/upgrader.go index 181ac3f895..e1c1fb2933 100644 --- a/pkg/operations/kubernetesupgrade/upgrader.go +++ b/pkg/operations/kubernetesupgrade/upgrader.go @@ -7,26 +7,26 @@ import ( "math/rand" "time" - "github.com/Azure/acs-engine/pkg/acsengine" - "github.com/Azure/acs-engine/pkg/acsengine/transform" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/armhelpers" - "github.com/Azure/acs-engine/pkg/armhelpers/utils" - "github.com/Azure/acs-engine/pkg/i18n" - "github.com/Azure/acs-engine/pkg/operations" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/armhelpers" + "github.com/Azure/aks-engine/pkg/armhelpers/utils" + "github.com/Azure/aks-engine/pkg/engine" + "github.com/Azure/aks-engine/pkg/engine/transform" + "github.com/Azure/aks-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/operations" "github.com/sirupsen/logrus" "k8s.io/api/core/v1" ) -// Upgrader holds information on upgrading an ACS cluster +// Upgrader holds information on upgrading an AKS cluster type Upgrader struct { Translator *i18n.Translator logger *logrus.Entry ClusterTopology - Client armhelpers.ACSEngineClient + Client armhelpers.AKSEngineClient kubeConfig string stepTimeout *time.Duration - ACSEngineVersion string + AKSEngineVersion string } type vmStatus int @@ -44,14 +44,14 @@ type vmInfo struct { } // Init initializes an upgrader struct -func (ku *Upgrader) Init(translator *i18n.Translator, logger *logrus.Entry, clusterTopology ClusterTopology, client armhelpers.ACSEngineClient, kubeConfig string, stepTimeout *time.Duration, acsEngineVersion string) { +func (ku *Upgrader) Init(translator *i18n.Translator, logger *logrus.Entry, clusterTopology ClusterTopology, client armhelpers.AKSEngineClient, kubeConfig string, stepTimeout *time.Duration, AKSEngineVersion string) { ku.Translator = translator ku.logger = logger ku.ClusterTopology = clusterTopology ku.Client = client ku.kubeConfig = kubeConfig ku.stepTimeout = stepTimeout - ku.ACSEngineVersion = acsEngineVersion + ku.AKSEngineVersion = AKSEngineVersion } // RunUpgrade runs the upgrade pipeline @@ -80,7 +80,7 @@ func (ku *Upgrader) upgradeMasterNodes(ctx context.Context) error { } ku.logger.Infof("Master nodes StorageProfile: %s", ku.ClusterTopology.DataModel.Properties.MasterProfile.StorageProfile) // Upgrade Master VMs - templateMap, parametersMap, err := ku.generateUpgradeTemplate(ku.ClusterTopology.DataModel, ku.ACSEngineVersion) + templateMap, parametersMap, err := ku.generateUpgradeTemplate(ku.ClusterTopology.DataModel, ku.AKSEngineVersion) if err != nil { return ku.Translator.Errorf("error generating upgrade template: %s", err.Error()) } @@ -204,7 +204,7 @@ func (ku *Upgrader) upgradeMasterNodes(ctx context.Context) error { func (ku *Upgrader) upgradeAgentPools(ctx context.Context) error { for _, agentPool := range ku.ClusterTopology.AgentPools { // Upgrade Agent VMs - templateMap, parametersMap, err := ku.generateUpgradeTemplate(ku.ClusterTopology.DataModel, ku.ACSEngineVersion) + templateMap, parametersMap, err := ku.generateUpgradeTemplate(ku.ClusterTopology.DataModel, ku.AKSEngineVersion) if err != nil { ku.logger.Errorf("Error generating upgrade template: %v", err) return ku.Translator.Errorf("Error generating upgrade template: %s", err.Error()) @@ -390,7 +390,7 @@ func (ku *Upgrader) upgradeAgentScaleSets(ctx context.Context) error { // need to apply the ARM template with target Kubernetes version to the VMSS first in order that the new VMSS instances // created can get the expected Kubernetes version. Otherwise the new instances created still have old Kubernetes version // if the topology doesn't have master nodes (so there are no ARM deployments in previous upgradeMasterNodes step) - templateMap, parametersMap, err := ku.generateUpgradeTemplate(ku.ClusterTopology.DataModel, ku.ACSEngineVersion) + templateMap, parametersMap, err := ku.generateUpgradeTemplate(ku.ClusterTopology.DataModel, ku.AKSEngineVersion) if err != nil { ku.logger.Errorf("error generating upgrade template in upgradeAgentScaleSets: %v", err) return err @@ -521,12 +521,12 @@ func (ku *Upgrader) upgradeAgentScaleSets(ctx context.Context) error { return nil } -func (ku *Upgrader) generateUpgradeTemplate(upgradeContainerService *api.ContainerService, acsengineVersion string) (map[string]interface{}, map[string]interface{}, error) { +func (ku *Upgrader) generateUpgradeTemplate(upgradeContainerService *api.ContainerService, aksengineVersion string) (map[string]interface{}, map[string]interface{}, error) { var err error - ctx := acsengine.Context{ + ctx := engine.Context{ Translator: ku.Translator, } - templateGenerator, err := acsengine.InitializeTemplateGenerator(ctx) + templateGenerator, err := engine.InitializeTemplateGenerator(ctx) if err != nil { return nil, nil, ku.Translator.Errorf("failed to initialize template generator: %s", err.Error()) } @@ -539,7 +539,7 @@ func (ku *Upgrader) generateUpgradeTemplate(upgradeContainerService *api.Contain var templateJSON string var parametersJSON string - if templateJSON, parametersJSON, err = templateGenerator.GenerateTemplate(upgradeContainerService, acsengine.DefaultGeneratorCode, acsengineVersion); err != nil { + if templateJSON, parametersJSON, err = templateGenerator.GenerateTemplate(upgradeContainerService, engine.DefaultGeneratorCode, aksengineVersion); err != nil { return nil, nil, ku.Translator.Errorf("error generating upgrade template: %s", err.Error()) } diff --git a/pkg/operations/scaledownagentpool.go b/pkg/operations/scaledownagentpool.go index 83f892d3bc..7fb604c83e 100644 --- a/pkg/operations/scaledownagentpool.go +++ b/pkg/operations/scaledownagentpool.go @@ -3,7 +3,7 @@ package operations import ( "container/list" - "github.com/Azure/acs-engine/pkg/armhelpers" + "github.com/Azure/aks-engine/pkg/armhelpers" log "github.com/sirupsen/logrus" ) @@ -15,7 +15,7 @@ type VMScalingErrorDetails struct { // ScaleDownVMs removes the vms in the provided list. Returns a list with details on each failure. // all items in the list will always be of type *VMScalingErrorDetails -func ScaleDownVMs(az armhelpers.ACSEngineClient, logger *log.Entry, subscriptionID string, resourceGroup string, vmNames ...string) *list.List { +func ScaleDownVMs(az armhelpers.AKSEngineClient, logger *log.Entry, subscriptionID string, resourceGroup string, vmNames ...string) *list.List { numVmsToDelete := len(vmNames) errChan := make(chan *VMScalingErrorDetails, numVmsToDelete) defer close(errChan) diff --git a/pkg/operations/scaledownagentpool_test.go b/pkg/operations/scaledownagentpool_test.go index 5aa92be2b0..10bed38877 100644 --- a/pkg/operations/scaledownagentpool_test.go +++ b/pkg/operations/scaledownagentpool_test.go @@ -3,8 +3,8 @@ package operations import ( "testing" - "github.com/Azure/acs-engine/pkg/armhelpers" - . "github.com/Azure/acs-engine/pkg/test" + "github.com/Azure/aks-engine/pkg/armhelpers" + . "github.com/Azure/aks-engine/pkg/test" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" log "github.com/sirupsen/logrus" @@ -16,7 +16,7 @@ func TestOperations(t *testing.T) { var _ = Describe("Scale down vms operation tests", func() { It("Should return error messages for failing vms", func() { - mockClient := armhelpers.MockACSEngineClient{} + mockClient := armhelpers.MockAKSEngineClient{} mockClient.FailGetVirtualMachine = true errs := ScaleDownVMs(&mockClient, log.NewEntry(log.New()), "sid", "rg", "vm1", "vm2", "vm3", "vm5") Expect(errs.Len()).To(Equal(4)) @@ -27,7 +27,7 @@ var _ = Describe("Scale down vms operation tests", func() { } }) It("Should return nil for errors if all deletes successful", func() { - mockClient := armhelpers.MockACSEngineClient{} + mockClient := armhelpers.MockAKSEngineClient{} errs := ScaleDownVMs(&mockClient, log.NewEntry(log.New()), "sid", "rg", "k8s-agent-F8EADCCF-0", "k8s-agent-F8EADCCF-3", "k8s-agent-F8EADCCF-2", "k8s-agent-F8EADCCF-4") Expect(errs).To(BeNil()) }) diff --git a/releases/Dockerfile.linux b/releases/Dockerfile.linux index 7f7ceda216..e8df76f54a 100644 --- a/releases/Dockerfile.linux +++ b/releases/Dockerfile.linux @@ -1,34 +1,34 @@ FROM alpine:3.7 -ARG ACSENGINE_VERSION=0.16.0 +ARG AKSENGINE_VERSION=0.16.0 ARG BUILD_DATE # Metadata as defined at http://label-schema.org LABEL maintainer="Microsoft" \ org.label-schema.schema-version="1.0" \ org.label-schema.vendor="Microsoft" \ - org.label-schema.name="Azure Container Service Engine (acs-engine)" \ - org.label-schema.version=$ACSENGINE_VERSION \ + org.label-schema.name="Azure Kubernetes Service Engine (aks-engine)" \ + org.label-schema.version=$AKSENGINE_VERSION \ org.label-schema.license="MIT" \ - org.label-schema.description="The Azure Container Service Engine (acs-engine) generates ARM (Azure Resource Manager) templates for Docker enabled clusters on Microsoft Azure with your choice of DCOS, Kubernetes, or Swarm orchestrators." \ - org.label-schema.url="https://github.com/Azure/acs-engine" \ - org.label-schema.usage="https://github.com/Azure/acs-engine/blob/master/docs/acsengine.md" \ + org.label-schema.description="The Azure Kubernetes Service Engine (aks-engine) generates ARM (Azure Resource Manager) templates for Kubernetes clusters on Microsoft Azure." \ + org.label-schema.url="https://github.com/Azure/aks-engine" \ + org.label-schema.usage="https://github.com/Azure/aks-engine/blob/master/docs/aksengine.md" \ org.label-schema.build-date=$BUILD_DATE \ - org.label-schema.vcs-url="https://github.com/Azure/acs-engine.git" \ - org.label-schema.docker.cmd="docker run -v \${PWD}:/acs-engine/workspace -it --rm microsoft/acs-engine:$ACSENGINE_VERSION" + org.label-schema.vcs-url="https://github.com/Azure/aks-engine.git" \ + org.label-schema.docker.cmd="docker run -v \${PWD}:/aks-engine/workspace -it --rm microsoft/aks-engine:$AKSENGINE_VERSION" RUN apk add --no-cache ca-certificates -ADD "https://github.com/Azure/acs-engine/releases/download/v${ACSENGINE_VERSION}/acs-engine-v${ACSENGINE_VERSION}-linux-amd64.tar.gz" /tmp/acs-engine.tgz +ADD "https://github.com/Azure/aks-engine/releases/download/v${AKSENGINE_VERSION}/aks-engine-v${AKSENGINE_VERSION}-linux-amd64.tar.gz" /tmp/aks-engine.tgz RUN mkdir /opt/ && \ - tar xvzf /tmp/acs-engine.tgz -C /opt/ && \ - rm /tmp/acs-engine.tgz && \ - chown -R root:root /opt/acs-engine-v${ACSENGINE_VERSION}-linux-amd64 && \ - ln -s /opt/acs-engine-v${ACSENGINE_VERSION}-linux-amd64/acs-engine /usr/local/bin/acs-engine && \ - chmod +x /usr/local/bin/acs-engine + tar xvzf /tmp/aks-engine.tgz -C /opt/ && \ + rm /tmp/aks-engine.tgz && \ + chown -R root:root /opt/aks-engine-v${AKSENGINE_VERSION}-linux-amd64 && \ + ln -s /opt/aks-engine-v${AKSENGINE_VERSION}-linux-amd64/aks-engine /usr/local/bin/aks-engine && \ + chmod +x /usr/local/bin/aks-engine -WORKDIR /acs-engine/workspace +WORKDIR /aks-engine/workspace -ENTRYPOINT [ "acs-engine" ] +ENTRYPOINT [ "aks-engine" ] CMD [ "--help" ] diff --git a/releases/README.Dockerfile.md b/releases/README.Dockerfile.md index c1ef3fdd19..042ab71fef 100644 --- a/releases/README.Dockerfile.md +++ b/releases/README.Dockerfile.md @@ -3,30 +3,30 @@ **Bash** ```bash $ VERSION=0.16.0 -$ docker build --no-cache --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` --build-arg ACSENGINE_VERSION="$VERSION" -t microsoft/acs-engine:$VERSION --file ./Dockerfile.linux . +$ docker build --no-cache --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` --build-arg AKSENGINE_VERSION="$VERSION" -t microsoft/aks-engine:$VERSION --file ./Dockerfile.linux . ``` **PowerShell** ```powershell PS> $VERSION="0.16.0" -PS> docker build --no-cache --build-arg BUILD_DATE=$(Get-Date((Get-Date).ToUniversalTime()) -UFormat "%Y-%m-%dT%H:%M:%SZ") --build-arg ACSENGINE_VERSION="$VERSION" -t microsoft/acs-engine:$VERSION --file .\Dockerfile.linux . +PS> docker build --no-cache --build-arg BUILD_DATE=$(Get-Date((Get-Date).ToUniversalTime()) -UFormat "%Y-%m-%dT%H:%M:%SZ") --build-arg AKSENGINE_VERSION="$VERSION" -t microsoft/aks-engine:$VERSION --file .\Dockerfile.linux . ``` # Inspect Docker image metadata **Bash** ```bash -$ docker image inspect microsoft/acs-engine:0.16.0 --format "{{json .Config.Labels}}" | jq +$ docker image inspect microsoft/aks-engine:0.16.0 --format "{{json .Config.Labels}}" | jq { "maintainer": "Microsoft", "org.label-schema.build-date": "2017-10-25T04:35:06Z", - "org.label-schema.description": "The Azure Container Service Engine (acs-engine) generates ARM (Azure Resource Manager) templates for Docker enabled clusters on Microsoft Azure with your choice of DCOS, Kubernetes, or Swarm orchestrators.", - "org.label-schema.docker.cmd": "docker run -v ${PWD}:/acs-engine/workspace -it --rm microsoft/acs-engine:0.16.0", + "org.label-schema.description": "The Azure Kubernetes Service Engine (aks-engine) generates ARM (Azure Resource Manager) templates for Kubernetes clusters on Microsoft Azure.", + "org.label-schema.docker.cmd": "docker run -v ${PWD}:/aks-engine/workspace -it --rm microsoft/aks-engine:0.16.0", "org.label-schema.license": "MIT", - "org.label-schema.name": "Azure Container Service Engine (acs-engine)", + "org.label-schema.name": "Azure Kubernetes Service Engine (aks-engine)", "org.label-schema.schema-version": "1.0", - "org.label-schema.url": "https://github.com/Azure/acs-engine", - "org.label-schema.usage": "https://github.com/Azure/acs-engine/blob/master/docs/acsengine.md", - "org.label-schema.vcs-url": "https://github.com/Azure/acs-engine.git", + "org.label-schema.url": "https://github.com/Azure/aks-engine", + "org.label-schema.usage": "https://github.com/Azure/aks-engine/blob/master/docs/aksengine.md", + "org.label-schema.vcs-url": "https://github.com/Azure/aks-engine.git", "org.label-schema.vendor": "Microsoft", "org.label-schema.version": "0.16.0" } @@ -34,18 +34,18 @@ $ docker image inspect microsoft/acs-engine:0.16.0 --format "{{json .Config.Labe **PowerShell** ```powershell -PS> docker image inspect microsoft/acs-engine:0.16.0 --format "{{json .Config.Labels}}" | ConvertFrom-Json | ConvertTo-Json +PS> docker image inspect microsoft/aks-engine:0.16.0 --format "{{json .Config.Labels}}" | ConvertFrom-Json | ConvertTo-Json { "maintainer": "Microsoft", "org.label-schema.build-date": "2017-10-25T04:35:06Z", - "org.label-schema.description": "The Azure Container Service Engine (acs-engine) generates ARM (Azure Resource Manager) templates for Docker enabled clusters on Microsoft Azure with your choice of DCOS, Kubernetes, or Swarm orchestrators.", - "org.label-schema.docker.cmd": "docker run -v ${PWD}:/acs-engine/workspace -it --rm microsoft/acs-engine:0.16.0", + "org.label-schema.description": "The Azure Kubernetes Service Engine (aks-engine) generates ARM (Azure Resource Manager) templates for Kubernetes clusters on Microsoft Azure.", + "org.label-schema.docker.cmd": "docker run -v ${PWD}:/aks-engine/workspace -it --rm microsoft/aks-engine:0.16.0", "org.label-schema.license": "MIT", - "org.label-schema.name": "Azure Container Service Engine (acs-engine)", + "org.label-schema.name": "Azure Kubernetes Service Engine (aks-engine)", "org.label-schema.schema-version": "1.0", - "org.label-schema.url": "https://github.com/Azure/acs-engine", - "org.label-schema.usage": "https://github.com/Azure/acs-engine/blob/master/docs/acsengine.md", - "org.label-schema.vcs-url": "https://github.com/Azure/acs-engine.git", + "org.label-schema.url": "https://github.com/Azure/aks-engine", + "org.label-schema.usage": "https://github.com/Azure/aks-engine/blob/master/docs/aksengine.md", + "org.label-schema.vcs-url": "https://github.com/Azure/aks-engine.git", "org.label-schema.vendor": "Microsoft", "org.label-schema.version": "0.16.0" } @@ -54,5 +54,5 @@ PS> docker image inspect microsoft/acs-engine:0.16.0 --format "{{json .Config.La # Run Docker image ``` -$ docker run -v ${PWD}:/acs-engine/workspace -it --rm microsoft/acs-engine:0.16.0 +$ docker run -v ${PWD}:/aks-engine/workspace -it --rm microsoft/aks-engine:0.16.0 ``` diff --git a/scripts/build-windows-k8s.sh b/scripts/build-windows-k8s.sh index 8c88453f0b..da2b4345ab 100755 --- a/scripts/build-windows-k8s.sh +++ b/scripts/build-windows-k8s.sh @@ -9,12 +9,12 @@ fetch_k8s() { } set_git_config() { - git config user.name "ACS CI" + git config user.name "AKS CI" git config user.email "containers@microsoft.com" } create_version_branch() { - git checkout -b ${ACS_BRANCH_NAME} ${KUBERNETES_TAG_BRANCH} || true + git checkout -b ${AKS_BRANCH_NAME} ${KUBERNETES_TAG_BRANCH} || true } version_lt() { @@ -212,7 +212,7 @@ k8s_18_cherry_pick() { fi } -apply_acs_cherry_picks() { +apply_aks_cherry_picks() { if [ "${KUBERNETES_RELEASE}" == "1.6" ]; then k8s_16_cherry_pick elif [ "${KUBERNETES_RELEASE}" == "1.7" ]; then @@ -262,7 +262,7 @@ get_kube_binaries() { fetch_k8s set_git_config create_version_branch - apply_acs_cherry_picks + apply_aks_cherry_picks # Due to what appears to be a bug in the Kubernetes Windows build system, one # has to first build a linux binary to generate _output/bin/deepcopy-gen. @@ -316,42 +316,42 @@ download_wincni() { } copy_dockerfile() { - cp ${ACS_ENGINE_HOME}/windows/Dockerfile ${DIST_DIR} + cp ${AKS_ENGINE_HOME}/windows/Dockerfile ${DIST_DIR} } create_zip() { - ZIP_NAME="${k8s_e2e_upstream_version:-"v${ACS_VERSION}int.zip"}" + ZIP_NAME="${k8s_e2e_upstream_version:-"v${AKS_VERSION}int.zip"}" cd ${DIST_DIR}/.. zip -r ../${ZIP_NAME} k/* cd - } upload_zip_to_blob_storage() { - az storage blob upload -f ${TOP_DIR}/../v${ACS_VERSION}int.zip -c ${AZURE_STORAGE_CONTAINER_NAME} -n v${ACS_VERSION}int.zip + az storage blob upload -f ${TOP_DIR}/../v${AKS_VERSION}int.zip -c ${AZURE_STORAGE_CONTAINER_NAME} -n v${AKS_VERSION}int.zip } -push_acs_branch() { +push_aks_branch() { if version_lt "${KUBERNETES_RELEASE}" "1.9"; then echo "push to azure repo..." cd ${GOPATH}/src/k8s.io/kubernetes - git push origin ${ACS_BRANCH_NAME} + git push origin ${AKS_BRANCH_NAME} else echo "no need to push to azure repo" fi } cleanup_output() { - rm ${TOP_DIR}/../v${ACS_VERSION}int.zip + rm ${TOP_DIR}/../v${AKS_VERSION}int.zip rm -r ${TOP_DIR} } -ACS_ENGINE_HOME=${GOPATH}/src/github.com/Azure/acs-engine +AKS_ENGINE_HOME=${GOPATH}/src/github.com/Azure/aks-engine usage() { - echo "$0 [-v version] [-p acs_patch_version]" + echo "$0 [-v version] [-p aks_patch_version]" echo " -v : version" - echo " -p : acs_patch_version" + echo " -p : aks_patch_version" echo " -u : k8s_e2e_upstream_version" echo " -z : zip_path" } @@ -362,7 +362,7 @@ while getopts ":v:p:u:z:" opt; do version=${OPTARG} ;; p) - acs_patch_version=${OPTARG} + aks_patch_version=${OPTARG} ;; u) k8s_e2e_upstream_version=${OPTARG} @@ -381,7 +381,7 @@ KUBEPATH=${GOPATH}/src/k8s.io/kubernetes if [ -z "${k8s_e2e_upstream_version}" ]; then - if [ -z "${version}" ] || [ -z "${acs_patch_version}" ]; then + if [ -z "${version}" ] || [ -z "${aks_patch_version}" ]; then usage exit 1 fi @@ -393,9 +393,9 @@ if [ -z "${k8s_e2e_upstream_version}" ]; then KUBERNETES_RELEASE=$(echo $version | cut -d'.' -f1,2) KUBERNETES_TAG_BRANCH=v${version} - ACS_VERSION=${version}-${acs_patch_version} - ACS_BRANCH_NAME=acs-v${ACS_VERSION} - TOP_DIR=${ACS_ENGINE_HOME}/_dist/k8s-windows-v${ACS_VERSION} + AKS_VERSION=${version}-${aks_patch_version} + AKS_BRANCH_NAME=acs-v${AKS_VERSION} + TOP_DIR=${AKS_ENGINE_HOME}/_dist/k8s-windows-v${AKS_VERSION} DIST_DIR=${TOP_DIR}/k create_dist_dir @@ -405,7 +405,7 @@ if [ -z "${k8s_e2e_upstream_version}" ]; then copy_dockerfile create_zip upload_zip_to_blob_storage - push_acs_branch + push_aks_branch cleanup_output else diff --git a/scripts/convert-lcg-lcl.sh b/scripts/convert-lcg-lcl.sh index 0a68de1c7a..b241cdde8f 100644 --- a/scripts/convert-lcg-lcl.sh +++ b/scripts/convert-lcg-lcl.sh @@ -11,13 +11,13 @@ convert_lcl_to_po() { do loc_lang=`basename "$dir"` translation_lang=`echo $loc_lang | tr - _` - publish/PythonLocalizerTool lcltopo $dir translations/$translation_lang/LC_MESSAGES/ translations/en_US/LC_MESSAGES/en-US/metadata acsengine "" - msgfmt -c -v -o translations/$translation_lang/LC_MESSAGES/acsengine.mo translations/$translation_lang/LC_MESSAGES/acsengine.po + publish/PythonLocalizerTool lcltopo $dir translations/$translation_lang/LC_MESSAGES/ translations/en_US/LC_MESSAGES/en-US/metadata aksengine "" + msgfmt -c -v -o translations/$translation_lang/LC_MESSAGES/aksengine.mo translations/$translation_lang/LC_MESSAGES/aksengine.po done } convert_po_to_lcg() { - publish/PythonLocalizerTool potolcg translations/en_US/LC_MESSAGES acsengine + publish/PythonLocalizerTool potolcg translations/en_US/LC_MESSAGES aksengine } case "${1-}" in diff --git a/scripts/devenv.ps1 b/scripts/devenv.ps1 index 383b171324..74832711c8 100644 --- a/scripts/devenv.ps1 +++ b/scripts/devenv.ps1 @@ -1,8 +1,8 @@ $pwd = (Get-Location).Path -docker build --pull -t acs-engine . +docker build --pull -t aks-engine . docker run --security-opt seccomp:unconfined -it ` - -v ${pwd}:/gopath/src/github.com/Azure/acs-engine ` - -w /gopath/src/github.com/Azure/acs-engine ` - acs-engine /bin/bash + -v ${pwd}:/gopath/src/github.com/Azure/aks-engine ` + -w /gopath/src/github.com/Azure/aks-engine ` + aks-engine /bin/bash diff --git a/scripts/devenv.sh b/scripts/devenv.sh index ba63f82025..b5c2066dcb 100755 --- a/scripts/devenv.sh +++ b/scripts/devenv.sh @@ -3,15 +3,15 @@ set -eu -o pipefail set -x -docker build --pull -t acs-engine . +docker build --pull -t aks-engine . docker run -it \ --privileged \ --security-opt seccomp:unconfined \ -v /var/run/docker.sock:/var/run/docker.sock \ - -v `pwd`:/gopath/src/github.com/Azure/acs-engine \ + -v `pwd`:/gopath/src/github.com/Azure/aks-engine \ -v ~/.azure:/root/.azure \ - -w /gopath/src/github.com/Azure/acs-engine \ - acs-engine /bin/bash + -w /gopath/src/github.com/Azure/aks-engine \ + aks-engine /bin/bash chown -R "$(logname):$(id -gn $(logname))" . ~/.azure diff --git a/scripts/ginkgo.coverage.sh b/scripts/ginkgo.coverage.sh index 5299fb33de..bbbae61413 100755 --- a/scripts/ginkgo.coverage.sh +++ b/scripts/ginkgo.coverage.sh @@ -25,7 +25,7 @@ hash goveralls 2>/dev/null || go get github.com/mattn/goveralls hash godir 2>/dev/null || go get github.com/Masterminds/godir generate_cover_data() { - ginkgo -skipPackage test/e2e/dcos,test/e2e/kubernetes,test/e2e/openshift -failFast -cover -r . + ginkgo -skipPackage test/e2e/kubernetes -failFast -cover -r . echo "" > ${coveragetxt} find . -type f -name "*.coverprofile" | while read -r file; do cat $file >> ${coveragetxt} && mv $file ${coverdir}; done echo "mode: $covermode" >"$profile" diff --git a/scripts/update-enus-po.sh b/scripts/update-enus-po.sh index 5f6b7bebdd..fe0c287441 100644 --- a/scripts/update-enus-po.sh +++ b/scripts/update-enus-po.sh @@ -2,5 +2,5 @@ scripts/update-translation.sh -l en_US -p -mv acsengine.po translations/en_US/LC_MESSAGES/acsengine.po -rm acsengine.pot \ No newline at end of file +mv aksengine.po translations/en_US/LC_MESSAGES/aksengine.po +rm aksengine.pot \ No newline at end of file diff --git a/scripts/update-translation.sh b/scripts/update-translation.sh index 612c96ab74..5892ad2564 100755 --- a/scripts/update-translation.sh +++ b/scripts/update-translation.sh @@ -1,8 +1,8 @@ #!/bin/bash -GO_SOURCE="pkg/acsengine/*.go pkg/acsengine/transform/*.go pkg/api/*.go pkg/operations/*.go pkg/operations/kubernetesupgrade/*.go" +GO_SOURCE="pkg/engine/*.go pkg/engine/transform/*.go pkg/api/*.go pkg/operations/*.go pkg/operations/kubernetesupgrade/*.go" LANGUAGE="en_US" -DOMAIN="acsengine" +DOMAIN="aksengine" generate_po="false" generate_mo="false" diff --git a/scripts/validate-generated.sh b/scripts/validate-generated.sh index 6b5c5a36e1..84f8654a7c 100755 --- a/scripts/validate-generated.sh +++ b/scripts/validate-generated.sh @@ -1,5 +1,9 @@ #!/usr/bin/env bash +# TODO: does this script need refactoring post-OpenShift, or can it be deleted? +echo "No generated files to check!" +exit 0 + #################################################### SOURCE="${BASH_SOURCE[0]}" while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink @@ -19,7 +23,6 @@ cp -a "${DIR}/.." "${T}/" (cd "${T}/" && go generate ./...) - GENERATED_FILES=( "pkg/openshift/certgen/unstable/templates/bindata.go" "pkg/openshift/certgen/release39/templates/bindata.go" diff --git a/scripts/validate-go.sh b/scripts/validate-go.sh index a9ebe20307..3805e65cbb 100755 --- a/scripts/validate-go.sh +++ b/scripts/validate-go.sh @@ -42,9 +42,7 @@ gometalinter \ --skip pkg/test \ --exclude pkg/i18n/i18n.go \ --exclude pkg/i18n/translations.go \ - --exclude pkg/acsengine/templates.go \ - --exclude pkg/openshift/certgen/release39/templates/bindata.go \ - --exclude pkg/openshift/certgen/unstable/templates/bindata.go \ + --exclude pkg/engine/templates.go \ ./... || exit_code=1 echo @@ -58,9 +56,7 @@ gometalinter \ --skip pkg/test \ --deadline 60s \ --exclude pkg/i18n/translations.go \ - --exclude pkg/acsengine/templates.go \ - --exclude pkg/openshift/certgen/release39/templates/bindata.go \ - --exclude pkg/openshift/certgen/unstable/templates/bindata.go \ + --exclude pkg/engine/templates.go \ ./... || exit_code=1 exit $exit_code diff --git a/test.mk b/test.mk index 04ba6e97a5..1d943a7489 100644 --- a/test.mk +++ b/test.mk @@ -25,11 +25,5 @@ test-kubernetes-with-container: test-kubernetes: @ORCHESTRATOR=kubernetes go run ./test/e2e/runner.go -test-dcos: - @ORCHESTRATOR=dcos go run ./test/e2e/runner.go - -test-openshift: - @ORCHESTRATOR=openshift go run ./test/e2e/runner.go - test-azure-constants: - ./scripts/azure-const.sh \ No newline at end of file + ./scripts/azure-const.sh diff --git a/test/acse-conf/acse-feature-validation.json b/test/acse-conf/acse-feature-validation.json deleted file mode 100644 index bae96266a0..0000000000 --- a/test/acse-conf/acse-feature-validation.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "deployments": [ - { - "cluster_definition": "windows/kubernetes-hybrid.json", - "location": "eastus" - }, - { - "cluster_definition": "windows/kubernetes.json", - "location": "eastus" - }, - { - "cluster_definition": "dcos-releases/dcos1.9.json", - "location": "eastus" - }, - { - "cluster_definition": "disks-managed/dcos-preAttachedDisks-vmas.json", - "location": "eastus" - }, - { - "cluster_definition": "disks-managed/dcos-vmss.json", - "location": "eastus" - }, - { - "cluster_definition": "disks-managed/kubernetes-preAttachedDisks-vmas.json", - "location": "eastus" - }, - { - "cluster_definition": "disks-managed/kubernetes-vmas.json", - "location": "eastus" - }, - { - "cluster_definition": "disks-managed/swarm-preAttachedDisks-vmss.json", - "location": "southcentralus" - }, - { - "cluster_definition": "disks-managed/swarmmode-vmas.json", - "location": "southcentralus" - }, - { - "cluster_definition": "disks-managed/swarmmode-vmss.json", - "location": "southcentralus" - }, - { - "cluster_definition": "disks-storageaccount/dcos.json", - "location": "westcentralus" - }, - { - "cluster_definition": "disks-storageaccount/kubernetes.json", - "location": "westcentralus" - }, - { - "cluster_definition": "disks-storageaccount/swarmmode.json", - "location": "southcentralus" - }, - { - "cluster_definition": "networkpolicy/kubernetes-calico.json", - "location": "southcentralus" - }, - { - "cluster_definition": "kubernetes-config/kubernetes-clustersubnet.json", - "location": "westus2" - }, - { - "cluster_definition": "v20170131/swarmmode.json", - "location": "westus2" - }, - { - "cluster_definition": "vnet/dcosvnet.json", - "location": "westus2" - }, - { - "cluster_definition": "vnet/kubernetesvnet.json", - "location": "westus2" - }, - { - "cluster_definition": "vnet/swarmmodevnet.json", - "location": "westus2" - } - ] -} diff --git a/test/acse-conf/acse-pr-non-k8s.json b/test/acse-conf/acse-pr-non-k8s.json deleted file mode 100644 index 1c5e5b59ba..0000000000 --- a/test/acse-conf/acse-pr-non-k8s.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "deployments": [ - { - "cluster_definition": "swarm.json", - "location": "westus2" - }, - { - "cluster_definition": "swarmmode.json", - "location": "westcentralus" - } - ] -} diff --git a/test/acse-conf/acse-regression-dcos.json b/test/acse-conf/acse-regression-dcos.json deleted file mode 100644 index 13b6ea121e..0000000000 --- a/test/acse-conf/acse-regression-dcos.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "deployments": [ - { - "cluster_definition": "dcos-releases/dcos1.9.json", - "category": "version" - }, - { - "cluster_definition": "disks-managed/dcos-preAttachedDisks-vmas.json", - "category": "managed-disk" - }, - { - "cluster_definition": "disks-managed/dcos-vmss.json", - "category": "managed-disk" - }, - { - "cluster_definition": "disks-storageaccount/dcos.json", - "category": "managed-disk" - }, - { - "cluster_definition": "vnet/dcosvnet.json", - "category": "network" - } - ] - } \ No newline at end of file diff --git a/test/acse-conf/acse-regression.json b/test/acse-conf/acse-regression.json deleted file mode 100644 index 2945d0d7a4..0000000000 --- a/test/acse-conf/acse-regression.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "deployments": [ - { - "cluster_definition": "dcos-releases/dcos1.9.json", - "category": "version" - }, - { - "cluster_definition": "disks-managed/dcos-preAttachedDisks-vmas.json", - "category": "managed-disk" - }, - { - "cluster_definition": "disks-managed/dcos-vmss.json", - "category": "managed-disk" - }, - { - "cluster_definition": "disks-managed/swarm-preAttachedDisks-vmss.json", - "category": "managed-disk" - }, - { - "cluster_definition": "disks-managed/swarmmode-vmas.json", - "category": "managed-disk" - }, - { - "cluster_definition": "disks-managed/swarmmode-vmss.json", - "category": "managed-disk" - }, - { - "cluster_definition": "disks-storageaccount/dcos.json", - "category": "managed-disk" - }, - { - "cluster_definition": "disks-storageaccount/swarmmode.json", - "category": "sa-disk" - }, - { - "cluster_definition": "keyvaultcerts/swarmmode.json", - "category": "keyvault", - "location": "westus" - }, - { - "cluster_definition": "networkpolicy/kubernetes-calico.json", - "category": "network" - }, - { - "cluster_definition": "v20170131/swarmmode.json", - "category": "version" - }, - { - "cluster_definition": "vnet/dcosvnet.json", - "category": "network" - }, - { - "cluster_definition": "vnet/kubernetesvnet.json", - "category": "network" - }, - { - "cluster_definition": "vnet/swarmmodevnet.json", - "category": "network" - } - ] -} \ No newline at end of file diff --git a/test/acse-conf/acse-svc-canary-dcos.json b/test/acse-conf/acse-svc-canary-dcos.json deleted file mode 100644 index c6a8deb5a0..0000000000 --- a/test/acse-conf/acse-svc-canary-dcos.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "deployments": [ - { - "cluster_definition": "dcos.json", - "category": "canary", - "location": "eastus2euap" - } - ] -} diff --git a/test/acse-conf/acse-svc-canary-swarmmode.json b/test/acse-conf/acse-svc-canary-swarmmode.json deleted file mode 100644 index 938304240e..0000000000 --- a/test/acse-conf/acse-svc-canary-swarmmode.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "deployments": [ - { - "cluster_definition": "swarmmode.json", - "category": "canary", - "location": "eastus2euap" - } - ] -} diff --git a/test/acse-conf/acse-svc-dcos.json b/test/acse-conf/acse-svc-dcos.json deleted file mode 100644 index 6b3cdd8277..0000000000 --- a/test/acse-conf/acse-svc-dcos.json +++ /dev/null @@ -1,124 +0,0 @@ -{ - "deployments": [ - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "canadacentral" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "canadaeast" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "centralindia" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "westindia" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "southindia" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "centralus" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "eastus2" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "eastus" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "westcentralus" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "westus2" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "westus" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "southeastasia" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "koreacentral" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "japaneast" - }, - { - "cluster_definition": "dcos-D2.json", - "category": "service-availability", - "location": "japanwest" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "northeurope" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "westeurope" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "uksouth" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "australiaeast" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "australiasoutheast" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "koreasouth" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "northcentralus" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "southcentralus" - }, - { - "cluster_definition": "dcos.json", - "category": "service-availability", - "location": "ukwest" - } - ] -} diff --git a/test/acse-conf/acse-svc-swarmmode.json b/test/acse-conf/acse-svc-swarmmode.json deleted file mode 100644 index 9c2685b5ca..0000000000 --- a/test/acse-conf/acse-svc-swarmmode.json +++ /dev/null @@ -1,124 +0,0 @@ -{ - "deployments": [ - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "canadacentral" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "canadaeast" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "centralindia" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "westindia" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "southindia" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "centralus" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "eastus2" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "eastus" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "westcentralus" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "westus2" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "westus" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "southeastasia" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "koreacentral" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "japaneast" - }, - { - "cluster_definition": "swarmmode-D2.json", - "category": "service-availability", - "location": "japanwest" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "northeurope" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "westeurope" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "uksouth" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "australiaeast" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "australiasoutheast" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "koreasouth" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "northcentralus" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "southcentralus" - }, - { - "cluster_definition": "swarmmode.json", - "category": "service-availability", - "location": "ukwest" - } - ] -} diff --git a/test/acs-engine-test/acs-engine-errors.json b/test/aks-engine-test/acs-engine-errors.json similarity index 80% rename from test/acs-engine-test/acs-engine-errors.json rename to test/aks-engine-test/acs-engine-errors.json index 399fb6c439..fa5a1e52bb 100644 --- a/test/acs-engine-test/acs-engine-errors.json +++ b/test/aks-engine-test/acs-engine-errors.json @@ -75,7 +75,6 @@ "class": "Deployment", "regex": "platformFaultDomainCount" }, - { "name": "K8sNodeNotReady", "class": "Validation", @@ -155,43 +154,6 @@ "name": "K8sWindowsNoSimpleWebOutboundInternet", "class": "Validation", "regex": "K8S-Windows: failed to get outbound internet connection inside simpleweb container" - }, - - { - "name": "DcosNodeNotReady", - "class": "Validation", - "regex": "gave up waiting for DCOS nodes" - }, - { - "name": "DcosMarathonValidationFailed", - "class": "Validation", - "regex": "dcos/test.sh] marathon validation failed" - }, - { - "name": "DcosMarathonNotAdded", - "class": "Validation", - "regex": "dcos/test.sh] gave up waiting for marathon to be added" - }, - { - "name": "DcosMarathonLbNotInstalled", - "class": "Validation", - "regex": "Failed to install marathon-lb" - }, - - { - "name": "DockerCeNetworkNotReady", - "class": "Validation", - "regex": "DockerCE: gave up waiting for network to be created" - }, - { - "name": "DockerCeServiceNotReady", - "class": "Validation", - "regex": "DockerCE: gave up waiting for service to be created" - }, - { - "name": "DockerCeServiceUnreachable", - "class": "Validation", - "regex": "DockerCE: gave up waiting for service to be externally reachable" } ] -} \ No newline at end of file +} diff --git a/test/acs-engine-test/config/config.go b/test/aks-engine-test/config/config.go similarity index 94% rename from test/acs-engine-test/config/config.go rename to test/aks-engine-test/config/config.go index 9c353ef56e..a31395702a 100644 --- a/test/acs-engine-test/config/config.go +++ b/test/aks-engine-test/config/config.go @@ -6,7 +6,7 @@ import ( "io/ioutil" ) -// Deployment represents an ACS cluster deployment on Azure +// Deployment represents an AKS cluster deployment on Azure type Deployment struct { ClusterDefinition string `json:"cluster_definition"` Location string `json:"location"` diff --git a/test/acs-engine-test/config/config_test.go b/test/aks-engine-test/config/config_test.go similarity index 58% rename from test/acs-engine-test/config/config_test.go rename to test/aks-engine-test/config/config_test.go index 866b6361c7..143bf4b442 100644 --- a/test/acs-engine-test/config/config_test.go +++ b/test/aks-engine-test/config/config_test.go @@ -11,19 +11,6 @@ func TestConfigParse(t *testing.T) { "cluster_definition":"examples/kubernetes.json", "location":"westus", "skip_validation":true - }, - { - "cluster_definition":"examples/dcos.json", - "location":"eastus", - "skip_validation":false - }, - { - "cluster_definition":"examples/swarm.json", - "location":"southcentralus" - }, - { - "cluster_definition":"examples/swarmmode.json", - "location":"westus2" } ] } @@ -36,7 +23,7 @@ func TestConfigParse(t *testing.T) { if err := testConfig.validate(); err != nil { t.Fatal(err) } - if len(testConfig.Deployments) != 4 { + if len(testConfig.Deployments) != 1 { t.Fatalf("Wrong number of deployments: %d instead of 4", len(testConfig.Deployments)) } } diff --git a/test/acs-engine-test/main.go b/test/aks-engine-test/main.go similarity index 96% rename from test/acs-engine-test/main.go rename to test/aks-engine-test/main.go index 046e46eb22..a5ded7ebe4 100644 --- a/test/acs-engine-test/main.go +++ b/test/aks-engine-test/main.go @@ -15,11 +15,11 @@ import ( "sync" "time" - "github.com/Azure/acs-engine/pkg/helpers" - "github.com/Azure/acs-engine/test/acs-engine-test/config" - "github.com/Azure/acs-engine/test/acs-engine-test/metrics" - "github.com/Azure/acs-engine/test/acs-engine-test/promote" - "github.com/Azure/acs-engine/test/acs-engine-test/report" + "github.com/Azure/aks-engine/pkg/helpers" + "github.com/Azure/aks-engine/test/aks-engine-test/config" + "github.com/Azure/aks-engine/test/aks-engine-test/metrics" + "github.com/Azure/aks-engine/test/aks-engine-test/promote" + "github.com/Azure/aks-engine/test/aks-engine-test/report" "github.com/pkg/errors" ) @@ -39,7 +39,7 @@ const ( combinedReport = "CombinedReport.json" metricsEndpoint = ":8125" - metricsNS = "ACSEngine" + metricsNS = "AKSEngine" metricError = "Error" metricDeploymentDuration = "DeploymentDuration" @@ -47,12 +47,12 @@ const ( ) const usage = `Usage: - acs-engine-test + aks-engine-test Options: -c : JSON file containing a list of deployment configurations. - Refer to acs-engine/test/acs-engine-test/acs-engine-test.json for examples - -d + Refer to aks-engine/test/aks-engine-test/aks-engine-test.json for examples + -d -e ` @@ -258,7 +258,7 @@ func (m *TestManager) testRun(d config.Deployment, index, attempt int, timeout t d.Location = m.regions[randomIndex] } testName := strings.TrimSuffix(d.ClusterDefinition, filepath.Ext(d.ClusterDefinition)) - instanceName := fmt.Sprintf("acse-%d-%s-%s-%d-%d", rand.Intn(0x0ffffff), d.Location, os.Getenv("BUILD_NUM"), index, attempt) + instanceName := fmt.Sprintf("akse-%d-%s-%s-%d-%d", rand.Intn(0x0ffffff), d.Location, os.Getenv("BUILD_NUM"), index, attempt) resourceGroup := fmt.Sprintf("%s-%s-%s-%s-%d-%d", rgPrefix, strings.Replace(testName, "/", "-", -1), d.Location, os.Getenv("BUILD_NUM"), index, attempt) logFile := fmt.Sprintf("%s/%s.log", logDir, resourceGroup) validateLogFile := fmt.Sprintf("%s/validate-%s.log", logDir, resourceGroup) @@ -539,7 +539,7 @@ func mainInternal() error { var logErrorFile string var err error flag.StringVar(&configFile, "c", "", "deployment configurations") - flag.StringVar(&rootDir, "d", "", "acs-engine root directory") + flag.StringVar(&rootDir, "d", "", "aks-engine root directory") flag.StringVar(&logErrorFile, "e", "", "logError config file") flag.StringVar(&saName, "j", "", "SA Name") flag.StringVar(&saKey, "k", "", "SA Key") @@ -576,7 +576,7 @@ func mainInternal() error { testManager.Manager = report.New(os.Getenv("JOB_BASE_NAME"), buildNum, len(testManager.config.Deployments), logErrorFile) // check root directory if rootDir == "" { - return errors.New("acs-engine root directory is not provided") + return errors.New("aks-engine root directory is not provided") } testManager.rootDir = rootDir if _, err = os.Stat(fmt.Sprintf("%s/%s", rootDir, script)); err != nil { diff --git a/test/acs-engine-test/metrics/metrics.go b/test/aks-engine-test/metrics/metrics.go similarity index 95% rename from test/acs-engine-test/metrics/metrics.go rename to test/aks-engine-test/metrics/metrics.go index 05ca32fba0..88f6c2eccc 100644 --- a/test/acs-engine-test/metrics/metrics.go +++ b/test/aks-engine-test/metrics/metrics.go @@ -3,7 +3,7 @@ package metrics import ( "fmt" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/helpers" "github.com/alexcesaro/statsd" ) diff --git a/test/acs-engine-test/metrics/metrics_test.go b/test/aks-engine-test/metrics/metrics_test.go similarity index 100% rename from test/acs-engine-test/metrics/metrics_test.go rename to test/aks-engine-test/metrics/metrics_test.go diff --git a/test/acs-engine-test/promote/promote.go b/test/aks-engine-test/promote/promote.go similarity index 92% rename from test/acs-engine-test/promote/promote.go rename to test/aks-engine-test/promote/promote.go index 8f43264700..3680caf236 100644 --- a/test/acs-engine-test/promote/promote.go +++ b/test/aks-engine-test/promote/promote.go @@ -9,10 +9,10 @@ import ( ) const ( - // ACSRPTests are the rp tests - ACSRPTests string = "ACSRpTests" - // ACSEngineTests are the ACS-Engine tests - ACSEngineTests string = "ACSEngineTests" + // AKSRPTests are the rp tests + AKSRPTests string = "AKSRPTests" + // AKSEngineTests are the AKS Engine tests + AKSEngineTests string = "AKSEngineTests" // SimDemTests are the SimDem tests SimDemTests string = "SimDemTests" ) @@ -24,16 +24,8 @@ type StorageAccount struct { } const ( - // Mesos is the string constant for MESOS orchestrator type - Mesos string = "Mesos" - // DCOS is the string constant for DCOS orchestrator type and defaults to DCOS188 - DCOS string = "DCOS" - // Swarm is the string constant for the Swarm orchestrator type - Swarm string = "Swarm" // Kubernetes is the string constant for the Kubernetes orchestrator type Kubernetes string = "Kubernetes" - // SwarmMode is the string constant for the Swarm Mode orchestrator type - SwarmMode string = "SwarmMode" // RecordTestRunTableName for storing RecordTestRun RecordTestRunTableName string = "RecordTestRun" // PromoteToFailureTableName for storing PromoteToFailure diff --git a/test/acs-engine-test/report/report.go b/test/aks-engine-test/report/report.go similarity index 99% rename from test/acs-engine-test/report/report.go rename to test/aks-engine-test/report/report.go index a8a0929064..7985d3207f 100644 --- a/test/acs-engine-test/report/report.go +++ b/test/aks-engine-test/report/report.go @@ -10,7 +10,7 @@ import ( "sync" "time" - "github.com/Azure/acs-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/helpers" ) // ErrorInfo represents the CI error diff --git a/test/acs-engine-test/report/report_test.go b/test/aks-engine-test/report/report_test.go similarity index 94% rename from test/acs-engine-test/report/report_test.go rename to test/aks-engine-test/report/report_test.go index dbabd8f37f..f5a87ab008 100644 --- a/test/acs-engine-test/report/report_test.go +++ b/test/aks-engine-test/report/report_test.go @@ -10,7 +10,7 @@ func TestReportParse(t *testing.T) { jobName := "TestJob" buildNum := 001 nDeploys := 4 - fileName := "../acs-engine-errors.json" + fileName := "../aks-engine-errors.json" dummy := New(jobName, buildNum, nDeploys, fileName) txt := "Error loading command module" diff --git a/test/akse-conf/akse-feature-validation.json b/test/akse-conf/akse-feature-validation.json new file mode 100644 index 0000000000..49e7e43be1 --- /dev/null +++ b/test/akse-conf/akse-feature-validation.json @@ -0,0 +1,36 @@ +{ + "deployments": [ + { + "cluster_definition": "windows/kubernetes-hybrid.json", + "location": "eastus" + }, + { + "cluster_definition": "windows/kubernetes.json", + "location": "eastus" + }, + { + "cluster_definition": "disks-managed/kubernetes-preAttachedDisks-vmas.json", + "location": "eastus" + }, + { + "cluster_definition": "disks-managed/kubernetes-vmas.json", + "location": "eastus" + }, + { + "cluster_definition": "disks-storageaccount/kubernetes.json", + "location": "westcentralus" + }, + { + "cluster_definition": "networkpolicy/kubernetes-calico.json", + "location": "southcentralus" + }, + { + "cluster_definition": "kubernetes-config/kubernetes-clustersubnet.json", + "location": "westus2" + }, + { + "cluster_definition": "vnet/kubernetesvnet.json", + "location": "westus2" + } + ] +} diff --git a/test/akse-conf/akse-regression.json b/test/akse-conf/akse-regression.json new file mode 100644 index 0000000000..e3d6afcf31 --- /dev/null +++ b/test/akse-conf/akse-regression.json @@ -0,0 +1,12 @@ +{ + "deployments": [ + { + "cluster_definition": "networkpolicy/kubernetes-calico.json", + "category": "network" + }, + { + "cluster_definition": "vnet/kubernetesvnet.json", + "category": "network" + } + ] +} diff --git a/test/acse-conf/acse-scale-vnet.json b/test/akse-conf/akse-scale-vnet.json similarity index 100% rename from test/acse-conf/acse-scale-vnet.json rename to test/akse-conf/akse-scale-vnet.json diff --git a/test/acse-conf/acse-scale.json b/test/akse-conf/akse-scale.json similarity index 100% rename from test/acse-conf/acse-scale.json rename to test/akse-conf/akse-scale.json diff --git a/test/acse-conf/acse-svc-canary-k8s-win.json b/test/akse-conf/akse-svc-canary-k8s-win.json similarity index 100% rename from test/acse-conf/acse-svc-canary-k8s-win.json rename to test/akse-conf/akse-svc-canary-k8s-win.json diff --git a/test/acse-conf/acse-svc-canary-k8s.json b/test/akse-conf/akse-svc-canary-k8s.json similarity index 100% rename from test/acse-conf/acse-svc-canary-k8s.json rename to test/akse-conf/akse-svc-canary-k8s.json diff --git a/test/acse-conf/acse-svc-k8s-win.json b/test/akse-conf/akse-svc-k8s-win.json similarity index 100% rename from test/acse-conf/acse-svc-k8s-win.json rename to test/akse-conf/akse-svc-k8s-win.json diff --git a/test/acse-conf/acse-svc-k8s.json b/test/akse-conf/akse-svc-k8s.json similarity index 100% rename from test/acse-conf/acse-svc-k8s.json rename to test/akse-conf/akse-svc-k8s.json diff --git a/test/acse-conf/acse-upgrade-lnx.json b/test/akse-conf/akse-upgrade-lnx.json similarity index 100% rename from test/acse-conf/acse-upgrade-lnx.json rename to test/akse-conf/akse-upgrade-lnx.json diff --git a/test/acse-conf/acse-upgrade-win.json b/test/akse-conf/akse-upgrade-win.json similarity index 100% rename from test/acse-conf/acse-upgrade-win.json rename to test/akse-conf/akse-upgrade-win.json diff --git a/test/acsengine-ci.groovy b/test/aksengine-ci.groovy similarity index 95% rename from test/acsengine-ci.groovy rename to test/aksengine-ci.groovy index 864bd9ae1c..ebcfbc3d83 100644 --- a/test/acsengine-ci.groovy +++ b/test/aksengine-ci.groovy @@ -7,7 +7,7 @@ node("slave") { wrap([$class: 'AnsiColorBuildWrapper', 'colorMapName': 'XTerm']) { env.GOPATH="${WORKSPACE}" env.PATH="${env.PATH}:${env.GOPATH}/bin" - def clone_dir = "${env.GOPATH}/src/github.com/Azure/acs-engine" + def clone_dir = "${env.GOPATH}/src/github.com/Azure/aks-engine" env.HOME=clone_dir def success = true Integer timeoutInMinutes = TEST_TIMEOUT.toInteger() @@ -18,7 +18,7 @@ node("slave") { stage('Init') { deleteDir() checkout scm - img = docker.build('acs-engine-test', '--pull .') + img = docker.build('aks-engine-test', '--pull .') } } catch(exc) { @@ -93,7 +93,7 @@ node("slave") { gitCommit = sh(returnStdout: true, script: 'git rev-parse HEAD').trim() emailext( to: to, - subject: "[ACS Engine is BROKEN] ${env.JOB_NAME} #${env.BUILD_NUM}", + subject: "[AKS Engine is BROKEN] ${env.JOB_NAME} #${env.BUILD_NUM}", body: "Commit: ${gitCommit}\n\n${url}${errorMsg}" ) } diff --git a/test/acsengine-features.groovy b/test/aksengine-features.groovy similarity index 93% rename from test/acsengine-features.groovy rename to test/aksengine-features.groovy index 7079b37ded..08b2a4fd20 100644 --- a/test/acsengine-features.groovy +++ b/test/aksengine-features.groovy @@ -7,7 +7,7 @@ node("slave") { wrap([$class: 'AnsiColorBuildWrapper', 'colorMapName': 'XTerm']) { env.GOPATH="${WORKSPACE}" env.PATH="${env.PATH}:${env.GOPATH}/bin" - def clone_dir = "${env.GOPATH}/src/github.com/Azure/acs-engine" + def clone_dir = "${env.GOPATH}/src/github.com/Azure/aks-engine" env.HOME=clone_dir String sendTo = "${SEND_TO}".trim() Integer timeoutInMinutes = STAGE_TIMEOUT.toInteger() @@ -18,7 +18,7 @@ node("slave") { stage('Init') { deleteDir() checkout scm - img = docker.build('acs-engine-test', '--pull .') + img = docker.build('aks-engine-test', '--pull .') } img.inside("-u root:root") { @@ -48,7 +48,7 @@ node("slave") { prefix = readFile('INSTANCE_NAME_PREFIX').trim() // Create report directory sh("mkdir -p ${junit_dir}") - // Build and test acs-engine + // Build and test aks-engine sh('make ci') } def pairs = "${SCENARIOS_LOCATIONS}".tokenize('|') @@ -74,7 +74,7 @@ node("slave") { try { stage(name) { def scripts = ["generate_template.sh", "deploy_template.sh"] - if(env.ORCHESTRATOR == "dcos" || env.ORCHESTRATOR == "swarmmode" || env.ORCHESTRATOR == "kubernetes") { + if(env.ORCHESTRATOR == "kubernetes") { scripts += "validate_deployment.sh" } for(k = 0; k < scripts.size(); k++) { @@ -111,7 +111,7 @@ node("slave") { if(sendTo != "") { emailext( to: "${sendTo}", - subject: "[ACS Engine Jenkins Failure] ${env.JOB_NAME} #${env.BUILD_NUM}", + subject: "[AKS Engine Jenkins Failure] ${env.JOB_NAME} #${env.BUILD_NUM}", body: "${env.BUILD_URL}testReport") } } diff --git a/test/acsengine-scale.groovy b/test/aksengine-scale.groovy similarity index 96% rename from test/acsengine-scale.groovy rename to test/aksengine-scale.groovy index 1025149cd3..e483afe8d5 100644 --- a/test/acsengine-scale.groovy +++ b/test/aksengine-scale.groovy @@ -7,7 +7,7 @@ node("slave") { wrap([$class: 'AnsiColorBuildWrapper', 'colorMapName': 'XTerm']) { env.GOPATH="${WORKSPACE}" env.PATH="${env.PATH}:${env.GOPATH}/bin" - def clone_dir = "${env.GOPATH}/src/github.com/Azure/acs-engine" + def clone_dir = "${env.GOPATH}/src/github.com/Azure/aks-engine" env.HOME=clone_dir String locations_str = "${LOCATIONS}" Integer scalingDelay = SCALE_CYCLE_DELAY_MIN.toInteger() @@ -35,7 +35,7 @@ uksouth ukwest" stage('Init') { deleteDir() checkout scm - img = docker.build('acs-engine-test', '--pull .') + img = docker.build('aks-engine-test', '--pull .') } img.inside("-u root:root") { @@ -48,7 +48,7 @@ uksouth ukwest" sh("az account set --subscription ${SUBSCRIPTION_ID}") // Create report directory sh("mkdir ${junit_dir}") - // Build and test acs-engine + // Build and test aks-engine sh('make ci') // Create template env.CLUSTER_DEFINITION = pwd()+"/examples/${CLUSTER_DEFINITION}" @@ -151,7 +151,7 @@ uksouth ukwest" if(sendTo != "") { emailext( to: "${sendTo}", - subject: "[ACS Engine Jenkins Failure] ${env.JOB_NAME} #${env.BUILD_NUM}", + subject: "[AKS Engine Jenkins Failure] ${env.JOB_NAME} #${env.BUILD_NUM}", body: "${env.BUILD_URL}testReport") } } diff --git a/test/acsengine-svc.groovy b/test/aksengine-svc.groovy similarity index 96% rename from test/acsengine-svc.groovy rename to test/aksengine-svc.groovy index 13cbf5731b..e932eaf42e 100644 --- a/test/acsengine-svc.groovy +++ b/test/aksengine-svc.groovy @@ -7,7 +7,7 @@ node("slave") { wrap([$class: 'AnsiColorBuildWrapper', 'colorMapName': 'XTerm']) { env.GOPATH="${WORKSPACE}" env.PATH="${env.PATH}:${env.GOPATH}/bin" - def clone_dir = "${env.GOPATH}/src/github.com/Azure/acs-engine" + def clone_dir = "${env.GOPATH}/src/github.com/Azure/aks-engine" env.HOME=clone_dir String locations_str = "${LOCATIONS}" String sendTo = "${SEND_TO}".trim() @@ -34,7 +34,7 @@ uksouth ukwest" stage('Init') { deleteDir() checkout scm - img = docker.build('acs-engine-test', '--pull .') + img = docker.build('aks-engine-test', '--pull .') } img.inside("-u root:root") { @@ -47,7 +47,7 @@ uksouth ukwest" sh("az account set --subscription ${SUBSCRIPTION_ID}") // Create report directory sh("mkdir ${junit_dir}") - // Build and test acs-engine + // Build and test aks-engine sh('make ci') // Create template env.CLUSTER_DEFINITION = "examples/${CLUSTER_DEFINITION}" @@ -123,7 +123,7 @@ uksouth ukwest" if(sendTo != "") { emailext( to: "${sendTo}", - subject: "[ACS Engine Jenkins Failure] ${env.JOB_NAME} #${env.BUILD_NUM}", + subject: "[AKS Engine Jenkins Failure] ${env.JOB_NAME} #${env.BUILD_NUM}", body: "${env.BUILD_URL}testReport") } } diff --git a/test/bootstrap/checkout-pr.sh b/test/bootstrap/checkout-pr.sh index f0050ca99a..81a8914d8f 100755 --- a/test/bootstrap/checkout-pr.sh +++ b/test/bootstrap/checkout-pr.sh @@ -16,8 +16,8 @@ set -x git init . git clean -dfx git reset --hard -git config --local user.name 'ACS Bot' -git config --local user.email 'acs-bot@microsoft.com' +git config --local user.name 'AKS Bot' +git config --local user.email 'aks-bot@microsoft.com' git fetch --tags https://github.com/${REPO_OWNER}/${REPO_NAME} master +refs/pull/${PULL_NUMBER}/head:refs/pr/${PULL_NUMBER} git checkout -B test "${PULL_BASE_SHA}" git merge --no-ff -m "Merge +refs/pull/${PULL_NUMBER}/head:refs/pr/${PULL_NUMBER}" "${PULL_PULL_SHA}" diff --git a/test/cluster-tests/dcos/marathon-slave-public.json b/test/cluster-tests/dcos/marathon-slave-public.json deleted file mode 100644 index 951eabf2e0..0000000000 --- a/test/cluster-tests/dcos/marathon-slave-public.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "id": "web", - "container": { - "type": "DOCKER", - "docker": { - "image": "yeasy/simple-web", - "network": "HOST", - "forcePullImage": false, - "privileged": false - } - }, - "instances": 3, - "cpus": 0.1, - "mem": 65, - "cmd": null, - "disk": 0, - "executor": null, - "fetch": null, - "constraints": null, - "acceptedResourceRoles": [ - "slave_public" - ], - "user": null, - "env": null, - "healthChecks": [{ - "protocol": "HTTP", - "path": "/", - "portIndex": 0, - "timeoutSeconds": 10, - "gracePeriodSeconds": 10, - "intervalSeconds": 2, - "maxConsecutiveFailures": 10 - }], - "portDefinitions": [ - { - "protocol": "tcp", - "port": 0, - "name": "80" - } - ], - "labels":{ - "HAPROXY_GROUP":"external", - "HAPROXY_0_VHOST":"{agentFQDN}", - "HAPROXY_0_MODE":"http" - } -} \ No newline at end of file diff --git a/test/cluster-tests/dcos/marathon.json b/test/cluster-tests/dcos/marathon.json deleted file mode 100644 index 0b6a768ba5..0000000000 --- a/test/cluster-tests/dcos/marathon.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "id": "web", - "container": { - "type": "DOCKER", - "docker": { - "image": "yeasy/simple-web", - "network": "BRIDGE", - "portMappings": [ - { "hostPort": 0, "containerPort": 80, "servicePort": 10000 } - ], - "forcePullImage":true - } - }, - "instances": 3, - "cpus": 0.1, - "mem": 65, - "healthChecks": [{ - "protocol": "HTTP", - "path": "/", - "portIndex": 0, - "timeoutSeconds": 10, - "gracePeriodSeconds": 10, - "intervalSeconds": 2, - "maxConsecutiveFailures": 10 - }], - "labels":{ - "HAPROXY_GROUP":"external", - "HAPROXY_0_VHOST":"{agentFQDN}", - "HAPROXY_0_MODE":"http" - } -} \ No newline at end of file diff --git a/test/cluster-tests/dcos/test.sh b/test/cluster-tests/dcos/test.sh deleted file mode 100755 index 7f6f41639c..0000000000 --- a/test/cluster-tests/dcos/test.sh +++ /dev/null @@ -1,126 +0,0 @@ -#!/bin/bash - -#################################################### -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" -#################################################### - -# do not use 'set -e' -# -o pipefail -set -x - -source "$DIR/../utils.sh" - -ENV_FILE="${CLUSTER_DEFINITION}.env" -if [ -e "${ENV_FILE}" ]; then - source "${ENV_FILE}" -fi - -MARATHON_JSON="${MARATHON_JSON:-marathon.json}" - -remote_exec="ssh -i "${SSH_KEY}" -o ConnectTimeout=30 -o StrictHostKeyChecking=no azureuser@${INSTANCE_NAME}.${LOCATION}.cloudapp.azure.com -p2200" -agentFQDN="${INSTANCE_NAME}0.${LOCATION}.cloudapp.azure.com" -remote_cp="scp -i "${SSH_KEY}" -P 2200 -o StrictHostKeyChecking=no" - -function teardown { - ${remote_exec} ./dcos marathon app remove /web -} - -###### Check node count -function check_node_count() { - log "Checking node count" - count=20 - while (( $count > 0 )); do - log " ... counting down $count" - node_count=$(${remote_exec} curl -s http://localhost:1050/system/health/v1/nodes | jq '.nodes | length') - [ $? -eq 0 ] && [ ! -z "$node_count" ] && [ $node_count -eq ${EXPECTED_NODE_COUNT} ] && log "Successfully got $EXPECTED_NODE_COUNT nodes" && break - sleep 30; count=$((count-1)) - done - if (( $node_count != ${EXPECTED_NODE_COUNT} )); then - log "gave up waiting for DCOS nodes: $node_count available, ${EXPECTED_NODE_COUNT} expected" - exit 1 - fi -} - -check_node_count - -log "Downloading dcos" -${remote_exec} curl -O https://dcos-mirror.azureedge.net/binaries/cli/linux/x86-64/dcos-1.10/dcos -if [[ "$?" != "0" ]]; then log "Failed to download dcos"; exit 1; fi -log "Setting dcos permissions" -${remote_exec} chmod a+x ./dcos -if [[ "$?" != "0" ]]; then log "Failed to chmod dcos"; exit 1; fi -log "Configuring dcos" -${remote_exec} ./dcos cluster setup http://localhost:80 -if [[ "$?" != "0" ]]; then log "Failed to configure dcos"; exit 1; fi - -log "Copying marathon.json" - -${remote_cp} "${DIR}/${MARATHON_JSON}" azureuser@${INSTANCE_NAME}.${LOCATION}.cloudapp.azure.com:marathon.json -if [[ "$?" != "0" ]]; then log "Failed to copy marathon.json"; exit 1; fi - -# feed agentFQDN to marathon.json -log "Configuring marathon.json" -${remote_exec} sed -i "s/{agentFQDN}/${agentFQDN}/g" marathon.json -if [[ "$?" != "0" ]]; then log "Failed to configure marathon.json"; exit 1; fi - - -log "Adding marathon app" -count=20 -while (( $count > 0 )); do - log " ... counting down $count" - ${remote_exec} ./dcos marathon app list | grep /web - retval=$? - if [[ $retval -eq 0 ]]; then log "Marathon App successfully installed" && break; fi - ${remote_exec} ./dcos marathon app add marathon.json - retval=$? - if [[ "$retval" == "0" ]]; then break; fi - sleep 15; count=$((count-1)) -done -if [[ $retval -ne 0 ]]; then log "gave up waiting for marathon to be added"; exit 1; fi - -# only need to teardown if app added successfully -trap teardown EXIT - -log "Validating marathon app" -count=0 -while [[ ${count} -lt 25 ]]; do - count=$((count+1)) - log " ... cycle $count" - running=$(${remote_exec} ./dcos marathon app show /web | jq .tasksRunning) - if [[ "${running}" == "3" ]]; then - log "Found 3 running tasks" - break - fi - sleep ${count} -done - -if [[ "${running}" != "3" ]]; then - log "marathon validation failed" - ${remote_exec} ./dcos marathon app show /web - ${remote_exec} ./dcos marathon app list - exit 1 -fi - -# install marathon-lb -${remote_exec} ./dcos package install marathon-lb --yes -if [[ "$?" != "0" ]]; then log "Failed to install marathon-lb"; exit 1; fi - -# curl simpleweb through external haproxy -log "Checking Service" -count=20 -while true; do - log " ... counting down $count" - rc=$(curl -sI --max-time 60 "http://${agentFQDN}" | head -n1 | cut -d$' ' -f2) - [[ "$rc" -eq "200" ]] && log "Successfully hitting simpleweb through external haproxy http://${agentFQDN}" && break - if [[ "${count}" -le 1 ]]; then - log "failed to get expected response from nginx through the loadbalancer: Error $rc" - exit 1 - fi - sleep 15; count=$((count-1)) -done diff --git a/test/cluster-tests/swarm/test.sh b/test/cluster-tests/swarm/test.sh deleted file mode 100755 index a0ce6dce8a..0000000000 --- a/test/cluster-tests/swarm/test.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -#################################################### -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" -#################################################### - -# do not use 'set -e' -set -x -set -u - -source "$DIR/../utils.sh" - -SSH="ssh -i ${SSH_KEY} -o ConnectTimeout=30 -o StrictHostKeyChecking=no -p2200 azureuser@${INSTANCE_NAME}.${LOCATION}.cloudapp.azure.com" - -deploy="docker -H :2375 run -d -p 80:80 yeasy/simple-web" -wait_duration=10 -total_loops=30 -while true; do - # || true is used to suppress the failure like "Error response from daemon: No elected primary cluster manager" - # it should be gone after a few retries - containerId="$($SSH $deploy 2>/dev/null )" || true - [[ ! -z $containerId ]] && [[ "$(echo $containerId | grep '[0-9a-z]\{64\}')" ]] && log "container deployed! containerId is $containerId" && break - log "Validation: Expected to get containerId. $(($total_loops*$wait_duration)) seconds remain" - sleep $wait_duration - total_loops=$((total_loops-1)) - if [ $total_loops -eq 0 ]; then - log "Swarm validation failed: timeout"; exit 1; - fi -done - -result=$($SSH curl localhost:2375/containers/json | jq "[.[].Id==\"$containerId\"] | any") - -if [ "$result" != "true" ]; then - log "Swarm validation failed: container not found"; exit 1; -fi - -log "Swarm validation completed" diff --git a/test/cluster-tests/swarmmode/test.sh b/test/cluster-tests/swarmmode/test.sh deleted file mode 100755 index 38ce4d5989..0000000000 --- a/test/cluster-tests/swarmmode/test.sh +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/bash - -#################################################### -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" -#################################################### - -# do not use 'set -e' -set -x -set -u - - -source "$DIR/../utils.sh" - -ssh_args="-i ${SSH_KEY} -o ConnectTimeout=30 -o StrictHostKeyChecking=no -p2200 azureuser@${INSTANCE_NAME}.${LOCATION}.cloudapp.azure.com" - -function teardown { - ssh ${ssh_args} docker service rm nginx - sleep 10 - ssh ${ssh_args} docker network rm network -} - -trap teardown EXIT - -log "Starting swarmmode deployment validation in ${LOCATION}" -sleep 30 -log "Creating network" -wait=10 -count=12 -args="${ssh_args} docker network create --driver overlay --subnet 10.0.9.0/24 --opt encrypted network" -while (( $count > 0 )); do - log " ... counting down $count" - timeout -k 60s -s KILL 60s ssh $args - retval=$? - if [[ "$retval" == "0" ]]; then break; fi - sleep $wait - count=$((count-1)) -done -if [[ "$retval" != "0" ]]; then - log "DockerCE: gave up waiting for network to be created" - exit 1 -fi - -log "Creating service" -wait=5 -count=12 -args="${ssh_args} docker service create --replicas 3 --name nginx --network network --publish 80:80 nginx" -while (( $count > 0 )); do - log " ... counting down $count" - ssh $args - retval=$? - if [[ "$retval" == "0" ]]; then break; fi - sleep $wait - count=$((count-1)) -done -if [[ "$retval" != "0" ]]; then - log "DockerCE: gave up waiting for service to be created" - exit 1 -fi - -sleep 10 -log "Testing service" -wait=5 -count=12 -while (( $count > 0 )); do - log " ... counting down $count" - curl --fail "http://${INSTANCE_NAME}0.${LOCATION}.cloudapp.azure.com:80/" - retval=$? - if [[ "$retval" == "0" ]]; then break; fi - sleep $wait - count=$((count-1)) -done -if [[ "$retval" != "0" ]]; then - log "DockerCE: gave up waiting for service to be externally reachable" - exit 1 -fi diff --git a/test/common.sh b/test/common.sh index 8be59a2f09..92bd2616b6 100755 --- a/test/common.sh +++ b/test/common.sh @@ -72,7 +72,7 @@ function generate_template() { jqi "${FINAL_CLUSTER_DEFINITION}" ".properties.windowsProfile.secrets[0].vaultCertificates[0].certificateStore = \"My\"" fi # Generate template - "${DIR}/../bin/acs-engine" generate --output-directory "${OUTPUT}" "${FINAL_CLUSTER_DEFINITION}" --debug + "${DIR}/../bin/aks-engine" generate --output-directory "${OUTPUT}" "${FINAL_CLUSTER_DEFINITION}" --debug # Fill in custom hyperkube spec, if it was set if [[ ! -z "${CUSTOM_HYPERKUBE_SPEC:-}" ]]; then diff --git a/test/e2e.sh b/test/e2e.sh index e12812ff81..134a673e2b 100755 --- a/test/e2e.sh +++ b/test/e2e.sh @@ -27,4 +27,4 @@ ROOT="${DIR}/.." make bootstrap build -${ROOT}/test/acs-engine-test/acs-engine-test -c ${TEST_CONFIG} -d ${ROOT} -e ${LOGERROR_CONFIG:-${ROOT}/test/acs-engine-test/acs-engine-errors.json} -j ${SA_NAME} -k ${SA_KEY} +${ROOT}/test/aks-engine-test/aks-engine-test -c ${TEST_CONFIG} -d ${ROOT} -e ${LOGERROR_CONFIG:-${ROOT}/test/aks-engine-test/aks-engine-errors.json} -j ${SA_NAME} -k ${SA_KEY} diff --git a/test/e2e/azure/cli.go b/test/e2e/azure/cli.go index 5026e81045..049fb24ea3 100644 --- a/test/e2e/azure/cli.go +++ b/test/e2e/azure/cli.go @@ -9,9 +9,8 @@ import ( "strconv" "time" - "github.com/Azure/acs-engine/test/e2e/engine" - "github.com/Azure/acs-engine/test/e2e/kubernetes/util" - + "github.com/Azure/aks-engine/test/e2e/engine" + "github.com/Azure/aks-engine/test/e2e/kubernetes/util" "github.com/kelseyhightower/envconfig" ) @@ -48,7 +47,7 @@ type VM struct { Name string `json:"name"` } -// Deployment represents a deployment of an acs cluster +// Deployment represents a deployment of an AKS cluster type Deployment struct { Name string // Name of the deployment TemplateDirectory string // engine.GeneratedDefinitionPath diff --git a/test/e2e/cleanup.sh b/test/e2e/cleanup.sh index 52b94a4eea..d311229caa 100755 --- a/test/e2e/cleanup.sh +++ b/test/e2e/cleanup.sh @@ -40,7 +40,7 @@ az account set -s $SUBSCRIPTION_ID_TO_CLEANUP (( deadline=$(date +%s)-${expirationInSecs%.*} )) # find resource groups created before our deadline echo "Looking for resource groups created over ${EXPIRATION_IN_HOURS} hours ago..." -for resourceGroup in `az group list | jq --arg dl $deadline '.[] | select(.name | contains("acse-test") | not) | select(.tags.now < $dl).name' | tr -d '\"' || ""`; do +for resourceGroup in `az group list | jq --arg dl $deadline '.[] | select(.name | contains("akse-test") | not) | select(.tags.now < $dl).name' | tr -d '\"' || ""`; do for deployment in `az group deployment list -g $resourceGroup | jq '.[] | .name' | tr -d '\"' || ""`; do echo "Will delete deployment ${deployment} from resource group ${resourceGroup}..." az group deployment delete -n $deployment -g $resourceGroup || echo "unable to delete deployment ${deployment}, will continue..." diff --git a/test/e2e/config/config.go b/test/e2e/config/config.go index 6764e0fc3d..013dda8f21 100644 --- a/test/e2e/config/config.go +++ b/test/e2e/config/config.go @@ -12,7 +12,7 @@ import ( "strings" "time" - "github.com/Azure/acs-engine/test/e2e/kubernetes/util" + "github.com/Azure/aks-engine/test/e2e/kubernetes/util" "github.com/kelseyhightower/envconfig" ) @@ -40,10 +40,6 @@ type Config struct { const ( kubernetesOrchestrator = "kubernetes" - dcosOrchestrator = "dcos" - swarmModeOrchestrator = "swarmmode" - swarmOrchestrator = "swarm" - openShiftOrchestrator = "openshift" ) // ParseConfig will parse needed environment variables for running the tests @@ -66,17 +62,7 @@ func (c *Config) GetKubeConfig() string { case c.IsKubernetes(): file := fmt.Sprintf("kubeconfig.%s.json", c.Location) kubeconfigPath = filepath.Join(c.CurrentWorkingDir, "_output", c.Name, "kubeconfig", file) - - case c.IsOpenShift(): - artifactsDir := filepath.Join(c.CurrentWorkingDir, "_output", c.Name) - masterTarball := filepath.Join(artifactsDir, "master.tar.gz") - out, err := exec.Command("tar", "-xzf", masterTarball, "-C", artifactsDir).CombinedOutput() - if err != nil { - log.Fatalf("Cannot untar master tarball: %v: %v", string(out), err) - } - kubeconfigPath = filepath.Join(artifactsDir, "etc", "origin", "master", "admin.kubeconfig") } - return kubeconfigPath } @@ -158,26 +144,6 @@ func (c *Config) IsKubernetes() bool { return c.Orchestrator == kubernetesOrchestrator } -// IsDCOS will return true if the ORCHESTRATOR env var is set to dcos -func (c *Config) IsDCOS() bool { - return c.Orchestrator == dcosOrchestrator -} - -// IsSwarmMode will return true if the ORCHESTRATOR env var is set to dcos -func (c *Config) IsSwarmMode() bool { - return c.Orchestrator == swarmModeOrchestrator -} - -// IsSwarm will return true if the ORCHESTRATOR env var is set to dcos -func (c *Config) IsSwarm() bool { - return c.Orchestrator == swarmOrchestrator -} - -// IsOpenShift will return true if the ORCHESTRATOR env var is set to openshift -func (c *Config) IsOpenShift() bool { - return c.Orchestrator == openShiftOrchestrator -} - // SetRandomRegion sets Location to a random region func (c *Config) SetRandomRegion() { var regions []string diff --git a/test/e2e/dcos-deployments.json b/test/e2e/dcos-deployments.json deleted file mode 100644 index 6055a4c6a6..0000000000 --- a/test/e2e/dcos-deployments.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "deployments": [ - { - "cluster_definition": "disks-managed/dcos-preAttachedDisks-vmas.json", - "location": "eastus" - }, - { - "cluster_definition": "disks-managed/dcos-vmss.json", - "location": "eastus" - }, - { - "cluster_definition": "disks-storageaccount/dcos.json", - "location": "eastus" - }, - { - "cluster_definition": "vnet/dcosvnet.json", - "location": "westus2" - } - ] -} \ No newline at end of file diff --git a/test/e2e/dcos/dcos.go b/test/e2e/dcos/dcos.go deleted file mode 100644 index 07b8f1938c..0000000000 --- a/test/e2e/dcos/dcos.go +++ /dev/null @@ -1,365 +0,0 @@ -package dcos - -import ( - "context" - "encoding/json" - "fmt" - "io/ioutil" - "log" - "strconv" - "strings" - "time" - - "github.com/Azure/acs-engine/test/e2e/config" - "github.com/Azure/acs-engine/test/e2e/engine" - "github.com/Azure/acs-engine/test/e2e/remote" - "github.com/pkg/errors" -) - -// Cluster holds information on how to communicate with the the dcos instances -type Cluster struct { - AdminUsername string - AgentFQDN string - Connection *remote.Connection -} - -// Node represents a node object returned from querying the v1/nodes api -type Node struct { - Host string `json:"host_ip"` - Health int `json:"health"` - Role string `json:"role"` -} - -// List holds a slice of nodes -type List struct { - Nodes []Node `json:"nodes"` -} - -// Version holds response from calling http://localhost:80/dcos-metadata/dcos-version.json -type Version struct { - Version string `json:"version"` -} - -// MarathonApp is the parent struct for a marathon app declared as json -type MarathonApp struct { - ID string `json:"id"` - Instances int `json:"instances"` - CPUS float64 `json:"cpus"` - Memory int `json:"mem"` - Disk int `json:"disk"` - GPUS int `json:"gpus"` - BackoffSeconds int `json:"backoffSeconds"` - BackoffFactor float64 `json:"backoffFactor"` - MaxLaunchDelaySeconds int `json:"maxLaunchDelaySeconds"` - RequirePorts bool `json:"requirePorts"` - KillSelection string `json:"killSelection"` - TaskHealthy int `json:"tasksHealthy"` - TaskRunning int `json:"tasksRunning"` - TaskStaged int `json:"tasksStaged"` - TaskUnhealthy int `json:"tasksUnhealthy"` - Container Container `json:"container"` - HealthChecks []HealthCheck `json:"healthChecks"` - UpgradeStrategy UpgradeStrategy `json:"upgradeStrategy"` - UnreachableStrategy UnreachableStrategy `json:"unreachableStrategy"` - AcceptedResourceRoles []string `json:"acceptedResourceRoles"` - Labels map[string]string `json:"labels"` -} - -// Container holds information about the type of container being deployed -type Container struct { - Type string `json:"type"` - Docker Docker `json:"docker"` -} - -// Docker tells what image is being deployed and its port mappings -type Docker struct { - Image string `json:"image"` - Network string `json:"network"` - Priviledged bool `json:"priviledged"` - ForcePullImage bool `json:"forcePullImage"` - PortMappings []PortMap `json:"portMappings"` -} - -// PortMap is how the ports are exposed to the system and container -type PortMap struct { - Name string `json:"name"` - ContainerPort int `json:"containerPort"` - HostPort int `json:"hostPort"` - ServicePort int `json:"servicePort"` - Protocol string `json:"protocol"` -} - -// HealthCheck contains the information needed to tell DCOS how to health check a given app -type HealthCheck struct { - GracePeriodSeconds int `json:"gracePeriodSeconds"` - IntervalSeconds int `json:"intervalSeconds"` - TimeoutSeconds int `json:"timeoutSeconds"` - MaxConsecutiveFailures int `json:"maxConsecutiveFailures"` - PortIndex int `json:"portIndex"` - Path string `json:"path"` - Protocol string `json:"protocol"` - IgnoreHTTP1xx bool `json:"ignoreHttp1xx"` -} - -// UpgradeStrategy holds how many instances can be up or down during an upgrade -type UpgradeStrategy struct { - MinimumHealthCapacity int `json:"minimumHealthCapacity"` - MaximumOverCapacity int `json:"maximumOverCapacity"` -} - -// UnreachableStrategy tells how long to wait if an instance isnt reachable -type UnreachableStrategy struct { - InactiveAfterSeconds int `json:"inactiveAfterSeconds"` - ExpungeAfterSeconds int `json:"expungeAfterSeconds"` -} - -// NewCluster returns a new cluster struct -func NewCluster(cfg *config.Config, eng *engine.Engine) (*Cluster, error) { - conn, err := remote.NewConnection(fmt.Sprintf("%s.%s.cloudapp.azure.com", cfg.Name, cfg.Location), "2200", eng.ClusterDefinition.Properties.LinuxProfile.AdminUsername, cfg.GetSSHKeyPath()) - if err != nil { - return nil, err - } - return &Cluster{ - AdminUsername: eng.ClusterDefinition.Properties.LinuxProfile.AdminUsername, - AgentFQDN: fmt.Sprintf("%s-0.%s.cloudapp.azure.com", cfg.Name, cfg.Location), - Connection: conn, - }, nil -} - -// InstallDCOSClient will download and place in the path the dcos client -func (c *Cluster) InstallDCOSClient() error { - - out, err := c.Connection.Execute("curl -O https://dcos-mirror.azureedge.net/binaries/cli/linux/x86-64/dcos-1.10/dcos") - if err != nil { - log.Printf("Error downloading DCOS cli:%s\n", err) - log.Printf("Output:%s\n", out) - return err - } - out, err = c.Connection.Execute("chmod a+x dcos") - if err != nil { - log.Printf("Error trying to chmod +x the dcos cli:%s\n", err) - log.Printf("Output:%s\n", out) - return err - } - out, err = c.Connection.Execute("./dcos cluster setup http://localhost:80") - if err != nil { - log.Printf("Error while trying dcos cluster setup:%s\n", err) - log.Printf("Output:%s\n", out) - return err - } - return nil -} - -// WaitForNodes will return an false if the nodes never become healthy -func (c *Cluster) WaitForNodes(nodeCount int, sleep, duration time.Duration) bool { - readyCh := make(chan bool, 1) - errCh := make(chan error) - ctx, cancel := context.WithTimeout(context.Background(), duration) - defer cancel() - go func() { - for { - select { - case <-ctx.Done(): - errCh <- errors.Errorf("Timeout exceeded (%s) while waiting for nodes to become ready", duration.String()) - default: - nodes, err := c.GetNodes() - ready := true - if err == nil { - for _, n := range nodes { - if n.Health != 0 { - ready = false - } - } - } - if ready { - readyCh <- true - } - time.Sleep(sleep) - } - } - }() - for { - select { - case <-errCh: - return false - case ready := <-readyCh: - return ready - } - } -} - -// GetNodes will return a []Node for a given cluster -func (c *Cluster) GetNodes() ([]Node, error) { - out, err := c.Connection.Execute("curl -s http://localhost:1050/system/health/v1/nodes") - if err != nil { - return nil, err - } - list := List{} - err = json.Unmarshal(out, &list) - if err != nil { - log.Printf("Error while trying to unmarshall json:%s\n JSON:%s\n", err, out) - return nil, err - } - return list.Nodes, nil -} - -// NodeCount will return the node count for a dcos cluster -func (c *Cluster) NodeCount() (int, error) { - nodes, err := c.GetNodes() - if err != nil { - return 0, err - } - return len(nodes), nil -} - -// AppCount will determine the number of apps installed -func (c *Cluster) AppCount() (int, error) { - count := 0 - out, err := c.Connection.Execute("./dcos marathon app list | sed -n '1!p' | wc -l") - if err != nil { - log.Printf("Error trying to fetch app count from dcos:%s\n", out) - return count, err - } - - count, err = strconv.Atoi(strings.TrimSpace(string(out))) - if err != nil { - log.Printf("Error trying to parse output to int:%s\n", err) - return count, err - } - // We should not count the marathon-lb as part of the installed app count - if count > 0 { - count = count - 1 - } - return count, nil -} - -// Version will return the node count for a dcos cluster -func (c *Cluster) Version() (string, error) { - out, err := c.Connection.Execute("curl -s http://localhost:80/dcos-metadata/dcos-version.json") - if err != nil { - log.Printf("Error while executing connection:%s\n", err) - } - version := Version{} - err = json.Unmarshal(out, &version) - if err != nil { - log.Printf("Error while trying to unmarshall json:%s\n JSON:%s\n", err, out) - return "", err - } - return version.Version, nil -} - -// InstallMarathonApp will send the marathon.json file to the remote server and install it using the dcos cli -func (c *Cluster) InstallMarathonApp(filepath string, sleep, duration time.Duration) (int, error) { - port := 0 - contents, err := ioutil.ReadFile(filepath) - if err != nil { - log.Printf("Error while trying to read marathon definition at (%s):%s\n", filepath, err) - return 0, err - } - - appCount, err := c.AppCount() - if err != nil { - return port, err - } - var app MarathonApp - json.Unmarshal(contents, &app) - app.ID = fmt.Sprintf("%s-%v", app.ID, appCount) - for idx, pm := range app.Container.Docker.PortMappings { - if pm.Name == "default" { - port = pm.ServicePort + appCount - app.Container.Docker.PortMappings[idx].ServicePort = port - } - } - - appJSON, err := json.Marshal(app) - if err != nil { - log.Printf("Error marshalling json:%s\n", err) - return port, err - } - - fileName := fmt.Sprintf("marathon.%v.json", appCount) - err = c.Connection.Write(strconv.Quote(string(appJSON)), fileName) - if err != nil { - return port, err - } - - if !c.AppExists(app.ID) { - _, err = c.Connection.Execute(fmt.Sprintf("./dcos marathon app add %s", fileName)) - if err != nil { - return 0, err - } - ready := c.WaitOnReady(app.ID, sleep, duration) - if !ready { - return 0, errors.Errorf("App %s was never installed", app.ID) - } - } - return port, nil -} - -// InstallMarathonLB will setup a loadbalancer if one has not been created -func (c *Cluster) InstallMarathonLB() error { - if !c.PackageExists("marathon-lb") { - _, err := c.Connection.Execute("./dcos package install marathon-lb --yes") - if err != nil { - return err - } - } - return nil -} - -// AppExists queries the marathon app list to see if an app exists for a given path -func (c *Cluster) AppExists(path string) bool { - cmd := fmt.Sprintf("./dcos marathon app list | grep %s", path) - _, err := c.Connection.Execute(cmd) - return err == nil -} - -// AppHealthy returns true if the app is deployed and healthy -func (c *Cluster) AppHealthy(path string) bool { - cmd := fmt.Sprintf("./dcos marathon app show %s", path) - out, err := c.Connection.Execute(cmd) - if err != nil { - return false - } - - var app MarathonApp - json.Unmarshal(out, &app) - return app.Instances == app.TaskHealthy -} - -// PackageExists retruns true if the package name is found when doing dcos package list -func (c *Cluster) PackageExists(name string) bool { - cmd := fmt.Sprintf("./dcos package list | grep %s", name) - _, err := c.Connection.Execute(cmd) - return err == nil -} - -// WaitOnReady will block until app is in ready state -func (c *Cluster) WaitOnReady(path string, sleep, duration time.Duration) bool { - readyCh := make(chan bool, 1) - errCh := make(chan error) - ctx, cancel := context.WithTimeout(context.Background(), duration) - defer cancel() - go func() { - for { - select { - case <-ctx.Done(): - errCh <- errors.Errorf("Timeout exceeded (%s) while waiting for app (%s) to become ready", duration.String(), path) - default: - if c.AppExists(path) && c.AppHealthy(path) { - time.Sleep(sleep) - readyCh <- true - } - time.Sleep(sleep) - } - } - }() - for { - select { - case <-errCh: - return false - case ready := <-readyCh: - return ready - } - } -} diff --git a/test/e2e/dcos/dcos_suite_test.go b/test/e2e/dcos/dcos_suite_test.go deleted file mode 100644 index 908efdc29a..0000000000 --- a/test/e2e/dcos/dcos_suite_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package dcos_test - -import ( - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "testing" -) - -func TestDcos(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Dcos Suite") -} diff --git a/test/e2e/dcos/dcos_test.go b/test/e2e/dcos/dcos_test.go deleted file mode 100644 index 5be5a52cac..0000000000 --- a/test/e2e/dcos/dcos_test.go +++ /dev/null @@ -1,93 +0,0 @@ -package dcos - -import ( - "fmt" - "log" - "os" - "path/filepath" - "time" - - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/test/e2e/config" - "github.com/Azure/acs-engine/test/e2e/engine" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var ( - cfg config.Config - eng engine.Engine - err error - cluster *Cluster -) - -var _ = BeforeSuite(func() { - cwd, _ := os.Getwd() - rootPath := filepath.Join(cwd, "../../..") // The current working dir of these tests is down a few levels from the root of the project. We should traverse up that path so we can find the _output dir - c, err := config.ParseConfig() - c.CurrentWorkingDir = rootPath - Expect(err).NotTo(HaveOccurred()) - cfg = *c // We have to do this because golang anon functions and scoping and stuff - - engCfg, err := engine.ParseConfig(c.CurrentWorkingDir, c.ClusterDefinition, c.Name) - Expect(err).NotTo(HaveOccurred()) - cs, err := engine.ParseInput(engCfg.ClusterDefinitionTemplate) - Expect(err).NotTo(HaveOccurred()) - eng = engine.Engine{ - Config: engCfg, - ClusterDefinition: cs, - } - - cluster, err = NewCluster(&cfg, &eng) - Expect(err).NotTo(HaveOccurred()) -}) - -var _ = Describe("Azure Container Cluster using the DCOS Orchestrator", func() { - Context("regardless of agent pool type", func() { - - It("should have have the appropriate node count", func() { - count, err := cluster.NodeCount() - Expect(err).NotTo(HaveOccurred()) - Expect(count).To(Equal(eng.NodeCount())) - }) - - It("should be running the expected version", func() { - version, err := cluster.Version() - Expect(err).NotTo(HaveOccurred()) - - expectedVersion := common.RationalizeReleaseAndVersion( - eng.ClusterDefinition.Properties.OrchestratorProfile.OrchestratorType, - eng.ClusterDefinition.Properties.OrchestratorProfile.OrchestratorRelease, - eng.ClusterDefinition.Properties.OrchestratorProfile.OrchestratorVersion, - false, - false) - Expect(version).To(Equal(expectedVersion)) - }) - - It("should be able to install marathon", func() { - err = cluster.InstallMarathonLB() - if err != nil { - log.Printf("Error while installing Marathon LB: %s\n", err.Error()) - } - Expect(err).NotTo(HaveOccurred()) - - marathonPath := filepath.Join(cfg.CurrentWorkingDir, "/test/e2e/dcos/marathon.json") - port, err := cluster.InstallMarathonApp(marathonPath, 5*time.Second, cfg.Timeout) - if err != nil { - log.Printf("Error while installing Marathon app: %s\n", err.Error()) - } - Expect(err).NotTo(HaveOccurred()) - - // Need to have a wait for ready check here - cmd := fmt.Sprintf("curl -sI http://marathon-lb.marathon.mesos:%v/", port) - out, err := cluster.Connection.ExecuteWithRetries(cmd, 5*time.Second, cfg.Timeout) - if err != nil { - log.Printf("Was not able to run %s, err: %s\n", cmd, err.Error()) - } - Expect(err).NotTo(HaveOccurred()) - Expect(out).To(MatchRegexp("^HTTP/1.1 200 OK")) - }) - - }) -}) diff --git a/test/e2e/dcos/marathon.json b/test/e2e/dcos/marathon.json deleted file mode 100644 index f0e162d9f0..0000000000 --- a/test/e2e/dcos/marathon.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "id": "/nginx", - "instances": 1, - "cpus": 0.1, - "mem": 65, - "disk": 0, - "gpus": 0, - "backoffSeconds": 1, - "backoffFactor": 1.15, - "maxLaunchDelaySeconds": 3600, - "container": { - "type": "DOCKER", - "docker": { - "image": "nginx:1.7.7", - "network": "BRIDGE", - "portMappings": [ - { - "containerPort": 80, - "hostPort": 0, - "servicePort": 10000, - "protocol": "tcp", - "name": "default" - } - ], - "privileged": false, - "forcePullImage": true - } - }, - "healthChecks": [ - { - "gracePeriodSeconds": 10, - "intervalSeconds": 2, - "timeoutSeconds": 10, - "maxConsecutiveFailures": 10, - "portIndex": 0, - "path": "/", - "protocol": "HTTP", - "ignoreHttp1xx": false - } - ], - "upgradeStrategy": { - "minimumHealthCapacity": 1, - "maximumOverCapacity": 1 - }, - "unreachableStrategy": { - "inactiveAfterSeconds": 300, - "expungeAfterSeconds": 600 - }, - "killSelection": "YOUNGEST_FIRST", - "acceptedResourceRoles": [ - "slave_public" - ], - "requirePorts": true, - "labels": { - "HAPROXY_GROUP": "external" - } -} \ No newline at end of file diff --git a/test/e2e/engine/cli.go b/test/e2e/engine/cli.go index ca5bad7df8..961988d07f 100644 --- a/test/e2e/engine/cli.go +++ b/test/e2e/engine/cli.go @@ -4,26 +4,26 @@ import ( "log" "os/exec" - "github.com/Azure/acs-engine/test/e2e/kubernetes/util" + "github.com/Azure/aks-engine/test/e2e/kubernetes/util" ) -// Generate will run acs-engine generate on a given cluster definition +// Generate will run aks-engine generate on a given cluster definition func (e *Engine) Generate() error { - cmd := exec.Command("./bin/acs-engine", "generate", e.Config.ClusterDefinitionTemplate, "--output-directory", e.Config.GeneratedDefinitionPath) + cmd := exec.Command("./bin/aks-engine", "generate", e.Config.ClusterDefinitionTemplate, "--output-directory", e.Config.GeneratedDefinitionPath) util.PrintCommand(cmd) out, err := cmd.CombinedOutput() if err != nil { - log.Printf("Error while trying to generate acs-engine template with cluster definition - %s: %s\n", e.Config.ClusterDefinitionTemplate, err) - log.Printf("Command:./bin/acs-engine generate %s --output-directory %s\n", e.Config.ClusterDefinitionTemplate, e.Config.GeneratedDefinitionPath) + log.Printf("Error while trying to generate aks-engine template with cluster definition - %s: %s\n", e.Config.ClusterDefinitionTemplate, err) + log.Printf("Command:./bin/aks-engine generate %s --output-directory %s\n", e.Config.ClusterDefinitionTemplate, e.Config.GeneratedDefinitionPath) log.Printf("Output:%s\n", out) return err } return nil } -// Deploy will run acs-engine deploy on a given cluster definition +// Deploy will run aks-engine deploy on a given cluster definition func (e *Engine) Deploy(location string) error { - cmd := exec.Command("./bin/acs-engine", "deploy", + cmd := exec.Command("./bin/aks-engine", "deploy", "--location", location, "--api-model", e.Config.ClusterDefinitionPath, "--dns-prefix", e.Config.DefinitionName, @@ -33,7 +33,7 @@ func (e *Engine) Deploy(location string) error { util.PrintCommand(cmd) out, err := cmd.CombinedOutput() if err != nil { - log.Printf("Error while trying to deploy acs-engine template with cluster definition - %s: %s\n", e.Config.ClusterDefinitionTemplate, err) + log.Printf("Error while trying to deploy aks-engine template with cluster definition - %s: %s\n", e.Config.ClusterDefinitionTemplate, err) log.Printf("Output:%s\n", out) return err } diff --git a/test/e2e/engine/template.go b/test/e2e/engine/template.go index a75d91ddd7..fec56c47d2 100644 --- a/test/e2e/engine/template.go +++ b/test/e2e/engine/template.go @@ -1,8 +1,6 @@ package engine import ( - "crypto/rand" - "encoding/base64" "encoding/json" "fmt" "io/ioutil" @@ -10,11 +8,11 @@ import ( "path/filepath" "strings" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/api/vlabs" - "github.com/Azure/acs-engine/pkg/helpers" - "github.com/Azure/acs-engine/pkg/i18n" - "github.com/Azure/acs-engine/test/e2e/config" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/pkg/api/vlabs" + "github.com/Azure/aks-engine/pkg/helpers" + "github.com/Azure/aks-engine/pkg/i18n" + "github.com/Azure/aks-engine/test/e2e/config" "github.com/kelseyhightower/envconfig" "github.com/pkg/errors" ) @@ -41,14 +39,14 @@ type Config struct { ClusterDefinitionPath string // The original template we want to use to build the cluster from. ClusterDefinitionTemplate string // This is the template after we splice in the environment variables - GeneratedDefinitionPath string // Holds the contents of running acs-engine generate + GeneratedDefinitionPath string // Holds the contents of running aks-engine generate OutputPath string // This is the root output path DefinitionName string // Unique cluster name GeneratedTemplatePath string // azuredeploy.json path GeneratedParametersPath string // azuredeploy.parameters.json path } -// Engine holds necessary information to interact with acs-engine cli +// Engine holds necessary information to interact with aks-engine cli type Engine struct { Config *Config ClusterDefinition *api.VlabsARMContainerService // Holds the parsed ClusterDefinition @@ -93,49 +91,12 @@ func Build(cfg *config.Config, masterSubnetID string, agentSubnetID string, isVM Secret: config.ClientSecret, } } - if cfg.IsOpenShift() { - // azProfile - cs.ContainerService.Properties.AzProfile = &vlabs.AzProfile{ - TenantID: config.TenantID, - SubscriptionID: config.SubscriptionID, - ResourceGroup: cfg.Name, - Location: cfg.Location, - } - // openshiftConfig - pass, err := generateRandomString(32) - if err != nil { - return nil, err - } - cs.ContainerService.Properties.OrchestratorProfile.OpenShiftConfig = &vlabs.OpenShiftConfig{ - ClusterUsername: "test-user", - ClusterPassword: pass, - } - // master and agent config - cs.ContainerService.Properties.MasterProfile.Distro = vlabs.Distro(config.Distro) - cs.ContainerService.Properties.MasterProfile.ImageRef = nil - if config.ImageName != "" && config.ImageResourceGroup != "" { - cs.ContainerService.Properties.MasterProfile.ImageRef = &vlabs.ImageReference{ - Name: config.ImageName, - ResourceGroup: config.ImageResourceGroup, - } - } - for i := range cs.ContainerService.Properties.AgentPoolProfiles { - cs.ContainerService.Properties.AgentPoolProfiles[i].Distro = vlabs.Distro(config.Distro) - cs.ContainerService.Properties.AgentPoolProfiles[i].ImageRef = nil - if config.ImageName != "" && config.ImageResourceGroup != "" { - cs.ContainerService.Properties.AgentPoolProfiles[i].ImageRef = &vlabs.ImageReference{ - Name: config.ImageName, - ResourceGroup: config.ImageResourceGroup, - } - } - } - } if config.MasterDNSPrefix != "" { cs.ContainerService.Properties.MasterProfile.DNSPrefix = config.MasterDNSPrefix } - if !cfg.IsKubernetes() && !cfg.IsOpenShift() && config.AgentDNSPrefix != "" { + if !cfg.IsKubernetes() && config.AgentDNSPrefix != "" { for idx, pool := range cs.ContainerService.Properties.AgentPoolProfiles { pool.DNSPrefix = fmt.Sprintf("%v-%v", config.AgentDNSPrefix, idx) } @@ -161,7 +122,7 @@ func Build(cfg *config.Config, masterSubnetID string, agentSubnetID string, isVM // Or, choose the version string if ENV declares it } else if config.OrchestratorVersion != "" { cs.ContainerService.Properties.OrchestratorProfile.OrchestratorVersion = config.OrchestratorVersion - // If ENV similarly has no version opinion, we will rely upon the acs-engine default + // If ENV similarly has no version opinion, we will rely upon the aks-engine default } else { log.Println("No orchestrator version specified, will use the default.") } @@ -284,17 +245,3 @@ func ParseOutput(path string) (*api.ContainerService, error) { } return containerService, nil } - -func generateRandomBytes(n int) ([]byte, error) { - b := make([]byte, n) - _, err := rand.Read(b) - if err != nil { - return nil, err - } - return b, nil -} - -func generateRandomString(s int) (string, error) { - b, err := generateRandomBytes(s) - return base64.URLEncoding.EncodeToString(b), err -} diff --git a/test/e2e/kubernetes/config.go b/test/e2e/kubernetes/config.go index f2509d35e9..a67049751f 100644 --- a/test/e2e/kubernetes/config.go +++ b/test/e2e/kubernetes/config.go @@ -6,7 +6,7 @@ import ( "os/exec" "strings" - "github.com/Azure/acs-engine/test/e2e/kubernetes/util" + "github.com/Azure/aks-engine/test/e2e/kubernetes/util" ) // Config represents a kubernetes config object diff --git a/test/e2e/kubernetes/deployment/deployment.go b/test/e2e/kubernetes/deployment/deployment.go index cd109ff5e1..f986af1a4a 100644 --- a/test/e2e/kubernetes/deployment/deployment.go +++ b/test/e2e/kubernetes/deployment/deployment.go @@ -9,8 +9,8 @@ import ( "strconv" "time" - "github.com/Azure/acs-engine/test/e2e/kubernetes/pod" - "github.com/Azure/acs-engine/test/e2e/kubernetes/util" + "github.com/Azure/aks-engine/test/e2e/kubernetes/pod" + "github.com/Azure/aks-engine/test/e2e/kubernetes/util" "github.com/pkg/errors" ) diff --git a/test/e2e/kubernetes/hpa/hpa.go b/test/e2e/kubernetes/hpa/hpa.go index c5ec40bef6..3e28ca3467 100644 --- a/test/e2e/kubernetes/hpa/hpa.go +++ b/test/e2e/kubernetes/hpa/hpa.go @@ -6,7 +6,7 @@ import ( "os/exec" "time" - "github.com/Azure/acs-engine/test/e2e/kubernetes/util" + "github.com/Azure/aks-engine/test/e2e/kubernetes/util" ) // HPA represents a kubernetes HPA diff --git a/test/e2e/kubernetes/job/job.go b/test/e2e/kubernetes/job/job.go index fcb4d4b05f..3331d08d0d 100644 --- a/test/e2e/kubernetes/job/job.go +++ b/test/e2e/kubernetes/job/job.go @@ -8,8 +8,8 @@ import ( "regexp" "time" - "github.com/Azure/acs-engine/test/e2e/kubernetes/pod" - "github.com/Azure/acs-engine/test/e2e/kubernetes/util" + "github.com/Azure/aks-engine/test/e2e/kubernetes/pod" + "github.com/Azure/aks-engine/test/e2e/kubernetes/util" "github.com/pkg/errors" ) diff --git a/test/e2e/kubernetes/kubernetes_test.go b/test/e2e/kubernetes/kubernetes_test.go index fdcb5596db..c5e3f0a663 100644 --- a/test/e2e/kubernetes/kubernetes_test.go +++ b/test/e2e/kubernetes/kubernetes_test.go @@ -11,21 +11,21 @@ import ( "strings" "time" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/test/e2e/config" - "github.com/Azure/acs-engine/test/e2e/engine" - "github.com/Azure/acs-engine/test/e2e/kubernetes/deployment" - "github.com/Azure/acs-engine/test/e2e/kubernetes/hpa" - "github.com/Azure/acs-engine/test/e2e/kubernetes/job" - "github.com/Azure/acs-engine/test/e2e/kubernetes/namespace" - "github.com/Azure/acs-engine/test/e2e/kubernetes/networkpolicy" - "github.com/Azure/acs-engine/test/e2e/kubernetes/node" - "github.com/Azure/acs-engine/test/e2e/kubernetes/persistentvolume" - "github.com/Azure/acs-engine/test/e2e/kubernetes/persistentvolumeclaims" - "github.com/Azure/acs-engine/test/e2e/kubernetes/pod" - "github.com/Azure/acs-engine/test/e2e/kubernetes/service" - "github.com/Azure/acs-engine/test/e2e/kubernetes/storageclass" - "github.com/Azure/acs-engine/test/e2e/kubernetes/util" + "github.com/Azure/aks-engine/pkg/api/common" + "github.com/Azure/aks-engine/test/e2e/config" + "github.com/Azure/aks-engine/test/e2e/engine" + "github.com/Azure/aks-engine/test/e2e/kubernetes/deployment" + "github.com/Azure/aks-engine/test/e2e/kubernetes/hpa" + "github.com/Azure/aks-engine/test/e2e/kubernetes/job" + "github.com/Azure/aks-engine/test/e2e/kubernetes/namespace" + "github.com/Azure/aks-engine/test/e2e/kubernetes/networkpolicy" + "github.com/Azure/aks-engine/test/e2e/kubernetes/node" + "github.com/Azure/aks-engine/test/e2e/kubernetes/persistentvolume" + "github.com/Azure/aks-engine/test/e2e/kubernetes/persistentvolumeclaims" + "github.com/Azure/aks-engine/test/e2e/kubernetes/pod" + "github.com/Azure/aks-engine/test/e2e/kubernetes/service" + "github.com/Azure/aks-engine/test/e2e/kubernetes/storageclass" + "github.com/Azure/aks-engine/test/e2e/kubernetes/util" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) diff --git a/test/e2e/kubernetes/namespace/namespace.go b/test/e2e/kubernetes/namespace/namespace.go index 19717b451c..686d85f17f 100644 --- a/test/e2e/kubernetes/namespace/namespace.go +++ b/test/e2e/kubernetes/namespace/namespace.go @@ -6,7 +6,7 @@ import ( "os/exec" "time" - "github.com/Azure/acs-engine/test/e2e/kubernetes/util" + "github.com/Azure/aks-engine/test/e2e/kubernetes/util" ) // Namespace holds namespace metadata diff --git a/test/e2e/kubernetes/networkpolicy/networkpolicy.go b/test/e2e/kubernetes/networkpolicy/networkpolicy.go index b7aaa0549f..c25392de26 100644 --- a/test/e2e/kubernetes/networkpolicy/networkpolicy.go +++ b/test/e2e/kubernetes/networkpolicy/networkpolicy.go @@ -4,7 +4,7 @@ import ( "log" "os/exec" - "github.com/Azure/acs-engine/test/e2e/kubernetes/util" + "github.com/Azure/aks-engine/test/e2e/kubernetes/util" ) // CreateNetworkPolicyFromFile will create a NetworkPolicy from file with a name diff --git a/test/e2e/kubernetes/node/node.go b/test/e2e/kubernetes/node/node.go index 85b0569971..e6dd2e6111 100644 --- a/test/e2e/kubernetes/node/node.go +++ b/test/e2e/kubernetes/node/node.go @@ -9,7 +9,7 @@ import ( "strings" "time" - "github.com/Azure/acs-engine/test/e2e/kubernetes/util" + "github.com/Azure/aks-engine/test/e2e/kubernetes/util" "github.com/pkg/errors" ) diff --git a/test/e2e/kubernetes/persistentvolume/persistentvolume.go b/test/e2e/kubernetes/persistentvolume/persistentvolume.go index 380a3252e9..24b028e7a0 100644 --- a/test/e2e/kubernetes/persistentvolume/persistentvolume.go +++ b/test/e2e/kubernetes/persistentvolume/persistentvolume.go @@ -7,7 +7,7 @@ import ( "os/exec" "time" - "github.com/Azure/acs-engine/test/e2e/kubernetes/util" + "github.com/Azure/aks-engine/test/e2e/kubernetes/util" "github.com/pkg/errors" ) diff --git a/test/e2e/kubernetes/persistentvolumeclaims/persistentvolumeclaims.go b/test/e2e/kubernetes/persistentvolumeclaims/persistentvolumeclaims.go index df02ed7e06..eea636858a 100644 --- a/test/e2e/kubernetes/persistentvolumeclaims/persistentvolumeclaims.go +++ b/test/e2e/kubernetes/persistentvolumeclaims/persistentvolumeclaims.go @@ -8,7 +8,7 @@ import ( "os/exec" "time" - "github.com/Azure/acs-engine/test/e2e/kubernetes/util" + "github.com/Azure/aks-engine/test/e2e/kubernetes/util" "github.com/pkg/errors" ) diff --git a/test/e2e/kubernetes/pod/pod.go b/test/e2e/kubernetes/pod/pod.go index fdc9789567..b1e6148aac 100644 --- a/test/e2e/kubernetes/pod/pod.go +++ b/test/e2e/kubernetes/pod/pod.go @@ -11,8 +11,8 @@ import ( "strings" "time" - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/test/e2e/kubernetes/util" + "github.com/Azure/aks-engine/pkg/api" + "github.com/Azure/aks-engine/test/e2e/kubernetes/util" "github.com/pkg/errors" ) diff --git a/test/e2e/kubernetes/service/service.go b/test/e2e/kubernetes/service/service.go index a2113f1bb4..bd5e1de661 100644 --- a/test/e2e/kubernetes/service/service.go +++ b/test/e2e/kubernetes/service/service.go @@ -11,7 +11,7 @@ import ( "regexp" "time" - "github.com/Azure/acs-engine/test/e2e/kubernetes/util" + "github.com/Azure/aks-engine/test/e2e/kubernetes/util" "github.com/pkg/errors" ) diff --git a/test/e2e/kubernetes/storageclass/storageclass.go b/test/e2e/kubernetes/storageclass/storageclass.go index 2009e388fb..24871eca0e 100644 --- a/test/e2e/kubernetes/storageclass/storageclass.go +++ b/test/e2e/kubernetes/storageclass/storageclass.go @@ -7,7 +7,7 @@ import ( "os/exec" "time" - "github.com/Azure/acs-engine/test/e2e/kubernetes/util" + "github.com/Azure/aks-engine/test/e2e/kubernetes/util" "github.com/pkg/errors" ) diff --git a/test/e2e/openshift/OWNERS b/test/e2e/openshift/OWNERS deleted file mode 100644 index 4e1cf8514f..0000000000 --- a/test/e2e/openshift/OWNERS +++ /dev/null @@ -1,4 +0,0 @@ -approvers: -- jim-minter -- kargakis -- pweil- diff --git a/test/e2e/openshift/node/node.go b/test/e2e/openshift/node/node.go deleted file mode 100644 index 4c009df58c..0000000000 --- a/test/e2e/openshift/node/node.go +++ /dev/null @@ -1,29 +0,0 @@ -package node - -import ( - "errors" - "fmt" - "log" - "os/exec" - "regexp" - "strings" -) - -// Version returns the version of an OpenShift cluster. -func Version() (string, error) { - cmd := exec.Command("oc", "version") - fmt.Printf("\n$ %s\n", strings.Join(cmd.Args, " ")) - out, err := cmd.CombinedOutput() - if err != nil { - log.Printf("Error trying to run 'oc version':%s", string(out)) - return "", err - } - exp := regexp.MustCompile(`(openshift\s)+(v\d+.\d+.\d+)+`) - for _, line := range strings.Split(string(out), "\n") { - if strings.HasPrefix(line, "openshift") { - s := exp.FindStringSubmatch(line) - return s[2], nil - } - } - return "", errors.New("cannot find openshift version") -} diff --git a/test/e2e/openshift/openshift_suite_test.go b/test/e2e/openshift/openshift_suite_test.go deleted file mode 100644 index 1f2db1fece..0000000000 --- a/test/e2e/openshift/openshift_suite_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package openshift_test - -import ( - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "testing" -) - -func TestOpenShift(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "OpenShift Suite") -} diff --git a/test/e2e/openshift/openshift_test.go b/test/e2e/openshift/openshift_test.go deleted file mode 100644 index d5e4c442cd..0000000000 --- a/test/e2e/openshift/openshift_test.go +++ /dev/null @@ -1,173 +0,0 @@ -package openshift - -import ( - "os" - "path/filepath" - "strings" - "time" - - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/Azure/acs-engine/test/e2e/config" - "github.com/Azure/acs-engine/test/e2e/engine" - knode "github.com/Azure/acs-engine/test/e2e/kubernetes/node" - "github.com/Azure/acs-engine/test/e2e/kubernetes/pod" - "github.com/Azure/acs-engine/test/e2e/openshift/node" - "github.com/Azure/acs-engine/test/e2e/openshift/util" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var ( - cfg config.Config - eng engine.Engine -) - -var _ = BeforeSuite(func() { - cwd, _ := os.Getwd() - rootPath := filepath.Join(cwd, "../../..") // The current working dir of these tests is down a few levels from the root of the project. We should traverse up that path so we can find the _output dir - c, err := config.ParseConfig() - c.CurrentWorkingDir = rootPath - Expect(err).NotTo(HaveOccurred()) - cfg = *c // We have to do this because golang anon functions and scoping and stuff - - engCfg, err := engine.ParseConfig(c.CurrentWorkingDir, c.ClusterDefinition, c.Name) - Expect(err).NotTo(HaveOccurred()) - csInput, err := engine.ParseInput(engCfg.ClusterDefinitionTemplate) - Expect(err).NotTo(HaveOccurred()) - csGenerated, err := engine.ParseOutput(engCfg.GeneratedDefinitionPath + "/apimodel.json") - Expect(err).NotTo(HaveOccurred()) - eng = engine.Engine{ - Config: engCfg, - ClusterDefinition: csInput, - ExpandedDefinition: csGenerated, - } -}) - -var _ = Describe("Azure Container Cluster using the OpenShift Orchestrator", func() { - - It("should have bootstrap autoapprover running", func() { - running, err := pod.WaitOnReady("bootstrap-autoapprover", "openshift-infra", 3, 30*time.Second, cfg.Timeout) - Expect(err).NotTo(HaveOccurred()) - Expect(running).To(Equal(true)) - }) - - It("should have have the appropriate node count", func() { - ready := knode.WaitOnReady(eng.NodeCount(), 10*time.Second, cfg.Timeout) - Expect(ready).To(Equal(true)) - }) - - It("should label nodes correctly", func() { - labels := map[string]map[string]string{ - "master": { - "node-role.kubernetes.io/master": "true", - "openshift-infra": "apiserver", - }, - "compute": { - "node-role.kubernetes.io/compute": "true", - "region": "primary", - }, - "infra": { - "region": "infra", - }, - } - list, err := knode.Get() - Expect(err).NotTo(HaveOccurred()) - - for _, node := range list.Nodes { - kind := strings.Split(node.Metadata.Name, "-")[1] - Expect(labels).To(HaveKey(kind)) - for k, v := range labels[kind] { - Expect(node.Metadata.Labels).To(HaveKeyWithValue(k, v)) - } - } - }) - - It("should be running the expected version", func() { - version, err := node.Version() - Expect(err).NotTo(HaveOccurred()) - // normalize patch version to zero so we can support testing - // across centos and rhel deployments where patch versions diverge. - version = strings.Join(append(strings.Split(version, ".")[:2], "0"), ".") - - var expectedVersion string - if eng.ClusterDefinition.Properties.OrchestratorProfile.OrchestratorRelease != "" || - eng.ClusterDefinition.Properties.OrchestratorProfile.OrchestratorVersion != "" { - expectedVersion = common.RationalizeReleaseAndVersion( - common.OpenShift, - eng.ClusterDefinition.Properties.OrchestratorProfile.OrchestratorRelease, - eng.ClusterDefinition.Properties.OrchestratorProfile.OrchestratorVersion, - false, - false) - } else { - expectedVersion = common.RationalizeReleaseAndVersion( - common.OpenShift, - eng.Config.OrchestratorRelease, - eng.Config.OrchestratorVersion, - false, - false) - } - expectedVersionRationalized := strings.Split(expectedVersion, "-")[0] // to account for -alpha and -beta suffixes - - // skip unstable test as the version will constantly be changing - if expectedVersionRationalized != "unstable" { - Expect(version).To(Equal("v" + expectedVersionRationalized)) - } - }) - - It("should have router running", func() { - running, err := pod.WaitOnReady("router", "default", 3, 30*time.Second, cfg.Timeout) - Expect(err).NotTo(HaveOccurred()) - Expect(running).To(Equal(true)) - }) - - It("should have docker-registry running", func() { - running, err := pod.WaitOnReady("docker-registry", "default", 3, 30*time.Second, cfg.Timeout) - Expect(err).NotTo(HaveOccurred()) - Expect(running).To(Equal(true)) - }) - - It("should have registry-console running", func() { - running, err := pod.WaitOnReady("registry-console", "default", 3, 30*time.Second, cfg.Timeout) - Expect(err).NotTo(HaveOccurred()) - Expect(running).To(Equal(true)) - }) - - It("should deploy a sample app and access it via a route", func() { - err := util.ApplyFromTemplate("nginx-example", "openshift", "default") - Expect(err).NotTo(HaveOccurred()) - Expect(util.WaitForDeploymentConfig("nginx-example", "default")).NotTo(HaveOccurred()) - host, err := util.GetHost("nginx-example", "default") - Expect(err).NotTo(HaveOccurred()) - Expect(util.TestHost(host, 10, 200*time.Millisecond)).NotTo(HaveOccurred()) - }) - - It("should have the openshift webconsole running", func() { - running, err := pod.WaitOnReady("webconsole", "openshift-web-console", 3, 30*time.Second, cfg.Timeout) - Expect(err).NotTo(HaveOccurred()) - Expect(running).To(Equal(true)) - }) - - It("should have prometheus running", func() { - running, err := pod.WaitOnReady("prometheus", "openshift-metrics", 3, 30*time.Second, cfg.Timeout) - Expect(err).NotTo(HaveOccurred()) - Expect(running).To(Equal(true)) - }) - - It("should have service catalog apiserver running", func() { - running, err := pod.WaitOnReady("apiserver", "kube-service-catalog", 3, 30*time.Second, cfg.Timeout) - Expect(err).NotTo(HaveOccurred()) - Expect(running).To(Equal(true)) - }) - - It("should have service catalog controller-manager running", func() { - running, err := pod.WaitOnReady("controller-manager", "kube-service-catalog", 3, 30*time.Second, cfg.Timeout) - Expect(err).NotTo(HaveOccurred()) - Expect(running).To(Equal(true)) - }) - - It("should have template service broker running", func() { - running, err := pod.WaitOnReady("asb", "openshift-ansible-service-broker", 3, 30*time.Second, cfg.Timeout) - Expect(err).NotTo(HaveOccurred()) - Expect(running).To(Equal(true)) - }) -}) diff --git a/test/e2e/openshift/util/util.go b/test/e2e/openshift/util/util.go deleted file mode 100644 index 54448749ae..0000000000 --- a/test/e2e/openshift/util/util.go +++ /dev/null @@ -1,375 +0,0 @@ -package util - -import ( - "fmt" - "io/ioutil" - "log" - "net/http" - "os" - "os/exec" - "path/filepath" - "strings" - "time" - - kerrors "k8s.io/apimachinery/pkg/util/errors" - - "github.com/Azure/acs-engine/pkg/api" - "github.com/Azure/acs-engine/pkg/api/common" - "github.com/pkg/errors" -) - -func printCmd(cmd *exec.Cmd) { - fmt.Printf("\n$ %s\n", strings.Join(cmd.Args, " ")) -} - -// ApplyFromTemplate processes and creates the provided templateName/templateNamespace template -// in the provided namespace. -func ApplyFromTemplate(templateName, templateNamespace, namespace string) error { - processCmd := exec.Command("oc", "process", templateName, "-n", templateNamespace) - printCmd(processCmd) - out, err := processCmd.CombinedOutput() - if err != nil { - return errors.Wrapf(err, "cannot process template %s\noutput: %s", templateName, string(out)) - } - if err := ioutil.WriteFile(templateName, out, 0644); err != nil { - return errors.Wrapf(err, "cannot create tempfile for processed template %s", templateName) - } - defer os.Remove(templateName) - createCmd := exec.Command("oc", "apply", "-n", namespace, "-f", templateName) - printCmd(createCmd) - out, err = createCmd.CombinedOutput() - if err != nil { - return errors.Wrapf(err, "cannot apply processed template %s\noutput: %s", templateName, string(out)) - } - return nil -} - -// WaitForDeploymentConfig waits until the provided deploymentconfig namespace/name -// gets deployed. -func WaitForDeploymentConfig(name, namespace string) error { - cmd := exec.Command("oc", "rollout", "status", fmt.Sprintf("dc/%s", name), "-n", namespace) - printCmd(cmd) - out, err := cmd.CombinedOutput() - if err != nil { - log.Printf("Error trying to see the rollout status of dc/%s: %s", name, string(out)) - return err - } - return nil -} - -// GetHost expects the name and namespace of a route in order to -// return its host. -func GetHost(name, namespace string) (string, error) { - cmd := exec.Command("oc", "get", fmt.Sprintf("route/%s", name), "-n", namespace, "-o", "jsonpath={.spec.host}") - printCmd(cmd) - out, err := cmd.CombinedOutput() - if err != nil { - log.Printf("Error trying to get the hostname of route/%s: %s", name, string(out)) - return "", err - } - return string(out), nil -} - -// TestHost tries to access host and retries maxRetries times with a retryDelay -// that is doubled on every retry. -func TestHost(host string, maxRetries int, retryDelay time.Duration) error { - backoff := retryDelay - url := fmt.Sprintf("http://%s", host) - - resp, err := http.Get(url) - if err == nil && resp.StatusCode == http.StatusOK { - return nil - } - if err == nil { - log.Printf("got status %q while trying to access %s", resp.Status, host) - resp.Body.Close() - } else { - log.Printf("error while trying to access %s: %v", host, err) - } - for retries := 1; retries <= maxRetries; retries++ { - log.Printf("Retry #%d to access %s", retries, host) - resp, err = http.Get(url) - if err != nil { - log.Printf("error while trying to access %s: %v", host, err) - continue - } - resp.Body.Close() - if resp.StatusCode == http.StatusOK { - return nil - } - log.Printf("got status %q while trying to access %s", resp.Status, host) - log.Printf("sleeping for %fs", backoff.Seconds()) - time.Sleep(backoff) - backoff *= 2 - } - if err != nil { - return err - } - return errors.Errorf("unexpected response status: %v", resp.Status) -} - -// DumpNodes dumps information about nodes. -func DumpNodes() (string, error) { - cmd := exec.Command("oc", "get", "nodes", "-o", "wide") - printCmd(cmd) - out, err := cmd.CombinedOutput() - if err != nil { - log.Printf("Error trying to list nodes: %s", string(out)) - return "", err - } - return string(out), nil -} - -// DumpPods dumps the pods from all namespaces. -func DumpPods() (string, error) { - cmd := exec.Command("oc", "get", "pods", "--all-namespaces", "-o", "wide") - printCmd(cmd) - out, err := cmd.CombinedOutput() - if err != nil { - log.Printf("Error trying to list pods from all namespaces: %s", string(out)) - return "", err - } - return string(out), nil -} - -// FetchLogs returns logs for the provided kind/name in namespace. -func FetchLogs(kind, namespace, name string) string { - cmd := exec.Command("oc", "logs", fmt.Sprintf("%s/%s", kind, name), "-n", namespace) - printCmd(cmd) - out, err := cmd.CombinedOutput() - if err != nil { - return fmt.Sprintf("Error trying to fetch logs from %s/%s in %s: %s", kind, name, namespace, string(out)) - } - return string(out) -} - -// FetchClusterInfo returns node and pod information about the cluster. -func FetchClusterInfo(logPath string) error { - needsLog := map[string]func() (string, error){ - "node-info": DumpNodes, - "pod-info": DumpPods, - } - - var errs []error - for base, logFn := range needsLog { - logs, err := logFn() - if err != nil { - errs = append(errs, err) - continue - } - path := filepath.Join(logPath, base) - if err := ioutil.WriteFile(path, []byte(logs), 0644); err != nil { - errs = append(errs, err) - } - } - - return kerrors.NewAggregate(errs) -} - -// FetchOpenShiftLogs returns logs for all OpenShift components -// (control plane and infra). -func FetchOpenShiftLogs(distro, version, sshKeyPath, adminName, name, location, logPath string) error { - if err := fetchControlPlaneLogs(distro, version, sshKeyPath, adminName, name, location, logPath); err != nil { - return errors.Wrap(err, "cannot fetch logs for control plane components: %v") - } - if err := fetchInfraLogs(logPath); err != nil { - return errors.Wrap(err, "cannot fetch logs for infra components: %v") - } - return nil -} - -// fetchControlPlaneLogs returns logs for Openshift control plane components. -func fetchControlPlaneLogs(distro, version, sshKeyPath, adminName, name, location, logPath string) error { - sshAddress := fmt.Sprintf("%s@%s.%s.cloudapp.azure.com", adminName, name, location) - - switch version { - case common.OpenShiftVersion3Dot9Dot0: - return fetch39ControlPlaneLogs(distro, sshKeyPath, sshAddress, logPath) - case common.OpenShiftVersionUnstable: - return fetchUnstableControlPlaneLogs(distro, sshKeyPath, sshAddress, name, logPath) - default: - return errors.Errorf("invalid OpenShift version %q - won't gather logs from the control plane", version) - } -} - -func fetch39ControlPlaneLogs(distro, sshKeyPath, sshAddress, logPath string) error { - var errs []error - for _, service := range getSystemdServices(distro) { - cmdToExec := fmt.Sprintf("sudo journalctl -u %s.service", service) - out := remoteExec(sshKeyPath, sshAddress, cmdToExec) - path := filepath.Join(logPath, service) - if err := ioutil.WriteFile(path, out, 0644); err != nil { - errs = append(errs, err) - } - } - - return kerrors.NewAggregate(errs) -} - -func getSystemdServices(distro string) []string { - services := []string{"etcd"} - switch api.Distro(distro) { - case api.OpenShift39RHEL: - services = append(services, "atomic-openshift-master-api", "atomic-openshift-master-controllers", "atomic-openshift-node") - case api.OpenShiftCentOS: - services = append(services, "origin-master-api", "origin-master-controllers", "origin-node") - default: - log.Printf("Will not gather journal for the control plane because invalid OpenShift distro was specified: %q", distro) - } - return services -} - -func remoteExec(sshKeyPath, sshAddress, cmdToExec string) []byte { - cmd := exec.Command("ssh", "-i", sshKeyPath, "-o", "ConnectTimeout=10", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", sshAddress, cmdToExec) - out, err := cmd.Output() - if err != nil { - log.Printf("Cannot execute remote command %q: %v", cmdToExec, err) - } - return out -} - -type resource struct { - kind string - namespace string - name string -} - -func (r resource) String() string { - return fmt.Sprintf("%s_%s_%s", r.namespace, r.kind, r.name) -} - -// TODO: Promote to 3.10 when the time comes -func fetchUnstableControlPlaneLogs(distro, sshKeyPath, sshAddress, name, logPath string) error { - controlPlane := []resource{ - {kind: "pod", namespace: "kube-system", name: fmt.Sprintf("master-api-ocp-master-%s-0", name)}, - {kind: "pod", namespace: "kube-system", name: fmt.Sprintf("master-controllers-ocp-master-%s-0", name)}, - {kind: "pod", namespace: "kube-system", name: fmt.Sprintf("master-etcd-ocp-master-%s-0", name)}, - } - - var errs []error - for _, r := range controlPlane { - log := FetchLogs(r.kind, r.namespace, r.name) - path := filepath.Join(logPath, r.name) - if err := ioutil.WriteFile(path, []byte(log), 0644); err != nil { - errs = append(errs, err) - } - } - - for _, service := range getSystemdServices(distro) { - // 3.10+ deployments run only the node process as a systemd service - if service != "atomic-openshift-node" && service != "origin-node" { - continue - } - cmdToExec := fmt.Sprintf("sudo journalctl -u %s.service", service) - out := remoteExec(sshKeyPath, sshAddress, cmdToExec) - path := filepath.Join(logPath, service) - if err := ioutil.WriteFile(path, out, 0644); err != nil { - errs = append(errs, err) - } - } - - return kerrors.NewAggregate(errs) -} - -// fetchInfraLogs returns logs for Openshift infra components. -// TODO: Eventually we may need to version this too. -func fetchInfraLogs(logPath string) error { - infraResources := []resource{ - // TODO: Maybe collapse this list and the actual readiness check tests - // in openshift e2e. - {kind: "deploymentconfig", namespace: "default", name: "router"}, - {kind: "deploymentconfig", namespace: "default", name: "docker-registry"}, - {kind: "deploymentconfig", namespace: "default", name: "registry-console"}, - {kind: "statefulset", namespace: "openshift-infra", name: "bootstrap-autoapprover"}, - {kind: "statefulset", namespace: "openshift-metrics", name: "prometheus"}, - {kind: "daemonset", namespace: "kube-service-catalog", name: "apiserver"}, - {kind: "daemonset", namespace: "kube-service-catalog", name: "controller-manager"}, - {kind: "deploymentconfig", namespace: "openshift-ansible-service-broker", name: "asb"}, - {kind: "deploymentconfig", namespace: "openshift-ansible-service-broker", name: "asb-etcd"}, - {kind: "daemonset", namespace: "openshift-template-service-broker", name: "apiserver"}, - {kind: "deployment", namespace: "openshift-web-console", name: "webconsole"}, - } - - var errs []error - for _, r := range infraResources { - log := FetchLogs(r.kind, r.namespace, r.name) - path := filepath.Join(logPath, "infra-"+r.String()) - err := ioutil.WriteFile(path, []byte(log), 0644) - if err != nil { - errs = append(errs, err) - } - } - - return kerrors.NewAggregate(errs) -} - -// FetchOpenShiftMetrics gathers metrics from etcd and the control plane. -func FetchOpenShiftMetrics(logPath string) error { - var errs []error - - // api server metrics - cmd := exec.Command("oc", "get", "--raw", "https://localhost:8443/metrics") - printCmd(cmd) - out, err := cmd.CombinedOutput() - if err != nil { - errs = append(errs, errors.Wrap(err, "cannot get api server metrics")) - } else { - path := filepath.Join(logPath, "api-server-metrics") - err := ioutil.WriteFile(path, []byte(out), 0644) - if err != nil { - errs = append(errs, errors.Wrap(err, "cannot write api server metrics: ")) - } - } - - // controller manager metrics - cmd = exec.Command("oc", "get", "--raw", "https://localhost:8444/metrics") - printCmd(cmd) - out, err = cmd.CombinedOutput() - if err != nil { - errs = append(errs, errors.Wrap(err, "cannot get controller manager metrics")) - } else { - path := filepath.Join(logPath, "controller-manager-metrics") - err := ioutil.WriteFile(path, []byte(out), 0644) - if err != nil { - errs = append(errs, errors.Wrap(err, "cannot write controller manager metrics")) - } - } - - // etcd metrics - cmd = exec.Command("oc", "get", "--raw", "https://localhost:2380/metrics") - printCmd(cmd) - out, err = cmd.CombinedOutput() - if err != nil { - errs = append(errs, errors.Wrap(err, "cannot get etcd metrics")) - } else { - path := filepath.Join(logPath, "etcd-metrics") - err := ioutil.WriteFile(path, []byte(out), 0644) - if err != nil { - errs = append(errs, errors.Wrap(err, "cannot write etcd metrics")) - } - } - - return kerrors.NewAggregate(errs) -} - -// FetchWaagentLogs returns stdout and stderr from waagent. -func FetchWaagentLogs(sshKeyPath, adminName, name, location, logPath string) error { - sshAddress := fmt.Sprintf("%s@%s.%s.cloudapp.azure.com", adminName, name, location) - - paths := []string{ - "/var/lib/waagent/custom-script/download/0/stderr", - "/var/lib/waagent/custom-script/download/0/stdout", - } - - var errs []error - for _, path := range paths { - cmdToExec := fmt.Sprintf("sudo cat %s", path) - out := remoteExec(sshKeyPath, sshAddress, cmdToExec) - logPath := filepath.Join(logPath, fmt.Sprintf("waagent-%s", filepath.Base(path))) - if err := ioutil.WriteFile(logPath, out, 0644); err != nil { - errs = append(errs, errors.Wrapf(err, "Cannot write to path %s", logPath)) - } - } - - return kerrors.NewAggregate(errs) -} diff --git a/test/e2e/remote/ssh.go b/test/e2e/remote/ssh.go index 31c7f0c0ac..55cdf86797 100644 --- a/test/e2e/remote/ssh.go +++ b/test/e2e/remote/ssh.go @@ -11,7 +11,7 @@ import ( "path/filepath" "time" - "github.com/Azure/acs-engine/test/e2e/kubernetes/util" + "github.com/Azure/aks-engine/test/e2e/kubernetes/util" "github.com/pkg/errors" "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/agent" diff --git a/test/e2e/runner.go b/test/e2e/runner.go index 2915c50bd1..2d1543df84 100644 --- a/test/e2e/runner.go +++ b/test/e2e/runner.go @@ -8,12 +8,11 @@ import ( "path/filepath" "time" - "github.com/Azure/acs-engine/test/e2e/azure" - "github.com/Azure/acs-engine/test/e2e/config" - "github.com/Azure/acs-engine/test/e2e/engine" - "github.com/Azure/acs-engine/test/e2e/metrics" - outil "github.com/Azure/acs-engine/test/e2e/openshift/util" - "github.com/Azure/acs-engine/test/e2e/runner" + "github.com/Azure/aks-engine/test/e2e/azure" + "github.com/Azure/aks-engine/test/e2e/config" + "github.com/Azure/aks-engine/test/e2e/engine" + "github.com/Azure/aks-engine/test/e2e/metrics" + "github.com/Azure/aks-engine/test/e2e/runner" ) var ( @@ -63,8 +62,8 @@ func main() { // Soak test specific setup if cfg.SoakClusterName != "" { - sa.Name = "acsesoaktests" + cfg.Location - sa.ResourceGroup.Name = "acse-test-infrastructure-storage" + sa.Name = "aksesoaktests" + cfg.Location + sa.ResourceGroup.Name = "akse-test-infrastructure-storage" sa.ResourceGroup.Location = cfg.Location err = sa.CreateStorageAccount() if err != nil { @@ -197,24 +196,6 @@ func teardown() { log.Printf("cliProvisioner.FetchProvisioningMetrics error: %s\n", err) } } - if cliProvisioner.Config.IsOpenShift() { - sshKeyPath := cfg.GetSSHKeyPath() - adminName := eng.ClusterDefinition.Properties.LinuxProfile.AdminUsername - version := eng.Config.OrchestratorVersion - distro := eng.Config.Distro - if err := outil.FetchWaagentLogs(sshKeyPath, adminName, cfg.Name, cfg.Location, logsPath); err != nil { - log.Printf("cannot fetch waagent logs: %v", err) - } - if err := outil.FetchOpenShiftLogs(distro, version, sshKeyPath, adminName, cfg.Name, cfg.Location, logsPath); err != nil { - log.Printf("cannot get openshift logs: %v", err) - } - if err := outil.FetchClusterInfo(logsPath); err != nil { - log.Printf("cannot get pod and node info: %v", err) - } - if err := outil.FetchOpenShiftMetrics(logsPath); err != nil { - log.Printf("cannot fetch openshift metrics: %v", err) - } - } if !cfg.SkipLogsCollection { if err := cliProvisioner.FetchActivityLog(acct, logsPath); err != nil { log.Printf("cannot fetch the activity log: %v", err) diff --git a/test/e2e/runner/cli_provisioner.go b/test/e2e/runner/cli_provisioner.go index 3a02741bca..14310f09c5 100644 --- a/test/e2e/runner/cli_provisioner.go +++ b/test/e2e/runner/cli_provisioner.go @@ -11,18 +11,15 @@ import ( "strings" "time" + "github.com/Azure/aks-engine/pkg/helpers" + "github.com/Azure/aks-engine/test/e2e/azure" + "github.com/Azure/aks-engine/test/e2e/config" + "github.com/Azure/aks-engine/test/e2e/engine" + "github.com/Azure/aks-engine/test/e2e/kubernetes/node" + "github.com/Azure/aks-engine/test/e2e/kubernetes/util" + "github.com/Azure/aks-engine/test/e2e/metrics" + "github.com/Azure/aks-engine/test/e2e/remote" "github.com/kelseyhightower/envconfig" - - "github.com/Azure/acs-engine/pkg/helpers" - "github.com/Azure/acs-engine/test/e2e/azure" - "github.com/Azure/acs-engine/test/e2e/config" - "github.com/Azure/acs-engine/test/e2e/dcos" - "github.com/Azure/acs-engine/test/e2e/engine" - "github.com/Azure/acs-engine/test/e2e/kubernetes/node" - "github.com/Azure/acs-engine/test/e2e/kubernetes/util" - "github.com/Azure/acs-engine/test/e2e/metrics" - onode "github.com/Azure/acs-engine/test/e2e/openshift/node" - "github.com/Azure/acs-engine/test/e2e/remote" "github.com/pkg/errors" ) @@ -153,7 +150,7 @@ func (cli *CLIProvisioner) provision() error { } } - // Lets modify our template and call acs-engine generate on it + // Lets modify our template and call aks-engine generate on it var eng *engine.Engine if cli.CreateVNET && cli.MasterVMSS { @@ -203,12 +200,12 @@ func (cli *CLIProvisioner) generateAndDeploy() error { fmt.Printf("Provisionning with the Deploy Command\n") err := cli.Engine.Deploy(cli.Config.Location) if err != nil { - return errors.Wrap(err, "Error while trying to deploy acs-engine template") + return errors.Wrap(err, "Error while trying to deploy aks-engine template") } } else { err := cli.Engine.Generate() if err != nil { - return errors.Wrap(err, "Error while trying to generate acs-engine template") + return errors.Wrap(err, "Error while trying to generate aks-engine template") } } @@ -226,9 +223,9 @@ func (cli *CLIProvisioner) generateAndDeploy() error { } cli.Engine.ExpandedDefinition = csGenerated - // Both Openshift and Kubernetes deployments should have a kubeconfig available + // Kubernetes deployments should have a kubeconfig available // at this point. - if (cli.Config.IsKubernetes() || cli.Config.IsOpenShift()) && !cli.IsPrivate() { + if cli.Config.IsKubernetes() && !cli.IsPrivate() { cli.Config.SetKubeConfig() } @@ -251,7 +248,7 @@ func (cli *CLIProvisioner) generateName() string { } func (cli *CLIProvisioner) waitForNodes() error { - if cli.Config.IsKubernetes() || cli.Config.IsOpenShift() { + if cli.Config.IsKubernetes() { if !cli.IsPrivate() { log.Println("Waiting on nodes to go into ready state...") ready := node.WaitOnReady(cli.Engine.NodeCount(), 10*time.Second, cli.Config.Timeout) @@ -262,8 +259,6 @@ func (cli *CLIProvisioner) waitForNodes() error { var err error if cli.Config.IsKubernetes() { version, err = node.Version() - } else if cli.Config.IsOpenShift() { - version, err = onode.Version() } if err != nil { log.Printf("Ready nodes did not return a version: %s", err) @@ -280,25 +275,6 @@ func (cli *CLIProvisioner) waitForNodes() error { } } - if cli.Config.IsDCOS() { - host := fmt.Sprintf("%s.%s.cloudapp.azure.com", cli.Config.Name, cli.Config.Location) - user := cli.Engine.ClusterDefinition.Properties.LinuxProfile.AdminUsername - log.Printf("SSH Key: %s\n", cli.Config.GetSSHKeyPath()) - log.Printf("Master Node: %s@%s\n", user, host) - log.Printf("SSH Command: ssh -i %s -p 2200 %s@%s", cli.Config.GetSSHKeyPath(), user, host) - cluster, err := dcos.NewCluster(cli.Config, cli.Engine) - if err != nil { - return err - } - err = cluster.InstallDCOSClient() - if err != nil { - return errors.Wrap(err, "Error trying to install dcos client") - } - ready := cluster.WaitForNodes(cli.Engine.NodeCount(), 10*time.Second, cli.Config.Timeout) - if !ready { - return errors.New("Error: Not all nodes in a healthy state") - } - } return nil } @@ -355,7 +331,7 @@ func (cli *CLIProvisioner) FetchProvisioningMetrics(path string, cfg *config.Con // IsPrivate will return true if the cluster has no public IPs func (cli *CLIProvisioner) IsPrivate() bool { - return (cli.Config.IsKubernetes() || cli.Config.IsOpenShift()) && + return cli.Config.IsKubernetes() && cli.Engine.ExpandedDefinition.Properties.OrchestratorProfile.KubernetesConfig.PrivateCluster != nil && helpers.IsTrueBoolPointer(cli.Engine.ExpandedDefinition.Properties.OrchestratorProfile.KubernetesConfig.PrivateCluster.Enabled) } diff --git a/test/e2e/runner/ginkgo.go b/test/e2e/runner/ginkgo.go index ab6cf36394..5399bc47b7 100644 --- a/test/e2e/runner/ginkgo.go +++ b/test/e2e/runner/ginkgo.go @@ -6,9 +6,9 @@ import ( "os" "os/exec" - "github.com/Azure/acs-engine/test/e2e/config" - "github.com/Azure/acs-engine/test/e2e/kubernetes/util" - "github.com/Azure/acs-engine/test/e2e/metrics" + "github.com/Azure/aks-engine/test/e2e/config" + "github.com/Azure/aks-engine/test/e2e/kubernetes/util" + "github.com/Azure/aks-engine/test/e2e/metrics" "github.com/kelseyhightower/envconfig" ) @@ -48,7 +48,7 @@ func (g *Ginkgo) Run() error { err = cmd.Wait() if err != nil { g.Point.RecordTestError() - if g.Config.IsKubernetes() || g.Config.IsOpenShift() { + if g.Config.IsKubernetes() { kubectl := exec.Command("kubectl", "get", "all", "--all-namespaces", "-o", "wide") util.PrintCommand(kubectl) kubectl.CombinedOutput() diff --git a/test/e2e/swarm-deployments.json b/test/e2e/swarm-deployments.json deleted file mode 100644 index 0292c5999a..0000000000 --- a/test/e2e/swarm-deployments.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "deployments": [ - { - "cluster_definition": "swarm.json", - "location": "westus2" - }, - { - "cluster_definition": "disks-managed/swarm-preAttachedDisks-vmss.json", - "location": "westus2" - } - ] -} \ No newline at end of file diff --git a/test/e2e/swarmmode-deployments.json b/test/e2e/swarmmode-deployments.json deleted file mode 100644 index f788f53341..0000000000 --- a/test/e2e/swarmmode-deployments.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "deployments": [ - { - "cluster_definition": "disks-managed/swarmmode-vmas.json", - "location": "westus2" - }, - { - "cluster_definition": "disks-managed/swarmmode-vmss.json", - "location": "westus2" - }, - { - "cluster_definition": "disks-storageaccount/swarmmode.json", - "location": "westus2" - }, - { - "cluster_definition": "v20170131/swarmmode.json", - "location": "westus2" - }, - { - "cluster_definition": "vnet/swarmmodevnet.json", - "location": "westus2" - } - ] -} diff --git a/test/i18n/i18ntestinput.go b/test/i18n/i18ntestinput.go index 4ce8fa690c..7b8272432e 100644 --- a/test/i18n/i18ntestinput.go +++ b/test/i18n/i18ntestinput.go @@ -1,7 +1,7 @@ package fake import ( - "github.com/Azure/acs-engine/pkg/i18n" + "github.com/Azure/aks-engine/pkg/i18n" "github.com/leonelquinteros/gotext" ) @@ -12,7 +12,7 @@ import ( // 4. msginit -l en_US -o i18ntestinput.po -i i18ntestinput.pot // 5. Modify i18ntestinput.po using poedit as necessary // Or msgfmt -c -v -o i18ntestinput.mo i18ntestinput.po -// 6. for d in "en_US"; do cp i18ntestinput.mo translations/test/$d/LC_MESSAGES/acsengine.mo; cp i18ntestinput.po translations/test/$d/LC_MESSAGES/acsengine.po; done +// 6. for d in "en_US"; do cp i18ntestinput.mo translations/test/$d/LC_MESSAGES/aksengine.mo; cp i18ntestinput.po translations/test/$d/LC_MESSAGES/aksengine.po; done // 7. rm i18ntestinput.* var ( diff --git a/test/step.sh b/test/step.sh index 7225ea195b..9bd05d1c6a 100755 --- a/test/step.sh +++ b/test/step.sh @@ -29,16 +29,16 @@ create_resource_group) ;; predeploy) - ACSE_PREDEPLOY=${ACSE_PREDEPLOY:-} - if [ ! -z "${ACSE_PREDEPLOY}" ] && [ -x "${ACSE_PREDEPLOY}" ]; then - "${ACSE_PREDEPLOY}" + AKSE_PREDEPLOY=${AKSE_PREDEPLOY:-} + if [ ! -z "${AKSE_PREDEPLOY}" ] && [ -x "${AKSE_PREDEPLOY}" ]; then + "${AKSE_PREDEPLOY}" fi ;; postdeploy) - ACSE_POSTDEPLOY=${ACSE_POSTDEPLOY:-} - if [ ! -z "${ACSE_POSTDEPLOY}" ] && [ -x "${ACSE_POSTDEPLOY}" ]; then - "${ACSE_POSTDEPLOY}" + AKSE_POSTDEPLOY=${AKSE_POSTDEPLOY:-} + if [ ! -z "${AKSE_POSTDEPLOY}" ] && [ -x "${AKSE_POSTDEPLOY}" ]; then + "${AKSE_POSTDEPLOY}" fi ;; diff --git a/translations/cs_CZ/LC_MESSAGES/acsengine.mo b/translations/cs_CZ/LC_MESSAGES/aksengine.mo similarity index 100% rename from translations/cs_CZ/LC_MESSAGES/acsengine.mo rename to translations/cs_CZ/LC_MESSAGES/aksengine.mo diff --git a/translations/cs_CZ/LC_MESSAGES/acsengine.po b/translations/cs_CZ/LC_MESSAGES/aksengine.po similarity index 88% rename from translations/cs_CZ/LC_MESSAGES/acsengine.po rename to translations/cs_CZ/LC_MESSAGES/aksengine.po index 31f931540f..cbe1e21eaa 100644 --- a/translations/cs_CZ/LC_MESSAGES/acsengine.po +++ b/translations/cs_CZ/LC_MESSAGES/aksengine.po @@ -1,10 +1,10 @@ -# English translations for acs-engine package. +# English translations for aks-engine package. # Copyright (C) 2017 -# This file is distributed under the same license as the acs-engine package. +# This file is distributed under the same license as the aks-engine package. # Jiangtian Li , 2017. msgid "" msgstr "" -"Project-Id-Version: acsengine\n" +"Project-Id-Version: aksengine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-25 00:04+0000\n" "PO-Revision-Date: 2017-07-24 17:23-0700\n" @@ -17,7 +17,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.0.3\n" -#: pkg/acsengine/engine.go:239 +#: pkg/engine/engine.go:239 #, c-format msgid "Error reading file %s, Error: %s" msgstr "Došlo k chybě při čtení souboru %s, chyba: %s" @@ -27,12 +27,12 @@ msgstr "Došlo k chybě při čtení souboru %s, chyba: %s" msgid "Error while querying ARM for resources: %+v" msgstr "Došlo k chybě při dotazování ARM na prostředky: %+v" -#: pkg/acsengine/transform.go:99 +#: pkg/engine/transform.go:99 #, c-format msgid "Found 2 resources with type %s in the template. There should only be 1" msgstr "V šabloně se našly dva prostředky typu %s. Měl by v ní být jenom jeden." -#: pkg/acsengine/transform.go:122 +#: pkg/engine/transform.go:122 #, c-format msgid "" "Found no resources with type %s in the template. There should have been 1" @@ -55,12 +55,12 @@ msgstr "Upgrade na Kubernetes 1.6.2 není podporovaný od verze: %s." msgid "Upgrade to Kubernetes version: %s is not supported from version: %s" msgstr "Upgrade na Kubernetes verze: %s není podporovaný od verze: %s." -#: pkg/acsengine/filesaver.go:24 +#: pkg/engine/filesaver.go:24 #, c-format msgid "error creating directory '%s': %s" msgstr "došlo k chybě při vytváření adresáře %s: %s" -#: pkg/acsengine/engine.go:1194 +#: pkg/engine/engine.go:1194 #, c-format msgid "error executing template for file %s: %v" msgstr "došlo k chybě při spouštění šablony pro soubor %s: %v" @@ -72,7 +72,7 @@ msgstr "došlo k chybě při spouštění šablony pro soubor %s: %v" msgid "error generating upgrade template: %s" msgstr "došlo k chybě při generování šablony upgradu: %s" -#: pkg/acsengine/engine.go:1189 +#: pkg/engine/engine.go:1189 #, c-format msgid "error parsing file %s: %v" msgstr "došlo k chybě při parsování souboru %s: %v" @@ -82,12 +82,12 @@ msgstr "došlo k chybě při parsování souboru %s: %v" msgid "error reading file %s: %s" msgstr "došlo k chybě při čtení souboru %s: %s" -#: pkg/acsengine/ssh.go:55 +#: pkg/engine/ssh.go:55 #, c-format msgid "failed to create openssh public key string: %q" msgstr "nepovedlo se vytvořit řetězec veřejného klíče openssh: %q" -#: pkg/acsengine/ssh.go:49 +#: pkg/engine/ssh.go:49 #, c-format msgid "failed to generate private key for ssh: %q" msgstr "nepovedlo se vygenerovat privátní klíč pro ssh: %q" @@ -102,12 +102,12 @@ msgstr "nepovedlo se inicializovat generátor šablony: %s" msgid "invalid version %s for conversion back from unversioned object" msgstr "neplatná verze %s pro převod zpět z objektu bez označení verze" -#: pkg/acsengine/engine.go:322 +#: pkg/engine/engine.go:322 #, c-format msgid "orchestrator '%s' is unsupported" msgstr "orchestrátor %s není podporovaný" -#: pkg/acsengine/engine.go:187 +#: pkg/engine/engine.go:187 #, c-format msgid "template file %s does not exist" msgstr "soubor šablony %s neexistuje" @@ -117,7 +117,7 @@ msgstr "soubor šablony %s neexistuje" msgid "unrecognized APIVersion '%s'" msgstr "nerozpoznaná verze API %s" -#: pkg/acsengine/engine.go:1183 +#: pkg/engine/engine.go:1183 #, c-format msgid "yaml file %s does not exist" msgstr "soubor yaml %s neexistuje" diff --git a/translations/de_DE/LC_MESSAGES/acsengine.mo b/translations/de_DE/LC_MESSAGES/aksengine.mo similarity index 100% rename from translations/de_DE/LC_MESSAGES/acsengine.mo rename to translations/de_DE/LC_MESSAGES/aksengine.mo diff --git a/translations/de_DE/LC_MESSAGES/acsengine.po b/translations/de_DE/LC_MESSAGES/aksengine.po similarity index 88% rename from translations/de_DE/LC_MESSAGES/acsengine.po rename to translations/de_DE/LC_MESSAGES/aksengine.po index 0f091267ed..110b7fe8d7 100644 --- a/translations/de_DE/LC_MESSAGES/acsengine.po +++ b/translations/de_DE/LC_MESSAGES/aksengine.po @@ -1,10 +1,10 @@ -# English translations for acs-engine package. +# English translations for aks-engine package. # Copyright (C) 2017 -# This file is distributed under the same license as the acs-engine package. +# This file is distributed under the same license as the aks-engine package. # Jiangtian Li , 2017. msgid "" msgstr "" -"Project-Id-Version: acsengine\n" +"Project-Id-Version: aksengine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-25 00:04+0000\n" "PO-Revision-Date: 2017-07-24 17:23-0700\n" @@ -17,7 +17,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.0.3\n" -#: pkg/acsengine/engine.go:239 +#: pkg/engine/engine.go:239 #, c-format msgid "Error reading file %s, Error: %s" msgstr "Fehler beim Lesen der Datei \"%s\", Fehler: %s" @@ -27,14 +27,14 @@ msgstr "Fehler beim Lesen der Datei \"%s\", Fehler: %s" msgid "Error while querying ARM for resources: %+v" msgstr "Fehler beim Abfragen von ARM für Ressourcen: %+v" -#: pkg/acsengine/transform.go:99 +#: pkg/engine/transform.go:99 #, c-format msgid "Found 2 resources with type %s in the template. There should only be 1" msgstr "" "In der Vorlage wurden zwei Ressourcen vom Typ \"%s\" gefunden. Es darf nur " "eine vorliegen." -#: pkg/acsengine/transform.go:122 +#: pkg/engine/transform.go:122 #, c-format msgid "" "Found no resources with type %s in the template. There should have been 1" @@ -62,12 +62,12 @@ msgstr "" "Ein Upgrade auf die Kubernetes-Version %s wird von Version %s aus nicht " "unterstützt." -#: pkg/acsengine/filesaver.go:24 +#: pkg/engine/filesaver.go:24 #, c-format msgid "error creating directory '%s': %s" msgstr "Fehler beim Erstellen des Verzeichnisses \"%s\": %s" -#: pkg/acsengine/engine.go:1194 +#: pkg/engine/engine.go:1194 #, c-format msgid "error executing template for file %s: %v" msgstr "Fehler beim Ausführen der Vorlage für die Datei \"%s\": %v" @@ -79,7 +79,7 @@ msgstr "Fehler beim Ausführen der Vorlage für die Datei \"%s\": %v" msgid "error generating upgrade template: %s" msgstr "Fehler beim Generieren der Upgradevorlage: %s" -#: pkg/acsengine/engine.go:1189 +#: pkg/engine/engine.go:1189 #, c-format msgid "error parsing file %s: %v" msgstr "Fehler beim Analysieren der Datei \"%s\": %v" @@ -89,14 +89,14 @@ msgstr "Fehler beim Analysieren der Datei \"%s\": %v" msgid "error reading file %s: %s" msgstr "Fehler beim Lesen der Datei \"%s\": %s" -#: pkg/acsengine/ssh.go:55 +#: pkg/engine/ssh.go:55 #, c-format msgid "failed to create openssh public key string: %q" msgstr "" "Fehler beim Erstellen der Zeichenfolge des öffentlichen OpenSSH-Schlüssels: " "%q" -#: pkg/acsengine/ssh.go:49 +#: pkg/engine/ssh.go:49 #, c-format msgid "failed to generate private key for ssh: %q" msgstr "Fehler beim Generieren des privaten Schlüssels für SSH: %q" @@ -113,12 +113,12 @@ msgstr "" "Ungültige Version (%s) für die Rückkonvertierung des Objekts ohne " "Versionsangabe." -#: pkg/acsengine/engine.go:322 +#: pkg/engine/engine.go:322 #, c-format msgid "orchestrator '%s' is unsupported" msgstr "Der Orchestrator \"%s\" wird nicht unterstützt." -#: pkg/acsengine/engine.go:187 +#: pkg/engine/engine.go:187 #, c-format msgid "template file %s does not exist" msgstr "Die Vorlagendatei \"%s\" ist nicht vorhanden." @@ -128,7 +128,7 @@ msgstr "Die Vorlagendatei \"%s\" ist nicht vorhanden." msgid "unrecognized APIVersion '%s'" msgstr "Unbekannte APIVersion \"%s\"." -#: pkg/acsengine/engine.go:1183 +#: pkg/engine/engine.go:1183 #, c-format msgid "yaml file %s does not exist" msgstr "Die YAML-Datei \"%s\" ist nicht vorhanden." diff --git a/translations/en_US/LC_MESSAGES/aksengine.mo b/translations/en_US/LC_MESSAGES/aksengine.mo new file mode 100644 index 0000000000000000000000000000000000000000..959e81d01cf760c6408660a87d5418ded0a5893d GIT binary patch literal 2658 zcmeH{O^+Kz5QdwOEUftsa6o{l2rWri#@J3^!z_*nW{nnN#ag@(w`e?5p6O)VJ?ZIj z>>xPt7dRquLgH5-A%w)AKp=s{0f{pb2i~3;$1B4D!F5|IKl4#le!Hrse>i>eGlBIq z>^a!Cu;*dvefYup5hU;@a2q^vLWn-t1oy!Ld;|O%?1F!QJ#goKA|J(&HgI|IK{sO)LZk(!gz63st`yTiywA}!m-_ILW{HX^j zoo&$RoP$p1H=xt`C)fl12P>VQfKKNZ;1>8j=yd*Gb91xO`6B3a9)M2g$Dq^s6-eN( zpwqe8sC1qOoz6Z8nc`s>N+hry0jUBq1VY4Pu+y;Rf_u51!tWC>$PiD$9))46;&B*C zSoRGN55XRB7wc=!7;VUK5J?r&M5atz`72aD_HijHhdYUTbGu-(aDG<~1~e(-a$T5^ zbGUBLL|+#wq7Ks4kLixI3E4&FvXWF}6DG^kEDbC-X_T;G$`f6r5owh!Xw1~E(b+EQL*nKmwLV)T?|Y;vhpS+swSKH~8&a&Xz15UsJU)7j8c|ut+PGv~9ctN=}NC@}aV&z_oVakl0VHiqJH&O^*bCpV38Km;=YILX$ z*QQh<)eP^WWeeP_xm2N6b;)TQgtw|T70YLkt;aV}Q=v_mFjNL8Z&_W}okHE~uUHkf z`aUSq7zQ^3JeRo@g+gz1tROL>E5rTk)hLv?#3Goc%MWWkaA>qs;O$3V9ph6F=B#3= zxN*R4zPv#m%gB4Xh;whGeQFG^jl5nt7Fv1lpmsiWTJ0ULwc~YOqgKmrUEFSA!O=V5 znRHXR?st*eJAUT^V&HcbpM^Ivfy(h&x{|&p0~Mp@impm}^XBp{m2V~5PSNsasHc|^ zr{W@r*&A^%^=VJVsmzmmk9}fwZZ;PDao_ak&|NRE%d|9=Gj1+b|S4*&oF literal 0 HcmV?d00001 diff --git a/translations/en_US/LC_MESSAGES/aksengine.po b/translations/en_US/LC_MESSAGES/aksengine.po new file mode 100644 index 0000000000..c49b50fc23 --- /dev/null +++ b/translations/en_US/LC_MESSAGES/aksengine.po @@ -0,0 +1,132 @@ +# English translations for aks-engine package. +# Copyright (C) 2017 +# This file is distributed under the same license as the aks-engine package. +# Jiangtian Li , 2017. +# +msgid "" +msgstr "" +"Project-Id-Version: aksengine\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-25 00:04+0000\n" +"PO-Revision-Date: 2017-07-24 17:23-0700\n" +"Last-Translator: Jiangtian Li \n" +"Language-Team: English\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 2.0.3\n" + +#: pkg/operations/kubernetesupgrade/upgrader.go:202 +#: pkg/operations/kubernetesupgrade/upgrader.go:217 +#, c-format +msgid "Error generating upgrade template: %s" +msgstr "Error generating upgrade template: %s" + +#: pkg/engine/engine.go:251 +#, c-format +msgid "Error reading file %s, Error: %s" +msgstr "Error reading file %s, Error: %s" + +#: pkg/operations/kubernetesupgrade/upgradecluster.go:76 +#, c-format +msgid "Error while querying ARM for resources: %+v" +msgstr "Error while querying ARM for resources: %+v" + +#: pkg/engine/transform/transform.go:121 +#: pkg/engine/transform/transform.go:129 +#, c-format +msgid "Found 2 resources with type %s in the template. There should only be 1" +msgstr "Found 2 resources with type %s in the template. There should only be 1" + +#: pkg/engine/transform/transform.go:158 +#, c-format +msgid "" +"Found no resources with type %s in the template. There should have been 1" +msgstr "" +"Found no resources with type %s in the template. There should have been 1" + +#: pkg/operations/kubernetesupgrade/upgradeagentnode.go:125 +#, c-format +msgid "Node was not ready within %v" +msgstr "Node was not ready within %v" + +#: pkg/api/apiloader.go:205 pkg/api/apiloader.go:210 pkg/api/apiloader.go:225 +#: pkg/api/apiloader.go:230 +#, c-format +msgid "The selected orchestrator version '%s' is not supported" +msgstr "The selected orchestrator version '%s' is not supported" + +#: pkg/operations/kubernetesupgrade/upgrader.go:120 +#, c-format +msgid "Total count of master VMs: %d exceeded expected count: %d" +msgstr "Total count of master VMs: %d exceeded expected count: %d" + +#: pkg/operations/kubernetesupgrade/upgradecluster.go:110 +#, c-format +msgid "Upgrade to Kubernetes version %s is not supported" +msgstr "Upgrade to Kubernetes version %s is not supported" + +#: pkg/engine/filesaver.go:26 +#, c-format +msgid "error creating directory '%s': %s" +msgstr "error creating directory '%s': %s" + +#: pkg/engine/engine.go:2545 +#, c-format +msgid "error executing template for file %s: %v" +msgstr "error executing template for file %s: %v" + +#: pkg/operations/kubernetesupgrade/upgrader.go:78 +#: pkg/operations/kubernetesupgrade/upgrader.go:391 +#, c-format +msgid "error generating upgrade template: %s" +msgstr "error generating upgrade template: %s" + +#: pkg/engine/engine.go:2540 +#, c-format +msgid "error parsing file %s: %v" +msgstr "error parsing file %s: %v" + +#: pkg/api/apiloader.go:32 +#, c-format +msgid "error reading file %s: %s" +msgstr "error reading file %s: %s" + +#: pkg/operations/kubernetesupgrade/upgrader.go:385 +#, c-format +msgid "failed to initialize template generator: %s" +msgstr "failed to initialize template generator: %s" + +#: pkg/api/apiloader.go:342 pkg/api/apiloader.go:369 +#, c-format +msgid "invalid version %s for conversion back from unversioned object" +msgstr "invalid version %s for conversion back from unversioned object" + +#: pkg/engine/engine.go:399 +#, c-format +msgid "orchestrator '%s' is unsupported" +msgstr "orchestrator '%s' is unsupported" + +#: pkg/engine/engine.go:195 +#, c-format +msgid "template file %s does not exist" +msgstr "template file %s does not exist" + +#: pkg/api/apiloader.go:184 +#, c-format +msgid "unrecognized APIVersion '%s'" +msgstr "unrecognized APIVersion '%s'" + +#: pkg/api/apiloader.go:272 +#, c-format +msgid "" +"unrecognized APIVersion in LoadContainerServiceForAgentPoolOnlyCluster '%s'" +msgstr "" +"unrecognized APIVersion in LoadContainerServiceForAgentPoolOnlyCluster '%s'" + +#: pkg/engine/engine.go:2534 +#, c-format +msgid "yaml file %s does not exist" +msgstr "yaml file %s does not exist" diff --git a/translations/en_US/LC_MESSAGES/acsengine.po.lcg b/translations/en_US/LC_MESSAGES/aksengine.po.lcg similarity index 98% rename from translations/en_US/LC_MESSAGES/acsengine.po.lcg rename to translations/en_US/LC_MESSAGES/aksengine.po.lcg index 5a83acc743..afb8ac478c 100644 --- a/translations/en_US/LC_MESSAGES/acsengine.po.lcg +++ b/translations/en_US/LC_MESSAGES/aksengine.po.lcg @@ -1,5 +1,5 @@ - + diff --git a/translations/en_US/LC_MESSAGES/en-US/lcl/acsengine.po.lcl b/translations/en_US/LC_MESSAGES/en-US/lcl/aksengine.po.lcl similarity index 99% rename from translations/en_US/LC_MESSAGES/en-US/lcl/acsengine.po.lcl rename to translations/en_US/LC_MESSAGES/en-US/lcl/aksengine.po.lcl index 6de2b3b832..887517a53b 100644 --- a/translations/en_US/LC_MESSAGES/en-US/lcl/acsengine.po.lcl +++ b/translations/en_US/LC_MESSAGES/en-US/lcl/aksengine.po.lcl @@ -1,5 +1,5 @@ - + diff --git a/translations/en_US/LC_MESSAGES/en-US/metadata/acsengine.po.xml b/translations/en_US/LC_MESSAGES/en-US/metadata/aksengine.po.xml similarity index 80% rename from translations/en_US/LC_MESSAGES/en-US/metadata/acsengine.po.xml rename to translations/en_US/LC_MESSAGES/en-US/metadata/aksengine.po.xml index 2aecc79b7f..c83a8bee47 100644 --- a/translations/en_US/LC_MESSAGES/en-US/metadata/acsengine.po.xml +++ b/translations/en_US/LC_MESSAGES/en-US/metadata/aksengine.po.xml @@ -1,5 +1,5 @@ - + @@ -9,7 +9,7 @@ - + @@ -21,14 +21,14 @@ - - + + - + @@ -59,13 +59,13 @@ - + - + @@ -78,7 +78,7 @@ - + @@ -102,13 +102,13 @@ - + - + @@ -126,18 +126,18 @@ - + - + - + - - - + + + \ No newline at end of file diff --git a/translations/es_ES/LC_MESSAGES/acsengine.mo b/translations/es_ES/LC_MESSAGES/aksengine.mo similarity index 100% rename from translations/es_ES/LC_MESSAGES/acsengine.mo rename to translations/es_ES/LC_MESSAGES/aksengine.mo diff --git a/translations/es_ES/LC_MESSAGES/acsengine.po b/translations/es_ES/LC_MESSAGES/aksengine.po similarity index 88% rename from translations/es_ES/LC_MESSAGES/acsengine.po rename to translations/es_ES/LC_MESSAGES/aksengine.po index 8d75309a23..c9596b3b13 100644 --- a/translations/es_ES/LC_MESSAGES/acsengine.po +++ b/translations/es_ES/LC_MESSAGES/aksengine.po @@ -1,10 +1,10 @@ -# English translations for acs-engine package. +# English translations for aks-engine package. # Copyright (C) 2017 -# This file is distributed under the same license as the acs-engine package. +# This file is distributed under the same license as the aks-engine package. # Jiangtian Li , 2017. msgid "" msgstr "" -"Project-Id-Version: acsengine\n" +"Project-Id-Version: aksengine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-25 00:04+0000\n" "PO-Revision-Date: 2017-07-24 17:23-0700\n" @@ -17,7 +17,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.0.3\n" -#: pkg/acsengine/engine.go:239 +#: pkg/engine/engine.go:239 #, c-format msgid "Error reading file %s, Error: %s" msgstr "Error al leer el archivo %s. Error: %s" @@ -27,14 +27,14 @@ msgstr "Error al leer el archivo %s. Error: %s" msgid "Error while querying ARM for resources: %+v" msgstr "Error al consultar ARM para los recursos: %+v" -#: pkg/acsengine/transform.go:99 +#: pkg/engine/transform.go:99 #, c-format msgid "Found 2 resources with type %s in the template. There should only be 1" msgstr "" "Se encontraron dos recursos con el tipo %s en la plantilla. Solo debería " "haber uno." -#: pkg/acsengine/transform.go:122 +#: pkg/engine/transform.go:122 #, c-format msgid "" "Found no resources with type %s in the template. There should have been 1" @@ -63,12 +63,12 @@ msgstr "" "La actualización a la versión %s de Kubernetes no se admite desde la versión " "%s." -#: pkg/acsengine/filesaver.go:24 +#: pkg/engine/filesaver.go:24 #, c-format msgid "error creating directory '%s': %s" msgstr "Error al crear el directorio \"%s\": %s" -#: pkg/acsengine/engine.go:1194 +#: pkg/engine/engine.go:1194 #, c-format msgid "error executing template for file %s: %v" msgstr "Error al ejecutar la plantilla para el archivo %s: %v" @@ -80,7 +80,7 @@ msgstr "Error al ejecutar la plantilla para el archivo %s: %v" msgid "error generating upgrade template: %s" msgstr "Error al generar la plantilla de actualización: %s" -#: pkg/acsengine/engine.go:1189 +#: pkg/engine/engine.go:1189 #, c-format msgid "error parsing file %s: %v" msgstr "Error al analizar el archivo %s: %v" @@ -90,12 +90,12 @@ msgstr "Error al analizar el archivo %s: %v" msgid "error reading file %s: %s" msgstr "Error al leer el archivo %s: %s" -#: pkg/acsengine/ssh.go:55 +#: pkg/engine/ssh.go:55 #, c-format msgid "failed to create openssh public key string: %q" msgstr "No se pudo crear la cadena de clave pública de OpenSSH: %q." -#: pkg/acsengine/ssh.go:49 +#: pkg/engine/ssh.go:49 #, c-format msgid "failed to generate private key for ssh: %q" msgstr "No se pudo generar la clave privada para SSH: %q." @@ -111,12 +111,12 @@ msgid "invalid version %s for conversion back from unversioned object" msgstr "" "La versión %s no es válida para la conversión desde un objeto sin versión." -#: pkg/acsengine/engine.go:322 +#: pkg/engine/engine.go:322 #, c-format msgid "orchestrator '%s' is unsupported" msgstr "El orquestador \"%s\" no se admite." -#: pkg/acsengine/engine.go:187 +#: pkg/engine/engine.go:187 #, c-format msgid "template file %s does not exist" msgstr "No existe el archivo de plantilla %s." @@ -126,7 +126,7 @@ msgstr "No existe el archivo de plantilla %s." msgid "unrecognized APIVersion '%s'" msgstr "No se reconoce ApiVersion \"%s\"." -#: pkg/acsengine/engine.go:1183 +#: pkg/engine/engine.go:1183 #, c-format msgid "yaml file %s does not exist" msgstr "No existe el archivo de YAML %s." diff --git a/translations/fr_FR/LC_MESSAGES/acsengine.mo b/translations/fr_FR/LC_MESSAGES/aksengine.mo similarity index 100% rename from translations/fr_FR/LC_MESSAGES/acsengine.mo rename to translations/fr_FR/LC_MESSAGES/aksengine.mo diff --git a/translations/fr_FR/LC_MESSAGES/acsengine.po b/translations/fr_FR/LC_MESSAGES/aksengine.po similarity index 88% rename from translations/fr_FR/LC_MESSAGES/acsengine.po rename to translations/fr_FR/LC_MESSAGES/aksengine.po index 980185f7b7..ec229ae0c9 100644 --- a/translations/fr_FR/LC_MESSAGES/acsengine.po +++ b/translations/fr_FR/LC_MESSAGES/aksengine.po @@ -1,10 +1,10 @@ -# English translations for acs-engine package. +# English translations for aks-engine package. # Copyright (C) 2017 -# This file is distributed under the same license as the acs-engine package. +# This file is distributed under the same license as the aks-engine package. # Jiangtian Li , 2017. msgid "" msgstr "" -"Project-Id-Version: acsengine\n" +"Project-Id-Version: aksengine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-25 00:04+0000\n" "PO-Revision-Date: 2017-07-24 17:23-0700\n" @@ -17,7 +17,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.0.3\n" -#: pkg/acsengine/engine.go:239 +#: pkg/engine/engine.go:239 #, c-format msgid "Error reading file %s, Error: %s" msgstr "Erreur de lecture du fichier %s. Erreur : %s" @@ -27,13 +27,13 @@ msgstr "Erreur de lecture du fichier %s. Erreur : %s" msgid "Error while querying ARM for resources: %+v" msgstr "Erreur pendant la recherche de ressources dans ARM : %+v" -#: pkg/acsengine/transform.go:99 +#: pkg/engine/transform.go:99 #, c-format msgid "Found 2 resources with type %s in the template. There should only be 1" msgstr "" "2 ressources trouvées avec le type %s dans le modèle. 1 seule est attendue" -#: pkg/acsengine/transform.go:122 +#: pkg/engine/transform.go:122 #, c-format msgid "" "Found no resources with type %s in the template. There should have been 1" @@ -61,12 +61,12 @@ msgstr "" "La mise à niveau vers la version %s de Kubernetes n'est pas prise en charge " "à partir de la version %s" -#: pkg/acsengine/filesaver.go:24 +#: pkg/engine/filesaver.go:24 #, c-format msgid "error creating directory '%s': %s" msgstr "erreur de création du répertoire « %s » : %s" -#: pkg/acsengine/engine.go:1194 +#: pkg/engine/engine.go:1194 #, c-format msgid "error executing template for file %s: %v" msgstr "erreur d'exécution du modèle pour le fichier %s : %v" @@ -78,7 +78,7 @@ msgstr "erreur d'exécution du modèle pour le fichier %s : %v" msgid "error generating upgrade template: %s" msgstr "erreur de génération du modèle de mise à niveau : %s" -#: pkg/acsengine/engine.go:1189 +#: pkg/engine/engine.go:1189 #, c-format msgid "error parsing file %s: %v" msgstr "erreur d'analyse du fichier %s : %v" @@ -88,12 +88,12 @@ msgstr "erreur d'analyse du fichier %s : %v" msgid "error reading file %s: %s" msgstr "erreur de lecture du fichier « %s » ; %s" -#: pkg/acsengine/ssh.go:55 +#: pkg/engine/ssh.go:55 #, c-format msgid "failed to create openssh public key string: %q" msgstr "échec de création de la chaîne de clé publique openssh : %q" -#: pkg/acsengine/ssh.go:49 +#: pkg/engine/ssh.go:49 #, c-format msgid "failed to generate private key for ssh: %q" msgstr "échec de génération de la clé privée pour ssh : %q" @@ -109,12 +109,12 @@ msgid "invalid version %s for conversion back from unversioned object" msgstr "" "version non valide %s pour la reconversion à partir de l'objet non versionné" -#: pkg/acsengine/engine.go:322 +#: pkg/engine/engine.go:322 #, c-format msgid "orchestrator '%s' is unsupported" msgstr "l'orchestrateur « %s » n'est pas pris en charge" -#: pkg/acsengine/engine.go:187 +#: pkg/engine/engine.go:187 #, c-format msgid "template file %s does not exist" msgstr "le fichier de modèle %s n'existe pas" @@ -124,7 +124,7 @@ msgstr "le fichier de modèle %s n'existe pas" msgid "unrecognized APIVersion '%s'" msgstr "version d'API « %s » non reconnue" -#: pkg/acsengine/engine.go:1183 +#: pkg/engine/engine.go:1183 #, c-format msgid "yaml file %s does not exist" msgstr "le fichier yaml %s n'existe pas" diff --git a/translations/hu_HU/LC_MESSAGES/acsengine.mo b/translations/hu_HU/LC_MESSAGES/aksengine.mo similarity index 100% rename from translations/hu_HU/LC_MESSAGES/acsengine.mo rename to translations/hu_HU/LC_MESSAGES/aksengine.mo diff --git a/translations/hu_HU/LC_MESSAGES/acsengine.po b/translations/hu_HU/LC_MESSAGES/aksengine.po similarity index 88% rename from translations/hu_HU/LC_MESSAGES/acsengine.po rename to translations/hu_HU/LC_MESSAGES/aksengine.po index 04b9aa157c..f1818270b0 100644 --- a/translations/hu_HU/LC_MESSAGES/acsengine.po +++ b/translations/hu_HU/LC_MESSAGES/aksengine.po @@ -1,10 +1,10 @@ -# English translations for acs-engine package. +# English translations for aks-engine package. # Copyright (C) 2017 -# This file is distributed under the same license as the acs-engine package. +# This file is distributed under the same license as the aks-engine package. # Jiangtian Li , 2017. msgid "" msgstr "" -"Project-Id-Version: acsengine\n" +"Project-Id-Version: aksengine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-25 00:04+0000\n" "PO-Revision-Date: 2017-07-24 17:23-0700\n" @@ -17,7 +17,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.0.3\n" -#: pkg/acsengine/engine.go:239 +#: pkg/engine/engine.go:239 #, c-format msgid "Error reading file %s, Error: %s" msgstr "Hiba történt a(z) %s fájl olvasása közben. Hiba: %s" @@ -28,12 +28,12 @@ msgid "Error while querying ARM for resources: %+v" msgstr "" "Hiba történt a következő erőforrások ARM-ből történő lekérdezése közben: %+v" -#: pkg/acsengine/transform.go:99 +#: pkg/engine/transform.go:99 #, c-format msgid "Found 2 resources with type %s in the template. There should only be 1" msgstr "Az engedélyezett 1 helyett 2 %s típusú erőforrás található a sablonban" -#: pkg/acsengine/transform.go:122 +#: pkg/engine/transform.go:122 #, c-format msgid "" "Found no resources with type %s in the template. There should have been 1" @@ -58,12 +58,12 @@ msgid "Upgrade to Kubernetes version: %s is not supported from version: %s" msgstr "" "A Kubernetes %s verzióról a(z) %s verzióra történő frissítés nem támogatott" -#: pkg/acsengine/filesaver.go:24 +#: pkg/engine/filesaver.go:24 #, c-format msgid "error creating directory '%s': %s" msgstr "Hiba történt a(z) %s könyvtár létrehozása közben: %s" -#: pkg/acsengine/engine.go:1194 +#: pkg/engine/engine.go:1194 #, c-format msgid "error executing template for file %s: %v" msgstr "Hiba történt a sablon végrehajtása közben (fájl: %s): %v" @@ -75,7 +75,7 @@ msgstr "Hiba történt a sablon végrehajtása közben (fájl: %s): %v" msgid "error generating upgrade template: %s" msgstr "Hiba történt a(z) %s frissítési sablon létrehozása közben" -#: pkg/acsengine/engine.go:1189 +#: pkg/engine/engine.go:1189 #, c-format msgid "error parsing file %s: %v" msgstr "Hiba történt a(z) %s fájl elemzése közben: %v" @@ -85,12 +85,12 @@ msgstr "Hiba történt a(z) %s fájl elemzése közben: %v" msgid "error reading file %s: %s" msgstr "Hiba történt a(z) %s fájl olvasása közben: %s" -#: pkg/acsengine/ssh.go:55 +#: pkg/engine/ssh.go:55 #, c-format msgid "failed to create openssh public key string: %q" msgstr "Nem sikerült létrehozni a(z) %q nyilvános OpenSSH-kulcs karakterláncát" -#: pkg/acsengine/ssh.go:49 +#: pkg/engine/ssh.go:49 #, c-format msgid "failed to generate private key for ssh: %q" msgstr "Nem sikerült létrehozni a(z) %q titkos SSH-kulcsot" @@ -105,12 +105,12 @@ msgstr "Nem sikerült inicializálni a(z) %s sablongenerátort" msgid "invalid version %s for conversion back from unversioned object" msgstr "Verzió nélküli objektum visszaalakítása – érvénytelen verzió (%s)" -#: pkg/acsengine/engine.go:322 +#: pkg/engine/engine.go:322 #, c-format msgid "orchestrator '%s' is unsupported" msgstr "A(z) %s vezénylő nem támogatott" -#: pkg/acsengine/engine.go:187 +#: pkg/engine/engine.go:187 #, c-format msgid "template file %s does not exist" msgstr "A(z) %s sablonfájl nem létezik" @@ -120,7 +120,7 @@ msgstr "A(z) %s sablonfájl nem létezik" msgid "unrecognized APIVersion '%s'" msgstr "Ismeretlen API-verzió: %s" -#: pkg/acsengine/engine.go:1183 +#: pkg/engine/engine.go:1183 #, c-format msgid "yaml file %s does not exist" msgstr "A(z) %s YAML-fájl nem létezik" diff --git a/translations/it_IT/LC_MESSAGES/acsengine.mo b/translations/it_IT/LC_MESSAGES/aksengine.mo similarity index 100% rename from translations/it_IT/LC_MESSAGES/acsengine.mo rename to translations/it_IT/LC_MESSAGES/aksengine.mo diff --git a/translations/it_IT/LC_MESSAGES/acsengine.po b/translations/it_IT/LC_MESSAGES/aksengine.po similarity index 88% rename from translations/it_IT/LC_MESSAGES/acsengine.po rename to translations/it_IT/LC_MESSAGES/aksengine.po index d86e21dc3c..d7ba241015 100644 --- a/translations/it_IT/LC_MESSAGES/acsengine.po +++ b/translations/it_IT/LC_MESSAGES/aksengine.po @@ -1,10 +1,10 @@ -# English translations for acs-engine package. +# English translations for aks-engine package. # Copyright (C) 2017 -# This file is distributed under the same license as the acs-engine package. +# This file is distributed under the same license as the aks-engine package. # Jiangtian Li , 2017. msgid "" msgstr "" -"Project-Id-Version: acsengine\n" +"Project-Id-Version: aksengine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-25 00:04+0000\n" "PO-Revision-Date: 2017-07-24 17:23-0700\n" @@ -17,7 +17,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.0.3\n" -#: pkg/acsengine/engine.go:239 +#: pkg/engine/engine.go:239 #, c-format msgid "Error reading file %s, Error: %s" msgstr "Errore durante la lettura del file %s. Errore: %s" @@ -27,13 +27,13 @@ msgstr "Errore durante la lettura del file %s. Errore: %s" msgid "Error while querying ARM for resources: %+v" msgstr "Errore durante la query su Azure Resource Manager per le risorse: %+v" -#: pkg/acsengine/transform.go:99 +#: pkg/engine/transform.go:99 #, c-format msgid "Found 2 resources with type %s in the template. There should only be 1" msgstr "" "Nel modello sono state trovate 2 risorse con tipo %s. Ne è consentita solo 1" -#: pkg/acsengine/transform.go:122 +#: pkg/engine/transform.go:122 #, c-format msgid "" "Found no resources with type %s in the template. There should have been 1" @@ -59,12 +59,12 @@ msgid "Upgrade to Kubernetes version: %s is not supported from version: %s" msgstr "" "L'aggiornamento a Kubernetes versione %s non è supportato dalla versione %s" -#: pkg/acsengine/filesaver.go:24 +#: pkg/engine/filesaver.go:24 #, c-format msgid "error creating directory '%s': %s" msgstr "errore durante la creazione della directory '%s': %s" -#: pkg/acsengine/engine.go:1194 +#: pkg/engine/engine.go:1194 #, c-format msgid "error executing template for file %s: %v" msgstr "errore durante l'esecuzione del modello per il file %s: %v" @@ -76,7 +76,7 @@ msgstr "errore durante l'esecuzione del modello per il file %s: %v" msgid "error generating upgrade template: %s" msgstr "errore durante la generazione del modello di aggiornamento: %s" -#: pkg/acsengine/engine.go:1189 +#: pkg/engine/engine.go:1189 #, c-format msgid "error parsing file %s: %v" msgstr "errore durante l'analisi del file %s: %v" @@ -86,12 +86,12 @@ msgstr "errore durante l'analisi del file %s: %v" msgid "error reading file %s: %s" msgstr "errore durante la lettura del file %s: %s" -#: pkg/acsengine/ssh.go:55 +#: pkg/engine/ssh.go:55 #, c-format msgid "failed to create openssh public key string: %q" msgstr "non è stato possibile creare la stringa di chiave pubblica OpenSSH: %q" -#: pkg/acsengine/ssh.go:49 +#: pkg/engine/ssh.go:49 #, c-format msgid "failed to generate private key for ssh: %q" msgstr "non è stato possibile generare la chiave privata per SSH: %q" @@ -108,12 +108,12 @@ msgstr "" "la versione %s non è valida per la riconversione da un oggetto senza " "versione" -#: pkg/acsengine/engine.go:322 +#: pkg/engine/engine.go:322 #, c-format msgid "orchestrator '%s' is unsupported" msgstr "l'agente di orchestrazione '%s' non è supportato" -#: pkg/acsengine/engine.go:187 +#: pkg/engine/engine.go:187 #, c-format msgid "template file %s does not exist" msgstr "il file modello %s non esiste" @@ -123,7 +123,7 @@ msgstr "il file modello %s non esiste" msgid "unrecognized APIVersion '%s'" msgstr "versione API '%s' non riconosciuta" -#: pkg/acsengine/engine.go:1183 +#: pkg/engine/engine.go:1183 #, c-format msgid "yaml file %s does not exist" msgstr "il file YAML %s non esiste" diff --git a/translations/ja_JP/LC_MESSAGES/acsengine.mo b/translations/ja_JP/LC_MESSAGES/aksengine.mo similarity index 100% rename from translations/ja_JP/LC_MESSAGES/acsengine.mo rename to translations/ja_JP/LC_MESSAGES/aksengine.mo diff --git a/translations/ja_JP/LC_MESSAGES/acsengine.po b/translations/ja_JP/LC_MESSAGES/aksengine.po similarity index 89% rename from translations/ja_JP/LC_MESSAGES/acsengine.po rename to translations/ja_JP/LC_MESSAGES/aksengine.po index 5ec9eea284..dadc6a9724 100644 --- a/translations/ja_JP/LC_MESSAGES/acsengine.po +++ b/translations/ja_JP/LC_MESSAGES/aksengine.po @@ -1,10 +1,10 @@ -# English translations for acs-engine package. +# English translations for aks-engine package. # Copyright (C) 2017 -# This file is distributed under the same license as the acs-engine package. +# This file is distributed under the same license as the aks-engine package. # Jiangtian Li , 2017. msgid "" msgstr "" -"Project-Id-Version: acsengine\n" +"Project-Id-Version: aksengine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-25 00:04+0000\n" "PO-Revision-Date: 2017-07-24 17:23-0700\n" @@ -17,7 +17,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.0.3\n" -#: pkg/acsengine/engine.go:239 +#: pkg/engine/engine.go:239 #, c-format msgid "Error reading file %s, Error: %s" msgstr "ファイル %s の読み取り中にエラーが発生しました。エラー: %s" @@ -27,12 +27,12 @@ msgstr "ファイル %s の読み取り中にエラーが発生しました。 msgid "Error while querying ARM for resources: %+v" msgstr "ARM にリソースを照会中にエラーが発生しました: %+v" -#: pkg/acsengine/transform.go:99 +#: pkg/engine/transform.go:99 #, c-format msgid "Found 2 resources with type %s in the template. There should only be 1" msgstr "テンプレートに種類 %s のリソースが 2 つ見つかりました。1 つだけ見つかる必要があります" -#: pkg/acsengine/transform.go:122 +#: pkg/engine/transform.go:122 #, c-format msgid "" "Found no resources with type %s in the template. There should have been 1" @@ -53,12 +53,12 @@ msgstr "Kubernetes 1.6.2 にバージョン %s からアップグレードする msgid "Upgrade to Kubernetes version: %s is not supported from version: %s" msgstr "Kubernetes バージョン %s にバージョン %s からアップグレードすることはサポートされていません" -#: pkg/acsengine/filesaver.go:24 +#: pkg/engine/filesaver.go:24 #, c-format msgid "error creating directory '%s': %s" msgstr "ディレクトリ '%s' の作成中にエラーが発生しました: %s" -#: pkg/acsengine/engine.go:1194 +#: pkg/engine/engine.go:1194 #, c-format msgid "error executing template for file %s: %v" msgstr "ファイル %s にテンプレートを実行中にエラーが発生しました: %v" @@ -70,7 +70,7 @@ msgstr "ファイル %s にテンプレートを実行中にエラーが発生 msgid "error generating upgrade template: %s" msgstr "アップグレード テンプレートの生成中にエラーが発生しました: %s" -#: pkg/acsengine/engine.go:1189 +#: pkg/engine/engine.go:1189 #, c-format msgid "error parsing file %s: %v" msgstr "ファイル %s の解析中にエラーが発生しました: %v" @@ -80,12 +80,12 @@ msgstr "ファイル %s の解析中にエラーが発生しました: %v" msgid "error reading file %s: %s" msgstr "ファイル %s の読み取り中にエラーが発生しました: %s" -#: pkg/acsengine/ssh.go:55 +#: pkg/engine/ssh.go:55 #, c-format msgid "failed to create openssh public key string: %q" msgstr "OpenSSH 公開キーの文字列を作成できませんでした: %q" -#: pkg/acsengine/ssh.go:49 +#: pkg/engine/ssh.go:49 #, c-format msgid "failed to generate private key for ssh: %q" msgstr "SSH の秘密キーを生成できませんでした" @@ -100,12 +100,12 @@ msgstr "Template Generator の初期化に失敗しました: %s" msgid "invalid version %s for conversion back from unversioned object" msgstr "バージョン管理外オブジェクトから変換し直すことのできないバージョンです: %s" -#: pkg/acsengine/engine.go:322 +#: pkg/engine/engine.go:322 #, c-format msgid "orchestrator '%s' is unsupported" msgstr "オーケストレーター '%s' はサポートされていません" -#: pkg/acsengine/engine.go:187 +#: pkg/engine/engine.go:187 #, c-format msgid "template file %s does not exist" msgstr "テンプレート ファイル %s が存在しません" @@ -115,7 +115,7 @@ msgstr "テンプレート ファイル %s が存在しません" msgid "unrecognized APIVersion '%s'" msgstr "認識されない APIVersionです: '%s'" -#: pkg/acsengine/engine.go:1183 +#: pkg/engine/engine.go:1183 #, c-format msgid "yaml file %s does not exist" msgstr "YAML ファイル %s が存在しません" diff --git a/translations/ko_KR/LC_MESSAGES/acsengine.mo b/translations/ko_KR/LC_MESSAGES/aksengine.mo similarity index 100% rename from translations/ko_KR/LC_MESSAGES/acsengine.mo rename to translations/ko_KR/LC_MESSAGES/aksengine.mo diff --git a/translations/ko_KR/LC_MESSAGES/acsengine.po b/translations/ko_KR/LC_MESSAGES/aksengine.po similarity index 88% rename from translations/ko_KR/LC_MESSAGES/acsengine.po rename to translations/ko_KR/LC_MESSAGES/aksengine.po index 90ee11c965..1987b3fc4d 100644 --- a/translations/ko_KR/LC_MESSAGES/acsengine.po +++ b/translations/ko_KR/LC_MESSAGES/aksengine.po @@ -1,10 +1,10 @@ -# English translations for acs-engine package. +# English translations for aks-engine package. # Copyright (C) 2017 -# This file is distributed under the same license as the acs-engine package. +# This file is distributed under the same license as the aks-engine package. # Jiangtian Li , 2017. msgid "" msgstr "" -"Project-Id-Version: acsengine\n" +"Project-Id-Version: aksengine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-25 00:04+0000\n" "PO-Revision-Date: 2017-07-24 17:23-0700\n" @@ -17,7 +17,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.0.3\n" -#: pkg/acsengine/engine.go:239 +#: pkg/engine/engine.go:239 #, c-format msgid "Error reading file %s, Error: %s" msgstr "%s 파일을 읽는 중 오류 발생, 오류: %s" @@ -27,12 +27,12 @@ msgstr "%s 파일을 읽는 중 오류 발생, 오류: %s" msgid "Error while querying ARM for resources: %+v" msgstr "ARM에 리소스를 쿼리하는 중 오류 발생: %+v" -#: pkg/acsengine/transform.go:99 +#: pkg/engine/transform.go:99 #, c-format msgid "Found 2 resources with type %s in the template. There should only be 1" msgstr "템플릿에서 유형이 %s인 리소스를 2개 찾았습니다. 1개만 있어야 합니다." -#: pkg/acsengine/transform.go:122 +#: pkg/engine/transform.go:122 #, c-format msgid "" "Found no resources with type %s in the template. There should have been 1" @@ -53,12 +53,12 @@ msgstr "%s 버전에서 Kubernetes 1.6.2로의 업그레이드는 지원되지 msgid "Upgrade to Kubernetes version: %s is not supported from version: %s" msgstr "%s 버전에서 Kubernetes %s 버전으로의 업그레이드는 지원되지 않습니다." -#: pkg/acsengine/filesaver.go:24 +#: pkg/engine/filesaver.go:24 #, c-format msgid "error creating directory '%s': %s" msgstr "'%s' 디렉터리를 만드는 중 오류 발생: %s" -#: pkg/acsengine/engine.go:1194 +#: pkg/engine/engine.go:1194 #, c-format msgid "error executing template for file %s: %v" msgstr "%s 파일에 대한 템플릿을 실행하는 중 오류 발생: %v" @@ -70,7 +70,7 @@ msgstr "%s 파일에 대한 템플릿을 실행하는 중 오류 발생: %v" msgid "error generating upgrade template: %s" msgstr "업그레이드 템플릿을 생성하는 중 오류 발생: %s" -#: pkg/acsengine/engine.go:1189 +#: pkg/engine/engine.go:1189 #, c-format msgid "error parsing file %s: %v" msgstr "%s 파일을 구문 분석하는 중 오류 발생: %v" @@ -80,12 +80,12 @@ msgstr "%s 파일을 구문 분석하는 중 오류 발생: %v" msgid "error reading file %s: %s" msgstr "%s 파일을 읽는 동안 오류 발생: %s" -#: pkg/acsengine/ssh.go:55 +#: pkg/engine/ssh.go:55 #, c-format msgid "failed to create openssh public key string: %q" msgstr "openssh 공개 키 문자열을 만들지 못함: %q" -#: pkg/acsengine/ssh.go:49 +#: pkg/engine/ssh.go:49 #, c-format msgid "failed to generate private key for ssh: %q" msgstr "ssh에 대한 개인 키를 생성하지 못함: %q" @@ -100,12 +100,12 @@ msgstr "템플릿 생성기를 초기화하지 못함: %s" msgid "invalid version %s for conversion back from unversioned object" msgstr "버전이 지정되지 않은 개체로부터 다시 변환하기 위한 버전 %s가 잘못됨" -#: pkg/acsengine/engine.go:322 +#: pkg/engine/engine.go:322 #, c-format msgid "orchestrator '%s' is unsupported" msgstr "오케스트레이터 '%s'은(는) 지원되지 않습니다." -#: pkg/acsengine/engine.go:187 +#: pkg/engine/engine.go:187 #, c-format msgid "template file %s does not exist" msgstr "템플릿 파일 %s이(가) 없습니다." @@ -115,7 +115,7 @@ msgstr "템플릿 파일 %s이(가) 없습니다." msgid "unrecognized APIVersion '%s'" msgstr "인식할 수 없는 APIVersion '%s'" -#: pkg/acsengine/engine.go:1183 +#: pkg/engine/engine.go:1183 #, c-format msgid "yaml file %s does not exist" msgstr "YAML 파일 %s이(가) 없습니다." diff --git a/translations/nl_NL/LC_MESSAGES/acsengine.mo b/translations/nl_NL/LC_MESSAGES/aksengine.mo similarity index 100% rename from translations/nl_NL/LC_MESSAGES/acsengine.mo rename to translations/nl_NL/LC_MESSAGES/aksengine.mo diff --git a/translations/nl_NL/LC_MESSAGES/acsengine.po b/translations/nl_NL/LC_MESSAGES/aksengine.po similarity index 88% rename from translations/nl_NL/LC_MESSAGES/acsengine.po rename to translations/nl_NL/LC_MESSAGES/aksengine.po index 245dfada88..a662316da1 100644 --- a/translations/nl_NL/LC_MESSAGES/acsengine.po +++ b/translations/nl_NL/LC_MESSAGES/aksengine.po @@ -1,10 +1,10 @@ -# English translations for acs-engine package. +# English translations for aks-engine package. # Copyright (C) 2017 -# This file is distributed under the same license as the acs-engine package. +# This file is distributed under the same license as the aks-engine package. # Jiangtian Li , 2017. msgid "" msgstr "" -"Project-Id-Version: acsengine\n" +"Project-Id-Version: aksengine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-25 00:04+0000\n" "PO-Revision-Date: 2017-07-24 17:23-0700\n" @@ -17,7 +17,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.0.3\n" -#: pkg/acsengine/engine.go:239 +#: pkg/engine/engine.go:239 #, c-format msgid "Error reading file %s, Error: %s" msgstr "Fout bij het lezen van het bestand %s, Fout: %s" @@ -27,14 +27,14 @@ msgstr "Fout bij het lezen van het bestand %s, Fout: %s" msgid "Error while querying ARM for resources: %+v" msgstr "Fout bij het uitvoeren van een query op ARM voor resources: %+v" -#: pkg/acsengine/transform.go:99 +#: pkg/engine/transform.go:99 #, c-format msgid "Found 2 resources with type %s in the template. There should only be 1" msgstr "" "In de sjabloon zijn twee resources gevonden met het type %s. Hiervan moet " "één resource zijn" -#: pkg/acsengine/transform.go:122 +#: pkg/engine/transform.go:122 #, c-format msgid "" "Found no resources with type %s in the template. There should have been 1" @@ -60,12 +60,12 @@ msgid "Upgrade to Kubernetes version: %s is not supported from version: %s" msgstr "" "Upgraden naar Kubernetes versie %s wordt niet ondersteund voor versie %s" -#: pkg/acsengine/filesaver.go:24 +#: pkg/engine/filesaver.go:24 #, c-format msgid "error creating directory '%s': %s" msgstr "fout bij het maken van de map %s: %s" -#: pkg/acsengine/engine.go:1194 +#: pkg/engine/engine.go:1194 #, c-format msgid "error executing template for file %s: %v" msgstr "fout bij het uitvoeren van de sjabloon voor het bestand %s: %v" @@ -77,7 +77,7 @@ msgstr "fout bij het uitvoeren van de sjabloon voor het bestand %s: %v" msgid "error generating upgrade template: %s" msgstr "fout bij het genereren van de upgradesjabloon: %s" -#: pkg/acsengine/engine.go:1189 +#: pkg/engine/engine.go:1189 #, c-format msgid "error parsing file %s: %v" msgstr "fout bij het parseren van het bestand %s: %v" @@ -87,12 +87,12 @@ msgstr "fout bij het parseren van het bestand %s: %v" msgid "error reading file %s: %s" msgstr "fout bij het lezen van het bestand %s: %s" -#: pkg/acsengine/ssh.go:55 +#: pkg/engine/ssh.go:55 #, c-format msgid "failed to create openssh public key string: %q" msgstr "kan de openbare sleutelreeks voor openssh niet maken: %q" -#: pkg/acsengine/ssh.go:49 +#: pkg/engine/ssh.go:49 #, c-format msgid "failed to generate private key for ssh: %q" msgstr "kan de persoonlijke sleutel voor ssh niet maken: %q" @@ -107,12 +107,12 @@ msgstr "kan de sjabloongenerator niet initialiseren: %s" msgid "invalid version %s for conversion back from unversioned object" msgstr "ongeldige versie %s voor conversie terug naar object zonder versie" -#: pkg/acsengine/engine.go:322 +#: pkg/engine/engine.go:322 #, c-format msgid "orchestrator '%s' is unsupported" msgstr "de orchestrator %s wordt niet ondersteund" -#: pkg/acsengine/engine.go:187 +#: pkg/engine/engine.go:187 #, c-format msgid "template file %s does not exist" msgstr "het sjabloonbestand %s bestaat niet" @@ -122,7 +122,7 @@ msgstr "het sjabloonbestand %s bestaat niet" msgid "unrecognized APIVersion '%s'" msgstr "de API-versie %s wordt niet herkend" -#: pkg/acsengine/engine.go:1183 +#: pkg/engine/engine.go:1183 #, c-format msgid "yaml file %s does not exist" msgstr "het yaml-bestand %s bestaat niet" diff --git a/translations/pl_PL/LC_MESSAGES/acsengine.mo b/translations/pl_PL/LC_MESSAGES/aksengine.mo similarity index 100% rename from translations/pl_PL/LC_MESSAGES/acsengine.mo rename to translations/pl_PL/LC_MESSAGES/aksengine.mo diff --git a/translations/pl_PL/LC_MESSAGES/acsengine.po b/translations/pl_PL/LC_MESSAGES/aksengine.po similarity index 88% rename from translations/pl_PL/LC_MESSAGES/acsengine.po rename to translations/pl_PL/LC_MESSAGES/aksengine.po index c9dd57368e..75ce7e7c62 100644 --- a/translations/pl_PL/LC_MESSAGES/acsengine.po +++ b/translations/pl_PL/LC_MESSAGES/aksengine.po @@ -1,10 +1,10 @@ -# English translations for acs-engine package. +# English translations for aks-engine package. # Copyright (C) 2017 -# This file is distributed under the same license as the acs-engine package. +# This file is distributed under the same license as the aks-engine package. # Jiangtian Li , 2017. msgid "" msgstr "" -"Project-Id-Version: acsengine\n" +"Project-Id-Version: aksengine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-25 00:04+0000\n" "PO-Revision-Date: 2017-07-24 17:23-0700\n" @@ -17,7 +17,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.0.3\n" -#: pkg/acsengine/engine.go:239 +#: pkg/engine/engine.go:239 #, c-format msgid "Error reading file %s, Error: %s" msgstr "Błąd podczas odczytywania pliku %s. Błąd: %s" @@ -29,14 +29,14 @@ msgstr "" "Błąd podczas wykonywania zapytania względem usługi ARM dotyczącego zasobów: " "%+v" -#: pkg/acsengine/transform.go:99 +#: pkg/engine/transform.go:99 #, c-format msgid "Found 2 resources with type %s in the template. There should only be 1" msgstr "" "Odnaleziono dwa zasoby o typie %s w szablonie. Powinien istnieć tylko jeden " "taki zasób" -#: pkg/acsengine/transform.go:122 +#: pkg/engine/transform.go:122 #, c-format msgid "" "Found no resources with type %s in the template. There should have been 1" @@ -64,12 +64,12 @@ msgid "Upgrade to Kubernetes version: %s is not supported from version: %s" msgstr "" "Uaktualnienie do rozwiązania Kubernetes %s z wersji %s nie jest obsługiwane" -#: pkg/acsengine/filesaver.go:24 +#: pkg/engine/filesaver.go:24 #, c-format msgid "error creating directory '%s': %s" msgstr "błąd podczas tworzenia katalogu „%s”: %s" -#: pkg/acsengine/engine.go:1194 +#: pkg/engine/engine.go:1194 #, c-format msgid "error executing template for file %s: %v" msgstr "błąd podczas wykonywania szablonu dla pliku %s: %v" @@ -81,7 +81,7 @@ msgstr "błąd podczas wykonywania szablonu dla pliku %s: %v" msgid "error generating upgrade template: %s" msgstr "błąd podczas generowania szablonu uaktualnienia: %s" -#: pkg/acsengine/engine.go:1189 +#: pkg/engine/engine.go:1189 #, c-format msgid "error parsing file %s: %v" msgstr "błąd podczas analizowania pliku %s: %v" @@ -91,12 +91,12 @@ msgstr "błąd podczas analizowania pliku %s: %v" msgid "error reading file %s: %s" msgstr "błąd podczas odczytywania pliku %s: %s" -#: pkg/acsengine/ssh.go:55 +#: pkg/engine/ssh.go:55 #, c-format msgid "failed to create openssh public key string: %q" msgstr "nie można utworzyć ciągu klucza publicznego OpenSSH: %q" -#: pkg/acsengine/ssh.go:49 +#: pkg/engine/ssh.go:49 #, c-format msgid "failed to generate private key for ssh: %q" msgstr "nie można wygenerować klucza prywatnego dla protokołu SSH: %q" @@ -112,12 +112,12 @@ msgid "invalid version %s for conversion back from unversioned object" msgstr "" "nieprawidłowa wersja %s na potrzeby konwersji z obiektu niewersjonowanego" -#: pkg/acsengine/engine.go:322 +#: pkg/engine/engine.go:322 #, c-format msgid "orchestrator '%s' is unsupported" msgstr "orkiestrator „%s” nie jest obsługiwany" -#: pkg/acsengine/engine.go:187 +#: pkg/engine/engine.go:187 #, c-format msgid "template file %s does not exist" msgstr "plik szablonu %s nie istnieje" @@ -127,7 +127,7 @@ msgstr "plik szablonu %s nie istnieje" msgid "unrecognized APIVersion '%s'" msgstr "nierozpoznana wersja interfejsu API „%s”" -#: pkg/acsengine/engine.go:1183 +#: pkg/engine/engine.go:1183 #, c-format msgid "yaml file %s does not exist" msgstr "plik YAML %s nie istnieje" diff --git a/translations/pt_BR/LC_MESSAGES/acsengine.mo b/translations/pt_BR/LC_MESSAGES/aksengine.mo similarity index 100% rename from translations/pt_BR/LC_MESSAGES/acsengine.mo rename to translations/pt_BR/LC_MESSAGES/aksengine.mo diff --git a/translations/pt_BR/LC_MESSAGES/acsengine.po b/translations/pt_BR/LC_MESSAGES/aksengine.po similarity index 88% rename from translations/pt_BR/LC_MESSAGES/acsengine.po rename to translations/pt_BR/LC_MESSAGES/aksengine.po index 3a9748101f..7919b54712 100644 --- a/translations/pt_BR/LC_MESSAGES/acsengine.po +++ b/translations/pt_BR/LC_MESSAGES/aksengine.po @@ -1,10 +1,10 @@ -# English translations for acs-engine package. +# English translations for aks-engine package. # Copyright (C) 2017 -# This file is distributed under the same license as the acs-engine package. +# This file is distributed under the same license as the aks-engine package. # Jiangtian Li , 2017. msgid "" msgstr "" -"Project-Id-Version: acsengine\n" +"Project-Id-Version: aksengine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-25 00:04+0000\n" "PO-Revision-Date: 2017-07-24 17:23-0700\n" @@ -17,7 +17,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.0.3\n" -#: pkg/acsengine/engine.go:239 +#: pkg/engine/engine.go:239 #, c-format msgid "Error reading file %s, Error: %s" msgstr "Erro ao ler o arquivo %s, Erro: %s" @@ -27,13 +27,13 @@ msgstr "Erro ao ler o arquivo %s, Erro: %s" msgid "Error while querying ARM for resources: %+v" msgstr "Erro ao consultar ARM para os recursos: %+v" -#: pkg/acsengine/transform.go:99 +#: pkg/engine/transform.go:99 #, c-format msgid "Found 2 resources with type %s in the template. There should only be 1" msgstr "" "Foram encontrados 2 recursos com o tipo %s no modelo. Deveria haver apenas 1" -#: pkg/acsengine/transform.go:122 +#: pkg/engine/transform.go:122 #, c-format msgid "" "Found no resources with type %s in the template. There should have been 1" @@ -56,12 +56,12 @@ msgstr "" "A atualização para a versão de Kubernetes: %s não é compatível com a versão: " "%s" -#: pkg/acsengine/filesaver.go:24 +#: pkg/engine/filesaver.go:24 #, c-format msgid "error creating directory '%s': %s" msgstr "erro ao criar o diretório '%s': %s" -#: pkg/acsengine/engine.go:1194 +#: pkg/engine/engine.go:1194 #, c-format msgid "error executing template for file %s: %v" msgstr "erro ao executar modelo para o arquivo %s: %v" @@ -73,7 +73,7 @@ msgstr "erro ao executar modelo para o arquivo %s: %v" msgid "error generating upgrade template: %s" msgstr "erro ao gerar o modelo de atualização: %s" -#: pkg/acsengine/engine.go:1189 +#: pkg/engine/engine.go:1189 #, c-format msgid "error parsing file %s: %v" msgstr "erro ao analisar o arquivo %s: %v" @@ -83,12 +83,12 @@ msgstr "erro ao analisar o arquivo %s: %v" msgid "error reading file %s: %s" msgstr "erro ao ler o arquivo '%s: %s" -#: pkg/acsengine/ssh.go:55 +#: pkg/engine/ssh.go:55 #, c-format msgid "failed to create openssh public key string: %q" msgstr "falha ao criar a cadeia de caracteres de chave pública openssh: %q" -#: pkg/acsengine/ssh.go:49 +#: pkg/engine/ssh.go:49 #, c-format msgid "failed to generate private key for ssh: %q" msgstr "falha ao gerar a chave privada para ssh: %q" @@ -103,12 +103,12 @@ msgstr "falha ao inicializar o gerador de modelos: %s" msgid "invalid version %s for conversion back from unversioned object" msgstr "versão %s inválida para conversão de objeto não versionado" -#: pkg/acsengine/engine.go:322 +#: pkg/engine/engine.go:322 #, c-format msgid "orchestrator '%s' is unsupported" msgstr "orquestrador '%s' sem suporte" -#: pkg/acsengine/engine.go:187 +#: pkg/engine/engine.go:187 #, c-format msgid "template file %s does not exist" msgstr "arquivo de modelo %s inexistente" @@ -118,7 +118,7 @@ msgstr "arquivo de modelo %s inexistente" msgid "unrecognized APIVersion '%s'" msgstr "APIVersion '%s' não reconhecida" -#: pkg/acsengine/engine.go:1183 +#: pkg/engine/engine.go:1183 #, c-format msgid "yaml file %s does not exist" msgstr "arquivo yaml %s inexistente" diff --git a/translations/pt_PT/LC_MESSAGES/acsengine.mo b/translations/pt_PT/LC_MESSAGES/aksengine.mo similarity index 100% rename from translations/pt_PT/LC_MESSAGES/acsengine.mo rename to translations/pt_PT/LC_MESSAGES/aksengine.mo diff --git a/translations/pt_PT/LC_MESSAGES/acsengine.po b/translations/pt_PT/LC_MESSAGES/aksengine.po similarity index 88% rename from translations/pt_PT/LC_MESSAGES/acsengine.po rename to translations/pt_PT/LC_MESSAGES/aksengine.po index f2984598e0..0f2d4429ce 100644 --- a/translations/pt_PT/LC_MESSAGES/acsengine.po +++ b/translations/pt_PT/LC_MESSAGES/aksengine.po @@ -1,10 +1,10 @@ -# English translations for acs-engine package. +# English translations for aks-engine package. # Copyright (C) 2017 -# This file is distributed under the same license as the acs-engine package. +# This file is distributed under the same license as the aks-engine package. # Jiangtian Li , 2017. msgid "" msgstr "" -"Project-Id-Version: acsengine\n" +"Project-Id-Version: aksengine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-25 00:04+0000\n" "PO-Revision-Date: 2017-07-24 17:23-0700\n" @@ -17,7 +17,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.0.3\n" -#: pkg/acsengine/engine.go:239 +#: pkg/engine/engine.go:239 #, c-format msgid "Error reading file %s, Error: %s" msgstr "Erro ao ler ficheiro %s, Erro: %s" @@ -27,13 +27,13 @@ msgstr "Erro ao ler ficheiro %s, Erro: %s" msgid "Error while querying ARM for resources: %+v" msgstr "Erro ao consultar o ARM para os recursos: %+v" -#: pkg/acsengine/transform.go:99 +#: pkg/engine/transform.go:99 #, c-format msgid "Found 2 resources with type %s in the template. There should only be 1" msgstr "" "Foram encontrados 2 recursos de tipo %s no modelo. Deve existir apenas 1." -#: pkg/acsengine/transform.go:122 +#: pkg/engine/transform.go:122 #, c-format msgid "" "Found no resources with type %s in the template. There should have been 1" @@ -57,12 +57,12 @@ msgstr "" "Atualizar para a versão Kubernetes: %s não é suportado a partir da versão: " "%s" -#: pkg/acsengine/filesaver.go:24 +#: pkg/engine/filesaver.go:24 #, c-format msgid "error creating directory '%s': %s" msgstr "erro ao criar diretório \"%s\": %s" -#: pkg/acsengine/engine.go:1194 +#: pkg/engine/engine.go:1194 #, c-format msgid "error executing template for file %s: %v" msgstr "erro ao executar o modelo para o ficheiro %s: %v" @@ -74,7 +74,7 @@ msgstr "erro ao executar o modelo para o ficheiro %s: %v" msgid "error generating upgrade template: %s" msgstr "erro ao gerar modelo de atualização: %s" -#: pkg/acsengine/engine.go:1189 +#: pkg/engine/engine.go:1189 #, c-format msgid "error parsing file %s: %v" msgstr "erro ao analisar o ficheiro %s: %v" @@ -84,12 +84,12 @@ msgstr "erro ao analisar o ficheiro %s: %v" msgid "error reading file %s: %s" msgstr "erro ao ler o ficheiro %s: %s" -#: pkg/acsengine/ssh.go:55 +#: pkg/engine/ssh.go:55 #, c-format msgid "failed to create openssh public key string: %q" msgstr "falha ao criar cadeia de chave pública de openssh: %q" -#: pkg/acsengine/ssh.go:49 +#: pkg/engine/ssh.go:49 #, c-format msgid "failed to generate private key for ssh: %q" msgstr "falha ao gerar chave privada para ssh: %q" @@ -104,12 +104,12 @@ msgstr "falha ao iniciar o gerador de modelo: %s" msgid "invalid version %s for conversion back from unversioned object" msgstr "versão %s inválida para a reconversão de um objeto sem versão definida" -#: pkg/acsengine/engine.go:322 +#: pkg/engine/engine.go:322 #, c-format msgid "orchestrator '%s' is unsupported" msgstr "o orquestrador \"%s\" não é suportado" -#: pkg/acsengine/engine.go:187 +#: pkg/engine/engine.go:187 #, c-format msgid "template file %s does not exist" msgstr "o ficheiro do modelo %s não existe" @@ -119,7 +119,7 @@ msgstr "o ficheiro do modelo %s não existe" msgid "unrecognized APIVersion '%s'" msgstr "APIVersion \"%s\" não reconhecida" -#: pkg/acsengine/engine.go:1183 +#: pkg/engine/engine.go:1183 #, c-format msgid "yaml file %s does not exist" msgstr "o ficheiro yaml %s não existe" diff --git a/translations/ru_RU/LC_MESSAGES/acsengine.mo b/translations/ru_RU/LC_MESSAGES/aksengine.mo similarity index 100% rename from translations/ru_RU/LC_MESSAGES/acsengine.mo rename to translations/ru_RU/LC_MESSAGES/aksengine.mo diff --git a/translations/ru_RU/LC_MESSAGES/acsengine.po b/translations/ru_RU/LC_MESSAGES/aksengine.po similarity index 89% rename from translations/ru_RU/LC_MESSAGES/acsengine.po rename to translations/ru_RU/LC_MESSAGES/aksengine.po index a0e6327844..20d88f6212 100644 --- a/translations/ru_RU/LC_MESSAGES/acsengine.po +++ b/translations/ru_RU/LC_MESSAGES/aksengine.po @@ -1,10 +1,10 @@ -# English translations for acs-engine package. +# English translations for aks-engine package. # Copyright (C) 2017 -# This file is distributed under the same license as the acs-engine package. +# This file is distributed under the same license as the aks-engine package. # Jiangtian Li , 2017. msgid "" msgstr "" -"Project-Id-Version: acsengine\n" +"Project-Id-Version: aksengine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-25 00:04+0000\n" "PO-Revision-Date: 2017-07-24 17:23-0700\n" @@ -17,7 +17,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.0.3\n" -#: pkg/acsengine/engine.go:239 +#: pkg/engine/engine.go:239 #, c-format msgid "Error reading file %s, Error: %s" msgstr "Ошибка при чтении файла %s, ошибка: %s" @@ -27,13 +27,13 @@ msgstr "Ошибка при чтении файла %s, ошибка: %s" msgid "Error while querying ARM for resources: %+v" msgstr "Ошибка при запросе ресурсов в ARM: %+v" -#: pkg/acsengine/transform.go:99 +#: pkg/engine/transform.go:99 #, c-format msgid "Found 2 resources with type %s in the template. There should only be 1" msgstr "" "В шаблоне найдено 2 ресурса с типом %s. Такой ресурс должен быть всего 1" -#: pkg/acsengine/transform.go:122 +#: pkg/engine/transform.go:122 #, c-format msgid "" "Found no resources with type %s in the template. There should have been 1" @@ -56,12 +56,12 @@ msgstr "Не поддерживается обновление до Kubernetes  msgid "Upgrade to Kubernetes version: %s is not supported from version: %s" msgstr "Не поддерживается обновление до Kubernetes %s с версии: %s" -#: pkg/acsengine/filesaver.go:24 +#: pkg/engine/filesaver.go:24 #, c-format msgid "error creating directory '%s': %s" msgstr "ошибка при создании каталога \"%s\": %s" -#: pkg/acsengine/engine.go:1194 +#: pkg/engine/engine.go:1194 #, c-format msgid "error executing template for file %s: %v" msgstr "ошибка при выполнении шаблона для файла %s: %v" @@ -73,7 +73,7 @@ msgstr "ошибка при выполнении шаблона для файл msgid "error generating upgrade template: %s" msgstr "ошибка при создании шаблона обновления: %s" -#: pkg/acsengine/engine.go:1189 +#: pkg/engine/engine.go:1189 #, c-format msgid "error parsing file %s: %v" msgstr "ошибка при анализе файла %s: %v" @@ -83,12 +83,12 @@ msgstr "ошибка при анализе файла %s: %v" msgid "error reading file %s: %s" msgstr "ошибка при чтении файла %s: %s" -#: pkg/acsengine/ssh.go:55 +#: pkg/engine/ssh.go:55 #, c-format msgid "failed to create openssh public key string: %q" msgstr "не удалось создать строку открытого ключа OpenSSH: %q" -#: pkg/acsengine/ssh.go:49 +#: pkg/engine/ssh.go:49 #, c-format msgid "failed to generate private key for ssh: %q" msgstr "не удалось создать закрытый ключ для SSH: %q" @@ -104,12 +104,12 @@ msgid "invalid version %s for conversion back from unversioned object" msgstr "" "недопустимая версия %s для обратного преобразования из объекта без версий" -#: pkg/acsengine/engine.go:322 +#: pkg/engine/engine.go:322 #, c-format msgid "orchestrator '%s' is unsupported" msgstr "оркестратор \"%s\" не поддерживается" -#: pkg/acsengine/engine.go:187 +#: pkg/engine/engine.go:187 #, c-format msgid "template file %s does not exist" msgstr "файл шаблона %s не существует" @@ -119,7 +119,7 @@ msgstr "файл шаблона %s не существует" msgid "unrecognized APIVersion '%s'" msgstr "нераспознанное значение APIVersion \"%s\"" -#: pkg/acsengine/engine.go:1183 +#: pkg/engine/engine.go:1183 #, c-format msgid "yaml file %s does not exist" msgstr "файл YAML %s не существует" diff --git a/translations/sv_SE/LC_MESSAGES/acsengine.mo b/translations/sv_SE/LC_MESSAGES/aksengine.mo similarity index 100% rename from translations/sv_SE/LC_MESSAGES/acsengine.mo rename to translations/sv_SE/LC_MESSAGES/aksengine.mo diff --git a/translations/sv_SE/LC_MESSAGES/acsengine.po b/translations/sv_SE/LC_MESSAGES/aksengine.po similarity index 88% rename from translations/sv_SE/LC_MESSAGES/acsengine.po rename to translations/sv_SE/LC_MESSAGES/aksengine.po index efee2859ed..efb17e77e7 100644 --- a/translations/sv_SE/LC_MESSAGES/acsengine.po +++ b/translations/sv_SE/LC_MESSAGES/aksengine.po @@ -1,10 +1,10 @@ -# English translations for acs-engine package. +# English translations for aks-engine package. # Copyright (C) 2017 -# This file is distributed under the same license as the acs-engine package. +# This file is distributed under the same license as the aks-engine package. # Jiangtian Li , 2017. msgid "" msgstr "" -"Project-Id-Version: acsengine\n" +"Project-Id-Version: aksengine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-25 00:04+0000\n" "PO-Revision-Date: 2017-07-24 17:23-0700\n" @@ -17,7 +17,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.0.3\n" -#: pkg/acsengine/engine.go:239 +#: pkg/engine/engine.go:239 #, c-format msgid "Error reading file %s, Error: %s" msgstr "Det gick inte att läsa filen %s, Fel: %s" @@ -27,12 +27,12 @@ msgstr "Det gick inte att läsa filen %s, Fel: %s" msgid "Error while querying ARM for resources: %+v" msgstr "Det uppstod ett fel när ARM tillfrågades om resurser: %+v" -#: pkg/acsengine/transform.go:99 +#: pkg/engine/transform.go:99 #, c-format msgid "Found 2 resources with type %s in the template. There should only be 1" msgstr "2 resurser av typen %s påträffades i mallen. Det ska bara finnas 1" -#: pkg/acsengine/transform.go:122 +#: pkg/engine/transform.go:122 #, c-format msgid "" "Found no resources with type %s in the template. There should have been 1" @@ -57,12 +57,12 @@ msgstr "Uppgradering till Kubernetes 1.6.2 stöds inte från version %s" msgid "Upgrade to Kubernetes version: %s is not supported from version: %s" msgstr "Uppgradering till Kubernetes version %s stöds inte från version %s" -#: pkg/acsengine/filesaver.go:24 +#: pkg/engine/filesaver.go:24 #, c-format msgid "error creating directory '%s': %s" msgstr "det uppstod ett fel när katalogen %s': %s skulle skapas" -#: pkg/acsengine/engine.go:1194 +#: pkg/engine/engine.go:1194 #, c-format msgid "error executing template for file %s: %v" msgstr "det uppstod ett fel när mallen för filen %s: %v skulle köras" @@ -74,7 +74,7 @@ msgstr "det uppstod ett fel när mallen för filen %s: %v skulle köras" msgid "error generating upgrade template: %s" msgstr "det uppstod ett fel när uppgraderingsmallen %s skulle genereras" -#: pkg/acsengine/engine.go:1189 +#: pkg/engine/engine.go:1189 #, c-format msgid "error parsing file %s: %v" msgstr "det uppstod ett fel när filen %s: %v skulle parsas" @@ -84,12 +84,12 @@ msgstr "det uppstod ett fel när filen %s: %v skulle parsas" msgid "error reading file %s: %s" msgstr "det gick inte att läsa filen %s: %s" -#: pkg/acsengine/ssh.go:55 +#: pkg/engine/ssh.go:55 #, c-format msgid "failed to create openssh public key string: %q" msgstr "det gick inte att skapa strängen %q för den offentliga nyckeln openssh" -#: pkg/acsengine/ssh.go:49 +#: pkg/engine/ssh.go:49 #, c-format msgid "failed to generate private key for ssh: %q" msgstr "det gick inte att generera den privata nyckeln för ssh: %q" @@ -104,12 +104,12 @@ msgstr "det gick inte att initiera mallgeneratorn %s" msgid "invalid version %s for conversion back from unversioned object" msgstr "ogiltig %s-version för abonnemangsändring från versionslöst objekt" -#: pkg/acsengine/engine.go:322 +#: pkg/engine/engine.go:322 #, c-format msgid "orchestrator '%s' is unsupported" msgstr "initieraren %s stöds inte" -#: pkg/acsengine/engine.go:187 +#: pkg/engine/engine.go:187 #, c-format msgid "template file %s does not exist" msgstr "mallfilen %s finns inte" @@ -119,7 +119,7 @@ msgstr "mallfilen %s finns inte" msgid "unrecognized APIVersion '%s'" msgstr "APIVersion %s känns inte igen" -#: pkg/acsengine/engine.go:1183 +#: pkg/engine/engine.go:1183 #, c-format msgid "yaml file %s does not exist" msgstr "yaml-filen %s finns inte" diff --git a/translations/tr_TR/LC_MESSAGES/acsengine.mo b/translations/tr_TR/LC_MESSAGES/aksengine.mo similarity index 100% rename from translations/tr_TR/LC_MESSAGES/acsengine.mo rename to translations/tr_TR/LC_MESSAGES/aksengine.mo diff --git a/translations/tr_TR/LC_MESSAGES/acsengine.po b/translations/tr_TR/LC_MESSAGES/aksengine.po similarity index 88% rename from translations/tr_TR/LC_MESSAGES/acsengine.po rename to translations/tr_TR/LC_MESSAGES/aksengine.po index 98c6a84011..374cd72d1a 100644 --- a/translations/tr_TR/LC_MESSAGES/acsengine.po +++ b/translations/tr_TR/LC_MESSAGES/aksengine.po @@ -1,10 +1,10 @@ -# English translations for acs-engine package. +# English translations for aks-engine package. # Copyright (C) 2017 -# This file is distributed under the same license as the acs-engine package. +# This file is distributed under the same license as the aks-engine package. # Jiangtian Li , 2017. msgid "" msgstr "" -"Project-Id-Version: acsengine\n" +"Project-Id-Version: aksengine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-25 00:04+0000\n" "PO-Revision-Date: 2017-07-24 17:23-0700\n" @@ -17,7 +17,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.0.3\n" -#: pkg/acsengine/engine.go:239 +#: pkg/engine/engine.go:239 #, c-format msgid "Error reading file %s, Error: %s" msgstr "%s dosyası okunurken hata oluştu, Hata: %s" @@ -27,12 +27,12 @@ msgstr "%s dosyası okunurken hata oluştu, Hata: %s" msgid "Error while querying ARM for resources: %+v" msgstr "Kaynaklar için ARM sorgulanırken hata oluştu: %+v" -#: pkg/acsengine/transform.go:99 +#: pkg/engine/transform.go:99 #, c-format msgid "Found 2 resources with type %s in the template. There should only be 1" msgstr "Şablonda %s türünde 2 kaynak bulundu. Yalnızca 1 olmalıdır" -#: pkg/acsengine/transform.go:122 +#: pkg/engine/transform.go:122 #, c-format msgid "" "Found no resources with type %s in the template. There should have been 1" @@ -55,12 +55,12 @@ msgid "Upgrade to Kubernetes version: %s is not supported from version: %s" msgstr "" "%s Kubernetes sürümüne yükseltmek %s sürümünden başlayarak desteklenmiyor" -#: pkg/acsengine/filesaver.go:24 +#: pkg/engine/filesaver.go:24 #, c-format msgid "error creating directory '%s': %s" msgstr "'%s' dizini oluşturulurken hata oluştu: %s" -#: pkg/acsengine/engine.go:1194 +#: pkg/engine/engine.go:1194 #, c-format msgid "error executing template for file %s: %v" msgstr "%s dosyası için şablon çalıştırılırken hata oluştu :%v" @@ -72,7 +72,7 @@ msgstr "%s dosyası için şablon çalıştırılırken hata oluştu :%v" msgid "error generating upgrade template: %s" msgstr "yükseltme şablonu oluşturulurken hata oluştu: %s" -#: pkg/acsengine/engine.go:1189 +#: pkg/engine/engine.go:1189 #, c-format msgid "error parsing file %s: %v" msgstr "%s dosyası ayrıştırılırken hata oluştu: %v" @@ -82,12 +82,12 @@ msgstr "%s dosyası ayrıştırılırken hata oluştu: %v" msgid "error reading file %s: %s" msgstr "%s dosyası okunurken hata oluştu: %s" -#: pkg/acsengine/ssh.go:55 +#: pkg/engine/ssh.go:55 #, c-format msgid "failed to create openssh public key string: %q" msgstr "openssh ortak anahtar dizesi oluşturulamadı: %q" -#: pkg/acsengine/ssh.go:49 +#: pkg/engine/ssh.go:49 #, c-format msgid "failed to generate private key for ssh: %q" msgstr "ssh için özel anahtar oluşturulamadı: %q" @@ -102,12 +102,12 @@ msgstr "şablon oluşturucu başlatılamadı: %s" msgid "invalid version %s for conversion back from unversioned object" msgstr "Sürüm bilgisi olmayan nesneden geri dönüştürme için geçersiz sürüm %s" -#: pkg/acsengine/engine.go:322 +#: pkg/engine/engine.go:322 #, c-format msgid "orchestrator '%s' is unsupported" msgstr "düzenleyici '%s' desteklenmiyor" -#: pkg/acsengine/engine.go:187 +#: pkg/engine/engine.go:187 #, c-format msgid "template file %s does not exist" msgstr "şablon dosyası %s yok" @@ -117,7 +117,7 @@ msgstr "şablon dosyası %s yok" msgid "unrecognized APIVersion '%s'" msgstr "tanınmayan APIVersion '%s'" -#: pkg/acsengine/engine.go:1183 +#: pkg/engine/engine.go:1183 #, c-format msgid "yaml file %s does not exist" msgstr "yaml dosyası %s yok" diff --git a/translations/zh_CN/LC_MESSAGES/acsengine.mo b/translations/zh_CN/LC_MESSAGES/aksengine.mo similarity index 100% rename from translations/zh_CN/LC_MESSAGES/acsengine.mo rename to translations/zh_CN/LC_MESSAGES/aksengine.mo diff --git a/translations/zh_CN/LC_MESSAGES/acsengine.po b/translations/zh_CN/LC_MESSAGES/aksengine.po similarity index 87% rename from translations/zh_CN/LC_MESSAGES/acsengine.po rename to translations/zh_CN/LC_MESSAGES/aksengine.po index 0bb8de537d..d08ec439c8 100644 --- a/translations/zh_CN/LC_MESSAGES/acsengine.po +++ b/translations/zh_CN/LC_MESSAGES/aksengine.po @@ -1,10 +1,10 @@ -# English translations for acs-engine package. +# English translations for aks-engine package. # Copyright (C) 2017 -# This file is distributed under the same license as the acs-engine package. +# This file is distributed under the same license as the aks-engine package. # Jiangtian Li , 2017. msgid "" msgstr "" -"Project-Id-Version: acsengine\n" +"Project-Id-Version: aksengine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-25 00:04+0000\n" "PO-Revision-Date: 2017-07-24 17:23-0700\n" @@ -17,7 +17,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.0.3\n" -#: pkg/acsengine/engine.go:239 +#: pkg/engine/engine.go:239 #, c-format msgid "Error reading file %s, Error: %s" msgstr "读取文件 %s 时出错,错误: %s" @@ -27,12 +27,12 @@ msgstr "读取文件 %s 时出错,错误: %s" msgid "Error while querying ARM for resources: %+v" msgstr "查询资源的 ARM 时出错: %+v" -#: pkg/acsengine/transform.go:99 +#: pkg/engine/transform.go:99 #, c-format msgid "Found 2 resources with type %s in the template. There should only be 1" msgstr "在模板中发现 2 个 %s 类型的资源。应仅有 1 个资源" -#: pkg/acsengine/transform.go:122 +#: pkg/engine/transform.go:122 #, c-format msgid "" "Found no resources with type %s in the template. There should have been 1" @@ -53,12 +53,12 @@ msgstr "从 %s 版本开始不支持升级到 Kubernetes 1.6.2" msgid "Upgrade to Kubernetes version: %s is not supported from version: %s" msgstr "不支持升级到 Kubernetes 版本 %s (从版本 %s 开始)" -#: pkg/acsengine/filesaver.go:24 +#: pkg/engine/filesaver.go:24 #, c-format msgid "error creating directory '%s': %s" msgstr "创建目录“%s”时出错: %s" -#: pkg/acsengine/engine.go:1194 +#: pkg/engine/engine.go:1194 #, c-format msgid "error executing template for file %s: %v" msgstr "执行 %s 文件的模板时出错: %v" @@ -70,7 +70,7 @@ msgstr "执行 %s 文件的模板时出错: %v" msgid "error generating upgrade template: %s" msgstr "生成升级模板时出错: %s" -#: pkg/acsengine/engine.go:1189 +#: pkg/engine/engine.go:1189 #, c-format msgid "error parsing file %s: %v" msgstr "分析文件 %s 时出错: %v" @@ -80,12 +80,12 @@ msgstr "分析文件 %s 时出错: %v" msgid "error reading file %s: %s" msgstr "读取文件 %s 时出错: %s" -#: pkg/acsengine/ssh.go:55 +#: pkg/engine/ssh.go:55 #, c-format msgid "failed to create openssh public key string: %q" msgstr "未能创建 openssh 公钥字符串: %q" -#: pkg/acsengine/ssh.go:49 +#: pkg/engine/ssh.go:49 #, c-format msgid "failed to generate private key for ssh: %q" msgstr "未能生成 ssh 私钥: %q" @@ -100,12 +100,12 @@ msgstr "未能初始化模板生成器: %s" msgid "invalid version %s for conversion back from unversioned object" msgstr "从未进行版本管理的对象转换回的无效版本 %s" -#: pkg/acsengine/engine.go:322 +#: pkg/engine/engine.go:322 #, c-format msgid "orchestrator '%s' is unsupported" msgstr "不支持业务流程协调程序“%s”" -#: pkg/acsengine/engine.go:187 +#: pkg/engine/engine.go:187 #, c-format msgid "template file %s does not exist" msgstr "模板文件 %s 不存在" @@ -115,7 +115,7 @@ msgstr "模板文件 %s 不存在" msgid "unrecognized APIVersion '%s'" msgstr "无法识别的 APIVersion“%s”" -#: pkg/acsengine/engine.go:1183 +#: pkg/engine/engine.go:1183 #, c-format msgid "yaml file %s does not exist" msgstr "yaml 文件 %s 不存在" diff --git a/translations/zh_TW/LC_MESSAGES/acsengine.mo b/translations/zh_TW/LC_MESSAGES/aksengine.mo similarity index 100% rename from translations/zh_TW/LC_MESSAGES/acsengine.mo rename to translations/zh_TW/LC_MESSAGES/aksengine.mo diff --git a/translations/zh_TW/LC_MESSAGES/acsengine.po b/translations/zh_TW/LC_MESSAGES/aksengine.po similarity index 87% rename from translations/zh_TW/LC_MESSAGES/acsengine.po rename to translations/zh_TW/LC_MESSAGES/aksengine.po index f74d0d54b3..de2c63b4fc 100644 --- a/translations/zh_TW/LC_MESSAGES/acsengine.po +++ b/translations/zh_TW/LC_MESSAGES/aksengine.po @@ -1,10 +1,10 @@ -# English translations for acs-engine package. +# English translations for aks-engine package. # Copyright (C) 2017 -# This file is distributed under the same license as the acs-engine package. +# This file is distributed under the same license as the aks-engine package. # Jiangtian Li , 2017. msgid "" msgstr "" -"Project-Id-Version: acsengine\n" +"Project-Id-Version: aksengine\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-25 00:04+0000\n" "PO-Revision-Date: 2017-07-24 17:23-0700\n" @@ -17,7 +17,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.0.3\n" -#: pkg/acsengine/engine.go:239 +#: pkg/engine/engine.go:239 #, c-format msgid "Error reading file %s, Error: %s" msgstr "讀取檔案 %s 時發生錯誤,錯誤: %s" @@ -27,12 +27,12 @@ msgstr "讀取檔案 %s 時發生錯誤,錯誤: %s" msgid "Error while querying ARM for resources: %+v" msgstr "查詢 ARM 以取得資源時發生錯誤: %+v " -#: pkg/acsengine/transform.go:99 +#: pkg/engine/transform.go:99 #, c-format msgid "Found 2 resources with type %s in the template. There should only be 1" msgstr "在範本中找到 2 個類型為 %s 的資源,但只應有 1 個" -#: pkg/acsengine/transform.go:122 +#: pkg/engine/transform.go:122 #, c-format msgid "" "Found no resources with type %s in the template. There should have been 1" @@ -53,12 +53,12 @@ msgstr "不支援從版本 %s 升級為 Kubernetes 1.6.2" msgid "Upgrade to Kubernetes version: %s is not supported from version: %s" msgstr "Kubernetes 版本 %s 不支援從版本 %s 升級" -#: pkg/acsengine/filesaver.go:24 +#: pkg/engine/filesaver.go:24 #, c-format msgid "error creating directory '%s': %s" msgstr "建立目錄 '%s' 時發生錯誤: %s" -#: pkg/acsengine/engine.go:1194 +#: pkg/engine/engine.go:1194 #, c-format msgid "error executing template for file %s: %v" msgstr "執行檔案 %s 的範本時發生錯誤: %v" @@ -70,7 +70,7 @@ msgstr "執行檔案 %s 的範本時發生錯誤: %v" msgid "error generating upgrade template: %s" msgstr "產生升級範本時發生錯誤: %s" -#: pkg/acsengine/engine.go:1189 +#: pkg/engine/engine.go:1189 #, c-format msgid "error parsing file %s: %v" msgstr "剖析檔案 %s 時發生錯誤: %v" @@ -80,12 +80,12 @@ msgstr "剖析檔案 %s 時發生錯誤: %v" msgid "error reading file %s: %s" msgstr "讀取檔案 %s 時發生錯誤: %s" -#: pkg/acsengine/ssh.go:55 +#: pkg/engine/ssh.go:55 #, c-format msgid "failed to create openssh public key string: %q" msgstr "無法建立 OpenSSH 公開金鑰字串: %q" -#: pkg/acsengine/ssh.go:49 +#: pkg/engine/ssh.go:49 #, c-format msgid "failed to generate private key for ssh: %q" msgstr "無法產生 SSH 的私密金鑰: %q" @@ -100,12 +100,12 @@ msgstr "無法將範本產生器初始化: %s" msgid "invalid version %s for conversion back from unversioned object" msgstr "無法從未進行版本控制的物件轉換回版本 %s" -#: pkg/acsengine/engine.go:322 +#: pkg/engine/engine.go:322 #, c-format msgid "orchestrator '%s' is unsupported" msgstr "不支援協調器 '%s'" -#: pkg/acsengine/engine.go:187 +#: pkg/engine/engine.go:187 #, c-format msgid "template file %s does not exist" msgstr "範本檔案 %s 不存在" @@ -115,7 +115,7 @@ msgstr "範本檔案 %s 不存在" msgid "unrecognized APIVersion '%s'" msgstr "無法識別的 APIVersion '%s'" -#: pkg/acsengine/engine.go:1183 +#: pkg/engine/engine.go:1183 #, c-format msgid "yaml file %s does not exist" msgstr "yaml 檔案 %s 不存在" diff --git a/vendor/golang.org/x/crypto/bcrypt/base64.go b/vendor/golang.org/x/crypto/bcrypt/base64.go deleted file mode 100644 index fc31160908..0000000000 --- a/vendor/golang.org/x/crypto/bcrypt/base64.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bcrypt - -import "encoding/base64" - -const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - -var bcEncoding = base64.NewEncoding(alphabet) - -func base64Encode(src []byte) []byte { - n := bcEncoding.EncodedLen(len(src)) - dst := make([]byte, n) - bcEncoding.Encode(dst, src) - for dst[n-1] == '=' { - n-- - } - return dst[:n] -} - -func base64Decode(src []byte) ([]byte, error) { - numOfEquals := 4 - (len(src) % 4) - for i := 0; i < numOfEquals; i++ { - src = append(src, '=') - } - - dst := make([]byte, bcEncoding.DecodedLen(len(src))) - n, err := bcEncoding.Decode(dst, src) - if err != nil { - return nil, err - } - return dst[:n], nil -} diff --git a/vendor/golang.org/x/crypto/bcrypt/bcrypt.go b/vendor/golang.org/x/crypto/bcrypt/bcrypt.go deleted file mode 100644 index 202fa8aff4..0000000000 --- a/vendor/golang.org/x/crypto/bcrypt/bcrypt.go +++ /dev/null @@ -1,295 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package bcrypt implements Provos and Mazières's bcrypt adaptive hashing -// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf -package bcrypt // import "golang.org/x/crypto/bcrypt" - -// The code is a port of Provos and Mazières's C implementation. -import ( - "crypto/rand" - "crypto/subtle" - "errors" - "fmt" - "io" - "strconv" - - "golang.org/x/crypto/blowfish" -) - -const ( - MinCost int = 4 // the minimum allowable cost as passed in to GenerateFromPassword - MaxCost int = 31 // the maximum allowable cost as passed in to GenerateFromPassword - DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword -) - -// The error returned from CompareHashAndPassword when a password and hash do -// not match. -var ErrMismatchedHashAndPassword = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password") - -// The error returned from CompareHashAndPassword when a hash is too short to -// be a bcrypt hash. -var ErrHashTooShort = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password") - -// The error returned from CompareHashAndPassword when a hash was created with -// a bcrypt algorithm newer than this implementation. -type HashVersionTooNewError byte - -func (hv HashVersionTooNewError) Error() string { - return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion) -} - -// The error returned from CompareHashAndPassword when a hash starts with something other than '$' -type InvalidHashPrefixError byte - -func (ih InvalidHashPrefixError) Error() string { - return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih)) -} - -type InvalidCostError int - -func (ic InvalidCostError) Error() string { - return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost)) -} - -const ( - majorVersion = '2' - minorVersion = 'a' - maxSaltSize = 16 - maxCryptedHashSize = 23 - encodedSaltSize = 22 - encodedHashSize = 31 - minHashSize = 59 -) - -// magicCipherData is an IV for the 64 Blowfish encryption calls in -// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes. -var magicCipherData = []byte{ - 0x4f, 0x72, 0x70, 0x68, - 0x65, 0x61, 0x6e, 0x42, - 0x65, 0x68, 0x6f, 0x6c, - 0x64, 0x65, 0x72, 0x53, - 0x63, 0x72, 0x79, 0x44, - 0x6f, 0x75, 0x62, 0x74, -} - -type hashed struct { - hash []byte - salt []byte - cost int // allowed range is MinCost to MaxCost - major byte - minor byte -} - -// GenerateFromPassword returns the bcrypt hash of the password at the given -// cost. If the cost given is less than MinCost, the cost will be set to -// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package, -// to compare the returned hashed password with its cleartext version. -func GenerateFromPassword(password []byte, cost int) ([]byte, error) { - p, err := newFromPassword(password, cost) - if err != nil { - return nil, err - } - return p.Hash(), nil -} - -// CompareHashAndPassword compares a bcrypt hashed password with its possible -// plaintext equivalent. Returns nil on success, or an error on failure. -func CompareHashAndPassword(hashedPassword, password []byte) error { - p, err := newFromHash(hashedPassword) - if err != nil { - return err - } - - otherHash, err := bcrypt(password, p.cost, p.salt) - if err != nil { - return err - } - - otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor} - if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 { - return nil - } - - return ErrMismatchedHashAndPassword -} - -// Cost returns the hashing cost used to create the given hashed -// password. When, in the future, the hashing cost of a password system needs -// to be increased in order to adjust for greater computational power, this -// function allows one to establish which passwords need to be updated. -func Cost(hashedPassword []byte) (int, error) { - p, err := newFromHash(hashedPassword) - if err != nil { - return 0, err - } - return p.cost, nil -} - -func newFromPassword(password []byte, cost int) (*hashed, error) { - if cost < MinCost { - cost = DefaultCost - } - p := new(hashed) - p.major = majorVersion - p.minor = minorVersion - - err := checkCost(cost) - if err != nil { - return nil, err - } - p.cost = cost - - unencodedSalt := make([]byte, maxSaltSize) - _, err = io.ReadFull(rand.Reader, unencodedSalt) - if err != nil { - return nil, err - } - - p.salt = base64Encode(unencodedSalt) - hash, err := bcrypt(password, p.cost, p.salt) - if err != nil { - return nil, err - } - p.hash = hash - return p, err -} - -func newFromHash(hashedSecret []byte) (*hashed, error) { - if len(hashedSecret) < minHashSize { - return nil, ErrHashTooShort - } - p := new(hashed) - n, err := p.decodeVersion(hashedSecret) - if err != nil { - return nil, err - } - hashedSecret = hashedSecret[n:] - n, err = p.decodeCost(hashedSecret) - if err != nil { - return nil, err - } - hashedSecret = hashedSecret[n:] - - // The "+2" is here because we'll have to append at most 2 '=' to the salt - // when base64 decoding it in expensiveBlowfishSetup(). - p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2) - copy(p.salt, hashedSecret[:encodedSaltSize]) - - hashedSecret = hashedSecret[encodedSaltSize:] - p.hash = make([]byte, len(hashedSecret)) - copy(p.hash, hashedSecret) - - return p, nil -} - -func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) { - cipherData := make([]byte, len(magicCipherData)) - copy(cipherData, magicCipherData) - - c, err := expensiveBlowfishSetup(password, uint32(cost), salt) - if err != nil { - return nil, err - } - - for i := 0; i < 24; i += 8 { - for j := 0; j < 64; j++ { - c.Encrypt(cipherData[i:i+8], cipherData[i:i+8]) - } - } - - // Bug compatibility with C bcrypt implementations. We only encode 23 of - // the 24 bytes encrypted. - hsh := base64Encode(cipherData[:maxCryptedHashSize]) - return hsh, nil -} - -func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) { - csalt, err := base64Decode(salt) - if err != nil { - return nil, err - } - - // Bug compatibility with C bcrypt implementations. They use the trailing - // NULL in the key string during expansion. - // We copy the key to prevent changing the underlying array. - ckey := append(key[:len(key):len(key)], 0) - - c, err := blowfish.NewSaltedCipher(ckey, csalt) - if err != nil { - return nil, err - } - - var i, rounds uint64 - rounds = 1 << cost - for i = 0; i < rounds; i++ { - blowfish.ExpandKey(ckey, c) - blowfish.ExpandKey(csalt, c) - } - - return c, nil -} - -func (p *hashed) Hash() []byte { - arr := make([]byte, 60) - arr[0] = '$' - arr[1] = p.major - n := 2 - if p.minor != 0 { - arr[2] = p.minor - n = 3 - } - arr[n] = '$' - n += 1 - copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost))) - n += 2 - arr[n] = '$' - n += 1 - copy(arr[n:], p.salt) - n += encodedSaltSize - copy(arr[n:], p.hash) - n += encodedHashSize - return arr[:n] -} - -func (p *hashed) decodeVersion(sbytes []byte) (int, error) { - if sbytes[0] != '$' { - return -1, InvalidHashPrefixError(sbytes[0]) - } - if sbytes[1] > majorVersion { - return -1, HashVersionTooNewError(sbytes[1]) - } - p.major = sbytes[1] - n := 3 - if sbytes[2] != '$' { - p.minor = sbytes[2] - n++ - } - return n, nil -} - -// sbytes should begin where decodeVersion left off. -func (p *hashed) decodeCost(sbytes []byte) (int, error) { - cost, err := strconv.Atoi(string(sbytes[0:2])) - if err != nil { - return -1, err - } - err = checkCost(cost) - if err != nil { - return -1, err - } - p.cost = cost - return 3, nil -} - -func (p *hashed) String() string { - return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor) -} - -func checkCost(cost int) error { - if cost < MinCost || cost > MaxCost { - return InvalidCostError(cost) - } - return nil -} diff --git a/vendor/golang.org/x/crypto/blowfish/block.go b/vendor/golang.org/x/crypto/blowfish/block.go deleted file mode 100644 index 9d80f19521..0000000000 --- a/vendor/golang.org/x/crypto/blowfish/block.go +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package blowfish - -// getNextWord returns the next big-endian uint32 value from the byte slice -// at the given position in a circular manner, updating the position. -func getNextWord(b []byte, pos *int) uint32 { - var w uint32 - j := *pos - for i := 0; i < 4; i++ { - w = w<<8 | uint32(b[j]) - j++ - if j >= len(b) { - j = 0 - } - } - *pos = j - return w -} - -// ExpandKey performs a key expansion on the given *Cipher. Specifically, it -// performs the Blowfish algorithm's key schedule which sets up the *Cipher's -// pi and substitution tables for calls to Encrypt. This is used, primarily, -// by the bcrypt package to reuse the Blowfish key schedule during its -// set up. It's unlikely that you need to use this directly. -func ExpandKey(key []byte, c *Cipher) { - j := 0 - for i := 0; i < 18; i++ { - // Using inlined getNextWord for performance. - var d uint32 - for k := 0; k < 4; k++ { - d = d<<8 | uint32(key[j]) - j++ - if j >= len(key) { - j = 0 - } - } - c.p[i] ^= d - } - - var l, r uint32 - for i := 0; i < 18; i += 2 { - l, r = encryptBlock(l, r, c) - c.p[i], c.p[i+1] = l, r - } - - for i := 0; i < 256; i += 2 { - l, r = encryptBlock(l, r, c) - c.s0[i], c.s0[i+1] = l, r - } - for i := 0; i < 256; i += 2 { - l, r = encryptBlock(l, r, c) - c.s1[i], c.s1[i+1] = l, r - } - for i := 0; i < 256; i += 2 { - l, r = encryptBlock(l, r, c) - c.s2[i], c.s2[i+1] = l, r - } - for i := 0; i < 256; i += 2 { - l, r = encryptBlock(l, r, c) - c.s3[i], c.s3[i+1] = l, r - } -} - -// This is similar to ExpandKey, but folds the salt during the key -// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero -// salt passed in, reusing ExpandKey turns out to be a place of inefficiency -// and specializing it here is useful. -func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) { - j := 0 - for i := 0; i < 18; i++ { - c.p[i] ^= getNextWord(key, &j) - } - - j = 0 - var l, r uint32 - for i := 0; i < 18; i += 2 { - l ^= getNextWord(salt, &j) - r ^= getNextWord(salt, &j) - l, r = encryptBlock(l, r, c) - c.p[i], c.p[i+1] = l, r - } - - for i := 0; i < 256; i += 2 { - l ^= getNextWord(salt, &j) - r ^= getNextWord(salt, &j) - l, r = encryptBlock(l, r, c) - c.s0[i], c.s0[i+1] = l, r - } - - for i := 0; i < 256; i += 2 { - l ^= getNextWord(salt, &j) - r ^= getNextWord(salt, &j) - l, r = encryptBlock(l, r, c) - c.s1[i], c.s1[i+1] = l, r - } - - for i := 0; i < 256; i += 2 { - l ^= getNextWord(salt, &j) - r ^= getNextWord(salt, &j) - l, r = encryptBlock(l, r, c) - c.s2[i], c.s2[i+1] = l, r - } - - for i := 0; i < 256; i += 2 { - l ^= getNextWord(salt, &j) - r ^= getNextWord(salt, &j) - l, r = encryptBlock(l, r, c) - c.s3[i], c.s3[i+1] = l, r - } -} - -func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { - xl, xr := l, r - xl ^= c.p[0] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16] - xr ^= c.p[17] - return xr, xl -} - -func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { - xl, xr := l, r - xl ^= c.p[17] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1] - xr ^= c.p[0] - return xr, xl -} diff --git a/vendor/golang.org/x/crypto/blowfish/cipher.go b/vendor/golang.org/x/crypto/blowfish/cipher.go deleted file mode 100644 index 2641dadd64..0000000000 --- a/vendor/golang.org/x/crypto/blowfish/cipher.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm. -package blowfish // import "golang.org/x/crypto/blowfish" - -// The code is a port of Bruce Schneier's C implementation. -// See https://www.schneier.com/blowfish.html. - -import "strconv" - -// The Blowfish block size in bytes. -const BlockSize = 8 - -// A Cipher is an instance of Blowfish encryption using a particular key. -type Cipher struct { - p [18]uint32 - s0, s1, s2, s3 [256]uint32 -} - -type KeySizeError int - -func (k KeySizeError) Error() string { - return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k)) -} - -// NewCipher creates and returns a Cipher. -// The key argument should be the Blowfish key, from 1 to 56 bytes. -func NewCipher(key []byte) (*Cipher, error) { - var result Cipher - if k := len(key); k < 1 || k > 56 { - return nil, KeySizeError(k) - } - initCipher(&result) - ExpandKey(key, &result) - return &result, nil -} - -// NewSaltedCipher creates a returns a Cipher that folds a salt into its key -// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is -// sufficient and desirable. For bcrypt compatibility, the key can be over 56 -// bytes. -func NewSaltedCipher(key, salt []byte) (*Cipher, error) { - if len(salt) == 0 { - return NewCipher(key) - } - var result Cipher - if k := len(key); k < 1 { - return nil, KeySizeError(k) - } - initCipher(&result) - expandKeyWithSalt(key, salt, &result) - return &result, nil -} - -// BlockSize returns the Blowfish block size, 8 bytes. -// It is necessary to satisfy the Block interface in the -// package "crypto/cipher". -func (c *Cipher) BlockSize() int { return BlockSize } - -// Encrypt encrypts the 8-byte buffer src using the key k -// and stores the result in dst. -// Note that for amounts of data larger than a block, -// it is not safe to just call Encrypt on successive blocks; -// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go). -func (c *Cipher) Encrypt(dst, src []byte) { - l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) - r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) - l, r = encryptBlock(l, r, c) - dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) - dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) -} - -// Decrypt decrypts the 8-byte buffer src using the key k -// and stores the result in dst. -func (c *Cipher) Decrypt(dst, src []byte) { - l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) - r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) - l, r = decryptBlock(l, r, c) - dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) - dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) -} - -func initCipher(c *Cipher) { - copy(c.p[0:], p[0:]) - copy(c.s0[0:], s0[0:]) - copy(c.s1[0:], s1[0:]) - copy(c.s2[0:], s2[0:]) - copy(c.s3[0:], s3[0:]) -} diff --git a/vendor/golang.org/x/crypto/blowfish/const.go b/vendor/golang.org/x/crypto/blowfish/const.go deleted file mode 100644 index d04077595a..0000000000 --- a/vendor/golang.org/x/crypto/blowfish/const.go +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// The startup permutation array and substitution boxes. -// They are the hexadecimal digits of PI; see: -// https://www.schneier.com/code/constants.txt. - -package blowfish - -var s0 = [256]uint32{ - 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, - 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, - 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, - 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, - 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, - 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, - 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, - 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, - 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, - 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, - 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, - 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, - 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, - 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, - 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, - 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, - 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, - 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, - 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, - 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, - 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, - 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, - 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, - 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, - 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, - 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, - 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, - 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, - 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, - 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, - 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, - 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, - 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, - 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, - 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, - 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, - 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, - 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, - 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, - 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, - 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, - 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, - 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, -} - -var s1 = [256]uint32{ - 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, - 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, - 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, - 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, - 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, - 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, - 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, - 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, - 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, - 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, - 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, - 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, - 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, - 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, - 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, - 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, - 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, - 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, - 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, - 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, - 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, - 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, - 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, - 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, - 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, - 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, - 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, - 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, - 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, - 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, - 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, - 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, - 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, - 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, - 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, - 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, - 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, - 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, - 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, - 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, - 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, - 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, - 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, -} - -var s2 = [256]uint32{ - 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, - 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, - 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, - 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, - 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, - 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, - 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, - 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, - 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, - 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, - 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, - 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, - 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, - 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, - 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, - 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, - 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, - 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, - 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, - 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, - 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, - 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, - 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, - 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, - 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, - 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, - 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, - 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, - 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, - 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, - 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, - 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, - 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, - 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, - 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, - 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, - 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, - 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, - 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, - 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, - 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, - 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, - 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, -} - -var s3 = [256]uint32{ - 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, - 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, - 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, - 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, - 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, - 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, - 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, - 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, - 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, - 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, - 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, - 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, - 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, - 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, - 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, - 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, - 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, - 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, - 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, - 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, - 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, - 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, - 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, - 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, - 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, - 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, - 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, - 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, - 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, - 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, - 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, - 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, - 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, - 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, - 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, - 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, - 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, - 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, - 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, - 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, - 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, - 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, - 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6, -} - -var p = [18]uint32{ - 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, - 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, - 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b, -} diff --git a/versioning.mk b/versioning.mk index ca442af492..0b4f1dcd28 100644 --- a/versioning.mk +++ b/versioning.mk @@ -3,12 +3,12 @@ GIT_SHA = $(shell git rev-parse --short HEAD) GIT_TAG = $(shell git describe --tags --abbrev=0 --exact-match 2>/dev/null || echo "canary") GIT_DIRTY = $(shell test -n "`git status --porcelain`" && echo "dirty" || echo "clean") -LDFLAGS += -X github.com/Azure/acs-engine/cmd.BuildSHA=${GIT_SHA} -LDFLAGS += -X github.com/Azure/acs-engine/cmd.GitTreeState=${GIT_DIRTY} +LDFLAGS += -X github.com/Azure/aks-engine/cmd.BuildSHA=${GIT_SHA} +LDFLAGS += -X github.com/Azure/aks-engine/cmd.GitTreeState=${GIT_DIRTY} DOCKER_VERSION ?= git-${GIT_SHA} ifneq ($(GIT_TAG),) - LDFLAGS += -X github.com/Azure/acs-engine/cmd.BuildTag=${GIT_TAG} + LDFLAGS += -X github.com/Azure/aks-engine/cmd.BuildTag=${GIT_TAG} endif info: From d71c3410026ec2471d4f6ff130092d18395090ff Mon Sep 17 00:00:00 2001 From: Cecile Robert-Michon Date: Thu, 15 Nov 2018 10:01:48 -0800 Subject: [PATCH 02/29] Fix prow set up (#3) --- .prowci/Makefile | 8 ++++---- .prowci/README.md | 9 ++++----- .prowci/config.yaml | 2 +- .prowci/hook.yaml | 2 +- .prowci/ingress.yaml | 4 ++-- .prowci/tide.yaml | 2 +- 6 files changed, 13 insertions(+), 14 deletions(-) diff --git a/.prowci/Makefile b/.prowci/Makefile index 7952884fb0..6fc6b4ae83 100644 --- a/.prowci/Makefile +++ b/.prowci/Makefile @@ -2,13 +2,13 @@ prow: prow-config prow-secrets prow-services .PHONY: prow prow-config: - kubectl create cm config --from-file=config=config.yaml - kubectl create cm plugins --from-file=plugins=plugins.yaml + kubectl create cm config --from-file=config.yaml=config.yaml + kubectl create cm plugins --from-file=plugins.yaml=plugins.yaml .PHONY: prow-config prow-config-update: - kubectl create cm config --from-file=config=config.yaml -o yaml --dry-run | kubectl replace -f - - kubectl create cm plugins --from-file=plugins=plugins.yaml -o yaml --dry-run | kubectl replace -f - + kubectl create cm config --from-file=config.yaml=config.yaml -o yaml --dry-run | kubectl replace -f - + kubectl create cm plugins --from-file=plugins.yaml=plugins.yaml -o yaml --dry-run | kubectl replace -f - .PHONY: prow-config-update prow-secrets: diff --git a/.prowci/README.md b/.prowci/README.md index a84097b627..343b62a148 100644 --- a/.prowci/README.md +++ b/.prowci/README.md @@ -6,10 +6,10 @@ Prow in [upstream docs][0]. ## aks-engine setup -Prow is optimized to run as a Kubernetes application. There are some pre-installation -steps that need to happen in a new Kubernetes cluster before deploying Prow. These -involve setting up an Ingress controller and a mechanism to do TLS. The [Azure docs][1] -explain how to setup Ingress with TLS on top of a Kubernetes cluster in Azure. +Deploy a new Kubernetes cluster (eg. `az aks create -g acse-test-prow-ci -n prow) + +Set up an Ingress controller and a mechanism to do TLS. The [Azure docs][1] +explain how to setup Ingress with TLS on top of a Kubernetes cluster in Azure. (make sure you specify `--set rbac.create=true` when creating the ingress controller) A Github webhook also needs to be setup in the repo that points to `dns-name/hook`. `dns-name` is the DNS name setup during the DNS configuration of the Ingress controller. @@ -35,6 +35,5 @@ appropriately on Github. `deck` is installed as the Prow frontend. Last, `tide` is also installed that takes care of merging pull requests that pass all tests and satisfy a set of label requirements. - [0]: https://github.com/kubernetes/test-infra/tree/master/prow#prow [1]: https://docs.microsoft.com/en-us/azure/aks/ingress \ No newline at end of file diff --git a/.prowci/config.yaml b/.prowci/config.yaml index 24f6a35ce7..381d66bdab 100644 --- a/.prowci/config.yaml +++ b/.prowci/config.yaml @@ -1,7 +1,7 @@ log_level: debug tide: - # target_url: http://ci-bot-aks-ingress.eastus.cloudapp.azure.com/tide.html + # target_url: http://prow-ci-bot-ingress.eastus.cloudapp.azure.com/tide.html merge_method: Azure/aks-engine: squash queries: diff --git a/.prowci/hook.yaml b/.prowci/hook.yaml index 8a8582051f..1c28f27d58 100644 --- a/.prowci/hook.yaml +++ b/.prowci/hook.yaml @@ -39,7 +39,7 @@ items: spec: containers: - name: hook - image: quay.io/kargakis/hook:workaround + image: registry.svc.ci.openshift.org/ci/hook:latest imagePullPolicy: IfNotPresent args: - --dry-run=false diff --git a/.prowci/ingress.yaml b/.prowci/ingress.yaml index d25d9c7dfb..b56a201f3d 100644 --- a/.prowci/ingress.yaml +++ b/.prowci/ingress.yaml @@ -9,9 +9,9 @@ spec: tls: - secretName: prow-tls hosts: - - ci-bot-aks-ingress.eastus.cloudapp.azure.com + - prow-ci-bot-ingress.eastus.cloudapp.azure.com rules: - - host: ci-bot-aks-ingress.eastus.cloudapp.azure.com + - host: prow-ci-bot-ingress.eastus.cloudapp.azure.com http: paths: - path: /* diff --git a/.prowci/tide.yaml b/.prowci/tide.yaml index 5ea89e2232..d15970deba 100644 --- a/.prowci/tide.yaml +++ b/.prowci/tide.yaml @@ -38,7 +38,7 @@ items: serviceAccountName: tide containers: - name: tide - image: quay.io/kargakis/tide:workaround + image: registry.svc.ci.openshift.org/ci/tide:latest imagePullPolicy: IfNotPresent args: - --dry-run=false From 1b082728b0a68c695dc10af17a191ef371919756 Mon Sep 17 00:00:00 2001 From: Jack Francis Date: Thu, 15 Nov 2018 10:35:52 -0800 Subject: [PATCH 03/29] E2E: honor CLEANUP_ON_EXIT, default to false (#5) --- test/e2e/config/config.go | 2 +- test/e2e/engine/template.go | 4 ++-- test/e2e/runner.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/e2e/config/config.go b/test/e2e/config/config.go index 013dda8f21..4debaf9c5b 100644 --- a/test/e2e/config/config.go +++ b/test/e2e/config/config.go @@ -25,7 +25,7 @@ type Config struct { Location string `envconfig:"LOCATION"` // Location where you want to create the cluster Regions []string `envconfig:"REGIONS"` // A whitelist of availableregions ClusterDefinition string `envconfig:"CLUSTER_DEFINITION" required:"true" default:"examples/kubernetes.json"` // ClusterDefinition is the path on disk to the json template these are normally located in examples/ - CleanUpOnExit bool `envconfig:"CLEANUP_ON_EXIT" default:"true"` // if set the tests will not clean up rgs when tests finish + CleanUpOnExit bool `envconfig:"CLEANUP_ON_EXIT" default:"false"` // if true the tests will clean up rgs when tests finish CleanUpIfFail bool `envconfig:"CLEANUP_IF_FAIL" default:"true"` RetainSSH bool `envconfig:"RETAIN_SSH" default:"true"` StabilityIterations int `envconfig:"STABILITY_ITERATIONS"` diff --git a/test/e2e/engine/template.go b/test/e2e/engine/template.go index fec56c47d2..3a1355b809 100644 --- a/test/e2e/engine/template.go +++ b/test/e2e/engine/template.go @@ -156,8 +156,8 @@ func Build(cfg *config.Config, masterSubnetID string, agentSubnetID string, isVM // NodeCount returns the number of nodes that should be provisioned for a given cluster definition func (e *Engine) NodeCount() int { - expectedCount := e.ClusterDefinition.Properties.MasterProfile.Count - for _, pool := range e.ClusterDefinition.Properties.AgentPoolProfiles { + expectedCount := e.ExpandedDefinition.Properties.MasterProfile.Count + for _, pool := range e.ExpandedDefinition.Properties.AgentPoolProfiles { expectedCount = expectedCount + pool.Count } return expectedCount diff --git a/test/e2e/runner.go b/test/e2e/runner.go index 2d1543df84..8dcc8ac320 100644 --- a/test/e2e/runner.go +++ b/test/e2e/runner.go @@ -130,7 +130,7 @@ func main() { } } } else { - cliProvisioner.ResourceGroups = append(rgs, cliProvisioner.Config.Name) + rgs = append(rgs, cliProvisioner.Config.Name) engCfg, err := engine.ParseConfig(cfg.CurrentWorkingDir, cfg.ClusterDefinition, cfg.Name) cfg.SetKubeConfig() if err != nil { From 97bfe989e4c5f875ce0ebc7253ac43acc120b887 Mon Sep 17 00:00:00 2001 From: Jack Francis Date: Thu, 15 Nov 2018 13:29:11 -0800 Subject: [PATCH 04/29] updated readme to reflect acs-engine transition (#20) --- README.md | 64 +++++-------------------------------------------------- 1 file changed, 5 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index 29bb115d81..1135b27fe4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Microsoft Azure Kubernetes Service Engine - Builds Kubernetes Clusters +# AKS-Engine - Units of Kubernetes on Azure! [![Coverage Status](https://codecov.io/gh/Azure/aks-engine/branch/master/graph/badge.svg)](https://codecov.io/gh/Azure/aks-engine) [![CircleCI](https://circleci.com/gh/Azure/aks-engine/tree/master.svg?style=svg)](https://circleci.com/gh/Azure/aks-engine/tree/master) @@ -6,66 +6,12 @@ ## Overview -The Azure Kubernetes Service Engine (`aks-engine`) generates ARM (Azure Resource Manager) templates for Kubernetes clusters on Microsoft Azure. The input to the tool is a cluster definition. The cluster definition (or apimodel) is very similar to (in many cases the same as) the ARM template syntax used to deploy a Microsoft Azure Kubernetes Service cluster. +AKS-Engine leverages ARM (Azure Resource Manager) to build Kubernetes IaaS in Azure. Originally [acs-engine](https://github.com/Azure/acs-engine), the project has moved here (1) to evolve without harming its legacy non-k8s bits that other non-k8s Azure upstream projects depend upon, and (2) to better reflect its affinity with [AKS](https://docs.microsoft.com/en-us/azure/aks), Azure's managed Kubernetes service offering. -The cluster definition file enables you to customize your Kubernetes cluster in many ways, including: +## Under Construction -* Kubernetes version -* multiple agent pools where each agent pool can specify: - * standard or premium VM Sizes, including GPU optimized VM sizes - * Node count - * Virtual Machine ScaleSets or Availability Sets - * Storage Account Disks or Managed Disks - * OS and distro -* Custom VNET -* Extensions - -More info, including a thorough walkthrough is [here](docs/aksengine.md). - -## User guides - -These guides show how to create your first deployment: - -* [Kubernetes Walkthrough](docs/kubernetes.md) - shows how to create a Linux or Windows Kubernetes cluster on Azure - -These guides cover more advanced features to try out after you have built your first cluster: - -* [Cluster Definition](docs/clusterdefinition.md) - describes the components of the cluster definition file -* [Custom VNET](examples/vnet) - shows how to use a custom VNET -* [Attached Disks](examples/disks-storageaccount) - shows how to attach up to 4 disks per node -* [Managed Disks](examples/disks-managed) - shows how to use managed disks -* [Large Clusters](examples/largeclusters) - shows how to create cluster sizes of up to 1200 nodes - -## Contributing - -Follow the [developers guide](docs/developers.md) to set up your environment. - -To build aks-engine, run `make build`. If you are developing with a working [Docker environment](https://docs.docker.com/engine), you can also run `make dev` (or `makedev.ps1` on Windows) first to start a Docker container and run `make build` inside the container. - -Please follow these instructions before submitting a PR: - -1. Execute `make test` to run unit tests. -2. Manually test deployments if you are making modifications to the templates. - * For example, if you have to change the expected resulting templates then you should deploy the relevant example cluster definitions to ensure that you are not introducing any regressions. -3. Make sure that your changes are properly documented and include relevant unit tests. - -## Usage - -### Generate Templates - -Usage is best demonstrated with an example: - -```sh -$ vim examples/kubernetes.json - -# insert your preferred, unique DNS prefix -# insert your SSH public key - -$ ./aks-engine generate examples/kubernetes.json -``` - -This produces a new directory inside `_output/` that contains an ARM template for deploying Kubernetes into Azure. (In the case of Kubernetes, some additional needed assets are generated and placed in the output directory.) +We are currently in transition from acs-engine to aks-engine! Bear with us as we stabilize this space as the future home for building customizable, self-managed Kubernetes on Azure! ## Code of conduct -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. \ No newline at end of file From 1aa131dcfea3daf4ecf77bb3a6b36560010e8b10 Mon Sep 17 00:00:00 2001 From: Matt Boersma Date: Thu, 15 Nov 2018 17:01:21 -0700 Subject: [PATCH 05/29] Add copyright header to source code that isn't Go (#24) --- packer/cleanup-vhd.sh | 3 +++ packer/feature-flagged.sh | 3 +++ packer/init-variables.sh | 3 +++ packer/install-dependencies.sh | 3 +++ pkg/engine/testdata/rename.sh | 3 +++ pkg/helpers/Get-AzureConstants.py | 3 +++ scripts/azure-const.sh | 4 ++++ scripts/build-windows-k8s.sh | 4 ++++ scripts/convert-lcg-lcl.sh | 3 +++ scripts/devenv.sh | 3 +++ scripts/update-enus-po.sh | 3 +++ scripts/update-translation.sh | 3 +++ scripts/validate-dependencies.sh | 3 +++ scripts/validate-generated.sh | 3 +++ test/cluster-tests/kubernetes/k8s-utils.sh | 3 +++ test/cluster-tests/kubernetes/test.sh | 3 +++ test/cluster-tests/utils.sh | 2 ++ test/common.sh | 3 +++ test/deploy.sh | 3 +++ test/e2e.sh | 3 +++ test/e2e/cleanup.sh | 3 +++ test/shunit/deploy_template.sh | 3 +++ test/shunit/generate_template.sh | 3 +++ test/shunit/scale_agent_pool.sh | 3 +++ test/shunit/validate_deployment.sh | 3 +++ test/step.sh | 3 +++ 26 files changed, 79 insertions(+) diff --git a/packer/cleanup-vhd.sh b/packer/cleanup-vhd.sh index bac4463301..0ebd36c80a 100644 --- a/packer/cleanup-vhd.sh +++ b/packer/cleanup-vhd.sh @@ -1,5 +1,8 @@ #!/bin/bash -eux +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + ## Cleanup packer SSH key and machine ID generated for this boot rm -f /root/.ssh/authorized_keys rm -f /home/packer/.ssh/authorized_keys diff --git a/packer/feature-flagged.sh b/packer/feature-flagged.sh index 4864eefe40..bd1f991263 100644 --- a/packer/feature-flagged.sh +++ b/packer/feature-flagged.sh @@ -1,5 +1,8 @@ #!/bin/bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + function installDockerEngine() { DOCKER_REPO="https://apt.dockerproject.org/repo" DOCKER_ENGINE_VERSION="1.13.*" diff --git a/packer/init-variables.sh b/packer/init-variables.sh index ae6091da84..b11e93793a 100755 --- a/packer/init-variables.sh +++ b/packer/init-variables.sh @@ -1,5 +1,8 @@ #!/bin/bash -e +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + CDIR=$(dirname "${BASH_SOURCE}") SETTINGS_JSON="${SETTINGS_JSON:-./packer/settings.json}" diff --git a/packer/install-dependencies.sh b/packer/install-dependencies.sh index f5ed222f8f..432f79e1d6 100644 --- a/packer/install-dependencies.sh +++ b/packer/install-dependencies.sh @@ -1,5 +1,8 @@ #!/bin/bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + source /home/packer/provision_installs.sh source /home/packer/provision_source.sh source /home/packer/feature-flagged.sh diff --git a/pkg/engine/testdata/rename.sh b/pkg/engine/testdata/rename.sh index 36f2a51b7b..18883e3ba2 100755 --- a/pkg/engine/testdata/rename.sh +++ b/pkg/engine/testdata/rename.sh @@ -1,5 +1,8 @@ #/bin/bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + for f in $(find . -name "*.err"); do len=${#f} mv ${f} ${f::len-4}; diff --git a/pkg/helpers/Get-AzureConstants.py b/pkg/helpers/Get-AzureConstants.py index d567f9ee44..95f0bac5fc 100644 --- a/pkg/helpers/Get-AzureConstants.py +++ b/pkg/helpers/Get-AzureConstants.py @@ -1,5 +1,8 @@ #!/usr/bin/python +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + import json import subprocess from time import gmtime, strftime diff --git a/scripts/azure-const.sh b/scripts/azure-const.sh index 478a5b0241..f03d6952f8 100755 --- a/scripts/azure-const.sh +++ b/scripts/azure-const.sh @@ -1,4 +1,8 @@ #!/bin/bash + +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + if [ -z "$CLIENT_ID" ]; then echo "must provide a CLIENT_ID env var" exit 1; diff --git a/scripts/build-windows-k8s.sh b/scripts/build-windows-k8s.sh index da2b4345ab..a01f0e2b9a 100755 --- a/scripts/build-windows-k8s.sh +++ b/scripts/build-windows-k8s.sh @@ -1,4 +1,8 @@ #!/bin/bash + +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + set -eo pipefail fetch_k8s() { diff --git a/scripts/convert-lcg-lcl.sh b/scripts/convert-lcg-lcl.sh index b241cdde8f..f6d13a4f83 100644 --- a/scripts/convert-lcg-lcl.sh +++ b/scripts/convert-lcg-lcl.sh @@ -1,5 +1,8 @@ #!/usr/bin/env bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + # DON'T RUN. This script requires PythonLocalizerTool which is not published yet. # TODO: make PythonLocalizerTool public set -eo pipefail diff --git a/scripts/devenv.sh b/scripts/devenv.sh index b5c2066dcb..231b66e26e 100755 --- a/scripts/devenv.sh +++ b/scripts/devenv.sh @@ -1,5 +1,8 @@ #!/usr/bin/env bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + set -eu -o pipefail set -x diff --git a/scripts/update-enus-po.sh b/scripts/update-enus-po.sh index fe0c287441..adfbc48fdb 100644 --- a/scripts/update-enus-po.sh +++ b/scripts/update-enus-po.sh @@ -1,5 +1,8 @@ #!/bin/bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + scripts/update-translation.sh -l en_US -p mv aksengine.po translations/en_US/LC_MESSAGES/aksengine.po diff --git a/scripts/update-translation.sh b/scripts/update-translation.sh index 5892ad2564..f52e3d4d02 100755 --- a/scripts/update-translation.sh +++ b/scripts/update-translation.sh @@ -1,5 +1,8 @@ #!/bin/bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + GO_SOURCE="pkg/engine/*.go pkg/engine/transform/*.go pkg/api/*.go pkg/operations/*.go pkg/operations/kubernetesupgrade/*.go" LANGUAGE="en_US" DOMAIN="aksengine" diff --git a/scripts/validate-dependencies.sh b/scripts/validate-dependencies.sh index e18b2fa311..f6e4ed8a45 100755 --- a/scripts/validate-dependencies.sh +++ b/scripts/validate-dependencies.sh @@ -1,5 +1,8 @@ #!/usr/bin/env bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + exit_code=0 echo "==> Running dep check <==" diff --git a/scripts/validate-generated.sh b/scripts/validate-generated.sh index 84f8654a7c..860030f243 100755 --- a/scripts/validate-generated.sh +++ b/scripts/validate-generated.sh @@ -1,5 +1,8 @@ #!/usr/bin/env bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + # TODO: does this script need refactoring post-OpenShift, or can it be deleted? echo "No generated files to check!" exit 0 diff --git a/test/cluster-tests/kubernetes/k8s-utils.sh b/test/cluster-tests/kubernetes/k8s-utils.sh index 57b78843b9..b235683d26 100644 --- a/test/cluster-tests/kubernetes/k8s-utils.sh +++ b/test/cluster-tests/kubernetes/k8s-utils.sh @@ -1,3 +1,6 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + function test_linux_deployment() { ###### Testing an nginx deployment log "Testing deployments" diff --git a/test/cluster-tests/kubernetes/test.sh b/test/cluster-tests/kubernetes/test.sh index 8513a0f68f..69cba81d08 100755 --- a/test/cluster-tests/kubernetes/test.sh +++ b/test/cluster-tests/kubernetes/test.sh @@ -1,5 +1,8 @@ #!/bin/bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + #################################################### SOURCE="${BASH_SOURCE[0]}" while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink diff --git a/test/cluster-tests/utils.sh b/test/cluster-tests/utils.sh index e1c265db6a..267bc9ac4c 100644 --- a/test/cluster-tests/utils.sh +++ b/test/cluster-tests/utils.sh @@ -1,3 +1,5 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. function log { local message="$1" diff --git a/test/common.sh b/test/common.sh index 92bd2616b6..1b2dfeab05 100755 --- a/test/common.sh +++ b/test/common.sh @@ -1,5 +1,8 @@ #!/bin/bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + #################################################### SOURCE="${BASH_SOURCE[0]}" while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink diff --git a/test/deploy.sh b/test/deploy.sh index 5d7731f12b..558a0ba98e 100755 --- a/test/deploy.sh +++ b/test/deploy.sh @@ -1,5 +1,8 @@ #!/usr/bin/env bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + SOURCE="${BASH_SOURCE[0]}" while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" diff --git a/test/e2e.sh b/test/e2e.sh index 134a673e2b..c38fb85f02 100755 --- a/test/e2e.sh +++ b/test/e2e.sh @@ -1,5 +1,8 @@ #!/bin/bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + SOURCE="${BASH_SOURCE[0]}" while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" diff --git a/test/e2e/cleanup.sh b/test/e2e/cleanup.sh index d311229caa..32b2455433 100755 --- a/test/e2e/cleanup.sh +++ b/test/e2e/cleanup.sh @@ -1,5 +1,8 @@ #!/bin/bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + #################################################### if [ -z "$SERVICE_PRINCIPAL_CLIENT_ID" ]; then diff --git a/test/shunit/deploy_template.sh b/test/shunit/deploy_template.sh index 10c66d2362..d7f84ec23c 100755 --- a/test/shunit/deploy_template.sh +++ b/test/shunit/deploy_template.sh @@ -1,5 +1,8 @@ #!/usr/bin/env bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + source "${HOME}/test/common.sh" function shunittest_deploy_template { diff --git a/test/shunit/generate_template.sh b/test/shunit/generate_template.sh index 28bd3b090c..a662b9dac1 100644 --- a/test/shunit/generate_template.sh +++ b/test/shunit/generate_template.sh @@ -1,5 +1,8 @@ #!/usr/bin/env bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + source "${HOME}/test/common.sh" function shunittest_generate_template { diff --git a/test/shunit/scale_agent_pool.sh b/test/shunit/scale_agent_pool.sh index 76f9007749..bdfe072ad3 100755 --- a/test/shunit/scale_agent_pool.sh +++ b/test/shunit/scale_agent_pool.sh @@ -1,5 +1,8 @@ #!/usr/bin/env bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + source "${HOME}/test/common.sh" function shunittest_scale_agent_pool { diff --git a/test/shunit/validate_deployment.sh b/test/shunit/validate_deployment.sh index 1dc6c786ea..9cd63ed9dc 100755 --- a/test/shunit/validate_deployment.sh +++ b/test/shunit/validate_deployment.sh @@ -1,5 +1,8 @@ #!/usr/bin/env bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + function shunittest_validate_deployment { set -eux -o pipefail diff --git a/test/step.sh b/test/step.sh index 9bd05d1c6a..33eca0e0cc 100755 --- a/test/step.sh +++ b/test/step.sh @@ -1,5 +1,8 @@ #!/usr/bin/env bash +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. + SOURCE="${BASH_SOURCE[0]}" while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" From 1271bf53e40b4e2e8e6b5aace54b9587ddada22e Mon Sep 17 00:00:00 2001 From: Cecile Robert-Michon Date: Thu, 15 Nov 2018 16:18:46 -0800 Subject: [PATCH 06/29] Add Copyright header (#23) --- LICENSE | 2 +- Makefile | 13 ++++++++++++- cmd/cmd_suite_test.go | 3 +++ cmd/deploy.go | 3 +++ cmd/deploy_test.go | 3 +++ cmd/generate.go | 3 +++ cmd/generate_test.go | 3 +++ cmd/orchestrators.go | 3 +++ cmd/orchestrators_test.go | 3 +++ cmd/root.go | 3 +++ cmd/root_test.go | 3 +++ cmd/scale.go | 3 +++ cmd/scale_test.go | 3 +++ cmd/upgrade.go | 3 +++ cmd/upgrade_test.go | 3 +++ cmd/version.go | 3 +++ cmd/version_test.go | 3 +++ main.go | 3 +++ pkg/api/addons.go | 3 +++ pkg/api/agentPoolOnlyApi/v20170831/const.go | 3 +++ pkg/api/agentPoolOnlyApi/v20170831/doc.go | 3 +++ pkg/api/agentPoolOnlyApi/v20170831/merge.go | 3 +++ pkg/api/agentPoolOnlyApi/v20170831/types.go | 3 +++ pkg/api/agentPoolOnlyApi/v20170831/types_test.go | 3 +++ pkg/api/agentPoolOnlyApi/v20170831/validate.go | 3 +++ .../agentPoolOnlyApi/v20180331/apiloader_test.go | 3 +++ pkg/api/agentPoolOnlyApi/v20180331/const.go | 3 +++ pkg/api/agentPoolOnlyApi/v20180331/doc.go | 3 +++ pkg/api/agentPoolOnlyApi/v20180331/errors.go | 3 +++ pkg/api/agentPoolOnlyApi/v20180331/merge.go | 3 +++ pkg/api/agentPoolOnlyApi/v20180331/merge_test.go | 3 +++ pkg/api/agentPoolOnlyApi/v20180331/types.go | 3 +++ pkg/api/agentPoolOnlyApi/v20180331/types_test.go | 3 +++ pkg/api/agentPoolOnlyApi/v20180331/validate.go | 3 +++ pkg/api/agentPoolOnlyApi/v20180331/validate_test.go | 3 +++ pkg/api/agentPoolOnlyApi/vlabs/const.go | 3 +++ pkg/api/agentPoolOnlyApi/vlabs/doc.go | 3 +++ pkg/api/agentPoolOnlyApi/vlabs/types.go | 3 +++ pkg/api/agentPoolOnlyApi/vlabs/types_test.go | 3 +++ pkg/api/agentPoolOnlyApi/vlabs/validate.go | 3 +++ pkg/api/apiloader.go | 3 +++ pkg/api/apiloader_test.go | 3 +++ pkg/api/azenvtypes.go | 3 +++ pkg/api/common/const.go | 3 +++ pkg/api/common/helper.go | 3 +++ pkg/api/common/helper_test.go | 3 +++ pkg/api/common/net.go | 3 +++ pkg/api/common/net_test.go | 3 +++ pkg/api/common/versions.go | 3 +++ pkg/api/common/versions_test.go | 3 +++ pkg/api/const.go | 3 +++ pkg/api/converterfromagentpoolonlyapi.go | 3 +++ pkg/api/converterfromagentpoolonlyapi_test.go | 3 +++ pkg/api/converterfromapi.go | 3 +++ pkg/api/convertertoagentpoolonlyapi.go | 3 +++ pkg/api/convertertoagentpoolonlyapi_test.go | 3 +++ pkg/api/convertertoapi.go | 3 +++ pkg/api/convertertoapi_test.go | 3 +++ pkg/api/defaults-apiserver.go | 3 +++ pkg/api/defaults-apiserver_test.go | 3 +++ pkg/api/defaults-cloud-controller-manager.go | 3 +++ pkg/api/defaults-controller-manager.go | 3 +++ pkg/api/defaults-controller-manager_test.go | 3 +++ pkg/api/defaults-kubelet.go | 3 +++ pkg/api/defaults-kubelet_test.go | 3 +++ pkg/api/defaults-scheduler.go | 3 +++ pkg/api/defaults-scheduler_test.go | 3 +++ pkg/api/defaults.go | 3 +++ pkg/api/defaults_test.go | 3 +++ pkg/api/doc.go | 3 +++ pkg/api/k8s_versions.go | 3 +++ pkg/api/k8s_versions_test.go | 3 +++ pkg/api/mocks.go | 3 +++ pkg/api/orchestrators.go | 3 +++ pkg/api/orchestrators_test.go | 3 +++ pkg/api/strictjson.go | 3 +++ pkg/api/strictjson_test.go | 3 +++ pkg/api/types.go | 3 +++ pkg/api/types_test.go | 3 +++ pkg/api/v20160930/const.go | 3 +++ pkg/api/v20160930/doc.go | 3 +++ pkg/api/v20160930/merge.go | 3 +++ pkg/api/v20160930/merge_test.go | 3 +++ pkg/api/v20160930/types.go | 3 +++ pkg/api/v20160930/types_test.go | 3 +++ pkg/api/v20160930/validate.go | 3 +++ pkg/api/v20170131/const.go | 3 +++ pkg/api/v20170131/doc.go | 3 +++ pkg/api/v20170131/merge.go | 3 +++ pkg/api/v20170131/merge_test.go | 3 +++ pkg/api/v20170131/types.go | 3 +++ pkg/api/v20170131/types_test.go | 3 +++ pkg/api/v20170131/validate.go | 3 +++ pkg/api/v20170131/validate_test.go | 3 +++ pkg/api/v20170701/const.go | 3 +++ pkg/api/v20170701/doc.go | 3 +++ pkg/api/v20170701/merge.go | 3 +++ pkg/api/v20170701/merge_test.go | 3 +++ pkg/api/v20170701/types.go | 3 +++ pkg/api/v20170701/types_test.go | 3 +++ pkg/api/v20170701/validate.go | 3 +++ pkg/api/v20170701/validate_test.go | 3 +++ pkg/api/v20170930/const.go | 3 +++ pkg/api/v20170930/types.go | 3 +++ pkg/api/v20170930/validate.go | 3 +++ pkg/api/vlabs/const.go | 3 +++ pkg/api/vlabs/doc.go | 3 +++ pkg/api/vlabs/merge.go | 3 +++ pkg/api/vlabs/merge_test.go | 3 +++ pkg/api/vlabs/orchestratorversiontypes.go | 3 +++ pkg/api/vlabs/types.go | 3 +++ pkg/api/vlabs/types_test.go | 3 +++ pkg/api/vlabs/validate.go | 3 +++ pkg/api/vlabs/validate_test.go | 3 +++ pkg/armhelpers/azureclient.go | 3 +++ pkg/armhelpers/azureclient_test.go | 3 +++ pkg/armhelpers/compute.go | 3 +++ pkg/armhelpers/const.go | 3 +++ pkg/armhelpers/deploymentError.go | 3 +++ pkg/armhelpers/deploymentError_test.go | 3 +++ pkg/armhelpers/deploymentOperations.go | 3 +++ pkg/armhelpers/deployments.go | 3 +++ pkg/armhelpers/disk.go | 3 +++ pkg/armhelpers/graph.go | 3 +++ pkg/armhelpers/groupsclient.go | 3 +++ pkg/armhelpers/interfaces.go | 3 +++ pkg/armhelpers/kubeclient.go | 3 +++ pkg/armhelpers/mockclients.go | 3 +++ pkg/armhelpers/msi.go | 3 +++ pkg/armhelpers/network.go | 3 +++ pkg/armhelpers/providers.go | 3 +++ pkg/armhelpers/storage.go | 3 +++ pkg/armhelpers/storage_test.go | 3 +++ pkg/armhelpers/utils/util.go | 3 +++ pkg/armhelpers/utils/util_test.go | 3 +++ pkg/engine/artifacts.go | 3 +++ pkg/engine/const.go | 3 +++ pkg/engine/customfiles.go | 3 +++ pkg/engine/customfiles_test.go | 3 +++ pkg/engine/doc.go | 3 +++ pkg/engine/engine.go | 3 +++ pkg/engine/engine_test.go | 3 +++ pkg/engine/fileloader.go | 3 +++ pkg/engine/output.go | 3 +++ pkg/engine/output_test.go | 3 +++ pkg/engine/params.go | 3 +++ pkg/engine/params_k8s.go | 3 +++ pkg/engine/params_k8s_test.go | 3 +++ pkg/engine/params_test.go | 3 +++ pkg/engine/template_generator.go | 3 +++ pkg/engine/tenantid.go | 3 +++ pkg/engine/tenantid_test.go | 3 +++ pkg/engine/transform/apimodel_merger.go | 3 +++ pkg/engine/transform/apimodel_merger_test.go | 3 +++ pkg/engine/transform/json.go | 3 +++ pkg/engine/transform/transform.go | 3 +++ pkg/engine/transform/transform_test.go | 3 +++ pkg/engine/types.go | 3 +++ pkg/helpers/azureconst.go | 3 +++ pkg/helpers/filesaver.go | 3 +++ pkg/helpers/helpers.go | 3 +++ pkg/helpers/helpers_test.go | 3 +++ pkg/helpers/pki.go | 3 +++ pkg/helpers/pki_test.go | 3 +++ pkg/i18n/const.go | 3 +++ pkg/i18n/i18n.go | 3 +++ pkg/i18n/i18n_test.go | 3 +++ pkg/i18n/resourceloader.go | 3 +++ pkg/operations/cordondrainvm.go | 3 +++ pkg/operations/cordondrainvm_test.go | 3 +++ pkg/operations/deletevm.go | 3 +++ .../kubernetesupgrade/upgradeagentnode.go | 3 +++ pkg/operations/kubernetesupgrade/upgradecluster.go | 3 +++ .../kubernetesupgrade/upgradecluster_test.go | 3 +++ .../kubernetesupgrade/upgrademasternode.go | 3 +++ pkg/operations/kubernetesupgrade/upgrader.go | 3 +++ pkg/operations/kubernetesupgrade/upgradeworkflow.go | 3 +++ pkg/operations/kubernetesupgrade/v16upgrader.go | 3 +++ pkg/operations/kubernetesupgrade/v17upgrader.go | 3 +++ pkg/operations/kubernetesupgrade/v18upgrader.go | 3 +++ pkg/operations/remote_ssh.go | 3 +++ pkg/operations/scaledownagentpool.go | 3 +++ pkg/operations/scaledownagentpool_test.go | 3 +++ pkg/test/util.go | 3 +++ scripts/copyright-header.sh | 9 +++++++++ scripts/copyright.txt | 3 +++ scripts/validate-copyright-header.sh | 10 ++++++++++ test/aks-engine-test/config/config.go | 3 +++ test/aks-engine-test/config/config_test.go | 3 +++ test/aks-engine-test/main.go | 3 +++ test/aks-engine-test/metrics/metrics.go | 3 +++ test/aks-engine-test/metrics/metrics_test.go | 3 +++ test/aks-engine-test/promote/promote.go | 3 +++ test/aks-engine-test/report/report.go | 3 +++ test/aks-engine-test/report/report_test.go | 3 +++ test/e2e/azure/cli.go | 3 +++ test/e2e/azure/cli_test.go | 3 +++ test/e2e/config/config.go | 3 +++ test/e2e/config/config_test.go | 3 +++ test/e2e/engine/cli.go | 3 +++ test/e2e/engine/template.go | 3 +++ test/e2e/kubernetes/config.go | 3 +++ test/e2e/kubernetes/deployment/deployment.go | 3 +++ test/e2e/kubernetes/hpa/hpa.go | 3 +++ test/e2e/kubernetes/job/job.go | 3 +++ test/e2e/kubernetes/kubernetes_suite_test.go | 3 +++ test/e2e/kubernetes/kubernetes_test.go | 3 +++ test/e2e/kubernetes/namespace/namespace.go | 3 +++ test/e2e/kubernetes/networkpolicy/networkpolicy.go | 3 +++ test/e2e/kubernetes/node/node.go | 3 +++ .../kubernetes/persistentvolume/persistentvolume.go | 3 +++ .../persistentvolumeclaims.go | 3 +++ test/e2e/kubernetes/pod/pod.go | 3 +++ test/e2e/kubernetes/service/service.go | 3 +++ test/e2e/kubernetes/storageclass/storageclass.go | 3 +++ test/e2e/kubernetes/util/util.go | 3 +++ test/e2e/metrics/metrics.go | 3 +++ test/e2e/remote/ssh.go | 3 +++ test/e2e/runner.go | 3 +++ test/e2e/runner/cli_provisioner.go | 3 +++ test/e2e/runner/ginkgo.go | 3 +++ test/i18n/i18ntestinput.go | 3 +++ 222 files changed, 686 insertions(+), 2 deletions(-) create mode 100755 scripts/copyright-header.sh create mode 100644 scripts/copyright.txt create mode 100644 scripts/validate-copyright-header.sh diff --git a/LICENSE b/LICENSE index ad1ad2347c..e571a6e47a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016 Microsoft Azure +Copyright (c) 2018 Microsoft Azure Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile index 376f9fc57c..d7947eeefd 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ DIST_DIRS = find * -type d -exec .NOTPARALLEL: -.PHONY: bootstrap build test test_fmt validate-generated fmt lint ci devenv +.PHONY: bootstrap build test test_fmt validate-generated validate-headers fmt lint ci devenv ifdef DEBUG GOFLAGS := -gcflags="-N -l" @@ -52,6 +52,17 @@ validate-generated: bootstrap validate-dependencies: bootstrap ./scripts/validate-dependencies.sh +.PHONY: validate-headers +validate-headers: + @echo ">> checking license header" + @licRes=$$(for file in $$(find . -type f -iname '*.go' ! -path './vendor/*') ; do \ + awk 'NR<=3' $$file | grep -Eq "(Copyright|generated|GENERATED)" || echo $$file; \ + done); \ + if [ -n "$${licRes}" ]; then \ + echo "license header checking failed:"; echo "$${licRes}"; \ + exit 1; \ + fi + .PHONY: generate generate: bootstrap go generate $(GOFLAGS) -v `go list ./...` diff --git a/cmd/cmd_suite_test.go b/cmd/cmd_suite_test.go index c3e9405372..849a7d8d03 100644 --- a/cmd/cmd_suite_test.go +++ b/cmd/cmd_suite_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package cmd_test import ( diff --git a/cmd/deploy.go b/cmd/deploy.go index ef43974efb..16a3bbbea2 100644 --- a/cmd/deploy.go +++ b/cmd/deploy.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package cmd import ( diff --git a/cmd/deploy_test.go b/cmd/deploy_test.go index 67cbc6faa6..3c1412e735 100644 --- a/cmd/deploy_test.go +++ b/cmd/deploy_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package cmd import ( diff --git a/cmd/generate.go b/cmd/generate.go index ad33977b4a..14244d31bb 100644 --- a/cmd/generate.go +++ b/cmd/generate.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package cmd import ( diff --git a/cmd/generate_test.go b/cmd/generate_test.go index 087384784d..6e02406677 100644 --- a/cmd/generate_test.go +++ b/cmd/generate_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package cmd import ( diff --git a/cmd/orchestrators.go b/cmd/orchestrators.go index fe41f5150f..36ef8c1d27 100644 --- a/cmd/orchestrators.go +++ b/cmd/orchestrators.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package cmd import ( diff --git a/cmd/orchestrators_test.go b/cmd/orchestrators_test.go index 21e0da7c76..6752de1f44 100644 --- a/cmd/orchestrators_test.go +++ b/cmd/orchestrators_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package cmd import ( diff --git a/cmd/root.go b/cmd/root.go index 7881146772..fb994255b5 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package cmd import ( diff --git a/cmd/root_test.go b/cmd/root_test.go index f1186e7c6c..0b60ccc50e 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package cmd import ( diff --git a/cmd/scale.go b/cmd/scale.go index c3f9b1d7b1..2c08ec7e9b 100644 --- a/cmd/scale.go +++ b/cmd/scale.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package cmd import ( diff --git a/cmd/scale_test.go b/cmd/scale_test.go index 2a71977938..5e33006559 100644 --- a/cmd/scale_test.go +++ b/cmd/scale_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package cmd import ( diff --git a/cmd/upgrade.go b/cmd/upgrade.go index e8bd85c9b0..2eb159180a 100644 --- a/cmd/upgrade.go +++ b/cmd/upgrade.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package cmd import ( diff --git a/cmd/upgrade_test.go b/cmd/upgrade_test.go index fdfd6ddb51..5c7e69f635 100644 --- a/cmd/upgrade_test.go +++ b/cmd/upgrade_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package cmd import ( diff --git a/cmd/version.go b/cmd/version.go index 4dc62406fc..0e52aad154 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package cmd import ( diff --git a/cmd/version_test.go b/cmd/version_test.go index 0fb365a2c5..ded35c542a 100644 --- a/cmd/version_test.go +++ b/cmd/version_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package cmd import ( diff --git a/main.go b/main.go index 75d1aa2ee4..efe3d40788 100644 --- a/main.go +++ b/main.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package main import ( diff --git a/pkg/api/addons.go b/pkg/api/addons.go index 3e057fb6ef..5a976b23b4 100644 --- a/pkg/api/addons.go +++ b/pkg/api/addons.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/agentPoolOnlyApi/v20170831/const.go b/pkg/api/agentPoolOnlyApi/v20170831/const.go index 91ade9fec2..4d11dea870 100644 --- a/pkg/api/agentPoolOnlyApi/v20170831/const.go +++ b/pkg/api/agentPoolOnlyApi/v20170831/const.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170831 const ( diff --git a/pkg/api/agentPoolOnlyApi/v20170831/doc.go b/pkg/api/agentPoolOnlyApi/v20170831/doc.go index 972517e451..3a786d4d27 100644 --- a/pkg/api/agentPoolOnlyApi/v20170831/doc.go +++ b/pkg/api/agentPoolOnlyApi/v20170831/doc.go @@ -1,2 +1,5 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + // Package v20170831 stores api model for version "2017-08-31" package v20170831 diff --git a/pkg/api/agentPoolOnlyApi/v20170831/merge.go b/pkg/api/agentPoolOnlyApi/v20170831/merge.go index 7f3619f990..e205d1d06d 100644 --- a/pkg/api/agentPoolOnlyApi/v20170831/merge.go +++ b/pkg/api/agentPoolOnlyApi/v20170831/merge.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170831 import ( diff --git a/pkg/api/agentPoolOnlyApi/v20170831/types.go b/pkg/api/agentPoolOnlyApi/v20170831/types.go index aa6d1d48de..d4aed981e9 100644 --- a/pkg/api/agentPoolOnlyApi/v20170831/types.go +++ b/pkg/api/agentPoolOnlyApi/v20170831/types.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170831 import "encoding/json" diff --git a/pkg/api/agentPoolOnlyApi/v20170831/types_test.go b/pkg/api/agentPoolOnlyApi/v20170831/types_test.go index 9a982adfe8..663602dde7 100644 --- a/pkg/api/agentPoolOnlyApi/v20170831/types_test.go +++ b/pkg/api/agentPoolOnlyApi/v20170831/types_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170831 import ( diff --git a/pkg/api/agentPoolOnlyApi/v20170831/validate.go b/pkg/api/agentPoolOnlyApi/v20170831/validate.go index 86d5c80f19..f94bf28fe3 100644 --- a/pkg/api/agentPoolOnlyApi/v20170831/validate.go +++ b/pkg/api/agentPoolOnlyApi/v20170831/validate.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170831 import ( diff --git a/pkg/api/agentPoolOnlyApi/v20180331/apiloader_test.go b/pkg/api/agentPoolOnlyApi/v20180331/apiloader_test.go index 555297ba90..79428f64e0 100644 --- a/pkg/api/agentPoolOnlyApi/v20180331/apiloader_test.go +++ b/pkg/api/agentPoolOnlyApi/v20180331/apiloader_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20180331_test import ( diff --git a/pkg/api/agentPoolOnlyApi/v20180331/const.go b/pkg/api/agentPoolOnlyApi/v20180331/const.go index 7ac69c8f06..636ce2a11d 100644 --- a/pkg/api/agentPoolOnlyApi/v20180331/const.go +++ b/pkg/api/agentPoolOnlyApi/v20180331/const.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20180331 const ( diff --git a/pkg/api/agentPoolOnlyApi/v20180331/doc.go b/pkg/api/agentPoolOnlyApi/v20180331/doc.go index 50fc1ab8da..65d46ebd64 100644 --- a/pkg/api/agentPoolOnlyApi/v20180331/doc.go +++ b/pkg/api/agentPoolOnlyApi/v20180331/doc.go @@ -1,2 +1,5 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + // Package v20180331 stores api model for version "2018-03-31" package v20180331 diff --git a/pkg/api/agentPoolOnlyApi/v20180331/errors.go b/pkg/api/agentPoolOnlyApi/v20180331/errors.go index b5eca1726c..5691e35a5f 100644 --- a/pkg/api/agentPoolOnlyApi/v20180331/errors.go +++ b/pkg/api/agentPoolOnlyApi/v20180331/errors.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20180331 import "github.com/pkg/errors" diff --git a/pkg/api/agentPoolOnlyApi/v20180331/merge.go b/pkg/api/agentPoolOnlyApi/v20180331/merge.go index f467119e33..53df6f1bc9 100644 --- a/pkg/api/agentPoolOnlyApi/v20180331/merge.go +++ b/pkg/api/agentPoolOnlyApi/v20180331/merge.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20180331 import ( diff --git a/pkg/api/agentPoolOnlyApi/v20180331/merge_test.go b/pkg/api/agentPoolOnlyApi/v20180331/merge_test.go index c45dc8a3bd..a81014cca2 100644 --- a/pkg/api/agentPoolOnlyApi/v20180331/merge_test.go +++ b/pkg/api/agentPoolOnlyApi/v20180331/merge_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20180331 import ( diff --git a/pkg/api/agentPoolOnlyApi/v20180331/types.go b/pkg/api/agentPoolOnlyApi/v20180331/types.go index 44ee202d29..0a7c178db4 100644 --- a/pkg/api/agentPoolOnlyApi/v20180331/types.go +++ b/pkg/api/agentPoolOnlyApi/v20180331/types.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20180331 import "encoding/json" diff --git a/pkg/api/agentPoolOnlyApi/v20180331/types_test.go b/pkg/api/agentPoolOnlyApi/v20180331/types_test.go index 95d415e6b1..fc4848da20 100644 --- a/pkg/api/agentPoolOnlyApi/v20180331/types_test.go +++ b/pkg/api/agentPoolOnlyApi/v20180331/types_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20180331 import ( diff --git a/pkg/api/agentPoolOnlyApi/v20180331/validate.go b/pkg/api/agentPoolOnlyApi/v20180331/validate.go index d0a4872a68..9e2be014a3 100644 --- a/pkg/api/agentPoolOnlyApi/v20180331/validate.go +++ b/pkg/api/agentPoolOnlyApi/v20180331/validate.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20180331 import ( diff --git a/pkg/api/agentPoolOnlyApi/v20180331/validate_test.go b/pkg/api/agentPoolOnlyApi/v20180331/validate_test.go index dde7e72e22..29cef98aa0 100644 --- a/pkg/api/agentPoolOnlyApi/v20180331/validate_test.go +++ b/pkg/api/agentPoolOnlyApi/v20180331/validate_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20180331 import ( diff --git a/pkg/api/agentPoolOnlyApi/vlabs/const.go b/pkg/api/agentPoolOnlyApi/vlabs/const.go index 6df12b1756..878c35a8d7 100644 --- a/pkg/api/agentPoolOnlyApi/vlabs/const.go +++ b/pkg/api/agentPoolOnlyApi/vlabs/const.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package vlabs const ( diff --git a/pkg/api/agentPoolOnlyApi/vlabs/doc.go b/pkg/api/agentPoolOnlyApi/vlabs/doc.go index 1f8ea61f6e..03d1f95f61 100644 --- a/pkg/api/agentPoolOnlyApi/vlabs/doc.go +++ b/pkg/api/agentPoolOnlyApi/vlabs/doc.go @@ -1,2 +1,5 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + // Package vlabs stores api model for version "2017-08-31" package vlabs diff --git a/pkg/api/agentPoolOnlyApi/vlabs/types.go b/pkg/api/agentPoolOnlyApi/vlabs/types.go index 1ea8216ea5..61e4aa975f 100644 --- a/pkg/api/agentPoolOnlyApi/vlabs/types.go +++ b/pkg/api/agentPoolOnlyApi/vlabs/types.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package vlabs import "encoding/json" diff --git a/pkg/api/agentPoolOnlyApi/vlabs/types_test.go b/pkg/api/agentPoolOnlyApi/vlabs/types_test.go index 0cedb47129..61eb7a9ff1 100644 --- a/pkg/api/agentPoolOnlyApi/vlabs/types_test.go +++ b/pkg/api/agentPoolOnlyApi/vlabs/types_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package vlabs import ( diff --git a/pkg/api/agentPoolOnlyApi/vlabs/validate.go b/pkg/api/agentPoolOnlyApi/vlabs/validate.go index 9b78150a75..547ec6af0f 100644 --- a/pkg/api/agentPoolOnlyApi/vlabs/validate.go +++ b/pkg/api/agentPoolOnlyApi/vlabs/validate.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package vlabs import ( diff --git a/pkg/api/apiloader.go b/pkg/api/apiloader.go index 57a517ac7d..eabeefb27b 100644 --- a/pkg/api/apiloader.go +++ b/pkg/api/apiloader.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/apiloader_test.go b/pkg/api/apiloader_test.go index 80125cbddb..0848fc22e5 100644 --- a/pkg/api/apiloader_test.go +++ b/pkg/api/apiloader_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/azenvtypes.go b/pkg/api/azenvtypes.go index 50c919ea80..fb84e1ee1b 100644 --- a/pkg/api/azenvtypes.go +++ b/pkg/api/azenvtypes.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api //AzureEnvironmentSpecConfig is the overall configuration differences in different cloud environments. diff --git a/pkg/api/common/const.go b/pkg/api/common/const.go index bd29d33d0b..4cdb642ed7 100644 --- a/pkg/api/common/const.go +++ b/pkg/api/common/const.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package common // the orchestrators supported diff --git a/pkg/api/common/helper.go b/pkg/api/common/helper.go index ebab97de1e..d12cf3362e 100644 --- a/pkg/api/common/helper.go +++ b/pkg/api/common/helper.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package common import ( diff --git a/pkg/api/common/helper_test.go b/pkg/api/common/helper_test.go index 909dc9a9fb..44816f9dd4 100644 --- a/pkg/api/common/helper_test.go +++ b/pkg/api/common/helper_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package common import ( diff --git a/pkg/api/common/net.go b/pkg/api/common/net.go index 0766c9bb67..2f55ecc874 100644 --- a/pkg/api/common/net.go +++ b/pkg/api/common/net.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package common import ( diff --git a/pkg/api/common/net_test.go b/pkg/api/common/net_test.go index 47ae3719c7..261be00366 100644 --- a/pkg/api/common/net_test.go +++ b/pkg/api/common/net_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package common import ( diff --git a/pkg/api/common/versions.go b/pkg/api/common/versions.go index 27432655fe..9afd5439b8 100644 --- a/pkg/api/common/versions.go +++ b/pkg/api/common/versions.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package common import ( diff --git a/pkg/api/common/versions_test.go b/pkg/api/common/versions_test.go index 7d9d178796..47309e8f89 100644 --- a/pkg/api/common/versions_test.go +++ b/pkg/api/common/versions_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package common import ( diff --git a/pkg/api/const.go b/pkg/api/const.go index 84a423b15d..4d989165f1 100644 --- a/pkg/api/const.go +++ b/pkg/api/const.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api // the orchestrators supported by vlabs diff --git a/pkg/api/converterfromagentpoolonlyapi.go b/pkg/api/converterfromagentpoolonlyapi.go index 01a40495f9..563ba6f55c 100644 --- a/pkg/api/converterfromagentpoolonlyapi.go +++ b/pkg/api/converterfromagentpoolonlyapi.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/converterfromagentpoolonlyapi_test.go b/pkg/api/converterfromagentpoolonlyapi_test.go index 2f8c34ce27..15332c32cb 100644 --- a/pkg/api/converterfromagentpoolonlyapi_test.go +++ b/pkg/api/converterfromagentpoolonlyapi_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/converterfromapi.go b/pkg/api/converterfromapi.go index c58cf52729..9158e352cc 100644 --- a/pkg/api/converterfromapi.go +++ b/pkg/api/converterfromapi.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/convertertoagentpoolonlyapi.go b/pkg/api/convertertoagentpoolonlyapi.go index da41c72da9..98e9c64e5c 100644 --- a/pkg/api/convertertoagentpoolonlyapi.go +++ b/pkg/api/convertertoagentpoolonlyapi.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/convertertoagentpoolonlyapi_test.go b/pkg/api/convertertoagentpoolonlyapi_test.go index cb8d6dcdce..2644ce0ada 100644 --- a/pkg/api/convertertoagentpoolonlyapi_test.go +++ b/pkg/api/convertertoagentpoolonlyapi_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/convertertoapi.go b/pkg/api/convertertoapi.go index 84f2f3291a..d19de23a98 100644 --- a/pkg/api/convertertoapi.go +++ b/pkg/api/convertertoapi.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/convertertoapi_test.go b/pkg/api/convertertoapi_test.go index 5b150fa522..e7cab23cd9 100644 --- a/pkg/api/convertertoapi_test.go +++ b/pkg/api/convertertoapi_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/defaults-apiserver.go b/pkg/api/defaults-apiserver.go index c313f96f88..31a3829f8d 100644 --- a/pkg/api/defaults-apiserver.go +++ b/pkg/api/defaults-apiserver.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/defaults-apiserver_test.go b/pkg/api/defaults-apiserver_test.go index 509e2b8f1a..9337739423 100644 --- a/pkg/api/defaults-apiserver_test.go +++ b/pkg/api/defaults-apiserver_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/defaults-cloud-controller-manager.go b/pkg/api/defaults-cloud-controller-manager.go index ec8fb7094f..c1a149ee9c 100644 --- a/pkg/api/defaults-cloud-controller-manager.go +++ b/pkg/api/defaults-cloud-controller-manager.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/defaults-controller-manager.go b/pkg/api/defaults-controller-manager.go index a306186616..6e8aec5cdf 100644 --- a/pkg/api/defaults-controller-manager.go +++ b/pkg/api/defaults-controller-manager.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/defaults-controller-manager_test.go b/pkg/api/defaults-controller-manager_test.go index 1d98e3823c..c8f343640e 100644 --- a/pkg/api/defaults-controller-manager_test.go +++ b/pkg/api/defaults-controller-manager_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/defaults-kubelet.go b/pkg/api/defaults-kubelet.go index c023778f71..6a9453d94e 100644 --- a/pkg/api/defaults-kubelet.go +++ b/pkg/api/defaults-kubelet.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/defaults-kubelet_test.go b/pkg/api/defaults-kubelet_test.go index 5381b376e1..c257401e98 100644 --- a/pkg/api/defaults-kubelet_test.go +++ b/pkg/api/defaults-kubelet_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/defaults-scheduler.go b/pkg/api/defaults-scheduler.go index 31f3bf5da7..2258d43d54 100644 --- a/pkg/api/defaults-scheduler.go +++ b/pkg/api/defaults-scheduler.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api // staticSchedulerConfig is not user-overridable diff --git a/pkg/api/defaults-scheduler_test.go b/pkg/api/defaults-scheduler_test.go index 576baf4888..2685f79eb9 100644 --- a/pkg/api/defaults-scheduler_test.go +++ b/pkg/api/defaults-scheduler_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/defaults.go b/pkg/api/defaults.go index 0236f72f85..f813877481 100644 --- a/pkg/api/defaults.go +++ b/pkg/api/defaults.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/defaults_test.go b/pkg/api/defaults_test.go index 1e1e803522..638d3fae4b 100644 --- a/pkg/api/defaults_test.go +++ b/pkg/api/defaults_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/doc.go b/pkg/api/doc.go index 1b04c1a03c..77efae7aef 100644 --- a/pkg/api/doc.go +++ b/pkg/api/doc.go @@ -1,2 +1,5 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + // Package api stores an unversion api package api diff --git a/pkg/api/k8s_versions.go b/pkg/api/k8s_versions.go index 2e7c4aac65..61b6022a1a 100644 --- a/pkg/api/k8s_versions.go +++ b/pkg/api/k8s_versions.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/k8s_versions_test.go b/pkg/api/k8s_versions_test.go index a22dd60c10..dd15195112 100644 --- a/pkg/api/k8s_versions_test.go +++ b/pkg/api/k8s_versions_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/mocks.go b/pkg/api/mocks.go index 98eb74f0e0..6010473730 100644 --- a/pkg/api/mocks.go +++ b/pkg/api/mocks.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/orchestrators.go b/pkg/api/orchestrators.go index 5c8849de58..09861c38d5 100644 --- a/pkg/api/orchestrators.go +++ b/pkg/api/orchestrators.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/orchestrators_test.go b/pkg/api/orchestrators_test.go index 320a2f91de..2f59b4b6b5 100644 --- a/pkg/api/orchestrators_test.go +++ b/pkg/api/orchestrators_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/strictjson.go b/pkg/api/strictjson.go index a88addcb37..073227dfb8 100644 --- a/pkg/api/strictjson.go +++ b/pkg/api/strictjson.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/strictjson_test.go b/pkg/api/strictjson_test.go index 0b384c927e..f0042cfc40 100644 --- a/pkg/api/strictjson_test.go +++ b/pkg/api/strictjson_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/types.go b/pkg/api/types.go index 112232b891..6ea98a1d84 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/types_test.go b/pkg/api/types_test.go index 3d3d1d6fd5..f664c800fb 100644 --- a/pkg/api/types_test.go +++ b/pkg/api/types_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package api import ( diff --git a/pkg/api/v20160930/const.go b/pkg/api/v20160930/const.go index c8555c9312..af7ad27740 100644 --- a/pkg/api/v20160930/const.go +++ b/pkg/api/v20160930/const.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20160930 const ( diff --git a/pkg/api/v20160930/doc.go b/pkg/api/v20160930/doc.go index e0c5ad3829..77cd6280fb 100644 --- a/pkg/api/v20160930/doc.go +++ b/pkg/api/v20160930/doc.go @@ -1,2 +1,5 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + // Package v20160930 stores api model for version "2016-09-30" package v20160930 diff --git a/pkg/api/v20160930/merge.go b/pkg/api/v20160930/merge.go index e7a394e46d..390fa0c538 100644 --- a/pkg/api/v20160930/merge.go +++ b/pkg/api/v20160930/merge.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20160930 import ( diff --git a/pkg/api/v20160930/merge_test.go b/pkg/api/v20160930/merge_test.go index dd92bd19d4..d4c63cd00f 100644 --- a/pkg/api/v20160930/merge_test.go +++ b/pkg/api/v20160930/merge_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20160930 import "testing" diff --git a/pkg/api/v20160930/types.go b/pkg/api/v20160930/types.go index 2757a9958b..ca99f1b385 100644 --- a/pkg/api/v20160930/types.go +++ b/pkg/api/v20160930/types.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20160930 import ( diff --git a/pkg/api/v20160930/types_test.go b/pkg/api/v20160930/types_test.go index 128a8999bd..7eb61117cc 100644 --- a/pkg/api/v20160930/types_test.go +++ b/pkg/api/v20160930/types_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20160930 import ( diff --git a/pkg/api/v20160930/validate.go b/pkg/api/v20160930/validate.go index e4b8a8e825..0cf116938f 100644 --- a/pkg/api/v20160930/validate.go +++ b/pkg/api/v20160930/validate.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20160930 import ( diff --git a/pkg/api/v20170131/const.go b/pkg/api/v20170131/const.go index 280ea9424d..3a963f6139 100644 --- a/pkg/api/v20170131/const.go +++ b/pkg/api/v20170131/const.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170131 const ( diff --git a/pkg/api/v20170131/doc.go b/pkg/api/v20170131/doc.go index d68d426985..12a8779472 100644 --- a/pkg/api/v20170131/doc.go +++ b/pkg/api/v20170131/doc.go @@ -1,2 +1,5 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + // Package v20170131 stores api model for version "2017-01-31" package v20170131 diff --git a/pkg/api/v20170131/merge.go b/pkg/api/v20170131/merge.go index 4b9d15c9ac..4f9daad4cf 100644 --- a/pkg/api/v20170131/merge.go +++ b/pkg/api/v20170131/merge.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170131 import ( diff --git a/pkg/api/v20170131/merge_test.go b/pkg/api/v20170131/merge_test.go index aaad511202..8280c91992 100644 --- a/pkg/api/v20170131/merge_test.go +++ b/pkg/api/v20170131/merge_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170131 import "testing" diff --git a/pkg/api/v20170131/types.go b/pkg/api/v20170131/types.go index 9d146a23cb..3eaef54326 100644 --- a/pkg/api/v20170131/types.go +++ b/pkg/api/v20170131/types.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170131 import ( diff --git a/pkg/api/v20170131/types_test.go b/pkg/api/v20170131/types_test.go index f8a49a3aa8..c873072495 100644 --- a/pkg/api/v20170131/types_test.go +++ b/pkg/api/v20170131/types_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170131 import ( diff --git a/pkg/api/v20170131/validate.go b/pkg/api/v20170131/validate.go index ec8f78ada3..24f8c68a70 100644 --- a/pkg/api/v20170131/validate.go +++ b/pkg/api/v20170131/validate.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170131 import ( diff --git a/pkg/api/v20170131/validate_test.go b/pkg/api/v20170131/validate_test.go index 445eccb6ef..71ee9cd414 100644 --- a/pkg/api/v20170131/validate_test.go +++ b/pkg/api/v20170131/validate_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170131 import "testing" diff --git a/pkg/api/v20170701/const.go b/pkg/api/v20170701/const.go index f8615d8885..d7251504aa 100644 --- a/pkg/api/v20170701/const.go +++ b/pkg/api/v20170701/const.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170701 const ( diff --git a/pkg/api/v20170701/doc.go b/pkg/api/v20170701/doc.go index 612735edfc..79dd2a300f 100644 --- a/pkg/api/v20170701/doc.go +++ b/pkg/api/v20170701/doc.go @@ -1,2 +1,5 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + // Package v20170701 stores api model for version "2017-07-01" package v20170701 diff --git a/pkg/api/v20170701/merge.go b/pkg/api/v20170701/merge.go index 1a8d2aeae6..1d6198b748 100644 --- a/pkg/api/v20170701/merge.go +++ b/pkg/api/v20170701/merge.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170701 import ( diff --git a/pkg/api/v20170701/merge_test.go b/pkg/api/v20170701/merge_test.go index 50dbe4badc..777eae27e0 100644 --- a/pkg/api/v20170701/merge_test.go +++ b/pkg/api/v20170701/merge_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170701 import "testing" diff --git a/pkg/api/v20170701/types.go b/pkg/api/v20170701/types.go index cfeceac36d..d39a4771bb 100644 --- a/pkg/api/v20170701/types.go +++ b/pkg/api/v20170701/types.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170701 import ( diff --git a/pkg/api/v20170701/types_test.go b/pkg/api/v20170701/types_test.go index 7c0ed6ef45..864ff0519e 100644 --- a/pkg/api/v20170701/types_test.go +++ b/pkg/api/v20170701/types_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170701 import ( diff --git a/pkg/api/v20170701/validate.go b/pkg/api/v20170701/validate.go index 8fc2dc2ec2..5307fd9a50 100644 --- a/pkg/api/v20170701/validate.go +++ b/pkg/api/v20170701/validate.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170701 import ( diff --git a/pkg/api/v20170701/validate_test.go b/pkg/api/v20170701/validate_test.go index 263cd06e28..2ff586e478 100644 --- a/pkg/api/v20170701/validate_test.go +++ b/pkg/api/v20170701/validate_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170701 import "testing" diff --git a/pkg/api/v20170930/const.go b/pkg/api/v20170930/const.go index be2235c45a..96bbf53e36 100644 --- a/pkg/api/v20170930/const.go +++ b/pkg/api/v20170930/const.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170930 const ( diff --git a/pkg/api/v20170930/types.go b/pkg/api/v20170930/types.go index a612b6d8ad..90d4253331 100644 --- a/pkg/api/v20170930/types.go +++ b/pkg/api/v20170930/types.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170930 // OSType represents OS types of agents diff --git a/pkg/api/v20170930/validate.go b/pkg/api/v20170930/validate.go index db7b384cd6..da3f3e41d1 100644 --- a/pkg/api/v20170930/validate.go +++ b/pkg/api/v20170930/validate.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package v20170930 import ( diff --git a/pkg/api/vlabs/const.go b/pkg/api/vlabs/const.go index ed18b35ac9..f896bd453a 100644 --- a/pkg/api/vlabs/const.go +++ b/pkg/api/vlabs/const.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package vlabs const ( diff --git a/pkg/api/vlabs/doc.go b/pkg/api/vlabs/doc.go index 28063c9a29..b78e2d3d6b 100644 --- a/pkg/api/vlabs/doc.go +++ b/pkg/api/vlabs/doc.go @@ -1,2 +1,5 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + // Package vlabs stores an experimental api model for acs package vlabs diff --git a/pkg/api/vlabs/merge.go b/pkg/api/vlabs/merge.go index 35c5cb76b3..f0827330b1 100644 --- a/pkg/api/vlabs/merge.go +++ b/pkg/api/vlabs/merge.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package vlabs import ( diff --git a/pkg/api/vlabs/merge_test.go b/pkg/api/vlabs/merge_test.go index ae5755e397..82f044f243 100644 --- a/pkg/api/vlabs/merge_test.go +++ b/pkg/api/vlabs/merge_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package vlabs import "testing" diff --git a/pkg/api/vlabs/orchestratorversiontypes.go b/pkg/api/vlabs/orchestratorversiontypes.go index 21ba5ac13a..b9187f73bc 100644 --- a/pkg/api/vlabs/orchestratorversiontypes.go +++ b/pkg/api/vlabs/orchestratorversiontypes.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package vlabs // PoolUpgradeProfile contains pool properties: diff --git a/pkg/api/vlabs/types.go b/pkg/api/vlabs/types.go index 0ec480dc84..63ddc0ec39 100644 --- a/pkg/api/vlabs/types.go +++ b/pkg/api/vlabs/types.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package vlabs import ( diff --git a/pkg/api/vlabs/types_test.go b/pkg/api/vlabs/types_test.go index 4b340f347f..c03b87639f 100644 --- a/pkg/api/vlabs/types_test.go +++ b/pkg/api/vlabs/types_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package vlabs import ( diff --git a/pkg/api/vlabs/validate.go b/pkg/api/vlabs/validate.go index e2fc737748..552b2e99c7 100644 --- a/pkg/api/vlabs/validate.go +++ b/pkg/api/vlabs/validate.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package vlabs import ( diff --git a/pkg/api/vlabs/validate_test.go b/pkg/api/vlabs/validate_test.go index 3f26a9f7f3..3b728afb0c 100644 --- a/pkg/api/vlabs/validate_test.go +++ b/pkg/api/vlabs/validate_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package vlabs import ( diff --git a/pkg/armhelpers/azureclient.go b/pkg/armhelpers/azureclient.go index ac353ab770..ca2d2b5a50 100644 --- a/pkg/armhelpers/azureclient.go +++ b/pkg/armhelpers/azureclient.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package armhelpers import ( diff --git a/pkg/armhelpers/azureclient_test.go b/pkg/armhelpers/azureclient_test.go index a514225197..d4f911fc65 100644 --- a/pkg/armhelpers/azureclient_test.go +++ b/pkg/armhelpers/azureclient_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package armhelpers import ( diff --git a/pkg/armhelpers/compute.go b/pkg/armhelpers/compute.go index c6a6931fe0..467897ac12 100644 --- a/pkg/armhelpers/compute.go +++ b/pkg/armhelpers/compute.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package armhelpers import ( diff --git a/pkg/armhelpers/const.go b/pkg/armhelpers/const.go index 5167e4ddf0..971c011a5e 100644 --- a/pkg/armhelpers/const.go +++ b/pkg/armhelpers/const.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package armhelpers import "time" diff --git a/pkg/armhelpers/deploymentError.go b/pkg/armhelpers/deploymentError.go index b188a5d008..ca78edcfa0 100644 --- a/pkg/armhelpers/deploymentError.go +++ b/pkg/armhelpers/deploymentError.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package armhelpers import ( diff --git a/pkg/armhelpers/deploymentError_test.go b/pkg/armhelpers/deploymentError_test.go index 6d574a1f5d..cddf184c17 100644 --- a/pkg/armhelpers/deploymentError_test.go +++ b/pkg/armhelpers/deploymentError_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package armhelpers import ( diff --git a/pkg/armhelpers/deploymentOperations.go b/pkg/armhelpers/deploymentOperations.go index 6104f46e3c..2b01b02629 100644 --- a/pkg/armhelpers/deploymentOperations.go +++ b/pkg/armhelpers/deploymentOperations.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package armhelpers import ( diff --git a/pkg/armhelpers/deployments.go b/pkg/armhelpers/deployments.go index 20df3d2cbf..92f8ac3656 100644 --- a/pkg/armhelpers/deployments.go +++ b/pkg/armhelpers/deployments.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package armhelpers import ( diff --git a/pkg/armhelpers/disk.go b/pkg/armhelpers/disk.go index 181825af47..da8b1d98dc 100644 --- a/pkg/armhelpers/disk.go +++ b/pkg/armhelpers/disk.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package armhelpers import ( diff --git a/pkg/armhelpers/graph.go b/pkg/armhelpers/graph.go index 6998f64425..239e29bab0 100644 --- a/pkg/armhelpers/graph.go +++ b/pkg/armhelpers/graph.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package armhelpers import ( diff --git a/pkg/armhelpers/groupsclient.go b/pkg/armhelpers/groupsclient.go index 20b55ed947..425a30f7b5 100644 --- a/pkg/armhelpers/groupsclient.go +++ b/pkg/armhelpers/groupsclient.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package armhelpers import ( diff --git a/pkg/armhelpers/interfaces.go b/pkg/armhelpers/interfaces.go index ceae143fea..f193d05477 100644 --- a/pkg/armhelpers/interfaces.go +++ b/pkg/armhelpers/interfaces.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package armhelpers import ( diff --git a/pkg/armhelpers/kubeclient.go b/pkg/armhelpers/kubeclient.go index 43652ba6da..50932af2d9 100644 --- a/pkg/armhelpers/kubeclient.go +++ b/pkg/armhelpers/kubeclient.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package armhelpers import ( diff --git a/pkg/armhelpers/mockclients.go b/pkg/armhelpers/mockclients.go index 8873dbdb9d..9e33397264 100644 --- a/pkg/armhelpers/mockclients.go +++ b/pkg/armhelpers/mockclients.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package armhelpers import ( diff --git a/pkg/armhelpers/msi.go b/pkg/armhelpers/msi.go index dce8cbb8ec..f0783d4ba4 100644 --- a/pkg/armhelpers/msi.go +++ b/pkg/armhelpers/msi.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package armhelpers import ( diff --git a/pkg/armhelpers/network.go b/pkg/armhelpers/network.go index 0046380622..aee479c9d7 100644 --- a/pkg/armhelpers/network.go +++ b/pkg/armhelpers/network.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package armhelpers import ( diff --git a/pkg/armhelpers/providers.go b/pkg/armhelpers/providers.go index c59007888f..80e0d199cd 100644 --- a/pkg/armhelpers/providers.go +++ b/pkg/armhelpers/providers.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package armhelpers import ( diff --git a/pkg/armhelpers/storage.go b/pkg/armhelpers/storage.go index 13ce9bb167..ab9dcb0e12 100644 --- a/pkg/armhelpers/storage.go +++ b/pkg/armhelpers/storage.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package armhelpers import ( diff --git a/pkg/armhelpers/storage_test.go b/pkg/armhelpers/storage_test.go index 2b579d3291..310624ad5d 100644 --- a/pkg/armhelpers/storage_test.go +++ b/pkg/armhelpers/storage_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package armhelpers import ( diff --git a/pkg/armhelpers/utils/util.go b/pkg/armhelpers/utils/util.go index 7518641790..430bd804fb 100644 --- a/pkg/armhelpers/utils/util.go +++ b/pkg/armhelpers/utils/util.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package utils import ( diff --git a/pkg/armhelpers/utils/util_test.go b/pkg/armhelpers/utils/util_test.go index bddbc3f96d..315c98a3ca 100644 --- a/pkg/armhelpers/utils/util_test.go +++ b/pkg/armhelpers/utils/util_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package utils import ( diff --git a/pkg/engine/artifacts.go b/pkg/engine/artifacts.go index 1ebe9a01d6..e15f722ebe 100644 --- a/pkg/engine/artifacts.go +++ b/pkg/engine/artifacts.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package engine import ( diff --git a/pkg/engine/const.go b/pkg/engine/const.go index e61cb94db2..52109e6006 100644 --- a/pkg/engine/const.go +++ b/pkg/engine/const.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package engine const ( diff --git a/pkg/engine/customfiles.go b/pkg/engine/customfiles.go index 5e7a3458ec..bb3d8531b8 100644 --- a/pkg/engine/customfiles.go +++ b/pkg/engine/customfiles.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package engine import ( diff --git a/pkg/engine/customfiles_test.go b/pkg/engine/customfiles_test.go index be7e77d8db..62e9c016ec 100644 --- a/pkg/engine/customfiles_test.go +++ b/pkg/engine/customfiles_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package engine import ( diff --git a/pkg/engine/doc.go b/pkg/engine/doc.go index e3125175ad..e3bc7f5bdb 100644 --- a/pkg/engine/doc.go +++ b/pkg/engine/doc.go @@ -1,2 +1,5 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + // Package engine takes an AKS cluster model and generates the corresponding template package engine diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index a90094240a..f47640972f 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package engine import ( diff --git a/pkg/engine/engine_test.go b/pkg/engine/engine_test.go index bb38d5d2b4..1ab0a7d6ff 100644 --- a/pkg/engine/engine_test.go +++ b/pkg/engine/engine_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package engine import ( diff --git a/pkg/engine/fileloader.go b/pkg/engine/fileloader.go index 6c6f8bb7fb..b863fc1474 100644 --- a/pkg/engine/fileloader.go +++ b/pkg/engine/fileloader.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package engine //go:generate go-bindata -nometadata -pkg $GOPACKAGE -prefix ../../parts/ -o templates.go ../../parts/... diff --git a/pkg/engine/output.go b/pkg/engine/output.go index 4a3b4d51a6..3e458e383a 100644 --- a/pkg/engine/output.go +++ b/pkg/engine/output.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package engine import ( diff --git a/pkg/engine/output_test.go b/pkg/engine/output_test.go index 252fe2c310..ef48c2e5a2 100644 --- a/pkg/engine/output_test.go +++ b/pkg/engine/output_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package engine import ( diff --git a/pkg/engine/params.go b/pkg/engine/params.go index 00f996c849..71ae3258e2 100644 --- a/pkg/engine/params.go +++ b/pkg/engine/params.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package engine import ( diff --git a/pkg/engine/params_k8s.go b/pkg/engine/params_k8s.go index d6ebc4a604..fec03212db 100644 --- a/pkg/engine/params_k8s.go +++ b/pkg/engine/params_k8s.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package engine import ( diff --git a/pkg/engine/params_k8s_test.go b/pkg/engine/params_k8s_test.go index 03b0b0a70c..e7b23ac3cf 100644 --- a/pkg/engine/params_k8s_test.go +++ b/pkg/engine/params_k8s_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package engine import ( diff --git a/pkg/engine/params_test.go b/pkg/engine/params_test.go index e307075133..5a9bc9a0d9 100644 --- a/pkg/engine/params_test.go +++ b/pkg/engine/params_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package engine import ( diff --git a/pkg/engine/template_generator.go b/pkg/engine/template_generator.go index 8f89bea9d3..f173355ad1 100644 --- a/pkg/engine/template_generator.go +++ b/pkg/engine/template_generator.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package engine import ( diff --git a/pkg/engine/tenantid.go b/pkg/engine/tenantid.go index 38f56873eb..14b0c06224 100644 --- a/pkg/engine/tenantid.go +++ b/pkg/engine/tenantid.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package engine import ( diff --git a/pkg/engine/tenantid_test.go b/pkg/engine/tenantid_test.go index f4a29bee52..f36e5fb64e 100644 --- a/pkg/engine/tenantid_test.go +++ b/pkg/engine/tenantid_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package engine import ( diff --git a/pkg/engine/transform/apimodel_merger.go b/pkg/engine/transform/apimodel_merger.go index a78d46e2a1..a81a00fa04 100644 --- a/pkg/engine/transform/apimodel_merger.go +++ b/pkg/engine/transform/apimodel_merger.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package transform import ( diff --git a/pkg/engine/transform/apimodel_merger_test.go b/pkg/engine/transform/apimodel_merger_test.go index f69c92a63b..d29da5f7c3 100644 --- a/pkg/engine/transform/apimodel_merger_test.go +++ b/pkg/engine/transform/apimodel_merger_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package transform import ( diff --git a/pkg/engine/transform/json.go b/pkg/engine/transform/json.go index d775441527..bdb4424a4d 100644 --- a/pkg/engine/transform/json.go +++ b/pkg/engine/transform/json.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package transform import ( diff --git a/pkg/engine/transform/transform.go b/pkg/engine/transform/transform.go index 71532d8b92..70a1d546a8 100644 --- a/pkg/engine/transform/transform.go +++ b/pkg/engine/transform/transform.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package transform import ( diff --git a/pkg/engine/transform/transform_test.go b/pkg/engine/transform/transform_test.go index 2ccd15ed5f..8852225956 100644 --- a/pkg/engine/transform/transform_test.go +++ b/pkg/engine/transform/transform_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package transform import ( diff --git a/pkg/engine/types.go b/pkg/engine/types.go index 930cafbc7c..73d369f056 100644 --- a/pkg/engine/types.go +++ b/pkg/engine/types.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package engine import ( diff --git a/pkg/helpers/azureconst.go b/pkg/helpers/azureconst.go index b201555bef..f231efa7c8 100644 --- a/pkg/helpers/azureconst.go +++ b/pkg/helpers/azureconst.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package helpers // AUTOGENERATED FILE diff --git a/pkg/helpers/filesaver.go b/pkg/helpers/filesaver.go index 8573a76ade..8c5ae8817f 100644 --- a/pkg/helpers/filesaver.go +++ b/pkg/helpers/filesaver.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package helpers import ( diff --git a/pkg/helpers/helpers.go b/pkg/helpers/helpers.go index 1e35e4ffbc..eea77ecd54 100644 --- a/pkg/helpers/helpers.go +++ b/pkg/helpers/helpers.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package helpers import ( diff --git a/pkg/helpers/helpers_test.go b/pkg/helpers/helpers_test.go index 42cbb18f0b..5a91ace9e6 100644 --- a/pkg/helpers/helpers_test.go +++ b/pkg/helpers/helpers_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package helpers import ( diff --git a/pkg/helpers/pki.go b/pkg/helpers/pki.go index 6cb219d9ae..9485d2b8ff 100644 --- a/pkg/helpers/pki.go +++ b/pkg/helpers/pki.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package helpers import ( diff --git a/pkg/helpers/pki_test.go b/pkg/helpers/pki_test.go index 50ba57d785..d59feb5426 100644 --- a/pkg/helpers/pki_test.go +++ b/pkg/helpers/pki_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package helpers import ( diff --git a/pkg/i18n/const.go b/pkg/i18n/const.go index dd6d6b7500..28e8eb85b7 100644 --- a/pkg/i18n/const.go +++ b/pkg/i18n/const.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package i18n const ( diff --git a/pkg/i18n/i18n.go b/pkg/i18n/i18n.go index f69c5050be..56c919f7a7 100644 --- a/pkg/i18n/i18n.go +++ b/pkg/i18n/i18n.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package i18n import ( diff --git a/pkg/i18n/i18n_test.go b/pkg/i18n/i18n_test.go index d0ee9b553f..47717b94bb 100644 --- a/pkg/i18n/i18n_test.go +++ b/pkg/i18n/i18n_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package i18n import ( diff --git a/pkg/i18n/resourceloader.go b/pkg/i18n/resourceloader.go index 7a2b106a7f..d6b581a59c 100644 --- a/pkg/i18n/resourceloader.go +++ b/pkg/i18n/resourceloader.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package i18n //go:generate go-bindata -nometadata -pkg $GOPACKAGE -prefix ../../ -o translations.go ../../translations/... diff --git a/pkg/operations/cordondrainvm.go b/pkg/operations/cordondrainvm.go index bff35394d0..eedacd6198 100644 --- a/pkg/operations/cordondrainvm.go +++ b/pkg/operations/cordondrainvm.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package operations import ( diff --git a/pkg/operations/cordondrainvm_test.go b/pkg/operations/cordondrainvm_test.go index d9c4ab2a35..d80c8aa8e8 100644 --- a/pkg/operations/cordondrainvm_test.go +++ b/pkg/operations/cordondrainvm_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package operations import ( diff --git a/pkg/operations/deletevm.go b/pkg/operations/deletevm.go index 375a1e9574..0417922868 100644 --- a/pkg/operations/deletevm.go +++ b/pkg/operations/deletevm.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package operations import ( diff --git a/pkg/operations/kubernetesupgrade/upgradeagentnode.go b/pkg/operations/kubernetesupgrade/upgradeagentnode.go index ffabe22c98..f55e9461d1 100644 --- a/pkg/operations/kubernetesupgrade/upgradeagentnode.go +++ b/pkg/operations/kubernetesupgrade/upgradeagentnode.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package kubernetesupgrade import ( diff --git a/pkg/operations/kubernetesupgrade/upgradecluster.go b/pkg/operations/kubernetesupgrade/upgradecluster.go index dc6f959af6..417828d890 100644 --- a/pkg/operations/kubernetesupgrade/upgradecluster.go +++ b/pkg/operations/kubernetesupgrade/upgradecluster.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package kubernetesupgrade import ( diff --git a/pkg/operations/kubernetesupgrade/upgradecluster_test.go b/pkg/operations/kubernetesupgrade/upgradecluster_test.go index fecc08fb4d..cf74a6c304 100644 --- a/pkg/operations/kubernetesupgrade/upgradecluster_test.go +++ b/pkg/operations/kubernetesupgrade/upgradecluster_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package kubernetesupgrade import ( diff --git a/pkg/operations/kubernetesupgrade/upgrademasternode.go b/pkg/operations/kubernetesupgrade/upgrademasternode.go index 8128edc1f5..019c7f1547 100644 --- a/pkg/operations/kubernetesupgrade/upgrademasternode.go +++ b/pkg/operations/kubernetesupgrade/upgrademasternode.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package kubernetesupgrade import ( diff --git a/pkg/operations/kubernetesupgrade/upgrader.go b/pkg/operations/kubernetesupgrade/upgrader.go index e1c1fb2933..c263d9f7c7 100644 --- a/pkg/operations/kubernetesupgrade/upgrader.go +++ b/pkg/operations/kubernetesupgrade/upgrader.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package kubernetesupgrade import ( diff --git a/pkg/operations/kubernetesupgrade/upgradeworkflow.go b/pkg/operations/kubernetesupgrade/upgradeworkflow.go index 6cf5cbdd21..6b81264f27 100644 --- a/pkg/operations/kubernetesupgrade/upgradeworkflow.go +++ b/pkg/operations/kubernetesupgrade/upgradeworkflow.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package kubernetesupgrade import "context" diff --git a/pkg/operations/kubernetesupgrade/v16upgrader.go b/pkg/operations/kubernetesupgrade/v16upgrader.go index 9ee251eb51..dce7764cb8 100644 --- a/pkg/operations/kubernetesupgrade/v16upgrader.go +++ b/pkg/operations/kubernetesupgrade/v16upgrader.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package kubernetesupgrade // Compiler to verify QueueMessageProcessor implements OperationsProcessor diff --git a/pkg/operations/kubernetesupgrade/v17upgrader.go b/pkg/operations/kubernetesupgrade/v17upgrader.go index e7713cfaa8..e99da05d10 100644 --- a/pkg/operations/kubernetesupgrade/v17upgrader.go +++ b/pkg/operations/kubernetesupgrade/v17upgrader.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package kubernetesupgrade // Compiler to verify QueueMessageProcessor implements OperationsProcessor diff --git a/pkg/operations/kubernetesupgrade/v18upgrader.go b/pkg/operations/kubernetesupgrade/v18upgrader.go index 6ce487543b..7158d816b5 100644 --- a/pkg/operations/kubernetesupgrade/v18upgrader.go +++ b/pkg/operations/kubernetesupgrade/v18upgrader.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package kubernetesupgrade // Compiler to verify QueueMessageProcessor implements OperationsProcessor diff --git a/pkg/operations/remote_ssh.go b/pkg/operations/remote_ssh.go index dcded87535..5d09baa8be 100644 --- a/pkg/operations/remote_ssh.go +++ b/pkg/operations/remote_ssh.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package operations import ( diff --git a/pkg/operations/scaledownagentpool.go b/pkg/operations/scaledownagentpool.go index 7fb604c83e..7f7b2d15ca 100644 --- a/pkg/operations/scaledownagentpool.go +++ b/pkg/operations/scaledownagentpool.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package operations import ( diff --git a/pkg/operations/scaledownagentpool_test.go b/pkg/operations/scaledownagentpool_test.go index 10bed38877..e81091b147 100644 --- a/pkg/operations/scaledownagentpool_test.go +++ b/pkg/operations/scaledownagentpool_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package operations import ( diff --git a/pkg/test/util.go b/pkg/test/util.go index aed59b15cd..77085e540b 100644 --- a/pkg/test/util.go +++ b/pkg/test/util.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package test import ( diff --git a/scripts/copyright-header.sh b/scripts/copyright-header.sh new file mode 100755 index 0000000000..f1c61184da --- /dev/null +++ b/scripts/copyright-header.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +for i in $(find .. -type f -iname '*.go' ! -path '../vendor/*') # do not run on the vendor dir +do + if ! grep -q Copyright $i + then + cat copyright.txt $i >$i.new && mv $i.new $i + fi +done diff --git a/scripts/copyright.txt b/scripts/copyright.txt new file mode 100644 index 0000000000..bf2dfde39d --- /dev/null +++ b/scripts/copyright.txt @@ -0,0 +1,3 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + diff --git a/scripts/validate-copyright-header.sh b/scripts/validate-copyright-header.sh new file mode 100644 index 0000000000..010edfea09 --- /dev/null +++ b/scripts/validate-copyright-header.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +@echo ">> checking license header" + @licRes=$$(for file in $$(find . -type f -iname '*.go' ! -path './vendor/*') ; do \ + awk 'NR<=3' $$file | grep -Eq "(Copyright|generated|GENERATED)" || echo $$file; \ + done); \ + if [ -n "$${licRes}" ]; then \ + echo "license header checking failed:"; echo "$${licRes}"; \ + exit 1; \ + fi \ No newline at end of file diff --git a/test/aks-engine-test/config/config.go b/test/aks-engine-test/config/config.go index a31395702a..92bbaf16b4 100644 --- a/test/aks-engine-test/config/config.go +++ b/test/aks-engine-test/config/config.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package config import ( diff --git a/test/aks-engine-test/config/config_test.go b/test/aks-engine-test/config/config_test.go index 143bf4b442..c058606143 100644 --- a/test/aks-engine-test/config/config_test.go +++ b/test/aks-engine-test/config/config_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package config import "testing" diff --git a/test/aks-engine-test/main.go b/test/aks-engine-test/main.go index a5ded7ebe4..26de85533a 100644 --- a/test/aks-engine-test/main.go +++ b/test/aks-engine-test/main.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package main import ( diff --git a/test/aks-engine-test/metrics/metrics.go b/test/aks-engine-test/metrics/metrics.go index 88f6c2eccc..f5e1981ef7 100644 --- a/test/aks-engine-test/metrics/metrics.go +++ b/test/aks-engine-test/metrics/metrics.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package metrics import ( diff --git a/test/aks-engine-test/metrics/metrics_test.go b/test/aks-engine-test/metrics/metrics_test.go index cf38ea75b3..b954705293 100644 --- a/test/aks-engine-test/metrics/metrics_test.go +++ b/test/aks-engine-test/metrics/metrics_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package metrics import ( diff --git a/test/aks-engine-test/promote/promote.go b/test/aks-engine-test/promote/promote.go index 3680caf236..38d8ecf328 100644 --- a/test/aks-engine-test/promote/promote.go +++ b/test/aks-engine-test/promote/promote.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package promote import ( diff --git a/test/aks-engine-test/report/report.go b/test/aks-engine-test/report/report.go index 7985d3207f..4a9ff36e0d 100644 --- a/test/aks-engine-test/report/report.go +++ b/test/aks-engine-test/report/report.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package report import ( diff --git a/test/aks-engine-test/report/report_test.go b/test/aks-engine-test/report/report_test.go index f5a87ab008..848c74173e 100644 --- a/test/aks-engine-test/report/report_test.go +++ b/test/aks-engine-test/report/report_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package report import ( diff --git a/test/e2e/azure/cli.go b/test/e2e/azure/cli.go index 049fb24ea3..810b41d33f 100644 --- a/test/e2e/azure/cli.go +++ b/test/e2e/azure/cli.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package azure import ( diff --git a/test/e2e/azure/cli_test.go b/test/e2e/azure/cli_test.go index c59aa5e383..643c4e78a9 100644 --- a/test/e2e/azure/cli_test.go +++ b/test/e2e/azure/cli_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package azure import ( diff --git a/test/e2e/config/config.go b/test/e2e/config/config.go index 4debaf9c5b..529fd25db4 100644 --- a/test/e2e/config/config.go +++ b/test/e2e/config/config.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package config import ( diff --git a/test/e2e/config/config_test.go b/test/e2e/config/config_test.go index 51ba7ad332..7a470c5143 100644 --- a/test/e2e/config/config_test.go +++ b/test/e2e/config/config_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package config import ( diff --git a/test/e2e/engine/cli.go b/test/e2e/engine/cli.go index 961988d07f..ced05d9c19 100644 --- a/test/e2e/engine/cli.go +++ b/test/e2e/engine/cli.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package engine import ( diff --git a/test/e2e/engine/template.go b/test/e2e/engine/template.go index 3a1355b809..66bca382d2 100644 --- a/test/e2e/engine/template.go +++ b/test/e2e/engine/template.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package engine import ( diff --git a/test/e2e/kubernetes/config.go b/test/e2e/kubernetes/config.go index a67049751f..e85e54c97c 100644 --- a/test/e2e/kubernetes/config.go +++ b/test/e2e/kubernetes/config.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package kubernetes import ( diff --git a/test/e2e/kubernetes/deployment/deployment.go b/test/e2e/kubernetes/deployment/deployment.go index f986af1a4a..a126637dff 100644 --- a/test/e2e/kubernetes/deployment/deployment.go +++ b/test/e2e/kubernetes/deployment/deployment.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package deployment import ( diff --git a/test/e2e/kubernetes/hpa/hpa.go b/test/e2e/kubernetes/hpa/hpa.go index 3e28ca3467..149b1859b1 100644 --- a/test/e2e/kubernetes/hpa/hpa.go +++ b/test/e2e/kubernetes/hpa/hpa.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package hpa import ( diff --git a/test/e2e/kubernetes/job/job.go b/test/e2e/kubernetes/job/job.go index 3331d08d0d..060c515f8b 100644 --- a/test/e2e/kubernetes/job/job.go +++ b/test/e2e/kubernetes/job/job.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package job import ( diff --git a/test/e2e/kubernetes/kubernetes_suite_test.go b/test/e2e/kubernetes/kubernetes_suite_test.go index b7670216ea..0d6bf0c707 100644 --- a/test/e2e/kubernetes/kubernetes_suite_test.go +++ b/test/e2e/kubernetes/kubernetes_suite_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package kubernetes_test import ( diff --git a/test/e2e/kubernetes/kubernetes_test.go b/test/e2e/kubernetes/kubernetes_test.go index c5e3f0a663..29d6b4097c 100644 --- a/test/e2e/kubernetes/kubernetes_test.go +++ b/test/e2e/kubernetes/kubernetes_test.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package kubernetes import ( diff --git a/test/e2e/kubernetes/namespace/namespace.go b/test/e2e/kubernetes/namespace/namespace.go index 686d85f17f..5b3ffe394c 100644 --- a/test/e2e/kubernetes/namespace/namespace.go +++ b/test/e2e/kubernetes/namespace/namespace.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package namespace import ( diff --git a/test/e2e/kubernetes/networkpolicy/networkpolicy.go b/test/e2e/kubernetes/networkpolicy/networkpolicy.go index c25392de26..595c608518 100644 --- a/test/e2e/kubernetes/networkpolicy/networkpolicy.go +++ b/test/e2e/kubernetes/networkpolicy/networkpolicy.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package networkpolicy import ( diff --git a/test/e2e/kubernetes/node/node.go b/test/e2e/kubernetes/node/node.go index e6dd2e6111..d9616dc10c 100644 --- a/test/e2e/kubernetes/node/node.go +++ b/test/e2e/kubernetes/node/node.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package node import ( diff --git a/test/e2e/kubernetes/persistentvolume/persistentvolume.go b/test/e2e/kubernetes/persistentvolume/persistentvolume.go index 24b028e7a0..e507b1c423 100644 --- a/test/e2e/kubernetes/persistentvolume/persistentvolume.go +++ b/test/e2e/kubernetes/persistentvolume/persistentvolume.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package persistentvolume import ( diff --git a/test/e2e/kubernetes/persistentvolumeclaims/persistentvolumeclaims.go b/test/e2e/kubernetes/persistentvolumeclaims/persistentvolumeclaims.go index eea636858a..48db27783f 100644 --- a/test/e2e/kubernetes/persistentvolumeclaims/persistentvolumeclaims.go +++ b/test/e2e/kubernetes/persistentvolumeclaims/persistentvolumeclaims.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package persistentvolumeclaims import ( diff --git a/test/e2e/kubernetes/pod/pod.go b/test/e2e/kubernetes/pod/pod.go index b1e6148aac..27d71f5a79 100644 --- a/test/e2e/kubernetes/pod/pod.go +++ b/test/e2e/kubernetes/pod/pod.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package pod import ( diff --git a/test/e2e/kubernetes/service/service.go b/test/e2e/kubernetes/service/service.go index bd5e1de661..a4259ab3f9 100644 --- a/test/e2e/kubernetes/service/service.go +++ b/test/e2e/kubernetes/service/service.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package service import ( diff --git a/test/e2e/kubernetes/storageclass/storageclass.go b/test/e2e/kubernetes/storageclass/storageclass.go index 24871eca0e..cc2f3ac24e 100644 --- a/test/e2e/kubernetes/storageclass/storageclass.go +++ b/test/e2e/kubernetes/storageclass/storageclass.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package storageclass import ( diff --git a/test/e2e/kubernetes/util/util.go b/test/e2e/kubernetes/util/util.go index 2fe159685a..f3ed1b8673 100644 --- a/test/e2e/kubernetes/util/util.go +++ b/test/e2e/kubernetes/util/util.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package util import ( diff --git a/test/e2e/metrics/metrics.go b/test/e2e/metrics/metrics.go index df667b9e25..4c2b32c725 100644 --- a/test/e2e/metrics/metrics.go +++ b/test/e2e/metrics/metrics.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package metrics import ( diff --git a/test/e2e/remote/ssh.go b/test/e2e/remote/ssh.go index 55cdf86797..e4a79daedb 100644 --- a/test/e2e/remote/ssh.go +++ b/test/e2e/remote/ssh.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package remote import ( diff --git a/test/e2e/runner.go b/test/e2e/runner.go index 8dcc8ac320..c9ab86a2f2 100644 --- a/test/e2e/runner.go +++ b/test/e2e/runner.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package main import ( diff --git a/test/e2e/runner/cli_provisioner.go b/test/e2e/runner/cli_provisioner.go index 14310f09c5..ea85d7e3d5 100644 --- a/test/e2e/runner/cli_provisioner.go +++ b/test/e2e/runner/cli_provisioner.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package runner import ( diff --git a/test/e2e/runner/ginkgo.go b/test/e2e/runner/ginkgo.go index 5399bc47b7..c28cd4daee 100644 --- a/test/e2e/runner/ginkgo.go +++ b/test/e2e/runner/ginkgo.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package runner import ( diff --git a/test/i18n/i18ntestinput.go b/test/i18n/i18ntestinput.go index 7b8272432e..8d67b6b52e 100644 --- a/test/i18n/i18ntestinput.go +++ b/test/i18n/i18ntestinput.go @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + package fake import ( From 6a1fec22741243d4566e7ce82ca9627d251ca5a3 Mon Sep 17 00:00:00 2001 From: Jack Francis Date: Thu, 15 Nov 2018 16:35:29 -0800 Subject: [PATCH 07/29] E2E: eliminate possible nil dereference (#22) --- test/e2e/engine/template.go | 41 ++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/test/e2e/engine/template.go b/test/e2e/engine/template.go index 66bca382d2..2f87017235 100644 --- a/test/e2e/engine/template.go +++ b/test/e2e/engine/template.go @@ -87,44 +87,47 @@ func Build(cfg *config.Config, masterSubnetID string, agentSubnetID string, isVM if err != nil { return nil, err } + prop := cs.ContainerService.Properties if config.ClientID != "" && config.ClientSecret != "" { - cs.ContainerService.Properties.ServicePrincipalProfile = &vlabs.ServicePrincipalProfile{ + prop.ServicePrincipalProfile = &vlabs.ServicePrincipalProfile{ ClientID: config.ClientID, Secret: config.ClientSecret, } } if config.MasterDNSPrefix != "" { - cs.ContainerService.Properties.MasterProfile.DNSPrefix = config.MasterDNSPrefix + prop.MasterProfile.DNSPrefix = config.MasterDNSPrefix } if !cfg.IsKubernetes() && config.AgentDNSPrefix != "" { - for idx, pool := range cs.ContainerService.Properties.AgentPoolProfiles { + for idx, pool := range prop.AgentPoolProfiles { pool.DNSPrefix = fmt.Sprintf("%v-%v", config.AgentDNSPrefix, idx) } } - if config.PublicSSHKey != "" { - cs.ContainerService.Properties.LinuxProfile.SSH.PublicKeys[0].KeyData = config.PublicSSHKey - if cs.ContainerService.Properties.OrchestratorProfile.KubernetesConfig != nil && cs.ContainerService.Properties.OrchestratorProfile.KubernetesConfig.PrivateCluster != nil && cs.ContainerService.Properties.OrchestratorProfile.KubernetesConfig.PrivateCluster.JumpboxProfile != nil { - cs.ContainerService.Properties.OrchestratorProfile.KubernetesConfig.PrivateCluster.JumpboxProfile.PublicKey = config.PublicSSHKey + if prop.LinuxProfile != nil { + if config.PublicSSHKey != "" { + prop.LinuxProfile.SSH.PublicKeys[0].KeyData = config.PublicSSHKey + if prop.OrchestratorProfile.KubernetesConfig != nil && prop.OrchestratorProfile.KubernetesConfig.PrivateCluster != nil && prop.OrchestratorProfile.KubernetesConfig.PrivateCluster.JumpboxProfile != nil { + prop.OrchestratorProfile.KubernetesConfig.PrivateCluster.JumpboxProfile.PublicKey = config.PublicSSHKey + } } } if config.WindowsAdminPasssword != "" { - cs.ContainerService.Properties.WindowsProfile.AdminPassword = config.WindowsAdminPasssword + prop.WindowsProfile.AdminPassword = config.WindowsAdminPasssword } // If the parsed api model input has no expressed version opinion, we check if ENV does have an opinion - if cs.ContainerService.Properties.OrchestratorProfile.OrchestratorRelease == "" && - cs.ContainerService.Properties.OrchestratorProfile.OrchestratorVersion == "" { + if prop.OrchestratorProfile.OrchestratorRelease == "" && + prop.OrchestratorProfile.OrchestratorVersion == "" { // First, prefer the release string if ENV declares it if config.OrchestratorRelease != "" { - cs.ContainerService.Properties.OrchestratorProfile.OrchestratorRelease = config.OrchestratorRelease + prop.OrchestratorProfile.OrchestratorRelease = config.OrchestratorRelease // Or, choose the version string if ENV declares it } else if config.OrchestratorVersion != "" { - cs.ContainerService.Properties.OrchestratorProfile.OrchestratorVersion = config.OrchestratorVersion + prop.OrchestratorProfile.OrchestratorVersion = config.OrchestratorVersion // If ENV similarly has no version opinion, we will rely upon the aks-engine default } else { log.Println("No orchestrator version specified, will use the default.") @@ -133,22 +136,22 @@ func Build(cfg *config.Config, masterSubnetID string, agentSubnetID string, isVM if config.CreateVNET { if isVMSS { - cs.ContainerService.Properties.MasterProfile.VnetSubnetID = masterSubnetID - cs.ContainerService.Properties.MasterProfile.AgentVnetSubnetID = agentSubnetID - for _, p := range cs.ContainerService.Properties.AgentPoolProfiles { + prop.MasterProfile.VnetSubnetID = masterSubnetID + prop.MasterProfile.AgentVnetSubnetID = agentSubnetID + for _, p := range prop.AgentPoolProfiles { p.VnetSubnetID = agentSubnetID } } else { - cs.ContainerService.Properties.MasterProfile.VnetSubnetID = masterSubnetID - for _, p := range cs.ContainerService.Properties.AgentPoolProfiles { + prop.MasterProfile.VnetSubnetID = masterSubnetID + for _, p := range prop.AgentPoolProfiles { p.VnetSubnetID = masterSubnetID } } } if config.EnableKMSEncryption && config.ClientObjectID != "" { - cs.ContainerService.Properties.OrchestratorProfile.KubernetesConfig.EnableEncryptionWithExternalKms = &config.EnableKMSEncryption - cs.ContainerService.Properties.ServicePrincipalProfile.ObjectID = config.ClientObjectID + prop.OrchestratorProfile.KubernetesConfig.EnableEncryptionWithExternalKms = &config.EnableKMSEncryption + prop.ServicePrincipalProfile.ObjectID = config.ClientObjectID } return &Engine{ From dd06fd5752dcebfa6fff4f567379ff841513d7ad Mon Sep 17 00:00:00 2001 From: Tariq Ibrahim Date: Thu, 15 Nov 2018 21:56:38 -0800 Subject: [PATCH 08/29] removing openshift artifacts (#26) --- .circleci/config.yml | 3 - Makefile | 6 +- .../en_US/LC_MESSAGES/acsengine.mo | Bin 2658 -> 0 bytes .../en_US/LC_MESSAGES/acsengine.po | 132 ------------------ scripts/validate-generated.sh | 41 ------ 5 files changed, 1 insertion(+), 181 deletions(-) delete mode 100644 pkg/openshift/translations/en_US/LC_MESSAGES/acsengine.mo delete mode 100644 pkg/openshift/translations/en_US/LC_MESSAGES/acsengine.po delete mode 100755 scripts/validate-generated.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index c365bfbc8b..924dbe6f0d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -24,9 +24,6 @@ jobs: - run: name: Install dependencies command: make bootstrap - - run: - name: Run validation rules - command: make validate-generated - run: name: Run linting rules command: make test-style diff --git a/Makefile b/Makefile index d7947eeefd..97ccda49a3 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ DIST_DIRS = find * -type d -exec .NOTPARALLEL: -.PHONY: bootstrap build test test_fmt validate-generated validate-headers fmt lint ci devenv +.PHONY: bootstrap build test test_fmt validate-headers fmt lint ci devenv ifdef DEBUG GOFLAGS := -gcflags="-N -l" @@ -44,10 +44,6 @@ all: build dev: $(DEV_ENV_CMD_IT) bash -.PHONY: validate-generated -validate-generated: bootstrap - ./scripts/validate-generated.sh - .PHONY: validate-dependencies validate-dependencies: bootstrap ./scripts/validate-dependencies.sh diff --git a/pkg/openshift/translations/en_US/LC_MESSAGES/acsengine.mo b/pkg/openshift/translations/en_US/LC_MESSAGES/acsengine.mo deleted file mode 100644 index 959e81d01cf760c6408660a87d5418ded0a5893d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2658 zcmeH{O^+Kz5QdwOEUftsa6o{l2rWri#@J3^!z_*nW{nnN#ag@(w`e?5p6O)VJ?ZIj z>>xPt7dRquLgH5-A%w)AKp=s{0f{pb2i~3;$1B4D!F5|IKl4#le!Hrse>i>eGlBIq z>^a!Cu;*dvefYup5hU;@a2q^vLWn-t1oy!Ld;|O%?1F!QJ#goKA|J(&HgI|IK{sO)LZk(!gz63st`yTiywA}!m-_ILW{HX^j zoo&$RoP$p1H=xt`C)fl12P>VQfKKNZ;1>8j=yd*Gb91xO`6B3a9)M2g$Dq^s6-eN( zpwqe8sC1qOoz6Z8nc`s>N+hry0jUBq1VY4Pu+y;Rf_u51!tWC>$PiD$9))46;&B*C zSoRGN55XRB7wc=!7;VUK5J?r&M5atz`72aD_HijHhdYUTbGu-(aDG<~1~e(-a$T5^ zbGUBLL|+#wq7Ks4kLixI3E4&FvXWF}6DG^kEDbC-X_T;G$`f6r5owh!Xw1~E(b+EQL*nKmwLV)T?|Y;vhpS+swSKH~8&a&Xz15UsJU)7j8c|ut+PGv~9ctN=}NC@}aV&z_oVakl0VHiqJH&O^*bCpV38Km;=YILX$ z*QQh<)eP^WWeeP_xm2N6b;)TQgtw|T70YLkt;aV}Q=v_mFjNL8Z&_W}okHE~uUHkf z`aUSq7zQ^3JeRo@g+gz1tROL>E5rTk)hLv?#3Goc%MWWkaA>qs;O$3V9ph6F=B#3= zxN*R4zPv#m%gB4Xh;whGeQFG^jl5nt7Fv1lpmsiWTJ0ULwc~YOqgKmrUEFSA!O=V5 znRHXR?st*eJAUT^V&HcbpM^Ivfy(h&x{|&p0~Mp@impm}^XBp{m2V~5PSNsasHc|^ zr{W@r*&A^%^=VJVsmzmmk9}fwZZ;PDao_ak&|NRE%d|9=Gj1+b|S4*&oF diff --git a/pkg/openshift/translations/en_US/LC_MESSAGES/acsengine.po b/pkg/openshift/translations/en_US/LC_MESSAGES/acsengine.po deleted file mode 100644 index 0738007592..0000000000 --- a/pkg/openshift/translations/en_US/LC_MESSAGES/acsengine.po +++ /dev/null @@ -1,132 +0,0 @@ -# English translations for acs-engine package. -# Copyright (C) 2017 -# This file is distributed under the same license as the acs-engine package. -# Jiangtian Li , 2017. -# -msgid "" -msgstr "" -"Project-Id-Version: acsengine\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-07-25 00:04+0000\n" -"PO-Revision-Date: 2017-07-24 17:23-0700\n" -"Last-Translator: Jiangtian Li \n" -"Language-Team: English\n" -"Language: en_US\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 2.0.3\n" - -#: pkg/operations/kubernetesupgrade/upgrader.go:202 -#: pkg/operations/kubernetesupgrade/upgrader.go:217 -#, c-format -msgid "Error generating upgrade template: %s" -msgstr "Error generating upgrade template: %s" - -#: pkg/acsengine/engine.go:251 -#, c-format -msgid "Error reading file %s, Error: %s" -msgstr "Error reading file %s, Error: %s" - -#: pkg/operations/kubernetesupgrade/upgradecluster.go:76 -#, c-format -msgid "Error while querying ARM for resources: %+v" -msgstr "Error while querying ARM for resources: %+v" - -#: pkg/acsengine/transform/transform.go:121 -#: pkg/acsengine/transform/transform.go:129 -#, c-format -msgid "Found 2 resources with type %s in the template. There should only be 1" -msgstr "Found 2 resources with type %s in the template. There should only be 1" - -#: pkg/acsengine/transform/transform.go:158 -#, c-format -msgid "" -"Found no resources with type %s in the template. There should have been 1" -msgstr "" -"Found no resources with type %s in the template. There should have been 1" - -#: pkg/operations/kubernetesupgrade/upgradeagentnode.go:125 -#, c-format -msgid "Node was not ready within %v" -msgstr "Node was not ready within %v" - -#: pkg/api/apiloader.go:205 pkg/api/apiloader.go:210 pkg/api/apiloader.go:225 -#: pkg/api/apiloader.go:230 -#, c-format -msgid "The selected orchestrator version '%s' is not supported" -msgstr "The selected orchestrator version '%s' is not supported" - -#: pkg/operations/kubernetesupgrade/upgrader.go:120 -#, c-format -msgid "Total count of master VMs: %d exceeded expected count: %d" -msgstr "Total count of master VMs: %d exceeded expected count: %d" - -#: pkg/operations/kubernetesupgrade/upgradecluster.go:110 -#, c-format -msgid "Upgrade to Kubernetes version %s is not supported" -msgstr "Upgrade to Kubernetes version %s is not supported" - -#: pkg/acsengine/filesaver.go:26 -#, c-format -msgid "error creating directory '%s': %s" -msgstr "error creating directory '%s': %s" - -#: pkg/acsengine/engine.go:2545 -#, c-format -msgid "error executing template for file %s: %v" -msgstr "error executing template for file %s: %v" - -#: pkg/operations/kubernetesupgrade/upgrader.go:78 -#: pkg/operations/kubernetesupgrade/upgrader.go:391 -#, c-format -msgid "error generating upgrade template: %s" -msgstr "error generating upgrade template: %s" - -#: pkg/acsengine/engine.go:2540 -#, c-format -msgid "error parsing file %s: %v" -msgstr "error parsing file %s: %v" - -#: pkg/api/apiloader.go:32 -#, c-format -msgid "error reading file %s: %s" -msgstr "error reading file %s: %s" - -#: pkg/operations/kubernetesupgrade/upgrader.go:385 -#, c-format -msgid "failed to initialize template generator: %s" -msgstr "failed to initialize template generator: %s" - -#: pkg/api/apiloader.go:342 pkg/api/apiloader.go:369 -#, c-format -msgid "invalid version %s for conversion back from unversioned object" -msgstr "invalid version %s for conversion back from unversioned object" - -#: pkg/acsengine/engine.go:399 -#, c-format -msgid "orchestrator '%s' is unsupported" -msgstr "orchestrator '%s' is unsupported" - -#: pkg/acsengine/engine.go:195 -#, c-format -msgid "template file %s does not exist" -msgstr "template file %s does not exist" - -#: pkg/api/apiloader.go:184 -#, c-format -msgid "unrecognized APIVersion '%s'" -msgstr "unrecognized APIVersion '%s'" - -#: pkg/api/apiloader.go:272 -#, c-format -msgid "" -"unrecognized APIVersion in LoadContainerServiceForAgentPoolOnlyCluster '%s'" -msgstr "" -"unrecognized APIVersion in LoadContainerServiceForAgentPoolOnlyCluster '%s'" - -#: pkg/acsengine/engine.go:2534 -#, c-format -msgid "yaml file %s does not exist" -msgstr "yaml file %s does not exist" diff --git a/scripts/validate-generated.sh b/scripts/validate-generated.sh deleted file mode 100755 index 860030f243..0000000000 --- a/scripts/validate-generated.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT license. - -# TODO: does this script need refactoring post-OpenShift, or can it be deleted? -echo "No generated files to check!" -exit 0 - -#################################################### -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" -#################################################### - -set -x - -T="$(mktemp -d)" -trap "rm -rf ${T}" EXIT - -cp -a "${DIR}/.." "${T}/" - -(cd "${T}/" && go generate ./...) - -GENERATED_FILES=( - "pkg/openshift/certgen/unstable/templates/bindata.go" - "pkg/openshift/certgen/release39/templates/bindata.go" -) - -for file in $GENERATED_FILES; do - if ! diff -r "${DIR}/../${file}" "${T}/${file}" 2>&1 ; then - echo "go generate produced changes that were not already present" - exit 1 - fi -done - -echo "Generated assets have no material difference than what is committed." From 54664d85a6259ede7df628d025b81d84ed89254f Mon Sep 17 00:00:00 2001 From: Jack Francis Date: Fri, 16 Nov 2018 09:18:27 -0800 Subject: [PATCH 09/29] *string needs nil guard (#28) --- pkg/operations/deletevm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/operations/deletevm.go b/pkg/operations/deletevm.go index 0417922868..b3784b3e6a 100644 --- a/pkg/operations/deletevm.go +++ b/pkg/operations/deletevm.go @@ -93,7 +93,7 @@ func CleanDeleteVirtualMachine(az armhelpers.AKSEngineClient, logger *log.Entry, } } - if vm.Identity != nil { + if vm.Identity != nil && vm.Identity.PrincipalID != nil { // Role assignments are not deleted if the VM is destroyed, so we must cleanup ourselves! // The role assignments should only be relevant if managed identities are used, // but always cleaning them up is easier than adding rule based logic here and there. From 1ff44b646cb511ca12ca1c38bd1ed8057aa07446 Mon Sep 17 00:00:00 2001 From: Jack Francis Date: Fri, 16 Nov 2018 10:40:05 -0800 Subject: [PATCH 10/29] E2E: retry node count test (#27) --- test/e2e/kubernetes/kubernetes_test.go | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/test/e2e/kubernetes/kubernetes_test.go b/test/e2e/kubernetes/kubernetes_test.go index 29d6b4097c..347d100987 100644 --- a/test/e2e/kubernetes/kubernetes_test.go +++ b/test/e2e/kubernetes/kubernetes_test.go @@ -143,8 +143,23 @@ var _ = Describe("Azure Container Cluster using the Kubernetes Orchestrator", fu }) It("should have have the appropriate node count", func() { - nodeList, err := node.Get() - Expect(err).NotTo(HaveOccurred()) + var nodeList *node.List + var err error + // Allow ten mins for node count to converge, in the case where we're running this test immediately after a scale operation + for i := 0; i < 60; i++ { + nodeList, err = node.Get() + if err != nil { + log.Printf("Error while getting nodes: %s\n", err) + } + if nodeList != nil && len(nodeList.Nodes) == eng.NodeCount() { + break + } else { + log.Printf("Got %d nodes, expected %d\n", len(nodeList.Nodes), eng.NodeCount()) + } + // Wait a minute before proceeding to create a new job w/ the same name + time.Sleep(10 * time.Second) + } + Expect(nodeList).NotTo(BeNil()) Expect(len(nodeList.Nodes)).To(Equal(eng.NodeCount())) }) From 3b08537f832f19415f8f48ead699ebe554f5f3b2 Mon Sep 17 00:00:00 2001 From: Jack Francis Date: Fri, 16 Nov 2018 11:49:45 -0800 Subject: [PATCH 11/29] accelerated networking rationalization, with tests (#25) --- pkg/api/const.go | 2 ++ pkg/api/defaults.go | 4 +-- pkg/api/defaults_test.go | 68 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/pkg/api/const.go b/pkg/api/const.go index 4d989165f1..add7e35c63 100644 --- a/pkg/api/const.go +++ b/pkg/api/const.go @@ -171,6 +171,8 @@ const ( ARMVirtualNetworksResourceType = "virtualNetworks" // DefaultAcceleratedNetworkingWindowsEnabled determines the aks-engine provided default for enabling accelerated networking on Windows nodes DefaultAcceleratedNetworkingWindowsEnabled = false + // DefaultAcceleratedNetworking determines the aks-engine provided default for enabling accelerated networking on Linux nodes + DefaultAcceleratedNetworking = true // DefaultDNSAutoscalerAddonName is the name of the dns-autoscaler addon DefaultDNSAutoscalerAddonName = "dns-autoscaler" ) diff --git a/pkg/api/defaults.go b/pkg/api/defaults.go index f813877481..443892aef2 100644 --- a/pkg/api/defaults.go +++ b/pkg/api/defaults.go @@ -376,11 +376,11 @@ func (p *Properties) setAgentProfileDefaults(isUpgrade, isScale bool) { // On instances that support hyperthreading, Accelerated Networking is supported on VM instances with 4 or more vCPUs. // Supported series are: D/DSv3, E/ESv3, Fsv2, and Ms/Mms. if profile.AcceleratedNetworkingEnabled == nil { - profile.AcceleratedNetworkingEnabled = helpers.PointerToBool(!isUpgrade && !isScale && helpers.AcceleratedNetworkingSupported(profile.VMSize)) + profile.AcceleratedNetworkingEnabled = helpers.PointerToBool(DefaultAcceleratedNetworking && !isUpgrade && !isScale && helpers.AcceleratedNetworkingSupported(profile.VMSize)) } if profile.AcceleratedNetworkingEnabledWindows == nil { - profile.AcceleratedNetworkingEnabledWindows = helpers.PointerToBool(DefaultAcceleratedNetworkingWindowsEnabled) + profile.AcceleratedNetworkingEnabledWindows = helpers.PointerToBool(DefaultAcceleratedNetworkingWindowsEnabled && !isUpgrade && !isScale && helpers.AcceleratedNetworkingSupported(profile.VMSize)) } if profile.OSType != Windows { diff --git a/pkg/api/defaults_test.go b/pkg/api/defaults_test.go index 638d3fae4b..72b56d4588 100644 --- a/pkg/api/defaults_test.go +++ b/pkg/api/defaults_test.go @@ -375,6 +375,74 @@ func TestAssignDefaultAddonVals(t *testing.T) { } +func TestAcceleratedNetworking(t *testing.T) { + mockCS := getMockBaseContainerService("1.10.8") + mockCS.Properties.OrchestratorProfile.OrchestratorType = "Kubernetes" + mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabled = nil + mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabledWindows = nil + isUpgrade := true + mockCS.SetPropertiesDefaults(isUpgrade, false) + + // In upgrade scenario, nil AcceleratedNetworkingEnabled should always render as false (i.e., we never turn on this feature on an existing vm that didn't have it before) + if helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabled) { + t.Errorf("expected nil acceleratedNetworkingEnabled to be false after upgrade, instead got %t", helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabled)) + } + // In upgrade scenario, nil AcceleratedNetworkingEnabledWindows should always render as false (i.e., we never turn on this feature on an existing vm that didn't have it before) + if helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabledWindows) { + t.Errorf("expected nil acceleratedNetworkingEnabledWindows to be false after upgrade, instead got %t", helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabledWindows)) + } + + mockCS = getMockBaseContainerService("1.10.8") + mockCS.Properties.OrchestratorProfile.OrchestratorType = "Kubernetes" + mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabled = nil + mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabledWindows = nil + isScale := true + mockCS.SetPropertiesDefaults(false, isScale) + + // In scale scenario, nil AcceleratedNetworkingEnabled should always render as false (i.e., we never turn on this feature on an existing agent pool / vmss that didn't have it before) + if helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabled) { + t.Errorf("expected nil acceleratedNetworkingEnabled to be false after upgrade, instead got %t", helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabled)) + } + // In scale scenario, nil AcceleratedNetworkingEnabledWindows should always render as false (i.e., we never turn on this feature on an existing vm that didn't have it before) + if helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabledWindows) { + t.Errorf("expected nil acceleratedNetworkingEnabledWindows to be false after upgrade, instead got %t", helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabledWindows)) + } + + mockCS = getMockBaseContainerService("1.10.8") + mockCS.Properties.OrchestratorProfile.OrchestratorType = "Kubernetes" + mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabled = nil + mockCS.Properties.AgentPoolProfiles[0].VMSize = "Standard_D2_v2" + mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabledWindows = nil + mockCS.Properties.AgentPoolProfiles[0].VMSize = "Standard_D2_v2" + mockCS.SetPropertiesDefaults(false, false) + + // In create scenario, nil AcceleratedNetworkingEnabled should be the defaults + if helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabled) != DefaultAcceleratedNetworking { + t.Errorf("expected default acceleratedNetworkingEnabled to be %t, instead got %t", DefaultAcceleratedNetworking, helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabled)) + } + // In create scenario, nil AcceleratedNetworkingEnabledWindows should be the defaults + if helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabledWindows) != DefaultAcceleratedNetworkingWindowsEnabled { + t.Errorf("expected default acceleratedNetworkingEnabledWindows to be %t, instead got %t", DefaultAcceleratedNetworkingWindowsEnabled, helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabledWindows)) + } + + mockCS = getMockBaseContainerService("1.10.8") + mockCS.Properties.OrchestratorProfile.OrchestratorType = "Kubernetes" + mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabled = nil + mockCS.Properties.AgentPoolProfiles[0].VMSize = "Standard_D666_v2" + mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabledWindows = nil + mockCS.Properties.AgentPoolProfiles[0].VMSize = "Standard_D666_v2" + mockCS.SetPropertiesDefaults(false, false) + + // In non-supported VM SKU scenario, acceleratedNetworkingEnabled should always be false + if helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabled) { + t.Errorf("expected acceleratedNetworkingEnabled to be %t for an unsupported VM SKU, instead got %t", false, helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabled)) + } + // In non-supported VM SKU scenario, acceleratedNetworkingEnabledWindows should always be false + if helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabledWindows) { + t.Errorf("expected acceleratedNetworkingEnabledWindows to be %t for an unsupported VM SKU, instead got %t", false, helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabledWindows)) + } +} + func TestKubeletFeatureGatesEnsureFeatureGatesOnAgentsFor1_6_0(t *testing.T) { mockCS := getMockBaseContainerService("1.6.0") properties := mockCS.Properties From bd1f6b42b0f40b415af632a41c85c8ba15dfeb74 Mon Sep 17 00:00:00 2001 From: Matt Boersma Date: Fri, 16 Nov 2018 14:10:10 -0700 Subject: [PATCH 12/29] Templates end with .tmpl (#31) * Change go template extension to .tmpl * Help GitHub's linguist identify .tmpl files as Go --- .gitattributes | 1 + docs/design/proposed-template-refactor.md | 30 ++++++++--------- parts/{agentoutputs.t => agentoutputs.tmpl} | 0 parts/{agentparams.t => agentparams.tmpl} | 0 parts/{iaasoutputs.t => iaasoutputs.tmpl} | 0 ...as.t => kubernetesagentresourcesvmas.tmpl} | 0 ...ss.t => kubernetesagentresourcesvmss.tmpl} | 0 ...esagentvars.t => kubernetesagentvars.tmpl} | 0 .../{kubernetesbase.t => kubernetesbase.tmpl} | 30 ++++++++--------- ...urces.t => kubernetesmasterresources.tmpl} | 0 ...s.t => kubernetesmasterresourcesvmss.tmpl} | 0 ...mastervars.t => kubernetesmastervars.tmpl} | 0 ...bernetesparams.t => kubernetesparams.tmpl} | 0 ...t => kuberneteswinagentresourcesvmas.tmpl} | 0 ...t => kuberneteswinagentresourcesvmss.tmpl} | 0 parts/{masteroutputs.t => masteroutputs.tmpl} | 0 parts/{masterparams.t => masterparams.tmpl} | 0 parts/{windowsparams.t => windowsparams.tmpl} | 0 pkg/engine/const.go | 32 +++++++++---------- 19 files changed, 47 insertions(+), 46 deletions(-) rename parts/{agentoutputs.t => agentoutputs.tmpl} (100%) rename parts/{agentparams.t => agentparams.tmpl} (100%) rename parts/{iaasoutputs.t => iaasoutputs.tmpl} (100%) rename parts/k8s/{kubernetesagentresourcesvmas.t => kubernetesagentresourcesvmas.tmpl} (100%) rename parts/k8s/{kubernetesagentresourcesvmss.t => kubernetesagentresourcesvmss.tmpl} (100%) rename parts/k8s/{kubernetesagentvars.t => kubernetesagentvars.tmpl} (100%) rename parts/k8s/{kubernetesbase.t => kubernetesbase.tmpl} (83%) rename parts/k8s/{kubernetesmasterresources.t => kubernetesmasterresources.tmpl} (100%) rename parts/k8s/{kubernetesmasterresourcesvmss.t => kubernetesmasterresourcesvmss.tmpl} (100%) rename parts/k8s/{kubernetesmastervars.t => kubernetesmastervars.tmpl} (100%) rename parts/k8s/{kubernetesparams.t => kubernetesparams.tmpl} (100%) rename parts/k8s/{kuberneteswinagentresourcesvmas.t => kuberneteswinagentresourcesvmas.tmpl} (100%) rename parts/k8s/{kuberneteswinagentresourcesvmss.t => kuberneteswinagentresourcesvmss.tmpl} (100%) rename parts/{masteroutputs.t => masteroutputs.tmpl} (100%) rename parts/{masterparams.t => masterparams.tmpl} (100%) rename parts/{windowsparams.t => windowsparams.tmpl} (100%) diff --git a/.gitattributes b/.gitattributes index aecf250376..67d1b83e08 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ +parts/*.tmpl linguist-language=Go * -crlf diff --git a/docs/design/proposed-template-refactor.md b/docs/design/proposed-template-refactor.md index 8e579dc031..57e8db2a9f 100644 --- a/docs/design/proposed-template-refactor.md +++ b/docs/design/proposed-template-refactor.md @@ -31,7 +31,7 @@ Once the input is validated, the template generator is invoked which will conver "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { - {{range .AgentPoolProfiles}}{{template "agentparams.t" .}},{{end}} + {{range .AgentPoolProfiles}}{{template "agentparams.tmpl" .}},{{end}} {{if .HasWindows}} "kubeBinariesSASURL": { "metadata": { @@ -57,15 +57,15 @@ Once the input is validated, the template generator is invoked which will conver }, "type": "string" }, - {{template "windowsparams.t"}}, + {{template "windowsparams.tmpl"}}, {{end}} - {{template "masterparams.t" .}}, - {{template "k8s/kubernetesparams.t" .}} + {{template "masterparams.tmpl" .}}, + {{template "k8s/kubernetesparams.tmpl" .}} }, "variables": { {{range $index, $agent := .AgentPoolProfiles}} "{{.Name}}Index": {{$index}}, - {{template "k8s/kubernetesagentvars.t" .}} + {{template "k8s/kubernetesagentvars.tmpl" .}} {{if IsNSeriesSKU .}} {{if IsNVIDIADevicePluginEnabled}} "registerWithGpuTaints": "nvidia.com/gpu=true:NoSchedule", @@ -78,30 +78,30 @@ Once the input is validated, the template generator is invoked which will conver "{{.Name}}AccountName": "[concat(variables('storageAccountBaseName'), 'agnt{{$index}}')]", {{end}} {{end}} - {{template "k8s/kubernetesmastervars.t" .}} + {{template "k8s/kubernetesmastervars.tmpl" .}} }, "resources": [ {{if IsOpenShift}} - {{template "openshift/infraresources.t" .}} + {{template "openshift/infraresources.tmpl" .}} {{end}} {{ range $index, $element := .AgentPoolProfiles}} {{if $index}}, {{end}} {{if .IsWindows}} {{if .IsVirtualMachineScaleSets}} - {{template "k8s/kuberneteswinagentresourcesvmss.t" .}} + {{template "k8s/kuberneteswinagentresourcesvmss.tmpl" .}} {{else}} - {{template "k8s/kuberneteswinagentresourcesvmas.t" .}} + {{template "k8s/kuberneteswinagentresourcesvmas.tmpl" .}} {{end}} {{else}} {{if .IsVirtualMachineScaleSets}} - {{template "k8s/kubernetesagentresourcesvmss.t" .}} + {{template "k8s/kubernetesagentresourcesvmss.tmpl" .}} {{else}} - {{template "k8s/kubernetesagentresourcesvmas.t" .}} + {{template "k8s/kubernetesagentresourcesvmas.tmpl" .}} {{end}} {{end}} {{end}} {{if not IsHostedMaster}} - ,{{template "k8s/kubernetesmasterresources.t" .}} + ,{{template "k8s/kubernetesmasterresources.tmpl" .}} {{else}} {{if not IsCustomVNET}} ,{ @@ -207,12 +207,12 @@ Once the input is validated, the template generator is invoked which will conver {{end}} ], "outputs": { - {{range .AgentPoolProfiles}}{{template "agentoutputs.t" .}} + {{range .AgentPoolProfiles}}{{template "agentoutputs.tmpl" .}} {{end}} {{if not IsHostedMaster}} - {{template "masteroutputs.t" .}} , + {{template "masteroutputs.tmpl" .}} , {{end}} - {{template "iaasoutputs.t" .}} + {{template "iaasoutputs.tmpl" .}} } } diff --git a/parts/agentoutputs.t b/parts/agentoutputs.tmpl similarity index 100% rename from parts/agentoutputs.t rename to parts/agentoutputs.tmpl diff --git a/parts/agentparams.t b/parts/agentparams.tmpl similarity index 100% rename from parts/agentparams.t rename to parts/agentparams.tmpl diff --git a/parts/iaasoutputs.t b/parts/iaasoutputs.tmpl similarity index 100% rename from parts/iaasoutputs.t rename to parts/iaasoutputs.tmpl diff --git a/parts/k8s/kubernetesagentresourcesvmas.t b/parts/k8s/kubernetesagentresourcesvmas.tmpl similarity index 100% rename from parts/k8s/kubernetesagentresourcesvmas.t rename to parts/k8s/kubernetesagentresourcesvmas.tmpl diff --git a/parts/k8s/kubernetesagentresourcesvmss.t b/parts/k8s/kubernetesagentresourcesvmss.tmpl similarity index 100% rename from parts/k8s/kubernetesagentresourcesvmss.t rename to parts/k8s/kubernetesagentresourcesvmss.tmpl diff --git a/parts/k8s/kubernetesagentvars.t b/parts/k8s/kubernetesagentvars.tmpl similarity index 100% rename from parts/k8s/kubernetesagentvars.t rename to parts/k8s/kubernetesagentvars.tmpl diff --git a/parts/k8s/kubernetesbase.t b/parts/k8s/kubernetesbase.tmpl similarity index 83% rename from parts/k8s/kubernetesbase.t rename to parts/k8s/kubernetesbase.tmpl index a220714660..c4d6aa4b95 100644 --- a/parts/k8s/kubernetesbase.t +++ b/parts/k8s/kubernetesbase.tmpl @@ -2,17 +2,17 @@ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { - {{range .AgentPoolProfiles}}{{template "agentparams.t" .}},{{end}} + {{range .AgentPoolProfiles}}{{template "agentparams.tmpl" .}},{{end}} {{if .HasWindows}} - {{template "windowsparams.t"}}, + {{template "windowsparams.tmpl"}}, {{end}} - {{template "masterparams.t" .}}, - {{template "k8s/kubernetesparams.t" .}} + {{template "masterparams.tmpl" .}}, + {{template "k8s/kubernetesparams.tmpl" .}} }, "variables": { {{range $index, $agent := .AgentPoolProfiles}} "{{.Name}}Index": {{$index}}, - {{template "k8s/kubernetesagentvars.t" .}} + {{template "k8s/kubernetesagentvars.tmpl" .}} {{if IsNSeriesSKU .}} {{if IsNVIDIADevicePluginEnabled}} "registerWithGpuTaints": "nvidia.com/gpu=true:NoSchedule", @@ -25,7 +25,7 @@ "{{.Name}}AccountName": "[concat(variables('storageAccountBaseName'), 'agnt{{$index}}')]", {{end}} {{end}} - {{template "k8s/kubernetesmastervars.t" .}} + {{template "k8s/kubernetesmastervars.tmpl" .}} }, "resources": [ {{if UserAssignedIDEnabled}} @@ -54,15 +54,15 @@ {{if $index}}, {{end}} {{if .IsWindows}} {{if .IsVirtualMachineScaleSets}} - {{template "k8s/kuberneteswinagentresourcesvmss.t" .}} + {{template "k8s/kuberneteswinagentresourcesvmss.tmpl" .}} {{else}} - {{template "k8s/kuberneteswinagentresourcesvmas.t" .}} + {{template "k8s/kuberneteswinagentresourcesvmas.tmpl" .}} {{end}} {{else}} {{if .IsVirtualMachineScaleSets}} - {{template "k8s/kubernetesagentresourcesvmss.t" .}} + {{template "k8s/kubernetesagentresourcesvmss.tmpl" .}} {{else}} - {{template "k8s/kubernetesagentresourcesvmas.t" .}} + {{template "k8s/kubernetesagentresourcesvmas.tmpl" .}} {{end}} {{end}} {{end}} @@ -125,19 +125,19 @@ } {{else}} {{if IsMasterVirtualMachineScaleSets}} - ,{{template "k8s/kubernetesmasterresourcesvmss.t" .}} + ,{{template "k8s/kubernetesmasterresourcesvmss.tmpl" .}} {{else}} - ,{{template "k8s/kubernetesmasterresources.t" .}} + ,{{template "k8s/kubernetesmasterresources.tmpl" .}} {{end}} {{end}} ], "outputs": { - {{range .AgentPoolProfiles}}{{template "agentoutputs.t" .}} + {{range .AgentPoolProfiles}}{{template "agentoutputs.tmpl" .}} {{end}} {{if not IsHostedMaster}} - {{template "masteroutputs.t" .}} , + {{template "masteroutputs.tmpl" .}} , {{end}} - {{template "iaasoutputs.t" .}} + {{template "iaasoutputs.tmpl" .}} } } diff --git a/parts/k8s/kubernetesmasterresources.t b/parts/k8s/kubernetesmasterresources.tmpl similarity index 100% rename from parts/k8s/kubernetesmasterresources.t rename to parts/k8s/kubernetesmasterresources.tmpl diff --git a/parts/k8s/kubernetesmasterresourcesvmss.t b/parts/k8s/kubernetesmasterresourcesvmss.tmpl similarity index 100% rename from parts/k8s/kubernetesmasterresourcesvmss.t rename to parts/k8s/kubernetesmasterresourcesvmss.tmpl diff --git a/parts/k8s/kubernetesmastervars.t b/parts/k8s/kubernetesmastervars.tmpl similarity index 100% rename from parts/k8s/kubernetesmastervars.t rename to parts/k8s/kubernetesmastervars.tmpl diff --git a/parts/k8s/kubernetesparams.t b/parts/k8s/kubernetesparams.tmpl similarity index 100% rename from parts/k8s/kubernetesparams.t rename to parts/k8s/kubernetesparams.tmpl diff --git a/parts/k8s/kuberneteswinagentresourcesvmas.t b/parts/k8s/kuberneteswinagentresourcesvmas.tmpl similarity index 100% rename from parts/k8s/kuberneteswinagentresourcesvmas.t rename to parts/k8s/kuberneteswinagentresourcesvmas.tmpl diff --git a/parts/k8s/kuberneteswinagentresourcesvmss.t b/parts/k8s/kuberneteswinagentresourcesvmss.tmpl similarity index 100% rename from parts/k8s/kuberneteswinagentresourcesvmss.t rename to parts/k8s/kuberneteswinagentresourcesvmss.tmpl diff --git a/parts/masteroutputs.t b/parts/masteroutputs.tmpl similarity index 100% rename from parts/masteroutputs.t rename to parts/masteroutputs.tmpl diff --git a/parts/masterparams.t b/parts/masterparams.tmpl similarity index 100% rename from parts/masterparams.t rename to parts/masterparams.tmpl diff --git a/parts/windowsparams.t b/parts/windowsparams.tmpl similarity index 100% rename from parts/windowsparams.t rename to parts/windowsparams.tmpl diff --git a/pkg/engine/const.go b/pkg/engine/const.go index 52109e6006..cc4f77ca40 100644 --- a/pkg/engine/const.go +++ b/pkg/engine/const.go @@ -132,20 +132,20 @@ const ( ) const ( - agentOutputs = "agentoutputs.t" - agentParams = "agentparams.t" - iaasOutputs = "iaasoutputs.t" - kubernetesBaseFile = "k8s/kubernetesbase.t" - kubernetesAgentResourcesVMAS = "k8s/kubernetesagentresourcesvmas.t" - kubernetesAgentResourcesVMSS = "k8s/kubernetesagentresourcesvmss.t" - kubernetesAgentVars = "k8s/kubernetesagentvars.t" - kubernetesMasterResourcesVMAS = "k8s/kubernetesmasterresources.t" - kubernetesMasterResourcesVMSS = "k8s/kubernetesmasterresourcesvmss.t" - kubernetesMasterVars = "k8s/kubernetesmastervars.t" - kubernetesParams = "k8s/kubernetesparams.t" - kubernetesWinAgentVars = "k8s/kuberneteswinagentresourcesvmas.t" - kubernetesWinAgentVarsVMSS = "k8s/kuberneteswinagentresourcesvmss.t" - masterOutputs = "masteroutputs.t" - masterParams = "masterparams.t" - windowsParams = "windowsparams.t" + agentOutputs = "agentoutputs.tmpl" + agentParams = "agentparams.tmpl" + iaasOutputs = "iaasoutputs.tmpl" + kubernetesBaseFile = "k8s/kubernetesbase.tmpl" + kubernetesAgentResourcesVMAS = "k8s/kubernetesagentresourcesvmas.tmpl" + kubernetesAgentResourcesVMSS = "k8s/kubernetesagentresourcesvmss.tmpl" + kubernetesAgentVars = "k8s/kubernetesagentvars.tmpl" + kubernetesMasterResourcesVMAS = "k8s/kubernetesmasterresources.tmpl" + kubernetesMasterResourcesVMSS = "k8s/kubernetesmasterresourcesvmss.tmpl" + kubernetesMasterVars = "k8s/kubernetesmastervars.tmpl" + kubernetesParams = "k8s/kubernetesparams.tmpl" + kubernetesWinAgentVars = "k8s/kuberneteswinagentresourcesvmas.tmpl" + kubernetesWinAgentVarsVMSS = "k8s/kuberneteswinagentresourcesvmss.tmpl" + masterOutputs = "masteroutputs.tmpl" + masterParams = "masterparams.tmpl" + windowsParams = "windowsparams.tmpl" ) From 428537e0ee6029cc29cf5f194a9efa73f5195d9b Mon Sep 17 00:00:00 2001 From: Tariq Ibrahim Date: Mon, 19 Nov 2018 09:29:41 -0800 Subject: [PATCH 13/29] remove additional sed statements for ip-masq addons (#30) --- parts/k8s/containeraddons/ip-masq-agent.yaml | 10 +++++--- parts/k8s/kubernetesmastercustomdata.yml | 8 ------ parts/k8s/kubernetesparams.tmpl | 9 ------- pkg/api/addons.go | 4 +++ pkg/api/const.go | 2 ++ pkg/api/types.go | 26 ++++++++++++++++++++ pkg/engine/params_k8s.go | 11 --------- 7 files changed, 39 insertions(+), 31 deletions(-) diff --git a/parts/k8s/containeraddons/ip-masq-agent.yaml b/parts/k8s/containeraddons/ip-masq-agent.yaml index 0c50453e4e..8382d84153 100644 --- a/parts/k8s/containeraddons/ip-masq-agent.yaml +++ b/parts/k8s/containeraddons/ip-masq-agent.yaml @@ -58,7 +58,11 @@ metadata: data: ip-masq-agent: |- nonMasqueradeCIDRs: - - - - - masqLinkLocal: + - {{ContainerConfig "non-masquerade-cidr"}} + {{- if ContainerConfig "non-masq-cni-cidr"}} + - {{ContainerConfig "non-masq-cni-cidr"}} + masqLinkLocal: true + {{else -}} + masqLinkLocal: false + {{end -}} resyncInterval: 60s \ No newline at end of file diff --git a/parts/k8s/kubernetesmastercustomdata.yml b/parts/k8s/kubernetesmastercustomdata.yml index 4f736ca368..c2a2b91d1b 100644 --- a/parts/k8s/kubernetesmastercustomdata.yml +++ b/parts/k8s/kubernetesmastercustomdata.yml @@ -350,14 +350,6 @@ MASTER_ARTIFACTS_CONFIG_PLACEHOLDER {{if HasCustomSearchDomain}} sed -i "s||{{WrapAsParameter "searchDomainName"}}|g; s||{{WrapAsParameter "searchDomainRealmUser"}}|g; s||{{WrapAsParameter "searchDomainRealmPassword"}}|g" /opt/azure/containers/setup-custom-search-domains.sh {{end}} - a=/etc/kubernetes/addons/ip-masq-agent.yaml - sed -i "s||{{WrapAsParameter "kubernetesNonMasqueradeCidr"}}|g" $a -{{if IsAzureCNI}} - sed -i "s||168.63.129.16/32|g; s||true|g" $a -{{else}} - sed -i "\||d" $a - sed -i "s||false|g" $a -{{end}} - path: /opt/azure/containers/mountetcd.sh permissions: "0744" diff --git a/parts/k8s/kubernetesparams.tmpl b/parts/k8s/kubernetesparams.tmpl index 1baef5d7ae..dd51dc0ee6 100644 --- a/parts/k8s/kubernetesparams.tmpl +++ b/parts/k8s/kubernetesparams.tmpl @@ -191,15 +191,6 @@ }, "type": "string" }, -{{if not IsHostedMaster}} - "kubernetesNonMasqueradeCidr": { - "metadata": { - "description": "kubernetesNonMasqueradeCidr cluster subnet" - }, - "defaultValue": "{{GetDefaultVNETCIDR}}", - "type": "string" - }, -{{end}} "kubernetesKubeletClusterDomain": { "metadata": { "description": "--cluster-domain Kubelet config" diff --git a/pkg/api/addons.go b/pkg/api/addons.go index 5a976b23b4..8043b33986 100644 --- a/pkg/api/addons.go +++ b/pkg/api/addons.go @@ -207,6 +207,10 @@ func (cs *ContainerService) setAddonsConfig(isUpdate bool) { Image: specConfig.KubernetesImageBase + "ip-masq-agent-amd64:v2.0.0", }, }, + Config: map[string]string{ + "non-masquerade-cidr": cs.Properties.GetNonMasqueradeCIDR(), + "non-masq-cni-cidr": cs.Properties.GetAzureCNICidr(), + }, } defaultAzureCNINetworkMonitorAddonsConfig := KubernetesAddon{ diff --git a/pkg/api/const.go b/pkg/api/const.go index add7e35c63..ee1fc3863c 100644 --- a/pkg/api/const.go +++ b/pkg/api/const.go @@ -55,6 +55,8 @@ const ( DefaultFirstConsecutiveKubernetesStaticIP = "10.240.255.5" // DefaultFirstConsecutiveKubernetesStaticIPVMSS specifies the static IP address on Kubernetes master 0 of VMSS DefaultFirstConsecutiveKubernetesStaticIPVMSS = "10.240.0.4" + //DefaultCNICIDR specifies the default value for + DefaultCNICIDR = "168.63.129.16/32" // DefaultKubernetesFirstConsecutiveStaticIPOffset specifies the IP address offset of master 0 // when VNET integration is enabled. DefaultKubernetesFirstConsecutiveStaticIPOffset = 5 diff --git a/pkg/api/types.go b/pkg/api/types.go index 6ea98a1d84..6e5be74783 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -897,6 +897,32 @@ func (p *Properties) HasAvailabilityZones() bool { return hasZones } +// GetNonMasqueradeCIDR returns the non-masquerade CIDR for the ip-masq-agent. +func (p *Properties) GetNonMasqueradeCIDR() string { + var nonMasqCidr string + if !p.IsHostedMasterProfile() { + if p.OrchestratorProfile.IsAzureCNI() { + if p.MasterProfile != nil && p.MasterProfile.IsCustomVNET() { + nonMasqCidr = p.MasterProfile.VnetCidr + } else { + nonMasqCidr = DefaultVNETCIDR + } + } else { + nonMasqCidr = p.OrchestratorProfile.KubernetesConfig.ClusterSubnet + } + } + return nonMasqCidr +} + +// GetAzureCNICidr returns the default CNI Cidr if Azure CNI is enabled. +func (p *Properties) GetAzureCNICidr() string { + var masqCNIIP string + if p.OrchestratorProfile != nil && p.OrchestratorProfile.IsAzureCNI() { + masqCNIIP = DefaultCNICIDR + } + return masqCNIIP +} + // IsCustomVNET returns true if the customer brought their own VNET func (m *MasterProfile) IsCustomVNET() bool { return len(m.VnetSubnetID) > 0 diff --git a/pkg/engine/params_k8s.go b/pkg/engine/params_k8s.go index fec03212db..7cc8292e2e 100644 --- a/pkg/engine/params_k8s.go +++ b/pkg/engine/params_k8s.go @@ -98,17 +98,6 @@ func assignKubernetesParameters(properties *api.Properties, parametersMap params CloudProviderRateLimitBucket: kubernetesConfig.CloudProviderRateLimitBucket, }) addValue(parametersMap, "kubeClusterCidr", kubernetesConfig.ClusterSubnet) - if !properties.IsHostedMasterProfile() { - if properties.OrchestratorProfile.IsAzureCNI() { - if properties.MasterProfile != nil && properties.MasterProfile.IsCustomVNET() { - addValue(parametersMap, "kubernetesNonMasqueradeCidr", properties.MasterProfile.VnetCidr) - } else { - addValue(parametersMap, "kubernetesNonMasqueradeCidr", DefaultVNETCIDR) - } - } else { - addValue(parametersMap, "kubernetesNonMasqueradeCidr", properties.OrchestratorProfile.KubernetesConfig.ClusterSubnet) - } - } addValue(parametersMap, "kubernetesKubeletClusterDomain", kubernetesConfig.KubeletConfig["--cluster-domain"]) addValue(parametersMap, "dockerBridgeCidr", kubernetesConfig.DockerBridgeSubnet) addValue(parametersMap, "networkPolicy", kubernetesConfig.NetworkPolicy) From 49a183cb668f1371d935d4b65d6dde1ff90b6e12 Mon Sep 17 00:00:00 2001 From: Matt Boersma Date: Mon, 19 Nov 2018 10:34:05 -0700 Subject: [PATCH 14/29] Update go-dev tools image for go 1.11.2 (#38) --- .circleci/config.yml | 2 +- Makefile | 2 +- makedev.ps1 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 924dbe6f0d..4db9d3116d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,7 @@ version: 2 defaults: &defaults working_directory: /go/src/github.com/Azure/aks-engine docker: - - image: quay.io/deis/go-dev:v1.17.2 + - image: quay.io/deis/go-dev:v1.17.3 environment: GOPATH: /go diff --git a/Makefile b/Makefile index 97ccda49a3..e688d28ba5 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ GITTAG := $(VERSION_SHORT) endif REPO_PATH := github.com/Azure/aks-engine -DEV_ENV_IMAGE := quay.io/deis/go-dev:v1.17.2 +DEV_ENV_IMAGE := quay.io/deis/go-dev:v1.17.3 DEV_ENV_WORK_DIR := /go/src/${REPO_PATH} DEV_ENV_OPTS := --rm -v ${CURDIR}:${DEV_ENV_WORK_DIR} -w ${DEV_ENV_WORK_DIR} ${DEV_ENV_VARS} DEV_ENV_CMD := docker run ${DEV_ENV_OPTS} ${DEV_ENV_IMAGE} diff --git a/makedev.ps1 b/makedev.ps1 index 62bc2bf085..f9ac4062cf 100644 --- a/makedev.ps1 +++ b/makedev.ps1 @@ -1,5 +1,5 @@ $REPO_PATH = "github.com/Azure/aks-engine" -$DEV_ENV_IMAGE = "quay.io/deis/go-dev:v1.17.2" +$DEV_ENV_IMAGE = "quay.io/deis/go-dev:v1.17.3" $DEV_ENV_WORK_DIR = "/go/src/$REPO_PATH" docker.exe run -it --rm -w $DEV_ENV_WORK_DIR -v `"$($PWD)`":$DEV_ENV_WORK_DIR $DEV_ENV_IMAGE bash From 125d95cb319bd1cb4b9d2aa588c64362efbcc594 Mon Sep 17 00:00:00 2001 From: Tariq Ibrahim Date: Mon, 19 Nov 2018 11:24:36 -0800 Subject: [PATCH 15/29] remove unused azconst methods (#35) --- Makefile | 2 +- pkg/engine/template_generator.go | 7 +- pkg/helpers/Get-AzureConstants.py | 77 +- pkg/helpers/azureconst.go | 1094 +---------------------------- pkg/helpers/azureconst_test.go | 240 +++++++ 5 files changed, 280 insertions(+), 1140 deletions(-) create mode 100644 pkg/helpers/azureconst_test.go diff --git a/Makefile b/Makefile index e688d28ba5..d9e0fec59a 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,7 @@ generate: bootstrap .PHONY: generate-azure-constants generate-azure-constants: - python pkg/engine/Get-AzureConstants.py + python pkg/helpers/Get-AzureConstants.py .PHONY: build build: generate diff --git a/pkg/engine/template_generator.go b/pkg/engine/template_generator.go index f173355ad1..3bb07d55dc 100644 --- a/pkg/engine/template_generator.go +++ b/pkg/engine/template_generator.go @@ -398,16 +398,13 @@ func (t *TemplateGenerator) getTemplateFuncMap(cs *api.ContainerService) templat return false }, "GetMasterAllowedSizes": func() string { - return helpers.GetMasterAgentAllowedSizes() + return helpers.GetKubernetesAllowedSizes() }, "GetDefaultVNETCIDR": func() string { return DefaultVNETCIDR }, "GetAgentAllowedSizes": func() string { - if cs.Properties.OrchestratorProfile.IsKubernetes() { - return helpers.GetKubernetesAgentAllowedSizes() - } - return helpers.GetMasterAgentAllowedSizes() + return helpers.GetKubernetesAllowedSizes() }, "GetSizeMap": func() string { return helpers.GetSizeMap() diff --git a/pkg/helpers/Get-AzureConstants.py b/pkg/helpers/Get-AzureConstants.py index 95f0bac5fc..73e74e9a9d 100644 --- a/pkg/helpers/Get-AzureConstants.py +++ b/pkg/helpers/Get-AzureConstants.py @@ -25,18 +25,6 @@ def getAllSizes(): return sizeMap -min_cores_k8s = 1 - -def getMasterAgentMap(sizeMap): - agentMap = {} - - for key in sizeMap.keys(): - size = sizeMap[key] - if size['numberOfCores'] >= min_cores_k8s: - agentMap[size['name']] = size - - return agentMap - def getLocations(): locations = json.loads(subprocess.check_output(['az', 'account', 'list-locations']).decode('utf-8')) @@ -61,8 +49,11 @@ def getStorageAccountType(sizeName): else: return "Standard_LRS" -def getFileContents(masterAgentMap, kubernetesAgentMap, sizeMap, locations): - text = r"""package helpers +def getFileContents(kubernetesSizeMap, locations): + text = r"""// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +package helpers // AUTOGENERATED FILE """ @@ -91,23 +82,11 @@ def getFileContents(masterAgentMap, kubernetesAgentMap, sizeMap, locations): } } -// GetMasterAgentAllowedSizes returns the agent allowed sizes -func GetMasterAgentAllowedSizes() string { +// GetKubernetesAllowedSizes returns the allowed sizes for Kubernetes agent +func GetKubernetesAllowedSizes() string { return ` "allowedValues": [ """ - masterAgentMapKeys = sorted(masterAgentMap.keys()) - for key in masterAgentMapKeys[:-1]: - text += ' "' + key + '",\n' - text += ' "' + masterAgentMapKeys[-1] + '"\n' - text += r""" ], -` -} - -// GetKubernetesAgentAllowedSizes returns the allowed sizes for Kubernetes agent -func GetKubernetesAgentAllowedSizes() string { - return ` "allowedValues": [ -""" - kubernetesAgentMapKeys = sorted(kubernetesAgentMap.keys()) + kubernetesAgentMapKeys = sorted(kubernetesSizeMap.keys()) for key in kubernetesAgentMapKeys[:-1]: text += ' "' + key + '",\n' text += ' "' + kubernetesAgentMapKeys[-1] + '"\n' @@ -121,7 +100,7 @@ def getFileContents(masterAgentMap, kubernetesAgentMap, sizeMap, locations): """ mergedMap = {} for key in kubernetesAgentMapKeys: - size = kubernetesAgentMap[key] + size = kubernetesSizeMap[key] if not key in mergedMap: mergedMap[size['name']] = size @@ -140,49 +119,15 @@ def getFileContents(masterAgentMap, kubernetesAgentMap, sizeMap, locations): text += r""" } ` -} - -// GetClassicAllowedSizes returns the classic allowed sizes -func GetClassicAllowedSizes() string { - return ` "allowedValues": [ -""" - sizeMapKeys = sorted(sizeMap.keys()) - for key in sizeMapKeys[:-1]: - text += ' "' + sizeMap[key]['name'] + '",\n' - key = sizeMapKeys[-1] - text += ' "' + sizeMap[key]['name'] + '"\n' - - text += r""" ], -` -} - -// GetClassicSizeMap returns the size / storage map -func GetClassicSizeMap() string { - return ` "vmSizesMap": { -""" - sizeMapKeys = sorted(sizeMap.keys()) - for key in sizeMapKeys[:-1]: - text += ' "' + sizeMap[key]['name'] + '": {\n' - storageAccountType = getStorageAccountType(size['name']) - text += ' "storageAccountType": "' + storageAccountType + '"\n },\n' - key = sizeMapKeys[-1] - text += ' "' + sizeMap[key]['name'] + '": {\n' - storageAccountType = getStorageAccountType(size['name']) - text += ' "storageAccountType": "' + storageAccountType + '"\n }\n' - - text += r""" } -` }""" return text def main(): outfile = 'pkg/helpers/azureconst.go' - allSizes = getAllSizes() - masterAgentMap = getMasterAgentMap(allSizes) - kubernetesAgentMap = allSizes + kubernetesSizeMap = getAllSizes() locations = getLocations() - text = getFileContents(masterAgentMap, kubernetesAgentMap, allSizes, locations) + text = getFileContents(kubernetesSizeMap, locations) with open(outfile, 'w') as f: f.write(text) diff --git a/pkg/helpers/azureconst.go b/pkg/helpers/azureconst.go index f231efa7c8..247aebe782 100644 --- a/pkg/helpers/azureconst.go +++ b/pkg/helpers/azureconst.go @@ -60,8 +60,8 @@ func GetAzureLocations() []string { } } -// GetMasterAgentAllowedSizes returns the agent allowed sizes -func GetMasterAgentAllowedSizes() string { +// GetKubernetesAllowedSizes returns the allowed sizes for Kubernetes agent +func GetKubernetesAllowedSizes() string { return ` "allowedValues": [ "Standard_A0", "Standard_A1", @@ -226,7 +226,10 @@ func GetMasterAgentAllowedSizes() string { "Standard_L16s", "Standard_L16s_v2", "Standard_L32s", + "Standard_L32s_v2", "Standard_L4s", + "Standard_L64s_v2", + "Standard_L80s_v2", "Standard_L8s", "Standard_L8s_v2", "Standard_M128", @@ -270,224 +273,11 @@ func GetMasterAgentAllowedSizes() string { "Standard_ND24s", "Standard_ND6s", "Standard_NV12", + "Standard_NV12s_v2", "Standard_NV24", - "Standard_NV6" - ], -` -} - -// GetKubernetesAgentAllowedSizes returns the allowed sizes for Kubernetes agent -func GetKubernetesAgentAllowedSizes() string { - return ` "allowedValues": [ - "Standard_A0", - "Standard_A1", - "Standard_A10", - "Standard_A11", - "Standard_A1_v2", - "Standard_A2", - "Standard_A2_v2", - "Standard_A2m_v2", - "Standard_A3", - "Standard_A4", - "Standard_A4_v2", - "Standard_A4m_v2", - "Standard_A5", - "Standard_A6", - "Standard_A7", - "Standard_A8", - "Standard_A8_v2", - "Standard_A8m_v2", - "Standard_A9", - "Standard_B1ms", - "Standard_B1s", - "Standard_B2ms", - "Standard_B2s", - "Standard_B4ms", - "Standard_B8ms", - "Standard_D1", - "Standard_D11", - "Standard_D11_v2", - "Standard_D11_v2_Promo", - "Standard_D12", - "Standard_D12_v2", - "Standard_D12_v2_Promo", - "Standard_D13", - "Standard_D13_v2", - "Standard_D13_v2_Promo", - "Standard_D14", - "Standard_D14_v2", - "Standard_D14_v2_Promo", - "Standard_D15_v2", - "Standard_D16_v3", - "Standard_D16s_v3", - "Standard_D1_v2", - "Standard_D2", - "Standard_D2_v2", - "Standard_D2_v2_Promo", - "Standard_D2_v3", - "Standard_D2s_v3", - "Standard_D3", - "Standard_D32_v3", - "Standard_D32s_v3", - "Standard_D3_v2", - "Standard_D3_v2_Promo", - "Standard_D4", - "Standard_D4_v2", - "Standard_D4_v2_Promo", - "Standard_D4_v3", - "Standard_D4s_v3", - "Standard_D5_v2", - "Standard_D5_v2_Promo", - "Standard_D64_v3", - "Standard_D64s_v3", - "Standard_D8_v3", - "Standard_D8s_v3", - "Standard_DC2s", - "Standard_DC4s", - "Standard_DS1", - "Standard_DS11", - "Standard_DS11-1_v2", - "Standard_DS11_v2", - "Standard_DS11_v2_Promo", - "Standard_DS12", - "Standard_DS12-1_v2", - "Standard_DS12-2_v2", - "Standard_DS12_v2", - "Standard_DS12_v2_Promo", - "Standard_DS13", - "Standard_DS13-2_v2", - "Standard_DS13-4_v2", - "Standard_DS13_v2", - "Standard_DS13_v2_Promo", - "Standard_DS14", - "Standard_DS14-4_v2", - "Standard_DS14-8_v2", - "Standard_DS14_v2", - "Standard_DS14_v2_Promo", - "Standard_DS15_v2", - "Standard_DS1_v2", - "Standard_DS2", - "Standard_DS2_v2", - "Standard_DS2_v2_Promo", - "Standard_DS3", - "Standard_DS3_v2", - "Standard_DS3_v2_Promo", - "Standard_DS4", - "Standard_DS4_v2", - "Standard_DS4_v2_Promo", - "Standard_DS5_v2", - "Standard_DS5_v2_Promo", - "Standard_E16-4s_v3", - "Standard_E16-8s_v3", - "Standard_E16_v3", - "Standard_E16s_v3", - "Standard_E20_v3", - "Standard_E20s_v3", - "Standard_E2_v3", - "Standard_E2s_v3", - "Standard_E32-16s_v3", - "Standard_E32-8s_v3", - "Standard_E32_v3", - "Standard_E32s_v3", - "Standard_E4-2s_v3", - "Standard_E4_v3", - "Standard_E4s_v3", - "Standard_E64-16s_v3", - "Standard_E64-32s_v3", - "Standard_E64_v3", - "Standard_E64i_v3", - "Standard_E64is_v3", - "Standard_E64s_v3", - "Standard_E8-2s_v3", - "Standard_E8-4s_v3", - "Standard_E8_v3", - "Standard_E8s_v3", - "Standard_F1", - "Standard_F16", - "Standard_F16s", - "Standard_F16s_v2", - "Standard_F1s", - "Standard_F2", - "Standard_F2s", - "Standard_F2s_v2", - "Standard_F32s_v2", - "Standard_F4", - "Standard_F4s", - "Standard_F4s_v2", - "Standard_F64s_v2", - "Standard_F72s_v2", - "Standard_F8", - "Standard_F8s", - "Standard_F8s_v2", - "Standard_G1", - "Standard_G2", - "Standard_G3", - "Standard_G4", - "Standard_G5", - "Standard_GS1", - "Standard_GS2", - "Standard_GS3", - "Standard_GS4", - "Standard_GS4-4", - "Standard_GS4-8", - "Standard_GS5", - "Standard_GS5-16", - "Standard_GS5-8", - "Standard_H16", - "Standard_H16m", - "Standard_H16mr", - "Standard_H16r", - "Standard_H8", - "Standard_H8m", - "Standard_L16s", - "Standard_L16s_v2", - "Standard_L32s", - "Standard_L4s", - "Standard_L8s", - "Standard_L8s_v2", - "Standard_M128", - "Standard_M128-32ms", - "Standard_M128-64ms", - "Standard_M128m", - "Standard_M128ms", - "Standard_M128s", - "Standard_M16-4ms", - "Standard_M16-8ms", - "Standard_M16ms", - "Standard_M32-16ms", - "Standard_M32-8ms", - "Standard_M32ls", - "Standard_M32ms", - "Standard_M32ts", - "Standard_M64", - "Standard_M64-16ms", - "Standard_M64-32ms", - "Standard_M64ls", - "Standard_M64m", - "Standard_M64ms", - "Standard_M64s", - "Standard_M8-2ms", - "Standard_M8-4ms", - "Standard_M8ms", - "Standard_NC12", - "Standard_NC12s_v2", - "Standard_NC12s_v3", - "Standard_NC24", - "Standard_NC24r", - "Standard_NC24rs_v2", - "Standard_NC24rs_v3", - "Standard_NC24s_v2", - "Standard_NC24s_v3", - "Standard_NC6", - "Standard_NC6s_v2", - "Standard_NC6s_v3", - "Standard_ND12s", - "Standard_ND24rs", - "Standard_ND24s", - "Standard_ND6s", - "Standard_NV12", - "Standard_NV24", - "Standard_NV6" + "Standard_NV24s_v2", + "Standard_NV6", + "Standard_NV6s_v2" ], ` } @@ -984,9 +774,18 @@ func GetSizeMap() string { "Standard_L32s": { "storageAccountType": "Premium_LRS" }, + "Standard_L32s_v2": { + "storageAccountType": "Premium_LRS" + }, "Standard_L4s": { "storageAccountType": "Premium_LRS" }, + "Standard_L64s_v2": { + "storageAccountType": "Premium_LRS" + }, + "Standard_L80s_v2": { + "storageAccountType": "Premium_LRS" + }, "Standard_L8s": { "storageAccountType": "Premium_LRS" }, @@ -1116,861 +915,20 @@ func GetSizeMap() string { "Standard_NV12": { "storageAccountType": "Standard_LRS" }, + "Standard_NV12s_v2": { + "storageAccountType": "Premium_LRS" + }, "Standard_NV24": { "storageAccountType": "Standard_LRS" }, + "Standard_NV24s_v2": { + "storageAccountType": "Premium_LRS" + }, "Standard_NV6": { "storageAccountType": "Standard_LRS" - } - } -` -} - -// GetClassicAllowedSizes returns the classic allowed sizes -func GetClassicAllowedSizes() string { - return ` "allowedValues": [ - "Standard_A0", - "Standard_A1", - "Standard_A10", - "Standard_A11", - "Standard_A1_v2", - "Standard_A2", - "Standard_A2_v2", - "Standard_A2m_v2", - "Standard_A3", - "Standard_A4", - "Standard_A4_v2", - "Standard_A4m_v2", - "Standard_A5", - "Standard_A6", - "Standard_A7", - "Standard_A8", - "Standard_A8_v2", - "Standard_A8m_v2", - "Standard_A9", - "Standard_B1ms", - "Standard_B1s", - "Standard_B2ms", - "Standard_B2s", - "Standard_B4ms", - "Standard_B8ms", - "Standard_D1", - "Standard_D11", - "Standard_D11_v2", - "Standard_D11_v2_Promo", - "Standard_D12", - "Standard_D12_v2", - "Standard_D12_v2_Promo", - "Standard_D13", - "Standard_D13_v2", - "Standard_D13_v2_Promo", - "Standard_D14", - "Standard_D14_v2", - "Standard_D14_v2_Promo", - "Standard_D15_v2", - "Standard_D16_v3", - "Standard_D16s_v3", - "Standard_D1_v2", - "Standard_D2", - "Standard_D2_v2", - "Standard_D2_v2_Promo", - "Standard_D2_v3", - "Standard_D2s_v3", - "Standard_D3", - "Standard_D32_v3", - "Standard_D32s_v3", - "Standard_D3_v2", - "Standard_D3_v2_Promo", - "Standard_D4", - "Standard_D4_v2", - "Standard_D4_v2_Promo", - "Standard_D4_v3", - "Standard_D4s_v3", - "Standard_D5_v2", - "Standard_D5_v2_Promo", - "Standard_D64_v3", - "Standard_D64s_v3", - "Standard_D8_v3", - "Standard_D8s_v3", - "Standard_DC2s", - "Standard_DC4s", - "Standard_DS1", - "Standard_DS11", - "Standard_DS11-1_v2", - "Standard_DS11_v2", - "Standard_DS11_v2_Promo", - "Standard_DS12", - "Standard_DS12-1_v2", - "Standard_DS12-2_v2", - "Standard_DS12_v2", - "Standard_DS12_v2_Promo", - "Standard_DS13", - "Standard_DS13-2_v2", - "Standard_DS13-4_v2", - "Standard_DS13_v2", - "Standard_DS13_v2_Promo", - "Standard_DS14", - "Standard_DS14-4_v2", - "Standard_DS14-8_v2", - "Standard_DS14_v2", - "Standard_DS14_v2_Promo", - "Standard_DS15_v2", - "Standard_DS1_v2", - "Standard_DS2", - "Standard_DS2_v2", - "Standard_DS2_v2_Promo", - "Standard_DS3", - "Standard_DS3_v2", - "Standard_DS3_v2_Promo", - "Standard_DS4", - "Standard_DS4_v2", - "Standard_DS4_v2_Promo", - "Standard_DS5_v2", - "Standard_DS5_v2_Promo", - "Standard_E16-4s_v3", - "Standard_E16-8s_v3", - "Standard_E16_v3", - "Standard_E16s_v3", - "Standard_E20_v3", - "Standard_E20s_v3", - "Standard_E2_v3", - "Standard_E2s_v3", - "Standard_E32-16s_v3", - "Standard_E32-8s_v3", - "Standard_E32_v3", - "Standard_E32s_v3", - "Standard_E4-2s_v3", - "Standard_E4_v3", - "Standard_E4s_v3", - "Standard_E64-16s_v3", - "Standard_E64-32s_v3", - "Standard_E64_v3", - "Standard_E64i_v3", - "Standard_E64is_v3", - "Standard_E64s_v3", - "Standard_E8-2s_v3", - "Standard_E8-4s_v3", - "Standard_E8_v3", - "Standard_E8s_v3", - "Standard_F1", - "Standard_F16", - "Standard_F16s", - "Standard_F16s_v2", - "Standard_F1s", - "Standard_F2", - "Standard_F2s", - "Standard_F2s_v2", - "Standard_F32s_v2", - "Standard_F4", - "Standard_F4s", - "Standard_F4s_v2", - "Standard_F64s_v2", - "Standard_F72s_v2", - "Standard_F8", - "Standard_F8s", - "Standard_F8s_v2", - "Standard_G1", - "Standard_G2", - "Standard_G3", - "Standard_G4", - "Standard_G5", - "Standard_GS1", - "Standard_GS2", - "Standard_GS3", - "Standard_GS4", - "Standard_GS4-4", - "Standard_GS4-8", - "Standard_GS5", - "Standard_GS5-16", - "Standard_GS5-8", - "Standard_H16", - "Standard_H16m", - "Standard_H16mr", - "Standard_H16r", - "Standard_H8", - "Standard_H8m", - "Standard_L16s", - "Standard_L16s_v2", - "Standard_L32s", - "Standard_L4s", - "Standard_L8s", - "Standard_L8s_v2", - "Standard_M128", - "Standard_M128-32ms", - "Standard_M128-64ms", - "Standard_M128m", - "Standard_M128ms", - "Standard_M128s", - "Standard_M16-4ms", - "Standard_M16-8ms", - "Standard_M16ms", - "Standard_M32-16ms", - "Standard_M32-8ms", - "Standard_M32ls", - "Standard_M32ms", - "Standard_M32ts", - "Standard_M64", - "Standard_M64-16ms", - "Standard_M64-32ms", - "Standard_M64ls", - "Standard_M64m", - "Standard_M64ms", - "Standard_M64s", - "Standard_M8-2ms", - "Standard_M8-4ms", - "Standard_M8ms", - "Standard_NC12", - "Standard_NC12s_v2", - "Standard_NC12s_v3", - "Standard_NC24", - "Standard_NC24r", - "Standard_NC24rs_v2", - "Standard_NC24rs_v3", - "Standard_NC24s_v2", - "Standard_NC24s_v3", - "Standard_NC6", - "Standard_NC6s_v2", - "Standard_NC6s_v3", - "Standard_ND12s", - "Standard_ND24rs", - "Standard_ND24s", - "Standard_ND6s", - "Standard_NV12", - "Standard_NV24", - "Standard_NV6" - ], -` -} - -// GetClassicSizeMap returns the size / storage map -func GetClassicSizeMap() string { - return ` "vmSizesMap": { - "Standard_A0": { - "storageAccountType": "Standard_LRS" - }, - "Standard_A1": { - "storageAccountType": "Standard_LRS" - }, - "Standard_A10": { - "storageAccountType": "Standard_LRS" - }, - "Standard_A11": { - "storageAccountType": "Standard_LRS" - }, - "Standard_A1_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_A2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_A2_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_A2m_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_A3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_A4": { - "storageAccountType": "Standard_LRS" - }, - "Standard_A4_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_A4m_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_A5": { - "storageAccountType": "Standard_LRS" - }, - "Standard_A6": { - "storageAccountType": "Standard_LRS" - }, - "Standard_A7": { - "storageAccountType": "Standard_LRS" - }, - "Standard_A8": { - "storageAccountType": "Standard_LRS" - }, - "Standard_A8_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_A8m_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_A9": { - "storageAccountType": "Standard_LRS" - }, - "Standard_B1ms": { - "storageAccountType": "Standard_LRS" - }, - "Standard_B1s": { - "storageAccountType": "Standard_LRS" - }, - "Standard_B2ms": { - "storageAccountType": "Standard_LRS" - }, - "Standard_B2s": { - "storageAccountType": "Standard_LRS" - }, - "Standard_B4ms": { - "storageAccountType": "Standard_LRS" - }, - "Standard_B8ms": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D1": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D11": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D11_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D11_v2_Promo": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D12": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D12_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D12_v2_Promo": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D13": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D13_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D13_v2_Promo": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D14": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D14_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D14_v2_Promo": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D15_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D16_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D16s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D1_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D2_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D2_v2_Promo": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D2_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D2s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D32_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D32s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D3_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D3_v2_Promo": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D4": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D4_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D4_v2_Promo": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D4_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D4s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D5_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D5_v2_Promo": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D64_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D64s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D8_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_D8s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DC2s": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DC4s": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS1": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS11": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS11-1_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS11_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS11_v2_Promo": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS12": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS12-1_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS12-2_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS12_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS12_v2_Promo": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS13": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS13-2_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS13-4_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS13_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS13_v2_Promo": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS14": { - "storageAccountType": "Standard_LRS" }, - "Standard_DS14-4_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS14-8_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS14_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS14_v2_Promo": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS15_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS1_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS2_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS2_v2_Promo": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS3_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS3_v2_Promo": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS4": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS4_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS4_v2_Promo": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS5_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_DS5_v2_Promo": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E16-4s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E16-8s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E16_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E16s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E20_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E20s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E2_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E2s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E32-16s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E32-8s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E32_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E32s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E4-2s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E4_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E4s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E64-16s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E64-32s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E64_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E64i_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E64is_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E64s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E8-2s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E8-4s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E8_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_E8s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_F1": { - "storageAccountType": "Standard_LRS" - }, - "Standard_F16": { - "storageAccountType": "Standard_LRS" - }, - "Standard_F16s": { - "storageAccountType": "Standard_LRS" - }, - "Standard_F16s_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_F1s": { - "storageAccountType": "Standard_LRS" - }, - "Standard_F2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_F2s": { - "storageAccountType": "Standard_LRS" - }, - "Standard_F2s_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_F32s_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_F4": { - "storageAccountType": "Standard_LRS" - }, - "Standard_F4s": { - "storageAccountType": "Standard_LRS" - }, - "Standard_F4s_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_F64s_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_F72s_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_F8": { - "storageAccountType": "Standard_LRS" - }, - "Standard_F8s": { - "storageAccountType": "Standard_LRS" - }, - "Standard_F8s_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_G1": { - "storageAccountType": "Standard_LRS" - }, - "Standard_G2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_G3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_G4": { - "storageAccountType": "Standard_LRS" - }, - "Standard_G5": { - "storageAccountType": "Standard_LRS" - }, - "Standard_GS1": { - "storageAccountType": "Standard_LRS" - }, - "Standard_GS2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_GS3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_GS4": { - "storageAccountType": "Standard_LRS" - }, - "Standard_GS4-4": { - "storageAccountType": "Standard_LRS" - }, - "Standard_GS4-8": { - "storageAccountType": "Standard_LRS" - }, - "Standard_GS5": { - "storageAccountType": "Standard_LRS" - }, - "Standard_GS5-16": { - "storageAccountType": "Standard_LRS" - }, - "Standard_GS5-8": { - "storageAccountType": "Standard_LRS" - }, - "Standard_H16": { - "storageAccountType": "Standard_LRS" - }, - "Standard_H16m": { - "storageAccountType": "Standard_LRS" - }, - "Standard_H16mr": { - "storageAccountType": "Standard_LRS" - }, - "Standard_H16r": { - "storageAccountType": "Standard_LRS" - }, - "Standard_H8": { - "storageAccountType": "Standard_LRS" - }, - "Standard_H8m": { - "storageAccountType": "Standard_LRS" - }, - "Standard_L16s": { - "storageAccountType": "Standard_LRS" - }, - "Standard_L16s_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_L32s": { - "storageAccountType": "Standard_LRS" - }, - "Standard_L4s": { - "storageAccountType": "Standard_LRS" - }, - "Standard_L8s": { - "storageAccountType": "Standard_LRS" - }, - "Standard_L8s_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M128": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M128-32ms": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M128-64ms": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M128m": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M128ms": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M128s": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M16-4ms": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M16-8ms": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M16ms": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M32-16ms": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M32-8ms": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M32ls": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M32ms": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M32ts": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M64": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M64-16ms": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M64-32ms": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M64ls": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M64m": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M64ms": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M64s": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M8-2ms": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M8-4ms": { - "storageAccountType": "Standard_LRS" - }, - "Standard_M8ms": { - "storageAccountType": "Standard_LRS" - }, - "Standard_NC12": { - "storageAccountType": "Standard_LRS" - }, - "Standard_NC12s_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_NC12s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_NC24": { - "storageAccountType": "Standard_LRS" - }, - "Standard_NC24r": { - "storageAccountType": "Standard_LRS" - }, - "Standard_NC24rs_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_NC24rs_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_NC24s_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_NC24s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_NC6": { - "storageAccountType": "Standard_LRS" - }, - "Standard_NC6s_v2": { - "storageAccountType": "Standard_LRS" - }, - "Standard_NC6s_v3": { - "storageAccountType": "Standard_LRS" - }, - "Standard_ND12s": { - "storageAccountType": "Standard_LRS" - }, - "Standard_ND24rs": { - "storageAccountType": "Standard_LRS" - }, - "Standard_ND24s": { - "storageAccountType": "Standard_LRS" - }, - "Standard_ND6s": { - "storageAccountType": "Standard_LRS" - }, - "Standard_NV12": { - "storageAccountType": "Standard_LRS" - }, - "Standard_NV24": { - "storageAccountType": "Standard_LRS" - }, - "Standard_NV6": { - "storageAccountType": "Standard_LRS" + "Standard_NV6s_v2": { + "storageAccountType": "Premium_LRS" } } ` diff --git a/pkg/helpers/azureconst_test.go b/pkg/helpers/azureconst_test.go new file mode 100644 index 0000000000..deca5b9700 --- /dev/null +++ b/pkg/helpers/azureconst_test.go @@ -0,0 +1,240 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +package helpers + +import ( + "strings" + "testing" +) + +func TestKubernetesAllowedSizes(t *testing.T) { + sizes := GetKubernetesAllowedSizes() + if len(sizes) == 0 { + t.Errorf("expected GetKubernetesAllowedSizes to return a non empty string") + } + + expectedSizes := []string{ + "Standard_A0", + "Standard_A1", + "Standard_A10", + "Standard_A11", + "Standard_A1_v2", + "Standard_A2", + "Standard_A2_v2", + "Standard_A2m_v2", + "Standard_A3", + "Standard_A4", + "Standard_A4_v2", + "Standard_A4m_v2", + "Standard_A5", + "Standard_A6", + "Standard_A7", + "Standard_A8", + "Standard_A8_v2", + "Standard_A8m_v2", + "Standard_A9", + "Standard_B1ms", + "Standard_B1s", + "Standard_B2ms", + "Standard_B2s", + "Standard_B4ms", + "Standard_B8ms", + "Standard_D1", + "Standard_D11", + "Standard_D11_v2", + "Standard_D11_v2_Promo", + "Standard_D12", + "Standard_D12_v2", + "Standard_D12_v2_Promo", + "Standard_D13", + "Standard_D13_v2", + "Standard_D13_v2_Promo", + "Standard_D14", + "Standard_D14_v2", + "Standard_D14_v2_Promo", + "Standard_D15_v2", + "Standard_D16_v3", + "Standard_D16s_v3", + "Standard_D1_v2", + "Standard_D2", + "Standard_D2_v2", + "Standard_D2_v2_Promo", + "Standard_D2_v3", + "Standard_D2s_v3", + "Standard_D3", + "Standard_D32_v3", + "Standard_D32s_v3", + "Standard_D3_v2", + "Standard_D3_v2_Promo", + "Standard_D4", + "Standard_D4_v2", + "Standard_D4_v2_Promo", + "Standard_D4_v3", + "Standard_D4s_v3", + "Standard_D5_v2", + "Standard_D5_v2_Promo", + "Standard_D64_v3", + "Standard_D64s_v3", + "Standard_D8_v3", + "Standard_D8s_v3", + "Standard_DC2s", + "Standard_DC4s", + "Standard_DS1", + "Standard_DS11", + "Standard_DS11-1_v2", + "Standard_DS11_v2", + "Standard_DS11_v2_Promo", + "Standard_DS12", + "Standard_DS12-1_v2", + "Standard_DS12-2_v2", + "Standard_DS12_v2", + "Standard_DS12_v2_Promo", + "Standard_DS13", + "Standard_DS13-2_v2", + "Standard_DS13-4_v2", + "Standard_DS13_v2", + "Standard_DS13_v2_Promo", + "Standard_DS14", + "Standard_DS14-4_v2", + "Standard_DS14-8_v2", + "Standard_DS14_v2", + "Standard_DS14_v2_Promo", + "Standard_DS15_v2", + "Standard_DS1_v2", + "Standard_DS2", + "Standard_DS2_v2", + "Standard_DS2_v2_Promo", + "Standard_DS3", + "Standard_DS3_v2", + "Standard_DS3_v2_Promo", + "Standard_DS4", + "Standard_DS4_v2", + "Standard_DS4_v2_Promo", + "Standard_DS5_v2", + "Standard_DS5_v2_Promo", + "Standard_E16-4s_v3", + "Standard_E16-8s_v3", + "Standard_E16_v3", + "Standard_E16s_v3", + "Standard_E20_v3", + "Standard_E20s_v3", + "Standard_E2_v3", + "Standard_E2s_v3", + "Standard_E32-16s_v3", + "Standard_E32-8s_v3", + "Standard_E32_v3", + "Standard_E32s_v3", + "Standard_E4-2s_v3", + "Standard_E4_v3", + "Standard_E4s_v3", + "Standard_E64-16s_v3", + "Standard_E64-32s_v3", + "Standard_E64_v3", + "Standard_E64i_v3", + "Standard_E64is_v3", + "Standard_E64s_v3", + "Standard_E8-2s_v3", + "Standard_E8-4s_v3", + "Standard_E8_v3", + "Standard_E8s_v3", + "Standard_F1", + "Standard_F16", + "Standard_F16s", + "Standard_F16s_v2", + "Standard_F1s", + "Standard_F2", + "Standard_F2s", + "Standard_F2s_v2", + "Standard_F32s_v2", + "Standard_F4", + "Standard_F4s", + "Standard_F4s_v2", + "Standard_F64s_v2", + "Standard_F72s_v2", + "Standard_F8", + "Standard_F8s", + "Standard_F8s_v2", + "Standard_G1", + "Standard_G2", + "Standard_G3", + "Standard_G4", + "Standard_G5", + "Standard_GS1", + "Standard_GS2", + "Standard_GS3", + "Standard_GS4", + "Standard_GS4-4", + "Standard_GS4-8", + "Standard_GS5", + "Standard_GS5-16", + "Standard_GS5-8", + "Standard_H16", + "Standard_H16m", + "Standard_H16mr", + "Standard_H16r", + "Standard_H8", + "Standard_H8m", + "Standard_L16s", + "Standard_L16s_v2", + "Standard_L32s", + "Standard_L32s_v2", + "Standard_L4s", + "Standard_L64s_v2", + "Standard_L80s_v2", + "Standard_L8s", + "Standard_L8s_v2", + "Standard_M128", + "Standard_M128-32ms", + "Standard_M128-64ms", + "Standard_M128m", + "Standard_M128ms", + "Standard_M128s", + "Standard_M16-4ms", + "Standard_M16-8ms", + "Standard_M16ms", + "Standard_M32-16ms", + "Standard_M32-8ms", + "Standard_M32ls", + "Standard_M32ms", + "Standard_M32ts", + "Standard_M64", + "Standard_M64-16ms", + "Standard_M64-32ms", + "Standard_M64ls", + "Standard_M64m", + "Standard_M64ms", + "Standard_M64s", + "Standard_M8-2ms", + "Standard_M8-4ms", + "Standard_M8ms", + "Standard_NC12", + "Standard_NC12s_v2", + "Standard_NC12s_v3", + "Standard_NC24", + "Standard_NC24r", + "Standard_NC24rs_v2", + "Standard_NC24rs_v3", + "Standard_NC24s_v2", + "Standard_NC24s_v3", + "Standard_NC6", + "Standard_NC6s_v2", + "Standard_NC6s_v3", + "Standard_ND12s", + "Standard_ND24rs", + "Standard_ND24s", + "Standard_ND6s", + "Standard_NV12", + "Standard_NV12s_v2", + "Standard_NV24", + "Standard_NV24s_v2", + "Standard_NV6", + "Standard_NV6s_v2", + } + + for _, expectedSize := range expectedSizes { + if !strings.Contains(sizes, expectedSize) { + t.Errorf("expected %s to be present in the list of allowedValues", expectedSize) + } + } +} From d47404fd21dae23340e8d04a9636c095201e6ba0 Mon Sep 17 00:00:00 2001 From: Cecile Robert-Michon Date: Mon, 19 Nov 2018 14:58:23 -0800 Subject: [PATCH 16/29] fix retrycmd_if_failure: $retries should be $r (#40) --- parts/k8s/kubernetesagentresourcesvmas.tmpl | 2 +- parts/k8s/kubernetesagentresourcesvmss.tmpl | 2 +- parts/k8s/kubernetesmasterresources.tmpl | 2 +- parts/k8s/kubernetesmasterresourcesvmss.tmpl | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/parts/k8s/kubernetesagentresourcesvmas.tmpl b/parts/k8s/kubernetesagentresourcesvmas.tmpl index 52b0912cc6..843d0da877 100644 --- a/parts/k8s/kubernetesagentresourcesvmas.tmpl +++ b/parts/k8s/kubernetesagentresourcesvmas.tmpl @@ -295,7 +295,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $retries); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not BlockOutboundInternet}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}gcr.azk8s.cn 80{{else}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' GPU_NODE={{IsNSeriesSKU .}} /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1{{if CSERunInBackground }} &{{end}}\"')]" + "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $r); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not BlockOutboundInternet}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}gcr.azk8s.cn 80{{else}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' GPU_NODE={{IsNSeriesSKU .}} /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1{{if CSERunInBackground }} &{{end}}\"')]" } } } diff --git a/parts/k8s/kubernetesagentresourcesvmss.tmpl b/parts/k8s/kubernetesagentresourcesvmss.tmpl index 3ab17f10cd..42c422373c 100644 --- a/parts/k8s/kubernetesagentresourcesvmss.tmpl +++ b/parts/k8s/kubernetesagentresourcesvmss.tmpl @@ -155,7 +155,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $retries); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not BlockOutboundInternet}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}gcr.azk8s.cn 80{{else}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' GPU_NODE={{IsNSeriesSKU .}} /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1{{if CSERunInBackground }} &{{end}}\"')]" + "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $r); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not BlockOutboundInternet}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}gcr.azk8s.cn 80{{else}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' GPU_NODE={{IsNSeriesSKU .}} /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1{{if CSERunInBackground }} &{{end}}\"')]" } } } diff --git a/parts/k8s/kubernetesmasterresources.tmpl b/parts/k8s/kubernetesmasterresources.tmpl index d42ebe6245..4d49925a9b 100644 --- a/parts/k8s/kubernetesmasterresources.tmpl +++ b/parts/k8s/kubernetesmasterresources.tmpl @@ -929,7 +929,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $retries); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not BlockOutboundInternet}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}gcr.azk8s.cn 80{{else}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' ',variables('provisionScriptParametersMaster'), ' /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1\"')]" + "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $r); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not BlockOutboundInternet}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}gcr.azk8s.cn 80{{else}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' ',variables('provisionScriptParametersMaster'), ' /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1\"')]" } } } diff --git a/parts/k8s/kubernetesmasterresourcesvmss.tmpl b/parts/k8s/kubernetesmasterresourcesvmss.tmpl index 779d62a651..3f610d2ef9 100644 --- a/parts/k8s/kubernetesmasterresourcesvmss.tmpl +++ b/parts/k8s/kubernetesmasterresourcesvmss.tmpl @@ -461,7 +461,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $retries); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not BlockOutboundInternet}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' ',variables('provisionScriptParametersMaster'), ' /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1\"')]" + "commandToExecute": "[concat('retrycmd_if_failure() { r=$1; w=$2; t=$3; shift && shift && shift; for i in $(seq 1 $r); do timeout $t ${@}; [ $? -eq 0 ] && break || if [ $i -eq $r ]; then return 1; else sleep $w; fi; done };{{if not BlockOutboundInternet}} ERR_OUTBOUND_CONN_FAIL=50; retrycmd_if_failure 150 1 3 nc -vz {{if IsMooncake}}k8s.gcr.io 443 && nc -vz gcr.io 443 && nc -vz docker.io 443{{end}} || exit $ERR_OUTBOUND_CONN_FAIL;{{end}} for i in $(seq 1 1200); do if [ -f /opt/azure/containers/provision.sh ]; then break; fi; if [ $i -eq 1200 ]; then exit 100; else sleep 1; fi; done; ', variables('provisionScriptParametersCommon'),' ',variables('provisionScriptParametersMaster'), ' /usr/bin/nohup /bin/bash -c \"/bin/bash /opt/azure/containers/provision.sh >> /var/log/azure/cluster-provision.log 2>&1\"')]" } } } From 686998c24b06a474f9b4b84b883ce15ee7555d7f Mon Sep 17 00:00:00 2001 From: Tariq Ibrahim Date: Tue, 20 Nov 2018 09:07:24 -0800 Subject: [PATCH 17/29] add support PB6 vm skus (#42) --- pkg/helpers/azureconst.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pkg/helpers/azureconst.go b/pkg/helpers/azureconst.go index 247aebe782..0126a16308 100644 --- a/pkg/helpers/azureconst.go +++ b/pkg/helpers/azureconst.go @@ -277,7 +277,10 @@ func GetKubernetesAllowedSizes() string { "Standard_NV24", "Standard_NV24s_v2", "Standard_NV6", - "Standard_NV6s_v2" + "Standard_NV6s_v2", + "Standard_PB12s", + "Standard_PB24s", + "Standard_PB6s" ], ` } @@ -929,6 +932,15 @@ func GetSizeMap() string { }, "Standard_NV6s_v2": { "storageAccountType": "Premium_LRS" + }, + "Standard_PB12s": { + "storageAccountType": "Premium_LRS" + }, + "Standard_PB24s": { + "storageAccountType": "Premium_LRS" + }, + "Standard_PB6s": { + "storageAccountType": "Premium_LRS" } } ` From f0c0fe2a8da35cb013acb13838a5bf9070581d2b Mon Sep 17 00:00:00 2001 From: Matt Boersma Date: Tue, 20 Nov 2018 11:28:33 -0700 Subject: [PATCH 18/29] Prune non-go files from vendoring (#43) --- Gopkg.lock | 218 +- Gopkg.toml | 1 + pkg/api/defaults_test.go | 10 +- .../Azure/azure-sdk-for-go/storage/README.md | 22 - .../Azure/go-autorest/autorest/adal/README.md | 292 - vendor/github.com/Jeffail/gabs/README.md | 284 - vendor/github.com/Jeffail/gabs/gabs_logo.png | Bin 56959 -> 0 bytes .../github.com/alexcesaro/statsd/.travis.yml | 9 - .../github.com/alexcesaro/statsd/CHANGELOG.md | 64 - vendor/github.com/alexcesaro/statsd/README.md | 50 - vendor/github.com/blang/semver/.travis.yml | 21 - vendor/github.com/blang/semver/README.md | 194 - vendor/github.com/blang/semver/package.json | 17 - vendor/github.com/dgrijalva/jwt-go/.gitignore | 4 - .../github.com/dgrijalva/jwt-go/.travis.yml | 13 - .../dgrijalva/jwt-go/MIGRATION_GUIDE.md | 97 - vendor/github.com/dgrijalva/jwt-go/README.md | 85 - .../dgrijalva/jwt-go/VERSION_HISTORY.md | 111 - vendor/github.com/ghodss/yaml/.gitignore | 20 - vendor/github.com/ghodss/yaml/.travis.yml | 7 - vendor/github.com/ghodss/yaml/README.md | 121 - .../go-bindata/go-bindata/CONTRIBUTING.md | 79 - .../github.com/go-bindata/go-bindata/Makefile | 2 - .../go-bindata/go-bindata/README.md | 191 - .../go-playground/locales/.gitignore | 24 - .../go-playground/locales/README.md | 172 - .../github.com/go-playground/locales/logo.png | Bin 37360 -> 0 bytes .../universal-translator/.gitignore | 24 - .../universal-translator/README.md | 90 - .../universal-translator/logo.png | Bin 16598 -> 0 bytes .../github.com/gogo/protobuf/proto/Makefile | 43 - vendor/github.com/golang/glog/README | 44 - .../github.com/golang/protobuf/proto/Makefile | 43 - .../golang/protobuf/ptypes/any/any.proto | 149 - .../protobuf/ptypes/duration/duration.proto | 117 - .../golang/protobuf/ptypes/regen.sh | 43 - .../protobuf/ptypes/timestamp/timestamp.proto | 133 - vendor/github.com/google/btree/.travis.yml | 1 - vendor/github.com/google/btree/README.md | 12 - vendor/github.com/google/gofuzz/.travis.yml | 13 - .../github.com/google/gofuzz/CONTRIBUTING.md | 67 - vendor/github.com/google/gofuzz/README.md | 71 - .../gnostic/OpenAPIv2/OpenAPIv2.proto | 663 --- .../googleapis/gnostic/OpenAPIv2/README.md | 16 - .../gnostic/OpenAPIv2/openapi-2.0.json | 1610 ------ .../googleapis/gnostic/compiler/README.md | 3 - .../gnostic/extensions/COMPILE-EXTENSION.sh | 5 - .../googleapis/gnostic/extensions/README.md | 5 - .../gnostic/extensions/extension.proto | 93 - .../gregjones/httpcache/.travis.yml | 19 - .../github.com/gregjones/httpcache/README.md | 25 - vendor/github.com/hpcloud/tail/.gitignore | 3 - vendor/github.com/hpcloud/tail/.travis.yml | 18 - vendor/github.com/hpcloud/tail/CHANGES.md | 63 - vendor/github.com/hpcloud/tail/Dockerfile | 19 - vendor/github.com/hpcloud/tail/Makefile | 11 - vendor/github.com/hpcloud/tail/README.md | 28 - vendor/github.com/hpcloud/tail/appveyor.yml | 11 - vendor/github.com/imdario/mergo/.gitignore | 33 - vendor/github.com/imdario/mergo/.travis.yml | 7 - .../imdario/mergo/CODE_OF_CONDUCT.md | 46 - vendor/github.com/imdario/mergo/README.md | 222 - .../inconshreveable/mousetrap/README.md | 23 - .../github.com/json-iterator/go/.codecov.yml | 3 - vendor/github.com/json-iterator/go/.gitignore | 4 - .../github.com/json-iterator/go/.travis.yml | 14 - vendor/github.com/json-iterator/go/Gopkg.lock | 21 - vendor/github.com/json-iterator/go/Gopkg.toml | 26 - vendor/github.com/json-iterator/go/README.md | 91 - vendor/github.com/json-iterator/go/build.sh | 12 - .../go/fuzzy_mode_convert_table.md | 7 - vendor/github.com/json-iterator/go/test.sh | 12 - .../kelseyhightower/envconfig/.travis.yml | 10 - .../kelseyhightower/envconfig/MAINTAINERS | 2 - .../kelseyhightower/envconfig/README.md | 188 - .../leonelquinteros/gotext/.gitignore | 29 - .../leonelquinteros/gotext/.travis.yml | 16 - .../leonelquinteros/gotext/Gopkg.lock | 15 - .../leonelquinteros/gotext/Gopkg.toml | 26 - .../leonelquinteros/gotext/README.md | 290 - vendor/github.com/marstr/guid/.travis.yml | 18 - vendor/github.com/marstr/guid/README.md | 27 - .../github.com/mattn/go-colorable/.travis.yml | 9 - .../github.com/mattn/go-colorable/README.md | 48 - vendor/github.com/mattn/go-isatty/.travis.yml | 13 - vendor/github.com/mattn/go-isatty/README.md | 50 - .../github.com/mattn/kinako/parser/Makefile | 4 - .../mattn/kinako/parser/parser.go.y | 214 - .../github.com/mattn/kinako/parser/y.output | 1381 ----- .../github.com/mitchellh/go-homedir/README.md | 14 - .../modern-go/concurrent/.gitignore | 1 - .../modern-go/concurrent/.travis.yml | 14 - .../github.com/modern-go/concurrent/README.md | 49 - .../github.com/modern-go/concurrent/test.sh | 12 - .../github.com/modern-go/reflect2/.gitignore | 2 - .../github.com/modern-go/reflect2/.travis.yml | 15 - .../github.com/modern-go/reflect2/Gopkg.lock | 15 - .../github.com/modern-go/reflect2/Gopkg.toml | 35 - .../github.com/modern-go/reflect2/README.md | 71 - vendor/github.com/modern-go/reflect2/test.sh | 12 - vendor/github.com/onsi/ginkgo/.gitignore | 7 - vendor/github.com/onsi/ginkgo/.travis.yml | 16 - vendor/github.com/onsi/ginkgo/CHANGELOG.md | 198 - vendor/github.com/onsi/ginkgo/CONTRIBUTING.md | 33 - vendor/github.com/onsi/ginkgo/README.md | 121 - vendor/github.com/onsi/ginkgo/RELEASING.md | 14 - .../support/go-colorable/README.md | 43 - .../stenographer/support/go-isatty/README.md | 37 - vendor/github.com/onsi/gomega/.gitignore | 5 - vendor/github.com/onsi/gomega/.travis.yml | 12 - vendor/github.com/onsi/gomega/CHANGELOG.md | 74 - vendor/github.com/onsi/gomega/CONTRIBUTING.md | 11 - vendor/github.com/onsi/gomega/README.md | 21 - .../github.com/peterbourgon/diskv/README.md | 141 - vendor/github.com/pkg/errors/.gitignore | 24 - vendor/github.com/pkg/errors/.travis.yml | 11 - vendor/github.com/pkg/errors/README.md | 52 - vendor/github.com/pkg/errors/appveyor.yml | 32 - vendor/github.com/satori/go.uuid/.travis.yml | 23 - vendor/github.com/satori/go.uuid/README.md | 65 - vendor/github.com/sirupsen/logrus/.gitignore | 1 - vendor/github.com/sirupsen/logrus/.travis.yml | 15 - .../github.com/sirupsen/logrus/CHANGELOG.md | 113 - vendor/github.com/sirupsen/logrus/README.md | 505 -- .../github.com/sirupsen/logrus/appveyor.yml | 14 - vendor/github.com/spf13/cobra/.gitignore | 36 - vendor/github.com/spf13/cobra/.mailmap | 3 - vendor/github.com/spf13/cobra/.travis.yml | 21 - vendor/github.com/spf13/cobra/README.md | 887 --- .../spf13/cobra/bash_completions.md | 206 - vendor/github.com/spf13/pflag/.gitignore | 2 - vendor/github.com/spf13/pflag/.travis.yml | 21 - vendor/github.com/spf13/pflag/README.md | 296 - vendor/golang.org/x/net/http2/.gitignore | 2 - vendor/golang.org/x/net/http2/Dockerfile | 51 - vendor/golang.org/x/net/http2/Makefile | 3 - vendor/golang.org/x/net/http2/README | 20 - vendor/golang.org/x/oauth2/.travis.yml | 13 - vendor/golang.org/x/oauth2/CONTRIBUTING.md | 26 - vendor/golang.org/x/oauth2/README.md | 77 - vendor/golang.org/x/sys/unix/.gitignore | 1 - vendor/golang.org/x/sys/unix/README.md | 173 - vendor/golang.org/x/sys/unix/mkall.sh | 194 - vendor/golang.org/x/sys/unix/mkerrors.sh | 569 -- vendor/golang.org/x/sys/unix/mksyscall.pl | 328 -- .../x/sys/unix/mksyscall_solaris.pl | 289 - .../golang.org/x/sys/unix/mksysctl_openbsd.pl | 264 - .../golang.org/x/sys/unix/mksysnum_darwin.pl | 39 - .../x/sys/unix/mksysnum_dragonfly.pl | 50 - .../golang.org/x/sys/unix/mksysnum_freebsd.pl | 50 - .../golang.org/x/sys/unix/mksysnum_netbsd.pl | 58 - .../golang.org/x/sys/unix/mksysnum_openbsd.pl | 50 - vendor/golang.org/x/text/language/Makefile | 16 - .../appengine/internal/base/api_base.proto | 33 - .../internal/datastore/datastore_v3.proto | 551 -- .../appengine/internal/log/log_service.proto | 150 - .../appengine/internal/regen.sh | 40 - .../internal/remote_api/remote_api.proto | 44 - .../internal/urlfetch/urlfetch_service.proto | 64 - vendor/gopkg.in/fsnotify.v1/.editorconfig | 5 - vendor/gopkg.in/fsnotify.v1/.gitignore | 6 - vendor/gopkg.in/fsnotify.v1/.travis.yml | 30 - vendor/gopkg.in/fsnotify.v1/CHANGELOG.md | 317 -- vendor/gopkg.in/fsnotify.v1/CONTRIBUTING.md | 77 - vendor/gopkg.in/fsnotify.v1/README.md | 79 - .../go-playground/validator.v9/.gitignore | 29 - .../go-playground/validator.v9/README.md | 139 - .../go-playground/validator.v9/logo.png | Bin 13443 -> 0 bytes vendor/gopkg.in/ini.v1/.gitignore | 6 - vendor/gopkg.in/ini.v1/.travis.yml | 16 - vendor/gopkg.in/ini.v1/Makefile | 15 - vendor/gopkg.in/ini.v1/README.md | 44 - vendor/gopkg.in/tomb.v1/README.md | 4 - vendor/gopkg.in/yaml.v2/.travis.yml | 9 - vendor/gopkg.in/yaml.v2/README.md | 135 - .../v1alpha1/generated.proto | 107 - .../v1beta1/generated.proto | 269 - vendor/k8s.io/api/apps/v1/generated.proto | 701 --- .../k8s.io/api/apps/v1beta1/generated.proto | 484 -- .../k8s.io/api/apps/v1beta2/generated.proto | 752 --- .../api/authentication/v1/generated.proto | 159 - .../authentication/v1beta1/generated.proto | 98 - .../api/authorization/v1/generated.proto | 272 - .../api/authorization/v1beta1/generated.proto | 272 - .../k8s.io/api/autoscaling/v1/generated.proto | 415 -- .../api/autoscaling/v2beta1/generated.proto | 397 -- .../api/autoscaling/v2beta2/generated.proto | 369 -- vendor/k8s.io/api/batch/v1/generated.proto | 184 - .../k8s.io/api/batch/v1beta1/generated.proto | 137 - .../k8s.io/api/batch/v2alpha1/generated.proto | 135 - .../api/certificates/v1beta1/generated.proto | 121 - .../api/coordination/v1beta1/generated.proto | 80 - vendor/k8s.io/api/core/v1/generated.proto | 4765 ----------------- .../k8s.io/api/events/v1beta1/generated.proto | 121 - .../api/extensions/v1beta1/generated.proto | 1160 ---- .../k8s.io/api/networking/v1/generated.proto | 195 - .../k8s.io/api/policy/v1beta1/generated.proto | 367 -- vendor/k8s.io/api/rbac/v1/generated.proto | 197 - .../k8s.io/api/rbac/v1alpha1/generated.proto | 199 - .../k8s.io/api/rbac/v1beta1/generated.proto | 198 - .../api/scheduling/v1alpha1/generated.proto | 67 - .../api/scheduling/v1beta1/generated.proto | 67 - .../api/settings/v1alpha1/generated.proto | 75 - vendor/k8s.io/api/storage/v1/generated.proto | 90 - .../api/storage/v1alpha1/generated.proto | 126 - .../api/storage/v1beta1/generated.proto | 186 - .../k8s.io/apimachinery/pkg/api/errors/OWNERS | 24 - .../k8s.io/apimachinery/pkg/api/meta/OWNERS | 25 - .../apimachinery/pkg/api/resource/OWNERS | 16 - .../pkg/api/resource/generated.proto | 88 - .../apimachinery/pkg/apis/meta/v1/OWNERS | 31 - .../pkg/apis/meta/v1/generated.proto | 879 --- .../pkg/apis/meta/v1beta1/generated.proto | 57 - .../apimachinery/pkg/runtime/generated.proto | 127 - .../pkg/runtime/schema/generated.proto | 26 - .../pkg/util/intstr/generated.proto | 43 - .../client-go/pkg/version/.gitattributes | 1 - vendor/k8s.io/client-go/pkg/version/def.bzl | 38 - vendor/k8s.io/client-go/rest/OWNERS | 24 - vendor/k8s.io/client-go/tools/metrics/OWNERS | 7 - vendor/k8s.io/client-go/transport/OWNERS | 7 - 221 files changed, 116 insertions(+), 29819 deletions(-) delete mode 100644 vendor/github.com/Azure/azure-sdk-for-go/storage/README.md delete mode 100644 vendor/github.com/Azure/go-autorest/autorest/adal/README.md delete mode 100644 vendor/github.com/Jeffail/gabs/README.md delete mode 100644 vendor/github.com/Jeffail/gabs/gabs_logo.png delete mode 100644 vendor/github.com/alexcesaro/statsd/.travis.yml delete mode 100644 vendor/github.com/alexcesaro/statsd/CHANGELOG.md delete mode 100644 vendor/github.com/alexcesaro/statsd/README.md delete mode 100644 vendor/github.com/blang/semver/.travis.yml delete mode 100644 vendor/github.com/blang/semver/README.md delete mode 100644 vendor/github.com/blang/semver/package.json delete mode 100644 vendor/github.com/dgrijalva/jwt-go/.gitignore delete mode 100644 vendor/github.com/dgrijalva/jwt-go/.travis.yml delete mode 100644 vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md delete mode 100644 vendor/github.com/dgrijalva/jwt-go/README.md delete mode 100644 vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md delete mode 100644 vendor/github.com/ghodss/yaml/.gitignore delete mode 100644 vendor/github.com/ghodss/yaml/.travis.yml delete mode 100644 vendor/github.com/ghodss/yaml/README.md delete mode 100644 vendor/github.com/go-bindata/go-bindata/CONTRIBUTING.md delete mode 100644 vendor/github.com/go-bindata/go-bindata/Makefile delete mode 100644 vendor/github.com/go-bindata/go-bindata/README.md delete mode 100644 vendor/github.com/go-playground/locales/.gitignore delete mode 100644 vendor/github.com/go-playground/locales/README.md delete mode 100644 vendor/github.com/go-playground/locales/logo.png delete mode 100644 vendor/github.com/go-playground/universal-translator/.gitignore delete mode 100644 vendor/github.com/go-playground/universal-translator/README.md delete mode 100644 vendor/github.com/go-playground/universal-translator/logo.png delete mode 100644 vendor/github.com/gogo/protobuf/proto/Makefile delete mode 100644 vendor/github.com/golang/glog/README delete mode 100644 vendor/github.com/golang/protobuf/proto/Makefile delete mode 100644 vendor/github.com/golang/protobuf/ptypes/any/any.proto delete mode 100644 vendor/github.com/golang/protobuf/ptypes/duration/duration.proto delete mode 100755 vendor/github.com/golang/protobuf/ptypes/regen.sh delete mode 100644 vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto delete mode 100644 vendor/github.com/google/btree/.travis.yml delete mode 100644 vendor/github.com/google/btree/README.md delete mode 100644 vendor/github.com/google/gofuzz/.travis.yml delete mode 100644 vendor/github.com/google/gofuzz/CONTRIBUTING.md delete mode 100644 vendor/github.com/google/gofuzz/README.md delete mode 100644 vendor/github.com/googleapis/gnostic/OpenAPIv2/OpenAPIv2.proto delete mode 100644 vendor/github.com/googleapis/gnostic/OpenAPIv2/README.md delete mode 100644 vendor/github.com/googleapis/gnostic/OpenAPIv2/openapi-2.0.json delete mode 100644 vendor/github.com/googleapis/gnostic/compiler/README.md delete mode 100755 vendor/github.com/googleapis/gnostic/extensions/COMPILE-EXTENSION.sh delete mode 100644 vendor/github.com/googleapis/gnostic/extensions/README.md delete mode 100644 vendor/github.com/googleapis/gnostic/extensions/extension.proto delete mode 100644 vendor/github.com/gregjones/httpcache/.travis.yml delete mode 100644 vendor/github.com/gregjones/httpcache/README.md delete mode 100644 vendor/github.com/hpcloud/tail/.gitignore delete mode 100644 vendor/github.com/hpcloud/tail/.travis.yml delete mode 100644 vendor/github.com/hpcloud/tail/CHANGES.md delete mode 100644 vendor/github.com/hpcloud/tail/Dockerfile delete mode 100644 vendor/github.com/hpcloud/tail/Makefile delete mode 100644 vendor/github.com/hpcloud/tail/README.md delete mode 100644 vendor/github.com/hpcloud/tail/appveyor.yml delete mode 100644 vendor/github.com/imdario/mergo/.gitignore delete mode 100644 vendor/github.com/imdario/mergo/.travis.yml delete mode 100644 vendor/github.com/imdario/mergo/CODE_OF_CONDUCT.md delete mode 100644 vendor/github.com/imdario/mergo/README.md delete mode 100644 vendor/github.com/inconshreveable/mousetrap/README.md delete mode 100644 vendor/github.com/json-iterator/go/.codecov.yml delete mode 100644 vendor/github.com/json-iterator/go/.gitignore delete mode 100644 vendor/github.com/json-iterator/go/.travis.yml delete mode 100644 vendor/github.com/json-iterator/go/Gopkg.lock delete mode 100644 vendor/github.com/json-iterator/go/Gopkg.toml delete mode 100644 vendor/github.com/json-iterator/go/README.md delete mode 100755 vendor/github.com/json-iterator/go/build.sh delete mode 100644 vendor/github.com/json-iterator/go/fuzzy_mode_convert_table.md delete mode 100755 vendor/github.com/json-iterator/go/test.sh delete mode 100644 vendor/github.com/kelseyhightower/envconfig/.travis.yml delete mode 100644 vendor/github.com/kelseyhightower/envconfig/MAINTAINERS delete mode 100644 vendor/github.com/kelseyhightower/envconfig/README.md delete mode 100644 vendor/github.com/leonelquinteros/gotext/.gitignore delete mode 100644 vendor/github.com/leonelquinteros/gotext/.travis.yml delete mode 100644 vendor/github.com/leonelquinteros/gotext/Gopkg.lock delete mode 100644 vendor/github.com/leonelquinteros/gotext/Gopkg.toml delete mode 100644 vendor/github.com/leonelquinteros/gotext/README.md delete mode 100644 vendor/github.com/marstr/guid/.travis.yml delete mode 100644 vendor/github.com/marstr/guid/README.md delete mode 100644 vendor/github.com/mattn/go-colorable/.travis.yml delete mode 100644 vendor/github.com/mattn/go-colorable/README.md delete mode 100644 vendor/github.com/mattn/go-isatty/.travis.yml delete mode 100644 vendor/github.com/mattn/go-isatty/README.md delete mode 100644 vendor/github.com/mattn/kinako/parser/Makefile delete mode 100644 vendor/github.com/mattn/kinako/parser/parser.go.y delete mode 100644 vendor/github.com/mattn/kinako/parser/y.output delete mode 100644 vendor/github.com/mitchellh/go-homedir/README.md delete mode 100644 vendor/github.com/modern-go/concurrent/.gitignore delete mode 100644 vendor/github.com/modern-go/concurrent/.travis.yml delete mode 100644 vendor/github.com/modern-go/concurrent/README.md delete mode 100755 vendor/github.com/modern-go/concurrent/test.sh delete mode 100644 vendor/github.com/modern-go/reflect2/.gitignore delete mode 100644 vendor/github.com/modern-go/reflect2/.travis.yml delete mode 100644 vendor/github.com/modern-go/reflect2/Gopkg.lock delete mode 100644 vendor/github.com/modern-go/reflect2/Gopkg.toml delete mode 100644 vendor/github.com/modern-go/reflect2/README.md delete mode 100755 vendor/github.com/modern-go/reflect2/test.sh delete mode 100644 vendor/github.com/onsi/ginkgo/.gitignore delete mode 100644 vendor/github.com/onsi/ginkgo/.travis.yml delete mode 100644 vendor/github.com/onsi/ginkgo/CHANGELOG.md delete mode 100644 vendor/github.com/onsi/ginkgo/CONTRIBUTING.md delete mode 100644 vendor/github.com/onsi/ginkgo/README.md delete mode 100644 vendor/github.com/onsi/ginkgo/RELEASING.md delete mode 100644 vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable/README.md delete mode 100644 vendor/github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty/README.md delete mode 100644 vendor/github.com/onsi/gomega/.gitignore delete mode 100644 vendor/github.com/onsi/gomega/.travis.yml delete mode 100644 vendor/github.com/onsi/gomega/CHANGELOG.md delete mode 100644 vendor/github.com/onsi/gomega/CONTRIBUTING.md delete mode 100644 vendor/github.com/onsi/gomega/README.md delete mode 100644 vendor/github.com/peterbourgon/diskv/README.md delete mode 100644 vendor/github.com/pkg/errors/.gitignore delete mode 100644 vendor/github.com/pkg/errors/.travis.yml delete mode 100644 vendor/github.com/pkg/errors/README.md delete mode 100644 vendor/github.com/pkg/errors/appveyor.yml delete mode 100644 vendor/github.com/satori/go.uuid/.travis.yml delete mode 100644 vendor/github.com/satori/go.uuid/README.md delete mode 100644 vendor/github.com/sirupsen/logrus/.gitignore delete mode 100644 vendor/github.com/sirupsen/logrus/.travis.yml delete mode 100644 vendor/github.com/sirupsen/logrus/CHANGELOG.md delete mode 100644 vendor/github.com/sirupsen/logrus/README.md delete mode 100644 vendor/github.com/sirupsen/logrus/appveyor.yml delete mode 100644 vendor/github.com/spf13/cobra/.gitignore delete mode 100644 vendor/github.com/spf13/cobra/.mailmap delete mode 100644 vendor/github.com/spf13/cobra/.travis.yml delete mode 100644 vendor/github.com/spf13/cobra/README.md delete mode 100644 vendor/github.com/spf13/cobra/bash_completions.md delete mode 100644 vendor/github.com/spf13/pflag/.gitignore delete mode 100644 vendor/github.com/spf13/pflag/.travis.yml delete mode 100644 vendor/github.com/spf13/pflag/README.md delete mode 100644 vendor/golang.org/x/net/http2/.gitignore delete mode 100644 vendor/golang.org/x/net/http2/Dockerfile delete mode 100644 vendor/golang.org/x/net/http2/Makefile delete mode 100644 vendor/golang.org/x/net/http2/README delete mode 100644 vendor/golang.org/x/oauth2/.travis.yml delete mode 100644 vendor/golang.org/x/oauth2/CONTRIBUTING.md delete mode 100644 vendor/golang.org/x/oauth2/README.md delete mode 100644 vendor/golang.org/x/sys/unix/.gitignore delete mode 100644 vendor/golang.org/x/sys/unix/README.md delete mode 100755 vendor/golang.org/x/sys/unix/mkall.sh delete mode 100755 vendor/golang.org/x/sys/unix/mkerrors.sh delete mode 100755 vendor/golang.org/x/sys/unix/mksyscall.pl delete mode 100755 vendor/golang.org/x/sys/unix/mksyscall_solaris.pl delete mode 100755 vendor/golang.org/x/sys/unix/mksysctl_openbsd.pl delete mode 100755 vendor/golang.org/x/sys/unix/mksysnum_darwin.pl delete mode 100755 vendor/golang.org/x/sys/unix/mksysnum_dragonfly.pl delete mode 100755 vendor/golang.org/x/sys/unix/mksysnum_freebsd.pl delete mode 100755 vendor/golang.org/x/sys/unix/mksysnum_netbsd.pl delete mode 100755 vendor/golang.org/x/sys/unix/mksysnum_openbsd.pl delete mode 100644 vendor/golang.org/x/text/language/Makefile delete mode 100644 vendor/google.golang.org/appengine/internal/base/api_base.proto delete mode 100755 vendor/google.golang.org/appengine/internal/datastore/datastore_v3.proto delete mode 100644 vendor/google.golang.org/appengine/internal/log/log_service.proto delete mode 100755 vendor/google.golang.org/appengine/internal/regen.sh delete mode 100644 vendor/google.golang.org/appengine/internal/remote_api/remote_api.proto delete mode 100644 vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto delete mode 100644 vendor/gopkg.in/fsnotify.v1/.editorconfig delete mode 100644 vendor/gopkg.in/fsnotify.v1/.gitignore delete mode 100644 vendor/gopkg.in/fsnotify.v1/.travis.yml delete mode 100644 vendor/gopkg.in/fsnotify.v1/CHANGELOG.md delete mode 100644 vendor/gopkg.in/fsnotify.v1/CONTRIBUTING.md delete mode 100644 vendor/gopkg.in/fsnotify.v1/README.md delete mode 100644 vendor/gopkg.in/go-playground/validator.v9/.gitignore delete mode 100644 vendor/gopkg.in/go-playground/validator.v9/README.md delete mode 100644 vendor/gopkg.in/go-playground/validator.v9/logo.png delete mode 100644 vendor/gopkg.in/ini.v1/.gitignore delete mode 100644 vendor/gopkg.in/ini.v1/.travis.yml delete mode 100644 vendor/gopkg.in/ini.v1/Makefile delete mode 100644 vendor/gopkg.in/ini.v1/README.md delete mode 100644 vendor/gopkg.in/tomb.v1/README.md delete mode 100644 vendor/gopkg.in/yaml.v2/.travis.yml delete mode 100644 vendor/gopkg.in/yaml.v2/README.md delete mode 100644 vendor/k8s.io/api/admissionregistration/v1alpha1/generated.proto delete mode 100644 vendor/k8s.io/api/admissionregistration/v1beta1/generated.proto delete mode 100644 vendor/k8s.io/api/apps/v1/generated.proto delete mode 100644 vendor/k8s.io/api/apps/v1beta1/generated.proto delete mode 100644 vendor/k8s.io/api/apps/v1beta2/generated.proto delete mode 100644 vendor/k8s.io/api/authentication/v1/generated.proto delete mode 100644 vendor/k8s.io/api/authentication/v1beta1/generated.proto delete mode 100644 vendor/k8s.io/api/authorization/v1/generated.proto delete mode 100644 vendor/k8s.io/api/authorization/v1beta1/generated.proto delete mode 100644 vendor/k8s.io/api/autoscaling/v1/generated.proto delete mode 100644 vendor/k8s.io/api/autoscaling/v2beta1/generated.proto delete mode 100644 vendor/k8s.io/api/autoscaling/v2beta2/generated.proto delete mode 100644 vendor/k8s.io/api/batch/v1/generated.proto delete mode 100644 vendor/k8s.io/api/batch/v1beta1/generated.proto delete mode 100644 vendor/k8s.io/api/batch/v2alpha1/generated.proto delete mode 100644 vendor/k8s.io/api/certificates/v1beta1/generated.proto delete mode 100644 vendor/k8s.io/api/coordination/v1beta1/generated.proto delete mode 100644 vendor/k8s.io/api/core/v1/generated.proto delete mode 100644 vendor/k8s.io/api/events/v1beta1/generated.proto delete mode 100644 vendor/k8s.io/api/extensions/v1beta1/generated.proto delete mode 100644 vendor/k8s.io/api/networking/v1/generated.proto delete mode 100644 vendor/k8s.io/api/policy/v1beta1/generated.proto delete mode 100644 vendor/k8s.io/api/rbac/v1/generated.proto delete mode 100644 vendor/k8s.io/api/rbac/v1alpha1/generated.proto delete mode 100644 vendor/k8s.io/api/rbac/v1beta1/generated.proto delete mode 100644 vendor/k8s.io/api/scheduling/v1alpha1/generated.proto delete mode 100644 vendor/k8s.io/api/scheduling/v1beta1/generated.proto delete mode 100644 vendor/k8s.io/api/settings/v1alpha1/generated.proto delete mode 100644 vendor/k8s.io/api/storage/v1/generated.proto delete mode 100644 vendor/k8s.io/api/storage/v1alpha1/generated.proto delete mode 100644 vendor/k8s.io/api/storage/v1beta1/generated.proto delete mode 100755 vendor/k8s.io/apimachinery/pkg/api/errors/OWNERS delete mode 100755 vendor/k8s.io/apimachinery/pkg/api/meta/OWNERS delete mode 100755 vendor/k8s.io/apimachinery/pkg/api/resource/OWNERS delete mode 100644 vendor/k8s.io/apimachinery/pkg/api/resource/generated.proto delete mode 100755 vendor/k8s.io/apimachinery/pkg/apis/meta/v1/OWNERS delete mode 100644 vendor/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto delete mode 100644 vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.proto delete mode 100644 vendor/k8s.io/apimachinery/pkg/runtime/generated.proto delete mode 100644 vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.proto delete mode 100644 vendor/k8s.io/apimachinery/pkg/util/intstr/generated.proto delete mode 100644 vendor/k8s.io/client-go/pkg/version/.gitattributes delete mode 100644 vendor/k8s.io/client-go/pkg/version/def.bzl delete mode 100755 vendor/k8s.io/client-go/rest/OWNERS delete mode 100755 vendor/k8s.io/client-go/tools/metrics/OWNERS delete mode 100755 vendor/k8s.io/client-go/transport/OWNERS diff --git a/Gopkg.lock b/Gopkg.lock index a17741de4b..d85a5f6f1e 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -2,7 +2,7 @@ [[projects]] - digest = "1:979a821d56fbe670625f96f9bc54ea17f74e2f75472dcc7811711c9955b8ca14" + digest = "1:906d785719b980b8a57104671bcf94ca226b49e128737a2ce1fd21611fb2a87e" name = "github.com/Azure/azure-sdk-for-go" packages = [ "services/apimanagement/mgmt/2017-03-01/apimanagement", @@ -17,12 +17,12 @@ "storage", "version", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "d3bcaa706ac10b18784811ff31e43be635159013" version = "v21.0.0" [[projects]] - digest = "1:aafd4229d26448b58665f4067d3fa5e945a2c90a30a639346767c21e4be9beb7" + digest = "1:ec10827fcacfaa45219ef2a22be6158b10c8de91b62094c7f40c3ab1fa76d67f" name = "github.com/Azure/go-autorest" packages = [ "autorest", @@ -34,31 +34,31 @@ "logger", "version", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "a88c19ef2016e095f0b6c3b451074b4663f53bed" version = "v10.15.4" [[projects]] - digest = "1:00ce6d124c3df5ca3073384f40a22c0c252e2962d433a90beb71ac2c95bc222c" + digest = "1:77a485286fddc15702c1a32635bbc6b17cf0daa59b015ed02d2f7f768a7b504a" name = "github.com/Jeffail/gabs" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "2a3aa15961d5fee6047b8151b67ac2f08ba2c48c" version = "1.0" [[projects]] - digest = "1:38b469493eb173db9c03321d64adcad4c7991ea0a19b5edc5bdc094f0e8c7384" + digest = "1:d6613cccd218e927314d7f6a7a6e8169473b07db7e07810341cacd3bdca920ba" name = "github.com/alexcesaro/statsd" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "7fea3f0d2fab1ad973e641e51dba45443a311a90" version = "v2.0.0" [[projects]] - digest = "1:705c40022f5c03bf96ffeb6477858d88565064485a513abcd0f11a0911546cb6" + digest = "1:aba270497eb2d49f5cba6f4162d524b9a1195a24cbce8be20bf56a0051f47deb" name = "github.com/blang/semver" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "2ee87856327ba09384cabd113bc6b5d174e9ec0f" version = "v3.5.1" @@ -66,73 +66,73 @@ digest = "1:620bade21ddf8256869717861431d52650c7e40bc56bdcd3d5ec3da63e7573b0" name = "github.com/davecgh/go-spew" packages = ["spew"] - pruneopts = "UT" + pruneopts = "NUT" revision = "5215b55f46b2b919f50a1df0eaa5886afe4e3b3d" [[projects]] - digest = "1:217f778e19b8d206112c21d21a7cc72ca3cb493b67631680a2324bc50335d432" + digest = "1:01ced7908dbaae42990af9521328922b8948bdcb174c23bba6db572381515716" name = "github.com/dgrijalva/jwt-go" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "dbeaa9332f19a944acb5736b4456cfcc02140e29" version = "v3.1.0" [[projects]] - digest = "1:2cd7915ab26ede7d95b8749e6b1f933f1c6d5398030684e6505940a10f31cfda" + digest = "1:81466b4218bf6adddac2572a30ac733a9255919bc2f470b4827a317bd4ee1756" name = "github.com/ghodss/yaml" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7" version = "v1.0.0" [[projects]] - digest = "1:ddac208e7ee66912adbaadd336c750ff133a99d09683e0baba18e40459b4730e" + digest = "1:ffcbca380dbcb924037ff7650da308aca0458296489349b8ce849436e47f0c8a" name = "github.com/go-bindata/go-bindata" packages = [ ".", "go-bindata", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "d266f3a456685e7541abc9f010d46fff146c7858" [[projects]] - digest = "1:c42f32253560d1527291221734a9b0d9f20ace8ad076398c86b4e8cb59a72307" + digest = "1:672bdbde3b59017aba3b328d0ec42dc30e0ab80ff48681947596785738c00ff1" name = "github.com/go-playground/locales" packages = [ ".", "currency", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "e4cbcb5d0652150d40ad0646651076b6bd2be4f6" version = "v0.11.2" [[projects]] - digest = "1:e022cf244bcac1b6ef933f1a2e0adcf6a6dfd7b872d8d41e4d4179bb09a87cbc" + digest = "1:1683152827ebac377858b53a6ad0be90fb1711061c7e580c5dc719834a349162" name = "github.com/go-playground/universal-translator" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "b32fa301c9fe55953584134cb6853a13c87ec0a1" version = "v0.16.0" [[projects]] - digest = "1:f83d740263b44fdeef3e1bce6147b5d7283fcad1a693d39639be33993ecf3db1" + digest = "1:a6afc27b2a73a5506832f3c5a1c19a30772cb69e7bd1ced4639eb36a55db224f" name = "github.com/gogo/protobuf" packages = [ "proto", "sortkeys", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "c0656edd0d9eab7c66d1eb0c568f9039345796f7" [[projects]] - digest = "1:2edd2416f89b4e841df0e4a78802ce14d2bc7ad79eba1a45986e39f0f8cb7d87" + digest = "1:78b8040ece2ff622580def2708b9eb0b2857711b6744c475439bf337e9c677ea" name = "github.com/golang/glog" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "44145f04b68cf362d9c4df2182967c2275eaefed" [[projects]] - digest = "1:8f2df6167daef6f4d56d07f99bbcf4733117db0dedfd959995b9a679c52561f1" + digest = "1:0d390d7037c2aecc37e78c2cfbe43d020d6f1fa83fd22266b7ec621189447d57" name = "github.com/golang/protobuf" packages = [ "proto", @@ -141,48 +141,48 @@ "ptypes/duration", "ptypes/timestamp", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" [[projects]] branch = "master" - digest = "1:0bfbe13936953a98ae3cfe8ed6670d396ad81edf069a806d2f6515d7bb6950df" + digest = "1:05f95ffdfcf651bdb0f05b40b69e7f5663047f8da75c72d58728acb59b5cc107" name = "github.com/google/btree" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "4030bb1f1f0c35b30ca7009e9ebd06849dd45306" [[projects]] - digest = "1:41bfd4219241b7f7d6e6fdb13fc712576f1337e68e6b895136283b76928fdd66" + digest = "1:f9425215dccf1c63f659ec781ca46bc81804341821d0cd8d2459c5b58f8bd067" name = "github.com/google/gofuzz" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "44d81051d367757e1c7c6a5a86423ece9afcf63c" [[projects]] - digest = "1:75eb87381d25cc75212f52358df9c3a2719584eaa9685cd510ce28699122f39d" + digest = "1:27b4ab41ffdc76ad6db56db327a4db234a59588ef059fc3fd678ba0bc6b9094f" name = "github.com/googleapis/gnostic" packages = [ "OpenAPIv2", "compiler", "extensions", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "0c5108395e2debce0d731cf0287ddf7242066aba" [[projects]] branch = "master" - digest = "1:86c1210529e69d69860f2bb3ee9ccce0b595aa3f9165e7dd1388e5c612915888" + digest = "1:7fdf3223c7372d1ced0b98bf53457c5e89d89aecbad9a77ba9fcc6e01f9e5621" name = "github.com/gregjones/httpcache" packages = [ ".", "diskcache", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "9cad4c3443a7200dd6400aef47183728de563a38" [[projects]] - digest = "1:a1038ef593beb4771c8f0f9c26e8b00410acd800af5c6864651d9bf160ea1813" + digest = "1:41933d387bfa3eaa6a82647914ed7044f7b8355764c24fb920892bc8c03ef0c3" name = "github.com/hpcloud/tail" packages = [ ".", @@ -191,23 +191,23 @@ "watch", "winfile", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "a30252cb686a21eb2d0b98132633053ec2f7f1e5" version = "v1.0.0" [[projects]] - digest = "1:3e260afa138eab6492b531a3b3d10ab4cb70512d423faa78b8949dec76e66a21" + digest = "1:65300ccc4bcb38b107b868155c303312978981e56bca707c81efec57575b5e06" name = "github.com/imdario/mergo" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "9316a62528ac99aaecb4e47eadd6dc8aa6533d58" version = "v0.3.5" [[projects]] - digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be" + digest = "1:406338ad39ab2e37b7f4452906442a3dbf0eb3379dd1f06aafb5c07e769a5fbb" name = "github.com/inconshreveable/mousetrap" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" version = "v1.0" @@ -219,93 +219,93 @@ "models", "pkg/escape", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "d610a79487e2cee1d0fa8cdd3ec59d511c24f0dc" [[projects]] - digest = "1:3e551bbb3a7c0ab2a2bf4660e7fcad16db089fdcfbb44b0199e62838038623ea" + digest = "1:8e36686e8b139f8fe240c1d5cf3a145bc675c22ff8e707857cdd3ae17b00d728" name = "github.com/json-iterator/go" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "1624edc4454b8682399def8740d46db5e4362ba4" version = "v1.1.5" [[projects]] - digest = "1:4f5ebfe82180f3816ea3501686efb41245ab7adbb62c3af9c5e93b526b40f217" + digest = "1:9508ab0002c1b789f50ddd242430e4c713cf25d75c4616731ca97fe873f25569" name = "github.com/kelseyhightower/envconfig" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "462fda1f11d8cad3660e52737b8beefd27acfb3f" [[projects]] - digest = "1:8c8e77781f74bcedc016745383185f74498d98e9d36cc7f14d4aa751657905a7" + digest = "1:36cc90298f456fc38e7738c9b18cf948d18f929c6e75a4c9fd47302b0ca93dd3" name = "github.com/leonelquinteros/gotext" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "1fc8dec04d161fc0b4007e808a48620c537b6a6e" version = "v1.2.3" [[projects]] - digest = "1:4e878df5f4e9fd625bf9c9aac77ef7cbfa4a74c01265505527c23470c0e40300" + digest = "1:13ada91f079028d1b4ca88e10a16439dcfa6541d26ed2e61e770f56d06301933" name = "github.com/marstr/guid" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "8bd9a64bf37eb297b492a4101fb28e80ac0b290f" version = "v1.1.0" [[projects]] - digest = "1:c658e84ad3916da105a761660dcaeb01e63416c8ec7bc62256a9b411a05fcd67" + digest = "1:08c231ec84231a7e23d67e4b58f975e1423695a32467a362ee55a803f9de8061" name = "github.com/mattn/go-colorable" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072" version = "v0.0.9" [[projects]] branch = "master" - digest = "1:0981502f9816113c9c8c4ac301583841855c8cf4da8c72f696b3ebedf6d0e4e5" + digest = "1:bffa444ca07c69c599ae5876bc18b25bfd5fa85b297ca10a25594d284a7e9c5d" name = "github.com/mattn/go-isatty" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "6ca4dbf54d38eea1a992b3c722a76a5d1c4cb25c" [[projects]] branch = "master" - digest = "1:550b558c67eb89895c0340dc551de58033d1bfaecbf46f1405d6f0bd03e3fbee" + digest = "1:d00e88d71d56d02265c0f9c3a4551db6981b3f00bcd9ae63c092e0e9829dfc82" name = "github.com/mattn/kinako" packages = [ "ast", "parser", "vm", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "332c0a7e205a29536e672337a4bea6c7a96b04c1" [[projects]] - digest = "1:12ae6210bdbdad658a9a67fd95cd9c99f7fdbf12f6d36eaf0af704e69dacf4f5" + digest = "1:b62c4f18ad6eb454ac5253e7791ded3d7867330015ca4b37b6336e57f514585e" name = "github.com/mitchellh/go-homedir" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "b8bc1bf767474819792c23f32d8286a45736f1c6" [[projects]] - digest = "1:33422d238f147d247752996a26574ac48dcf472976eda7f5134015f06bf16563" + digest = "1:2f42fa12d6911c7b7659738758631bec870b7e9b4c6be5444f963cdcfccc191f" name = "github.com/modern-go/concurrent" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" version = "1.0.3" [[projects]] - digest = "1:e32bdbdb7c377a07a9a46378290059822efdce5c8d96fe71940d87cb4f918855" + digest = "1:c6aca19413b13dc59c220ad7430329e2ec454cc310bc6d8de2c7e2b93c18a0f6" name = "github.com/modern-go/reflect2" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd" version = "1.0.1" [[projects]] - digest = "1:42e29deef12327a69123b9cb2cb45fee4af5c12c2a23c6e477338279a052703f" + digest = "1:0be1cd4c73d5e22a30edcf32a18e9809a370a7a4a52c4f41a86070b34da93fef" name = "github.com/onsi/ginkgo" packages = [ ".", @@ -327,12 +327,12 @@ "reporters/stenographer/support/go-isatty", "types", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "3774a09d95489ccaa16032e0770d08ea77ba6184" version = "v1.6.0" [[projects]] - digest = "1:e340739c2403b0e6ee006e83c375754f44c1a483b695eff1b588acf8c4824925" + digest = "1:fbe747f38101b666e0e931b9c54e389848790fa4a99508b3da73db58a822546d" name = "github.com/onsi/gomega" packages = [ ".", @@ -348,7 +348,7 @@ "matchers/support/goraph/util", "types", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "dcabb60a477c2b6f456df65037cb6708210fbb02" [[projects]] @@ -356,53 +356,53 @@ digest = "1:3bf17a6e6eaa6ad24152148a631d18662f7212e21637c2699bff3369b7f00fa2" name = "github.com/petar/GoLLRB" packages = ["llrb"] - pruneopts = "UT" + pruneopts = "NUT" revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4" [[projects]] - digest = "1:0e7775ebbcf00d8dd28ac663614af924411c868dca3d5aa762af0fae3808d852" + digest = "1:6c6d91dc326ed6778783cff869c49fb2f61303cdd2ebbcf90abe53505793f3b6" name = "github.com/peterbourgon/diskv" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "5f041e8faa004a95c88a202771f4cc3e991971e6" version = "v2.0.1" [[projects]] - digest = "1:40e195917a951a8bf867cd05de2a46aaf1806c50cf92eebf4c16f78cd196f747" + digest = "1:5cf3f025cbee5951a4ee961de067c8a89fc95a5adabead774f82822efabab121" name = "github.com/pkg/errors" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "645ef00459ed84a119197bfb8d8205042c6df63d" version = "v0.8.0" [[projects]] - digest = "1:274f67cb6fed9588ea2521ecdac05a6d62a8c51c074c1fccc6a49a40ba80e925" + digest = "1:6bc0652ea6e39e22ccd522458b8bdd8665bf23bdc5a20eec90056e4dc7e273ca" name = "github.com/satori/go.uuid" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "f58768cc1a7a7e77a3bd49e98cdd21419399b6a3" version = "v1.2.0" [[projects]] - digest = "1:5f2aaa360f48d1711795bd88c7e45a38f86cf81e4bc01453d20983baa67e2d51" + digest = "1:31c5d934770c8b0698c28eb8576cb39b14e2fcf3c5f2a6e8449116884cd92e3f" name = "github.com/sirupsen/logrus" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "f006c2ac4710855cf0f916dd6b77acf6b048dc6e" version = "v1.0.3" [[projects]] - digest = "1:0feb002a830159bc8bbdcda7a786705a6ec68cc98b8f8494bbf6a61065090684" + digest = "1:05abf3b6b5898a29553ef857ec65c358270f5c610def33dc11cd7f40d89fd858" name = "github.com/spf13/cobra" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "4cdb38c072b86bf795d2c81de50784d9fdd6eb77" [[projects]] - digest = "1:1b21a2b4058a779f290c7341cd93267492e0ecea6c8b54f64a4a5fd7ff131034" + digest = "1:3ab855aa584d08db6541ce99dad60c12bd6a328ecb8a7358363887f85c976347" name = "github.com/spf13/pflag" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66" version = "v1.0.0" @@ -417,11 +417,11 @@ "ssh/agent", "ssh/terminal", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "81e90905daefcd6fd217b62423c0908922eadb30" [[projects]] - digest = "1:cc31faad92b4371c2dd4a1aeba49f32856b2a40f0164e1939c45bc13440b2939" + digest = "1:7905c1c991e9affb7e6a7578efd2c7fcad2b5587ded1ef9c11c5d21fdef81ba9" name = "golang.org/x/net" packages = [ "context", @@ -434,18 +434,18 @@ "idna", "lex/httplex", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "ab555f366c4508dbe0802550b1b20c46c5c18aa0" [[projects]] branch = "master" - digest = "1:70afbb0d0abb4b9f7d4a6616dab26f6a74e35d6fbbcb37de72876a49df6d7361" + digest = "1:b9f6fdaae6f237049963344e4f5320429c0a4088f4b34ec43c36b384b89917e1" name = "golang.org/x/oauth2" packages = [ ".", "internal", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "8527f56f71077909d6ead7facfe18fbf05ebdf83" [[projects]] @@ -453,21 +453,21 @@ digest = "1:39ebcc2b11457b703ae9ee2e8cca0f68df21969c6102cb3b705f76cca0ea0239" name = "golang.org/x/sync" packages = ["errgroup"] - pruneopts = "UT" + pruneopts = "NUT" revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca" [[projects]] - digest = "1:e1a85d3648114c446b2874647bf30f646a8594e7e4e45db87fe962aba60e51f5" + digest = "1:a969921c213e6d90554219689f484043e1e897d1936e524cfbb4fd6cb8ae2736" name = "golang.org/x/sys" packages = [ "unix", "windows", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "95c6576299259db960f6c5b9b69ea52422860fce" [[projects]] - digest = "1:436b24586f8fee329e0dd65fd67c817681420cda1d7f934345c13fe78c212a73" + digest = "1:8a12cbc891b7130d3f660f8a309e5c0b083f831e6ac38cdaa1f12e63c12d6bea" name = "golang.org/x/text" packages = [ "collate", @@ -497,18 +497,18 @@ "unicode/norm", "unicode/rangetable", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "e19ae1496984b1c655b8044a65c0300a3c878dd3" [[projects]] digest = "1:d37b0ef2944431fe9e8ef35c6fffc8990d9e2ca300588df94a6890f3649ae365" name = "golang.org/x/time" packages = ["rate"] - pruneopts = "UT" + pruneopts = "NUT" revision = "f51c12702a4d776e4c1fa9b0fabab841babae631" [[projects]] - digest = "1:6247f76e55a1e1a5c19a81e2d4b4dff6730461eeb5bbb0a16dd4a8ec8637ee93" + digest = "1:36354a269794d9cb4cebae233f65a966e818f763088370c8524726853a31c96f" name = "google.golang.org/appengine" packages = [ "internal", @@ -519,24 +519,24 @@ "internal/urlfetch", "urlfetch", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "ae0ab99deb4dc413a2b4bd6c8bdd0eb67f1e4d06" version = "v1.2.0" [[projects]] - digest = "1:abeb38ade3f32a92943e5be54f55ed6d6e3b6602761d74b4aab4c9dd45c18abd" + digest = "1:1b91ae0dc69a41d4c2ed23ea5cffb721ea63f5037ca4b81e6d6771fbb8f45129" name = "gopkg.in/fsnotify.v1" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9" source = "https://github.com/fsnotify/fsnotify.git" version = "v1.4.7" [[projects]] - digest = "1:090964cce6d9d87e77c889afb714bb93e9f2dc79a1e1d54f794220cc1f33ccfd" + digest = "1:bd1ad9b0806a00aa9bb291a5fdf40834811a74b1f3246f8984360bbecfef7cb3" name = "gopkg.in/go-playground/validator.v9" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "fb68f39656d7ebf8aa339ad4917aa0c260ecc237" version = "v9.4.0" @@ -544,37 +544,37 @@ digest = "1:ef72505cf098abdd34efeea032103377bec06abb61d8a06f002d5d296a4b1185" name = "gopkg.in/inf.v0" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4" version = "v0.9.0" [[projects]] - digest = "1:fe8a03a8222d5b913f256972933d26d24ad7c8286692a42943bc01633cc8fce3" + digest = "1:f59266de09e138237bf9df9deb57b9ebbdb1e33b8399bb739c3745e7d3d2787b" name = "gopkg.in/ini.v1" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "358ee7663966325963d4e8b2e1fbd570c5195153" version = "v1.38.1" [[projects]] branch = "v1" - digest = "1:0caa92e17bc0b65a98c63e5bc76a9e844cd5e56493f8fdbb28fad101a16254d9" + digest = "1:8fb1ccb16a6cfecbfdfeb84d8ea1cc7afa8f9ef16526bc2326f72d993e32cef1" name = "gopkg.in/tomb.v1" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "dd632973f1e7218eb1089048e0798ec9ae7dceb8" [[projects]] - digest = "1:73e6fda93622790d2371344759df06ff5ff2fac64a6b6e8832b792e7402956e7" + digest = "1:13e704c08924325be00f96e47e7efe0bfddf0913cdfc237423c83f9b183ff590" name = "gopkg.in/yaml.v2" packages = ["."] - pruneopts = "UT" + pruneopts = "NUT" revision = "d670f9405373e636a5a2765eea47fac0c9bc91a4" version = "v2.0.0" [[projects]] branch = "master" - digest = "1:c7b7bc1b77509825c47ad27e805edd3053f7c2e08c8bd04f6150483063d81ce8" + digest = "1:4c538f78d79d05e4dc19308b3da298a0d5b2ade51156b5a16366fd523bab5f54" name = "k8s.io/api" packages = [ "admissionregistration/v1alpha1", @@ -609,12 +609,12 @@ "storage/v1alpha1", "storage/v1beta1", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "74c9151590fc25da763fda38bb2e3eb9a1590c63" [[projects]] branch = "master" - digest = "1:065b4bf57948a52a1867e5237bf0ffe61946e8f646a3aa28616dbcdf705bbf2a" + digest = "1:2de7192b1fc3884f49b413d351c24947fdd781e111f46b8291dcecc506391d14" name = "k8s.io/apimachinery" packages = [ "pkg/api/equality", @@ -655,11 +655,11 @@ "pkg/watch", "third_party/forked/golang/reflect", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "1c355ce7f987f9610178d7c598031fbfa62b3af9" [[projects]] - digest = "1:51fd9ac9f2be10d79f5af101a7a1d758ef283fdb028a0d11198754bd3d4a6020" + digest = "1:3b5b7622d385891eeac9eaf3151ea57d38cff4f05c57d6ad94134f346f7f8099" name = "k8s.io/client-go" packages = [ "discovery", @@ -717,7 +717,7 @@ "util/homedir", "util/integer", ] - pruneopts = "UT" + pruneopts = "NUT" revision = "1638f8970cefaa404ff3a62950f88b08292b2696" version = "v9.0.0" diff --git a/Gopkg.toml b/Gopkg.toml index 31ef8910a7..92a0179e19 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -100,6 +100,7 @@ required = [ [prune] go-tests = true + non-go = true unused-packages = true [[constraint]] diff --git a/pkg/api/defaults_test.go b/pkg/api/defaults_test.go index 72b56d4588..e201056f98 100644 --- a/pkg/api/defaults_test.go +++ b/pkg/api/defaults_test.go @@ -417,12 +417,14 @@ func TestAcceleratedNetworking(t *testing.T) { mockCS.SetPropertiesDefaults(false, false) // In create scenario, nil AcceleratedNetworkingEnabled should be the defaults - if helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabled) != DefaultAcceleratedNetworking { - t.Errorf("expected default acceleratedNetworkingEnabled to be %t, instead got %t", DefaultAcceleratedNetworking, helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabled)) + acceleratedNetworking := DefaultAcceleratedNetworking + if helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabled) != acceleratedNetworking { + t.Errorf("expected default acceleratedNetworkingEnabled to be %t, instead got %t", acceleratedNetworking, helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabled)) } // In create scenario, nil AcceleratedNetworkingEnabledWindows should be the defaults - if helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabledWindows) != DefaultAcceleratedNetworkingWindowsEnabled { - t.Errorf("expected default acceleratedNetworkingEnabledWindows to be %t, instead got %t", DefaultAcceleratedNetworkingWindowsEnabled, helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabledWindows)) + acceleratedNetworking = DefaultAcceleratedNetworkingWindowsEnabled + if helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabledWindows) != acceleratedNetworking { + t.Errorf("expected default acceleratedNetworkingEnabledWindows to be %t, instead got %t", acceleratedNetworking, helpers.IsTrueBoolPointer(mockCS.Properties.AgentPoolProfiles[0].AcceleratedNetworkingEnabledWindows)) } mockCS = getMockBaseContainerService("1.10.8") diff --git a/vendor/github.com/Azure/azure-sdk-for-go/storage/README.md b/vendor/github.com/Azure/azure-sdk-for-go/storage/README.md deleted file mode 100644 index 459b45831c..0000000000 --- a/vendor/github.com/Azure/azure-sdk-for-go/storage/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Azure Storage SDK for Go (Preview) - -:exclamation: IMPORTANT: This package is in maintenance only and will be deprecated in the -future. Please use one of the following packages instead. - -| Service | Import Path/Repo | -|---------|------------------| -| Storage - Blobs | [github.com/Azure/azure-storage-blob-go](https://github.com/Azure/azure-storage-blob-go) | -| Storage - Files | [github.com/Azure/azure-storage-file-go](https://github.com/Azure/azure-storage-file-go) | -| Storage - Queues | [github.com/Azure/azure-storage-queue-go](https://github.com/Azure/azure-storage-queue-go) | - -The `github.com/Azure/azure-sdk-for-go/storage` package is used to manage -[Azure Storage](https://docs.microsoft.com/en-us/azure/storage/) data plane -resources: containers, blobs, tables, and queues. - -To manage storage *accounts* use Azure Resource Manager (ARM) via the packages -at [github.com/Azure/azure-sdk-for-go/services/storage](https://github.com/Azure/azure-sdk-for-go/tree/master/services/storage). - -This package also supports the [Azure Storage -Emulator](https://azure.microsoft.com/documentation/articles/storage-use-emulator/) -(Windows only). - diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/README.md b/vendor/github.com/Azure/go-autorest/autorest/adal/README.md deleted file mode 100644 index 7b0c4bc4d2..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/README.md +++ /dev/null @@ -1,292 +0,0 @@ -# Azure Active Directory authentication for Go - -This is a standalone package for authenticating with Azure Active -Directory from other Go libraries and applications, in particular the [Azure SDK -for Go](https://github.com/Azure/azure-sdk-for-go). - -Note: Despite the package's name it is not related to other "ADAL" libraries -maintained in the [github.com/AzureAD](https://github.com/AzureAD) org. Issues -should be opened in [this repo's](https://github.com/Azure/go-autorest/issues) -or [the SDK's](https://github.com/Azure/azure-sdk-for-go/issues) issue -trackers. - -## Install - -```bash -go get -u github.com/Azure/go-autorest/autorest/adal -``` - -## Usage - -An Active Directory application is required in order to use this library. An application can be registered in the [Azure Portal](https://portal.azure.com/) by following these [guidelines](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-integrating-applications) or using the [Azure CLI](https://github.com/Azure/azure-cli). - -### Register an Azure AD Application with secret - - -1. Register a new application with a `secret` credential - - ``` - az ad app create \ - --display-name example-app \ - --homepage https://example-app/home \ - --identifier-uris https://example-app/app \ - --password secret - ``` - -2. Create a service principal using the `Application ID` from previous step - - ``` - az ad sp create --id "Application ID" - ``` - - * Replace `Application ID` with `appId` from step 1. - -### Register an Azure AD Application with certificate - -1. Create a private key - - ``` - openssl genrsa -out "example-app.key" 2048 - ``` - -2. Create the certificate - - ``` - openssl req -new -key "example-app.key" -subj "/CN=example-app" -out "example-app.csr" - openssl x509 -req -in "example-app.csr" -signkey "example-app.key" -out "example-app.crt" -days 10000 - ``` - -3. Create the PKCS12 version of the certificate containing also the private key - - ``` - openssl pkcs12 -export -out "example-app.pfx" -inkey "example-app.key" -in "example-app.crt" -passout pass: - - ``` - -4. Register a new application with the certificate content form `example-app.crt` - - ``` - certificateContents="$(tail -n+2 "example-app.crt" | head -n-1)" - - az ad app create \ - --display-name example-app \ - --homepage https://example-app/home \ - --identifier-uris https://example-app/app \ - --key-usage Verify --end-date 2018-01-01 \ - --key-value "${certificateContents}" - ``` - -5. Create a service principal using the `Application ID` from previous step - - ``` - az ad sp create --id "APPLICATION_ID" - ``` - - * Replace `APPLICATION_ID` with `appId` from step 4. - - -### Grant the necessary permissions - -Azure relies on a Role-Based Access Control (RBAC) model to manage the access to resources at a fine-grained -level. There is a set of [pre-defined roles](https://docs.microsoft.com/en-us/azure/active-directory/role-based-access-built-in-roles) -which can be assigned to a service principal of an Azure AD application depending of your needs. - -``` -az role assignment create --assigner "SERVICE_PRINCIPAL_ID" --role "ROLE_NAME" -``` - -* Replace the `SERVICE_PRINCIPAL_ID` with the `appId` from previous step. -* Replace the `ROLE_NAME` with a role name of your choice. - -It is also possible to define custom role definitions. - -``` -az role definition create --role-definition role-definition.json -``` - -* Check [custom roles](https://docs.microsoft.com/en-us/azure/active-directory/role-based-access-control-custom-roles) for more details regarding the content of `role-definition.json` file. - - -### Acquire Access Token - -The common configuration used by all flows: - -```Go -const activeDirectoryEndpoint = "https://login.microsoftonline.com/" -tenantID := "TENANT_ID" -oauthConfig, err := adal.NewOAuthConfig(activeDirectoryEndpoint, tenantID) - -applicationID := "APPLICATION_ID" - -callback := func(token adal.Token) error { - // This is called after the token is acquired -} - -// The resource for which the token is acquired -resource := "https://management.core.windows.net/" -``` - -* Replace the `TENANT_ID` with your tenant ID. -* Replace the `APPLICATION_ID` with the value from previous section. - -#### Client Credentials - -```Go -applicationSecret := "APPLICATION_SECRET" - -spt, err := adal.NewServicePrincipalToken( - oauthConfig, - appliationID, - applicationSecret, - resource, - callbacks...) -if err != nil { - return nil, err -} - -// Acquire a new access token -err = spt.Refresh() -if (err == nil) { - token := spt.Token -} -``` - -* Replace the `APPLICATION_SECRET` with the `password` value from previous section. - -#### Client Certificate - -```Go -certificatePath := "./example-app.pfx" - -certData, err := ioutil.ReadFile(certificatePath) -if err != nil { - return nil, fmt.Errorf("failed to read the certificate file (%s): %v", certificatePath, err) -} - -// Get the certificate and private key from pfx file -certificate, rsaPrivateKey, err := decodePkcs12(certData, "") -if err != nil { - return nil, fmt.Errorf("failed to decode pkcs12 certificate while creating spt: %v", err) -} - -spt, err := adal.NewServicePrincipalTokenFromCertificate( - oauthConfig, - applicationID, - certificate, - rsaPrivateKey, - resource, - callbacks...) - -// Acquire a new access token -err = spt.Refresh() -if (err == nil) { - token := spt.Token -} -``` - -* Update the certificate path to point to the example-app.pfx file which was created in previous section. - - -#### Device Code - -```Go -oauthClient := &http.Client{} - -// Acquire the device code -deviceCode, err := adal.InitiateDeviceAuth( - oauthClient, - oauthConfig, - applicationID, - resource) -if err != nil { - return nil, fmt.Errorf("Failed to start device auth flow: %s", err) -} - -// Display the authentication message -fmt.Println(*deviceCode.Message) - -// Wait here until the user is authenticated -token, err := adal.WaitForUserCompletion(oauthClient, deviceCode) -if err != nil { - return nil, fmt.Errorf("Failed to finish device auth flow: %s", err) -} - -spt, err := adal.NewServicePrincipalTokenFromManualToken( - oauthConfig, - applicationID, - resource, - *token, - callbacks...) - -if (err == nil) { - token := spt.Token -} -``` - -#### Username password authenticate - -```Go -spt, err := adal.NewServicePrincipalTokenFromUsernamePassword( - oauthConfig, - applicationID, - username, - password, - resource, - callbacks...) - -if (err == nil) { - token := spt.Token -} -``` - -#### Authorization code authenticate - -``` Go -spt, err := adal.NewServicePrincipalTokenFromAuthorizationCode( - oauthConfig, - applicationID, - clientSecret, - authorizationCode, - redirectURI, - resource, - callbacks...) - -err = spt.Refresh() -if (err == nil) { - token := spt.Token -} -``` - -### Command Line Tool - -A command line tool is available in `cmd/adal.go` that can acquire a token for a given resource. It supports all flows mentioned above. - -``` -adal -h - -Usage of ./adal: - -applicationId string - application id - -certificatePath string - path to pk12/PFC application certificate - -mode string - authentication mode (device, secret, cert, refresh) (default "device") - -resource string - resource for which the token is requested - -secret string - application secret - -tenantId string - tenant id - -tokenCachePath string - location of oath token cache (default "/home/cgc/.adal/accessToken.json") -``` - -Example acquire a token for `https://management.core.windows.net/` using device code flow: - -``` -adal -mode device \ - -applicationId "APPLICATION_ID" \ - -tenantId "TENANT_ID" \ - -resource https://management.core.windows.net/ - -``` diff --git a/vendor/github.com/Jeffail/gabs/README.md b/vendor/github.com/Jeffail/gabs/README.md deleted file mode 100644 index 9ae67f7536..0000000000 --- a/vendor/github.com/Jeffail/gabs/README.md +++ /dev/null @@ -1,284 +0,0 @@ -![Gabs](gabs_logo.png "Gabs") - -Gabs is a small utility for dealing with dynamic or unknown JSON structures in golang. It's pretty much just a helpful wrapper around the golang json.Marshal/json.Unmarshal behaviour and map[string]interface{} objects. It does nothing spectacular except for being fabulous. - -https://godoc.org/github.com/Jeffail/gabs - -##How to install: - -```bash -go get github.com/Jeffail/gabs -``` - -##How to use - -###Parsing and searching JSON - -```go -... - -import "github.com/Jeffail/gabs" - -jsonParsed, err := gabs.ParseJSON([]byte(`{ - "outter":{ - "inner":{ - "value1":10, - "value2":22 - }, - "alsoInner":{ - "value1":20 - } - } -}`)) - -var value float64 -var ok bool - -value, ok = jsonParsed.Path("outter.inner.value1").Data().(float64) -// value == 10.0, ok == true - -value, ok = jsonParsed.Search("outter", "inner", "value1").Data().(float64) -// value == 10.0, ok == true - -value, ok = jsonParsed.Path("does.not.exist").Data().(float64) -// value == 0.0, ok == false - -exists := jsonParsed.Exists("outter", "inner", "value1") -// exists == true - -exists := jsonParsed.Exists("does", "not", "exist") -// exists == false - -exists := jsonParsed.ExistsP("does.not.exist") -// exists == false - -... -``` - -###Iterating objects - -```go -... - -jsonParsed, _ := gabs.ParseJSON([]byte(`{"object":{ "first": 1, "second": 2, "third": 3 }}`)) - -// S is shorthand for Search -children, _ := jsonParsed.S("object").ChildrenMap() -for key, child := range children { - fmt.Printf("key: %v, value: %v\n", key, child.Data().(string)) -} - -... -``` - -###Iterating arrays - -```go -... - -jsonParsed, _ := gabs.ParseJSON([]byte(`{"array":[ "first", "second", "third" ]}`)) - -// S is shorthand for Search -children, _ := jsonParsed.S("array").Children() -for _, child := range children { - fmt.Println(child.Data().(string)) -} - -... -``` - -Will print: - -``` -first -second -third -``` - -Children() will return all children of an array in order. This also works on objects, however, the children will be returned in a random order. - -###Searching through arrays - -If your JSON structure contains arrays you can still search the fields of the objects within the array, this returns a JSON array containing the results for each element. - -```go -... - -jsonParsed, _ := gabs.ParseJSON([]byte(`{"array":[ {"value":1}, {"value":2}, {"value":3} ]}`)) -fmt.Println(jsonParsed.Path("array.value").String()) - -... -``` - -Will print: - -``` -[1,2,3] -``` - -###Generating JSON - -```go -... - -jsonObj := gabs.New() -// or gabs.Consume(jsonObject) to work on an existing map[string]interface{} - -jsonObj.Set(10, "outter", "inner", "value") -jsonObj.SetP(20, "outter.inner.value2") -jsonObj.Set(30, "outter", "inner2", "value3") - -fmt.Println(jsonObj.String()) - -... -``` - -Will print: - -``` -{"outter":{"inner":{"value":10,"value2":20},"inner2":{"value3":30}}} -``` - -To pretty-print: - -```go -... - -fmt.Println(jsonObj.StringIndent("", " ")) - -... -``` - -Will print: - -``` -{ - "outter": { - "inner": { - "value": 10, - "value2": 20 - }, - "inner2": { - "value3": 30 - } - } -} -``` - -###Generating Arrays - -```go -... - -jsonObj := gabs.New() - -jsonObj.Array("foo", "array") -// Or .ArrayP("foo.array") - -jsonObj.ArrayAppend(10, "foo", "array") -jsonObj.ArrayAppend(20, "foo", "array") -jsonObj.ArrayAppend(30, "foo", "array") - -fmt.Println(jsonObj.String()) - -... -``` - -Will print: - -``` -{"foo":{"array":[10,20,30]}} -``` - -Working with arrays by index: - -```go -... - -jsonObj := gabs.New() - -// Create an array with the length of 3 -jsonObj.ArrayOfSize(3, "foo") - -jsonObj.S("foo").SetIndex("test1", 0) -jsonObj.S("foo").SetIndex("test2", 1) - -// Create an embedded array with the length of 3 -jsonObj.S("foo").ArrayOfSizeI(3, 2) - -jsonObj.S("foo").Index(2).SetIndex(1, 0) -jsonObj.S("foo").Index(2).SetIndex(2, 1) -jsonObj.S("foo").Index(2).SetIndex(3, 2) - -fmt.Println(jsonObj.String()) - -... -``` - -Will print: - -``` -{"foo":["test1","test2",[1,2,3]]} -``` - -###Converting back to JSON - -This is the easiest part: - -```go -... - -jsonParsedObj := gabs.ParseJSON([]byte(`{ - "outter":{ - "values":{ - "first":10, - "second":11 - } - }, - "outter2":"hello world" -}`)) - -jsonOutput := jsonParsedObj.String() -// Becomes `{"outter":{"values":{"first":10,"second":11}},"outter2":"hello world"}` - -... -``` - -And to serialize a specific segment is as simple as: - -```go -... - -jsonParsedObj := gabs.ParseJSON([]byte(`{ - "outter":{ - "values":{ - "first":10, - "second":11 - } - }, - "outter2":"hello world" -}`)) - -jsonOutput := jsonParsedObj.Search("outter").String() -// Becomes `{"values":{"first":10,"second":11}}` - -... -``` - -### Parsing Numbers - -Gabs uses the `json` package under the bonnet, which by default will parse all number values into `float64`. If you need to parse `Int` values then you should use a `json.Decoder` (https://golang.org/pkg/encoding/json/#Decoder): - -```go -sample := []byte(`{"test":{"int":10, "float":6.66}}`) -dec := json.NewDecoder(bytes.NewReader(sample)) -dec.UseNumber() - -val, err := gabs.ParseJSONDecoder(dec) -if err != nil { - t.Errorf("Failed to parse: %v", err) - return -} - -intValue, err := val.Path("test.int").Data().(json.Number).Int64() -``` diff --git a/vendor/github.com/Jeffail/gabs/gabs_logo.png b/vendor/github.com/Jeffail/gabs/gabs_logo.png deleted file mode 100644 index e8c2832288620f4fadba3ac8f77417fed3ceb0ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56959 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 diff --git a/vendor/github.com/alexcesaro/statsd/.travis.yml b/vendor/github.com/alexcesaro/statsd/.travis.yml deleted file mode 100644 index 48915e737a..0000000000 --- a/vendor/github.com/alexcesaro/statsd/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: go - -go: - - 1.2 - - 1.3 - - 1.4 - - 1.5 - - 1.6 - - tip diff --git a/vendor/github.com/alexcesaro/statsd/CHANGELOG.md b/vendor/github.com/alexcesaro/statsd/CHANGELOG.md deleted file mode 100644 index 04d811b719..0000000000 --- a/vendor/github.com/alexcesaro/statsd/CHANGELOG.md +++ /dev/null @@ -1,64 +0,0 @@ -# Change Log -All notable changes to this project will be documented in this file. -This project adheres to [Semantic Versioning](http://semver.org/). - -## [2.0.0] - 2016-03-20 - -- `New` signature changed. The default address used is now ":8125". To use - another address use the `Address` option: - - Before: - ``` - statsd.New(":8125") - statsd.New(":9000") - ``` - - After - ``` - statsd.New() - statsd.New(statsd.Address(":9000")) - ``` - -- The `rate` parameter has been removed from the `Count` and `Timing` methods. - Use the new `SampleRate` option instead. - -- `Count`, `Gauge` and `Timing` now accept a `interface{}` instead of an int as - the value parameter. So you can now use any type of integer or float in these - functions. - -- The `WithInfluxDBTags` and `WithDatadogTags` options were replaced by the - `TagsFormat` and `Tags` options: - - Before: - ``` - statsd.New(statsd.WithInfluxDBTags("tag", "value")) - statsd.New(statsd.WithDatadogTags("tag", "value")) - ``` - - After - ``` - statsd.New(statsd.TagsFormat(statsd.InfluxDB), statsd.Tags("tag", "value")) - statsd.New(statsd.TagsFormat(statsd.Datadog), statsd.Tags("tag", "value")) - ``` - -- All options whose named began by `With` had the `With` stripped: - - Before: - ``` - statsd.New(statsd.WithMaxPacketSize(65000)) - ``` - - After - ``` - statsd.New(statsd.MaxPacketSize(65000)) - ``` - -- `ChangeGauge` has been removed as it is a bad practice: UDP packets can be - lost so using relative changes can cause unreliable values in the long term. - Use `Gauge` instead which sends an absolute value. - -- The `Histogram` method has been added. - -- The `Clone` method was added to the `Client`, it allows to create a new - `Client` with different rate / prefix / tags parameters while still using the - same connection. diff --git a/vendor/github.com/alexcesaro/statsd/README.md b/vendor/github.com/alexcesaro/statsd/README.md deleted file mode 100644 index 774a1c6879..0000000000 --- a/vendor/github.com/alexcesaro/statsd/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# statsd -[![Build Status](https://travis-ci.org/alexcesaro/statsd.svg?branch=v2)](https://travis-ci.org/alexcesaro/statsd) [![Code Coverage](http://gocover.io/_badge/gopkg.in/alexcesaro/statsd.v2)](http://gocover.io/gopkg.in/alexcesaro/statsd.v2) [![Documentation](https://godoc.org/gopkg.in/alexcesaro/statsd.v2?status.svg)](https://godoc.org/gopkg.in/alexcesaro/statsd.v2) - -## Introduction - -statsd is a simple and efficient [Statsd](https://github.com/etsy/statsd) -client. - -See the [benchmark](https://github.com/alexcesaro/statsdbench) for a comparison -with other Go StatsD clients. - -## Features - -- Supports all StatsD metrics: counter, gauge, timing and set -- Supports InfluxDB and Datadog tags -- Fast and GC-friendly: all functions for sending metrics do not allocate -- Efficient: metrics are buffered by default -- Simple and clean API -- 100% test coverage -- Versioned API using gopkg.in - - -## Documentation - -https://godoc.org/gopkg.in/alexcesaro/statsd.v2 - - -## Download - - go get gopkg.in/alexcesaro/statsd.v2 - - -## Example - -See the [examples in the documentation](https://godoc.org/gopkg.in/alexcesaro/statsd.v2#example-package). - - -## License - -[MIT](LICENSE) - - -## Contribute - -Do you have any question the documentation does not answer? Is there a use case -that you feel is common and is not well-addressed by the current API? - -If so you are more than welcome to ask questions in the -[thread on golang-nuts](https://groups.google.com/d/topic/golang-nuts/Tz6t4_iLgnw/discussion) -or open an issue or send a pull-request here on Github. diff --git a/vendor/github.com/blang/semver/.travis.yml b/vendor/github.com/blang/semver/.travis.yml deleted file mode 100644 index 102fb9a691..0000000000 --- a/vendor/github.com/blang/semver/.travis.yml +++ /dev/null @@ -1,21 +0,0 @@ -language: go -matrix: - include: - - go: 1.4.3 - - go: 1.5.4 - - go: 1.6.3 - - go: 1.7 - - go: tip - allow_failures: - - go: tip -install: -- go get golang.org/x/tools/cmd/cover -- go get github.com/mattn/goveralls -script: -- echo "Test and track coverage" ; $HOME/gopath/bin/goveralls -package "." -service=travis-ci - -repotoken $COVERALLS_TOKEN -- echo "Build examples" ; cd examples && go build -- echo "Check if gofmt'd" ; diff -u <(echo -n) <(gofmt -d -s .) -env: - global: - secure: HroGEAUQpVq9zX1b1VIkraLiywhGbzvNnTZq2TMxgK7JHP8xqNplAeF1izrR2i4QLL9nsY+9WtYss4QuPvEtZcVHUobw6XnL6radF7jS1LgfYZ9Y7oF+zogZ2I5QUMRLGA7rcxQ05s7mKq3XZQfeqaNts4bms/eZRefWuaFZbkw= diff --git a/vendor/github.com/blang/semver/README.md b/vendor/github.com/blang/semver/README.md deleted file mode 100644 index 08b2e4a3d7..0000000000 --- a/vendor/github.com/blang/semver/README.md +++ /dev/null @@ -1,194 +0,0 @@ -semver for golang [![Build Status](https://travis-ci.org/blang/semver.svg?branch=master)](https://travis-ci.org/blang/semver) [![GoDoc](https://godoc.org/github.com/blang/semver?status.png)](https://godoc.org/github.com/blang/semver) [![Coverage Status](https://img.shields.io/coveralls/blang/semver.svg)](https://coveralls.io/r/blang/semver?branch=master) -====== - -semver is a [Semantic Versioning](http://semver.org/) library written in golang. It fully covers spec version `2.0.0`. - -Usage ------ -```bash -$ go get github.com/blang/semver -``` -Note: Always vendor your dependencies or fix on a specific version tag. - -```go -import github.com/blang/semver -v1, err := semver.Make("1.0.0-beta") -v2, err := semver.Make("2.0.0-beta") -v1.Compare(v2) -``` - -Also check the [GoDocs](http://godoc.org/github.com/blang/semver). - -Why should I use this lib? ------ - -- Fully spec compatible -- No reflection -- No regex -- Fully tested (Coverage >99%) -- Readable parsing/validation errors -- Fast (See [Benchmarks](#benchmarks)) -- Only Stdlib -- Uses values instead of pointers -- Many features, see below - - -Features ------ - -- Parsing and validation at all levels -- Comparator-like comparisons -- Compare Helper Methods -- InPlace manipulation -- Ranges `>=1.0.0 <2.0.0 || >=3.0.0 !3.0.1-beta.1` -- Wildcards `>=1.x`, `<=2.5.x` -- Sortable (implements sort.Interface) -- database/sql compatible (sql.Scanner/Valuer) -- encoding/json compatible (json.Marshaler/Unmarshaler) - -Ranges ------- - -A `Range` is a set of conditions which specify which versions satisfy the range. - -A condition is composed of an operator and a version. The supported operators are: - -- `<1.0.0` Less than `1.0.0` -- `<=1.0.0` Less than or equal to `1.0.0` -- `>1.0.0` Greater than `1.0.0` -- `>=1.0.0` Greater than or equal to `1.0.0` -- `1.0.0`, `=1.0.0`, `==1.0.0` Equal to `1.0.0` -- `!1.0.0`, `!=1.0.0` Not equal to `1.0.0`. Excludes version `1.0.0`. - -Note that spaces between the operator and the version will be gracefully tolerated. - -A `Range` can link multiple `Ranges` separated by space: - -Ranges can be linked by logical AND: - - - `>1.0.0 <2.0.0` would match between both ranges, so `1.1.1` and `1.8.7` but not `1.0.0` or `2.0.0` - - `>1.0.0 <3.0.0 !2.0.3-beta.2` would match every version between `1.0.0` and `3.0.0` except `2.0.3-beta.2` - -Ranges can also be linked by logical OR: - - - `<2.0.0 || >=3.0.0` would match `1.x.x` and `3.x.x` but not `2.x.x` - -AND has a higher precedence than OR. It's not possible to use brackets. - -Ranges can be combined by both AND and OR - - - `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1` - -Range usage: - -``` -v, err := semver.Parse("1.2.3") -range, err := semver.ParseRange(">1.0.0 <2.0.0 || >=3.0.0") -if range(v) { - //valid -} - -``` - -Example ------ - -Have a look at full examples in [examples/main.go](examples/main.go) - -```go -import github.com/blang/semver - -v, err := semver.Make("0.0.1-alpha.preview+123.github") -fmt.Printf("Major: %d\n", v.Major) -fmt.Printf("Minor: %d\n", v.Minor) -fmt.Printf("Patch: %d\n", v.Patch) -fmt.Printf("Pre: %s\n", v.Pre) -fmt.Printf("Build: %s\n", v.Build) - -// Prerelease versions array -if len(v.Pre) > 0 { - fmt.Println("Prerelease versions:") - for i, pre := range v.Pre { - fmt.Printf("%d: %q\n", i, pre) - } -} - -// Build meta data array -if len(v.Build) > 0 { - fmt.Println("Build meta data:") - for i, build := range v.Build { - fmt.Printf("%d: %q\n", i, build) - } -} - -v001, err := semver.Make("0.0.1") -// Compare using helpers: v.GT(v2), v.LT, v.GTE, v.LTE -v001.GT(v) == true -v.LT(v001) == true -v.GTE(v) == true -v.LTE(v) == true - -// Or use v.Compare(v2) for comparisons (-1, 0, 1): -v001.Compare(v) == 1 -v.Compare(v001) == -1 -v.Compare(v) == 0 - -// Manipulate Version in place: -v.Pre[0], err = semver.NewPRVersion("beta") -if err != nil { - fmt.Printf("Error parsing pre release version: %q", err) -} - -fmt.Println("\nValidate versions:") -v.Build[0] = "?" - -err = v.Validate() -if err != nil { - fmt.Printf("Validation failed: %s\n", err) -} -``` - - -Benchmarks ------ - - BenchmarkParseSimple-4 5000000 390 ns/op 48 B/op 1 allocs/op - BenchmarkParseComplex-4 1000000 1813 ns/op 256 B/op 7 allocs/op - BenchmarkParseAverage-4 1000000 1171 ns/op 163 B/op 4 allocs/op - BenchmarkStringSimple-4 20000000 119 ns/op 16 B/op 1 allocs/op - BenchmarkStringLarger-4 10000000 206 ns/op 32 B/op 2 allocs/op - BenchmarkStringComplex-4 5000000 324 ns/op 80 B/op 3 allocs/op - BenchmarkStringAverage-4 5000000 273 ns/op 53 B/op 2 allocs/op - BenchmarkValidateSimple-4 200000000 9.33 ns/op 0 B/op 0 allocs/op - BenchmarkValidateComplex-4 3000000 469 ns/op 0 B/op 0 allocs/op - BenchmarkValidateAverage-4 5000000 256 ns/op 0 B/op 0 allocs/op - BenchmarkCompareSimple-4 100000000 11.8 ns/op 0 B/op 0 allocs/op - BenchmarkCompareComplex-4 50000000 30.8 ns/op 0 B/op 0 allocs/op - BenchmarkCompareAverage-4 30000000 41.5 ns/op 0 B/op 0 allocs/op - BenchmarkSort-4 3000000 419 ns/op 256 B/op 2 allocs/op - BenchmarkRangeParseSimple-4 2000000 850 ns/op 192 B/op 5 allocs/op - BenchmarkRangeParseAverage-4 1000000 1677 ns/op 400 B/op 10 allocs/op - BenchmarkRangeParseComplex-4 300000 5214 ns/op 1440 B/op 30 allocs/op - BenchmarkRangeMatchSimple-4 50000000 25.6 ns/op 0 B/op 0 allocs/op - BenchmarkRangeMatchAverage-4 30000000 56.4 ns/op 0 B/op 0 allocs/op - BenchmarkRangeMatchComplex-4 10000000 153 ns/op 0 B/op 0 allocs/op - -See benchmark cases at [semver_test.go](semver_test.go) - - -Motivation ------ - -I simply couldn't find any lib supporting the full spec. Others were just wrong or used reflection and regex which i don't like. - - -Contribution ------ - -Feel free to make a pull request. For bigger changes create a issue first to discuss about it. - - -License ------ - -See [LICENSE](LICENSE) file. diff --git a/vendor/github.com/blang/semver/package.json b/vendor/github.com/blang/semver/package.json deleted file mode 100644 index 1cf8ebdd9c..0000000000 --- a/vendor/github.com/blang/semver/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "author": "blang", - "bugs": { - "URL": "https://github.com/blang/semver/issues", - "url": "https://github.com/blang/semver/issues" - }, - "gx": { - "dvcsimport": "github.com/blang/semver" - }, - "gxVersion": "0.10.0", - "language": "go", - "license": "MIT", - "name": "semver", - "releaseCmd": "git commit -a -m \"gx publish $VERSION\"", - "version": "3.5.1" -} - diff --git a/vendor/github.com/dgrijalva/jwt-go/.gitignore b/vendor/github.com/dgrijalva/jwt-go/.gitignore deleted file mode 100644 index 80bed650ec..0000000000 --- a/vendor/github.com/dgrijalva/jwt-go/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.DS_Store -bin - - diff --git a/vendor/github.com/dgrijalva/jwt-go/.travis.yml b/vendor/github.com/dgrijalva/jwt-go/.travis.yml deleted file mode 100644 index 1027f56cd9..0000000000 --- a/vendor/github.com/dgrijalva/jwt-go/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: go - -script: - - go vet ./... - - go test -v ./... - -go: - - 1.3 - - 1.4 - - 1.5 - - 1.6 - - 1.7 - - tip diff --git a/vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md b/vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md deleted file mode 100644 index 7fc1f793cb..0000000000 --- a/vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md +++ /dev/null @@ -1,97 +0,0 @@ -## Migration Guide from v2 -> v3 - -Version 3 adds several new, frequently requested features. To do so, it introduces a few breaking changes. We've worked to keep these as minimal as possible. This guide explains the breaking changes and how you can quickly update your code. - -### `Token.Claims` is now an interface type - -The most requested feature from the 2.0 verison of this library was the ability to provide a custom type to the JSON parser for claims. This was implemented by introducing a new interface, `Claims`, to replace `map[string]interface{}`. We also included two concrete implementations of `Claims`: `MapClaims` and `StandardClaims`. - -`MapClaims` is an alias for `map[string]interface{}` with built in validation behavior. It is the default claims type when using `Parse`. The usage is unchanged except you must type cast the claims property. - -The old example for parsing a token looked like this.. - -```go - if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil { - fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"]) - } -``` - -is now directly mapped to... - -```go - if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil { - claims := token.Claims.(jwt.MapClaims) - fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"]) - } -``` - -`StandardClaims` is designed to be embedded in your custom type. You can supply a custom claims type with the new `ParseWithClaims` function. Here's an example of using a custom claims type. - -```go - type MyCustomClaims struct { - User string - *StandardClaims - } - - if token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, keyLookupFunc); err == nil { - claims := token.Claims.(*MyCustomClaims) - fmt.Printf("Token for user %v expires %v", claims.User, claims.StandardClaims.ExpiresAt) - } -``` - -### `ParseFromRequest` has been moved - -To keep this library focused on the tokens without becoming overburdened with complex request processing logic, `ParseFromRequest` and its new companion `ParseFromRequestWithClaims` have been moved to a subpackage, `request`. The method signatues have also been augmented to receive a new argument: `Extractor`. - -`Extractors` do the work of picking the token string out of a request. The interface is simple and composable. - -This simple parsing example: - -```go - if token, err := jwt.ParseFromRequest(tokenString, req, keyLookupFunc); err == nil { - fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"]) - } -``` - -is directly mapped to: - -```go - if token, err := request.ParseFromRequest(req, request.OAuth2Extractor, keyLookupFunc); err == nil { - claims := token.Claims.(jwt.MapClaims) - fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"]) - } -``` - -There are several concrete `Extractor` types provided for your convenience: - -* `HeaderExtractor` will search a list of headers until one contains content. -* `ArgumentExtractor` will search a list of keys in request query and form arguments until one contains content. -* `MultiExtractor` will try a list of `Extractors` in order until one returns content. -* `AuthorizationHeaderExtractor` will look in the `Authorization` header for a `Bearer` token. -* `OAuth2Extractor` searches the places an OAuth2 token would be specified (per the spec): `Authorization` header and `access_token` argument -* `PostExtractionFilter` wraps an `Extractor`, allowing you to process the content before it's parsed. A simple example is stripping the `Bearer ` text from a header - - -### RSA signing methods no longer accept `[]byte` keys - -Due to a [critical vulnerability](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/), we've decided the convenience of accepting `[]byte` instead of `rsa.PublicKey` or `rsa.PrivateKey` isn't worth the risk of misuse. - -To replace this behavior, we've added two helper methods: `ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error)` and `ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error)`. These are just simple helpers for unpacking PEM encoded PKCS1 and PKCS8 keys. If your keys are encoded any other way, all you need to do is convert them to the `crypto/rsa` package's types. - -```go - func keyLookupFunc(*Token) (interface{}, error) { - // Don't forget to validate the alg is what you expect: - if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { - return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) - } - - // Look up key - key, err := lookupPublicKey(token.Header["kid"]) - if err != nil { - return nil, err - } - - // Unpack key from PEM encoded PKCS8 - return jwt.ParseRSAPublicKeyFromPEM(key) - } -``` diff --git a/vendor/github.com/dgrijalva/jwt-go/README.md b/vendor/github.com/dgrijalva/jwt-go/README.md deleted file mode 100644 index 25aec486c6..0000000000 --- a/vendor/github.com/dgrijalva/jwt-go/README.md +++ /dev/null @@ -1,85 +0,0 @@ -A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html) - -[![Build Status](https://travis-ci.org/dgrijalva/jwt-go.svg?branch=master)](https://travis-ci.org/dgrijalva/jwt-go) - -**BREAKING CHANGES:*** Version 3.0.0 is here. It includes _a lot_ of changes including a few that break the API. We've tried to break as few things as possible, so there should just be a few type signature changes. A full list of breaking changes is available in `VERSION_HISTORY.md`. See `MIGRATION_GUIDE.md` for more information on updating your code. - -**NOTICE:** It's important that you [validate the `alg` presented is what you expect](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/). This library attempts to make it easy to do the right thing by requiring key types match the expected alg, but you should take the extra step to verify it in your usage. See the examples provided. - - -## What the heck is a JWT? - -JWT.io has [a great introduction](https://jwt.io/introduction) to JSON Web Tokens. - -In short, it's a signed JSON object that does something useful (for example, authentication). It's commonly used for `Bearer` tokens in Oauth 2. A token is made of three parts, separated by `.`'s. The first two parts are JSON objects, that have been [base64url](http://tools.ietf.org/html/rfc4648) encoded. The last part is the signature, encoded the same way. - -The first part is called the header. It contains the necessary information for verifying the last part, the signature. For example, which encryption method was used for signing and what key was used. - -The part in the middle is the interesting bit. It's called the Claims and contains the actual stuff you care about. Refer to [the RFC](http://self-issued.info/docs/draft-jones-json-web-token.html) for information about reserved keys and the proper way to add your own. - -## What's in the box? - -This library supports the parsing and verification as well as the generation and signing of JWTs. Current supported signing algorithms are HMAC SHA, RSA, RSA-PSS, and ECDSA, though hooks are present for adding your own. - -## Examples - -See [the project documentation](https://godoc.org/github.com/dgrijalva/jwt-go) for examples of usage: - -* [Simple example of parsing and validating a token](https://godoc.org/github.com/dgrijalva/jwt-go#example-Parse--Hmac) -* [Simple example of building and signing a token](https://godoc.org/github.com/dgrijalva/jwt-go#example-New--Hmac) -* [Directory of Examples](https://godoc.org/github.com/dgrijalva/jwt-go#pkg-examples) - -## Extensions - -This library publishes all the necessary components for adding your own signing methods. Simply implement the `SigningMethod` interface and register a factory method using `RegisterSigningMethod`. - -Here's an example of an extension that integrates with the Google App Engine signing tools: https://github.com/someone1/gcp-jwt-go - -## Compliance - -This library was last reviewed to comply with [RTF 7519](http://www.rfc-editor.org/info/rfc7519) dated May 2015 with a few notable differences: - -* In order to protect against accidental use of [Unsecured JWTs](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#UnsecuredJWT), tokens using `alg=none` will only be accepted if the constant `jwt.UnsafeAllowNoneSignatureType` is provided as the key. - -## Project Status & Versioning - -This library is considered production ready. Feedback and feature requests are appreciated. The API should be considered stable. There should be very few backwards-incompatible changes outside of major version updates (and only with good reason). - -This project uses [Semantic Versioning 2.0.0](http://semver.org). Accepted pull requests will land on `master`. Periodically, versions will be tagged from `master`. You can find all the releases on [the project releases page](https://github.com/dgrijalva/jwt-go/releases). - -While we try to make it obvious when we make breaking changes, there isn't a great mechanism for pushing announcements out to users. You may want to use this alternative package include: `gopkg.in/dgrijalva/jwt-go.v2`. It will do the right thing WRT semantic versioning. - -## Usage Tips - -### Signing vs Encryption - -A token is simply a JSON object that is signed by its author. this tells you exactly two things about the data: - -* The author of the token was in the possession of the signing secret -* The data has not been modified since it was signed - -It's important to know that JWT does not provide encryption, which means anyone who has access to the token can read its contents. If you need to protect (encrypt) the data, there is a companion spec, `JWE`, that provides this functionality. JWE is currently outside the scope of this library. - -### Choosing a Signing Method - -There are several signing methods available, and you should probably take the time to learn about the various options before choosing one. The principal design decision is most likely going to be symmetric vs asymmetric. - -Symmetric signing methods, such as HSA, use only a single secret. This is probably the simplest signing method to use since any `[]byte` can be used as a valid secret. They are also slightly computationally faster to use, though this rarely is enough to matter. Symmetric signing methods work the best when both producers and consumers of tokens are trusted, or even the same system. Since the same secret is used to both sign and validate tokens, you can't easily distribute the key for validation. - -Asymmetric signing methods, such as RSA, use different keys for signing and verifying tokens. This makes it possible to produce tokens with a private key, and allow any consumer to access the public key for verification. - -### JWT and OAuth - -It's worth mentioning that OAuth and JWT are not the same thing. A JWT token is simply a signed JSON object. It can be used anywhere such a thing is useful. There is some confusion, though, as JWT is the most common type of bearer token used in OAuth2 authentication. - -Without going too far down the rabbit hole, here's a description of the interaction of these technologies: - -* OAuth is a protocol for allowing an identity provider to be separate from the service a user is logging in to. For example, whenever you use Facebook to log into a different service (Yelp, Spotify, etc), you are using OAuth. -* OAuth defines several options for passing around authentication data. One popular method is called a "bearer token". A bearer token is simply a string that _should_ only be held by an authenticated user. Thus, simply presenting this token proves your identity. You can probably derive from here why a JWT might make a good bearer token. -* Because bearer tokens are used for authentication, it's important they're kept secret. This is why transactions that use bearer tokens typically happen over SSL. - -## More - -Documentation can be found [on godoc.org](http://godoc.org/github.com/dgrijalva/jwt-go). - -The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. You'll also find several implementation examples in the documentation. diff --git a/vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md b/vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md deleted file mode 100644 index c21551f6bb..0000000000 --- a/vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md +++ /dev/null @@ -1,111 +0,0 @@ -## `jwt-go` Version History - -#### 3.1.0 - -* Improvements to `jwt` command line tool -* Added `SkipClaimsValidation` option to `Parser` -* Documentation updates - -#### 3.0.0 - -* **Compatibility Breaking Changes**: See MIGRATION_GUIDE.md for tips on updating your code - * Dropped support for `[]byte` keys when using RSA signing methods. This convenience feature could contribute to security vulnerabilities involving mismatched key types with signing methods. - * `ParseFromRequest` has been moved to `request` subpackage and usage has changed - * The `Claims` property on `Token` is now type `Claims` instead of `map[string]interface{}`. The default value is type `MapClaims`, which is an alias to `map[string]interface{}`. This makes it possible to use a custom type when decoding claims. -* Other Additions and Changes - * Added `Claims` interface type to allow users to decode the claims into a custom type - * Added `ParseWithClaims`, which takes a third argument of type `Claims`. Use this function instead of `Parse` if you have a custom type you'd like to decode into. - * Dramatically improved the functionality and flexibility of `ParseFromRequest`, which is now in the `request` subpackage - * Added `ParseFromRequestWithClaims` which is the `FromRequest` equivalent of `ParseWithClaims` - * Added new interface type `Extractor`, which is used for extracting JWT strings from http requests. Used with `ParseFromRequest` and `ParseFromRequestWithClaims`. - * Added several new, more specific, validation errors to error type bitmask - * Moved examples from README to executable example files - * Signing method registry is now thread safe - * Added new property to `ValidationError`, which contains the raw error returned by calls made by parse/verify (such as those returned by keyfunc or json parser) - -#### 2.7.0 - -This will likely be the last backwards compatible release before 3.0.0, excluding essential bug fixes. - -* Added new option `-show` to the `jwt` command that will just output the decoded token without verifying -* Error text for expired tokens includes how long it's been expired -* Fixed incorrect error returned from `ParseRSAPublicKeyFromPEM` -* Documentation updates - -#### 2.6.0 - -* Exposed inner error within ValidationError -* Fixed validation errors when using UseJSONNumber flag -* Added several unit tests - -#### 2.5.0 - -* Added support for signing method none. You shouldn't use this. The API tries to make this clear. -* Updated/fixed some documentation -* Added more helpful error message when trying to parse tokens that begin with `BEARER ` - -#### 2.4.0 - -* Added new type, Parser, to allow for configuration of various parsing parameters - * You can now specify a list of valid signing methods. Anything outside this set will be rejected. - * You can now opt to use the `json.Number` type instead of `float64` when parsing token JSON -* Added support for [Travis CI](https://travis-ci.org/dgrijalva/jwt-go) -* Fixed some bugs with ECDSA parsing - -#### 2.3.0 - -* Added support for ECDSA signing methods -* Added support for RSA PSS signing methods (requires go v1.4) - -#### 2.2.0 - -* Gracefully handle a `nil` `Keyfunc` being passed to `Parse`. Result will now be the parsed token and an error, instead of a panic. - -#### 2.1.0 - -Backwards compatible API change that was missed in 2.0.0. - -* The `SignedString` method on `Token` now takes `interface{}` instead of `[]byte` - -#### 2.0.0 - -There were two major reasons for breaking backwards compatibility with this update. The first was a refactor required to expand the width of the RSA and HMAC-SHA signing implementations. There will likely be no required code changes to support this change. - -The second update, while unfortunately requiring a small change in integration, is required to open up this library to other signing methods. Not all keys used for all signing methods have a single standard on-disk representation. Requiring `[]byte` as the type for all keys proved too limiting. Additionally, this implementation allows for pre-parsed tokens to be reused, which might matter in an application that parses a high volume of tokens with a small set of keys. Backwards compatibilty has been maintained for passing `[]byte` to the RSA signing methods, but they will also accept `*rsa.PublicKey` and `*rsa.PrivateKey`. - -It is likely the only integration change required here will be to change `func(t *jwt.Token) ([]byte, error)` to `func(t *jwt.Token) (interface{}, error)` when calling `Parse`. - -* **Compatibility Breaking Changes** - * `SigningMethodHS256` is now `*SigningMethodHMAC` instead of `type struct` - * `SigningMethodRS256` is now `*SigningMethodRSA` instead of `type struct` - * `KeyFunc` now returns `interface{}` instead of `[]byte` - * `SigningMethod.Sign` now takes `interface{}` instead of `[]byte` for the key - * `SigningMethod.Verify` now takes `interface{}` instead of `[]byte` for the key -* Renamed type `SigningMethodHS256` to `SigningMethodHMAC`. Specific sizes are now just instances of this type. - * Added public package global `SigningMethodHS256` - * Added public package global `SigningMethodHS384` - * Added public package global `SigningMethodHS512` -* Renamed type `SigningMethodRS256` to `SigningMethodRSA`. Specific sizes are now just instances of this type. - * Added public package global `SigningMethodRS256` - * Added public package global `SigningMethodRS384` - * Added public package global `SigningMethodRS512` -* Moved sample private key for HMAC tests from an inline value to a file on disk. Value is unchanged. -* Refactored the RSA implementation to be easier to read -* Exposed helper methods `ParseRSAPrivateKeyFromPEM` and `ParseRSAPublicKeyFromPEM` - -#### 1.0.2 - -* Fixed bug in parsing public keys from certificates -* Added more tests around the parsing of keys for RS256 -* Code refactoring in RS256 implementation. No functional changes - -#### 1.0.1 - -* Fixed panic if RS256 signing method was passed an invalid key - -#### 1.0.0 - -* First versioned release -* API stabilized -* Supports creating, signing, parsing, and validating JWT tokens -* Supports RS256 and HS256 signing methods \ No newline at end of file diff --git a/vendor/github.com/ghodss/yaml/.gitignore b/vendor/github.com/ghodss/yaml/.gitignore deleted file mode 100644 index e256a31e00..0000000000 --- a/vendor/github.com/ghodss/yaml/.gitignore +++ /dev/null @@ -1,20 +0,0 @@ -# OSX leaves these everywhere on SMB shares -._* - -# Eclipse files -.classpath -.project -.settings/** - -# Emacs save files -*~ - -# Vim-related files -[._]*.s[a-w][a-z] -[._]s[a-w][a-z] -*.un~ -Session.vim -.netrwhist - -# Go test binaries -*.test diff --git a/vendor/github.com/ghodss/yaml/.travis.yml b/vendor/github.com/ghodss/yaml/.travis.yml deleted file mode 100644 index 0e9d6edc01..0000000000 --- a/vendor/github.com/ghodss/yaml/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: go -go: - - 1.3 - - 1.4 -script: - - go test - - go build diff --git a/vendor/github.com/ghodss/yaml/README.md b/vendor/github.com/ghodss/yaml/README.md deleted file mode 100644 index 0200f75b4d..0000000000 --- a/vendor/github.com/ghodss/yaml/README.md +++ /dev/null @@ -1,121 +0,0 @@ -# YAML marshaling and unmarshaling support for Go - -[![Build Status](https://travis-ci.org/ghodss/yaml.svg)](https://travis-ci.org/ghodss/yaml) - -## Introduction - -A wrapper around [go-yaml](https://github.com/go-yaml/yaml) designed to enable a better way of handling YAML when marshaling to and from structs. - -In short, this library first converts YAML to JSON using go-yaml and then uses `json.Marshal` and `json.Unmarshal` to convert to or from the struct. This means that it effectively reuses the JSON struct tags as well as the custom JSON methods `MarshalJSON` and `UnmarshalJSON` unlike go-yaml. For a detailed overview of the rationale behind this method, [see this blog post](http://ghodss.com/2014/the-right-way-to-handle-yaml-in-golang/). - -## Compatibility - -This package uses [go-yaml](https://github.com/go-yaml/yaml) and therefore supports [everything go-yaml supports](https://github.com/go-yaml/yaml#compatibility). - -## Caveats - -**Caveat #1:** When using `yaml.Marshal` and `yaml.Unmarshal`, binary data should NOT be preceded with the `!!binary` YAML tag. If you do, go-yaml will convert the binary data from base64 to native binary data, which is not compatible with JSON. You can still use binary in your YAML files though - just store them without the `!!binary` tag and decode the base64 in your code (e.g. in the custom JSON methods `MarshalJSON` and `UnmarshalJSON`). This also has the benefit that your YAML and your JSON binary data will be decoded exactly the same way. As an example: - -``` -BAD: - exampleKey: !!binary gIGC - -GOOD: - exampleKey: gIGC -... and decode the base64 data in your code. -``` - -**Caveat #2:** When using `YAMLToJSON` directly, maps with keys that are maps will result in an error since this is not supported by JSON. This error will occur in `Unmarshal` as well since you can't unmarshal map keys anyways since struct fields can't be keys. - -## Installation and usage - -To install, run: - -``` -$ go get github.com/ghodss/yaml -``` - -And import using: - -``` -import "github.com/ghodss/yaml" -``` - -Usage is very similar to the JSON library: - -```go -package main - -import ( - "fmt" - - "github.com/ghodss/yaml" -) - -type Person struct { - Name string `json:"name"` // Affects YAML field names too. - Age int `json:"age"` -} - -func main() { - // Marshal a Person struct to YAML. - p := Person{"John", 30} - y, err := yaml.Marshal(p) - if err != nil { - fmt.Printf("err: %v\n", err) - return - } - fmt.Println(string(y)) - /* Output: - age: 30 - name: John - */ - - // Unmarshal the YAML back into a Person struct. - var p2 Person - err = yaml.Unmarshal(y, &p2) - if err != nil { - fmt.Printf("err: %v\n", err) - return - } - fmt.Println(p2) - /* Output: - {John 30} - */ -} -``` - -`yaml.YAMLToJSON` and `yaml.JSONToYAML` methods are also available: - -```go -package main - -import ( - "fmt" - - "github.com/ghodss/yaml" -) - -func main() { - j := []byte(`{"name": "John", "age": 30}`) - y, err := yaml.JSONToYAML(j) - if err != nil { - fmt.Printf("err: %v\n", err) - return - } - fmt.Println(string(y)) - /* Output: - name: John - age: 30 - */ - j2, err := yaml.YAMLToJSON(y) - if err != nil { - fmt.Printf("err: %v\n", err) - return - } - fmt.Println(string(j2)) - /* Output: - {"age":30,"name":"John"} - */ -} -``` diff --git a/vendor/github.com/go-bindata/go-bindata/CONTRIBUTING.md b/vendor/github.com/go-bindata/go-bindata/CONTRIBUTING.md deleted file mode 100644 index e0732f54eb..0000000000 --- a/vendor/github.com/go-bindata/go-bindata/CONTRIBUTING.md +++ /dev/null @@ -1,79 +0,0 @@ -## Contribution guidelines. - -So you wish to contribute to this project? Fantastic! -Here are a few guidelines to help you do this in a -streamlined fashion. - - -## Bug reports - -When supplying a bug report, please consider the following guidelines. -These serve to make it easier for us to address the issue and find a solution. -Most of these are pretty self-evident, but sometimes it is still necessary -to reiterate them. - -* Be clear in the way you express the problem. Use simple language and - just enough of it to clearly define the issue. Not everyone is a native - English speaker. And while most can handle themselves pretty well, - it helps to stay away from more esoteric vocabulary. - - Be patient with non-native English speakers. If their bug reports - or comments are hard to understand, just ask for clarification. - Do not start guessing at their meaning, as this may just lead to - more confusion and misunderstandings. -* Clearly define any information which is relevant to the problem. - This includes library versions, operating system and any other - external dependencies which may be needed. -* Where applicable, provide a step-by-step listing of the way to - reproduce the problem. Make sure this is the simplest possible - way to do so. Omit any and all unneccesary steps, because they may - just complicate our understanding of the real problem. - If need be, create a whole new code project on your local machine, - which specifically tries to create the problem you are running into; - nothing more, nothing less. - - Include this program in the bug report. It often suffices to paste - the code in a [Gist](https://gist.github.com) or on the - [Go playground](http://play.golang.org). -* If possible, provide us with a listing of the steps you have already - undertaken to solve the problem. This can save us a great deal of - wasted time, trying out solutions you have already covered. - - -## Pull requests - -Bug reports are great. Supplying fixes to bugs is even better. -When submitting a pull request, the following guidelines are -good to keep in mind: - -* `go fmt`: **Always** run your code through `go fmt`, before - committing it. Code has to be readable by many different - people. And the only way this will be as painless as possible, - is if we all stick to the same code style. - - Some of our projects may have automated build-servers hooked up - to commit hooks. These will vet any submitted code and determine - if it meets a set of properties. One of which is code formatting. - These servers will outright deny a submission which has not been - run through `go fmt`, even if the code itself is correct. - - We try to maintain a zero-tolerance policy on this matter, - because consistently formatted code makes life a great deal - easier for everyone involved. -* Commit log messages: When committing changes, do so often and - clearly -- Even if you have changed only 1 character in a code - comment. This means that commit log messages should clearly state - exactly what the change does and why. If it fixes a known issue, - then mention the issue number in the commit log. E.g.: - - > Fixes return value for `foo/boo.Baz()` to be consistent with - > the rest of the API. This addresses issue #32 - - Do not pile a lot of unrelated changes into a single commit. - Pick and choose only those changes for a single commit, which are - directly related. We would much rather see a hundred commits - saying nothing but `"Runs go fmt"` in between any real fixes - than have these style changes embedded in those real fixes. - It creates a lot of noise when trying to review code. - - diff --git a/vendor/github.com/go-bindata/go-bindata/Makefile b/vendor/github.com/go-bindata/go-bindata/Makefile deleted file mode 100644 index 84b661cb23..0000000000 --- a/vendor/github.com/go-bindata/go-bindata/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -all: - make -C testdata diff --git a/vendor/github.com/go-bindata/go-bindata/README.md b/vendor/github.com/go-bindata/go-bindata/README.md deleted file mode 100644 index e8c7e5bcb6..0000000000 --- a/vendor/github.com/go-bindata/go-bindata/README.md +++ /dev/null @@ -1,191 +0,0 @@ -## bindata - -[![Go Report Card](https://goreportcard.com/badge/github.com/go-bindata/bindata)](https://goreportcard.com/report/github.com/go-bindata/bindata) - -This package converts any file into managable Go source code. Useful for -embedding binary data into a go program. The file data is optionally gzip -compressed before being converted to a raw byte slice. - -It comes with a command line tool in the `go-bindata` sub directory. -This tool offers a set of command line options, used to customize the -output being generated. - - -### Installation - -To install the library and command line program, use the following: - - go get -u github.com/go-bindata/go-bindata/... - - -### Usage - -Conversion is done on one or more sets of files. They are all embedded in a new -Go source file, along with a table of contents and an `Asset` function, -which allows quick access to the asset, based on its name. - -The simplest invocation generates a `bindata.go` file in the current -working directory. It includes all assets from the `data` directory. - - $ go-bindata data/ - -To include all input sub-directories recursively, use the elipsis postfix -as defined for Go import paths. Otherwise it will only consider assets in the -input directory itself. - - $ go-bindata data/... - -To specify the name of the output file being generated, we use the following: - - $ go-bindata -o myfile.go data/ - -Multiple input directories can be specified if necessary. - - $ go-bindata dir1/... /path/to/dir2/... dir3 - - -The following paragraphs detail some of the command line options which can be -supplied to `go-bindata`. Refer to the `testdata/out` directory for various -output examples from the assets in `testdata/in`. Each example uses different -command line options. - -To ignore files, pass in regexes using -ignore, for example: - - $ go-bindata -ignore=\\.gitignore data/... - -### Accessing an asset - -To access asset data, we use the `Asset(string) ([]byte, error)` function which -is included in the generated output. - - data, err := Asset("pub/style/foo.css") - if err != nil { - // Asset was not found. - } - - // use asset data - - -### Debug vs Release builds - -When invoking the program with the `-debug` flag, the generated code does -not actually include the asset data. Instead, it generates function stubs -which load the data from the original file on disk. The asset API remains -identical between debug and release builds, so your code will not have to -change. - -This is useful during development when you expect the assets to change often. -The host application using these assets uses the same API in both cases and -will not have to care where the actual data comes from. - -An example is a Go webserver with some embedded, static web content like -HTML, JS and CSS files. While developing it, you do not want to rebuild the -whole server and restart it every time you make a change to a bit of -javascript. You just want to build and launch the server once. Then just press -refresh in the browser to see those changes. Embedding the assets with the -`debug` flag allows you to do just that. When you are finished developing and -ready for deployment, just re-invoke `go-bindata` without the `-debug` flag. -It will now embed the latest version of the assets. - - -### Lower memory footprint - -Using the `-nomemcopy` flag, will alter the way the output file is generated. -It will employ a hack that allows us to read the file data directly from -the compiled program's `.rodata` section. This ensures that when we call -call our generated function, we omit unnecessary memcopies. - -The downside of this, is that it requires dependencies on the `reflect` and -`unsafe` packages. These may be restricted on platforms like AppEngine and -thus prevent you from using this mode. - -Another disadvantage is that the byte slice we create, is strictly read-only. -For most use-cases this is not a problem, but if you ever try to alter the -returned byte slice, a runtime panic is thrown. Use this mode only on target -platforms where memory constraints are an issue. - -The default behaviour is to use the old code generation method. This -prevents the two previously mentioned issues, but will employ at least one -extra memcopy and thus increase memory requirements. - -For instance, consider the following two examples: - -This would be the default mode, using an extra memcopy but gives a safe -implementation without dependencies on `reflect` and `unsafe`: - -```go -func myfile() []byte { - return []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a} -} -``` - -Here is the same functionality, but uses the `.rodata` hack. -The byte slice returned from this example can not be written to without -generating a runtime error. - -```go -var _myfile = "\x89\x50\x4e\x47\x0d\x0a\x1a" - -func myfile() []byte { - var empty [0]byte - sx := (*reflect.StringHeader)(unsafe.Pointer(&_myfile)) - b := empty[:] - bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) - bx.Data = sx.Data - bx.Len = len(_myfile) - bx.Cap = bx.Len - return b -} -``` - - -### Optional compression - -When the `-nocompress` flag is given, the supplied resource is *not* GZIP -compressed before being turned into Go code. The data should still be accessed -through a function call, so nothing changes in the usage of the generated file. - -This feature is useful if you do not care for compression, or the supplied -resource is already compressed. Doing it again would not add any value and may -even increase the size of the data. - -The default behaviour of the program is to use compression. - - -### Path prefix stripping - -The keys used in the `_bindata` map, are the same as the input file name -passed to `go-bindata`. This includes the path. In most cases, this is not -desireable, as it puts potentially sensitive information in your code base. -For this purpose, the tool supplies another command line flag `-prefix`. -This accepts a portion of a path name, which should be stripped off from -the map keys and function names. - -For example, running without the `-prefix` flag, we get: - - $ go-bindata /path/to/templates/ - - _bindata["/path/to/templates/foo.html"] = path_to_templates_foo_html - -Running with the `-prefix` flag, we get: - - $ go-bindata -prefix "/path/to/" /path/to/templates/ - - _bindata["templates/foo.html"] = templates_foo_html - - -### Build tags - -With the optional `-tags` flag, you can specify any go build tags that -must be fulfilled for the output file to be included in a build. This -is useful when including binary data in multiple formats, where the desired -format is specified at build time with the appropriate tags. - -The tags are appended to a `// +build` line in the beginning of the output file -and must follow the build tags syntax specified by the go tool. - -### Related projects - -[go-bindata-assetfs](https://github.com/elazarl/go-bindata-assetfs#readme) - -implements `http.FileSystem` interface. Allows you to serve assets with `net/http`. - diff --git a/vendor/github.com/go-playground/locales/.gitignore b/vendor/github.com/go-playground/locales/.gitignore deleted file mode 100644 index daf913b1b3..0000000000 --- a/vendor/github.com/go-playground/locales/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof diff --git a/vendor/github.com/go-playground/locales/README.md b/vendor/github.com/go-playground/locales/README.md deleted file mode 100644 index b462c93a09..0000000000 --- a/vendor/github.com/go-playground/locales/README.md +++ /dev/null @@ -1,172 +0,0 @@ -## locales -![Project status](https://img.shields.io/badge/version-0.11.1-green.svg) -[![Build Status](https://semaphoreci.com/api/v1/joeybloggs/locales/branches/master/badge.svg)](https://semaphoreci.com/joeybloggs/locales) -[![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/locales)](https://goreportcard.com/report/github.com/go-playground/locales) -[![GoDoc](https://godoc.org/github.com/go-playground/locales?status.svg)](https://godoc.org/github.com/go-playground/locales) -![License](https://img.shields.io/dub/l/vibe-d.svg) -[![Gitter](https://badges.gitter.im/go-playground/locales.svg)](https://gitter.im/go-playground/locales?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) - -Locales is a set of locales generated from the [Unicode CLDR Project](http://cldr.unicode.org/) which can be used independently or within -an i18n package; these were built for use with, but not exclusive to, [Universal Translator](https://github.com/go-playground/universal-translator). - -Features --------- -- [x] Rules generated from the latest [CLDR](http://cldr.unicode.org/index/downloads) data, v31.0.1 -- [x] Contains Cardinal, Ordinal and Range Plural Rules -- [x] Contains Month, Weekday and Timezone translations built in -- [x] Contains Date & Time formatting functions -- [x] Contains Number, Currency, Accounting and Percent formatting functions -- [x] Supports the "Gregorian" calendar only ( my time isn't unlimited, had to draw the line somewhere ) - -Full Tests --------------------- -I could sure use your help adding tests for every locale, it is a huge undertaking and I just don't have the free time to do it all at the moment; -any help would be **greatly appreciated!!!!** please see [issue](https://github.com/go-playground/locales/issues/1) for details. - -Installation ------------ - -Use go get - -```shell -go get github.com/go-playground/locales -``` - -NOTES --------- -You'll notice most return types are []byte, this is because most of the time the results will be concatenated with a larger body -of text and can avoid some allocations if already appending to a byte array, otherwise just cast as string. - -Usage -------- -```go -package main - -import ( - "fmt" - "time" - - "github.com/go-playground/locales/currency" - "github.com/go-playground/locales/en_CA" -) - -func main() { - - loc, _ := time.LoadLocation("America/Toronto") - datetime := time.Date(2016, 02, 03, 9, 0, 1, 0, loc) - - l := en_CA.New() - - // Dates - fmt.Println(l.FmtDateFull(datetime)) - fmt.Println(l.FmtDateLong(datetime)) - fmt.Println(l.FmtDateMedium(datetime)) - fmt.Println(l.FmtDateShort(datetime)) - - // Times - fmt.Println(l.FmtTimeFull(datetime)) - fmt.Println(l.FmtTimeLong(datetime)) - fmt.Println(l.FmtTimeMedium(datetime)) - fmt.Println(l.FmtTimeShort(datetime)) - - // Months Wide - fmt.Println(l.MonthWide(time.January)) - fmt.Println(l.MonthWide(time.February)) - fmt.Println(l.MonthWide(time.March)) - // ... - - // Months Abbreviated - fmt.Println(l.MonthAbbreviated(time.January)) - fmt.Println(l.MonthAbbreviated(time.February)) - fmt.Println(l.MonthAbbreviated(time.March)) - // ... - - // Months Narrow - fmt.Println(l.MonthNarrow(time.January)) - fmt.Println(l.MonthNarrow(time.February)) - fmt.Println(l.MonthNarrow(time.March)) - // ... - - // Weekdays Wide - fmt.Println(l.WeekdayWide(time.Sunday)) - fmt.Println(l.WeekdayWide(time.Monday)) - fmt.Println(l.WeekdayWide(time.Tuesday)) - // ... - - // Weekdays Abbreviated - fmt.Println(l.WeekdayAbbreviated(time.Sunday)) - fmt.Println(l.WeekdayAbbreviated(time.Monday)) - fmt.Println(l.WeekdayAbbreviated(time.Tuesday)) - // ... - - // Weekdays Short - fmt.Println(l.WeekdayShort(time.Sunday)) - fmt.Println(l.WeekdayShort(time.Monday)) - fmt.Println(l.WeekdayShort(time.Tuesday)) - // ... - - // Weekdays Narrow - fmt.Println(l.WeekdayNarrow(time.Sunday)) - fmt.Println(l.WeekdayNarrow(time.Monday)) - fmt.Println(l.WeekdayNarrow(time.Tuesday)) - // ... - - var f64 float64 - - f64 = -10356.4523 - - // Number - fmt.Println(l.FmtNumber(f64, 2)) - - // Currency - fmt.Println(l.FmtCurrency(f64, 2, currency.CAD)) - fmt.Println(l.FmtCurrency(f64, 2, currency.USD)) - - // Accounting - fmt.Println(l.FmtAccounting(f64, 2, currency.CAD)) - fmt.Println(l.FmtAccounting(f64, 2, currency.USD)) - - f64 = 78.12 - - // Percent - fmt.Println(l.FmtPercent(f64, 0)) - - // Plural Rules for locale, so you know what rules you must cover - fmt.Println(l.PluralsCardinal()) - fmt.Println(l.PluralsOrdinal()) - - // Cardinal Plural Rules - fmt.Println(l.CardinalPluralRule(1, 0)) - fmt.Println(l.CardinalPluralRule(1.0, 0)) - fmt.Println(l.CardinalPluralRule(1.0, 1)) - fmt.Println(l.CardinalPluralRule(3, 0)) - - // Ordinal Plural Rules - fmt.Println(l.OrdinalPluralRule(21, 0)) // 21st - fmt.Println(l.OrdinalPluralRule(22, 0)) // 22nd - fmt.Println(l.OrdinalPluralRule(33, 0)) // 33rd - fmt.Println(l.OrdinalPluralRule(34, 0)) // 34th - - // Range Plural Rules - fmt.Println(l.RangePluralRule(1, 0, 1, 0)) // 1-1 - fmt.Println(l.RangePluralRule(1, 0, 2, 0)) // 1-2 - fmt.Println(l.RangePluralRule(5, 0, 8, 0)) // 5-8 -} -``` - -NOTES: -------- -These rules were generated from the [Unicode CLDR Project](http://cldr.unicode.org/), if you encounter any issues -I strongly encourage contributing to the CLDR project to get the locale information corrected and the next time -these locales are regenerated the fix will come with. - -I do however realize that time constraints are often important and so there are two options: - -1. Create your own locale, copy, paste and modify, and ensure it complies with the `Translator` interface. -2. Add an exception in the locale generation code directly and once regenerated, fix will be in place. - -Please to not make fixes inside the locale files, they WILL get overwritten when the locales are regenerated. - -License ------- -Distributed under MIT License, please see license file in code for more details. diff --git a/vendor/github.com/go-playground/locales/logo.png b/vendor/github.com/go-playground/locales/logo.png deleted file mode 100644 index 3038276e6873076ecd542099e95b25037b1c0c34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37360 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