Skip to content

Commit 0d46fee

Browse files
committed
feat: multiple registries
1 parent 96448bc commit 0d46fee

21 files changed

Lines changed: 188 additions & 236 deletions

File tree

.vscode/launch.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,21 @@
325325
"${workspaceFolder}/examples/scroll-cwd-pull/", "artifacts.druid.gg/druid-team/scroll-minecraft-forge:1.20.1",
326326
],
327327
},
328+
{
329+
"name": "Debug Daemon run registry login",
330+
"type": "go",
331+
"request": "launch",
332+
"mode": "debug",
333+
"console": "integratedTerminal",
334+
"program": "${workspaceFolder}/main.go",
335+
"args": [
336+
"registry",
337+
"login",
338+
"--host", "artifacts.druid.gg/my-project",
339+
"--user", "myuser",
340+
"--password", "mypass"
341+
],
342+
},
328343
{
329344
"name": "Debug Daemon run registry push meta",
330345
"type": "go",

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ VERSION ?= "dev"
44

55
generate-api: ## Generate API types from OpenAPI spec
66
@echo "Generating API types from OpenAPI spec..."
7-
@which oapi-codegen > /dev/null || (echo "Installing oapi-codegen..." && go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest)
7+
@which oapi-codegen > /dev/null || (echo "Installing oapi-codegen..." && go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@v2.5.1)
88
@PATH="$(shell go env GOPATH)/bin:$$PATH" oapi-codegen -config api/oapi-codegen.yaml api/openapi.yaml
99

1010
validate-api: ## Validate OpenAPI spec
1111
@echo "Validating OpenAPI spec..."
12-
@which oapi-codegen > /dev/null || (echo "Installing oapi-codegen..." && go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest)
12+
@which oapi-codegen > /dev/null || (echo "Installing oapi-codegen..." && go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@v2.5.1)
1313
@PATH="$(shell go env GOPATH)/bin:$$PATH" oapi-codegen -config api/oapi-codegen.yaml api/openapi.yaml > /dev/null
1414
@echo "✓ OpenAPI spec is valid"
1515

cmd/registry_login.go

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cmd
22

33
import (
4+
"github.com/highcard-dev/daemon/internal/core/domain"
45
"github.com/spf13/cobra"
56
"github.com/spf13/viper"
67
)
@@ -12,26 +13,45 @@ var registryPassword string
1213
var LoginCommand = &cobra.Command{
1314
Use: "login",
1415
Short: "Login to OCI registry",
15-
RunE: func(cmd *cobra.Command, args []string) error {
16-
17-
viper.Set("registry.host", registryHost)
18-
viper.Set("registry.user", registryUser)
19-
viper.Set("registry.password", registryPassword)
20-
21-
//TODO: validate credentials
22-
23-
err := viper.WriteConfig()
16+
Long: `Add or update registry credentials in the configuration.
17+
Supports multiple registries with path-based credential matching.
2418
25-
return err
19+
Examples:
20+
druid registry login --host registry-1.docker.io -u user -p pass
21+
druid registry login --host artifacts.druid.gg/project1 -u user1 -p pass1
22+
druid registry login --host artifacts.druid.gg/project2 -u user2 -p pass2`,
23+
RunE: func(cmd *cobra.Command, args []string) error {
24+
var registries []domain.RegistryCredential
25+
viper.UnmarshalKey("registries", &registries)
26+
27+
newCred := domain.RegistryCredential{
28+
Host: registryHost,
29+
Username: registryUser,
30+
Password: registryPassword,
31+
}
32+
33+
found := false
34+
for i := range registries {
35+
if registries[i].Host == registryHost {
36+
registries[i] = newCred
37+
found = true
38+
break
39+
}
40+
}
41+
42+
if !found {
43+
registries = append(registries, newCred)
44+
}
45+
46+
viper.Set("registries", registries)
47+
48+
return viper.WriteConfig()
2649
},
2750
}
2851

2952
func init() {
30-
31-
LoginCommand.Flags().StringVarP(&registryHost, "host", "", "", "OCI registry host")
32-
53+
LoginCommand.Flags().StringVarP(&registryHost, "host", "", "", "OCI registry host (e.g., artifacts.druid.gg/project1)")
3354
LoginCommand.Flags().StringVarP(&registryUser, "user", "u", "", "username")
34-
3555
LoginCommand.Flags().StringVarP(&registryPassword, "password", "p", "", "User password")
3656

3757
LoginCommand.MarkFlagRequired("host")

cmd/registry_pull.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"github.com/highcard-dev/daemon/internal/core/services/registry"
77
"github.com/highcard-dev/daemon/internal/utils/logger"
88
"github.com/spf13/cobra"
9-
"github.com/spf13/viper"
109
)
1110

1211
var PullCommand = &cobra.Command{
@@ -17,11 +16,7 @@ var PullCommand = &cobra.Command{
1716

1817
artifact := args[0]
1918

20-
user := viper.GetString("registry.user")
21-
password := viper.GetString("registry.password")
22-
host := viper.GetString("registry.host")
23-
24-
registryClient := registry.NewOciClient(host, user, password)
19+
registryClient := registry.NewOciClient(LoadRegistryStore())
2520

2621
err := registryClient.Pull(filepath.Join(cwd, ".scroll"), artifact)
2722
if err != nil {

cmd/registry_push.go

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"github.com/highcard-dev/daemon/internal/core/services/registry"
1111
"github.com/highcard-dev/daemon/internal/utils/logger"
1212
"github.com/spf13/cobra"
13-
"github.com/spf13/viper"
1413
"go.uber.org/zap"
1514
)
1615

@@ -28,12 +27,9 @@ var PushCommand = &cobra.Command{
2827
Args: cobra.MaximumNArgs(1),
2928
RunE: func(cmd *cobra.Command, args []string) error {
3029

31-
user := viper.GetString("registry.user")
32-
password := viper.GetString("registry.password")
33-
host := viper.GetString("registry.host")
34-
35-
if user == "" || password == "" || host == "" {
36-
return fmt.Errorf("registry host, user and password must be set. Please use `druid registry login` to set them")
30+
credStore := LoadRegistryStore()
31+
if !credStore.HasCredentials() {
32+
return fmt.Errorf("no registry credentials configured. Please use `druid registry login` to set them")
3733
}
3834

3935
folder := "."
@@ -49,9 +45,9 @@ var PushCommand = &cobra.Command{
4945
return err
5046
}
5147

52-
logger.Log().Info("Pushing "+scroll.Name+" to registry", zap.String("path", fullPath), zap.String("registry", host))
48+
logger.Log().Info("Pushing "+scroll.Name+" to registry", zap.String("path", fullPath))
5349

54-
ociClient := registry.NewOciClient(host, user, password)
50+
ociClient := registry.NewOciClient(credStore)
5551

5652
repo := scroll.Name
5753

@@ -93,7 +89,7 @@ var PushCommand = &cobra.Command{
9389
time.Sleep(time.Duration(tries+1) * time.Second)
9490
}
9591

96-
logger.Log().Info("Pushed "+scroll.Name+" to registry", zap.String("path", fullPath), zap.String("registry", host))
92+
logger.Log().Info("Pushed "+scroll.Name+" to registry", zap.String("path", fullPath))
9793
return nil
9894
},
9995
}

cmd/registry_push_meta.go

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"github.com/highcard-dev/daemon/internal/core/services/registry"
88
"github.com/highcard-dev/daemon/internal/utils/logger"
99
"github.com/spf13/cobra"
10-
"github.com/spf13/viper"
1110
"go.uber.org/zap"
1211
)
1312

@@ -17,12 +16,9 @@ var PushMetaCommand = &cobra.Command{
1716
Args: cobra.RangeArgs(1, 2),
1817
RunE: func(cmd *cobra.Command, args []string) error {
1918

20-
user := viper.GetString("registry.user")
21-
password := viper.GetString("registry.password")
22-
host := viper.GetString("registry.host")
23-
24-
if user == "" || password == "" || host == "" {
25-
return fmt.Errorf("registry host, user and password must be set. Please use `druid registry login` to set them")
19+
credStore := LoadRegistryStore()
20+
if !credStore.HasCredentials() {
21+
return fmt.Errorf("no registry credentials configured. Please use `druid registry login` to set them")
2622
}
2723

2824
artifact := args[0]
@@ -33,9 +29,9 @@ var PushMetaCommand = &cobra.Command{
3329

3430
fullPath := path.Join(cwd, folder)
3531

36-
logger.Log().Info("Pushing "+artifact+" meta to registry", zap.String("path", fullPath), zap.String("registry", host))
32+
logger.Log().Info("Pushing "+artifact+" meta to registry", zap.String("path", fullPath))
3733

38-
ociClient := registry.NewOciClient(host, user, password)
34+
ociClient := registry.NewOciClient(credStore)
3935

4036
_, err := ociClient.PushMeta(fullPath, artifact)
4137

cmd/root.go

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@ package cmd
33
import (
44
"os"
55

6+
"github.com/highcard-dev/daemon/internal/core/domain"
7+
"github.com/highcard-dev/daemon/internal/core/services/registry"
68
"github.com/spf13/cobra"
79
"github.com/spf13/viper"
810
)
911

1012
var envPath string
1113
var cwd string
1214
var ignoreLockfileQueue bool
15+
var configFile string
1316

1417
var RootCmd = &cobra.Command{
1518
Use: "druid",
@@ -22,8 +25,6 @@ var RootCmd = &cobra.Command{
2225
}
2326

2427
func init() {
25-
26-
viper.SetDefault("registry.host", "registry-1.docker.io")
2728
cobra.OnInitialize(initConfig)
2829

2930
RootCmd.AddCommand(ServeCommand)
@@ -43,22 +44,26 @@ func init() {
4344
RootCmd.PersistentFlags().StringVarP(&cwd, "cwd", "", c, "Path to environment file (.env)")
4445

4546
RootCmd.PersistentFlags().StringVarP(&envPath, "env-file", "e", "./.env", "Path to environment file (.env)")
47+
RootCmd.PersistentFlags().StringVar(&configFile, "config", "", "Path to config file (default: ~/.druid.yaml)")
4648
RootCmd.PersistentFlags().BoolVar(&ignoreVersionCheck, "ignore-version-check", false, "Ignore version check between scroll.yaml and scroll-lock.json")
4749
RootCmd.PersistentFlags().BoolVar(&ignoreLockfileQueue, "ignore-lockfile-queue", false, "Skip queuing the lock file")
4850

4951
}
5052

5153
func initConfig() {
52-
home, err := os.UserHomeDir()
53-
cobra.CheckErr(err)
54+
viper.AutomaticEnv()
5455

55-
viper.SetConfigType("yaml")
56-
viper.SetConfigName(".druid")
56+
if configFile != "" {
57+
viper.SetConfigFile(configFile)
58+
} else {
59+
home, err := os.UserHomeDir()
60+
cobra.CheckErr(err)
5761

58-
// Search config in home directory with name ".cobra" (without extension).
59-
viper.AddConfigPath(home)
62+
viper.SetConfigType("yaml")
63+
viper.SetConfigName(".druid")
64+
viper.AddConfigPath(home)
65+
}
6066

61-
viper.AutomaticEnv()
6267
viper.SafeWriteConfig()
6368
viper.ReadInConfig()
6469
}
@@ -68,3 +73,24 @@ func Execute() {
6873
os.Exit(1)
6974
}
7075
}
76+
77+
func LoadRegistryStore() *registry.CredentialStore {
78+
var registries []domain.RegistryCredential
79+
viper.UnmarshalKey("registries", &registries)
80+
81+
if len(registries) == 0 {
82+
host := viper.GetString("registry.host")
83+
user := viper.GetString("registry.user")
84+
password := viper.GetString("registry.password")
85+
86+
if host != "" {
87+
registries = append(registries, domain.RegistryCredential{
88+
Host: host,
89+
Username: user,
90+
Password: password,
91+
})
92+
}
93+
}
94+
95+
return registry.NewCredentialStore(registries)
96+
}

cmd/run.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
snapshotService "github.com/highcard-dev/daemon/internal/core/services/snapshot"
99
"github.com/highcard-dev/daemon/internal/utils/logger"
1010
"github.com/spf13/cobra"
11-
"github.com/spf13/viper"
1211
"go.uber.org/zap"
1312
)
1413

@@ -20,11 +19,7 @@ var RunCmd = &cobra.Command{
2019
RunE: func(cmd *cobra.Command, args []string) error {
2120
command := args[0]
2221

23-
host := viper.GetString("registry.host")
24-
user := viper.GetString("registry.user")
25-
password := viper.GetString("registry.password")
26-
27-
client := registry.NewOciClient(host, user, password)
22+
client := registry.NewOciClient(LoadRegistryStore())
2823

2924
ctx := cmd.Context()
3025

cmd/serve.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"github.com/highcard-dev/daemon/internal/signals"
2020
"github.com/highcard-dev/daemon/internal/utils/logger"
2121
"github.com/spf13/cobra"
22-
"github.com/spf13/viper"
2322
"go.uber.org/zap"
2423
)
2524

@@ -60,11 +59,7 @@ to interact and monitor the Scroll Application`,
6059
return err
6160
}
6261

63-
host := viper.GetString("registry.host")
64-
user := viper.GetString("registry.user")
65-
password := viper.GetString("registry.password")
66-
67-
client := registry.NewOciClient(host, user, password)
62+
client := registry.NewOciClient(LoadRegistryStore())
6863
logManager := services.NewLogManager()
6964
consoleService := services.NewConsoleManager(logManager)
7065

cmd/update.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"github.com/highcard-dev/daemon/internal/utils/logger"
1212
v1 "github.com/opencontainers/image-spec/specs-go/v1"
1313
"github.com/spf13/cobra"
14-
"github.com/spf13/viper"
1514
)
1615

1716
var UpdateCommand = &cobra.Command{
@@ -39,11 +38,7 @@ var UpdateCommand = &cobra.Command{
3938
//ctx := context.Background()
4039
logger.Log().Info("Checking for updates for " + artifact)
4140

42-
host := viper.GetString("registry.host")
43-
user := viper.GetString("registry.user")
44-
password := viper.GetString("registry.password")
45-
46-
registryClient := registry.NewOciClient(host, user, password)
41+
registryClient := registry.NewOciClient(LoadRegistryStore())
4742

4843
canUpdate := false
4944

0 commit comments

Comments
 (0)