e2e-aci_test.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. /*
  2. Copyright 2020 Docker, Inc.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package main
  14. import (
  15. "context"
  16. "errors"
  17. "fmt"
  18. "io/ioutil"
  19. "net/http"
  20. "net/url"
  21. "os"
  22. "runtime"
  23. "strconv"
  24. "strings"
  25. "syscall"
  26. "testing"
  27. "time"
  28. "gotest.tools/v3/assert"
  29. is "gotest.tools/v3/assert/cmp"
  30. "gotest.tools/v3/icmd"
  31. "gotest.tools/v3/poll"
  32. "github.com/Azure/azure-sdk-for-go/profiles/2019-03-01/resources/mgmt/resources"
  33. azure_storage "github.com/Azure/azure-sdk-for-go/profiles/2019-03-01/storage/mgmt/storage"
  34. "github.com/Azure/azure-storage-file-go/azfile"
  35. "github.com/Azure/go-autorest/autorest/to"
  36. "github.com/docker/api/aci"
  37. "github.com/docker/api/aci/login"
  38. "github.com/docker/api/containers"
  39. "github.com/docker/api/context/store"
  40. "github.com/docker/api/errdefs"
  41. "github.com/docker/api/tests/aci-e2e/storage"
  42. . "github.com/docker/api/tests/framework"
  43. )
  44. const (
  45. contextName = "aci-test"
  46. location = "westeurope"
  47. )
  48. var binDir string
  49. func TestMain(m *testing.M) {
  50. p, cleanup, err := SetupExistingCLI()
  51. if err != nil {
  52. fmt.Println(err)
  53. os.Exit(1)
  54. }
  55. binDir = p
  56. exitCode := m.Run()
  57. cleanup()
  58. os.Exit(exitCode)
  59. }
  60. // Cannot be parallelized as login/logout is global.
  61. func TestLoginLogout(t *testing.T) {
  62. startTime := strconv.Itoa(int(time.Now().UnixNano()))
  63. c := NewE2eCLI(t, binDir)
  64. rg := "E2E-" + startTime
  65. t.Run("login", func(t *testing.T) {
  66. azureLogin(t)
  67. })
  68. t.Run("create context", func(t *testing.T) {
  69. sID := getSubscriptionID(t)
  70. err := createResourceGroup(sID, rg)
  71. assert.Check(t, is.Nil(err))
  72. t.Cleanup(func() {
  73. _ = deleteResourceGroup(rg)
  74. })
  75. res := c.RunDockerCmd("context", "create", "aci", contextName, "--subscription-id", sID, "--resource-group", rg, "--location", location)
  76. res.Assert(t, icmd.Success)
  77. res = c.RunDockerCmd("context", "use", contextName)
  78. res.Assert(t, icmd.Expected{Out: contextName})
  79. res = c.RunDockerCmd("context", "ls")
  80. res.Assert(t, icmd.Expected{Out: contextName + " *"})
  81. })
  82. t.Run("delete context", func(t *testing.T) {
  83. res := c.RunDockerCmd("context", "use", "default")
  84. res.Assert(t, icmd.Expected{Out: "default"})
  85. res = c.RunDockerCmd("context", "rm", contextName)
  86. res.Assert(t, icmd.Expected{Out: contextName})
  87. })
  88. t.Run("logout", func(t *testing.T) {
  89. _, err := os.Stat(login.GetTokenStorePath())
  90. assert.NilError(t, err)
  91. res := c.RunDockerCmd("logout", "azure")
  92. res.Assert(t, icmd.Expected{Out: "Removing login credentials for Azure"})
  93. _, err = os.Stat(login.GetTokenStorePath())
  94. assert.ErrorContains(t, err, "no such file or directory")
  95. })
  96. t.Run("create context fail", func(t *testing.T) {
  97. res := c.RunDockerCmd("context", "create", "aci", "fail-context")
  98. res.Assert(t, icmd.Expected{
  99. ExitCode: errdefs.ExitCodeLoginRequired,
  100. Err: `not logged in to azure, you need to run "docker login azure" first`,
  101. })
  102. })
  103. }
  104. func TestContainerRun(t *testing.T) {
  105. c := NewParallelE2eCLI(t, binDir)
  106. sID, rg := setupTestResourceGroup(t, c)
  107. const (
  108. testShareName = "dockertestshare"
  109. testFileContent = "Volume mounted successfully!"
  110. testFileName = "index.html"
  111. )
  112. // Bootstrap volume
  113. aciContext := store.AciContext{
  114. SubscriptionID: sID,
  115. Location: location,
  116. ResourceGroup: rg,
  117. }
  118. saName := "e2e" + strconv.Itoa(int(time.Now().UnixNano()))
  119. _, cleanupSa := createStorageAccount(t, aciContext, saName)
  120. t.Cleanup(func() {
  121. if err := cleanupSa(); err != nil {
  122. t.Error(err)
  123. }
  124. })
  125. keys := getStorageKeys(t, aciContext, saName)
  126. assert.Assert(t, len(keys) > 0)
  127. k := *keys[0].Value
  128. cred, u := createFileShare(t, k, testShareName, saName)
  129. uploadFile(t, *cred, u.String(), testFileName, testFileContent)
  130. // Used in subtests
  131. var (
  132. container string
  133. hostIP string
  134. endpoint string
  135. )
  136. t.Run("run", func(t *testing.T) {
  137. mountTarget := "/usr/share/nginx/html"
  138. res := c.RunDockerCmd(
  139. "run", "-d",
  140. "-v", fmt.Sprintf("%s:%s@%s:%s", saName, k, testShareName, mountTarget),
  141. "-p", "80:80",
  142. "nginx",
  143. )
  144. res.Assert(t, icmd.Success)
  145. container = getContainerName(res.Stdout())
  146. t.Logf("Container name: %s", container)
  147. })
  148. t.Run("inspect", func(t *testing.T) {
  149. res := c.RunDockerCmd("inspect", container)
  150. res.Assert(t, icmd.Success)
  151. containerInspect, err := ParseContainerInspect(res.Stdout())
  152. assert.NilError(t, err)
  153. assert.Equal(t, containerInspect.Platform, "Linux")
  154. assert.Equal(t, containerInspect.CPULimit, 1.0)
  155. assert.Equal(t, containerInspect.RestartPolicyCondition, containers.RestartPolicyNone)
  156. assert.Assert(t, is.Len(containerInspect.Ports, 1))
  157. hostIP = containerInspect.Ports[0].HostIP
  158. endpoint = fmt.Sprintf("http://%s:%d", containerInspect.Ports[0].HostIP, containerInspect.Ports[0].HostPort)
  159. t.Logf("Endpoint: %s", endpoint)
  160. })
  161. t.Run("ps", func(t *testing.T) {
  162. res := c.RunDockerCmd("ps")
  163. res.Assert(t, icmd.Success)
  164. out := strings.Split(strings.TrimSpace(res.Stdout()), "\n")
  165. l := out[len(out)-1]
  166. assert.Assert(t, strings.Contains(l, container))
  167. assert.Assert(t, strings.Contains(l, "nginx"))
  168. assert.Assert(t, strings.Contains(l, "Running"))
  169. assert.Assert(t, strings.Contains(l, hostIP+":80->80/tcp"))
  170. })
  171. t.Run("http get", func(t *testing.T) {
  172. r, err := http.Get(endpoint)
  173. assert.NilError(t, err)
  174. assert.Equal(t, r.StatusCode, http.StatusOK)
  175. b, err := ioutil.ReadAll(r.Body)
  176. assert.NilError(t, err)
  177. assert.Assert(t, strings.Contains(string(b), testFileContent), "Actual content: "+string(b))
  178. })
  179. t.Run("logs", func(t *testing.T) {
  180. res := c.RunDockerCmd("logs", container)
  181. res.Assert(t, icmd.Expected{Out: "GET"})
  182. })
  183. t.Run("exec", func(t *testing.T) {
  184. res := c.RunDockerCmd("exec", container, "pwd")
  185. res.Assert(t, icmd.Expected{Out: "/"})
  186. res = c.RunDockerCmd("exec", container, "echo", "fail_with_argument")
  187. res.Assert(t, icmd.Expected{
  188. ExitCode: 1,
  189. Err: "ACI exec command does not accept arguments to the command. Only the binary should be specified",
  190. })
  191. })
  192. t.Run("logs follow", func(t *testing.T) {
  193. cmd := c.NewDockerCmd("logs", "--follow", container)
  194. res := icmd.StartCmd(cmd)
  195. checkUp := func(t poll.LogT) poll.Result {
  196. r, _ := http.Get(endpoint + "/is_up")
  197. if r != nil && r.StatusCode == http.StatusNotFound {
  198. return poll.Success()
  199. }
  200. return poll.Continue("waiting for container to serve request")
  201. }
  202. poll.WaitOn(t, checkUp, poll.WithDelay(1*time.Second), poll.WithTimeout(60*time.Second))
  203. assert.Assert(t, !strings.Contains(res.Stdout(), "/test"))
  204. checkLogs := func(t poll.LogT) poll.Result {
  205. if strings.Contains(res.Stdout(), "/test") {
  206. return poll.Success()
  207. }
  208. return poll.Continue("waiting for logs to contain /test")
  209. }
  210. // Do request on /test
  211. go func() {
  212. time.Sleep(3 * time.Second)
  213. _, _ = http.Get(endpoint + "/test")
  214. }()
  215. poll.WaitOn(t, checkLogs, poll.WithDelay(3*time.Second), poll.WithTimeout(20*time.Second))
  216. if runtime.GOOS == "windows" {
  217. err := res.Cmd.Process.Kill()
  218. assert.NilError(t, err)
  219. } else {
  220. err := res.Cmd.Process.Signal(syscall.SIGTERM)
  221. assert.NilError(t, err)
  222. }
  223. })
  224. t.Run("rm", func(t *testing.T) {
  225. res := c.RunDockerCmd("rm", container)
  226. res.Assert(t, icmd.Expected{Out: container})
  227. checkStopped := func(t poll.LogT) poll.Result {
  228. res := c.RunDockerCmd("inspect", container)
  229. if res.ExitCode == 1 {
  230. return poll.Success()
  231. }
  232. return poll.Continue("waiting for container to stop")
  233. }
  234. poll.WaitOn(t, checkStopped, poll.WithDelay(5*time.Second), poll.WithTimeout(60*time.Second))
  235. })
  236. }
  237. func TestContainerRunAttached(t *testing.T) {
  238. c := NewParallelE2eCLI(t, binDir)
  239. _, _ = setupTestResourceGroup(t, c)
  240. // Used in subtests
  241. var (
  242. container string
  243. endpoint string
  244. )
  245. t.Run("run attached limits", func(t *testing.T) {
  246. container = "test-container"
  247. cmd := c.NewDockerCmd(
  248. "run",
  249. "--name", container,
  250. "--restart", "on-failure",
  251. "--memory", "0.1G", "--cpus", "0.1",
  252. "-p", "80:80",
  253. "nginx",
  254. )
  255. runRes := icmd.StartCmd(cmd)
  256. checkRunning := func(t poll.LogT) poll.Result {
  257. res := c.RunDockerCmd("inspect", container)
  258. if res.ExitCode == 0 {
  259. return poll.Success()
  260. }
  261. return poll.Continue("waiting for container to be running")
  262. }
  263. poll.WaitOn(t, checkRunning, poll.WithDelay(5*time.Second), poll.WithTimeout(60*time.Second))
  264. inspectRes := c.RunDockerCmd("inspect", container)
  265. inspectRes.Assert(t, icmd.Success)
  266. containerInspect, err := ParseContainerInspect(inspectRes.Stdout())
  267. assert.NilError(t, err)
  268. assert.Equal(t, containerInspect.Platform, "Linux")
  269. assert.Equal(t, containerInspect.CPULimit, 0.1)
  270. assert.Equal(t, containerInspect.MemoryLimit, uint64(107374182))
  271. assert.Equal(t, containerInspect.RestartPolicyCondition, containers.RestartPolicyOnFailure)
  272. assert.Assert(t, is.Len(containerInspect.Ports, 1))
  273. endpoint = fmt.Sprintf("http://%s:%d", containerInspect.Ports[0].HostIP, containerInspect.Ports[0].HostPort)
  274. t.Logf("Endpoint: %s", endpoint)
  275. assert.Assert(t, !strings.Contains(runRes.Stdout(), "/test"))
  276. checkRequest := func(t poll.LogT) poll.Result {
  277. r, _ := http.Get(endpoint + "/test")
  278. if r != nil && r.StatusCode == http.StatusNotFound {
  279. return poll.Success()
  280. }
  281. return poll.Continue("waiting for container to serve request")
  282. }
  283. poll.WaitOn(t, checkRequest, poll.WithDelay(1*time.Second), poll.WithTimeout(60*time.Second))
  284. checkLog := func(t poll.LogT) poll.Result {
  285. if strings.Contains(runRes.Stdout(), "/test") {
  286. return poll.Success()
  287. }
  288. return poll.Continue("waiting for logs to contain /test")
  289. }
  290. poll.WaitOn(t, checkLog, poll.WithDelay(1*time.Second), poll.WithTimeout(20*time.Second))
  291. })
  292. t.Run("rm attached", func(t *testing.T) {
  293. res := c.RunDockerCmd("rm", container)
  294. res.Assert(t, icmd.Expected{Out: container})
  295. })
  296. }
  297. func TestCompose(t *testing.T) {
  298. c := NewParallelE2eCLI(t, binDir)
  299. _, _ = setupTestResourceGroup(t, c)
  300. const (
  301. composeFile = "../composefiles/aci-demo/aci_demo_port.yaml"
  302. composeFileMultiplePorts = "../composefiles/aci-demo/aci_demo_multi_port.yaml"
  303. composeProjectName = "acie2e"
  304. serverContainer = composeProjectName + "_web"
  305. wordsContainer = composeProjectName + "_words"
  306. )
  307. t.Run("compose up", func(t *testing.T) {
  308. // Name of Compose project is taken from current folder "acie2e"
  309. res := c.RunDockerCmd("compose", "up", "-f", composeFile)
  310. res.Assert(t, icmd.Success)
  311. res = c.RunDockerCmd("ps")
  312. res.Assert(t, icmd.Success)
  313. out := strings.Split(strings.TrimSpace(res.Stdout()), "\n")
  314. // Check three containers are running
  315. assert.Assert(t, is.Len(out, 4))
  316. webRunning := false
  317. for _, l := range out {
  318. if strings.Contains(l, serverContainer) {
  319. webRunning = true
  320. strings.Contains(l, ":80->80/tcp")
  321. }
  322. }
  323. assert.Assert(t, webRunning, "web container not running")
  324. res = c.RunDockerCmd("inspect", serverContainer)
  325. res.Assert(t, icmd.Success)
  326. containerInspect, err := ParseContainerInspect(res.Stdout())
  327. assert.NilError(t, err)
  328. assert.Assert(t, is.Len(containerInspect.Ports, 1))
  329. endpoint := fmt.Sprintf("http://%s:%d", containerInspect.Ports[0].HostIP, containerInspect.Ports[0].HostPort)
  330. t.Logf("Endpoint: %s", endpoint)
  331. r, err := http.Get(endpoint + "/words/noun")
  332. assert.NilError(t, err)
  333. assert.Equal(t, r.StatusCode, http.StatusOK)
  334. b, err := ioutil.ReadAll(r.Body)
  335. assert.NilError(t, err)
  336. assert.Assert(t, strings.Contains(string(b), `"word":`))
  337. })
  338. t.Run("logs web", func(t *testing.T) {
  339. res := c.RunDockerCmd("logs", serverContainer)
  340. res.Assert(t, icmd.Expected{Out: "Listening on port 80"})
  341. })
  342. t.Run("update", func(t *testing.T) {
  343. res := c.RunDockerCmd("compose", "up", "-f", composeFileMultiplePorts, "--project-name", composeProjectName)
  344. res.Assert(t, icmd.Success)
  345. res = c.RunDockerCmd("ps")
  346. res.Assert(t, icmd.Success)
  347. out := strings.Split(strings.TrimSpace(res.Stdout()), "\n")
  348. // Check three containers are running
  349. assert.Assert(t, is.Len(out, 4))
  350. for _, cName := range []string{serverContainer, wordsContainer} {
  351. res = c.RunDockerCmd("inspect", cName)
  352. res.Assert(t, icmd.Success)
  353. containerInspect, err := ParseContainerInspect(res.Stdout())
  354. assert.NilError(t, err)
  355. assert.Assert(t, is.Len(containerInspect.Ports, 1))
  356. endpoint := fmt.Sprintf("http://%s:%d", containerInspect.Ports[0].HostIP, containerInspect.Ports[0].HostPort)
  357. t.Logf("Endpoint: %s", endpoint)
  358. var route string
  359. switch cName {
  360. case serverContainer:
  361. route = "/words/noun"
  362. assert.Equal(t, containerInspect.Ports[0].HostPort, uint32(80))
  363. assert.Equal(t, containerInspect.Ports[0].ContainerPort, uint32(80))
  364. case wordsContainer:
  365. route = "/noun"
  366. assert.Equal(t, containerInspect.Ports[0].HostPort, uint32(8080))
  367. assert.Equal(t, containerInspect.Ports[0].ContainerPort, uint32(8080))
  368. }
  369. checkUp := func(t poll.LogT) poll.Result {
  370. r, _ := http.Get(endpoint + route)
  371. if r != nil && r.StatusCode == http.StatusOK {
  372. return poll.Success()
  373. }
  374. return poll.Continue("Waiting for container to serve request")
  375. }
  376. poll.WaitOn(t, checkUp, poll.WithDelay(1*time.Second), poll.WithTimeout(60*time.Second))
  377. res = c.RunDockerCmd("ps")
  378. p := containerInspect.Ports[0]
  379. res.Assert(t, icmd.Expected{
  380. Out: fmt.Sprintf("%s:%d->%d/tcp", p.HostIP, p.HostPort, p.ContainerPort),
  381. })
  382. }
  383. })
  384. t.Run("down", func(t *testing.T) {
  385. res := c.RunDockerCmd("compose", "down", "--project-name", composeProjectName)
  386. res.Assert(t, icmd.Success)
  387. res = c.RunDockerCmd("ps")
  388. res.Assert(t, icmd.Success)
  389. out := strings.Split(strings.TrimSpace(res.Stdout()), "\n")
  390. assert.Equal(t, len(out), 1)
  391. })
  392. }
  393. func TestRunEnvVars(t *testing.T) {
  394. c := NewParallelE2eCLI(t, binDir)
  395. _, _ = setupTestResourceGroup(t, c)
  396. t.Run("run", func(t *testing.T) {
  397. cmd := c.NewDockerCmd(
  398. "run", "-d",
  399. "-e", "MYSQL_ROOT_PASSWORD=rootpwd",
  400. "-e", "MYSQL_DATABASE=mytestdb",
  401. "-e", "MYSQL_USER",
  402. "-e", "MYSQL_PASSWORD=userpwd",
  403. "mysql:5.7",
  404. )
  405. cmd.Env = append(cmd.Env, "MYSQL_USER=user1")
  406. res := icmd.RunCmd(cmd)
  407. res.Assert(t, icmd.Success)
  408. out := strings.Split(strings.TrimSpace(res.Stdout()), "\n")
  409. container := strings.TrimSpace(out[len(out)-1])
  410. t.Logf("Container name: %s", container)
  411. res = c.RunDockerCmd("inspect", container)
  412. res.Assert(t, icmd.Success)
  413. containerInspect, err := ParseContainerInspect(res.Stdout())
  414. assert.NilError(t, err)
  415. assert.Equal(t, containerInspect.Image, "mysql:5.7")
  416. check := func(t poll.LogT) poll.Result {
  417. res := c.RunDockerCmd("logs", container)
  418. if strings.Contains(res.Stdout(), "Giving user user1 access to schema mytestdb") {
  419. return poll.Success()
  420. }
  421. return poll.Continue("waiting for DB container to be up")
  422. }
  423. poll.WaitOn(t, check, poll.WithDelay(5*time.Second), poll.WithTimeout(60*time.Second))
  424. })
  425. }
  426. func setupTestResourceGroup(t *testing.T, c *E2eCLI) (string, string) {
  427. startTime := strconv.Itoa(int(time.Now().UnixNano()))
  428. name := "E2E-" + startTime
  429. azureLogin(t)
  430. sID := getSubscriptionID(t)
  431. t.Logf("Create resource group %q", name)
  432. err := createResourceGroup(sID, name)
  433. assert.Check(t, is.Nil(err))
  434. t.Cleanup(func() {
  435. if err := deleteResourceGroup(name); err != nil {
  436. t.Error(err)
  437. }
  438. })
  439. createAciContextAndUseIt(t, c, sID, name)
  440. // Check nothing is running
  441. res := c.RunDockerCmd("ps")
  442. res.Assert(t, icmd.Success)
  443. assert.Assert(t, is.Len(strings.Split(strings.TrimSpace(res.Stdout()), "\n"), 1))
  444. return sID, name
  445. }
  446. func deleteResourceGroup(rgName string) error {
  447. ctx := context.TODO()
  448. helper := aci.NewACIResourceGroupHelper()
  449. models, err := helper.GetSubscriptionIDs(ctx)
  450. if err != nil {
  451. return err
  452. }
  453. if len(models) == 0 {
  454. return errors.New("unable to delete resource group: no models")
  455. }
  456. return helper.DeleteAsync(ctx, *models[0].SubscriptionID, rgName)
  457. }
  458. func azureLogin(t *testing.T) {
  459. t.Log("Log in to Azure")
  460. login, err := login.NewAzureLoginService()
  461. assert.NilError(t, err)
  462. // in order to create new service principal and get these 3 values : `az ad sp create-for-rbac --name 'TestServicePrincipal' --sdk-auth`
  463. clientID := os.Getenv("AZURE_CLIENT_ID")
  464. clientSecret := os.Getenv("AZURE_CLIENT_SECRET")
  465. tenantID := os.Getenv("AZURE_TENANT_ID")
  466. err = login.TestLoginFromServicePrincipal(clientID, clientSecret, tenantID)
  467. assert.NilError(t, err)
  468. }
  469. func getSubscriptionID(t *testing.T) string {
  470. ctx := context.TODO()
  471. helper := aci.NewACIResourceGroupHelper()
  472. models, err := helper.GetSubscriptionIDs(ctx)
  473. assert.Check(t, is.Nil(err))
  474. assert.Check(t, len(models) == 1)
  475. return *models[0].SubscriptionID
  476. }
  477. func createResourceGroup(sID, rgName string) error {
  478. helper := aci.NewACIResourceGroupHelper()
  479. _, err := helper.CreateOrUpdate(context.TODO(), sID, rgName, resources.Group{Location: to.StringPtr(location)})
  480. return err
  481. }
  482. func createAciContextAndUseIt(t *testing.T, c *E2eCLI, sID, rgName string) {
  483. t.Log("Create ACI context")
  484. res := c.RunDockerCmd("context", "create", "aci", contextName, "--subscription-id", sID, "--resource-group", rgName, "--location", location)
  485. res.Assert(t, icmd.Success)
  486. res = c.RunDockerCmd("context", "use", contextName)
  487. res.Assert(t, icmd.Expected{Out: contextName})
  488. res = c.RunDockerCmd("context", "ls")
  489. res.Assert(t, icmd.Expected{Out: contextName + " *"})
  490. }
  491. func createStorageAccount(t *testing.T, aciContext store.AciContext, name string) (azure_storage.Account, func() error) {
  492. t.Logf("Create storage account %q", name)
  493. account, err := storage.CreateStorageAccount(context.TODO(), aciContext, name)
  494. assert.Check(t, is.Nil(err))
  495. assert.Check(t, is.Equal(*(account.Name), name))
  496. return account, func() error { return deleteStorageAccount(aciContext, name) }
  497. }
  498. func deleteStorageAccount(aciContext store.AciContext, name string) error {
  499. _, err := storage.DeleteStorageAccount(context.TODO(), aciContext, name)
  500. return err
  501. }
  502. func getStorageKeys(t *testing.T, aciContext store.AciContext, saName string) []azure_storage.AccountKey {
  503. l, err := storage.ListKeys(context.TODO(), aciContext, saName)
  504. assert.NilError(t, err)
  505. assert.Assert(t, l.Keys != nil)
  506. return *l.Keys
  507. }
  508. func createFileShare(t *testing.T, key, share, storageAccount string) (*azfile.SharedKeyCredential, *url.URL) {
  509. // Create a ShareURL object that wraps a soon-to-be-created share's URL and a default pipeline.
  510. u, _ := url.Parse(fmt.Sprintf("https://%s.file.core.windows.net/%s", storageAccount, share))
  511. cred, err := azfile.NewSharedKeyCredential(storageAccount, key)
  512. assert.NilError(t, err)
  513. shareURL := azfile.NewShareURL(*u, azfile.NewPipeline(cred, azfile.PipelineOptions{}))
  514. _, err = shareURL.Create(context.TODO(), azfile.Metadata{}, 0)
  515. assert.NilError(t, err)
  516. return cred, u
  517. }
  518. func uploadFile(t *testing.T, cred azfile.SharedKeyCredential, baseURL, fileName, content string) {
  519. fURL, err := url.Parse(baseURL + "/" + fileName)
  520. assert.NilError(t, err)
  521. fileURL := azfile.NewFileURL(*fURL, azfile.NewPipeline(&cred, azfile.PipelineOptions{}))
  522. err = azfile.UploadBufferToAzureFile(context.TODO(), []byte(content), fileURL, azfile.UploadToAzureFileOptions{})
  523. assert.NilError(t, err)
  524. }
  525. func getContainerName(stdout string) string {
  526. out := strings.Split(strings.TrimSpace(stdout), "\n")
  527. return strings.TrimSpace(out[len(out)-1])
  528. }