From 9f96c4496572e5638995e53fc4ccd3858aa365e5 Mon Sep 17 00:00:00 2001 From: Miguel Mota Date: Fri, 15 Feb 2019 23:37:57 -0800 Subject: [PATCH] clean up --- cmd/ipdr/main.go | 6 +- docker/client.go | 251 +++----------------------------------- docker/client_test.go | 103 +--------------- docker/util.go | 10 +- docker/util_test.go | 30 ----- ipfs/ipfs.go | 20 +-- netutil/netutil.go | 5 +- registry/registry.go | 32 +++-- registry/registry_test.go | 2 +- regutil/regutil.go | 4 +- regutil/regutil_test.go | 37 +++++- server/server.go | 11 +- 12 files changed, 106 insertions(+), 405 deletions(-) diff --git a/cmd/ipdr/main.go b/cmd/ipdr/main.go index 4d85728..b253ef8 100644 --- a/cmd/ipdr/main.go +++ b/cmd/ipdr/main.go @@ -13,12 +13,10 @@ import ( var green = color.New(color.FgGreen) var ( - // ErrImageIDRequired ... + // ErrImageIDRequired is error for when image ID is required ErrImageIDRequired = errors.New("image hash or name is required") - // ErrOnlyOneArgumentRequired ... + // ErrOnlyOneArgumentRequired is error for when one argument only is required ErrOnlyOneArgumentRequired = errors.New("only one argument is required") - // ErrSubCommandRequired ... - ErrSubCommandRequired = errors.New("sub command is required") ) func main() { diff --git a/docker/client.go b/docker/client.go index f55ab48..81bd713 100644 --- a/docker/client.go +++ b/docker/client.go @@ -1,84 +1,30 @@ package docker import ( - "bufio" "context" "fmt" "io" "io/ioutil" - "net/http" "os" - "os/exec" - "path/filepath" - "strings" - container "github.com/docker/docker/api/types/container" log "github.com/sirupsen/logrus" types "github.com/docker/docker/api/types" filters "github.com/docker/docker/api/types/filters" - mount "github.com/docker/docker/api/types/mount" client "github.com/docker/docker/client" - nat "github.com/docker/go-connections/nat" - tlsconfig "github.com/docker/go-connections/tlsconfig" ) -// Client ... +// Client is client structure type Client struct { client *client.Client } -// NewClient ... +// NewClient creates a new client instance func NewClient() *Client { return newEnvClient() } -// newClient ... -func newClient() *Client { - httpclient := &http.Client{} - - if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" { - options := tlsconfig.Options{ - CAFile: filepath.Join(dockerCertPath, "ca.pem"), - CertFile: filepath.Join(dockerCertPath, "cert.pem"), - KeyFile: filepath.Join(dockerCertPath, "key.pem"), - InsecureSkipVerify: os.Getenv("DOCKER_TLS_VERIFY") == "", - } - tlsc, err := tlsconfig.Client(options) - if err != nil { - log.Fatalf("[docker] %s", err) - } - - httpclient.Transport = &http.Transport{ - TLSClientConfig: tlsc, - } - } - - host := os.Getenv("DOCKER_HOST") - version := os.Getenv("DOCKER_VERSION") - - if host == "" { - log.Fatal("[docker] DOCKER_HOST is required") - } - - if version == "" { - version = dockerVersionFromCLI() - if version == "" { - log.Fatal("[docker] DOCKER_VERSION is required") - } - } - - cl, err := client.NewClient(host, version, httpclient, nil) - if err != nil { - log.Fatalf("[docker] %s", err) - } - - return &Client{ - client: cl, - } -} - -// newEnvClient ... +// newEnvClient returns a new client instance based on environment variables func newEnvClient() *Client { cl, err := client.NewEnvClient() if err != nil { @@ -90,14 +36,14 @@ func newEnvClient() *Client { } } -// ImageSummary .... +// ImageSummary is structure for image summary type ImageSummary struct { ID string Tags []string Size int64 } -// ListImages ... +// ListImages return list of docker images func (s *Client) ListImages() ([]*ImageSummary, error) { images, err := s.client.ImageList(context.Background(), types.ImageListOptions{ All: true, @@ -118,7 +64,7 @@ func (s *Client) ListImages() ([]*ImageSummary, error) { return summaries, nil } -// HasImage ... +// HasImage returns true if image ID is available locally func (s *Client) HasImage(imageID string) (bool, error) { args := filters.NewArgs() args.Add("reference", StripImageTagHost(imageID)) @@ -137,7 +83,7 @@ func (s *Client) HasImage(imageID string) (bool, error) { return false, nil } -// PullImage ... +// PullImage pulls a docker image func (s *Client) PullImage(imageID string) error { reader, err := s.client.ImagePull(context.Background(), imageID, types.ImagePullOptions{}) if err != nil { @@ -148,7 +94,7 @@ func (s *Client) PullImage(imageID string) error { return nil } -// PushImage ... +// PushImage pushes a docker image func (s *Client) PushImage(imageID string) error { reader, err := s.client.ImagePush(context.Background(), imageID, types.ImagePushOptions{ // NOTE: if no auth, then any value is required @@ -161,12 +107,12 @@ func (s *Client) PushImage(imageID string) error { return nil } -// TagImage ... +// TagImage tags an image func (s *Client) TagImage(imageID, tag string) error { return s.client.ImageTag(context.Background(), imageID, tag) } -// RemoveImage ... +// RemoveImage remove an image from the local registry func (s *Client) RemoveImage(imageID string) error { _, err := s.client.ImageRemove(context.Background(), imageID, types.ImageRemoveOptions{ Force: true, @@ -176,7 +122,7 @@ func (s *Client) RemoveImage(imageID string) error { return err } -// RemoveAllImages ... +// RemoveAllImages removes all images from the local registry func (s *Client) RemoveAllImages() error { images, err := s.ListImages() if err != nil { @@ -204,171 +150,26 @@ func (s *Client) RemoveAllImages() error { return nil } -// CreateContainerConfig ... -type CreateContainerConfig struct { - // container:host - Volumes map[string]string - Ports map[string]string -} - -// CreateContainer ... -func (s *Client) CreateContainer(imageID string, cmd []string, config *CreateContainerConfig) (string, error) { - if config == nil { - config = &CreateContainerConfig{} - } - - dockerConfig := &container.Config{ - Image: imageID, - Cmd: cmd, - Tty: false, - Volumes: map[string]struct{}{}, - ExposedPorts: map[nat.Port]struct{}{}, - } - - hostConfig := &container.HostConfig{ - Binds: nil, - PortBindings: map[nat.Port][]nat.PortBinding{}, - AutoRemove: true, - IpcMode: "", - Privileged: false, - Mounts: []mount.Mount{}, - } - - if len(config.Volumes) > 0 { - for k, v := range config.Volumes { - dockerConfig.Volumes[k] = struct{}{} - hostConfig.Mounts = append(hostConfig.Mounts, mount.Mount{ - Type: "bind", - Source: v, - Target: k, - ReadOnly: false, - }) - } - } - - if len(config.Ports) > 0 { - for k, v := range config.Ports { - t, err := nat.NewPort("tcp", k) - if err != nil { - return "", err - } - dockerConfig.ExposedPorts[t] = struct{}{} - hostConfig.PortBindings[t] = []nat.PortBinding{ - { - HostIP: "0.0.0.0", - HostPort: v, - }, - } - } - } - - resp, err := s.client.ContainerCreate(context.Background(), dockerConfig, hostConfig, nil, "") - if err != nil { - return "", err - } - - log.Printf("[docker] container %s is ready", resp.ID) - - return resp.ID, nil -} - -// StartContainer ... -func (s *Client) StartContainer(containerID string) error { - err := s.client.ContainerStart(context.TODO(), containerID, types.ContainerStartOptions{}) - - if err != nil { - log.Printf("[docker] error starting container %s; %v", containerID, err) - return err - } - - reader, err := s.client.ContainerLogs(context.TODO(), containerID, types.ContainerLogsOptions{ - ShowStdout: true, - ShowStderr: true, - Follow: true, - }) - - go func() { - log.Println("[docker] logging to stdout..") - scanner := bufio.NewScanner(reader) - for scanner.Scan() { - line := scanner.Text() - log.Printf("[docker] [container %s] [log] %s\n", ShortContainerID(containerID), line) - } - }() - - if err != nil { - log.Printf("[docker] error reading container logs for %s; %v", containerID, err) - return err - } - - log.Printf("[docker] running container %s", containerID) - return nil -} - -// StopContainer ... -func (s *Client) StopContainer(containerID string) error { - log.Printf("[docker] stopping container %s", containerID) - err := s.client.ContainerStop(context.Background(), containerID, nil) - if err != nil { - return err - } - - log.Println("[docker] container stopped") - return nil -} - -// InspectContainer ... -func (s *Client) InspectContainer(containerID string) (types.ContainerJSON, error) { - info, err := s.client.ContainerInspect(context.Background(), containerID) - if err != nil { - return types.ContainerJSON{}, err - } - - return info, nil -} - -// ContainerExec ... -func (s *Client) ContainerExec(containerID string, cmd []string) (io.Reader, error) { - id, err := s.client.ContainerExecCreate(context.Background(), containerID, types.ExecConfig{ - AttachStdout: true, - Cmd: cmd, - }) - - log.Printf("[docker] exec ID %s", id.ID) - if err != nil { - return nil, err - } - - resp, err := s.client.ContainerExecAttach(context.Background(), id.ID, types.ExecConfig{}) - if err != nil { - return nil, err - } - - return resp.Reader, nil -} - -// ReadImage ... +// ReadImage reads the contents of an image into an IO reader func (s *Client) ReadImage(imageID string) (io.Reader, error) { return s.client.ImageSave(context.Background(), []string{imageID}) } -// LoadImage ... +// LoadImage loads an image from an IO reader func (s *Client) LoadImage(input io.Reader) error { output, err := s.client.ImageLoad(context.Background(), input, false) if err != nil { return err } - //io.Copy(os.Stdout, output) - fmt.Println(output) body, err := ioutil.ReadAll(output.Body) fmt.Println(string(body)) return err } -// LoadImageByFilepath ... -func (s *Client) LoadImageByFilepath(filepath string) error { +// LoadImageByFilePath loads an image from a tarball +func (s *Client) LoadImageByFilePath(filepath string) error { input, err := os.Open(filepath) if err != nil { log.Printf("[docker] load image by filepath error; %v", err) @@ -377,7 +178,7 @@ func (s *Client) LoadImageByFilepath(filepath string) error { return s.LoadImage(input) } -// SaveImageTar ... +// SaveImageTar saves an image into a tarball func (s *Client) SaveImageTar(imageID string, dest string) error { reader, err := s.ReadImage(imageID) @@ -390,23 +191,3 @@ func (s *Client) SaveImageTar(imageID string, dest string) error { io.Copy(fo, reader) return nil } - -func dockerVersionFromCLI() string { - cmd := `docker version --format="{{.Client.APIVersion}}"` - out, err := exec.Command("sh", "-c", cmd).Output() - if err != nil { - return "" - } - - return strings.TrimSpace(string(out)) -} - -// CommitContainer ... -func (s *Client) CommitContainer(containerID string) (string, error) { - resp, err := s.client.ContainerCommit(context.Background(), containerID, types.ContainerCommitOptions{}) - if err != nil { - return "", err - } - - return resp.ID, nil -} diff --git a/docker/client_test.go b/docker/client_test.go index e10f1dc..c5836dd 100644 --- a/docker/client_test.go +++ b/docker/client_test.go @@ -103,9 +103,9 @@ func TestLoadImage(t *testing.T) { } } -func TestLoadImageByFilepath(t *testing.T) { +func TestLoadImageByFilePath(t *testing.T) { client := NewClient() - err := client.LoadImageByFilepath(testImageTar) + err := client.LoadImageByFilePath(testImageTar) if err != nil { t.Error(err) } @@ -175,102 +175,3 @@ func TestRemoveAllImages(t *testing.T) { t.Error("expected number of images to be 0") } } - -func TestCreateContainer(t *testing.T) { - client := NewClient() - err := client.PullImage(testImage) - if err != nil { - t.Error(err) - } - containerID, err := client.CreateContainer(testImage, []string{}, nil) - if err != nil { - t.Error(err) - } - - if containerID == "" { - t.Error("expected container ID") - } -} - -func TestStopContainer(t *testing.T) { - client := NewClient() - err := client.PullImage(testImage) - if err != nil { - t.Error(err) - } - containerID, err := client.CreateContainer(testImage, []string{}, nil) - if err != nil { - t.Error(err) - } - err = client.StopContainer(containerID) - if err != nil { - t.Error(err) - } - - err = client.StopContainer(containerID) - if err != nil { - t.Error(err) - } -} - -func TestInspectContainer(t *testing.T) { - client := NewClient() - err := client.PullImage(testImage) - if err != nil { - t.Error(err) - } - containerID, err := client.CreateContainer(testImage, []string{}, nil) - if err != nil { - t.Error(err) - } - err = client.StopContainer(containerID) - if err != nil { - t.Error(err) - } - info, err := client.InspectContainer(containerID) - if err != nil { - t.Error(err) - } - - if info.ID != containerID { - t.Error("expected id to match") - } - - err = client.StopContainer(containerID) - if err != nil { - t.Error(err) - } -} - -func TestCommitContainer(t *testing.T) { - client := NewClient() - err := client.PullImage(testImage) - if err != nil { - t.Error(err) - } - containerID, err := client.CreateContainer(testImage, []string{}, nil) - if err != nil { - t.Error(err) - } - - commitedImageID, err := client.CommitContainer(containerID) - if err != nil { - t.Error(err) - } - - if commitedImageID == "" { - t.Error("expected commited image ID") - } - - err = client.StopContainer(containerID) - if err != nil { - t.Error(err) - } -} - -func TestDockerVersionFromCLI(t *testing.T) { - version := dockerVersionFromCLI() - if version == "" { - t.Error("expected version to not be empty") - } -} diff --git a/docker/util.go b/docker/util.go index 48136e5..6362983 100644 --- a/docker/util.go +++ b/docker/util.go @@ -2,19 +2,13 @@ package docker import "regexp" -// ShortImageID ... +// ShortImageID returns the short version of an image ID func ShortImageID(imageID string) string { re := regexp.MustCompile(`(sha256:)?([0-9a-zA-Z]{12}).*`) return re.ReplaceAllString(imageID, `$2`) } -// ShortContainerID ... -func ShortContainerID(containerID string) string { - re := regexp.MustCompile(`([0-9a-zA-Z]{12}).*`) - return re.ReplaceAllString(containerID, `$1`) -} - -// TestStripImageTagHost ... +// TestStripImageTagHost strips the host from an image tag func StripImageTagHost(imageTag string) string { re := regexp.MustCompile(`(.*\..*?\/)?(.*)`) matches := re.FindStringSubmatch(imageTag) diff --git a/docker/util_test.go b/docker/util_test.go index aa7cd82..9375eea 100644 --- a/docker/util_test.go +++ b/docker/util_test.go @@ -39,36 +39,6 @@ func TestShortImageID(t *testing.T) { } } -func TestShortContainerID(t *testing.T) { - tests := []struct { - in string - out string - }{ - { - "9d4db8b8dc0fe4de396843d0257c64afbf7186b78418ac6a98539ad4a85bed42", - "9d4db8b8dc0f", - }, - { - "9d4db8b8dc0f", - "9d4db8b8dc0f", - }, - { - "9d4", - "9d4", - }, - } - - for i, tt := range tests { - t.Run(fmt.Sprintf("%v", i), func(t *testing.T) { - shortid := ShortContainerID(tt.in) - - if shortid != tt.out { - t.Errorf("want %v; got %v", tt.out, shortid) - } - }) - } -} - func TestStripImageTagHost(t *testing.T) { for i, tt := range []struct { in string diff --git a/ipfs/ipfs.go b/ipfs/ipfs.go index bac00d5..b1197ae 100644 --- a/ipfs/ipfs.go +++ b/ipfs/ipfs.go @@ -13,14 +13,14 @@ import ( log "github.com/sirupsen/logrus" ) -// Client ... +// Client is the client structure type Client struct { client *api.Shell isRemote bool host string } -// NewClient ... +// NewClient returns a new IPFS client instance func NewClient() *Client { err := RunDaemon() if err != nil { @@ -38,7 +38,7 @@ func NewClient() *Client { } } -// NewRemoteClient ... +// NewRemoteClient returns a new IPFS shell client func NewRemoteClient(host string) *Client { client := api.NewShell(host) return &Client{ @@ -48,17 +48,17 @@ func NewRemoteClient(host string) *Client { } } -// Get ... +// Get fetches the contents and outputs into a directory func (client *Client) Get(hash, outdir string) error { return client.client.Get(hash, outdir) } -// AddDir ... +// AddDir adds a directory to IPFS func (client *Client) AddDir(dir string) (string, error) { return client.client.AddDir(dir) } -// Refs ... +// Refs returns the refs of an IPFS hash func (client *Client) Refs(hash string, recursive bool) (<-chan string, error) { if client.isRemote { return client.remoteRefs(hash, recursive) @@ -67,6 +67,7 @@ func (client *Client) Refs(hash string, recursive bool) (<-chan string, error) { return client.client.Refs(hash, recursive) } +// removeRefs returns refs using the IPFS API func (client *Client) remoteRefs(hash string, recursive bool) (<-chan string, error) { url := fmt.Sprintf("http://%s/api/v0/refs?arg=%s&recursive=%v", client.host, hash, recursive) @@ -96,7 +97,7 @@ func (client *Client) remoteRefs(hash string, recursive bool) (<-chan string, er return out, nil } -// RunDaemon ... +// RunDaemon rusn the IPFS daemon func RunDaemon() error { var err error ready := make(chan bool) @@ -113,8 +114,7 @@ func RunDaemon() error { return nil } -// hacky way to spawn daemon -// TODO: improve +// spawnIpfsDaemon spawns the IPFS daemon by issuing shell commands func spawnIpfsDaemon(ready chan bool) error { out, err := exec.Command("pgrep", "ipfs").Output() if err != nil || strings.TrimSpace(string(out)) == "" { @@ -149,6 +149,7 @@ func GatewayURL() (string, error) { return fmt.Sprintf("http://127.0.0.1:%s", port), nil } +// getIpfsAPIURL returns the IPFS API base URL func getIpfsAPIURL() (string, error) { out, err := exec.Command("ipfs", "config", "Addresses.API").Output() if err != nil { @@ -158,6 +159,7 @@ func getIpfsAPIURL() (string, error) { return strings.TrimSpace(string(out)), nil } +// getIpfsGatewayPort return the IPFS gateway port number func getIpfsGatewayPort() (string, error) { out, err := exec.Command("ipfs", "config", "Addresses.Gateway").Output() if err != nil { diff --git a/netutil/netutil.go b/netutil/netutil.go index 730be16..ace2fbe 100644 --- a/netutil/netutil.go +++ b/netutil/netutil.go @@ -9,9 +9,9 @@ import ( func GetFreePort() (int, error) { ip, err := LocalIP() if err != nil { - return 0, err + return 0, err } - addr, err := net.ResolveTCPAddr("tcp", ip.String() + ":0") + addr, err := net.ResolveTCPAddr("tcp", ip.String()+":0") if err != nil { return 0, err } @@ -54,6 +54,7 @@ func LocalIP() (net.IP, error) { return nil, errors.New("no IP") } +// isPrivateIP return true if IP address is from a private range func isPrivateIP(ip net.IP) bool { var privateIPBlocks []*net.IPNet for _, cidr := range []string{ diff --git a/registry/registry.go b/registry/registry.go index 4e3da09..e516231 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -24,19 +24,19 @@ import ( log "github.com/sirupsen/logrus" ) -// Registry ... +// Registry is the registry structure type Registry struct { dockerLocalRegistryHost string ipfsClient *ipfs.Client } -// Config ... +// Config is the config for the registry type Config struct { DockerLocalRegistryHost string IPFSHost string } -// NewRegistry ... +// NewRegistry returns a new registry client instance func NewRegistry(config *Config) *Registry { dockerLocalRegistryHost := config.DockerLocalRegistryHost if dockerLocalRegistryHost == "" { @@ -64,7 +64,7 @@ func NewRegistry(config *Config) *Registry { } } -// PushImageByID uploads Docker image by image ID (hash or repo tag) to IPFS +// PushImageByID uploads Docker image by image ID, which is hash or repo tag, to IPFS func (registry *Registry) PushImageByID(imageID string) (string, error) { // normalize image ID imageID, err := registry.TagToImageID(imageID) @@ -103,7 +103,7 @@ func (registry *Registry) TagToImageID(imageID string) (string, error) { return imageID, nil } -// PushImage uploads Docker image to IPFS +// PushImage uploads the Docker image to IPFS func (registry *Registry) PushImage(reader io.Reader) (string, error) { tmp, err := mktmp() if err != nil { @@ -134,7 +134,7 @@ func (registry *Registry) PushImage(reader io.Reader) (string, error) { return imageIpfsHash, nil } -// DownloadImage download Docker image from IPFS +// DownloadImage downloads the Docker image from IPFS func (registry *Registry) DownloadImage(ipfsHash string) (string, error) { tmp, err := mktmp() if err != nil { @@ -150,7 +150,7 @@ func (registry *Registry) DownloadImage(ipfsHash string) (string, error) { return path, nil } -// PullImage pull Docker image from IPFS +// PullImage pulls the Docker image from IPFS func (registry *Registry) PullImage(ipfsHash string) (string, error) { go server.Run() client := docker.NewClient() @@ -182,6 +182,7 @@ func (registry *Registry) PullImage(ipfsHash string) (string, error) { return dockerizedHash, nil } +// mktmp creates a temporary directory func mktmp() (string, error) { tmp, err := ioutil.TempDir("", "") if err != nil { @@ -191,6 +192,7 @@ func mktmp() (string, error) { return tmp, err } +// ipfsPrep formats the image data into a registry compatible format func ipfsPrep(tmp string) (string, error) { root, err := mktmp() if err != nil { @@ -263,6 +265,7 @@ func ipfsPrep(tmp string) (string, error) { return root, nil } +// uploadDir uploads the directory to IPFS func (registry *Registry) uploadDir(root string) (string, error) { hash, err := registry.ipfsClient.AddDir(root) if err != nil { @@ -295,6 +298,7 @@ func (registry *Registry) uploadDir(root string) (string, error) { return "", errors.New("could not upload") } +// ipfsShellCmd executes an IPFS command via the shell func ipfsShellCmd(cmdStr string) (string, string, error) { path, err := exec.LookPath("ipfs") if err != nil { @@ -325,6 +329,7 @@ func ipfsShellCmd(cmdStr string) (string, string, error) { return outstr, errstr, nil } +// copyio is a helper to copy IO readers func copyio(out io.Reader, in io.Writer) error { _, err := io.Copy(in, out) if err != nil { @@ -334,6 +339,7 @@ func copyio(out io.Reader, in io.Writer) error { return nil } +// writeJSON writes an interface to a JSON file func writeJSON(idate interface{}, path string) error { data, err := json.Marshal(idate) if err != nil { @@ -369,6 +375,7 @@ func makeV2Manifest(manifest map[string]interface{}, configFile, configDest, tmp return v2manifest, nil } +// mergemap merges two maps func mergemap(a, b map[string]interface{}) map[string]interface{} { for k, v := range b { a[k] = v @@ -376,6 +383,7 @@ func mergemap(a, b map[string]interface{}) map[string]interface{} { return a } +// prepareV2Manifest preps the docker image into a docker registry V2 manifest format func prepareV2Manifest(mf map[string]interface{}, tmp, blobDir string) (map[string]interface{}, error) { res := make(map[string]interface{}) res["schemaVersion"] = 2 @@ -407,6 +415,7 @@ func prepareV2Manifest(mf map[string]interface{}, tmp, blobDir string) (map[stri return res, nil } +// compressLayer returns the sha256 hash of a directory func compressLayer(path, blobDir string) (int64, string, error) { log.Printf("[registry] compressing layer: %s", path) tmp := blobDir + "/layer.tmp.tgz" @@ -434,6 +443,7 @@ func compressLayer(path, blobDir string) (int64, string, error) { return size, digest, nil } +// gzipFile gzips a file into a destination file func gzipFile(src, dst string) error { data, _ := ioutil.ReadFile(src) var b bytes.Buffer @@ -444,6 +454,7 @@ func gzipFile(src, dst string) error { return ioutil.WriteFile(dst, b.Bytes(), os.ModePerm) } +// fileSize returns the size of the file func fileSize(path string) (int64, error) { fi, err := os.Stat(path) if err != nil { @@ -453,6 +464,7 @@ func fileSize(path string) (int64, error) { return fi.Size(), nil } +// sha256 returns the sha256 hash of a file func sha256File(path string) (string, error) { // TODO: stream instead of reading whole image in memory f, err := os.Open(path) @@ -469,6 +481,7 @@ func sha256File(path string) (string, error) { return hex.EncodeToString(h.Sum(nil)), nil } +// renameFile renames a file func renameFile(src, dst string) error { if err := os.Rename(src, dst); err != nil { return err @@ -477,6 +490,7 @@ func renameFile(src, dst string) error { return nil } +// mkdir creates a directory if it doesn't exist func mkdir(path string) { if _, err := os.Stat(path); os.IsNotExist(err) { os.Mkdir(path, os.ModePerm) @@ -491,6 +505,7 @@ func copyFile(src, dst string) error { return ioutil.WriteFile(dst, data, 0644) } +// untar untars a reader into a destination directory func untar(reader io.Reader, dst string) error { tr := tar.NewReader(reader) @@ -532,6 +547,7 @@ func untar(reader io.Reader, dst string) error { } } +// readJSON reads a file into a map structure func readJSON(filepath string) (map[string]map[string]string, error) { body, _ := ioutil.ReadFile(filepath) var data map[string]map[string]string @@ -543,6 +559,7 @@ func readJSON(filepath string) (map[string]map[string]string, error) { return data, nil } +// readJSONArray reads a file into an array of map structures func readJSONArray(filepath string) ([]map[string]interface{}, error) { body, _ := ioutil.ReadFile(filepath) var data []map[string]interface{} @@ -554,6 +571,7 @@ func readJSONArray(filepath string) ([]map[string]interface{}, error) { return data, nil } +// normalizeImageName normalizes an image name func normalizeImageName(name string) string { // TODO return name diff --git a/registry/registry_test.go b/registry/registry_test.go index fe75d57..ac72ead 100644 --- a/registry/registry_test.go +++ b/registry/registry_test.go @@ -66,7 +66,7 @@ func TestPushImage(t *testing.T) { func TestPushImageByID(t *testing.T) { t.Skip() client := docker.NewClient() - err := client.LoadImageByFilepath(testImageTar) + err := client.LoadImageByFilePath(testImageTar) if err != nil { t.Error(err) } diff --git a/regutil/regutil.go b/regutil/regutil.go index 8e78088..7c01bb7 100644 --- a/regutil/regutil.go +++ b/regutil/regutil.go @@ -7,7 +7,7 @@ import ( base58 "github.com/jbenet/go-base58" ) -// DockerizeHash base58 to base32 conversion +// DockerizeHash does base58 to base32 conversion func DockerizeHash(base58Hash string) string { decodedB58 := base58.Decode(base58Hash) b32str := base32.StdEncoding.EncodeToString(decodedB58) @@ -15,7 +15,7 @@ func DockerizeHash(base58Hash string) string { return strings.ToLower(b32str[0 : len(b32str)-1]) } -// IpfsifyHash base32 to base58 conversion +// IpfsifyHash does base32 to base58 conversion func IpfsifyHash(base32Hash string) string { decodedB32, err := base32.StdEncoding.DecodeString(strings.ToUpper(base32Hash) + "=") if err != nil { diff --git a/regutil/regutil_test.go b/regutil/regutil_test.go index 934e933..9163588 100644 --- a/regutil/regutil_test.go +++ b/regutil/regutil_test.go @@ -1,3 +1,38 @@ package regutil -// TODO: tests +import ( + "fmt" + "testing" +) + +func TestDockerizeHash(t *testing.T) { + for i, tt := range []struct { + in string + out string + }{ + {"QmaCm7VNsmM61FApFevTcJ1PxPabmfY4Tf2dFjpAdVdHLF", "ciqlarwwgn3qewftxxsapdx6aqi5yi7scootos7m5bqbjuzshoavapa"}, + } { + t.Run(fmt.Sprintf("%v", i), func(t *testing.T) { + got := DockerizeHash(tt.in) + if got != tt.out { + t.Errorf("want %q, got %q", tt.out, got) + } + }) + } +} + +func TestIpfsifyHash(t *testing.T) { + for i, tt := range []struct { + in string + out string + }{ + {"ciqlarwwgn3qewftxxsapdx6aqi5yi7scootos7m5bqbjuzshoavapa", "QmaCm7VNsmM61FApFevTcJ1PxPabmfY4Tf2dFjpAdVdHLF"}, + } { + t.Run(fmt.Sprintf("%v", i), func(t *testing.T) { + got := IpfsifyHash(tt.in) + if got != tt.out { + t.Errorf("want %q, got %q", tt.out, got) + } + }) + } +} diff --git a/server/server.go b/server/server.go index 84327e4..da72e20 100644 --- a/server/server.go +++ b/server/server.go @@ -15,7 +15,7 @@ import ( var listener net.Listener var serverHost = fmt.Sprintf("0.0.0.0:%v", 5000) -// Run ... +// Run runs the registry server func Run() error { // already listening if listener != nil { @@ -31,7 +31,7 @@ func Run() error { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { uri := r.RequestURI - log.Printf("[registry] %s", uri) + log.Printf("[registry/server] %s", uri) if uri == "/v2/" { jsonstr := []byte(fmt.Sprintf(`{"what": "a registry", "gateway":%q, "handles": [%q, %q], "problematic": ["version 1 registries"], "project": "https://github.com/miguelmota/ipdr"}`, gw, contentTypes["manifestListV2Schema"], contentTypes["manifestV2Schema"])) @@ -77,7 +77,7 @@ func Run() error { // manifest request location = location + suffix } - log.Printf("[registry] location %s", location) + log.Printf("[registry/server] location %s", location) req, err := http.NewRequest("GET", location, nil) if err != nil { @@ -113,18 +113,19 @@ func Run() error { } port := listener.Addr().(*net.TCPAddr).Port - log.Printf("[registry] port %v", port) + log.Printf("[registry/server] port %v", port) return http.Serve(listener, nil) } -// Close ... +// Close stops the server func Close() { if listener != nil { listener.Close() } } +// ipfsURL returns the full IPFS url func ipfsURL(hash string) string { url, err := ipfs.GatewayURL() if err != nil {