Skip to content

Commit 1fc8ddc

Browse files
committed
stembuild: install microsoft OpenSSH
This commit adds the execution of `Add-WindowsCapability` via the `govc guest.run` command because `Add-WindowsCapability` is not viable over WinRM.
1 parent 713e079 commit 1fc8ddc

File tree

5 files changed

+243
-5
lines changed

5 files changed

+243
-5
lines changed

stembuild/construct/constructfakes/fake_iaas_client.go

Lines changed: 83 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

stembuild/construct/vmconstruct.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ func NewVMConstruct(
7171
scriptExecutor ScriptExecutorI,
7272
setupFlags []string,
7373
) *VMConstruct {
74-
7574
return &VMConstruct{
7675
ctx: ctx,
7776
remoteManager: remoteManager,
@@ -114,6 +113,7 @@ type GuestManager interface {
114113
type IaasClient interface {
115114
UploadArtifact(vmInventoryPath, artifact, destination, username, password string) error
116115
MakeDirectory(vmInventoryPath, path, username, password string) error
116+
Run(vmInventoryPath, username, password string, commandArgs []string) error
117117
Start(vmInventoryPath, username, password, command string, args ...string) (string, error)
118118
WaitForExit(vmInventoryPath, username, password, pid string) (int, error)
119119
IsPoweredOff(vmInventoryPath string) (bool, error)
@@ -143,6 +143,13 @@ func (c *VMConstruct) PrepareVM() error {
143143
}
144144
c.messenger.PrintOut("\nAll files have been uploaded.\n")
145145

146+
c.messenger.PrintOut("\nInstalling OpenSSH on target VM...")
147+
err = c.installOpenSSH()
148+
if err != nil {
149+
return err
150+
}
151+
c.messenger.PrintOut("OpenSSH install succeeded.\n")
152+
146153
c.messenger.PrintOut("\nAttempting to enable WinRM on the guest vm...")
147154
err = c.winRMEnabler.Enable()
148155
if err != nil {
@@ -270,6 +277,12 @@ func (c *VMConstruct) isPoweredOff(duration time.Duration) error {
270277
return err
271278
}
272279

280+
func (c *VMConstruct) installOpenSSH() error {
281+
const installOpenSSHCommand = `"Add-WindowsCapability -Online -Name (Get-WindowsCapability -Online -Name OpenSSH.Server* | ForEach-Object Name)"`
282+
283+
return c.Client.Run(c.vmInventoryPath, c.vmUsername, c.vmPassword, []string{powershellExePath, installOpenSSHCommand})
284+
}
285+
273286
func EncodePowershellCommand(command []byte) string {
274287
runeCommand := []rune(string(command))
275288
utf16Command := utf16.Encode(runeCommand)

stembuild/construct/vmconstruct_test.go

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func (p *nonWaitingPoller) Poll(_ time.Duration, loopFunc func() (bool, error))
3232
return nil
3333
}
3434

35-
var _ = Describe("construct_helpers", func() {
35+
var _ = Describe("VMConstruct", func() {
3636
var (
3737
outBuf *Buffer
3838
errBuf *Buffer
@@ -125,7 +125,7 @@ var _ = Describe("construct_helpers", func() {
125125
Expect(vmConstruct.PrepareVM()).NotTo(Succeed())
126126

127127
Expect(fakeVcenterClient.MakeDirectoryCallCount()).To(Equal(1))
128-
Expect(fakeWinRMEnabler.EnableCallCount()).To(Equal(0))
128+
Expect(fakeVcenterClient.RunCallCount()).To(Equal(0))
129129
})
130130

131131
It("it logs the attempt", func() {
@@ -141,7 +141,7 @@ var _ = Describe("construct_helpers", func() {
141141
Expect(vmConstruct.PrepareVM()).To(Succeed())
142142

143143
Expect(fakeVcenterClient.MakeDirectoryCallCount()).To(Equal(1))
144-
Expect(fakeWinRMEnabler.EnableCallCount()).To(Equal(1))
144+
Expect(fakeVcenterClient.RunCallCount()).To(Equal(1))
145145
})
146146

147147
It("it logs success", func() {
@@ -244,6 +244,7 @@ var _ = Describe("construct_helpers", func() {
244244

245245
Expect(fakeVcenterClient.MakeDirectoryCallCount()).To(Equal(1))
246246
Expect(fakeVcenterClient.UploadArtifactCallCount()).To(Equal(2))
247+
Expect(fakeVcenterClient.RunCallCount()).To(Equal(0))
247248
})
248249

249250
It("it logs the attempt", func() {
@@ -261,7 +262,7 @@ var _ = Describe("construct_helpers", func() {
261262
Expect(fakeVcenterClient.MakeDirectoryCallCount()).To(Equal(1))
262263
Expect(fakeVcenterClient.UploadArtifactCallCount()).To(Equal(2))
263264
Expect(fakeWinRMEnabler.EnableCallCount()).To(Equal(1))
264-
Expect(fakeVMConnectionValidator.ValidateCallCount()).To(Equal(1))
265+
Expect(fakeVcenterClient.RunCallCount()).To(Equal(1))
265266
})
266267

267268
It("it logs success", func() {
@@ -272,6 +273,71 @@ var _ = Describe("construct_helpers", func() {
272273
})
273274
})
274275

276+
Describe("it installs Microsoft's OpenSSH", func() {
277+
Context("when it fails", func() {
278+
var installOpenSshErr error
279+
BeforeEach(func() {
280+
installOpenSshErr = errors.New("fake-install-open-ssh-error")
281+
fakeVcenterClient.RunReturns(installOpenSshErr)
282+
})
283+
284+
It("returns the error", func() {
285+
err := vmConstruct.PrepareVM()
286+
Expect(err).To(Equal(installOpenSshErr))
287+
})
288+
289+
It("does not execute the next step", func() {
290+
Expect(vmConstruct.PrepareVM()).NotTo(Succeed())
291+
292+
Expect(fakeVcenterClient.MakeDirectoryCallCount()).To(Equal(1))
293+
Expect(fakeVcenterClient.UploadArtifactCallCount()).To(Equal(2))
294+
Expect(fakeVcenterClient.RunCallCount()).To(Equal(1))
295+
Expect(fakeWinRMEnabler.EnableCallCount()).To(Equal(0))
296+
})
297+
298+
It("it logs the attempt", func() {
299+
Expect(vmConstruct.PrepareVM()).NotTo(Succeed())
300+
301+
Eventually(outBuf).Should(Say("\nInstalling OpenSSH on target VM..."))
302+
Eventually(outBuf).ShouldNot(Say("\nInstalling OpenSSH on target VM...OpenSSH install succeeded.\n"))
303+
})
304+
})
305+
306+
Context("when it succeeds", func() {
307+
It("executes the next step", func() {
308+
Expect(vmConstruct.PrepareVM()).To(Succeed())
309+
310+
Expect(fakeVcenterClient.MakeDirectoryCallCount()).To(Equal(1))
311+
Expect(fakeVcenterClient.UploadArtifactCallCount()).To(Equal(2))
312+
Expect(fakeVcenterClient.RunCallCount()).To(Equal(1))
313+
Expect(fakeWinRMEnabler.EnableCallCount()).To(Equal(1))
314+
})
315+
316+
It("invokes VCenterClient.Run() as expected", func() {
317+
Expect(vmConstruct.PrepareVM()).To(Succeed())
318+
319+
expectedCommandArgs := []string{
320+
`C:\Windows\System32\WindowsPowerShell\V1.0\powershell.exe`,
321+
`"Add-WindowsCapability -Online -Name (Get-WindowsCapability -Online -Name OpenSSH.Server* | ForEach-Object Name)"`,
322+
}
323+
324+
actualVmInventoryPath, actualVmUsername, actualVmPassword, actualCommandArgs :=
325+
fakeVcenterClient.RunArgsForCall(0)
326+
327+
Expect(actualVmInventoryPath).To(Equal(vmInventoryPath))
328+
Expect(actualVmUsername).To(Equal(vmUsername))
329+
Expect(actualVmPassword).To(Equal(vmPassword))
330+
Expect(actualCommandArgs).To(Equal(expectedCommandArgs))
331+
})
332+
333+
It("it logs success", func() {
334+
Expect(vmConstruct.PrepareVM()).To(Succeed())
335+
336+
Eventually(outBuf).Should(Say("\nInstalling OpenSSH on target VM...OpenSSH install succeeded.\n"))
337+
})
338+
})
339+
})
340+
275341
Describe("enables WinRM", func() {
276342
Context("when it fails", func() {
277343
var enableErr error
@@ -332,6 +398,7 @@ var _ = Describe("construct_helpers", func() {
332398

333399
Expect(fakeVcenterClient.MakeDirectoryCallCount()).To(Equal(1))
334400
Expect(fakeVcenterClient.UploadArtifactCallCount()).To(Equal(2))
401+
Expect(fakeVcenterClient.RunCallCount()).To(Equal(1))
335402
Expect(fakeWinRMEnabler.EnableCallCount()).To(Equal(1))
336403
Expect(fakeVMConnectionValidator.ValidateCallCount()).To(Equal(1))
337404
Expect(fakeRemoteManager.ExtractArchiveCallCount()).To(Equal(0))
@@ -351,6 +418,7 @@ var _ = Describe("construct_helpers", func() {
351418

352419
Expect(fakeVcenterClient.MakeDirectoryCallCount()).To(Equal(1))
353420
Expect(fakeVcenterClient.UploadArtifactCallCount()).To(Equal(2))
421+
Expect(fakeVcenterClient.RunCallCount()).To(Equal(1))
354422
Expect(fakeWinRMEnabler.EnableCallCount()).To(Equal(1))
355423
Expect(fakeVMConnectionValidator.ValidateCallCount()).To(Equal(1))
356424
Expect(fakeRemoteManager.ExtractArchiveCallCount()).To(Equal(1))
@@ -382,6 +450,7 @@ var _ = Describe("construct_helpers", func() {
382450

383451
Expect(fakeVcenterClient.MakeDirectoryCallCount()).To(Equal(1))
384452
Expect(fakeVcenterClient.UploadArtifactCallCount()).To(Equal(2))
453+
Expect(fakeVcenterClient.RunCallCount()).To(Equal(1))
385454
Expect(fakeWinRMEnabler.EnableCallCount()).To(Equal(1))
386455
Expect(fakeVMConnectionValidator.ValidateCallCount()).To(Equal(1))
387456
Expect(fakeRemoteManager.ExtractArchiveCallCount()).To(Equal(1))
@@ -402,6 +471,7 @@ var _ = Describe("construct_helpers", func() {
402471

403472
Expect(fakeVcenterClient.MakeDirectoryCallCount()).To(Equal(1))
404473
Expect(fakeVcenterClient.UploadArtifactCallCount()).To(Equal(2))
474+
Expect(fakeVcenterClient.RunCallCount()).To(Equal(1))
405475
Expect(fakeWinRMEnabler.EnableCallCount()).To(Equal(1))
406476
Expect(fakeVMConnectionValidator.ValidateCallCount()).To(Equal(1))
407477
Expect(fakeRemoteManager.ExtractArchiveCallCount()).To(Equal(1))
@@ -450,6 +520,7 @@ var _ = Describe("construct_helpers", func() {
450520

451521
Expect(fakeVcenterClient.MakeDirectoryCallCount()).To(Equal(1))
452522
Expect(fakeVcenterClient.UploadArtifactCallCount()).To(Equal(2))
523+
Expect(fakeVcenterClient.RunCallCount()).To(Equal(1))
453524
Expect(fakeWinRMEnabler.EnableCallCount()).To(Equal(1))
454525
Expect(fakeVMConnectionValidator.ValidateCallCount()).To(Equal(1))
455526
Expect(fakeRemoteManager.ExtractArchiveCallCount()).To(Equal(1))
@@ -471,6 +542,7 @@ var _ = Describe("construct_helpers", func() {
471542

472543
Expect(fakeVcenterClient.MakeDirectoryCallCount()).To(Equal(1))
473544
Expect(fakeVcenterClient.UploadArtifactCallCount()).To(Equal(2))
545+
Expect(fakeVcenterClient.RunCallCount()).To(Equal(1))
474546
Expect(fakeWinRMEnabler.EnableCallCount()).To(Equal(1))
475547
Expect(fakeVMConnectionValidator.ValidateCallCount()).To(Equal(1))
476548
Expect(fakeRemoteManager.ExtractArchiveCallCount()).To(Equal(1))
@@ -515,6 +587,7 @@ var _ = Describe("construct_helpers", func() {
515587

516588
Expect(fakeVcenterClient.MakeDirectoryCallCount()).To(Equal(1))
517589
Expect(fakeVcenterClient.UploadArtifactCallCount()).To(Equal(2))
590+
Expect(fakeVcenterClient.RunCallCount()).To(Equal(1))
518591
Expect(fakeWinRMEnabler.EnableCallCount()).To(Equal(1))
519592
Expect(fakeVMConnectionValidator.ValidateCallCount()).To(Equal(1))
520593
Expect(fakeRemoteManager.ExtractArchiveCallCount()).To(Equal(1))
@@ -537,6 +610,7 @@ var _ = Describe("construct_helpers", func() {
537610

538611
Expect(fakeVcenterClient.MakeDirectoryCallCount()).To(Equal(1))
539612
Expect(fakeVcenterClient.UploadArtifactCallCount()).To(Equal(2))
613+
Expect(fakeVcenterClient.RunCallCount()).To(Equal(1))
540614
Expect(fakeWinRMEnabler.EnableCallCount()).To(Equal(1))
541615
Expect(fakeVMConnectionValidator.ValidateCallCount()).To(Equal(1))
542616
Expect(fakeRemoteManager.ExtractArchiveCallCount()).To(Equal(1))
@@ -571,6 +645,7 @@ var _ = Describe("construct_helpers", func() {
571645

572646
Expect(fakeVcenterClient.MakeDirectoryCallCount()).To(Equal(1))
573647
Expect(fakeVcenterClient.UploadArtifactCallCount()).To(Equal(2))
648+
Expect(fakeVcenterClient.RunCallCount()).To(Equal(1))
574649
Expect(fakeWinRMEnabler.EnableCallCount()).To(Equal(1))
575650
Expect(fakeVMConnectionValidator.ValidateCallCount()).To(Equal(1))
576651
Expect(fakeRemoteManager.ExtractArchiveCallCount()).To(Equal(1))
@@ -594,6 +669,7 @@ var _ = Describe("construct_helpers", func() {
594669

595670
Expect(fakeVcenterClient.MakeDirectoryCallCount()).To(Equal(1))
596671
Expect(fakeVcenterClient.UploadArtifactCallCount()).To(Equal(2))
672+
Expect(fakeVcenterClient.RunCallCount()).To(Equal(1))
597673
Expect(fakeWinRMEnabler.EnableCallCount()).To(Equal(1))
598674
Expect(fakeVMConnectionValidator.ValidateCallCount()).To(Equal(1))
599675
Expect(fakeRemoteManager.ExtractArchiveCallCount()).To(Equal(1))
@@ -634,6 +710,7 @@ var _ = Describe("construct_helpers", func() {
634710

635711
Expect(fakeVcenterClient.MakeDirectoryCallCount()).To(Equal(1))
636712
Expect(fakeVcenterClient.UploadArtifactCallCount()).To(Equal(2))
713+
Expect(fakeVcenterClient.RunCallCount()).To(Equal(1))
637714
Expect(fakeWinRMEnabler.EnableCallCount()).To(Equal(1))
638715
Expect(fakeVMConnectionValidator.ValidateCallCount()).To(Equal(1))
639716
Expect(fakeRemoteManager.ExtractArchiveCallCount()).To(Equal(1))
@@ -668,6 +745,7 @@ var _ = Describe("construct_helpers", func() {
668745

669746
Expect(fakeVcenterClient.MakeDirectoryCallCount()).To(Equal(1))
670747
Expect(fakeVcenterClient.UploadArtifactCallCount()).To(Equal(2))
748+
Expect(fakeVcenterClient.RunCallCount()).To(Equal(1))
671749
Expect(fakeWinRMEnabler.EnableCallCount()).To(Equal(1))
672750
Expect(fakeVMConnectionValidator.ValidateCallCount()).To(Equal(1))
673751
Expect(fakeRemoteManager.ExtractArchiveCallCount()).To(Equal(1))
@@ -693,6 +771,7 @@ var _ = Describe("construct_helpers", func() {
693771

694772
Expect(fakeVcenterClient.MakeDirectoryCallCount()).To(Equal(1))
695773
Expect(fakeVcenterClient.UploadArtifactCallCount()).To(Equal(2))
774+
Expect(fakeVcenterClient.RunCallCount()).To(Equal(1))
696775
Expect(fakeWinRMEnabler.EnableCallCount()).To(Equal(1))
697776
Expect(fakeVMConnectionValidator.ValidateCallCount()).To(Equal(1))
698777
Expect(fakeRemoteManager.ExtractArchiveCallCount()).To(Equal(1))

stembuild/iaas_cli/iaas_clients/vcenter_client.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,19 @@ func (c *VcenterClient) IsPoweredOff(vmInventoryPath string) (bool, error) {
166166
return false, nil
167167
}
168168

169+
func (c *VcenterClient) Run(vmInventoryPath, username, password string, commandAndArgs []string) error {
170+
args := c.buildGovcCommand(append([]string{"guest.run", "-l", vmCredentials(username, password), "-vm", vmInventoryPath}, commandAndArgs...)...)
171+
_, exitCode, err := c.Runner.RunWithOutput(args)
172+
if err != nil {
173+
return fmt.Errorf("vcenter_client - '%v' return an error '%s'", args, err)
174+
}
175+
if exitCode != 0 {
176+
return fmt.Errorf("vcenter_client - '%v' exited with '%d'", args, exitCode)
177+
}
178+
179+
return nil
180+
}
181+
169182
func (c *VcenterClient) Start(vmInventoryPath, username, password, command string, args ...string) (string, error) {
170183
cmdArgs := c.buildGovcCommand(append([]string{"guest.start", "-l", vmCredentials(username, password), "-vm", vmInventoryPath, command}, args...)...)
171184
pid, exitCode, err := c.Runner.RunWithOutput(cmdArgs)

0 commit comments

Comments
 (0)