Skip to content

Commit

Permalink
First version of image list fetching from local file via relative path
Browse files Browse the repository at this point in the history
Reworked main's user interface to automatically recognise and validate URL or filepath
Reworked http-fetcher to accept  full URLs
Added images.json test file
  • Loading branch information
OneFlyingBanana committed Apr 26, 2024
1 parent eced8c4 commit ca048a0
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 39 deletions.
19 changes: 19 additions & 0 deletions image-list/images.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"results": [
{
"name": "alpine:3.1"
},
{
"name": "alpine:3.2"
},
{
"name": "alpine:3.3"
},
{
"name": "ubuntu:latest"
},
{
"name": "nginx:1.19"
}
]
}
68 changes: 59 additions & 9 deletions internal/store/file-fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,79 @@ package store

import (
"context"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"os"
"path/filepath"
)

type FileImageList struct {
Path string
}

func FileImageListFetcher() *FileImageList {
func FileImageListFetcher(relativePath string) *FileImageList {
// Get the current working directory
dir, err := os.Getwd()
if err != nil {
fmt.Println("Error getting current directory:", err)
return nil
}

// Construct the absolute path from the relative path
absPath := filepath.Join(dir, relativePath)

return &FileImageList{
Path: "images.json",
Path: absPath,
}
}

func (client *FileImageList) List(ctx context.Context) ([]Image, error) {
// Placeholder for fetching images from a file
images := []Image{
{"alpine:3.1"},
{"alpine:3.2"},
{"alpine:3.3"},

fmt.Println("Reading from:", client.Path)

// Read the file
data, err := os.ReadFile(client.Path)
if err != nil {
return nil, err
}

// Define a struct to match the JSON structure
var imageData struct {
Results []struct {
Name string `json:"name"`
} `json:"results"`
}

// Parse the JSON data
err = json.Unmarshal(data, &imageData)
if err != nil {
return nil, err
}

// Convert the parsed data into a slice of Image structs
images := make([]Image, len(imageData.Results))
for i, result := range imageData.Results {
images[i] = Image{
Reference: result.Name,
}
}
fmt.Println("Fetched", len(images), "images :", images)

return images, nil
}

func (client *FileImageList) GetHash(ctx context.Context) (string, error) {
// Placeholder for fetching image hash from a remote registry
return "hash456", nil
// Read the file
data, err := os.ReadFile(client.Path)
if err != nil {
return "", err
}

// Hash and return the body
hash := sha256.Sum256(data)
hashString := hex.EncodeToString(hash[:])

return hashString, nil
}
21 changes: 10 additions & 11 deletions internal/store/http-fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,24 @@ import (
"fmt"
"io"
"net/http"
"path"
)

type RemoteImageList struct {
BaseURL string
Repository string
BaseURL string
}

func RemoteImageListFetcher() *RemoteImageList {
func RemoteImageListFetcher(url string) *RemoteImageList {
return &RemoteImageList{
BaseURL: "https://registry.hub.docker.com/v2/repositories",
Repository: "alpine",
BaseURL: url,
}
}

func (client *RemoteImageList) List(ctx context.Context) ([]Image, error) {
url := fmt.Sprintf("%s/%s/", client.BaseURL, client.Repository)
resp, err := http.Get(url)
// Extract the last segment of the BaseURL to use as the image name
lastSegment := path.Base(client.BaseURL)
fmt.Println("Last segment:", lastSegment)
resp, err := http.Get(client.BaseURL)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -53,7 +54,7 @@ func (client *RemoteImageList) List(ctx context.Context) ([]Image, error) {
images := make([]Image, len(data.Results))
for i, result := range data.Results {
images[i] = Image{
Reference: fmt.Sprintf("%s:%s", client.Repository, result.Name),
Reference: fmt.Sprintf("%s:%s", lastSegment, result.Name),
}
}
fmt.Println("Fetched", len(images), "images :", images)
Expand All @@ -62,9 +63,7 @@ func (client *RemoteImageList) List(ctx context.Context) ([]Image, error) {
}

func (client *RemoteImageList) GetHash(ctx context.Context) (string, error) {
url := fmt.Sprintf("%s/%s/", client.BaseURL, client.Repository)
fmt.Println("Source :", url)
resp, err := http.Get(url)
resp, err := http.Get(client.BaseURL)
if err != nil {
return "", err
}
Expand Down
70 changes: 51 additions & 19 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ import (
"fmt"
"net/http"
"net/http/pprof"
"net/url"
"os"
"os/signal"
"path/filepath"
"strings"
"syscall"
"time"

Expand Down Expand Up @@ -62,26 +65,55 @@ func run() error {
return metricsSrv.Shutdown(shutdownCtx)
})

// Prompt the user to choose between remote and file fetcher
fmt.Println("Choose an image list fetcher:")
fmt.Println("1. Remote")
fmt.Println("2. File")
fmt.Print("Enter your choice (1 or 2): ")
var fetcher store.ImageFetcher
for {
fmt.Print("Enter the source (URL or relative file path): ")

reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
return fmt.Errorf("failed to read user input: %w", err)
}
// For testing purposes :
// https://registry.hub.docker.com/v2/repositories/alpine
// /image-list/images.json

var fetcher store.ImageFetcher
switch input {
case "1\n":
fetcher = store.RemoteImageListFetcher()
case "2\n":
fetcher = store.FileImageListFetcher()
default:
return fmt.Errorf("invalid choice")
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
fmt.Println("Error reading input. Please try again.")
continue
}
input = strings.TrimSpace(input)

// Try to parse the input as a URL
parsedURL, err := url.Parse(input)
if err != nil || parsedURL.Scheme == "" {
// If there was an error, the input is not a valid URL.
fmt.Println("Input is not a valid URL. Checking if it is a file path...")
// Check if the input is a file path
if strings.ContainsAny(input, "\\:*?\"<>|") {
fmt.Println("Path contains invalid characters. Please try again.")
continue
}
// Get the current working directory
dir, err := os.Getwd()
if err != nil {
fmt.Println("Error getting current directory:", err)
continue
}

// Construct the absolute path from the relative path
absPath := filepath.Join(dir, input)

// Check if the file exists
if _, err := os.Stat(absPath); os.IsNotExist(err) {
fmt.Println("No URL or file found. Please try again.")
continue
}
fmt.Println("Input is a valid file path.")
fetcher = store.FileImageListFetcher(input)
} else {
fmt.Println("Input is a valid URL.")
// If there was no error, the input is a valid URL.
fetcher = store.RemoteImageListFetcher(input)
}
break
}

// Instantiate a new Satellite and its components
Expand All @@ -99,7 +131,7 @@ func run() error {
return s.Run(ctx)
})

err = g.Wait()
err := g.Wait()
if err != nil {
return err
}
Expand Down

0 comments on commit ca048a0

Please sign in to comment.