Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 99817dc25d | |||
| cf8011196f | |||
| 1f3bcd6b69 |
@@ -12,7 +12,9 @@ MCR (Metacircular Container Registry) is a container registry service integrated
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
make all # vet → lint → test → build
|
make all # vet → lint → test → build
|
||||||
make mcr # build binary with version injection
|
make mcrsrv # build API server binary with version injection
|
||||||
|
make mcr-web # build web UI binary with version injection
|
||||||
|
make mcrctl # build admin CLI binary
|
||||||
make build # compile all packages
|
make build # compile all packages
|
||||||
make test # run all tests
|
make test # run all tests
|
||||||
make vet # go vet
|
make vet # go vet
|
||||||
@@ -53,8 +55,9 @@ go test ./internal/server -run TestPushManifest
|
|||||||
|
|
||||||
## Package Structure
|
## Package Structure
|
||||||
|
|
||||||
- `cmd/mcr/` — CLI entry point (cobra subcommands: server, init, status, snapshot)
|
- `cmd/mcrsrv/` — API server entry point (cobra subcommands: server, init, status, snapshot)
|
||||||
- `cmd/mcr-web/` — Web UI entry point
|
- `cmd/mcr-web/` — Web UI entry point
|
||||||
|
- `cmd/mcrctl/` — Admin CLI entry point
|
||||||
- `internal/auth/` — MCIAS integration (token validation, 30s cache by SHA-256)
|
- `internal/auth/` — MCIAS integration (token validation, 30s cache by SHA-256)
|
||||||
- `internal/config/` — TOML config loading and validation
|
- `internal/config/` — TOML config loading and validation
|
||||||
- `internal/db/` — SQLite setup, migrations (idempotent, tracked in `schema_migrations`)
|
- `internal/db/` — SQLite setup, migrations (idempotent, tracked in `schema_migrations`)
|
||||||
|
|||||||
@@ -62,10 +62,14 @@ func newClient(serverURL, grpcAddr, token, caCertFile string) (*apiClient, error
|
|||||||
|
|
||||||
if grpcAddr != "" {
|
if grpcAddr != "" {
|
||||||
creds := credentials.NewTLS(tlsCfg)
|
creds := credentials.NewTLS(tlsCfg)
|
||||||
cc, err := grpc.NewClient(grpcAddr,
|
dialOpts := []grpc.DialOption{
|
||||||
grpc.WithTransportCredentials(creds),
|
grpc.WithTransportCredentials(creds),
|
||||||
grpc.WithDefaultCallOptions(grpc.ForceCodecV2(mcrv1.JSONCodec{})),
|
grpc.WithDefaultCallOptions(grpc.ForceCodecV2(mcrv1.JSONCodec{})),
|
||||||
)
|
}
|
||||||
|
if token != "" {
|
||||||
|
dialOpts = append(dialOpts, grpc.WithPerRPCCredentials(bearerToken(token)))
|
||||||
|
}
|
||||||
|
cc, err := grpc.NewClient(grpcAddr, dialOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("grpc dial: %w", err)
|
return nil, fmt.Errorf("grpc dial: %w", err)
|
||||||
}
|
}
|
||||||
@@ -91,6 +95,16 @@ func (c *apiClient) useGRPC() bool {
|
|||||||
return c.grpcConn != nil
|
return c.grpcConn != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bearerToken implements grpc.PerRPCCredentials, injecting the
|
||||||
|
// Authorization header into every gRPC call.
|
||||||
|
type bearerToken string
|
||||||
|
|
||||||
|
func (t bearerToken) GetRequestMetadata(_ context.Context, _ ...string) (map[string]string, error) {
|
||||||
|
return map[string]string{"authorization": "Bearer " + string(t)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t bearerToken) RequireTransportSecurity() bool { return true }
|
||||||
|
|
||||||
// apiError is the JSON error envelope returned by the REST API.
|
// apiError is the JSON error envelope returned by the REST API.
|
||||||
type apiError struct {
|
type apiError struct {
|
||||||
Error string `json:"error"`
|
Error string `json:"error"`
|
||||||
|
|||||||
@@ -38,7 +38,9 @@ ca_cert = "/path/to/ca.pem"
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLoadConfigMissingDefaultIsOK(t *testing.T) {
|
func TestLoadConfigMissingDefaultIsOK(t *testing.T) {
|
||||||
// Empty path triggers default search; missing file is not an error.
|
// Point XDG_CONFIG_HOME at an empty dir so we don't find the real config.
|
||||||
|
t.Setenv("XDG_CONFIG_HOME", t.TempDir())
|
||||||
|
|
||||||
cfg, err := loadConfig("")
|
cfg, err := loadConfig("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
Reference in New Issue
Block a user