зеркало из https://github.com/docker/hub-tool.git
Коммит
940ef126a6
|
@ -1,5 +1,5 @@
|
|||
name: Build PR
|
||||
on: [push,pull_request]
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
|
@ -31,7 +31,7 @@ jobs:
|
|||
env:
|
||||
GO111MODULE: "on"
|
||||
E2E_HUB_USERNAME: ${{ secrets.E2E_HUB_USERNAME }}
|
||||
E2E_HUB_TOKEN_TOKEN: ${{ secrets.E2E_HUB_TOKEN_TOKEN }}
|
||||
E2E_HUB_TOKEN: ${{ secrets.E2E_HUB_TOKEN }}
|
||||
steps:
|
||||
- name: Docker version
|
||||
run: docker version
|
||||
|
|
11
Makefile
11
Makefile
|
@ -55,14 +55,21 @@ e2e-build:
|
|||
|
||||
.PHONY: e2e
|
||||
e2e: e2e-build ## Run the end-to-end tests
|
||||
@docker run $(E2E_ENV) --rm -v /var/run/docker.sock:/var/run/docker.sock -v $(shell go env GOCACHE):/root/.cache/go-build $(BINARY_NAME):e2e
|
||||
docker run $(E2E_ENV) --rm \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-v $(shell go env GOCACHE):/root/.cache/go-build \
|
||||
-v $(shell go env GOMODCACHE):/go/pkg/mod \
|
||||
$(BINARY_NAME):e2e
|
||||
|
||||
test-unit-build:
|
||||
docker build $(BUILD_ARGS) . --target test-unit -t $(BINARY_NAME):test-unit
|
||||
|
||||
.PHONY: test-unit
|
||||
test-unit: test-unit-build ## Run unit tests
|
||||
docker run --rm -v $(shell go env GOCACHE):/root/.cache/go-build $(BINARY_NAME):test-unit
|
||||
docker run --rm \
|
||||
-v $(shell go env GOCACHE):/root/.cache/go-build \
|
||||
-v $(shell go env GOMODCACHE):/go/pkg/mod \
|
||||
$(BINARY_NAME):test-unit
|
||||
|
||||
.PHONY: lint
|
||||
lint: ## Run the go linter
|
||||
|
|
|
@ -23,10 +23,14 @@ import (
|
|||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/cli/cli/utils"
|
||||
"github.com/docker/cli/cli/command"
|
||||
cliflags "github.com/docker/cli/cli/flags"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
|
||||
"github.com/docker/hub-cli-plugin/internal/commands"
|
||||
"github.com/docker/hub-cli-plugin/internal/hub"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -43,7 +47,22 @@ func main() {
|
|||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
rootCmd := commands.NewRootCmd(ctx, dockerCli, os.Args[0])
|
||||
authResolver := func(hub *registry.IndexInfo) types.AuthConfig {
|
||||
return command.ResolveAuthConfig(ctx, dockerCli, hub)
|
||||
}
|
||||
|
||||
hubClient, err := hub.NewClient(authResolver, hub.WithContext(ctx))
|
||||
if err != nil {
|
||||
if hub.IsAuthenticationError(err) {
|
||||
fmt.Println(utils.Red(`You need to be logged in to Docker Hub to use this tool.
|
||||
Please login to Docker Hub using the "docker login" command.`))
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
rootCmd := commands.NewRootCmd(dockerCli, hubClient, os.Args[0])
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
|
@ -17,12 +17,14 @@
|
|||
package e2e
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
clitypes "github.com/docker/cli/cli/config/types"
|
||||
"gotest.tools/assert"
|
||||
"gotest.tools/v3/env"
|
||||
"gotest.tools/v3/fs"
|
||||
|
@ -30,13 +32,25 @@ import (
|
|||
)
|
||||
|
||||
func hubToolCmd(t *testing.T, args ...string) (icmd.Cmd, func()) {
|
||||
user := os.Getenv("E2E_HUB_USERNAME")
|
||||
token := os.Getenv("E2E_HUB_TOKEN")
|
||||
|
||||
config := configfile.ConfigFile{
|
||||
AuthConfigs: map[string]clitypes.AuthConfig{"https://index.docker.io/v1/": {
|
||||
Username: user,
|
||||
Password: token,
|
||||
}},
|
||||
}
|
||||
data, err := json.Marshal(&config)
|
||||
assert.NilError(t, err)
|
||||
|
||||
pwd, err := os.Getwd()
|
||||
assert.NilError(t, err)
|
||||
hubTool := os.Getenv("BINARY")
|
||||
configDir := fs.NewDir(t, t.Name())
|
||||
configDir := fs.NewDir(t, t.Name(), fs.WithFile("config.json", string(data)))
|
||||
cleanup := env.Patch(t, "PATH", os.Getenv("PATH")+getPathSeparator()+filepath.Join(pwd, "..", "bin"))
|
||||
fmt.Println(os.Getenv("PATH"), os.Getenv("PWD"))
|
||||
env := append(os.Environ(), "DOCKER_CONFIG="+configDir.Path())
|
||||
|
||||
return icmd.Cmd{Command: append([]string{hubTool}, args...), Env: env}, func() { cleanup(); configDir.Remove() }
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
Copyright 2020 Docker Hub Tool authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gotest.tools/v3/icmd"
|
||||
)
|
||||
|
||||
func TestUserNeedsToBeLoggedIn(t *testing.T) {
|
||||
cmd, cleanup := hubToolCmd(t, "--version")
|
||||
// Remove the config file
|
||||
cleanup()
|
||||
|
||||
output := icmd.RunCmd(cmd)
|
||||
output.Equal(icmd.Expected{
|
||||
ExitCode: 1,
|
||||
Out: `You need to be logged in to Docker Hub to use this tool.
|
||||
Please login to Docker Hub using the "docker login" command
|
||||
`,
|
||||
})
|
||||
}
|
|
@ -17,11 +17,11 @@
|
|||
package account
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/hub-cli-plugin/internal/hub"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -29,15 +29,15 @@ const (
|
|||
)
|
||||
|
||||
//NewAccountCmd configures the org manage command
|
||||
func NewAccountCmd(ctx context.Context, dockerCli command.Cli) *cobra.Command {
|
||||
func NewAccountCmd(streams command.Streams, hubClient *hub.Client) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: accountName,
|
||||
Long: "Manage organizations",
|
||||
Args: cli.NoArgs,
|
||||
RunE: command.ShowHelp(dockerCli.Err()),
|
||||
RunE: command.ShowHelp(streams.Err()),
|
||||
}
|
||||
cmd.AddCommand(
|
||||
newInfoCmd(ctx, dockerCli, accountName),
|
||||
newInfoCmd(streams, hubClient, accountName),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
|
|
|
@ -17,18 +17,14 @@
|
|||
package account
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/cli/cli/utils"
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
|
@ -45,7 +41,7 @@ type infoOptions struct {
|
|||
format.Option
|
||||
}
|
||||
|
||||
func newInfoCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobra.Command {
|
||||
func newInfoCmd(streams command.Streams, hubClient *hub.Client, parent string) *cobra.Command {
|
||||
var opts infoOptions
|
||||
cmd := &cobra.Command{
|
||||
Use: infoName + " [OPTIONS]",
|
||||
|
@ -55,7 +51,7 @@ func newInfoCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobr
|
|||
metrics.Send(parent, infoName)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runInfo(ctx, dockerCli, opts)
|
||||
return runInfo(streams, hubClient, opts)
|
||||
},
|
||||
}
|
||||
opts.AddFormatFlag(cmd.Flags())
|
||||
|
@ -63,23 +59,16 @@ func newInfoCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobr
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runInfo(ctx context.Context, dockerCli command.Cli, opts infoOptions) error {
|
||||
authResolver := func(hub *registry.IndexInfo) types.AuthConfig {
|
||||
return command.ResolveAuthConfig(ctx, dockerCli, hub)
|
||||
}
|
||||
client, err := hub.NewClient(authResolver)
|
||||
func runInfo(streams command.Streams, hubClient *hub.Client, opts infoOptions) error {
|
||||
user, err := hubClient.GetUserInfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
user, err := client.GetUserInfo()
|
||||
plan, err := hubClient.GetHubPlan(user.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
plan, err := client.GetHubPlan(user.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return opts.Print(os.Stdout, account{user, plan}, printAccount)
|
||||
return opts.Print(streams.Out(), account{user, plan}, printAccount)
|
||||
}
|
||||
|
||||
func printAccount(out io.Writer, value interface{}) error {
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
package org
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/hub-cli-plugin/internal/hub"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -29,17 +29,17 @@ const (
|
|||
)
|
||||
|
||||
//NewOrgCmd configures the org manage command
|
||||
func NewOrgCmd(ctx context.Context, dockerCli command.Cli) *cobra.Command {
|
||||
func NewOrgCmd(streams command.Streams, hubClient *hub.Client) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: orgName,
|
||||
Long: "Manage organizations",
|
||||
Args: cli.NoArgs,
|
||||
RunE: command.ShowHelp(dockerCli.Err()),
|
||||
RunE: command.ShowHelp(streams.Err()),
|
||||
}
|
||||
cmd.AddCommand(
|
||||
newListCmd(ctx, dockerCli, orgName),
|
||||
newMembersCmd(ctx, dockerCli, orgName),
|
||||
newTeamsCmd(ctx, dockerCli, orgName),
|
||||
newListCmd(streams, hubClient, orgName),
|
||||
newMembersCmd(streams, hubClient, orgName),
|
||||
newTeamsCmd(streams, hubClient, orgName),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
|
|
|
@ -17,17 +17,13 @@
|
|||
package org
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/hub-cli-plugin/internal/format"
|
||||
|
@ -58,7 +54,7 @@ type listOptions struct {
|
|||
format.Option
|
||||
}
|
||||
|
||||
func newListCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobra.Command {
|
||||
func newListCmd(streams command.Streams, hubClient *hub.Client, parent string) *cobra.Command {
|
||||
var opts listOptions
|
||||
cmd := &cobra.Command{
|
||||
Use: listName,
|
||||
|
@ -68,7 +64,7 @@ func newListCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobr
|
|||
metrics.Send(parent, listName)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runList(ctx, dockerCli, opts)
|
||||
return runList(streams, hubClient, opts)
|
||||
},
|
||||
}
|
||||
opts.AddFormatFlag(cmd.Flags())
|
||||
|
@ -76,19 +72,12 @@ func newListCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobr
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runList(ctx context.Context, dockerCli command.Cli, opts listOptions) error {
|
||||
authResolver := func(hub *registry.IndexInfo) types.AuthConfig {
|
||||
return command.ResolveAuthConfig(ctx, dockerCli, hub)
|
||||
}
|
||||
client, err := hub.NewClient(authResolver)
|
||||
func runList(streams command.Streams, hubClient *hub.Client, opts listOptions) error {
|
||||
organizations, err := hubClient.GetOrganizations()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
organizations, err := client.GetOrganizations()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return opts.Print(os.Stdout, organizations, printOrganizations)
|
||||
return opts.Print(streams.Out(), organizations, printOrganizations)
|
||||
}
|
||||
|
||||
func printOrganizations(out io.Writer, values interface{}) error {
|
||||
|
|
|
@ -17,17 +17,13 @@
|
|||
package org
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/hub-cli-plugin/internal/format"
|
||||
|
@ -55,7 +51,7 @@ type memberOptions struct {
|
|||
format.Option
|
||||
}
|
||||
|
||||
func newMembersCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobra.Command {
|
||||
func newMembersCmd(streams command.Streams, hubClient *hub.Client, parent string) *cobra.Command {
|
||||
var opts memberOptions
|
||||
cmd := &cobra.Command{
|
||||
Use: membersName + " ORGANIZATION",
|
||||
|
@ -65,7 +61,7 @@ func newMembersCmd(ctx context.Context, dockerCli command.Cli, parent string) *c
|
|||
metrics.Send(parent, membersName)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runMembers(ctx, dockerCli, opts, args[0])
|
||||
return runMembers(streams, hubClient, opts, args[0])
|
||||
},
|
||||
}
|
||||
opts.AddFormatFlag(cmd.Flags())
|
||||
|
@ -73,19 +69,12 @@ func newMembersCmd(ctx context.Context, dockerCli command.Cli, parent string) *c
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runMembers(ctx context.Context, dockerCli command.Cli, opts memberOptions, organization string) error {
|
||||
authResolver := func(hub *registry.IndexInfo) types.AuthConfig {
|
||||
return command.ResolveAuthConfig(ctx, dockerCli, hub)
|
||||
}
|
||||
client, err := hub.NewClient(authResolver)
|
||||
func runMembers(streams command.Streams, hubClient *hub.Client, opts memberOptions, organization string) error {
|
||||
members, err := hubClient.GetMembers(organization)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
members, err := client.GetMembers(organization)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return opts.Print(os.Stdout, members, printMembers)
|
||||
return opts.Print(streams.Out(), members, printMembers)
|
||||
}
|
||||
|
||||
func printMembers(out io.Writer, values interface{}) error {
|
||||
|
|
|
@ -17,17 +17,13 @@
|
|||
package org
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/hub-cli-plugin/internal/format"
|
||||
|
@ -56,7 +52,7 @@ type teamsOptions struct {
|
|||
format.Option
|
||||
}
|
||||
|
||||
func newTeamsCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobra.Command {
|
||||
func newTeamsCmd(streams command.Streams, hubClient *hub.Client, parent string) *cobra.Command {
|
||||
var opts teamsOptions
|
||||
cmd := &cobra.Command{
|
||||
Use: teamsName + " ORGANIZATION",
|
||||
|
@ -66,7 +62,7 @@ func newTeamsCmd(ctx context.Context, dockerCli command.Cli, parent string) *cob
|
|||
metrics.Send(parent, teamsName)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runTeams(ctx, dockerCli, opts, args[0])
|
||||
return runTeams(streams, hubClient, opts, args[0])
|
||||
},
|
||||
}
|
||||
opts.AddFormatFlag(cmd.Flags())
|
||||
|
@ -74,19 +70,12 @@ func newTeamsCmd(ctx context.Context, dockerCli command.Cli, parent string) *cob
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runTeams(ctx context.Context, dockerCli command.Cli, opts teamsOptions, organization string) error {
|
||||
authResolver := func(hub *registry.IndexInfo) types.AuthConfig {
|
||||
return command.ResolveAuthConfig(ctx, dockerCli, hub)
|
||||
}
|
||||
client, err := hub.NewClient(authResolver)
|
||||
func runTeams(streams command.Streams, hubClient *hub.Client, opts teamsOptions, organization string) error {
|
||||
teams, err := hubClient.GetTeams(organization)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
teams, err := client.GetTeams(organization)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return opts.Print(os.Stdout, teams, printTeams)
|
||||
return opts.Print(streams.Out(), teams, printTeams)
|
||||
}
|
||||
|
||||
func printTeams(out io.Writer, values interface{}) error {
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
package repo
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/hub-cli-plugin/internal/hub"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -29,16 +29,16 @@ const (
|
|||
)
|
||||
|
||||
//NewRepoCmd configures the repo manage command
|
||||
func NewRepoCmd(ctx context.Context, dockerCli command.Cli) *cobra.Command {
|
||||
func NewRepoCmd(streams command.Streams, hubClient *hub.Client) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: repoName,
|
||||
Long: "Manage repositories",
|
||||
Args: cli.NoArgs,
|
||||
RunE: command.ShowHelp(dockerCli.Err()),
|
||||
RunE: command.ShowHelp(streams.Err()),
|
||||
}
|
||||
cmd.AddCommand(
|
||||
newListCmd(ctx, dockerCli, repoName),
|
||||
newRmCmd(ctx, dockerCli, repoName),
|
||||
newListCmd(streams, hubClient, repoName),
|
||||
newRmCmd(streams, hubClient, repoName),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
|
|
|
@ -17,18 +17,14 @@
|
|||
package repo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
|
@ -67,7 +63,7 @@ type listOptions struct {
|
|||
all bool
|
||||
}
|
||||
|
||||
func newListCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobra.Command {
|
||||
func newListCmd(streams command.Streams, hubClient *hub.Client, parent string) *cobra.Command {
|
||||
var opts listOptions
|
||||
cmd := &cobra.Command{
|
||||
Use: listName + " [ORGANIZATION]",
|
||||
|
@ -77,7 +73,7 @@ func newListCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobr
|
|||
metrics.Send(parent, listName)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runList(ctx, dockerCli, opts, args)
|
||||
return runList(streams, hubClient, opts, args)
|
||||
},
|
||||
}
|
||||
cmd.Flags().BoolVar(&opts.all, "all", false, "Fetch all available repositories")
|
||||
|
@ -86,30 +82,22 @@ func newListCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobr
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runList(ctx context.Context, dockerCli command.Cli, opts listOptions, args []string) error {
|
||||
var account string
|
||||
authResolver := func(hub *registry.IndexInfo) types.AuthConfig {
|
||||
authConfig := command.ResolveAuthConfig(ctx, dockerCli, hub)
|
||||
account = authConfig.Username
|
||||
return authConfig
|
||||
}
|
||||
var clientOps []hub.ClientOp
|
||||
func runList(streams command.Streams, hubClient *hub.Client, opts listOptions, args []string) error {
|
||||
account := hubClient.AuthConfig.Username
|
||||
if opts.all {
|
||||
clientOps = append(clientOps, hub.WithAllElements())
|
||||
}
|
||||
client, err := hub.NewClient(authResolver, clientOps...)
|
||||
if err != nil {
|
||||
return err
|
||||
if err := hubClient.Apply(hub.WithAllElements()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(args) > 0 {
|
||||
account = args[0]
|
||||
}
|
||||
repositories, err := client.GetRepositories(account)
|
||||
repositories, err := hubClient.GetRepositories(account)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return opts.Print(os.Stdout, repositories, printRepositories)
|
||||
return opts.Print(streams.Out(), repositories, printRepositories)
|
||||
}
|
||||
|
||||
func printRepositories(out io.Writer, values interface{}) error {
|
||||
|
|
|
@ -18,16 +18,12 @@ package repo
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/hub-cli-plugin/internal/hub"
|
||||
|
@ -42,7 +38,7 @@ type rmOptions struct {
|
|||
force bool
|
||||
}
|
||||
|
||||
func newRmCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobra.Command {
|
||||
func newRmCmd(streams command.Streams, hubClient *hub.Client, parent string) *cobra.Command {
|
||||
var opts rmOptions
|
||||
cmd := &cobra.Command{
|
||||
Use: rmName + " [OPTIONS] REPOSITORY",
|
||||
|
@ -52,7 +48,7 @@ func newRmCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobra.
|
|||
metrics.Send(parent, rmName)
|
||||
},
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
return runRm(ctx, dockerCli, opts, args[0])
|
||||
return runRm(streams, hubClient, opts, args[0])
|
||||
},
|
||||
}
|
||||
cmd.Flags().BoolVar(&opts.force, "force", false, "Force deletion of the repository")
|
||||
|
@ -60,7 +56,7 @@ func newRmCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobra.
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runRm(ctx context.Context, dockerCli command.Cli, opts rmOptions, repository string) error {
|
||||
func runRm(streams command.Streams, hubClient *hub.Client, opts rmOptions, repository string) error {
|
||||
ref, err := reference.Parse(repository)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -71,8 +67,8 @@ func runRm(ctx context.Context, dockerCli command.Cli, opts rmOptions, repositor
|
|||
}
|
||||
|
||||
if !opts.force {
|
||||
fmt.Println("Please type the name of your repository to confirm deletion:", namedRef.Name())
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
fmt.Fprintln(streams.Out(), "Please type the name of your repository to confirm deletion:", namedRef.Name())
|
||||
reader := bufio.NewReader(streams.In())
|
||||
input, _ := reader.ReadString('\n')
|
||||
input = strings.ToLower(strings.TrimSpace(input))
|
||||
if input != namedRef.Name() {
|
||||
|
@ -80,16 +76,9 @@ func runRm(ctx context.Context, dockerCli command.Cli, opts rmOptions, repositor
|
|||
}
|
||||
}
|
||||
|
||||
authResolver := func(hub *registry.IndexInfo) types.AuthConfig {
|
||||
return command.ResolveAuthConfig(ctx, dockerCli, hub)
|
||||
}
|
||||
client, err := hub.NewClient(authResolver)
|
||||
if err != nil {
|
||||
if err := hubClient.RemoveRepository(namedRef.Name()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := client.RemoveRepository(namedRef.Name()); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("Deleted", repository)
|
||||
fmt.Fprintln(streams.Out(), "Deleted", repository)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/cli/cli/command"
|
||||
|
@ -28,6 +27,7 @@ import (
|
|||
"github.com/docker/hub-cli-plugin/internal/commands/org"
|
||||
"github.com/docker/hub-cli-plugin/internal/commands/repo"
|
||||
"github.com/docker/hub-cli-plugin/internal/commands/tag"
|
||||
"github.com/docker/hub-cli-plugin/internal/hub"
|
||||
)
|
||||
|
||||
type options struct {
|
||||
|
@ -35,7 +35,7 @@ type options struct {
|
|||
}
|
||||
|
||||
//NewRootCmd returns the main command
|
||||
func NewRootCmd(ctx context.Context, dockerCli command.Cli, name string) *cobra.Command {
|
||||
func NewRootCmd(streams command.Streams, hubClient *hub.Client, name string) *cobra.Command {
|
||||
var flags options
|
||||
cmd := &cobra.Command{
|
||||
Use: name,
|
||||
|
@ -52,10 +52,10 @@ func NewRootCmd(ctx context.Context, dockerCli command.Cli, name string) *cobra.
|
|||
cmd.Flags().BoolVar(&flags.showVersion, "version", false, "Display version of the scan plugin")
|
||||
|
||||
cmd.AddCommand(
|
||||
account.NewAccountCmd(ctx, dockerCli),
|
||||
org.NewOrgCmd(ctx, dockerCli),
|
||||
repo.NewRepoCmd(ctx, dockerCli),
|
||||
tag.NewTagCmd(ctx, dockerCli),
|
||||
account.NewAccountCmd(streams, hubClient),
|
||||
org.NewOrgCmd(streams, hubClient),
|
||||
repo.NewRepoCmd(streams, hubClient),
|
||||
tag.NewTagCmd(streams, hubClient),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
package tag
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/hub-cli-plugin/internal/hub"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -29,17 +29,17 @@ const (
|
|||
)
|
||||
|
||||
//NewTagCmd configures the tag manage command
|
||||
func NewTagCmd(ctx context.Context, dockerCli command.Cli) *cobra.Command {
|
||||
func NewTagCmd(streams command.Streams, hubClient *hub.Client) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: tagName,
|
||||
Long: "Manage tags",
|
||||
Args: cli.NoArgs,
|
||||
RunE: command.ShowHelp(dockerCli.Err()),
|
||||
RunE: command.ShowHelp(streams.Err()),
|
||||
}
|
||||
cmd.AddCommand(
|
||||
newInspectCmd(ctx, dockerCli, tagName),
|
||||
newListCmd(ctx, dockerCli, tagName),
|
||||
newRmCmd(ctx, dockerCli, tagName),
|
||||
newInspectCmd(streams, hubClient, tagName),
|
||||
newListCmd(streams, hubClient, tagName),
|
||||
newRmCmd(streams, hubClient, tagName),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
|
|
|
@ -17,22 +17,23 @@
|
|||
package tag
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/docker/buildx/util/imagetools"
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
clitypes "github.com/docker/cli/cli/config/types"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/go-units"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/hub-cli-plugin/internal/hub"
|
||||
"github.com/docker/hub-cli-plugin/internal/metrics"
|
||||
)
|
||||
|
||||
|
@ -44,7 +45,7 @@ type inspectOptions struct {
|
|||
format string
|
||||
}
|
||||
|
||||
func newInspectCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobra.Command {
|
||||
func newInspectCmd(streams command.Streams, hubClient *hub.Client, parent string) *cobra.Command {
|
||||
var opts inspectOptions
|
||||
cmd := &cobra.Command{
|
||||
Use: inspectName + " [OPTIONS] REPOSITORY:TAG",
|
||||
|
@ -54,7 +55,7 @@ func newInspectCmd(ctx context.Context, dockerCli command.Cli, parent string) *c
|
|||
metrics.Send(parent, inspectName)
|
||||
},
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
return runInspect(ctx, dockerCli, opts, args[0])
|
||||
return runInspect(streams, hubClient, opts, args[0])
|
||||
},
|
||||
}
|
||||
cmd.Flags().StringVar(&opts.format, "format", "", `Print original manifest ("json")`)
|
||||
|
@ -62,18 +63,20 @@ func newInspectCmd(ctx context.Context, dockerCli command.Cli, parent string) *c
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runInspect(ctx context.Context, dockerCli command.Cli, opts inspectOptions, image string) error {
|
||||
func runInspect(streams command.Streams, hubClient *hub.Client, opts inspectOptions, image string) error {
|
||||
resolver := imagetools.New(imagetools.Opt{
|
||||
Auth: dockerCli.ConfigFile(),
|
||||
Auth: &authResolver{
|
||||
authConfig: convert(hubClient.AuthConfig),
|
||||
},
|
||||
})
|
||||
|
||||
raw, descriptor, err := resolver.Get(ctx, image)
|
||||
raw, descriptor, err := resolver.Get(hubClient.Ctx, image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if opts.format == "json" {
|
||||
fmt.Printf("%s", raw) // avoid newline to keep digest
|
||||
fmt.Fprintf(streams.Out(), "%s", raw) // avoid newline to keep digest
|
||||
return nil
|
||||
} else if opts.format != "" {
|
||||
return fmt.Errorf("unsupported format type: %q", opts.format)
|
||||
|
@ -83,15 +86,15 @@ func runInspect(ctx context.Context, dockerCli command.Cli, opts inspectOptions,
|
|||
// case images.MediaTypeDockerSchema2Manifest, specs.MediaTypeImageManifest:
|
||||
// TODO: handle distribution manifest and schema1
|
||||
case images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
|
||||
if err := imagetools.PrintManifestList(raw, descriptor, image, os.Stdout); err != nil {
|
||||
if err := imagetools.PrintManifestList(raw, descriptor, image, streams.Out()); err != nil {
|
||||
return err
|
||||
}
|
||||
case images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest:
|
||||
if err := printManifest(raw, descriptor, image, os.Stdout); err != nil {
|
||||
if err := printManifest(raw, descriptor, image, streams.Out()); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
fmt.Printf("%s\n", raw)
|
||||
fmt.Fprintf(streams.Out(), "%s\n", raw)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -146,3 +149,23 @@ func printManifest(raw []byte, descriptor ocispec.Descriptor, image string, out
|
|||
|
||||
return w.Flush()
|
||||
}
|
||||
|
||||
type authResolver struct {
|
||||
authConfig clitypes.AuthConfig
|
||||
}
|
||||
|
||||
func (a *authResolver) GetAuthConfig(registryHostname string) (clitypes.AuthConfig, error) {
|
||||
return a.authConfig, nil
|
||||
}
|
||||
|
||||
func convert(config types.AuthConfig) clitypes.AuthConfig {
|
||||
return clitypes.AuthConfig{
|
||||
Username: config.Username,
|
||||
Password: config.Password,
|
||||
Auth: config.Auth,
|
||||
Email: config.Email,
|
||||
ServerAddress: config.ServerAddress,
|
||||
IdentityToken: config.IdentityToken,
|
||||
RegistryToken: config.RegistryToken,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,10 +17,8 @@
|
|||
package tag
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
@ -28,8 +26,6 @@ import (
|
|||
"github.com/cli/cli/utils"
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
|
@ -120,7 +116,7 @@ type listOptions struct {
|
|||
sort string
|
||||
}
|
||||
|
||||
func newListCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobra.Command {
|
||||
func newListCmd(streams command.Streams, hubClient *hub.Client, parent string) *cobra.Command {
|
||||
var opts listOptions
|
||||
cmd := &cobra.Command{
|
||||
Use: lsName + " [OPTION] REPOSITORY",
|
||||
|
@ -130,7 +126,7 @@ func newListCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobr
|
|||
metrics.Send(parent, lsName)
|
||||
},
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
return runList(ctx, dockerCli, opts, args[0])
|
||||
return runList(streams, hubClient, opts, args[0])
|
||||
},
|
||||
}
|
||||
cmd.Flags().BoolVar(&opts.platforms, "platforms", false, "List all available platforms per tag")
|
||||
|
@ -141,31 +137,25 @@ func newListCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobr
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runList(ctx context.Context, dockerCli command.Cli, opts listOptions, repository string) error {
|
||||
func runList(streams command.Streams, hubClient *hub.Client, opts listOptions, repository string) error {
|
||||
ordering, err := mapOrdering(opts.sort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
authResolver := func(hub *registry.IndexInfo) types.AuthConfig {
|
||||
return command.ResolveAuthConfig(ctx, dockerCli, hub)
|
||||
}
|
||||
var clientOps []hub.ClientOp
|
||||
if opts.all {
|
||||
clientOps = append(clientOps, hub.WithAllElements())
|
||||
if err := hubClient.Apply(hub.WithAllElements()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
client, err := hub.NewClient(authResolver, clientOps...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := promptCallToAction(dockerCli.Out(), client); err != nil {
|
||||
fmt.Fprint(dockerCli.Err(), err)
|
||||
if err := promptCallToAction(streams.Err(), hubClient); err != nil {
|
||||
fmt.Fprint(streams.Err(), err)
|
||||
}
|
||||
|
||||
var reqOps []hub.RequestOp
|
||||
if ordering != "" {
|
||||
reqOps = append(reqOps, hub.WithSortingOrder(ordering))
|
||||
}
|
||||
tags, err := client.GetTags(repository, reqOps...)
|
||||
tags, err := hubClient.GetTags(repository, reqOps...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -174,7 +164,7 @@ func runList(ctx context.Context, dockerCli command.Cli, opts listOptions, repos
|
|||
defaultColumns = append(defaultColumns, platformColumn)
|
||||
}
|
||||
|
||||
return opts.Print(os.Stdout, tags, printTags)
|
||||
return opts.Print(streams.Out(), tags, printTags)
|
||||
}
|
||||
|
||||
func printTags(out io.Writer, values interface{}) error {
|
||||
|
|
|
@ -18,16 +18,12 @@ package tag
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/hub-cli-plugin/internal/hub"
|
||||
|
@ -42,7 +38,7 @@ type rmOptions struct {
|
|||
force bool
|
||||
}
|
||||
|
||||
func newRmCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobra.Command {
|
||||
func newRmCmd(streams command.Streams, hubClient *hub.Client, parent string) *cobra.Command {
|
||||
var opts rmOptions
|
||||
cmd := &cobra.Command{
|
||||
Use: rmName + " [OPTIONS] REPOSITORY:TAG",
|
||||
|
@ -52,7 +48,7 @@ func newRmCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobra.
|
|||
metrics.Send(parent, rmName)
|
||||
},
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
return runRm(ctx, dockerCli, opts, args[0])
|
||||
return runRm(streams, hubClient, opts, args[0])
|
||||
},
|
||||
}
|
||||
cmd.Flags().BoolVar(&opts.force, "force", false, "Force deletion of the tag")
|
||||
|
@ -60,7 +56,7 @@ func newRmCmd(ctx context.Context, dockerCli command.Cli, parent string) *cobra.
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runRm(ctx context.Context, dockerCli command.Cli, opts rmOptions, image string) error {
|
||||
func runRm(streams command.Streams, hubClient *hub.Client, opts rmOptions, image string) error {
|
||||
ref, err := reference.Parse(image)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -71,8 +67,8 @@ func runRm(ctx context.Context, dockerCli command.Cli, opts rmOptions, image str
|
|||
}
|
||||
|
||||
if !opts.force {
|
||||
fmt.Println("Please type the name of your repository to confirm deletion:", namedTaggedRef.Name())
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
fmt.Fprintln(streams.Out(), "Please type the name of your repository to confirm deletion:", namedTaggedRef.Name())
|
||||
reader := bufio.NewReader(streams.In())
|
||||
input, _ := reader.ReadString('\n')
|
||||
input = strings.ToLower(strings.TrimSpace(input))
|
||||
if input != namedTaggedRef.Name() {
|
||||
|
@ -80,16 +76,9 @@ func runRm(ctx context.Context, dockerCli command.Cli, opts rmOptions, image str
|
|||
}
|
||||
}
|
||||
|
||||
authResolver := func(hub *registry.IndexInfo) types.AuthConfig {
|
||||
return command.ResolveAuthConfig(ctx, dockerCli, hub)
|
||||
}
|
||||
client, err := hub.NewClient(authResolver)
|
||||
if err != nil {
|
||||
if err := hubClient.RemoveTag(namedTaggedRef.Name(), namedTaggedRef.Tag()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := client.RemoveTag(namedTaggedRef.Name(), namedTaggedRef.Tag()); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("Deleted", image)
|
||||
fmt.Fprintln(streams.Out(), "Deleted", image)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package hub
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
@ -39,6 +40,9 @@ const (
|
|||
|
||||
//Client sends authenticated calls to the Hub API
|
||||
type Client struct {
|
||||
AuthConfig types.AuthConfig
|
||||
Ctx context.Context
|
||||
|
||||
domain string
|
||||
token string
|
||||
fetchAllElements bool
|
||||
|
@ -58,22 +62,37 @@ type RequestOp func(r *http.Request) error
|
|||
func NewClient(authResolver AuthResolver, ops ...ClientOp) (*Client, error) {
|
||||
hubInstance := getInstance()
|
||||
hubAuthConfig := authResolver(hubInstance.RegistryInfo)
|
||||
token, err := login(hubInstance.APIHubBaseURL, hubAuthConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// Check if the user is logged in
|
||||
if hubAuthConfig.Username == "" {
|
||||
return nil, &authenticationError{}
|
||||
}
|
||||
client := &Client{
|
||||
domain: hubInstance.APIHubBaseURL,
|
||||
token: token,
|
||||
AuthConfig: hubAuthConfig,
|
||||
domain: hubInstance.APIHubBaseURL,
|
||||
}
|
||||
for _, op := range ops {
|
||||
if err := op(client); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
token, err := client.login(hubInstance.APIHubBaseURL, hubAuthConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client.token = token
|
||||
return client, nil
|
||||
}
|
||||
|
||||
//Apply changes client behavior using ClientOp
|
||||
func (c *Client) Apply(ops ...ClientOp) error {
|
||||
for _, op := range ops {
|
||||
if err := op(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//WithAllElements makes the client fetch all the elements it can find, enabling pagination.
|
||||
func WithAllElements() ClientOp {
|
||||
return func(c *Client) error {
|
||||
|
@ -82,6 +101,14 @@ func WithAllElements() ClientOp {
|
|||
}
|
||||
}
|
||||
|
||||
//WithContext set the client context
|
||||
func WithContext(ctx context.Context) ClientOp {
|
||||
return func(c *Client) error {
|
||||
c.Ctx = ctx
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
//WithHubToken sets the bearer token to the request
|
||||
func WithHubToken(token string) RequestOp {
|
||||
return func(req *http.Request) error {
|
||||
|
@ -103,7 +130,7 @@ func WithSortingOrder(order string) RequestOp {
|
|||
}
|
||||
}
|
||||
|
||||
func login(hubBaseURL string, hubAuthConfig types.AuthConfig) (string, error) {
|
||||
func (c *Client) login(hubBaseURL string, hubAuthConfig types.AuthConfig) (string, error) {
|
||||
data, err := json.Marshal(hubAuthConfig)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -116,7 +143,7 @@ func login(hubBaseURL string, hubAuthConfig types.AuthConfig) (string, error) {
|
|||
return "", err
|
||||
}
|
||||
req.Header["Content-Type"] = []string{"application/json"}
|
||||
buf, err := doRequest(req)
|
||||
buf, err := c.doRequest(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -130,7 +157,7 @@ func login(hubBaseURL string, hubAuthConfig types.AuthConfig) (string, error) {
|
|||
return creds.Token, nil
|
||||
}
|
||||
|
||||
func doRequest(req *http.Request, reqOps ...RequestOp) ([]byte, error) {
|
||||
func (c *Client) doRequest(req *http.Request, reqOps ...RequestOp) ([]byte, error) {
|
||||
req.Header["Accept"] = []string{"application/json"}
|
||||
req.Header["User-Agent"] = []string{fmt.Sprintf("hub-tool/%s", internal.Version)}
|
||||
for _, op := range reqOps {
|
||||
|
@ -138,6 +165,9 @@ func doRequest(req *http.Request, reqOps ...RequestOp) ([]byte, error) {
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
if c.Ctx != nil {
|
||||
req = req.WithContext(c.Ctx)
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -34,6 +34,7 @@ func TestDoRequestAddsCustomUserAgent(t *testing.T) {
|
|||
defer server.Close()
|
||||
req, err := http.NewRequest("GET", server.URL, nil)
|
||||
assert.NilError(t, err)
|
||||
_, err = doRequest(req)
|
||||
client := Client{}
|
||||
_, err = client.doRequest(req)
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
Copyright 2020 Docker Hub Tool authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package hub
|
||||
|
||||
import "fmt"
|
||||
|
||||
type authenticationError struct {
|
||||
}
|
||||
|
||||
func (a authenticationError) Error() string {
|
||||
return "authentication error"
|
||||
}
|
||||
|
||||
// IsAuthenticationError check if the error type is an authentication error
|
||||
func IsAuthenticationError(err error) bool {
|
||||
_, ok := err.(*authenticationError)
|
||||
return ok
|
||||
}
|
||||
|
||||
type invalidTokenError struct {
|
||||
token string
|
||||
}
|
||||
|
||||
func (i invalidTokenError) Error() string {
|
||||
return fmt.Sprintf("invalid authentication token %q", i.token)
|
||||
}
|
||||
|
||||
// IsInvalidTokenError check if the error type is an invalid token error
|
||||
func IsInvalidTokenError(err error) bool {
|
||||
_, ok := err.(*invalidTokenError)
|
||||
return ok
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
Copyright 2020 Docker Hub Tool authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package hub
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func TestIsAuthenticationError(t *testing.T) {
|
||||
assert.Assert(t, IsAuthenticationError(&authenticationError{}))
|
||||
assert.Assert(t, !IsAuthenticationError(errors.New("")))
|
||||
}
|
||||
|
||||
func TestIsInvalidTokenError(t *testing.T) {
|
||||
assert.Assert(t, IsInvalidTokenError(&invalidTokenError{}))
|
||||
assert.Assert(t, !IsInvalidTokenError(errors.New("")))
|
||||
}
|
|
@ -72,7 +72,7 @@ func (c *Client) GetMembersPerTeam(organization, team string) ([]Member, error)
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
response, err := doRequest(req, WithHubToken(c.token))
|
||||
response, err := c.doRequest(req, WithHubToken(c.token))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ func (c *Client) getMembersPage(url string) ([]Member, string, error) {
|
|||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
response, err := doRequest(req, WithHubToken(c.token))
|
||||
response, err := c.doRequest(req, WithHubToken(c.token))
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ func (c *Client) getOrganizationsPage(url string) ([]Organization, string, error
|
|||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
response, err := doRequest(req, WithHubToken(c.token))
|
||||
response, err := c.doRequest(req, WithHubToken(c.token))
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ func (c *Client) GetHubPlan(accountID string) (*Plan, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
response, err := doRequest(req, WithHubToken(c.token))
|
||||
response, err := c.doRequest(req, WithHubToken(c.token))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ func (c *Client) RemoveRepository(repository string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = doRequest(req, WithHubToken(c.token))
|
||||
_, err = c.doRequest(req, WithHubToken(c.token))
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ func (c *Client) getRepositoriesPage(url, account string) ([]Repository, string,
|
|||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
response, err := doRequest(req, WithHubToken(c.token))
|
||||
response, err := c.doRequest(req, WithHubToken(c.token))
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ func (c *Client) RemoveTag(repository, tag string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = doRequest(req, WithHubToken(c.token))
|
||||
_, err = c.doRequest(req, WithHubToken(c.token))
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ func (c *Client) getTagsPage(url, repository string, reqOps ...RequestOp) ([]Tag
|
|||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
response, err := doRequest(req, append(reqOps, WithHubToken(c.token))...)
|
||||
response, err := c.doRequest(req, append(reqOps, WithHubToken(c.token))...)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ func (c *Client) getTeamsPage(url, organization string) ([]Team, string, error)
|
|||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
response, err := doRequest(req, WithHubToken(c.token))
|
||||
response, err := c.doRequest(req, WithHubToken(c.token))
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ func (c *Client) GetUserInfo() (*User, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
response, err := doRequest(req, WithHubToken(c.token))
|
||||
response, err := c.doRequest(req, WithHubToken(c.token))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче