Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(e2e): add spec to cover legacy docker config file #1206

Merged
merged 5 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"
}
}
}