From fc543e0ea988a6cce2ecb5d26ca052316e45cdf0 Mon Sep 17 00:00:00 2001 From: Qingqing Zheng Date: Fri, 6 Apr 2018 13:56:00 -0700 Subject: [PATCH 1/8] check if linuxprofile is nil --- pkg/api/agentPoolOnlyApi/v20180331/validate.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/api/agentPoolOnlyApi/v20180331/validate.go b/pkg/api/agentPoolOnlyApi/v20180331/validate.go index 8798d77fb0..dd808c7491 100644 --- a/pkg/api/agentPoolOnlyApi/v20180331/validate.go +++ b/pkg/api/agentPoolOnlyApi/v20180331/validate.go @@ -84,9 +84,12 @@ func (a *Properties) Validate() error { } } - if e := a.LinuxProfile.Validate(); e != nil { - return e + if a.LinuxProfile != nil { + if e := a.LinuxProfile.Validate(); e != nil { + return e + } } + if e := validateVNET(a); e != nil { return e } From bee38ce7bded6d3ae4e8f0e36cd47bcb41f53e32 Mon Sep 17 00:00:00 2001 From: Qingqing Zheng Date: Fri, 6 Apr 2018 16:13:53 -0700 Subject: [PATCH 2/8] add a test to check linuxprofile --- .../agentPoolOnly/v20180331/agents.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 pkg/acsengine/testdata/agentPoolOnly/v20180331/agents.json diff --git a/pkg/acsengine/testdata/agentPoolOnly/v20180331/agents.json b/pkg/acsengine/testdata/agentPoolOnly/v20180331/agents.json new file mode 100644 index 0000000000..29a34b81b4 --- /dev/null +++ b/pkg/acsengine/testdata/agentPoolOnly/v20180331/agents.json @@ -0,0 +1,19 @@ +{ + "apiVersion": "2018-03-31", + "properties": { + "dnsPrefix": "agents006", + "fqdn": "agents006.azmk8s.io", + "kubernetesVersion": "1.8.7", + "agentPoolProfiles": [ + { + "name": "agentpool1", + "count": 1, + "vmSize": "Standard_D2_v2" + } + ], + "servicePrincipalProfile": { + "clientID": "ServicePrincipalClientID", + "secret": "myServicePrincipalClientSecret" + } + } +} \ No newline at end of file From cde023d642689e326661c6dd9777b58cedb0f006 Mon Sep 17 00:00:00 2001 From: Qingqing Zheng Date: Fri, 6 Apr 2018 16:18:12 -0700 Subject: [PATCH 3/8] add newline to json --- pkg/acsengine/testdata/agentPoolOnly/v20180331/agents.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/acsengine/testdata/agentPoolOnly/v20180331/agents.json b/pkg/acsengine/testdata/agentPoolOnly/v20180331/agents.json index 29a34b81b4..bb4edfb639 100644 --- a/pkg/acsengine/testdata/agentPoolOnly/v20180331/agents.json +++ b/pkg/acsengine/testdata/agentPoolOnly/v20180331/agents.json @@ -16,4 +16,4 @@ "secret": "myServicePrincipalClientSecret" } } -} \ No newline at end of file +} From b7e1eee744fdb4b87fa6b369d1fa26572cc9a0ab Mon Sep 17 00:00:00 2001 From: Qingqing Zheng Date: Mon, 9 Apr 2018 11:41:10 -0700 Subject: [PATCH 4/8] assign empty when nil linuxprofile --- pkg/api/convertertoagentpoolonlyapi.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/api/convertertoagentpoolonlyapi.go b/pkg/api/convertertoagentpoolonlyapi.go index ff0bd60670..e845f934aa 100644 --- a/pkg/api/convertertoagentpoolonlyapi.go +++ b/pkg/api/convertertoagentpoolonlyapi.go @@ -316,6 +316,8 @@ func convertV20180331AgentPoolOnlyProperties(obj *v20180331.Properties) *Propert } if obj.LinuxProfile != nil { properties.LinuxProfile = convertV20180331AgentPoolOnlyLinuxProfile(obj.LinuxProfile) + } else { + properties.LinuxProfile = &LinuxProfile{} } if obj.WindowsProfile != nil { properties.WindowsProfile = convertV20180331AgentPoolOnlyWindowsProfile(obj.WindowsProfile) From 40fb4c286d521781b59931ccea6e07b6b8c1109f Mon Sep 17 00:00:00 2001 From: Qingqing Zheng Date: Mon, 9 Apr 2018 13:34:28 -0700 Subject: [PATCH 5/8] assign ssh before convert --- cmd/deploy.go | 12 +++-- pkg/api/apiloader.go | 72 ++++++++++++++++++++------ pkg/api/convertertoagentpoolonlyapi.go | 1 + 3 files changed, 64 insertions(+), 21 deletions(-) diff --git a/cmd/deploy.go b/cmd/deploy.go index db24a7a6f0..5778d6576c 100644 --- a/cmd/deploy.go +++ b/cmd/deploy.go @@ -147,9 +147,11 @@ func (dc *deployCmd) validate(cmd *cobra.Command, args []string) error { func autofillApimodel(dc *deployCmd) { var err error - if dc.containerService.Properties.LinuxProfile.AdminUsername == "" { - log.Warnf("apimodel: no linuxProfile.adminUsername was specified. Will use 'azureuser'.") - dc.containerService.Properties.LinuxProfile.AdminUsername = "azureuser" + if dc.containerService.Properties.LinuxProfile != nil { + if dc.containerService.Properties.LinuxProfile.AdminUsername == "" { + log.Warnf("apimodel: no linuxProfile.adminUsername was specified. Will use 'azureuser'.") + dc.containerService.Properties.LinuxProfile.AdminUsername = "azureuser" + } } if dc.dnsPrefix != "" && dc.containerService.Properties.MasterProfile.DNSPrefix != "" { @@ -181,9 +183,9 @@ func autofillApimodel(dc *deployCmd) { } } - if dc.containerService.Properties.LinuxProfile.SSH.PublicKeys == nil || + if dc.containerService.Properties.LinuxProfile != nil && (dc.containerService.Properties.LinuxProfile.SSH.PublicKeys == nil || len(dc.containerService.Properties.LinuxProfile.SSH.PublicKeys) == 0 || - dc.containerService.Properties.LinuxProfile.SSH.PublicKeys[0].KeyData == "" { + dc.containerService.Properties.LinuxProfile.SSH.PublicKeys[0].KeyData == "") { creator := &acsengine.SSHCreator{ Translator: &i18n.Translator{ Locale: dc.locale, diff --git a/pkg/api/apiloader.go b/pkg/api/apiloader.go index f381b0c9ae..23229f5b78 100644 --- a/pkg/api/apiloader.go +++ b/pkg/api/apiloader.go @@ -1,7 +1,10 @@ package api import ( + "crypto/rand" + "crypto/rsa" "encoding/json" + "io" "io/ioutil" "reflect" @@ -17,6 +20,7 @@ import ( "github.com/Azure/acs-engine/pkg/helpers" "github.com/Azure/acs-engine/pkg/i18n" log "github.com/sirupsen/logrus" + "golang.org/x/crypto/ssh" ) // Apiloader represents the object that loads api model @@ -45,7 +49,7 @@ func (a *Apiloader) DeserializeContainerService(contents []byte, validate, isUpd if service == nil || err != nil { if isAgentPoolOnlyClusterJSON(contents) { log.Info("No masterProfile: interpreting API model as agent pool only") - service, err := a.LoadContainerServiceForAgentPoolOnlyCluster(contents, version, validate, isUpdate, "") + service, _, err := a.LoadContainerServiceForAgentPoolOnlyCluster(contents, version, validate, isUpdate, "") if service == nil || err != nil { log.Infof("Error returned by LoadContainerServiceForAgentPoolOnlyCluster: %+v", err) } @@ -185,59 +189,72 @@ func (a *Apiloader) LoadContainerService( } // LoadContainerServiceForAgentPoolOnlyCluster loads an ACS Cluster API Model, validates it, and returns the unversioned representation -func (a *Apiloader) LoadContainerServiceForAgentPoolOnlyCluster(contents []byte, version string, validate, isUpdate bool, defaultKubernetesVersion string) (*ContainerService, error) { +func (a *Apiloader) LoadContainerServiceForAgentPoolOnlyCluster(contents []byte, version string, validate, isUpdate bool, defaultKubernetesVersion string) (*ContainerService, bool, error) { + IsSSHAutoGenerated := false switch version { case v20170831.APIVersion: managedCluster := &v20170831.ManagedCluster{} if e := json.Unmarshal(contents, &managedCluster); e != nil { - return nil, e + return nil, IsSSHAutoGenerated, e } // verify orchestrator version if len(managedCluster.Properties.KubernetesVersion) > 0 && !common.AllKubernetesSupportedVersions[managedCluster.Properties.KubernetesVersion] { - return nil, a.Translator.Errorf("The selected orchestrator version '%s' is not supported", managedCluster.Properties.KubernetesVersion) + return nil, IsSSHAutoGenerated, a.Translator.Errorf("The selected orchestrator version '%s' is not supported", managedCluster.Properties.KubernetesVersion) } // use defaultKubernetesVersion arg if no version was supplied in the request contents if managedCluster.Properties.KubernetesVersion == "" && defaultKubernetesVersion != "" { if !common.AllKubernetesSupportedVersions[defaultKubernetesVersion] { - return nil, a.Translator.Errorf("The selected orchestrator version '%s' is not supported", defaultKubernetesVersion) + return nil, IsSSHAutoGenerated, a.Translator.Errorf("The selected orchestrator version '%s' is not supported", defaultKubernetesVersion) } managedCluster.Properties.KubernetesVersion = defaultKubernetesVersion } if e := managedCluster.Properties.Validate(); validate && e != nil { - return nil, e + return nil, IsSSHAutoGenerated, e } - return ConvertV20170831AgentPoolOnly(managedCluster), nil + return ConvertV20170831AgentPoolOnly(managedCluster), false, nil case v20180331.APIVersion: managedCluster := &v20180331.ManagedCluster{} if e := json.Unmarshal(contents, &managedCluster); e != nil { - return nil, e + return nil, IsSSHAutoGenerated, e } // verify orchestrator version if len(managedCluster.Properties.KubernetesVersion) > 0 && !common.AllKubernetesSupportedVersions[managedCluster.Properties.KubernetesVersion] { - return nil, a.Translator.Errorf("The selected orchestrator version '%s' is not supported", managedCluster.Properties.KubernetesVersion) + return nil, IsSSHAutoGenerated, a.Translator.Errorf("The selected orchestrator version '%s' is not supported", managedCluster.Properties.KubernetesVersion) } // use defaultKubernetesVersion arg if no version was supplied in the request contents if managedCluster.Properties.KubernetesVersion == "" && defaultKubernetesVersion != "" { if !common.AllKubernetesSupportedVersions[defaultKubernetesVersion] { - return nil, a.Translator.Errorf("The selected orchestrator version '%s' is not supported", defaultKubernetesVersion) + return nil, IsSSHAutoGenerated, a.Translator.Errorf("The selected orchestrator version '%s' is not supported", defaultKubernetesVersion) } managedCluster.Properties.KubernetesVersion = defaultKubernetesVersion } if e := managedCluster.Properties.Validate(); validate && e != nil { - return nil, e + return nil, IsSSHAutoGenerated, e } - return ConvertV20180331AgentPoolOnly(managedCluster), nil + + if managedCluster.Properties.LinuxProfile == nil { + linuxProfile := &v20180331.LinuxProfile{} + linuxProfile.AdminUsername = "azureuser" + publicKey, err := a.createSSH(rand.Reader) + if err != nil { + return nil, IsSSHAutoGenerated, err + } + linuxProfile.SSH.PublicKeys = []v20180331.PublicKey{{KeyData: publicKey}} + managedCluster.Properties.LinuxProfile = linuxProfile + IsSSHAutoGenerated = true + } + return ConvertV20180331AgentPoolOnly(managedCluster), IsSSHAutoGenerated, nil case apvlabs.APIVersion: managedCluster := &apvlabs.ManagedCluster{} if e := json.Unmarshal(contents, &managedCluster); e != nil { - return nil, e + return nil, IsSSHAutoGenerated, e } if e := managedCluster.Properties.Validate(); validate && e != nil { - return nil, e + return nil, IsSSHAutoGenerated, e } - return ConvertVLabsAgentPoolOnly(managedCluster), nil + return ConvertVLabsAgentPoolOnly(managedCluster), IsSSHAutoGenerated, nil default: - return nil, a.Translator.Errorf("unrecognized APIVersion in LoadContainerServiceForAgentPoolOnlyCluster '%s'", version) + return nil, IsSSHAutoGenerated, a.Translator.Errorf("unrecognized APIVersion in LoadContainerServiceForAgentPoolOnlyCluster '%s'", version) } } @@ -364,3 +381,26 @@ func setContainerServiceDefaultsv20170131(c *v20170131.ContainerService) { } } } + +const ( + // SSHKeySize is the size (in bytes) of SSH key to create + SSHKeySize = 4096 +) + +func (a *Apiloader) createSSH(rg io.Reader) (publicKeyString string, err error) { + log.Debugf("ssh: generating %dbit rsa key", SSHKeySize) + privateKey, err := rsa.GenerateKey(rg, SSHKeySize) + if err != nil { + return "", a.Translator.Errorf("failed to generate private key for ssh: %q", err) + } + + publicKey := privateKey.PublicKey + sshPublicKey, err := ssh.NewPublicKey(&publicKey) + if err != nil { + return "", a.Translator.Errorf("failed to create openssh public key string: %q", err) + } + authorizedKeyBytes := ssh.MarshalAuthorizedKey(sshPublicKey) + authorizedKey := string(authorizedKeyBytes) + + return authorizedKey, nil +} diff --git a/pkg/api/convertertoagentpoolonlyapi.go b/pkg/api/convertertoagentpoolonlyapi.go index e845f934aa..02a9e77c6a 100644 --- a/pkg/api/convertertoagentpoolonlyapi.go +++ b/pkg/api/convertertoagentpoolonlyapi.go @@ -319,6 +319,7 @@ func convertV20180331AgentPoolOnlyProperties(obj *v20180331.Properties) *Propert } else { properties.LinuxProfile = &LinuxProfile{} } + if obj.WindowsProfile != nil { properties.WindowsProfile = convertV20180331AgentPoolOnlyWindowsProfile(obj.WindowsProfile) } From ca3d4b7ce1ba41619d5b4120c4d14c4a647d5b9a Mon Sep 17 00:00:00 2001 From: Qingqing Zheng Date: Mon, 9 Apr 2018 14:44:49 -0700 Subject: [PATCH 6/8] remove the empty assignment --- pkg/api/convertertoagentpoolonlyapi.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkg/api/convertertoagentpoolonlyapi.go b/pkg/api/convertertoagentpoolonlyapi.go index 02a9e77c6a..65935f1b74 100644 --- a/pkg/api/convertertoagentpoolonlyapi.go +++ b/pkg/api/convertertoagentpoolonlyapi.go @@ -316,8 +316,6 @@ func convertV20180331AgentPoolOnlyProperties(obj *v20180331.Properties) *Propert } if obj.LinuxProfile != nil { properties.LinuxProfile = convertV20180331AgentPoolOnlyLinuxProfile(obj.LinuxProfile) - } else { - properties.LinuxProfile = &LinuxProfile{} } if obj.WindowsProfile != nil { From 09502b4cb51d83b44b22b6f89deb6a53d6c28bc3 Mon Sep 17 00:00:00 2001 From: Qingqing Zheng Date: Mon, 9 Apr 2018 17:42:23 -0700 Subject: [PATCH 7/8] resorve dup code --- cmd/deploy.go | 8 +++----- pkg/acsengine/ssh.go | 41 ++++++--------------------------------- pkg/acsengine/ssh_test.go | 10 +++++++--- pkg/api/apiloader.go | 28 +------------------------- pkg/helpers/helpers.go | 28 ++++++++++++++++++++++++++ 5 files changed, 45 insertions(+), 70 deletions(-) diff --git a/cmd/deploy.go b/cmd/deploy.go index 5778d6576c..1ff4b0bc7a 100644 --- a/cmd/deploy.go +++ b/cmd/deploy.go @@ -186,12 +186,10 @@ func autofillApimodel(dc *deployCmd) { if dc.containerService.Properties.LinuxProfile != nil && (dc.containerService.Properties.LinuxProfile.SSH.PublicKeys == nil || len(dc.containerService.Properties.LinuxProfile.SSH.PublicKeys) == 0 || dc.containerService.Properties.LinuxProfile.SSH.PublicKeys[0].KeyData == "") { - creator := &acsengine.SSHCreator{ - Translator: &i18n.Translator{ - Locale: dc.locale, - }, + translator := &i18n.Translator{ + Locale: dc.locale, } - _, publicKey, err := creator.CreateSaveSSH(dc.containerService.Properties.LinuxProfile.AdminUsername, dc.outputDirectory) + _, publicKey, err := acsengine.CreateSaveSSH(dc.containerService.Properties.LinuxProfile.AdminUsername, dc.outputDirectory, translator) if err != nil { log.Fatal("Failed to generate SSH Key") } diff --git a/pkg/acsengine/ssh.go b/pkg/acsengine/ssh.go index 2a955311d9..6743a4112a 100644 --- a/pkg/acsengine/ssh.go +++ b/pkg/acsengine/ssh.go @@ -4,26 +4,16 @@ import ( "crypto/rand" "crypto/rsa" "fmt" - "io" - "github.com/Azure/acs-engine/pkg/i18n" - log "github.com/sirupsen/logrus" - "golang.org/x/crypto/ssh" -) - -// SSHCreator represents the object that creates SSH key pair -type SSHCreator struct { - Translator *i18n.Translator -} + "github.com/Azure/acs-engine/pkg/helpers" -const ( - // SSHKeySize is the size (in bytes) of SSH key to create - SSHKeySize = 4096 + "github.com/Azure/acs-engine/pkg/i18n" ) // CreateSaveSSH generates and stashes an SSH key pair. -func (s *SSHCreator) CreateSaveSSH(username, outputDirectory string) (privateKey *rsa.PrivateKey, publicKeyString string, err error) { - privateKey, publicKeyString, err = s.CreateSSH(rand.Reader) +func CreateSaveSSH(username, outputDirectory string, s *i18n.Translator) (privateKey *rsa.PrivateKey, publicKeyString string, err error) { + + privateKey, publicKeyString, err = helpers.CreateSSH(rand.Reader, s) if err != nil { return nil, "", err } @@ -31,7 +21,7 @@ func (s *SSHCreator) CreateSaveSSH(username, outputDirectory string) (privateKey privateKeyPem := privateKeyToPem(privateKey) f := &FileSaver{ - Translator: s.Translator, + Translator: s, } err = f.SaveFile(outputDirectory, fmt.Sprintf("%s_rsa", username), privateKeyPem) @@ -41,22 +31,3 @@ func (s *SSHCreator) CreateSaveSSH(username, outputDirectory string) (privateKey return privateKey, publicKeyString, nil } - -// CreateSSH creates an SSH key pair. -func (s *SSHCreator) CreateSSH(rg io.Reader) (privateKey *rsa.PrivateKey, publicKeyString string, err error) { - log.Debugf("ssh: generating %dbit rsa key", SSHKeySize) - privateKey, err = rsa.GenerateKey(rg, SSHKeySize) - if err != nil { - return nil, "", s.Translator.Errorf("failed to generate private key for ssh: %q", err) - } - - publicKey := privateKey.PublicKey - sshPublicKey, err := ssh.NewPublicKey(&publicKey) - if err != nil { - return nil, "", s.Translator.Errorf("failed to create openssh public key string: %q", err) - } - authorizedKeyBytes := ssh.MarshalAuthorizedKey(sshPublicKey) - authorizedKey := string(authorizedKeyBytes) - - return privateKey, authorizedKey, nil -} diff --git a/pkg/acsengine/ssh_test.go b/pkg/acsengine/ssh_test.go index 4c6a1c740a..fe4f82f96a 100644 --- a/pkg/acsengine/ssh_test.go +++ b/pkg/acsengine/ssh_test.go @@ -3,6 +3,10 @@ package acsengine import ( "math/rand" "testing" + + "github.com/Azure/acs-engine/pkg/helpers" + + "github.com/Azure/acs-engine/pkg/i18n" ) func TestCreateSSH(t *testing.T) { @@ -63,11 +67,11 @@ EPDesL0rH+3s1CKpgkhYdbJ675GFoGoq+X21QaqsdvoXmmuJF9qq9Tq+JaWloUNq -----END RSA PRIVATE KEY----- ` - creator := &SSHCreator{ - Translator: nil, + translator := &i18n.Translator{ + Locale: nil, } - privateKey, publicKey, err := creator.CreateSSH(rg) + privateKey, publicKey, err := helpers.CreateSSH(rg, translator) if err != nil { t.Fatalf("failed to generate SSH: %s", err) } diff --git a/pkg/api/apiloader.go b/pkg/api/apiloader.go index 23229f5b78..02bade36e1 100644 --- a/pkg/api/apiloader.go +++ b/pkg/api/apiloader.go @@ -2,9 +2,7 @@ package api import ( "crypto/rand" - "crypto/rsa" "encoding/json" - "io" "io/ioutil" "reflect" @@ -20,7 +18,6 @@ import ( "github.com/Azure/acs-engine/pkg/helpers" "github.com/Azure/acs-engine/pkg/i18n" log "github.com/sirupsen/logrus" - "golang.org/x/crypto/ssh" ) // Apiloader represents the object that loads api model @@ -235,7 +232,7 @@ func (a *Apiloader) LoadContainerServiceForAgentPoolOnlyCluster(contents []byte, if managedCluster.Properties.LinuxProfile == nil { linuxProfile := &v20180331.LinuxProfile{} linuxProfile.AdminUsername = "azureuser" - publicKey, err := a.createSSH(rand.Reader) + _, publicKey, err := helpers.CreateSSH(rand.Reader, a.Translator) if err != nil { return nil, IsSSHAutoGenerated, err } @@ -381,26 +378,3 @@ func setContainerServiceDefaultsv20170131(c *v20170131.ContainerService) { } } } - -const ( - // SSHKeySize is the size (in bytes) of SSH key to create - SSHKeySize = 4096 -) - -func (a *Apiloader) createSSH(rg io.Reader) (publicKeyString string, err error) { - log.Debugf("ssh: generating %dbit rsa key", SSHKeySize) - privateKey, err := rsa.GenerateKey(rg, SSHKeySize) - if err != nil { - return "", a.Translator.Errorf("failed to generate private key for ssh: %q", err) - } - - publicKey := privateKey.PublicKey - sshPublicKey, err := ssh.NewPublicKey(&publicKey) - if err != nil { - return "", a.Translator.Errorf("failed to create openssh public key string: %q", err) - } - authorizedKeyBytes := ssh.MarshalAuthorizedKey(sshPublicKey) - authorizedKey := string(authorizedKeyBytes) - - return authorizedKey, nil -} diff --git a/pkg/helpers/helpers.go b/pkg/helpers/helpers.go index 9affc4fac2..2cade4d925 100644 --- a/pkg/helpers/helpers.go +++ b/pkg/helpers/helpers.go @@ -3,7 +3,17 @@ package helpers import ( // "fmt" "bytes" + "crypto/rsa" "encoding/json" + "io" + + "github.com/Azure/acs-engine/pkg/i18n" + "golang.org/x/crypto/ssh" +) + +const ( + // SSHKeySize is the size (in bytes) of SSH key to create + SSHKeySize = 4096 ) // JSONMarshalIndent marshals formatted JSON w/ optional SetEscapeHTML @@ -46,3 +56,21 @@ func PointerToBool(b bool) *bool { p := b return &p } + +// CreateSSH creates an SSH key pair. +func CreateSSH(rg io.Reader, s *i18n.Translator) (privateKey *rsa.PrivateKey, publicKeyString string, err error) { + privateKey, err = rsa.GenerateKey(rg, SSHKeySize) + if err != nil { + return nil, "", s.Errorf("failed to generate private key for ssh: %q", err) + } + + publicKey := privateKey.PublicKey + sshPublicKey, err := ssh.NewPublicKey(&publicKey) + if err != nil { + return nil, "", s.Errorf("failed to create openssh public key string: %q", err) + } + authorizedKeyBytes := ssh.MarshalAuthorizedKey(sshPublicKey) + authorizedKey := string(authorizedKeyBytes) + + return privateKey, authorizedKey, nil +} From 1e48478b1184bf82d9ff3930aa13c13ff108161e Mon Sep 17 00:00:00 2001 From: Qingqing Zheng Date: Mon, 9 Apr 2018 17:50:27 -0700 Subject: [PATCH 8/8] trigger test --- pkg/acsengine/ssh.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/acsengine/ssh.go b/pkg/acsengine/ssh.go index 6743a4112a..bcee867057 100644 --- a/pkg/acsengine/ssh.go +++ b/pkg/acsengine/ssh.go @@ -6,7 +6,6 @@ import ( "fmt" "github.com/Azure/acs-engine/pkg/helpers" - "github.com/Azure/acs-engine/pkg/i18n" )