Skip to content

Commit

Permalink
Merge pull request #44
Browse files Browse the repository at this point in the history
* refactoring the routes and adding groups to the router

* simpligying the harbor config

* fixing running test cases using dagger run command

* adding absolute path flag in test case to configure the path to the c…

* adding utils for simplification

* fixing the logger contex error and coderabbit fixes

* making the secure push compulsory until specified

* coderabbit review

* fixing the test cases

* adding running tests in github workflow
  • Loading branch information
Mehul-Kumar-27 authored Sep 20, 2024
1 parent 02ba374 commit 72219c0
Show file tree
Hide file tree
Showing 21 changed files with 844 additions and 283 deletions.
4 changes: 3 additions & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
HARBOR_USERNAME=admin
HARBOR_PASSWORD=Harbor12345
ZOT_URL="127.0.0.1:8585"
TOKEN=""
TOKEN=""
ENV=dev
USE_UNSECURE=true
36 changes: 36 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,42 @@ on:
workflow_dispatch:

jobs:
run-tests:
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: '>=1.22'

- name: Install Curl
run: sudo apt-get install curl

- name: Install Docker
run: |
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
- name: Install Dagger CLI
run: |
cd /usr/local
curl -L https://dl.dagger.io/dagger/install.sh | sudo sh
cd -
- name: Generated the dagger go code
run: dagger develop

- name: Run Test Cases
run: dagger run go test ./... -v -count=1

dagger-build-satellite:
needs: run-tests
runs-on: ubuntu-latest
permissions:
contents: write
Expand Down Expand Up @@ -43,6 +78,7 @@ jobs:
# cloud-token: ${{ secrets.DAGGER_CLOUD_TOKEN }}

