Skip to content

Commit

Permalink
test(e2e): add spec to cover legacy docker config file (#1206)
Browse files Browse the repository at this point in the history
Signed-off-by: Billy Zha <jinzha1@microsoft.com>
  • Loading branch information
qweeah committed Dec 21, 2023
1 parent ad47ec0 commit a377128
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 45 deletions.
7 changes: 3 additions & 4 deletions test/e2e/internal/utils/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,9 @@ const (
orasBinary = "oras"

// customize your own basic auth file via `htpasswd -cBb <file_name> <user_name> <password>`
Username = "hello"
Password = "oras-test"
AuthConfigPath = "test.config"
DefaultTimeout = 10 * time.Second
Username = "hello"
Password = "oras-test"
DefaultTimeout = 10 * time.Second
// If the command hasn't exited yet, ginkgo session ExitCode is -1
notResponding = -1
)
Expand Down
15 changes: 8 additions & 7 deletions test/e2e/internal/utils/testdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ limitations under the License.
package utils

const (
PreviewDesc = "** This command is in preview and under development. **"
ExampleDesc = "\nExample - "
ImageRepo = "command/images"
BlobRepo = "command/blobs"
ArtifactRepo = "command/artifacts"
Namespace = "command"
InvalidRepo = "INVALID"
PreviewDesc = "** This command is in preview and under development. **"
ExampleDesc = "\nExample - "
ImageRepo = "command/images"
BlobRepo = "command/blobs"
ArtifactRepo = "command/artifacts"
Namespace = "command"
InvalidRepo = "INVALID"
LegacyConfigName = "legacy.config"
// env
RegHostKey = "ORAS_REGISTRY_HOST"
FallbackRegHostKey = "ORAS_REGISTRY_FALLBACK_HOST"
Expand Down
73 changes: 40 additions & 33 deletions test/e2e/suite/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,49 +17,47 @@ package scenario

import (
"fmt"
"path/filepath"
"strings"
"time"

. "github.com/onsi/ginkgo/v2"
"oras.land/oras-go/v2"
"oras.land/oras/test/e2e/internal/testdata/foobar"
. "oras.land/oras/test/e2e/internal/utils"
)

var _ = Describe("Common registry user", Ordered, func() {
When("logging out", Ordered, func() {
It("should use logout command to logout", func() {
ORAS("logout", ZOTHost, "--registry-config", AuthConfigPath).Exec()
})

var _ = Describe("Common registry user", func() {
When("not logged in", func() {
It("should run commands without logging in", func() {
RunWithoutLogin("attach", ZOTHost+"/repo:tag", "-a", "test=true", "--artifact-type", "doc/example")
ORAS("copy", ZOTHost+"/repo:from", ZOTHost+"/repo:to", "--from-registry-config", AuthConfigPath, "--to-registry-config", AuthConfigPath).
ExpectFailure().
MatchErrKeyWords("Error:", "credential required").
WithDescription("fail without logging in").Exec()
RunWithoutLogin("discover", ZOTHost+"/repo:tag")
RunWithoutLogin("push", "-a", "key=value", ZOTHost+"/repo:tag")
RunWithoutLogin("pull", ZOTHost+"/repo:tag")
RunWithoutLogin("manifest", "fetch", ZOTHost+"/repo:tag")
RunWithoutLogin("blob", "delete", ZOTHost+"/repo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
RunWithoutLogin("blob", "push", ZOTHost+"/repo", WriteTempFile("blob", "test"))
RunWithoutLogin("tag", ZOTHost+"/repo:tag", "tag1")
RunWithoutLogin("resolve", ZOTHost+"/repo:tag")
RunWithoutLogin("repo", "ls", ZOTHost)
RunWithoutLogin("repo", "tags", RegistryRef(ZOTHost, "repo", ""))
RunWithoutLogin("manifest", "fetch-config", ZOTHost+"/repo:tag")
authConfigPath := filepath.Join(GinkgoT().TempDir(), "auth.config")
RunWithoutLogin("attach", ZOTHost+"/repo:tag", "-a", "test=true", "--artifact-type", "doc/example", "--registry-config", authConfigPath)
RunWithoutLogin("copy", ZOTHost+"/repo:from", ZOTHost+"/repo:to", "--from-registry-config", authConfigPath, "--to-registry-config", authConfigPath)
RunWithoutLogin("discover", ZOTHost+"/repo:tag", "--registry-config", authConfigPath)
RunWithoutLogin("push", "-a", "key=value", ZOTHost+"/repo:tag", "--registry-config", authConfigPath)
RunWithoutLogin("pull", ZOTHost+"/repo:tag", "--registry-config", authConfigPath)
RunWithoutLogin("manifest", "fetch", ZOTHost+"/repo:tag", "--registry-config", authConfigPath)
RunWithoutLogin("blob", "delete", ZOTHost+"/repo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "--registry-config", authConfigPath)
RunWithoutLogin("blob", "push", ZOTHost+"/repo", WriteTempFile("blob", "test"), "--registry-config", authConfigPath)
RunWithoutLogin("tag", ZOTHost+"/repo:tag", "tag1", "--registry-config", authConfigPath)
RunWithoutLogin("resolve", ZOTHost+"/repo:tag", "--registry-config", authConfigPath)
RunWithoutLogin("repo", "ls", ZOTHost, "--registry-config", authConfigPath)
RunWithoutLogin("repo", "tags", RegistryRef(ZOTHost, "repo", ""), "--registry-config", authConfigPath)
RunWithoutLogin("manifest", "fetch-config", ZOTHost+"/repo:tag", "--registry-config", authConfigPath)
})
})

When("logging in", func() {
It("should use basic auth", func() {
ORAS("login", ZOTHost, "-u", Username, "-p", Password, "--registry-config", AuthConfigPath).
tmpConfigName := "test.config"
It("should succeed to use basic auth", func() {
ORAS("login", ZOTHost, "-u", Username, "-p", Password, "--registry-config", filepath.Join(GinkgoT().TempDir(), tmpConfigName)).
WithTimeOut(20*time.Second).
MatchContent("Login Succeeded\n").
MatchErrKeyWords("WARNING", "Using --password via the CLI is insecure", "Use --password-stdin").Exec()
})

It("should fail if no username input", func() {
ORAS("login", ZOTHost, "--registry-config", AuthConfigPath).
ORAS("login", ZOTHost, "--registry-config", filepath.Join(GinkgoT().TempDir(), tmpConfigName)).
WithTimeOut(20 * time.Second).
WithInput(strings.NewReader("")).
MatchKeyWords("username:").
Expand All @@ -68,47 +66,56 @@ var _ = Describe("Common registry user", Ordered, func() {
})

It("should fail if no password input", func() {
ORAS("login", ZOTHost, "--registry-config", AuthConfigPath).
ORAS("login", ZOTHost, "--registry-config", filepath.Join(GinkgoT().TempDir(), tmpConfigName)).
WithTimeOut(20*time.Second).
MatchKeyWords("Username: ", "Password: ").
WithInput(strings.NewReader(fmt.Sprintf("%s\n", Username))).ExpectFailure().Exec()
})

It("should fail if password is empty", func() {
ORAS("login", ZOTHost, "--registry-config", AuthConfigPath).
ORAS("login", ZOTHost, "--registry-config", filepath.Join(GinkgoT().TempDir(), tmpConfigName)).
WithTimeOut(20*time.Second).
MatchKeyWords("Username: ", "Password: ").
MatchErrKeyWords("Error: password required").
WithInput(strings.NewReader(fmt.Sprintf("%s\n\n", Username))).ExpectFailure().Exec()
})

It("should fail if no token input", func() {
ORAS("login", ZOTHost, "--registry-config", AuthConfigPath).
ORAS("login", ZOTHost, "--registry-config", filepath.Join(GinkgoT().TempDir(), tmpConfigName)).
WithTimeOut(20*time.Second).
MatchKeyWords("Username: ", "Token: ").
WithInput(strings.NewReader("\n")).ExpectFailure().Exec()
})

It("should fail if token is empty", func() {
ORAS("login", ZOTHost, "--registry-config", AuthConfigPath).
ORAS("login", ZOTHost, "--registry-config", filepath.Join(GinkgoT().TempDir(), tmpConfigName)).
WithTimeOut(20*time.Second).
MatchKeyWords("Username: ", "Token: ").
MatchErrKeyWords("Error: token required").
WithInput(strings.NewReader("\n\n")).ExpectFailure().Exec()
})

It("should use prompted input", func() {
ORAS("login", ZOTHost, "--registry-config", AuthConfigPath).
It("should succeed to use prompted input", func() {
ORAS("login", ZOTHost, "--registry-config", filepath.Join(GinkgoT().TempDir(), tmpConfigName)).
WithTimeOut(20*time.Second).
WithInput(strings.NewReader(fmt.Sprintf("%s\n%s\n", Username, Password))).
MatchKeyWords("Username: ", "Password: ", "Login Succeeded\n").Exec()
})
})

When("using legacy config", func() {
var LegacyConfigPath = filepath.Join(TestDataRoot, LegacyConfigName)
It("should succeed to copy", func() {
src := RegistryRef(ZOTHost, ArtifactRepo, foobar.Tag)
dst := RegistryRef(ZOTHost, fmt.Sprintf("command/auth/%d/copy", GinkgoRandomSeed()), foobar.Tag)
foobarStates := append(foobar.ImageLayerStateKeys, foobar.ManifestStateKey, foobar.ImageConfigStateKey(oras.MediaTypeUnknownConfig))
ORAS("cp", src, dst, "-v", "--from-registry-config", LegacyConfigPath, "--to-registry-config", LegacyConfigPath).MatchStatus(foobarStates, true, len(foobarStates)).Exec()
})
})
})

func RunWithoutLogin(args ...string) {
ORAS(append(args, "--registry-config", AuthConfigPath)...).
ExpectFailure().
ORAS(args...).ExpectFailure().
MatchErrKeyWords("Error:", "credential required").
WithDescription("fail without logging in").Exec()
}
3 changes: 2 additions & 1 deletion test/e2e/suite/command/custom_header.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package command

import (
"fmt"
"path/filepath"

. "github.com/onsi/ginkgo/v2"
"oras.land/oras/test/e2e/internal/testdata/foobar"
Expand Down Expand Up @@ -80,7 +81,7 @@ var _ = Describe("1.1 registry users:", func() {
MatchRequestHeaders(FoobarHeader, AbHeader).Exec()
})
It("login", func() {
ORAS("login", Host, "-u", Username, "-p", Password, "--registry-config", AuthConfigPath,
ORAS("login", Host, "-u", Username, "-p", Password, "--registry-config", filepath.Join(GinkgoT().TempDir(), "test.config"),
"-H", FoobarHeaderInput, "-H", AbHeaderInput).
MatchRequestHeaders(FoobarHeader, AbHeader).Exec()
})
Expand Down
7 changes: 7 additions & 0 deletions test/e2e/testdata/legacy.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"auths": {
"http://localhost:7000/": {
"auth": "aGVsbG86b3Jhcy10ZXN0"
}
}
}

0 comments on commit a377128

Please sign in to comment.