Skip to content

Commit

Permalink
cli: add config and images command
Browse files Browse the repository at this point in the history
Extends the existing zot CLI to add commands for listing all images and
their details on a zot server.
Listing all images introduces the need for configurations.

Each configuration has a name and URL at the least. Check 'zot config
-h' for more details.

The user can specify the URL of zot server explicitly while running the
command or configure a URL and pass it directly.

Adding a configuration:
zot config add aci-zot <zot-url>

Run 'zot config --help' for more.

Listing all images:
zot images --url <zot-url>

Pass a config instead of the url:
zot images <config-name>

Filter the list of images by image name:
zot images <config-name> --name <image-name>

Run 'zot images --help' for all details

- Stores configurations in '$HOME/.zot' file

Add CLI README
  • Loading branch information
tsnaik committed Jul 2, 2020
1 parent 4a1519b commit ad684ac
Show file tree
Hide file tree
Showing 17 changed files with 2,169 additions and 84 deletions.
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Uses [OCI storage layout](https://github.com/opencontainers/image-spec/blob/master/image-layout.md) for storage layout
* Supports [helm charts](https://helm.sh/docs/topics/registries/)
* Currently suitable for on-prem deployments (e.g. colocated with Kubernetes)
* [Command-line client support](#cli)
* TLS support
* Authentication via:
* TLS mutual authentication
Expand Down Expand Up @@ -97,6 +98,44 @@ podman run --rm -p 8080:8080 \
zot:latest
```

# CLI

The same zot binary can be used for interacting with any zot server instances.

## Adding a zot server URL

To add a zot server URL with an alias "remote-zot":

```console
$ zot config add remote-zot https://server-example:8080
```

List all configured URLs with their aliases:
```console
$ zot config -l
remote-zot https://server-example:8080
local http://localhost:8080
```

## Fetching images
You can fetch all images from a server by using its alias specified [in this step](#adding-a-zot-server-url):

```console
$ zot images remote-zot
IMAGE NAME TAG DIGEST SIZE
postgres 9.6.18-alpine ef27f3e1 14.4MB
postgres 9.5-alpine 264450a7 14.4MB
busybox latest 414aeb86 707.8KB
```

Or filter the list by an image name:

```console
$ zot images remote-zot -n busybox
IMAGE NAME TAG DIGEST SIZE
busybox latest 414aeb86 707.8KB
```

# Ecosystem

Since we couldn't find clients or client libraries that are stictly compliant to
Expand Down
57 changes: 53 additions & 4 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -461,8 +461,8 @@ go_repository(
go_repository(
name = "com_github_kr_pty",
importpath = "github.com/kr/pty",
sum = "h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI=",
version = "v1.1.8",
sum = "h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=",
version = "v1.1.1",
)

go_repository(
Expand Down Expand Up @@ -881,8 +881,8 @@ go_repository(
go_repository(
name = "org_golang_google_appengine",
importpath = "google.golang.org/appengine",
sum = "h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs=",
version = "v1.1.0",
sum = "h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=",
version = "v1.4.0",
)

go_repository(
Expand Down Expand Up @@ -1521,3 +1521,52 @@ go_repository(
sum = "h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=",
version = "v1.24.0",
)

go_repository(
name = "com_github_briandowns_spinner",
importpath = "github.com/briandowns/spinner",
sum = "h1:OixPqDEcX3juo5AjQZAnFPbeUA0jvkp2qzB5gOZJ/L0=",
version = "v1.11.1",
)

go_repository(
name = "com_github_coreos_go_etcd",
importpath = "github.com/coreos/go-etcd",
sum = "h1:bXhRBIXoTm9BYHS3gE0TtQuyNZyeEMux2sDi4oo5YOo=",
version = "v2.0.0+incompatible",
)

go_repository(
name = "com_github_dustin_go_humanize",
importpath = "github.com/dustin/go-humanize",
sum = "h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=",
version = "v1.0.0",
)

go_repository(
name = "com_github_go_resty_resty_v2",
importpath = "github.com/go-resty/resty/v2",
sum = "h1:JOOeAvjSlapTT92p8xiS19Zxev1neGikoHsXJeOq8So=",
version = "v2.3.0",
)

go_repository(
name = "com_github_mattn_go_runewidth",
importpath = "github.com/mattn/go-runewidth",
sum = "h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=",
version = "v0.0.7",
)

go_repository(
name = "com_github_olekukonko_tablewriter",
importpath = "github.com/olekukonko/tablewriter",
sum = "h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=",
version = "v0.0.4",
)

go_repository(
name = "org_golang_x_exp",
importpath = "golang.org/x/exp",
sum = "h1:c2HOrn5iMezYjSlGPncknSEr/8x5LELb/ilJbXi9DEA=",
version = "v0.0.0-20190121172915-509febef88a4",
)
10 changes: 9 additions & 1 deletion cmd/zot/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@ package main

import (
"os"
"path"

"github.com/anuvu/zot/pkg/cli"
)

func main() {
if err := cli.NewRootCmd().Execute(); err != nil {
home, err := os.UserHomeDir()
if err != nil {
panic(err)
}

configPath := path.Join(home + "/.zot")

if err := cli.NewRootCmd(configPath).Execute(); err != nil {
os.Exit(1)
}
}
4 changes: 3 additions & 1 deletion cmd/zot/main_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main_test

import (
"io/ioutil"
"testing"

"github.com/anuvu/zot/pkg/api"
Expand All @@ -14,7 +15,8 @@ func TestIntegration(t *testing.T) {
c := api.NewController(config)
So(c, ShouldNotBeNil)

cl := cli.NewRootCmd()
tempFile, _ := ioutil.TempFile("", "tmp-")
cl := cli.NewRootCmd(tempFile.Name())
So(cl, ShouldNotBeNil)

So(cl.Execute(), ShouldBeNil)
Expand Down
54 changes: 31 additions & 23 deletions errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,35 @@ package errors
import "errors"

var (
ErrBadConfig = errors.New("config: invalid config")
ErrRepoNotFound = errors.New("repository: not found")
ErrRepoIsNotDir = errors.New("repository: not a directory")
ErrRepoBadVersion = errors.New("repository: unsupported layout version")
ErrManifestNotFound = errors.New("manifest: not found")
ErrBadManifest = errors.New("manifest: invalid contents")
ErrUploadNotFound = errors.New("uploads: not found")
ErrBadUploadRange = errors.New("uploads: bad range")
ErrBlobNotFound = errors.New("blob: not found")
ErrBadBlob = errors.New("blob: bad blob")
ErrBadBlobDigest = errors.New("blob: bad blob digest")
ErrUnknownCode = errors.New("error: unknown error code")
ErrBadCACert = errors.New("tls: invalid ca cert")
ErrBadUser = errors.New("ldap: non-existent user")
ErrEntriesExceeded = errors.New("ldap: too many entries returned")
ErrLDAPEmptyPassphrase = errors.New("ldap: empty passphrase")
ErrLDAPBadConn = errors.New("ldap: bad connection")
ErrLDAPConfig = errors.New("config: invalid LDAP configuration")
ErrCacheRootBucket = errors.New("cache: unable to create/update root bucket")
ErrCacheNoBucket = errors.New("cache: unable to find bucket")
ErrCacheMiss = errors.New("cache: miss")
ErrRequireCred = errors.New("ldap: bind credentials required")
ErrInvalidCred = errors.New("ldap: invalid credentials")
ErrBadConfig = errors.New("config: invalid config")
ErrRepoNotFound = errors.New("repository: not found")
ErrRepoIsNotDir = errors.New("repository: not a directory")
ErrRepoBadVersion = errors.New("repository: unsupported layout version")
ErrManifestNotFound = errors.New("manifest: not found")
ErrBadManifest = errors.New("manifest: invalid contents")
ErrUploadNotFound = errors.New("uploads: not found")
ErrBadUploadRange = errors.New("uploads: bad range")
ErrBlobNotFound = errors.New("blob: not found")
ErrBadBlob = errors.New("blob: bad blob")
ErrBadBlobDigest = errors.New("blob: bad blob digest")
ErrUnknownCode = errors.New("error: unknown error code")
ErrBadCACert = errors.New("tls: invalid ca cert")
ErrBadUser = errors.New("ldap: non-existent user")
ErrEntriesExceeded = errors.New("ldap: too many entries returned")
ErrLDAPEmptyPassphrase = errors.New("ldap: empty passphrase")
ErrLDAPBadConn = errors.New("ldap: bad connection")
ErrLDAPConfig = errors.New("config: invalid LDAP configuration")
ErrCacheRootBucket = errors.New("cache: unable to create/update root bucket")
ErrCacheNoBucket = errors.New("cache: unable to find bucket")
ErrCacheMiss = errors.New("cache: miss")
ErrRequireCred = errors.New("ldap: bind credentials required")
ErrInvalidCred = errors.New("ldap: invalid credentials")
ErrInvalidArgs = errors.New("cli: Invalid Arguments")
ErrInvalidFlagsCombination = errors.New("cli: Invalid combination of flags. Add --help flag")
ErrInvalidURL = errors.New("cli: invalid URL format")
ErrUnauthorizedAccess = errors.New("cli: unauthorized access. check credentials")
ErrCannotResetConfigKey = errors.New("cli: cannot reset given config key")
ErrConfigNotFound = errors.New("cli: config with the given name does not exist")
ErrNoURLProvided = errors.New("cli: no URL provided in argument or via config. see 'zot config -h'")
ErrIllegalConfigKey = errors.New("cli: given config key is not allowed")
)
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ go 1.14

require (
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
github.com/briandowns/spinner v1.11.1
github.com/chartmuseum/auth v0.4.0
github.com/dustin/go-humanize v1.0.0
github.com/getlantern/deepcopy v0.0.0-20160317154340-7f45deb8130a
github.com/go-chi/chi v4.0.2+incompatible // indirect
github.com/go-ldap/ldap/v3 v3.1.3
Expand All @@ -15,6 +17,7 @@ require (
github.com/mitchellh/mapstructure v1.1.2
github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484 // indirect
github.com/nmcclain/ldap v0.0.0-20191021200707-3b3b69a7e9e3
github.com/olekukonko/tablewriter v0.0.4
github.com/opencontainers/distribution-spec v1.0.0-rc0
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.0.1
Expand All @@ -29,4 +32,5 @@ require (
go.etcd.io/bbolt v1.3.4
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9
gopkg.in/resty.v1 v1.12.0
gopkg.in/yaml.v2 v2.2.4
)
Loading

0 comments on commit ad684ac

Please sign in to comment.