build-ground-control:
needs: run-tests
runs-on: ubuntu-latest
permissions:
contents: write
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ dist/
.DS_Store
zot/cache.db
secrets.txt
__debug_bin1949266242
13 changes: 11 additions & 2 deletions ci/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,23 @@ To run a particular function, run:
To build the satellite binaries, use the following command:
- ```sh
dagger call build --source=. --name=satellite export --path=./bin
This would spin up a container and install required dependencies and build various architecture binaries and export them to the host on path ./bin for testing on the host.
This would spin up a container and install required dependencies and build various architecture binaries and export them to the host on path ./bin for testing on the host.
- #### Example: Releasing to GitHub
To release the project on GitHub, use the following command
- ```sh
dagger call release --directory=. --token=<your_github_token> --name=satellite
The above function would then proceed to release the project on github for the name provided. The above function also takes argument `--release-type` which would tell the release what kind of release it is i.e major, minor or path, The default value is set to be path release
The above function would then proceed to release the project on github for the name provided. The above function also takes argument `--release-type` which would tell the release what kind of release it is i.e major, minor or path, The default value is set to be path release
- #### Example: Releasing to GitHub with type of release
To release the project on GitHub, use the following command
- ```sh
dagger call release --directory=. --token=<your_github_token> --name=satellite --release-type=minor
The above function would release the minor version for the project mentioned
- #### Example: Running test cases using dagger
To run the test cases using dagger use the following command
- ```sh
dagger run go test ./... -v -count=1
This would run the test cases present in the entire project.
To run the test cases without dagger use the following command
- ```sh
go test ./... -v -count=1 -args -abs=false
This would set the config file to use the relative path.
2 changes: 1 addition & 1 deletion config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ log_level = "info"

# For testing purposes :
# https://demo.goharbor.io/v2/myproject/album-server
# /image-list/images.json
# ./image-list/images.json
166 changes: 166 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package config

import (
"fmt"
"os"

"github.com/joho/godotenv"
"github.com/spf13/viper"
)

var AppConfig *Config

type Config struct {
log_level string
own_registry bool
own_registry_adr string
own_registry_port string
zot_config_path string
input string
zot_url string
registry string
repository string
user_input string
scheme string
api_version string
image string
harbor_password string
harbor_username string
env string
use_unsecure bool
}

func GetLogLevel() string {
return AppConfig.log_level
}

func GetOwnRegistry() bool {
return AppConfig.own_registry
}

func GetOwnRegistryAdr() string {
return AppConfig.own_registry_adr
}

func GetOwnRegistryPort() string {
return AppConfig.own_registry_port
}

func GetZotConfigPath() string {
return AppConfig.zot_config_path
}

func GetInput() string {
return AppConfig.input
}

func SetZotURL(url string) {
AppConfig.zot_url = url
}

func GetZotURL() string {
return AppConfig.zot_url
}

func SetRegistry(registry string) {
AppConfig.registry = registry
}

func GetRegistry() string {
return AppConfig.registry
}

func SetRepository(repository string) {
AppConfig.repository = repository
}

func GetRepository() string {
return AppConfig.repository
}

func SetUserInput(user_input string) {
AppConfig.user_input = user_input
}

func GetUserInput() string {
return AppConfig.user_input
}

func SetScheme(scheme string) {
AppConfig.scheme = scheme
}

func GetScheme() string {
return AppConfig.scheme
}

func SetAPIVersion(api_version string) {
AppConfig.api_version = api_version
}

func GetAPIVersion() string {
return AppConfig.api_version
}

func SetImage(image string) {
AppConfig.image = image
}

func GetImage() string {
return AppConfig.image
}

func UseUnsecure() bool {
return AppConfig.use_unsecure
}

func GetHarborPassword() string {
return AppConfig.harbor_password
}

func GetHarborUsername() string {
return AppConfig.harbor_username
}

func LoadConfig() (*Config, error) {
viper.SetConfigName("config")
viper.SetConfigType("toml")
viper.AddConfigPath(".")
if err := viper.ReadInConfig(); err != nil {
return nil, fmt.Errorf("error reading config file at path '%s': %w", viper.ConfigFileUsed(), err)
}

// Load environment and start satellite
if err := godotenv.Load(); err != nil {
return &Config{}, fmt.Errorf("error loading .env file: %w", err)
}
var use_unsecure bool
if os.Getenv("USE_UNSECURE") == "true" {
use_unsecure = true
} else {
use_unsecure = false
}

return &Config{
log_level: viper.GetString("log_level"),
own_registry: viper.GetBool("bring_own_registry"),
own_registry_adr: viper.GetString("own_registry_adr"),
own_registry_port: viper.GetString("own_registry_port"),
zot_config_path: viper.GetString("zotConfigPath"),
input: viper.GetString("url_or_file"),
harbor_password: os.Getenv("HARBOR_PASSWORD"),
harbor_username: os.Getenv("HARBOR_USERNAME"),
env: os.Getenv("ENV"),
zot_url: os.Getenv("ZOT_URL"),
use_unsecure: use_unsecure,
}, nil
}

func InitConfig() error {
var err error
AppConfig, err = LoadConfig()
if err != nil {
return err
}
return nil
}
11 changes: 11 additions & 0 deletions internal/images/get-images.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ import (
"time"
)

type ImageList struct {
RegistryURL string `json:"registryUrl"`
Repositories []struct {
Repository string `json:"repository"`
Images []struct {
Name string `json:"name"`
} `json:"images"`
} `json:"repositories"`
}


type Image struct {
ID int `json:"ID"`
Registry string `json:"Registry"`
Expand Down
28 changes: 23 additions & 5 deletions internal/replicate/replicate.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"path/filepath"
"strings"

"container-registry.com/harbor-satellite/internal/config"
"container-registry.com/harbor-satellite/internal/store"
"container-registry.com/harbor-satellite/logger"
"github.com/google/go-containerregistry/pkg/authn"
Expand All @@ -20,7 +21,12 @@ type Replicator interface {
DeleteExtraImages(ctx context.Context, imgs []store.Image) error
}

type BasicReplicator struct{}
type BasicReplicator struct {
username string
password string
use_unsecure bool
zot_url string
}

type ImageInfo struct {
Name string `json:"name"`
Expand All @@ -37,7 +43,12 @@ type RegistryInfo struct {
}

func NewReplicator(context context.Context) Replicator {
return &BasicReplicator{}
return &BasicReplicator{
username: config.GetHarborUsername(),
password: config.GetHarborPassword(),
use_unsecure: config.UseUnsecure(),
zot_url: config.GetZotURL(),
}
}

func (r *BasicReplicator) Replicate(ctx context.Context, image string) error {
Expand Down Expand Up @@ -177,9 +188,12 @@ func CopyImage(ctx context.Context, imageName string) error {
Username: username,
Password: password,
})

options := []crane.Option{crane.WithAuth(auth)}
if config.UseUnsecure() {
options = append(options, crane.Insecure)
}
// Pull the image with authentication
srcImage, err := crane.Pull(imageName, crane.WithAuth(auth), crane.Insecure)
srcImage, err := crane.Pull(imageName, options...)
if err != nil {
log.Error().Msgf("Failed to pull image: %v", err)
return fmt.Errorf("failed to pull image: %w", err)
Expand All @@ -188,7 +202,11 @@ func CopyImage(ctx context.Context, imageName string) error {
}

// Push the image to the destination registry
err = crane.Push(srcImage, destRef, crane.Insecure)
push_options := []crane.Option{}
if config.UseUnsecure() {
push_options = append(push_options, crane.Insecure)
}
err = crane.Push(srcImage, destRef, push_options...)
if err != nil {
log.Error().Msgf("Failed to push image: %v", err)
return fmt.Errorf("failed to push image: %w", err)
Expand Down
34 changes: 34 additions & 0 deletions internal/satellite/routes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package satellite

import (
"encoding/json"
"net/http"

"container-registry.com/harbor-satellite/internal/server"
)

type SatelliteRegistrar struct{}

type SatelliteResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
StatusCode int `json:"status_code"`
}

func (sr *SatelliteRegistrar) RegisterRoutes(router server.Router) {
satelliteGroup := router.Group("/satellite")
satelliteGroup.HandleFunc("/ping", sr.Ping)
}

func (sr *SatelliteRegistrar) Ping(w http.ResponseWriter, r *http.Request) {
response := SatelliteResponse{
Success: true,
Message: "Ping satellite successful",
StatusCode: http.StatusOK,
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(response); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
Loading

0 comments on commit 72219c0

Please sign in to comment.