8 Commits

Author SHA1 Message Date
d5580f01f2 Migrate module path from kyle/ to mc/ org
All import paths updated to git.wntrmute.dev/mc/. Bumps mcdsl to v1.2.0.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 02:05:59 -07:00
296bbc5357 Add mcrctl purge command for tag retention
Client-side purge that keeps the last N tags per repository (excluding
latest) and deletes older manifests. Uses existing MCR APIs — no new
server RPCs needed.

Server-side: added updated_at to TagInfo struct and GetRepositoryDetail
query so tags can be sorted by recency.

Usage: mcrctl purge --keep 3 --dry-run --gc

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 01:42:28 -07:00
078dd39052 Merge pull request 'Bump mcdsl for $PORT env var support' (#1) from feature/port-env-adoption into master 2026-03-27 08:16:21 +00:00
e81903dd88 Update mcdsl to v1.1.0 (tagged release)
Replace pseudo-version with the tagged v1.1.0 release.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 01:14:52 -07:00
0838bcbab2 Bump mcdsl to f94c4b1 for $PORT env var support
Update mcdsl from v1.0.0 to the port-env-support branch tip, which
adds automatic $PORT environment variable support to the config
package. Adapt grpcserver.New call to the updated signature that now
accepts an *Options parameter (pass nil for default behavior).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 01:07:52 -07:00
acc4851549 Update RUNBOOK MCP example to use pinned version tags
Replace :latest with :v1.1.0 in the MCP service definition example
to match the new platform convention of explicit version pinning.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 23:31:02 -07:00
9d7043a594 Block guest accounts from web UI login
The web UI now validates the MCIAS token after login and rejects
accounts with the guest role before setting the session cookie.
This is defense-in-depth alongside the env:restricted MCIAS tag.

The webserver.New() constructor takes a new ValidateFunc parameter
that inspects token roles post-authentication. MCIAS login does not
return roles, so this requires an extra ValidateToken round-trip at
login time (result is cached for 30s).

Security: guest role accounts are denied web UI access

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 23:02:22 -07:00
3d36c58d0d Add RUNBOOK.md and expand README.md
Create operational runbook covering health checks, start/stop/restart
(MCP and Docker Compose), backup/restore, garbage collection, and
incident procedures for database corruption, TLS expiry, MCIAS outage,
disk full, and push/pull failures. Includes MCP service definition
reference for the two-component deployment (mcr-api + mcr-web).

Rewrite README from 2-line stub to full project overview with
quick-start instructions, binary descriptions, port tables, and links
to ARCHITECTURE.md and RUNBOOK.md per engineering standards.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 22:11:21 -07:00
88 changed files with 3312 additions and 703 deletions

View File

@@ -881,6 +881,10 @@ separate binary (`mcr-web`) that communicates with mcrsrv via gRPC.
- CSRF protection via signed double-submit cookies on all mutating requests.
- Session cookie: `HttpOnly`, `Secure`, `SameSite=Strict`.
- All user input escaped by `html/template`.
- Guest accounts are blocked at login. After MCIAS authentication succeeds,
the web UI validates the token and checks roles; accounts with the `guest`
role are denied access. This is defense-in-depth alongside the
`env:restricted` MCIAS tag.
---
@@ -1059,7 +1063,7 @@ The audit log is append-only. It never contains credentials or token values.
| Threat | Mitigation |
|--------|------------|
| Unauthenticated access | All endpoints require MCIAS bearer token; `env:restricted` tag blocks guest/viewer login |
| Unauthenticated access | All endpoints require MCIAS bearer token; `env:restricted` tag blocks guest/viewer login; web UI additionally rejects `guest` role at login |
| Unauthorized push/delete | Policy engine enforces per-principal, per-repository access; default-deny for system accounts |
| Digest mismatch (supply chain) | All uploads verified against client-supplied digest; rejected if mismatch |
| Blob corruption | Content-addressed storage; digests verified on write. Periodic integrity scrub via `mcrctl scrub` (future) |

View File

@@ -32,7 +32,7 @@ go test ./internal/server -run TestPushManifest
## Tech Stack
- **Language:** Go 1.25+, `CGO_ENABLED=0`, statically linked
- **Module path:** `git.wntrmute.dev/kyle/mcr`
- **Module path:** `git.wntrmute.dev/mc/mcr`
- **Database:** SQLite via `modernc.org/sqlite` (pure-Go, no CGo)
- **Config:** TOML via `go-toml/v2`, env overrides via `MCR_*`
- **APIs:** REST (chi) + gRPC (protobuf), kept in sync

View File

@@ -24,8 +24,8 @@ lint:
golangci-lint run ./...
proto:
protoc --go_out=. --go_opt=module=git.wntrmute.dev/kyle/mcr \
--go-grpc_out=. --go-grpc_opt=module=git.wntrmute.dev/kyle/mcr \
protoc --go_out=. --go_opt=module=git.wntrmute.dev/mc/mcr \
--go-grpc_out=. --go-grpc_opt=module=git.wntrmute.dev/mc/mcr \
proto/mcr/v1/*.proto
proto-lint:

View File

@@ -32,6 +32,30 @@ See `PROJECT_PLAN.md` for the implementation roadmap and
### Next Steps
1. Deploy to rift (issue MCR service token, generate TLS cert, update mc-proxy routes)
2. Consider adding roles to MCIAS login response to eliminate the extra ValidateToken round-trip
### 2026-03-26 — Web UI: block guest login
**Task:** Prevent MCIAS guest accounts from logging into the web UI.
**Changes:**
- `internal/webserver/server.go`: Added `ValidateFunc` type; `New()`
accepts a validate function to inspect tokens post-login.
- `internal/webserver/auth.go`: After `loginFn` succeeds, calls
`validateFn` to retrieve roles. Rejects accounts with the `guest`
role before setting the session cookie.
- `cmd/mcr-web/main.go`: Wires `ValidateFunc` via `authClient.ValidateToken()`.
- `internal/webserver/server_test.go`: Added guest/user test accounts,
`validateFn` returning role-appropriate responses, `TestLoginDeniesGuest`.
- `ARCHITECTURE.md`: Updated Web UI security section and threat mitigations
to document guest blocking as defense-in-depth.
**Design note:** MCIAS `/v1/auth/login` does not return roles, so the
web UI makes a second `ValidateToken` call after login to inspect them.
This is an extra MCIAS round-trip at login time (cached for 30s). A
future MCIAS change to include roles in the login response would
eliminate this.
### 2026-03-25 — Phase 13: Deployment Artifacts
@@ -688,7 +712,7 @@ Lint fix:
entry points with cobra subcommands.
**Changes:**
- `go.mod`: module `git.wntrmute.dev/kyle/mcr`, Go 1.25, cobra dependency
- `go.mod`: module `git.wntrmute.dev/mc/mcr`, Go 1.25, cobra dependency
- Directory skeleton: `cmd/mcrsrv/`, `cmd/mcr-web/`, `cmd/mcrctl/`,
`internal/`, `proto/mcr/v1/`, `gen/mcr/v1/`, `web/templates/`,
`web/static/`, `deploy/docker/`, `deploy/examples/`, `deploy/scripts/`,

View File

@@ -63,7 +63,7 @@ produces a project that builds and lints cleanly with no functionality.
### Step 0.1: Go module and directory structure
**Acceptance criteria:**
- `go.mod` initialized with module path `git.wntrmute.dev/kyle/mcr`
- `go.mod` initialized with module path `git.wntrmute.dev/mc/mcr`
- Directory skeleton created per `ARCHITECTURE.md` §13:
`cmd/mcrsrv/`, `cmd/mcr-web/`, `cmd/mcrctl/`, `internal/`, `proto/mcr/v1/`,
`gen/mcr/v1/`, `web/`, `deploy/`

View File

@@ -1,3 +1,59 @@
MCR is the Metacircular Container Registry
# MCR
This is a container registry integrated with MCIAS.
Metacircular Container Registry -- an OCI Distribution Spec-compliant
container registry for the Metacircular platform. MCR stores and serves
container images with authentication delegated to MCIAS and a local
policy engine for fine-grained access control. Metadata is stored in
SQLite; blobs are stored as content-addressed files on the filesystem.
## Quick Start
Build the binaries:
```bash
make all
```
This produces three binaries:
| Binary | Purpose |
|--------|---------|
| `mcrsrv` | Registry server (OCI + admin REST + gRPC) |
| `mcr-web` | Web UI (htmx, communicates with mcrsrv via gRPC) |
| `mcrctl` | Admin CLI |
Copy and edit the example configuration:
```bash
cp deploy/examples/mcr.toml /srv/mcr/mcr.toml
# Edit TLS paths, database path, storage paths, MCIAS URL
```
Run the server:
```bash
./mcrsrv server --config /srv/mcr/mcr.toml
```
The server starts two listeners:
| Port | Protocol | Purpose |
|------|----------|---------|
| 8443 | TCP | HTTPS -- OCI Distribution endpoints + admin REST API |
| 9443 | TCP | gRPC admin API (TLS, MCIAS auth) |
Run the web UI:
```bash
./mcr-web server --config /srv/mcr/mcr.toml
```
| Port | Protocol | Purpose |
|------|----------|---------|
| 8080 | TCP | HTTP -- web UI (repository browsing, policy management) |
## Documentation
- [ARCHITECTURE.md](ARCHITECTURE.md) -- full technical specification, OCI compliance details, database schema, policy engine, and security model.
- [RUNBOOK.md](RUNBOOK.md) -- operational procedures, health checks, backup/restore, incident response, and MCP deployment.
- [CLAUDE.md](CLAUDE.md) -- context for AI-assisted development.

404
RUNBOOK.md Normal file
View File

@@ -0,0 +1,404 @@
# MCR Runbook
## Service Overview
MCR (Metacircular Container Registry) is an OCI Distribution
Spec-compliant container registry for the Metacircular platform. It
stores and serves container images, with authentication delegated to
MCIAS and a local policy engine for fine-grained access control.
MCR runs as two containers:
- **mcr-api** -- the registry server. Exposes OCI Distribution endpoints
and an admin REST API on port 8443 (HTTPS), plus a gRPC admin API on
port 9443. Handles blob storage, manifest management, and
token-based authentication via MCIAS.
- **mcr-web** -- the web UI. Communicates with mcr-api via gRPC on port
9443. Provides repository/tag browsing and ACL policy management for
administrators. Listens on port 8080. Guest accounts are blocked at
login; only `admin` and `user` roles can access the web interface.
Both are fronted by MC-Proxy for TLS routing. Metadata is stored in
SQLite; blobs are stored as content-addressed files on the filesystem
under `/srv/mcr/layers/`.
## Health Checks
### REST
```bash
curl -k https://localhost:8443/v1/health
```
Expected: HTTP 200.
### gRPC
Use the `AdminService.Health` RPC on port 9443. This method is public
(no auth required).
### OCI Version Check
```bash
curl -k https://localhost:8443/v2/
```
Expected: HTTP 401 with `WWW-Authenticate` header (confirms the OCI
endpoint is alive and responding). An authenticated request returns
HTTP 200 with `{}`.
### CLI
```bash
mcrctl status --addr https://localhost:8443
```
Expected output: `ok`
## Common Operations
### Start the Service (MCP)
1. Deploy via MCP:
```bash
mcp deploy mcr
```
2. Verify health:
```bash
curl -k https://localhost:8443/v1/health
```
### Start the Service (Docker Compose)
1. Verify config exists: `ls /srv/mcr/mcr.toml`
2. Start the containers:
```bash
docker compose -f deploy/docker/docker-compose-rift.yml up -d
```
3. Verify health:
```bash
curl -k https://localhost:8443/v1/health
```
### Stop the Service
Via MCP:
```bash
mcp stop mcr
```
Via Docker Compose:
```bash
docker compose -f deploy/docker/docker-compose-rift.yml stop
```
MCR handles SIGTERM gracefully: it stops accepting new connections,
drains in-flight requests (including ongoing uploads) for up to 60
seconds, then force-closes remaining connections and exits.
### Restart the Service
Via MCP:
```bash
mcp restart mcr
```
Via Docker Compose:
```bash
docker compose -f deploy/docker/docker-compose-rift.yml restart
```
Verify health after restart:
```bash
curl -k https://localhost:8443/v1/health
```
### Backup (Snapshot)
MCR backups have two parts: the SQLite database (metadata) and the blob
filesystem. The database snapshot alone is usable but incomplete --
missing blobs return 404 on pull.
1. Run the snapshot command:
```bash
mcrsrv snapshot --config /srv/mcr/mcr.toml
```
2. The snapshot is saved to `/srv/mcr/backups/mcr-YYYYMMDD-HHMMSS.db`.
3. Verify the snapshot file exists and has a reasonable size:
```bash
ls -lh /srv/mcr/backups/
```
4. For a complete backup, also copy the blob directory:
```bash
rsync -a /srv/mcr/layers/ /backup/mcr/layers/
```
A systemd timer (`mcr-backup.timer`) runs the database snapshot daily
at 02:00 UTC with 5-minute jitter.
### Restore from Snapshot
1. Stop the service (see above).
2. Back up the current database:
```bash
cp /srv/mcr/mcr.db /srv/mcr/mcr.db.pre-restore
```
3. Copy the snapshot into place:
```bash
cp /srv/mcr/backups/mcr-YYYYMMDD-HHMMSS.db /srv/mcr/mcr.db
```
4. If restoring blobs as well:
```bash
rsync -a /backup/mcr/layers/ /srv/mcr/layers/
```
5. Start the service (see above).
6. Verify the service is healthy:
```bash
curl -k https://localhost:8443/v1/health
```
7. Verify an image pull works:
```bash
docker pull mcr.svc.mcp.metacircular.net:8443/<repo>:<tag>
```
### Log Inspection
Container logs (mcr-api):
```bash
docker compose -f deploy/docker/docker-compose-rift.yml logs --tail 100 mcr-api
```
Container logs (mcr-web):
```bash
docker compose -f deploy/docker/docker-compose-rift.yml logs --tail 100 mcr-web
```
Follow logs in real time:
```bash
docker compose -f deploy/docker/docker-compose-rift.yml logs -f mcr-api mcr-web
```
Via MCP:
```bash
mcp logs mcr
```
MCR logs to stderr as structured text (slog). Log level is configured
via `[log] level` in `mcr.toml` (debug, info, warn, error).
### Garbage Collection
Garbage collection removes unreferenced blobs -- blobs no longer
referenced by any manifest. GC acquires a registry-wide lock that
blocks new blob uploads for the duration of the mark-and-sweep phase.
Pulls are not blocked.
1. Trigger GC via CLI:
```bash
mcrctl gc --addr https://mcr.svc.mcp.metacircular.net:8443
```
2. Check GC status:
```bash
mcrctl gc status --addr https://mcr.svc.mcp.metacircular.net:8443
```
3. GC can also be triggered via the REST API:
```bash
curl -k -X POST -H "Authorization: Bearer <token>" https://localhost:8443/v1/gc
```
If a previous GC crashed after the database sweep but before filesystem
cleanup, orphaned files may remain on disk. Run reconciliation to clean
them up:
```bash
mcrctl gc --reconcile --addr https://mcr.svc.mcp.metacircular.net:8443
```
## Incident Procedures
### Database Corruption
Symptoms: server fails to start with SQLite errors, or API requests
return unexpected errors.
1. Stop the service.
2. Check for WAL/SHM files alongside the database:
```bash
ls -la /srv/mcr/mcr.db*
```
3. Attempt an integrity check:
```bash
sqlite3 /srv/mcr/mcr.db "PRAGMA integrity_check;"
```
4. If integrity check fails, restore from the most recent snapshot:
```bash
cp /srv/mcr/mcr.db /srv/mcr/mcr.db.corrupt
cp /srv/mcr/backups/mcr-YYYYMMDD-HHMMSS.db /srv/mcr/mcr.db
```
5. Start the service and verify health.
6. Note: blobs on the filesystem are unaffected by database corruption.
Images pushed after the snapshot was taken will be missing from
metadata. Their blobs remain on disk and will be cleaned up by GC
unless the metadata is re-created.
### TLS Certificate Expiry
Symptoms: health check fails with TLS errors, Docker clients get
certificate verification errors on push/pull.
1. Check certificate expiry:
```bash
openssl x509 -in /srv/mcr/certs/cert.pem -noout -enddate
```
2. Replace the certificate and key files at the paths configured in
`mcr.toml` (`[server] tls_cert` and `tls_key`).
3. Restart the service to load the new certificate.
4. Verify health:
```bash
curl -k https://localhost:8443/v1/health
```
### MCIAS Outage
Symptoms: push/pull fails with 401 or 502 errors. Authentication
cannot complete.
1. Confirm MCIAS is unreachable:
```bash
curl -k https://svc.metacircular.net:8443/v1/health
```
2. Cached token validation results remain valid for up to 30 seconds
after the last successful MCIAS check. Operations using
recently-validated tokens may continue briefly.
3. Once cached tokens expire, all authenticated operations (push, pull,
catalog, admin) will fail until MCIAS recovers.
4. The OCI `/v2/` version check endpoint still responds (confirms MCR
itself is running).
5. Escalate to MCIAS (see Escalation below).
### Disk Full
Symptoms: blob uploads fail, database writes fail, container may crash.
1. Check disk usage:
```bash
df -h /srv/mcr/
du -sh /srv/mcr/layers/ /srv/mcr/uploads/ /srv/mcr/mcr.db
```
2. Clean up stale uploads:
```bash
ls -la /srv/mcr/uploads/
```
Remove upload files that are old and have no matching in-progress
upload in the database.
3. Run garbage collection to reclaim unreferenced blobs:
```bash
mcrctl gc --addr https://mcr.svc.mcp.metacircular.net:8443
```
4. If GC does not free enough space, identify large repositories:
```bash
mcrctl repo list --addr https://mcr.svc.mcp.metacircular.net:8443
```
5. Delete unused tags or repositories to free space, then run GC again.
6. If the disk is completely full and the service cannot start, manually
remove orphaned files from `/srv/mcr/uploads/` to free enough space
for the service to start, then run GC.
### Image Push/Pull Failures
Symptoms: `docker push` or `docker pull` returns errors.
1. Verify the service is running and healthy:
```bash
curl -k https://localhost:8443/v1/health
```
2. Test OCI endpoint:
```bash
curl -k https://localhost:8443/v2/
```
Expected: HTTP 401 with `WWW-Authenticate` header.
3. Test authentication:
```bash
curl -k -u username:password https://localhost:8443/v2/token?service=mcr
```
Expected: HTTP 200 with a token response.
4. Check if the issue is policy-related (403 Denied):
```bash
mcrctl policy list --addr https://mcr.svc.mcp.metacircular.net:8443
```
Review policy rules for the affected account and repository.
5. Check audit log for denied requests:
```bash
mcrctl audit tail --n 20 --addr https://mcr.svc.mcp.metacircular.net:8443
```
6. For push failures, verify all referenced blobs exist before pushing
the manifest. The error `MANIFEST_BLOB_UNKNOWN` means a layer was
not uploaded before the manifest push.
7. Check logs for detailed error information:
```bash
docker compose -f deploy/docker/docker-compose-rift.yml logs --tail 50 mcr-api
```
## MCP Deployment
MCR is deployed via MCP as a two-component service on the `rift` node.
### Service Definition
```toml
name = "mcr"
node = "rift"
active = true
[[components]]
name = "api"
image = "mcr.svc.mcp.metacircular.net:8443/mcr:v1.1.0"
network = "mcpnet"
user = "0:0"
restart = "unless-stopped"
ports = ["127.0.0.1:28443:8443", "127.0.0.1:29443:9443"]
volumes = ["/srv/mcr:/srv/mcr"]
cmd = ["server", "--config", "/srv/mcr/mcr.toml"]
[[components]]
name = "web"
image = "mcr.svc.mcp.metacircular.net:8443/mcr-web:v1.1.0"
network = "mcpnet"
user = "0:0"
restart = "unless-stopped"
ports = ["127.0.0.1:28080:8080"]
volumes = ["/srv/mcr:/srv/mcr"]
cmd = ["server", "--config", "/srv/mcr/mcr.toml"]
```
### Port Mapping
| Component | Container Port | Host Port | Purpose |
|-----------|---------------|-----------|---------|
| mcr-api | 8443 | 28443 | HTTPS (OCI + admin REST) |
| mcr-api | 9443 | 29443 | gRPC admin API |
| mcr-web | 8080 | 28080 | Web UI (HTTP, behind MC-Proxy) |
Both containers share the `/srv/mcr` volume for configuration, database,
and blob storage. They are connected to the `mcpnet` Docker network.
## Escalation
Escalate when:
- Database corruption cannot be resolved by restoring a snapshot.
- MCIAS is down and registry operations are urgently needed.
- Disk full cannot be resolved by GC and cleanup.
- Push/pull failures persist after following the procedures above.
- Any issue not covered by this runbook.
Escalation path: Kyle (platform owner).

View File

@@ -17,10 +17,10 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
mcrv1 "git.wntrmute.dev/kyle/mcr/gen/mcr/v1"
"git.wntrmute.dev/kyle/mcr/internal/auth"
"git.wntrmute.dev/kyle/mcr/internal/config"
"git.wntrmute.dev/kyle/mcr/internal/webserver"
mcrv1 "git.wntrmute.dev/mc/mcr/gen/mcr/v1"
"git.wntrmute.dev/mc/mcr/internal/auth"
"git.wntrmute.dev/mc/mcr/internal/config"
"git.wntrmute.dev/mc/mcr/internal/webserver"
)
var version = "dev"
@@ -99,6 +99,14 @@ func runServer(configPath string) error {
return authClient.Login(username, password)
}
validateFn := func(token string) ([]string, error) {
claims, err := authClient.ValidateToken(token)
if err != nil {
return nil, err
}
return claims.Roles, nil
}
// Generate CSRF key.
csrfKey := make([]byte, 32)
if _, err := rand.Read(csrfKey); err != nil {
@@ -106,7 +114,7 @@ func runServer(configPath string) error {
}
// Create web server.
srv, err := webserver.New(registryClient, policyClient, auditClient, adminClient, loginFn, csrfKey)
srv, err := webserver.New(registryClient, policyClient, auditClient, adminClient, loginFn, validateFn, csrfKey)
if err != nil {
return fmt.Errorf("create web server: %w", err)
}
@@ -162,6 +170,7 @@ func runServer(configPath string) error {
func dialGRPC(cfg *config.Config) (*grpc.ClientConn, error) {
tlsCfg := &tls.Config{
MinVersion: tls.VersionTLS13,
ServerName: cfg.Web.TLSServerName,
}
if cfg.Web.CACert != "" {

View File

@@ -14,7 +14,7 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
mcrv1 "git.wntrmute.dev/kyle/mcr/gen/mcr/v1"
mcrv1 "git.wntrmute.dev/mc/mcr/gen/mcr/v1"
)
// apiClient wraps both REST and gRPC transports. When grpcAddr is set

View File

@@ -11,7 +11,7 @@ import (
"github.com/spf13/cobra"
mcrv1 "git.wntrmute.dev/kyle/mcr/gen/mcr/v1"
mcrv1 "git.wntrmute.dev/mc/mcr/gen/mcr/v1"
)
var version = "dev"
@@ -62,6 +62,7 @@ func main() {
root.AddCommand(statusCmd())
root.AddCommand(repoCmd())
root.AddCommand(gcCmd())
root.AddCommand(purgeCmd())
root.AddCommand(policyCmd())
root.AddCommand(auditCmd())
root.AddCommand(snapshotCmd())

274
cmd/mcrctl/purge.go Normal file
View File

@@ -0,0 +1,274 @@
package main
import (
"context"
"encoding/json"
"fmt"
"os"
"path"
"sort"
"strings"
"github.com/spf13/cobra"
mcrv1 "git.wntrmute.dev/mc/mcr/gen/mcr/v1"
)
func purgeCmd() *cobra.Command {
var (
keep int
repo string
dryRun bool
trigGC bool
)
cmd := &cobra.Command{
Use: "purge",
Short: "Remove old image tags, keeping the last N per repository",
Long: `Purge removes old image tags from repositories based on a retention
policy. The 'latest' tag is always kept. For each repository, tags are
sorted by updated_at (most recent first) and only the --keep most recent
are retained. Remaining tags' manifests are deleted, cascading to their
tag references. Run with --gc to trigger garbage collection afterward.`,
RunE: func(_ *cobra.Command, _ []string) error {
return runPurge(keep, repo, dryRun, trigGC)
},
}
cmd.Flags().IntVar(&keep, "keep", 3, "number of tags to keep per repo (excluding latest)")
cmd.Flags().StringVar(&repo, "repo", "", "limit to repositories matching this glob pattern")
cmd.Flags().BoolVar(&dryRun, "dry-run", false, "show what would be deleted without deleting")
cmd.Flags().BoolVar(&trigGC, "gc", false, "trigger garbage collection after purging")
return cmd
}
// tagWithTime is a tag with its timestamp for sorting.
type tagWithTime struct {
Name string
Digest string
UpdatedAt string
}
func runPurge(keep int, repoPattern string, dryRun, trigGC bool) error {
if keep < 0 {
return fmt.Errorf("--keep must be non-negative")
}
// List repositories.
repos, err := listRepos()
if err != nil {
return err
}
// Filter by pattern if given.
if repoPattern != "" {
var filtered []string
for _, r := range repos {
matched, _ := path.Match(repoPattern, r)
if matched {
filtered = append(filtered, r)
}
}
repos = filtered
}
if len(repos) == 0 {
_, _ = fmt.Fprintln(os.Stdout, "No repositories matched.")
return nil
}
totalDeleted := 0
for _, repoName := range repos {
tags, err := listTagsWithTime(repoName)
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "warning: skipping %s: %v\n", repoName, err)
continue
}
// Separate latest from versioned tags.
var latest *tagWithTime
var versioned []tagWithTime
for _, t := range tags {
if t.Name == "latest" {
lt := t
latest = &lt
} else {
versioned = append(versioned, t)
}
}
// Sort by updated_at descending (most recent first).
sort.Slice(versioned, func(i, j int) bool {
return versioned[i].UpdatedAt > versioned[j].UpdatedAt
})
// Determine which tags to delete.
if len(versioned) <= keep {
continue // nothing to purge
}
toDelete := versioned[keep:]
// Build set of digests that are still referenced by kept tags.
keptDigests := make(map[string]bool)
if latest != nil {
keptDigests[latest.Digest] = true
}
for _, t := range versioned[:keep] {
keptDigests[t.Digest] = true
}
for _, t := range toDelete {
if keptDigests[t.Digest] {
// Manifest is shared with a kept tag — skip deletion.
if dryRun {
_, _ = fmt.Fprintf(os.Stdout, "[skip] %s:%s (manifest shared with kept tag)\n", repoName, t.Name)
}
continue
}
if dryRun {
_, _ = fmt.Fprintf(os.Stdout, "[delete] %s:%s (digest: %s, updated: %s)\n", repoName, t.Name, t.Digest[:12], t.UpdatedAt)
} else {
if err := deleteManifest(repoName, t.Digest); err != nil {
_, _ = fmt.Fprintf(os.Stderr, "warning: failed to delete %s:%s: %v\n", repoName, t.Name, err)
continue
}
_, _ = fmt.Fprintf(os.Stdout, "deleted %s:%s\n", repoName, t.Name)
}
totalDeleted++
}
}
if dryRun {
_, _ = fmt.Fprintf(os.Stdout, "\nDry run: %d manifests would be deleted.\n", totalDeleted)
} else {
_, _ = fmt.Fprintf(os.Stdout, "\nPurged %d manifests.\n", totalDeleted)
}
// Trigger GC if requested and not a dry run.
if trigGC && !dryRun && totalDeleted > 0 {
_, _ = fmt.Fprintln(os.Stdout, "Triggering garbage collection...")
if err := triggerGC(); err != nil {
return fmt.Errorf("gc: %w", err)
}
_, _ = fmt.Fprintln(os.Stdout, "Garbage collection started.")
}
return nil
}
// listRepos returns all repository names.
func listRepos() ([]string, error) {
if client.useGRPC() {
resp, err := client.registry.ListRepositories(context.Background(), &mcrv1.ListRepositoriesRequest{})
if err != nil {
return nil, fmt.Errorf("list repositories: %w", err)
}
var names []string
for _, r := range resp.GetRepositories() {
names = append(names, r.GetName())
}
return names, nil
}
data, err := client.restDo("GET", "/v1/repositories", nil)
if err != nil {
return nil, fmt.Errorf("list repositories: %w", err)
}
var repos []struct {
Name string `json:"name"`
}
if err := json.Unmarshal(data, &repos); err != nil {
return nil, err
}
var names []string
for _, r := range repos {
names = append(names, r.Name)
}
return names, nil
}
// listTagsWithTime returns tags with timestamps for a repository.
func listTagsWithTime(repoName string) ([]tagWithTime, error) {
if client.useGRPC() {
resp, err := client.registry.GetRepository(context.Background(), &mcrv1.GetRepositoryRequest{Name: repoName})
if err != nil {
return nil, fmt.Errorf("get repository: %w", err)
}
var tags []tagWithTime
for _, t := range resp.GetTags() {
tags = append(tags, tagWithTime{
Name: t.GetName(),
Digest: t.GetDigest(),
UpdatedAt: t.GetUpdatedAt(),
})
}
return tags, nil
}
data, err := client.restDo("GET", "/v1/repositories/"+repoName, nil)
if err != nil {
return nil, fmt.Errorf("get repository: %w", err)
}
var detail struct {
Tags []struct {
Name string `json:"name"`
Digest string `json:"digest"`
UpdatedAt string `json:"updated_at"`
} `json:"tags"`
}
if err := json.Unmarshal(data, &detail); err != nil {
return nil, err
}
var tags []tagWithTime
for _, t := range detail.Tags {
tags = append(tags, tagWithTime{
Name: t.Name,
Digest: t.Digest,
UpdatedAt: t.UpdatedAt,
})
}
return tags, nil
}
// deleteManifest deletes a manifest by digest via the OCI API.
func deleteManifest(repoName, digest string) error {
if client.useGRPC() {
// No gRPC RPC for OCI manifest delete — fall back to REST.
// The OCI Distribution spec uses DELETE /v2/{name}/manifests/{reference}.
}
// URL-encode the repo name for path segments with slashes.
_, err := client.restDo("DELETE", "/v2/"+repoName+"/manifests/"+digest, nil)
return err
}
// triggerGC starts garbage collection.
func triggerGC() error {
if client.useGRPC() {
_, err := client.registry.GarbageCollect(context.Background(), &mcrv1.GarbageCollectRequest{})
return err
}
_, err := client.restDo("POST", "/v1/gc", nil)
return err
}
// formatRepoName truncates long repo names for display.
func formatRepoName(name string, maxLen int) string {
if len(name) <= maxLen {
return name
}
parts := strings.Split(name, "/")
if len(parts) > 1 {
return "..." + parts[len(parts)-1]
}
return name[:maxLen-3] + "..."
}

View File

@@ -16,17 +16,17 @@ import (
"github.com/spf13/cobra"
"git.wntrmute.dev/kyle/mcr/internal/auth"
"git.wntrmute.dev/kyle/mcr/internal/config"
"git.wntrmute.dev/kyle/mcr/internal/db"
"git.wntrmute.dev/kyle/mcr/internal/gc"
"git.wntrmute.dev/kyle/mcr/internal/oci"
"git.wntrmute.dev/kyle/mcr/internal/policy"
"git.wntrmute.dev/kyle/mcr/internal/server"
"git.wntrmute.dev/kyle/mcr/internal/storage"
"git.wntrmute.dev/mc/mcr/internal/auth"
"git.wntrmute.dev/mc/mcr/internal/config"
"git.wntrmute.dev/mc/mcr/internal/db"
"git.wntrmute.dev/mc/mcr/internal/gc"
"git.wntrmute.dev/mc/mcr/internal/oci"
"git.wntrmute.dev/mc/mcr/internal/policy"
"git.wntrmute.dev/mc/mcr/internal/server"
"git.wntrmute.dev/mc/mcr/internal/storage"
"git.wntrmute.dev/kyle/mcr/internal/grpcserver"
mcdsldb "git.wntrmute.dev/kyle/mcdsl/db"
"git.wntrmute.dev/mc/mcr/internal/grpcserver"
mcdsldb "git.wntrmute.dev/mc/mcdsl/db"
)
var version = "dev"

View File

@@ -25,9 +25,10 @@ service_name = "mcr"
tags = ["env:restricted"]
[web]
listen_addr = "127.0.0.1:8080" # Web UI listen address
grpc_addr = "127.0.0.1:9443" # mcrsrv gRPC address for the web UI
ca_cert = "" # CA cert for verifying mcrsrv gRPC TLS
listen_addr = "127.0.0.1:8080" # Web UI listen address
grpc_addr = "127.0.0.1:9443" # mcrsrv gRPC address for the web UI
tls_server_name = "" # Override TLS server name (when dial address differs from cert SAN)
ca_cert = "" # CA cert for verifying mcrsrv gRPC TLS
[log]
level = "info" # debug, info, warn, error

View File

@@ -30,9 +30,10 @@ service_name = "mcr"
service_token = "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL21jaWFzLm1ldGFjaXJjdWxhci5uZXQiLCJzdWIiOiIwYWM3NDk3ZS0wZTE5LTRhOWMtYWI3Yi03YWZjMzc0ZDU3NzIiLCJleHAiOjE4MDYwMzczNzMsIm5iZiI6MTc3NDUwMTM3MywiaWF0IjoxNzc0NTAxMzczLCJqdGkiOiI1NTM0ZDU0OS1kYzY5LTRiNzctYTY5MC0xNzQ3NjE0MDUzYzEiLCJyb2xlcyI6bnVsbH0.bsnoGMrFzJJCIanGuiAvpqmlO2OssvFjYynQgiSt_TPMuLxziRuwuRIL9C_kRnHdF7C6c1mTHncKVj1hkLPiCg"
[web]
listen_addr = ":8080"
grpc_addr = "mcr:9443"
ca_cert = "/srv/mcr/certs/ca.pem"
listen_addr = ":8080"
grpc_addr = "mcr-api:9443"
tls_server_name = "mcr.svc.mcp.metacircular.net"
ca_cert = "/srv/mcr/certs/ca.pem"
[log]
level = "info"

View File

@@ -1,14 +1,97 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.32.1
// source: mcr/v1/admin.proto
package mcrv1
// HealthRequest is the request message for Health.
type HealthRequest struct{}
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type HealthRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *HealthRequest) Reset() {
*x = HealthRequest{}
mi := &file_mcr_v1_admin_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *HealthRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*HealthRequest) ProtoMessage() {}
func (x *HealthRequest) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_admin_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use HealthRequest.ProtoReflect.Descriptor instead.
func (*HealthRequest) Descriptor() ([]byte, []int) {
return file_mcr_v1_admin_proto_rawDescGZIP(), []int{0}
}
// HealthResponse is the response message for Health.
type HealthResponse struct {
Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *HealthResponse) Reset() {
*x = HealthResponse{}
mi := &file_mcr_v1_admin_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *HealthResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*HealthResponse) ProtoMessage() {}
func (x *HealthResponse) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_admin_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use HealthResponse.ProtoReflect.Descriptor instead.
func (*HealthResponse) Descriptor() ([]byte, []int) {
return file_mcr_v1_admin_proto_rawDescGZIP(), []int{1}
}
func (x *HealthResponse) GetStatus() string {
@@ -17,3 +100,65 @@ func (x *HealthResponse) GetStatus() string {
}
return ""
}
var File_mcr_v1_admin_proto protoreflect.FileDescriptor
const file_mcr_v1_admin_proto_rawDesc = "" +
"\n" +
"\x12mcr/v1/admin.proto\x12\x06mcr.v1\"\x0f\n" +
"\rHealthRequest\"(\n" +
"\x0eHealthResponse\x12\x16\n" +
"\x06status\x18\x01 \x01(\tR\x06status2G\n" +
"\fAdminService\x127\n" +
"\x06Health\x12\x15.mcr.v1.HealthRequest\x1a\x16.mcr.v1.HealthResponseB,Z*git.wntrmute.dev/mc/mcr/gen/mcr/v1;mcrv1b\x06proto3"
var (
file_mcr_v1_admin_proto_rawDescOnce sync.Once
file_mcr_v1_admin_proto_rawDescData []byte
)
func file_mcr_v1_admin_proto_rawDescGZIP() []byte {
file_mcr_v1_admin_proto_rawDescOnce.Do(func() {
file_mcr_v1_admin_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_mcr_v1_admin_proto_rawDesc), len(file_mcr_v1_admin_proto_rawDesc)))
})
return file_mcr_v1_admin_proto_rawDescData
}
var file_mcr_v1_admin_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_mcr_v1_admin_proto_goTypes = []any{
(*HealthRequest)(nil), // 0: mcr.v1.HealthRequest
(*HealthResponse)(nil), // 1: mcr.v1.HealthResponse
}
var file_mcr_v1_admin_proto_depIdxs = []int32{
0, // 0: mcr.v1.AdminService.Health:input_type -> mcr.v1.HealthRequest
1, // 1: mcr.v1.AdminService.Health:output_type -> mcr.v1.HealthResponse
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_mcr_v1_admin_proto_init() }
func file_mcr_v1_admin_proto_init() {
if File_mcr_v1_admin_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_mcr_v1_admin_proto_rawDesc), len(file_mcr_v1_admin_proto_rawDesc)),
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_mcr_v1_admin_proto_goTypes,
DependencyIndexes: file_mcr_v1_admin_proto_depIdxs,
MessageInfos: file_mcr_v1_admin_proto_msgTypes,
}.Build()
File_mcr_v1_admin_proto = out.File
file_mcr_v1_admin_proto_goTypes = nil
file_mcr_v1_admin_proto_depIdxs = nil
}

View File

@@ -1,38 +1,92 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc v6.32.1
// source: mcr/v1/admin.proto
package mcrv1
import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// AdminServiceServer is the server API for AdminService.
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
AdminService_Health_FullMethodName = "/mcr.v1.AdminService/Health"
)
// AdminServiceClient is the client API for AdminService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type AdminServiceClient interface {
Health(ctx context.Context, in *HealthRequest, opts ...grpc.CallOption) (*HealthResponse, error)
}
type adminServiceClient struct {
cc grpc.ClientConnInterface
}
func NewAdminServiceClient(cc grpc.ClientConnInterface) AdminServiceClient {
return &adminServiceClient{cc}
}
func (c *adminServiceClient) Health(ctx context.Context, in *HealthRequest, opts ...grpc.CallOption) (*HealthResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(HealthResponse)
err := c.cc.Invoke(ctx, AdminService_Health_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// AdminServiceServer is the server API for AdminService service.
// All implementations must embed UnimplementedAdminServiceServer
// for forward compatibility.
type AdminServiceServer interface {
Health(context.Context, *HealthRequest) (*HealthResponse, error)
mustEmbedUnimplementedAdminServiceServer()
}
// UnimplementedAdminServiceServer should be embedded to have forward
// compatible implementations.
// UnimplementedAdminServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedAdminServiceServer struct{}
func (UnimplementedAdminServiceServer) Health(context.Context, *HealthRequest) (*HealthResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Health not implemented")
return nil, status.Error(codes.Unimplemented, "method Health not implemented")
}
func (UnimplementedAdminServiceServer) mustEmbedUnimplementedAdminServiceServer() {}
func (UnimplementedAdminServiceServer) testEmbeddedByValue() {}
// UnsafeAdminServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to AdminServiceServer will
// result in compilation errors.
type UnsafeAdminServiceServer interface {
mustEmbedUnimplementedAdminServiceServer()
}
func (UnimplementedAdminServiceServer) mustEmbedUnimplementedAdminServiceServer() {}
// RegisterAdminServiceServer registers the AdminServiceServer with the grpc.Server.
func RegisterAdminServiceServer(s grpc.ServiceRegistrar, srv AdminServiceServer) {
// If the following call panics, it indicates UnimplementedAdminServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&AdminService_ServiceDesc, srv)
}
func adminServiceHealthHandler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
func _AdminService_Health_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(HealthRequest)
if err := dec(in); err != nil {
return nil, err
@@ -42,47 +96,26 @@ func adminServiceHealthHandler(srv any, ctx context.Context, dec func(any) error
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/mcr.v1.AdminService/Health",
FullMethod: AdminService_Health_FullMethodName,
}
handler := func(ctx context.Context, req any) (any, error) {
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AdminServiceServer).Health(ctx, req.(*HealthRequest))
}
return interceptor(ctx, in, info, handler)
}
// AdminService_ServiceDesc is the grpc.ServiceDesc for AdminService.
// AdminService_ServiceDesc is the grpc.ServiceDesc for AdminService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var AdminService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "mcr.v1.AdminService",
HandlerType: (*AdminServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Health",
Handler: adminServiceHealthHandler,
Handler: _AdminService_Health_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "mcr/v1/admin.proto",
}
// AdminServiceClient is the client API for AdminService.
type AdminServiceClient interface {
Health(ctx context.Context, in *HealthRequest, opts ...grpc.CallOption) (*HealthResponse, error)
}
type adminServiceClient struct {
cc grpc.ClientConnInterface
}
// NewAdminServiceClient creates a new AdminServiceClient.
func NewAdminServiceClient(cc grpc.ClientConnInterface) AdminServiceClient {
return &adminServiceClient{cc}
}
func (c *adminServiceClient) Health(ctx context.Context, in *HealthRequest, opts ...grpc.CallOption) (*HealthResponse, error) {
out := new(HealthResponse)
err := c.cc.Invoke(ctx, "/mcr.v1.AdminService/Health", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}

View File

@@ -1,18 +1,68 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.32.1
// source: mcr/v1/audit.proto
package mcrv1
// AuditEvent represents an audit log entry.
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type AuditEvent struct {
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` //nolint:revive,stylecheck // proto field name
EventTime string `protobuf:"bytes,2,opt,name=event_time,json=eventTime,proto3" json:"event_time,omitempty"`
EventType string `protobuf:"bytes,3,opt,name=event_type,json=eventType,proto3" json:"event_type,omitempty"`
ActorId string `protobuf:"bytes,4,opt,name=actor_id,json=actorId,proto3" json:"actor_id,omitempty"` //nolint:revive,stylecheck // proto field name
Repository string `protobuf:"bytes,5,opt,name=repository,proto3" json:"repository,omitempty"`
Digest string `protobuf:"bytes,6,opt,name=digest,proto3" json:"digest,omitempty"`
IpAddress string `protobuf:"bytes,7,opt,name=ip_address,json=ipAddress,proto3" json:"ip_address,omitempty"` //nolint:revive,stylecheck // proto field name
Details map[string]string `protobuf:"bytes,8,rep,name=details,proto3" json:"details,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
EventTime string `protobuf:"bytes,2,opt,name=event_time,json=eventTime,proto3" json:"event_time,omitempty"`
EventType string `protobuf:"bytes,3,opt,name=event_type,json=eventType,proto3" json:"event_type,omitempty"`
ActorId string `protobuf:"bytes,4,opt,name=actor_id,json=actorId,proto3" json:"actor_id,omitempty"`
Repository string `protobuf:"bytes,5,opt,name=repository,proto3" json:"repository,omitempty"`
Digest string `protobuf:"bytes,6,opt,name=digest,proto3" json:"digest,omitempty"`
IpAddress string `protobuf:"bytes,7,opt,name=ip_address,json=ipAddress,proto3" json:"ip_address,omitempty"`
Details map[string]string `protobuf:"bytes,8,rep,name=details,proto3" json:"details,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AuditEvent) Reset() {
*x = AuditEvent{}
mi := &file_mcr_v1_audit_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AuditEvent) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AuditEvent) ProtoMessage() {}
func (x *AuditEvent) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_audit_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AuditEvent.ProtoReflect.Descriptor instead.
func (*AuditEvent) Descriptor() ([]byte, []int) {
return file_mcr_v1_audit_proto_rawDescGZIP(), []int{0}
}
func (x *AuditEvent) GetId() int64 {
@@ -71,14 +121,46 @@ func (x *AuditEvent) GetDetails() map[string]string {
return nil
}
// ListAuditEventsRequest is the request message for ListAuditEvents.
type ListAuditEventsRequest struct {
Pagination *PaginationRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"`
EventType string `protobuf:"bytes,2,opt,name=event_type,json=eventType,proto3" json:"event_type,omitempty"`
ActorId string `protobuf:"bytes,3,opt,name=actor_id,json=actorId,proto3" json:"actor_id,omitempty"` //nolint:revive,stylecheck // proto field name
Repository string `protobuf:"bytes,4,opt,name=repository,proto3" json:"repository,omitempty"`
Since string `protobuf:"bytes,5,opt,name=since,proto3" json:"since,omitempty"`
Until string `protobuf:"bytes,6,opt,name=until,proto3" json:"until,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Pagination *PaginationRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"`
EventType string `protobuf:"bytes,2,opt,name=event_type,json=eventType,proto3" json:"event_type,omitempty"`
ActorId string `protobuf:"bytes,3,opt,name=actor_id,json=actorId,proto3" json:"actor_id,omitempty"`
Repository string `protobuf:"bytes,4,opt,name=repository,proto3" json:"repository,omitempty"`
Since string `protobuf:"bytes,5,opt,name=since,proto3" json:"since,omitempty"`
Until string `protobuf:"bytes,6,opt,name=until,proto3" json:"until,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListAuditEventsRequest) Reset() {
*x = ListAuditEventsRequest{}
mi := &file_mcr_v1_audit_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListAuditEventsRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListAuditEventsRequest) ProtoMessage() {}
func (x *ListAuditEventsRequest) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_audit_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListAuditEventsRequest.ProtoReflect.Descriptor instead.
func (*ListAuditEventsRequest) Descriptor() ([]byte, []int) {
return file_mcr_v1_audit_proto_rawDescGZIP(), []int{1}
}
func (x *ListAuditEventsRequest) GetPagination() *PaginationRequest {
@@ -123,9 +205,41 @@ func (x *ListAuditEventsRequest) GetUntil() string {
return ""
}
// ListAuditEventsResponse is the response message for ListAuditEvents.
type ListAuditEventsResponse struct {
Events []*AuditEvent `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Events []*AuditEvent `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListAuditEventsResponse) Reset() {
*x = ListAuditEventsResponse{}
mi := &file_mcr_v1_audit_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListAuditEventsResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListAuditEventsResponse) ProtoMessage() {}
func (x *ListAuditEventsResponse) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_audit_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListAuditEventsResponse.ProtoReflect.Descriptor instead.
func (*ListAuditEventsResponse) Descriptor() ([]byte, []int) {
return file_mcr_v1_audit_proto_rawDescGZIP(), []int{2}
}
func (x *ListAuditEventsResponse) GetEvents() []*AuditEvent {
@@ -134,3 +248,101 @@ func (x *ListAuditEventsResponse) GetEvents() []*AuditEvent {
}
return nil
}
var File_mcr_v1_audit_proto protoreflect.FileDescriptor
const file_mcr_v1_audit_proto_rawDesc = "" +
"\n" +
"\x12mcr/v1/audit.proto\x12\x06mcr.v1\x1a\x13mcr/v1/common.proto\"\xc3\x02\n" +
"\n" +
"AuditEvent\x12\x0e\n" +
"\x02id\x18\x01 \x01(\x03R\x02id\x12\x1d\n" +
"\n" +
"event_time\x18\x02 \x01(\tR\teventTime\x12\x1d\n" +
"\n" +
"event_type\x18\x03 \x01(\tR\teventType\x12\x19\n" +
"\bactor_id\x18\x04 \x01(\tR\aactorId\x12\x1e\n" +
"\n" +
"repository\x18\x05 \x01(\tR\n" +
"repository\x12\x16\n" +
"\x06digest\x18\x06 \x01(\tR\x06digest\x12\x1d\n" +
"\n" +
"ip_address\x18\a \x01(\tR\tipAddress\x129\n" +
"\adetails\x18\b \x03(\v2\x1f.mcr.v1.AuditEvent.DetailsEntryR\adetails\x1a:\n" +
"\fDetailsEntry\x12\x10\n" +
"\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xd9\x01\n" +
"\x16ListAuditEventsRequest\x129\n" +
"\n" +
"pagination\x18\x01 \x01(\v2\x19.mcr.v1.PaginationRequestR\n" +
"pagination\x12\x1d\n" +
"\n" +
"event_type\x18\x02 \x01(\tR\teventType\x12\x19\n" +
"\bactor_id\x18\x03 \x01(\tR\aactorId\x12\x1e\n" +
"\n" +
"repository\x18\x04 \x01(\tR\n" +
"repository\x12\x14\n" +
"\x05since\x18\x05 \x01(\tR\x05since\x12\x14\n" +
"\x05until\x18\x06 \x01(\tR\x05until\"E\n" +
"\x17ListAuditEventsResponse\x12*\n" +
"\x06events\x18\x01 \x03(\v2\x12.mcr.v1.AuditEventR\x06events2b\n" +
"\fAuditService\x12R\n" +
"\x0fListAuditEvents\x12\x1e.mcr.v1.ListAuditEventsRequest\x1a\x1f.mcr.v1.ListAuditEventsResponseB,Z*git.wntrmute.dev/mc/mcr/gen/mcr/v1;mcrv1b\x06proto3"
var (
file_mcr_v1_audit_proto_rawDescOnce sync.Once
file_mcr_v1_audit_proto_rawDescData []byte
)
func file_mcr_v1_audit_proto_rawDescGZIP() []byte {
file_mcr_v1_audit_proto_rawDescOnce.Do(func() {
file_mcr_v1_audit_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_mcr_v1_audit_proto_rawDesc), len(file_mcr_v1_audit_proto_rawDesc)))
})
return file_mcr_v1_audit_proto_rawDescData
}
var file_mcr_v1_audit_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_mcr_v1_audit_proto_goTypes = []any{
(*AuditEvent)(nil), // 0: mcr.v1.AuditEvent
(*ListAuditEventsRequest)(nil), // 1: mcr.v1.ListAuditEventsRequest
(*ListAuditEventsResponse)(nil), // 2: mcr.v1.ListAuditEventsResponse
nil, // 3: mcr.v1.AuditEvent.DetailsEntry
(*PaginationRequest)(nil), // 4: mcr.v1.PaginationRequest
}
var file_mcr_v1_audit_proto_depIdxs = []int32{
3, // 0: mcr.v1.AuditEvent.details:type_name -> mcr.v1.AuditEvent.DetailsEntry
4, // 1: mcr.v1.ListAuditEventsRequest.pagination:type_name -> mcr.v1.PaginationRequest
0, // 2: mcr.v1.ListAuditEventsResponse.events:type_name -> mcr.v1.AuditEvent
1, // 3: mcr.v1.AuditService.ListAuditEvents:input_type -> mcr.v1.ListAuditEventsRequest
2, // 4: mcr.v1.AuditService.ListAuditEvents:output_type -> mcr.v1.ListAuditEventsResponse
4, // [4:5] is the sub-list for method output_type
3, // [3:4] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name
3, // [3:3] is the sub-list for extension extendee
0, // [0:3] is the sub-list for field type_name
}
func init() { file_mcr_v1_audit_proto_init() }
func file_mcr_v1_audit_proto_init() {
if File_mcr_v1_audit_proto != nil {
return
}
file_mcr_v1_common_proto_init()
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_mcr_v1_audit_proto_rawDesc), len(file_mcr_v1_audit_proto_rawDesc)),
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_mcr_v1_audit_proto_goTypes,
DependencyIndexes: file_mcr_v1_audit_proto_depIdxs,
MessageInfos: file_mcr_v1_audit_proto_msgTypes,
}.Build()
File_mcr_v1_audit_proto = out.File
file_mcr_v1_audit_proto_goTypes = nil
file_mcr_v1_audit_proto_depIdxs = nil
}

View File

@@ -1,38 +1,92 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc v6.32.1
// source: mcr/v1/audit.proto
package mcrv1
import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// AuditServiceServer is the server API for AuditService.
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
AuditService_ListAuditEvents_FullMethodName = "/mcr.v1.AuditService/ListAuditEvents"
)
// AuditServiceClient is the client API for AuditService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type AuditServiceClient interface {
ListAuditEvents(ctx context.Context, in *ListAuditEventsRequest, opts ...grpc.CallOption) (*ListAuditEventsResponse, error)
}
type auditServiceClient struct {
cc grpc.ClientConnInterface
}
func NewAuditServiceClient(cc grpc.ClientConnInterface) AuditServiceClient {
return &auditServiceClient{cc}
}
func (c *auditServiceClient) ListAuditEvents(ctx context.Context, in *ListAuditEventsRequest, opts ...grpc.CallOption) (*ListAuditEventsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListAuditEventsResponse)
err := c.cc.Invoke(ctx, AuditService_ListAuditEvents_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// AuditServiceServer is the server API for AuditService service.
// All implementations must embed UnimplementedAuditServiceServer
// for forward compatibility.
type AuditServiceServer interface {
ListAuditEvents(context.Context, *ListAuditEventsRequest) (*ListAuditEventsResponse, error)
mustEmbedUnimplementedAuditServiceServer()
}
// UnimplementedAuditServiceServer should be embedded to have forward
// compatible implementations.
// UnimplementedAuditServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedAuditServiceServer struct{}
func (UnimplementedAuditServiceServer) ListAuditEvents(context.Context, *ListAuditEventsRequest) (*ListAuditEventsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListAuditEvents not implemented")
return nil, status.Error(codes.Unimplemented, "method ListAuditEvents not implemented")
}
func (UnimplementedAuditServiceServer) mustEmbedUnimplementedAuditServiceServer() {}
func (UnimplementedAuditServiceServer) testEmbeddedByValue() {}
// UnsafeAuditServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to AuditServiceServer will
// result in compilation errors.
type UnsafeAuditServiceServer interface {
mustEmbedUnimplementedAuditServiceServer()
}
func (UnimplementedAuditServiceServer) mustEmbedUnimplementedAuditServiceServer() {}
// RegisterAuditServiceServer registers the AuditServiceServer with the grpc.Server.
func RegisterAuditServiceServer(s grpc.ServiceRegistrar, srv AuditServiceServer) {
// If the following call panics, it indicates UnimplementedAuditServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&AuditService_ServiceDesc, srv)
}
func auditServiceListAuditEventsHandler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
func _AuditService_ListAuditEvents_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListAuditEventsRequest)
if err := dec(in); err != nil {
return nil, err
@@ -42,47 +96,26 @@ func auditServiceListAuditEventsHandler(srv any, ctx context.Context, dec func(a
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/mcr.v1.AuditService/ListAuditEvents",
FullMethod: AuditService_ListAuditEvents_FullMethodName,
}
handler := func(ctx context.Context, req any) (any, error) {
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuditServiceServer).ListAuditEvents(ctx, req.(*ListAuditEventsRequest))
}
return interceptor(ctx, in, info, handler)
}
// AuditService_ServiceDesc is the grpc.ServiceDesc for AuditService.
// AuditService_ServiceDesc is the grpc.ServiceDesc for AuditService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var AuditService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "mcr.v1.AuditService",
HandlerType: (*AuditServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "ListAuditEvents",
Handler: auditServiceListAuditEventsHandler,
Handler: _AuditService_ListAuditEvents_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "mcr/v1/audit.proto",
}
// AuditServiceClient is the client API for AuditService.
type AuditServiceClient interface {
ListAuditEvents(ctx context.Context, in *ListAuditEventsRequest, opts ...grpc.CallOption) (*ListAuditEventsResponse, error)
}
type auditServiceClient struct {
cc grpc.ClientConnInterface
}
// NewAuditServiceClient creates a new AuditServiceClient.
func NewAuditServiceClient(cc grpc.ClientConnInterface) AuditServiceClient {
return &auditServiceClient{cc}
}
func (c *auditServiceClient) ListAuditEvents(ctx context.Context, in *ListAuditEventsRequest, opts ...grpc.CallOption) (*ListAuditEventsResponse, error) {
out := new(ListAuditEventsResponse)
err := c.cc.Invoke(ctx, "/mcr.v1.AuditService/ListAuditEvents", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}

View File

@@ -1,12 +1,63 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.32.1
// source: mcr/v1/common.proto
package mcrv1
// PaginationRequest controls pagination for list RPCs.
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// Pagination controls for list RPCs.
type PaginationRequest struct {
Limit int32 `protobuf:"varint,1,opt,name=limit,proto3" json:"limit,omitempty"`
Offset int32 `protobuf:"varint,2,opt,name=offset,proto3" json:"offset,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Limit int32 `protobuf:"varint,1,opt,name=limit,proto3" json:"limit,omitempty"`
Offset int32 `protobuf:"varint,2,opt,name=offset,proto3" json:"offset,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *PaginationRequest) Reset() {
*x = PaginationRequest{}
mi := &file_mcr_v1_common_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *PaginationRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PaginationRequest) ProtoMessage() {}
func (x *PaginationRequest) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_common_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PaginationRequest.ProtoReflect.Descriptor instead.
func (*PaginationRequest) Descriptor() ([]byte, []int) {
return file_mcr_v1_common_proto_rawDescGZIP(), []int{0}
}
func (x *PaginationRequest) GetLimit() int32 {
@@ -22,3 +73,60 @@ func (x *PaginationRequest) GetOffset() int32 {
}
return 0
}
var File_mcr_v1_common_proto protoreflect.FileDescriptor
const file_mcr_v1_common_proto_rawDesc = "" +
"\n" +
"\x13mcr/v1/common.proto\x12\x06mcr.v1\"A\n" +
"\x11PaginationRequest\x12\x14\n" +
"\x05limit\x18\x01 \x01(\x05R\x05limit\x12\x16\n" +
"\x06offset\x18\x02 \x01(\x05R\x06offsetB,Z*git.wntrmute.dev/mc/mcr/gen/mcr/v1;mcrv1b\x06proto3"
var (
file_mcr_v1_common_proto_rawDescOnce sync.Once
file_mcr_v1_common_proto_rawDescData []byte
)
func file_mcr_v1_common_proto_rawDescGZIP() []byte {
file_mcr_v1_common_proto_rawDescOnce.Do(func() {
file_mcr_v1_common_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_mcr_v1_common_proto_rawDesc), len(file_mcr_v1_common_proto_rawDesc)))
})
return file_mcr_v1_common_proto_rawDescData
}
var file_mcr_v1_common_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_mcr_v1_common_proto_goTypes = []any{
(*PaginationRequest)(nil), // 0: mcr.v1.PaginationRequest
}
var file_mcr_v1_common_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_mcr_v1_common_proto_init() }
func file_mcr_v1_common_proto_init() {
if File_mcr_v1_common_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_mcr_v1_common_proto_rawDesc), len(file_mcr_v1_common_proto_rawDesc)),
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_mcr_v1_common_proto_goTypes,
DependencyIndexes: file_mcr_v1_common_proto_depIdxs,
MessageInfos: file_mcr_v1_common_proto_msgTypes,
}.Build()
File_mcr_v1_common_proto = out.File
file_mcr_v1_common_proto_goTypes = nil
file_mcr_v1_common_proto_depIdxs = nil
}

View File

@@ -1,23 +1,73 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.32.1
// source: mcr/v1/policy.proto
package mcrv1
// PolicyRule represents a policy rule.
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type PolicyRule struct {
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` //nolint:revive,stylecheck // proto field name
Priority int32 `protobuf:"varint,2,opt,name=priority,proto3" json:"priority,omitempty"`
Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
Effect string `protobuf:"bytes,4,opt,name=effect,proto3" json:"effect,omitempty"`
Roles []string `protobuf:"bytes,5,rep,name=roles,proto3" json:"roles,omitempty"`
AccountTypes []string `protobuf:"bytes,6,rep,name=account_types,json=accountTypes,proto3" json:"account_types,omitempty"`
SubjectUuid string `protobuf:"bytes,7,opt,name=subject_uuid,json=subjectUuid,proto3" json:"subject_uuid,omitempty"` //nolint:revive,stylecheck // proto field name
Actions []string `protobuf:"bytes,8,rep,name=actions,proto3" json:"actions,omitempty"`
Repositories []string `protobuf:"bytes,9,rep,name=repositories,proto3" json:"repositories,omitempty"`
Enabled bool `protobuf:"varint,10,opt,name=enabled,proto3" json:"enabled,omitempty"`
CreatedBy string `protobuf:"bytes,11,opt,name=created_by,json=createdBy,proto3" json:"created_by,omitempty"`
CreatedAt string `protobuf:"bytes,12,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
UpdatedAt string `protobuf:"bytes,13,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
Priority int32 `protobuf:"varint,2,opt,name=priority,proto3" json:"priority,omitempty"`
Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
Effect string `protobuf:"bytes,4,opt,name=effect,proto3" json:"effect,omitempty"`
Roles []string `protobuf:"bytes,5,rep,name=roles,proto3" json:"roles,omitempty"`
AccountTypes []string `protobuf:"bytes,6,rep,name=account_types,json=accountTypes,proto3" json:"account_types,omitempty"`
SubjectUuid string `protobuf:"bytes,7,opt,name=subject_uuid,json=subjectUuid,proto3" json:"subject_uuid,omitempty"`
Actions []string `protobuf:"bytes,8,rep,name=actions,proto3" json:"actions,omitempty"`
Repositories []string `protobuf:"bytes,9,rep,name=repositories,proto3" json:"repositories,omitempty"`
Enabled bool `protobuf:"varint,10,opt,name=enabled,proto3" json:"enabled,omitempty"`
CreatedBy string `protobuf:"bytes,11,opt,name=created_by,json=createdBy,proto3" json:"created_by,omitempty"`
CreatedAt string `protobuf:"bytes,12,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
UpdatedAt string `protobuf:"bytes,13,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *PolicyRule) Reset() {
*x = PolicyRule{}
mi := &file_mcr_v1_policy_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *PolicyRule) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PolicyRule) ProtoMessage() {}
func (x *PolicyRule) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_policy_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PolicyRule.ProtoReflect.Descriptor instead.
func (*PolicyRule) Descriptor() ([]byte, []int) {
return file_mcr_v1_policy_proto_rawDescGZIP(), []int{0}
}
func (x *PolicyRule) GetId() int64 {
@@ -111,9 +161,41 @@ func (x *PolicyRule) GetUpdatedAt() string {
return ""
}
// ListPolicyRulesRequest is the request message for ListPolicyRules.
type ListPolicyRulesRequest struct {
Pagination *PaginationRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Pagination *PaginationRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListPolicyRulesRequest) Reset() {
*x = ListPolicyRulesRequest{}
mi := &file_mcr_v1_policy_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListPolicyRulesRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListPolicyRulesRequest) ProtoMessage() {}
func (x *ListPolicyRulesRequest) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_policy_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListPolicyRulesRequest.ProtoReflect.Descriptor instead.
func (*ListPolicyRulesRequest) Descriptor() ([]byte, []int) {
return file_mcr_v1_policy_proto_rawDescGZIP(), []int{1}
}
func (x *ListPolicyRulesRequest) GetPagination() *PaginationRequest {
@@ -123,9 +205,41 @@ func (x *ListPolicyRulesRequest) GetPagination() *PaginationRequest {
return nil
}
// ListPolicyRulesResponse is the response message for ListPolicyRules.
type ListPolicyRulesResponse struct {
Rules []*PolicyRule `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Rules []*PolicyRule `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListPolicyRulesResponse) Reset() {
*x = ListPolicyRulesResponse{}
mi := &file_mcr_v1_policy_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListPolicyRulesResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListPolicyRulesResponse) ProtoMessage() {}
func (x *ListPolicyRulesResponse) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_policy_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListPolicyRulesResponse.ProtoReflect.Descriptor instead.
func (*ListPolicyRulesResponse) Descriptor() ([]byte, []int) {
return file_mcr_v1_policy_proto_rawDescGZIP(), []int{2}
}
func (x *ListPolicyRulesResponse) GetRules() []*PolicyRule {
@@ -135,17 +249,49 @@ func (x *ListPolicyRulesResponse) GetRules() []*PolicyRule {
return nil
}
// CreatePolicyRuleRequest is the request message for CreatePolicyRule.
type CreatePolicyRuleRequest struct {
Priority int32 `protobuf:"varint,1,opt,name=priority,proto3" json:"priority,omitempty"`
Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
Effect string `protobuf:"bytes,3,opt,name=effect,proto3" json:"effect,omitempty"`
Roles []string `protobuf:"bytes,4,rep,name=roles,proto3" json:"roles,omitempty"`
AccountTypes []string `protobuf:"bytes,5,rep,name=account_types,json=accountTypes,proto3" json:"account_types,omitempty"`
SubjectUuid string `protobuf:"bytes,6,opt,name=subject_uuid,json=subjectUuid,proto3" json:"subject_uuid,omitempty"` //nolint:revive,stylecheck // proto field name
Actions []string `protobuf:"bytes,7,rep,name=actions,proto3" json:"actions,omitempty"`
Repositories []string `protobuf:"bytes,8,rep,name=repositories,proto3" json:"repositories,omitempty"`
Enabled bool `protobuf:"varint,9,opt,name=enabled,proto3" json:"enabled,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Priority int32 `protobuf:"varint,1,opt,name=priority,proto3" json:"priority,omitempty"`
Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
Effect string `protobuf:"bytes,3,opt,name=effect,proto3" json:"effect,omitempty"`
Roles []string `protobuf:"bytes,4,rep,name=roles,proto3" json:"roles,omitempty"`
AccountTypes []string `protobuf:"bytes,5,rep,name=account_types,json=accountTypes,proto3" json:"account_types,omitempty"`
SubjectUuid string `protobuf:"bytes,6,opt,name=subject_uuid,json=subjectUuid,proto3" json:"subject_uuid,omitempty"`
Actions []string `protobuf:"bytes,7,rep,name=actions,proto3" json:"actions,omitempty"`
Repositories []string `protobuf:"bytes,8,rep,name=repositories,proto3" json:"repositories,omitempty"`
Enabled bool `protobuf:"varint,9,opt,name=enabled,proto3" json:"enabled,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CreatePolicyRuleRequest) Reset() {
*x = CreatePolicyRuleRequest{}
mi := &file_mcr_v1_policy_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CreatePolicyRuleRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreatePolicyRuleRequest) ProtoMessage() {}
func (x *CreatePolicyRuleRequest) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_policy_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CreatePolicyRuleRequest.ProtoReflect.Descriptor instead.
func (*CreatePolicyRuleRequest) Descriptor() ([]byte, []int) {
return file_mcr_v1_policy_proto_rawDescGZIP(), []int{3}
}
func (x *CreatePolicyRuleRequest) GetPriority() int32 {
@@ -211,9 +357,41 @@ func (x *CreatePolicyRuleRequest) GetEnabled() bool {
return false
}
// GetPolicyRuleRequest is the request message for GetPolicyRule.
type GetPolicyRuleRequest struct {
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` //nolint:revive,stylecheck // proto field name
state protoimpl.MessageState `protogen:"open.v1"`
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetPolicyRuleRequest) Reset() {
*x = GetPolicyRuleRequest{}
mi := &file_mcr_v1_policy_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetPolicyRuleRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetPolicyRuleRequest) ProtoMessage() {}
func (x *GetPolicyRuleRequest) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_policy_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetPolicyRuleRequest.ProtoReflect.Descriptor instead.
func (*GetPolicyRuleRequest) Descriptor() ([]byte, []int) {
return file_mcr_v1_policy_proto_rawDescGZIP(), []int{4}
}
func (x *GetPolicyRuleRequest) GetId() int64 {
@@ -223,19 +401,52 @@ func (x *GetPolicyRuleRequest) GetId() int64 {
return 0
}
// UpdatePolicyRuleRequest is the request message for UpdatePolicyRule.
type UpdatePolicyRuleRequest struct {
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` //nolint:revive,stylecheck // proto field name
Priority int32 `protobuf:"varint,2,opt,name=priority,proto3" json:"priority,omitempty"`
Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
Effect string `protobuf:"bytes,4,opt,name=effect,proto3" json:"effect,omitempty"`
Roles []string `protobuf:"bytes,5,rep,name=roles,proto3" json:"roles,omitempty"`
AccountTypes []string `protobuf:"bytes,6,rep,name=account_types,json=accountTypes,proto3" json:"account_types,omitempty"`
SubjectUuid string `protobuf:"bytes,7,opt,name=subject_uuid,json=subjectUuid,proto3" json:"subject_uuid,omitempty"` //nolint:revive,stylecheck // proto field name
Actions []string `protobuf:"bytes,8,rep,name=actions,proto3" json:"actions,omitempty"`
Repositories []string `protobuf:"bytes,9,rep,name=repositories,proto3" json:"repositories,omitempty"`
Enabled bool `protobuf:"varint,10,opt,name=enabled,proto3" json:"enabled,omitempty"`
UpdateMask []string `protobuf:"bytes,11,rep,name=update_mask,json=updateMask,proto3" json:"update_mask,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
Priority int32 `protobuf:"varint,2,opt,name=priority,proto3" json:"priority,omitempty"`
Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
Effect string `protobuf:"bytes,4,opt,name=effect,proto3" json:"effect,omitempty"`
Roles []string `protobuf:"bytes,5,rep,name=roles,proto3" json:"roles,omitempty"`
AccountTypes []string `protobuf:"bytes,6,rep,name=account_types,json=accountTypes,proto3" json:"account_types,omitempty"`
SubjectUuid string `protobuf:"bytes,7,opt,name=subject_uuid,json=subjectUuid,proto3" json:"subject_uuid,omitempty"`
Actions []string `protobuf:"bytes,8,rep,name=actions,proto3" json:"actions,omitempty"`
Repositories []string `protobuf:"bytes,9,rep,name=repositories,proto3" json:"repositories,omitempty"`
Enabled bool `protobuf:"varint,10,opt,name=enabled,proto3" json:"enabled,omitempty"`
// Field mask for partial updates — only fields listed here are applied.
UpdateMask []string `protobuf:"bytes,11,rep,name=update_mask,json=updateMask,proto3" json:"update_mask,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UpdatePolicyRuleRequest) Reset() {
*x = UpdatePolicyRuleRequest{}
mi := &file_mcr_v1_policy_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UpdatePolicyRuleRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UpdatePolicyRuleRequest) ProtoMessage() {}
func (x *UpdatePolicyRuleRequest) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_policy_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UpdatePolicyRuleRequest.ProtoReflect.Descriptor instead.
func (*UpdatePolicyRuleRequest) Descriptor() ([]byte, []int) {
return file_mcr_v1_policy_proto_rawDescGZIP(), []int{5}
}
func (x *UpdatePolicyRuleRequest) GetId() int64 {
@@ -315,9 +526,41 @@ func (x *UpdatePolicyRuleRequest) GetUpdateMask() []string {
return nil
}
// DeletePolicyRuleRequest is the request message for DeletePolicyRule.
type DeletePolicyRuleRequest struct {
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` //nolint:revive,stylecheck // proto field name
state protoimpl.MessageState `protogen:"open.v1"`
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeletePolicyRuleRequest) Reset() {
*x = DeletePolicyRuleRequest{}
mi := &file_mcr_v1_policy_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeletePolicyRuleRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeletePolicyRuleRequest) ProtoMessage() {}
func (x *DeletePolicyRuleRequest) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_policy_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeletePolicyRuleRequest.ProtoReflect.Descriptor instead.
func (*DeletePolicyRuleRequest) Descriptor() ([]byte, []int) {
return file_mcr_v1_policy_proto_rawDescGZIP(), []int{6}
}
func (x *DeletePolicyRuleRequest) GetId() int64 {
@@ -327,5 +570,173 @@ func (x *DeletePolicyRuleRequest) GetId() int64 {
return 0
}
// DeletePolicyRuleResponse is the response message for DeletePolicyRule.
type DeletePolicyRuleResponse struct{}
type DeletePolicyRuleResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeletePolicyRuleResponse) Reset() {
*x = DeletePolicyRuleResponse{}
mi := &file_mcr_v1_policy_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeletePolicyRuleResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeletePolicyRuleResponse) ProtoMessage() {}
func (x *DeletePolicyRuleResponse) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_policy_proto_msgTypes[7]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeletePolicyRuleResponse.ProtoReflect.Descriptor instead.
func (*DeletePolicyRuleResponse) Descriptor() ([]byte, []int) {
return file_mcr_v1_policy_proto_rawDescGZIP(), []int{7}
}
var File_mcr_v1_policy_proto protoreflect.FileDescriptor
const file_mcr_v1_policy_proto_rawDesc = "" +
"\n" +
"\x13mcr/v1/policy.proto\x12\x06mcr.v1\x1a\x13mcr/v1/common.proto\"\x85\x03\n" +
"\n" +
"PolicyRule\x12\x0e\n" +
"\x02id\x18\x01 \x01(\x03R\x02id\x12\x1a\n" +
"\bpriority\x18\x02 \x01(\x05R\bpriority\x12 \n" +
"\vdescription\x18\x03 \x01(\tR\vdescription\x12\x16\n" +
"\x06effect\x18\x04 \x01(\tR\x06effect\x12\x14\n" +
"\x05roles\x18\x05 \x03(\tR\x05roles\x12#\n" +
"\raccount_types\x18\x06 \x03(\tR\faccountTypes\x12!\n" +
"\fsubject_uuid\x18\a \x01(\tR\vsubjectUuid\x12\x18\n" +
"\aactions\x18\b \x03(\tR\aactions\x12\"\n" +
"\frepositories\x18\t \x03(\tR\frepositories\x12\x18\n" +
"\aenabled\x18\n" +
" \x01(\bR\aenabled\x12\x1d\n" +
"\n" +
"created_by\x18\v \x01(\tR\tcreatedBy\x12\x1d\n" +
"\n" +
"created_at\x18\f \x01(\tR\tcreatedAt\x12\x1d\n" +
"\n" +
"updated_at\x18\r \x01(\tR\tupdatedAt\"S\n" +
"\x16ListPolicyRulesRequest\x129\n" +
"\n" +
"pagination\x18\x01 \x01(\v2\x19.mcr.v1.PaginationRequestR\n" +
"pagination\"C\n" +
"\x17ListPolicyRulesResponse\x12(\n" +
"\x05rules\x18\x01 \x03(\v2\x12.mcr.v1.PolicyRuleR\x05rules\"\xa5\x02\n" +
"\x17CreatePolicyRuleRequest\x12\x1a\n" +
"\bpriority\x18\x01 \x01(\x05R\bpriority\x12 \n" +
"\vdescription\x18\x02 \x01(\tR\vdescription\x12\x16\n" +
"\x06effect\x18\x03 \x01(\tR\x06effect\x12\x14\n" +
"\x05roles\x18\x04 \x03(\tR\x05roles\x12#\n" +
"\raccount_types\x18\x05 \x03(\tR\faccountTypes\x12!\n" +
"\fsubject_uuid\x18\x06 \x01(\tR\vsubjectUuid\x12\x18\n" +
"\aactions\x18\a \x03(\tR\aactions\x12\"\n" +
"\frepositories\x18\b \x03(\tR\frepositories\x12\x18\n" +
"\aenabled\x18\t \x01(\bR\aenabled\"&\n" +
"\x14GetPolicyRuleRequest\x12\x0e\n" +
"\x02id\x18\x01 \x01(\x03R\x02id\"\xd6\x02\n" +
"\x17UpdatePolicyRuleRequest\x12\x0e\n" +
"\x02id\x18\x01 \x01(\x03R\x02id\x12\x1a\n" +
"\bpriority\x18\x02 \x01(\x05R\bpriority\x12 \n" +
"\vdescription\x18\x03 \x01(\tR\vdescription\x12\x16\n" +
"\x06effect\x18\x04 \x01(\tR\x06effect\x12\x14\n" +
"\x05roles\x18\x05 \x03(\tR\x05roles\x12#\n" +
"\raccount_types\x18\x06 \x03(\tR\faccountTypes\x12!\n" +
"\fsubject_uuid\x18\a \x01(\tR\vsubjectUuid\x12\x18\n" +
"\aactions\x18\b \x03(\tR\aactions\x12\"\n" +
"\frepositories\x18\t \x03(\tR\frepositories\x12\x18\n" +
"\aenabled\x18\n" +
" \x01(\bR\aenabled\x12\x1f\n" +
"\vupdate_mask\x18\v \x03(\tR\n" +
"updateMask\")\n" +
"\x17DeletePolicyRuleRequest\x12\x0e\n" +
"\x02id\x18\x01 \x01(\x03R\x02id\"\x1a\n" +
"\x18DeletePolicyRuleResponse2\x8f\x03\n" +
"\rPolicyService\x12R\n" +
"\x0fListPolicyRules\x12\x1e.mcr.v1.ListPolicyRulesRequest\x1a\x1f.mcr.v1.ListPolicyRulesResponse\x12G\n" +
"\x10CreatePolicyRule\x12\x1f.mcr.v1.CreatePolicyRuleRequest\x1a\x12.mcr.v1.PolicyRule\x12A\n" +
"\rGetPolicyRule\x12\x1c.mcr.v1.GetPolicyRuleRequest\x1a\x12.mcr.v1.PolicyRule\x12G\n" +
"\x10UpdatePolicyRule\x12\x1f.mcr.v1.UpdatePolicyRuleRequest\x1a\x12.mcr.v1.PolicyRule\x12U\n" +
"\x10DeletePolicyRule\x12\x1f.mcr.v1.DeletePolicyRuleRequest\x1a .mcr.v1.DeletePolicyRuleResponseB,Z*git.wntrmute.dev/mc/mcr/gen/mcr/v1;mcrv1b\x06proto3"
var (
file_mcr_v1_policy_proto_rawDescOnce sync.Once
file_mcr_v1_policy_proto_rawDescData []byte
)
func file_mcr_v1_policy_proto_rawDescGZIP() []byte {
file_mcr_v1_policy_proto_rawDescOnce.Do(func() {
file_mcr_v1_policy_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_mcr_v1_policy_proto_rawDesc), len(file_mcr_v1_policy_proto_rawDesc)))
})
return file_mcr_v1_policy_proto_rawDescData
}
var file_mcr_v1_policy_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_mcr_v1_policy_proto_goTypes = []any{
(*PolicyRule)(nil), // 0: mcr.v1.PolicyRule
(*ListPolicyRulesRequest)(nil), // 1: mcr.v1.ListPolicyRulesRequest
(*ListPolicyRulesResponse)(nil), // 2: mcr.v1.ListPolicyRulesResponse
(*CreatePolicyRuleRequest)(nil), // 3: mcr.v1.CreatePolicyRuleRequest
(*GetPolicyRuleRequest)(nil), // 4: mcr.v1.GetPolicyRuleRequest
(*UpdatePolicyRuleRequest)(nil), // 5: mcr.v1.UpdatePolicyRuleRequest
(*DeletePolicyRuleRequest)(nil), // 6: mcr.v1.DeletePolicyRuleRequest
(*DeletePolicyRuleResponse)(nil), // 7: mcr.v1.DeletePolicyRuleResponse
(*PaginationRequest)(nil), // 8: mcr.v1.PaginationRequest
}
var file_mcr_v1_policy_proto_depIdxs = []int32{
8, // 0: mcr.v1.ListPolicyRulesRequest.pagination:type_name -> mcr.v1.PaginationRequest
0, // 1: mcr.v1.ListPolicyRulesResponse.rules:type_name -> mcr.v1.PolicyRule
1, // 2: mcr.v1.PolicyService.ListPolicyRules:input_type -> mcr.v1.ListPolicyRulesRequest
3, // 3: mcr.v1.PolicyService.CreatePolicyRule:input_type -> mcr.v1.CreatePolicyRuleRequest
4, // 4: mcr.v1.PolicyService.GetPolicyRule:input_type -> mcr.v1.GetPolicyRuleRequest
5, // 5: mcr.v1.PolicyService.UpdatePolicyRule:input_type -> mcr.v1.UpdatePolicyRuleRequest
6, // 6: mcr.v1.PolicyService.DeletePolicyRule:input_type -> mcr.v1.DeletePolicyRuleRequest
2, // 7: mcr.v1.PolicyService.ListPolicyRules:output_type -> mcr.v1.ListPolicyRulesResponse
0, // 8: mcr.v1.PolicyService.CreatePolicyRule:output_type -> mcr.v1.PolicyRule
0, // 9: mcr.v1.PolicyService.GetPolicyRule:output_type -> mcr.v1.PolicyRule
0, // 10: mcr.v1.PolicyService.UpdatePolicyRule:output_type -> mcr.v1.PolicyRule
7, // 11: mcr.v1.PolicyService.DeletePolicyRule:output_type -> mcr.v1.DeletePolicyRuleResponse
7, // [7:12] is the sub-list for method output_type
2, // [2:7] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
}
func init() { file_mcr_v1_policy_proto_init() }
func file_mcr_v1_policy_proto_init() {
if File_mcr_v1_policy_proto != nil {
return
}
file_mcr_v1_common_proto_init()
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_mcr_v1_policy_proto_rawDesc), len(file_mcr_v1_policy_proto_rawDesc)),
NumEnums: 0,
NumMessages: 8,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_mcr_v1_policy_proto_goTypes,
DependencyIndexes: file_mcr_v1_policy_proto_depIdxs,
MessageInfos: file_mcr_v1_policy_proto_msgTypes,
}.Build()
File_mcr_v1_policy_proto = out.File
file_mcr_v1_policy_proto_goTypes = nil
file_mcr_v1_policy_proto_depIdxs = nil
}

View File

@@ -1,178 +1,34 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc v6.32.1
// source: mcr/v1/policy.proto
package mcrv1
import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// PolicyServiceServer is the server API for PolicyService.
type PolicyServiceServer interface {
ListPolicyRules(context.Context, *ListPolicyRulesRequest) (*ListPolicyRulesResponse, error)
CreatePolicyRule(context.Context, *CreatePolicyRuleRequest) (*PolicyRule, error)
GetPolicyRule(context.Context, *GetPolicyRuleRequest) (*PolicyRule, error)
UpdatePolicyRule(context.Context, *UpdatePolicyRuleRequest) (*PolicyRule, error)
DeletePolicyRule(context.Context, *DeletePolicyRuleRequest) (*DeletePolicyRuleResponse, error)
mustEmbedUnimplementedPolicyServiceServer()
}
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
// UnimplementedPolicyServiceServer should be embedded to have forward
// compatible implementations.
type UnimplementedPolicyServiceServer struct{}
const (
PolicyService_ListPolicyRules_FullMethodName = "/mcr.v1.PolicyService/ListPolicyRules"
PolicyService_CreatePolicyRule_FullMethodName = "/mcr.v1.PolicyService/CreatePolicyRule"
PolicyService_GetPolicyRule_FullMethodName = "/mcr.v1.PolicyService/GetPolicyRule"
PolicyService_UpdatePolicyRule_FullMethodName = "/mcr.v1.PolicyService/UpdatePolicyRule"
PolicyService_DeletePolicyRule_FullMethodName = "/mcr.v1.PolicyService/DeletePolicyRule"
)
func (UnimplementedPolicyServiceServer) ListPolicyRules(context.Context, *ListPolicyRulesRequest) (*ListPolicyRulesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListPolicyRules not implemented")
}
func (UnimplementedPolicyServiceServer) CreatePolicyRule(context.Context, *CreatePolicyRuleRequest) (*PolicyRule, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreatePolicyRule not implemented")
}
func (UnimplementedPolicyServiceServer) GetPolicyRule(context.Context, *GetPolicyRuleRequest) (*PolicyRule, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPolicyRule not implemented")
}
func (UnimplementedPolicyServiceServer) UpdatePolicyRule(context.Context, *UpdatePolicyRuleRequest) (*PolicyRule, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdatePolicyRule not implemented")
}
func (UnimplementedPolicyServiceServer) DeletePolicyRule(context.Context, *DeletePolicyRuleRequest) (*DeletePolicyRuleResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeletePolicyRule not implemented")
}
func (UnimplementedPolicyServiceServer) mustEmbedUnimplementedPolicyServiceServer() {}
// RegisterPolicyServiceServer registers the PolicyServiceServer with the grpc.Server.
func RegisterPolicyServiceServer(s grpc.ServiceRegistrar, srv PolicyServiceServer) {
s.RegisterService(&PolicyService_ServiceDesc, srv)
}
func policyServiceListPolicyRulesHandler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(ListPolicyRulesRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PolicyServiceServer).ListPolicyRules(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/mcr.v1.PolicyService/ListPolicyRules",
}
handler := func(ctx context.Context, req any) (any, error) {
return srv.(PolicyServiceServer).ListPolicyRules(ctx, req.(*ListPolicyRulesRequest))
}
return interceptor(ctx, in, info, handler)
}
func policyServiceCreatePolicyRuleHandler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(CreatePolicyRuleRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PolicyServiceServer).CreatePolicyRule(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/mcr.v1.PolicyService/CreatePolicyRule",
}
handler := func(ctx context.Context, req any) (any, error) {
return srv.(PolicyServiceServer).CreatePolicyRule(ctx, req.(*CreatePolicyRuleRequest))
}
return interceptor(ctx, in, info, handler)
}
func policyServiceGetPolicyRuleHandler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(GetPolicyRuleRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PolicyServiceServer).GetPolicyRule(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/mcr.v1.PolicyService/GetPolicyRule",
}
handler := func(ctx context.Context, req any) (any, error) {
return srv.(PolicyServiceServer).GetPolicyRule(ctx, req.(*GetPolicyRuleRequest))
}
return interceptor(ctx, in, info, handler)
}
func policyServiceUpdatePolicyRuleHandler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(UpdatePolicyRuleRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PolicyServiceServer).UpdatePolicyRule(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/mcr.v1.PolicyService/UpdatePolicyRule",
}
handler := func(ctx context.Context, req any) (any, error) {
return srv.(PolicyServiceServer).UpdatePolicyRule(ctx, req.(*UpdatePolicyRuleRequest))
}
return interceptor(ctx, in, info, handler)
}
func policyServiceDeletePolicyRuleHandler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(DeletePolicyRuleRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PolicyServiceServer).DeletePolicyRule(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/mcr.v1.PolicyService/DeletePolicyRule",
}
handler := func(ctx context.Context, req any) (any, error) {
return srv.(PolicyServiceServer).DeletePolicyRule(ctx, req.(*DeletePolicyRuleRequest))
}
return interceptor(ctx, in, info, handler)
}
// PolicyService_ServiceDesc is the grpc.ServiceDesc for PolicyService.
var PolicyService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "mcr.v1.PolicyService",
HandlerType: (*PolicyServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "ListPolicyRules",
Handler: policyServiceListPolicyRulesHandler,
},
{
MethodName: "CreatePolicyRule",
Handler: policyServiceCreatePolicyRuleHandler,
},
{
MethodName: "GetPolicyRule",
Handler: policyServiceGetPolicyRuleHandler,
},
{
MethodName: "UpdatePolicyRule",
Handler: policyServiceUpdatePolicyRuleHandler,
},
{
MethodName: "DeletePolicyRule",
Handler: policyServiceDeletePolicyRuleHandler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "mcr/v1/policy.proto",
}
// PolicyServiceClient is the client API for PolicyService.
// PolicyServiceClient is the client API for PolicyService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type PolicyServiceClient interface {
ListPolicyRules(ctx context.Context, in *ListPolicyRulesRequest, opts ...grpc.CallOption) (*ListPolicyRulesResponse, error)
CreatePolicyRule(ctx context.Context, in *CreatePolicyRuleRequest, opts ...grpc.CallOption) (*PolicyRule, error)
@@ -185,14 +41,14 @@ type policyServiceClient struct {
cc grpc.ClientConnInterface
}
// NewPolicyServiceClient creates a new PolicyServiceClient.
func NewPolicyServiceClient(cc grpc.ClientConnInterface) PolicyServiceClient {
return &policyServiceClient{cc}
}
func (c *policyServiceClient) ListPolicyRules(ctx context.Context, in *ListPolicyRulesRequest, opts ...grpc.CallOption) (*ListPolicyRulesResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListPolicyRulesResponse)
err := c.cc.Invoke(ctx, "/mcr.v1.PolicyService/ListPolicyRules", in, out, opts...)
err := c.cc.Invoke(ctx, PolicyService_ListPolicyRules_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -200,8 +56,9 @@ func (c *policyServiceClient) ListPolicyRules(ctx context.Context, in *ListPolic
}
func (c *policyServiceClient) CreatePolicyRule(ctx context.Context, in *CreatePolicyRuleRequest, opts ...grpc.CallOption) (*PolicyRule, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(PolicyRule)
err := c.cc.Invoke(ctx, "/mcr.v1.PolicyService/CreatePolicyRule", in, out, opts...)
err := c.cc.Invoke(ctx, PolicyService_CreatePolicyRule_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -209,8 +66,9 @@ func (c *policyServiceClient) CreatePolicyRule(ctx context.Context, in *CreatePo
}
func (c *policyServiceClient) GetPolicyRule(ctx context.Context, in *GetPolicyRuleRequest, opts ...grpc.CallOption) (*PolicyRule, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(PolicyRule)
err := c.cc.Invoke(ctx, "/mcr.v1.PolicyService/GetPolicyRule", in, out, opts...)
err := c.cc.Invoke(ctx, PolicyService_GetPolicyRule_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -218,8 +76,9 @@ func (c *policyServiceClient) GetPolicyRule(ctx context.Context, in *GetPolicyRu
}
func (c *policyServiceClient) UpdatePolicyRule(ctx context.Context, in *UpdatePolicyRuleRequest, opts ...grpc.CallOption) (*PolicyRule, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(PolicyRule)
err := c.cc.Invoke(ctx, "/mcr.v1.PolicyService/UpdatePolicyRule", in, out, opts...)
err := c.cc.Invoke(ctx, PolicyService_UpdatePolicyRule_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -227,10 +86,188 @@ func (c *policyServiceClient) UpdatePolicyRule(ctx context.Context, in *UpdatePo
}
func (c *policyServiceClient) DeletePolicyRule(ctx context.Context, in *DeletePolicyRuleRequest, opts ...grpc.CallOption) (*DeletePolicyRuleResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(DeletePolicyRuleResponse)
err := c.cc.Invoke(ctx, "/mcr.v1.PolicyService/DeletePolicyRule", in, out, opts...)
err := c.cc.Invoke(ctx, PolicyService_DeletePolicyRule_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// PolicyServiceServer is the server API for PolicyService service.
// All implementations must embed UnimplementedPolicyServiceServer
// for forward compatibility.
type PolicyServiceServer interface {
ListPolicyRules(context.Context, *ListPolicyRulesRequest) (*ListPolicyRulesResponse, error)
CreatePolicyRule(context.Context, *CreatePolicyRuleRequest) (*PolicyRule, error)
GetPolicyRule(context.Context, *GetPolicyRuleRequest) (*PolicyRule, error)
UpdatePolicyRule(context.Context, *UpdatePolicyRuleRequest) (*PolicyRule, error)
DeletePolicyRule(context.Context, *DeletePolicyRuleRequest) (*DeletePolicyRuleResponse, error)
mustEmbedUnimplementedPolicyServiceServer()
}
// UnimplementedPolicyServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedPolicyServiceServer struct{}
func (UnimplementedPolicyServiceServer) ListPolicyRules(context.Context, *ListPolicyRulesRequest) (*ListPolicyRulesResponse, error) {
return nil, status.Error(codes.Unimplemented, "method ListPolicyRules not implemented")
}
func (UnimplementedPolicyServiceServer) CreatePolicyRule(context.Context, *CreatePolicyRuleRequest) (*PolicyRule, error) {
return nil, status.Error(codes.Unimplemented, "method CreatePolicyRule not implemented")
}
func (UnimplementedPolicyServiceServer) GetPolicyRule(context.Context, *GetPolicyRuleRequest) (*PolicyRule, error) {
return nil, status.Error(codes.Unimplemented, "method GetPolicyRule not implemented")
}
func (UnimplementedPolicyServiceServer) UpdatePolicyRule(context.Context, *UpdatePolicyRuleRequest) (*PolicyRule, error) {
return nil, status.Error(codes.Unimplemented, "method UpdatePolicyRule not implemented")
}
func (UnimplementedPolicyServiceServer) DeletePolicyRule(context.Context, *DeletePolicyRuleRequest) (*DeletePolicyRuleResponse, error) {
return nil, status.Error(codes.Unimplemented, "method DeletePolicyRule not implemented")
}
func (UnimplementedPolicyServiceServer) mustEmbedUnimplementedPolicyServiceServer() {}
func (UnimplementedPolicyServiceServer) testEmbeddedByValue() {}
// UnsafePolicyServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to PolicyServiceServer will
// result in compilation errors.
type UnsafePolicyServiceServer interface {
mustEmbedUnimplementedPolicyServiceServer()
}
func RegisterPolicyServiceServer(s grpc.ServiceRegistrar, srv PolicyServiceServer) {
// If the following call panics, it indicates UnimplementedPolicyServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&PolicyService_ServiceDesc, srv)
}
func _PolicyService_ListPolicyRules_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListPolicyRulesRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PolicyServiceServer).ListPolicyRules(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: PolicyService_ListPolicyRules_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PolicyServiceServer).ListPolicyRules(ctx, req.(*ListPolicyRulesRequest))
}
return interceptor(ctx, in, info, handler)
}
func _PolicyService_CreatePolicyRule_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreatePolicyRuleRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PolicyServiceServer).CreatePolicyRule(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: PolicyService_CreatePolicyRule_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PolicyServiceServer).CreatePolicyRule(ctx, req.(*CreatePolicyRuleRequest))
}
return interceptor(ctx, in, info, handler)
}
func _PolicyService_GetPolicyRule_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetPolicyRuleRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PolicyServiceServer).GetPolicyRule(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: PolicyService_GetPolicyRule_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PolicyServiceServer).GetPolicyRule(ctx, req.(*GetPolicyRuleRequest))
}
return interceptor(ctx, in, info, handler)
}
func _PolicyService_UpdatePolicyRule_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdatePolicyRuleRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PolicyServiceServer).UpdatePolicyRule(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: PolicyService_UpdatePolicyRule_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PolicyServiceServer).UpdatePolicyRule(ctx, req.(*UpdatePolicyRuleRequest))
}
return interceptor(ctx, in, info, handler)
}
func _PolicyService_DeletePolicyRule_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeletePolicyRuleRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PolicyServiceServer).DeletePolicyRule(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: PolicyService_DeletePolicyRule_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PolicyServiceServer).DeletePolicyRule(ctx, req.(*DeletePolicyRuleRequest))
}
return interceptor(ctx, in, info, handler)
}
// PolicyService_ServiceDesc is the grpc.ServiceDesc for PolicyService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var PolicyService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "mcr.v1.PolicyService",
HandlerType: (*PolicyServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "ListPolicyRules",
Handler: _PolicyService_ListPolicyRules_Handler,
},
{
MethodName: "CreatePolicyRule",
Handler: _PolicyService_CreatePolicyRule_Handler,
},
{
MethodName: "GetPolicyRule",
Handler: _PolicyService_GetPolicyRule_Handler,
},
{
MethodName: "UpdatePolicyRule",
Handler: _PolicyService_UpdatePolicyRule_Handler,
},
{
MethodName: "DeletePolicyRule",
Handler: _PolicyService_DeletePolicyRule_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "mcr/v1/policy.proto",
}

View File

@@ -1,15 +1,65 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.32.1
// source: mcr/v1/registry.proto
package mcrv1
// RepositoryMetadata is a repository summary for listing.
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type RepositoryMetadata struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
TagCount int32 `protobuf:"varint,2,opt,name=tag_count,json=tagCount,proto3" json:"tag_count,omitempty"`
ManifestCount int32 `protobuf:"varint,3,opt,name=manifest_count,json=manifestCount,proto3" json:"manifest_count,omitempty"`
TotalSize int64 `protobuf:"varint,4,opt,name=total_size,json=totalSize,proto3" json:"total_size,omitempty"`
CreatedAt string `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
TagCount int32 `protobuf:"varint,2,opt,name=tag_count,json=tagCount,proto3" json:"tag_count,omitempty"`
ManifestCount int32 `protobuf:"varint,3,opt,name=manifest_count,json=manifestCount,proto3" json:"manifest_count,omitempty"`
TotalSize int64 `protobuf:"varint,4,opt,name=total_size,json=totalSize,proto3" json:"total_size,omitempty"`
CreatedAt string `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RepositoryMetadata) Reset() {
*x = RepositoryMetadata{}
mi := &file_mcr_v1_registry_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RepositoryMetadata) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RepositoryMetadata) ProtoMessage() {}
func (x *RepositoryMetadata) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_registry_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RepositoryMetadata.ProtoReflect.Descriptor instead.
func (*RepositoryMetadata) Descriptor() ([]byte, []int) {
return file_mcr_v1_registry_proto_rawDescGZIP(), []int{0}
}
func (x *RepositoryMetadata) GetName() string {
@@ -47,10 +97,43 @@ func (x *RepositoryMetadata) GetCreatedAt() string {
return ""
}
// TagInfo is a tag with its manifest digest.
type TagInfo struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Digest string `protobuf:"bytes,2,opt,name=digest,proto3" json:"digest,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Digest string `protobuf:"bytes,2,opt,name=digest,proto3" json:"digest,omitempty"`
UpdatedAt string `protobuf:"bytes,3,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *TagInfo) Reset() {
*x = TagInfo{}
mi := &file_mcr_v1_registry_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *TagInfo) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*TagInfo) ProtoMessage() {}
func (x *TagInfo) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_registry_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use TagInfo.ProtoReflect.Descriptor instead.
func (*TagInfo) Descriptor() ([]byte, []int) {
return file_mcr_v1_registry_proto_rawDescGZIP(), []int{1}
}
func (x *TagInfo) GetName() string {
@@ -67,12 +150,51 @@ func (x *TagInfo) GetDigest() string {
return ""
}
// ManifestInfo is a manifest summary.
func (x *TagInfo) GetUpdatedAt() string {
if x != nil {
return x.UpdatedAt
}
return ""
}
type ManifestInfo struct {
Digest string `protobuf:"bytes,1,opt,name=digest,proto3" json:"digest,omitempty"`
MediaType string `protobuf:"bytes,2,opt,name=media_type,json=mediaType,proto3" json:"media_type,omitempty"`
Size int64 `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"`
CreatedAt string `protobuf:"bytes,4,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Digest string `protobuf:"bytes,1,opt,name=digest,proto3" json:"digest,omitempty"`
MediaType string `protobuf:"bytes,2,opt,name=media_type,json=mediaType,proto3" json:"media_type,omitempty"`
Size int64 `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"`
CreatedAt string `protobuf:"bytes,4,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ManifestInfo) Reset() {
*x = ManifestInfo{}
mi := &file_mcr_v1_registry_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ManifestInfo) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ManifestInfo) ProtoMessage() {}
func (x *ManifestInfo) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_registry_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ManifestInfo.ProtoReflect.Descriptor instead.
func (*ManifestInfo) Descriptor() ([]byte, []int) {
return file_mcr_v1_registry_proto_rawDescGZIP(), []int{2}
}
func (x *ManifestInfo) GetDigest() string {
@@ -103,9 +225,41 @@ func (x *ManifestInfo) GetCreatedAt() string {
return ""
}
// ListRepositoriesRequest is the request message for ListRepositories.
type ListRepositoriesRequest struct {
Pagination *PaginationRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Pagination *PaginationRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListRepositoriesRequest) Reset() {
*x = ListRepositoriesRequest{}
mi := &file_mcr_v1_registry_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListRepositoriesRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListRepositoriesRequest) ProtoMessage() {}
func (x *ListRepositoriesRequest) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_registry_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListRepositoriesRequest.ProtoReflect.Descriptor instead.
func (*ListRepositoriesRequest) Descriptor() ([]byte, []int) {
return file_mcr_v1_registry_proto_rawDescGZIP(), []int{3}
}
func (x *ListRepositoriesRequest) GetPagination() *PaginationRequest {
@@ -115,9 +269,41 @@ func (x *ListRepositoriesRequest) GetPagination() *PaginationRequest {
return nil
}
// ListRepositoriesResponse is the response message for ListRepositories.
type ListRepositoriesResponse struct {
Repositories []*RepositoryMetadata `protobuf:"bytes,1,rep,name=repositories,proto3" json:"repositories,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Repositories []*RepositoryMetadata `protobuf:"bytes,1,rep,name=repositories,proto3" json:"repositories,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListRepositoriesResponse) Reset() {
*x = ListRepositoriesResponse{}
mi := &file_mcr_v1_registry_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListRepositoriesResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListRepositoriesResponse) ProtoMessage() {}
func (x *ListRepositoriesResponse) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_registry_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListRepositoriesResponse.ProtoReflect.Descriptor instead.
func (*ListRepositoriesResponse) Descriptor() ([]byte, []int) {
return file_mcr_v1_registry_proto_rawDescGZIP(), []int{4}
}
func (x *ListRepositoriesResponse) GetRepositories() []*RepositoryMetadata {
@@ -127,9 +313,41 @@ func (x *ListRepositoriesResponse) GetRepositories() []*RepositoryMetadata {
return nil
}
// GetRepositoryRequest is the request message for GetRepository.
type GetRepositoryRequest struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetRepositoryRequest) Reset() {
*x = GetRepositoryRequest{}
mi := &file_mcr_v1_registry_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetRepositoryRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetRepositoryRequest) ProtoMessage() {}
func (x *GetRepositoryRequest) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_registry_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetRepositoryRequest.ProtoReflect.Descriptor instead.
func (*GetRepositoryRequest) Descriptor() ([]byte, []int) {
return file_mcr_v1_registry_proto_rawDescGZIP(), []int{5}
}
func (x *GetRepositoryRequest) GetName() string {
@@ -139,13 +357,45 @@ func (x *GetRepositoryRequest) GetName() string {
return ""
}
// GetRepositoryResponse is the response message for GetRepository.
type GetRepositoryResponse struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Tags []*TagInfo `protobuf:"bytes,2,rep,name=tags,proto3" json:"tags,omitempty"`
Manifests []*ManifestInfo `protobuf:"bytes,3,rep,name=manifests,proto3" json:"manifests,omitempty"`
TotalSize int64 `protobuf:"varint,4,opt,name=total_size,json=totalSize,proto3" json:"total_size,omitempty"`
CreatedAt string `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Tags []*TagInfo `protobuf:"bytes,2,rep,name=tags,proto3" json:"tags,omitempty"`
Manifests []*ManifestInfo `protobuf:"bytes,3,rep,name=manifests,proto3" json:"manifests,omitempty"`
TotalSize int64 `protobuf:"varint,4,opt,name=total_size,json=totalSize,proto3" json:"total_size,omitempty"`
CreatedAt string `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetRepositoryResponse) Reset() {
*x = GetRepositoryResponse{}
mi := &file_mcr_v1_registry_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetRepositoryResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetRepositoryResponse) ProtoMessage() {}
func (x *GetRepositoryResponse) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_registry_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetRepositoryResponse.ProtoReflect.Descriptor instead.
func (*GetRepositoryResponse) Descriptor() ([]byte, []int) {
return file_mcr_v1_registry_proto_rawDescGZIP(), []int{6}
}
func (x *GetRepositoryResponse) GetName() string {
@@ -183,9 +433,41 @@ func (x *GetRepositoryResponse) GetCreatedAt() string {
return ""
}
// DeleteRepositoryRequest is the request message for DeleteRepository.
type DeleteRepositoryRequest struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeleteRepositoryRequest) Reset() {
*x = DeleteRepositoryRequest{}
mi := &file_mcr_v1_registry_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeleteRepositoryRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeleteRepositoryRequest) ProtoMessage() {}
func (x *DeleteRepositoryRequest) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_registry_proto_msgTypes[7]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeleteRepositoryRequest.ProtoReflect.Descriptor instead.
func (*DeleteRepositoryRequest) Descriptor() ([]byte, []int) {
return file_mcr_v1_registry_proto_rawDescGZIP(), []int{7}
}
func (x *DeleteRepositoryRequest) GetName() string {
@@ -195,15 +477,113 @@ func (x *DeleteRepositoryRequest) GetName() string {
return ""
}
// DeleteRepositoryResponse is the response message for DeleteRepository.
type DeleteRepositoryResponse struct{}
type DeleteRepositoryResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
// GarbageCollectRequest is the request message for GarbageCollect.
type GarbageCollectRequest struct{}
func (x *DeleteRepositoryResponse) Reset() {
*x = DeleteRepositoryResponse{}
mi := &file_mcr_v1_registry_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeleteRepositoryResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeleteRepositoryResponse) ProtoMessage() {}
func (x *DeleteRepositoryResponse) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_registry_proto_msgTypes[8]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeleteRepositoryResponse.ProtoReflect.Descriptor instead.
func (*DeleteRepositoryResponse) Descriptor() ([]byte, []int) {
return file_mcr_v1_registry_proto_rawDescGZIP(), []int{8}
}
type GarbageCollectRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GarbageCollectRequest) Reset() {
*x = GarbageCollectRequest{}
mi := &file_mcr_v1_registry_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GarbageCollectRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GarbageCollectRequest) ProtoMessage() {}
func (x *GarbageCollectRequest) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_registry_proto_msgTypes[9]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GarbageCollectRequest.ProtoReflect.Descriptor instead.
func (*GarbageCollectRequest) Descriptor() ([]byte, []int) {
return file_mcr_v1_registry_proto_rawDescGZIP(), []int{9}
}
// GarbageCollectResponse is the response message for GarbageCollect.
type GarbageCollectResponse struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` //nolint:revive,stylecheck // proto field name
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GarbageCollectResponse) Reset() {
*x = GarbageCollectResponse{}
mi := &file_mcr_v1_registry_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GarbageCollectResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GarbageCollectResponse) ProtoMessage() {}
func (x *GarbageCollectResponse) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_registry_proto_msgTypes[10]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GarbageCollectResponse.ProtoReflect.Descriptor instead.
func (*GarbageCollectResponse) Descriptor() ([]byte, []int) {
return file_mcr_v1_registry_proto_rawDescGZIP(), []int{10}
}
func (x *GarbageCollectResponse) GetId() string {
@@ -213,15 +593,80 @@ func (x *GarbageCollectResponse) GetId() string {
return ""
}
// GetGCStatusRequest is the request message for GetGCStatus.
type GetGCStatusRequest struct{}
type GetGCStatusRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetGCStatusRequest) Reset() {
*x = GetGCStatusRequest{}
mi := &file_mcr_v1_registry_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetGCStatusRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetGCStatusRequest) ProtoMessage() {}
func (x *GetGCStatusRequest) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_registry_proto_msgTypes[11]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetGCStatusRequest.ProtoReflect.Descriptor instead.
func (*GetGCStatusRequest) Descriptor() ([]byte, []int) {
return file_mcr_v1_registry_proto_rawDescGZIP(), []int{11}
}
// GCLastRun records the result of the last garbage collection run.
type GCLastRun struct {
StartedAt string `protobuf:"bytes,1,opt,name=started_at,json=startedAt,proto3" json:"started_at,omitempty"`
CompletedAt string `protobuf:"bytes,2,opt,name=completed_at,json=completedAt,proto3" json:"completed_at,omitempty"`
BlobsRemoved int32 `protobuf:"varint,3,opt,name=blobs_removed,json=blobsRemoved,proto3" json:"blobs_removed,omitempty"`
BytesFreed int64 `protobuf:"varint,4,opt,name=bytes_freed,json=bytesFreed,proto3" json:"bytes_freed,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
StartedAt string `protobuf:"bytes,1,opt,name=started_at,json=startedAt,proto3" json:"started_at,omitempty"`
CompletedAt string `protobuf:"bytes,2,opt,name=completed_at,json=completedAt,proto3" json:"completed_at,omitempty"`
BlobsRemoved int32 `protobuf:"varint,3,opt,name=blobs_removed,json=blobsRemoved,proto3" json:"blobs_removed,omitempty"`
BytesFreed int64 `protobuf:"varint,4,opt,name=bytes_freed,json=bytesFreed,proto3" json:"bytes_freed,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GCLastRun) Reset() {
*x = GCLastRun{}
mi := &file_mcr_v1_registry_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GCLastRun) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GCLastRun) ProtoMessage() {}
func (x *GCLastRun) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_registry_proto_msgTypes[12]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GCLastRun.ProtoReflect.Descriptor instead.
func (*GCLastRun) Descriptor() ([]byte, []int) {
return file_mcr_v1_registry_proto_rawDescGZIP(), []int{12}
}
func (x *GCLastRun) GetStartedAt() string {
@@ -252,10 +697,42 @@ func (x *GCLastRun) GetBytesFreed() int64 {
return 0
}
// GetGCStatusResponse is the response message for GetGCStatus.
type GetGCStatusResponse struct {
Running bool `protobuf:"varint,1,opt,name=running,proto3" json:"running,omitempty"`
LastRun *GCLastRun `protobuf:"bytes,2,opt,name=last_run,json=lastRun,proto3" json:"last_run,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Running bool `protobuf:"varint,1,opt,name=running,proto3" json:"running,omitempty"`
LastRun *GCLastRun `protobuf:"bytes,2,opt,name=last_run,json=lastRun,proto3" json:"last_run,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetGCStatusResponse) Reset() {
*x = GetGCStatusResponse{}
mi := &file_mcr_v1_registry_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetGCStatusResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetGCStatusResponse) ProtoMessage() {}
func (x *GetGCStatusResponse) ProtoReflect() protoreflect.Message {
mi := &file_mcr_v1_registry_proto_msgTypes[13]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetGCStatusResponse.ProtoReflect.Descriptor instead.
func (*GetGCStatusResponse) Descriptor() ([]byte, []int) {
return file_mcr_v1_registry_proto_rawDescGZIP(), []int{13}
}
func (x *GetGCStatusResponse) GetRunning() bool {
@@ -271,3 +748,146 @@ func (x *GetGCStatusResponse) GetLastRun() *GCLastRun {
}
return nil
}
var File_mcr_v1_registry_proto protoreflect.FileDescriptor
const file_mcr_v1_registry_proto_rawDesc = "" +
"\n" +
"\x15mcr/v1/registry.proto\x12\x06mcr.v1\x1a\x13mcr/v1/common.proto\"\xaa\x01\n" +
"\x12RepositoryMetadata\x12\x12\n" +
"\x04name\x18\x01 \x01(\tR\x04name\x12\x1b\n" +
"\ttag_count\x18\x02 \x01(\x05R\btagCount\x12%\n" +
"\x0emanifest_count\x18\x03 \x01(\x05R\rmanifestCount\x12\x1d\n" +
"\n" +
"total_size\x18\x04 \x01(\x03R\ttotalSize\x12\x1d\n" +
"\n" +
"created_at\x18\x05 \x01(\tR\tcreatedAt\"T\n" +
"\aTagInfo\x12\x12\n" +
"\x04name\x18\x01 \x01(\tR\x04name\x12\x16\n" +
"\x06digest\x18\x02 \x01(\tR\x06digest\x12\x1d\n" +
"\n" +
"updated_at\x18\x03 \x01(\tR\tupdatedAt\"x\n" +
"\fManifestInfo\x12\x16\n" +
"\x06digest\x18\x01 \x01(\tR\x06digest\x12\x1d\n" +
"\n" +
"media_type\x18\x02 \x01(\tR\tmediaType\x12\x12\n" +
"\x04size\x18\x03 \x01(\x03R\x04size\x12\x1d\n" +
"\n" +
"created_at\x18\x04 \x01(\tR\tcreatedAt\"T\n" +
"\x17ListRepositoriesRequest\x129\n" +
"\n" +
"pagination\x18\x01 \x01(\v2\x19.mcr.v1.PaginationRequestR\n" +
"pagination\"Z\n" +
"\x18ListRepositoriesResponse\x12>\n" +
"\frepositories\x18\x01 \x03(\v2\x1a.mcr.v1.RepositoryMetadataR\frepositories\"*\n" +
"\x14GetRepositoryRequest\x12\x12\n" +
"\x04name\x18\x01 \x01(\tR\x04name\"\xc2\x01\n" +
"\x15GetRepositoryResponse\x12\x12\n" +
"\x04name\x18\x01 \x01(\tR\x04name\x12#\n" +
"\x04tags\x18\x02 \x03(\v2\x0f.mcr.v1.TagInfoR\x04tags\x122\n" +
"\tmanifests\x18\x03 \x03(\v2\x14.mcr.v1.ManifestInfoR\tmanifests\x12\x1d\n" +
"\n" +
"total_size\x18\x04 \x01(\x03R\ttotalSize\x12\x1d\n" +
"\n" +
"created_at\x18\x05 \x01(\tR\tcreatedAt\"-\n" +
"\x17DeleteRepositoryRequest\x12\x12\n" +
"\x04name\x18\x01 \x01(\tR\x04name\"\x1a\n" +
"\x18DeleteRepositoryResponse\"\x17\n" +
"\x15GarbageCollectRequest\"(\n" +
"\x16GarbageCollectResponse\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\"\x14\n" +
"\x12GetGCStatusRequest\"\x93\x01\n" +
"\tGCLastRun\x12\x1d\n" +
"\n" +
"started_at\x18\x01 \x01(\tR\tstartedAt\x12!\n" +
"\fcompleted_at\x18\x02 \x01(\tR\vcompletedAt\x12#\n" +
"\rblobs_removed\x18\x03 \x01(\x05R\fblobsRemoved\x12\x1f\n" +
"\vbytes_freed\x18\x04 \x01(\x03R\n" +
"bytesFreed\"]\n" +
"\x13GetGCStatusResponse\x12\x18\n" +
"\arunning\x18\x01 \x01(\bR\arunning\x12,\n" +
"\blast_run\x18\x02 \x01(\v2\x11.mcr.v1.GCLastRunR\alastRun2\xa6\x03\n" +
"\x0fRegistryService\x12U\n" +
"\x10ListRepositories\x12\x1f.mcr.v1.ListRepositoriesRequest\x1a .mcr.v1.ListRepositoriesResponse\x12L\n" +
"\rGetRepository\x12\x1c.mcr.v1.GetRepositoryRequest\x1a\x1d.mcr.v1.GetRepositoryResponse\x12U\n" +
"\x10DeleteRepository\x12\x1f.mcr.v1.DeleteRepositoryRequest\x1a .mcr.v1.DeleteRepositoryResponse\x12O\n" +
"\x0eGarbageCollect\x12\x1d.mcr.v1.GarbageCollectRequest\x1a\x1e.mcr.v1.GarbageCollectResponse\x12F\n" +
"\vGetGCStatus\x12\x1a.mcr.v1.GetGCStatusRequest\x1a\x1b.mcr.v1.GetGCStatusResponseB,Z*git.wntrmute.dev/mc/mcr/gen/mcr/v1;mcrv1b\x06proto3"
var (
file_mcr_v1_registry_proto_rawDescOnce sync.Once
file_mcr_v1_registry_proto_rawDescData []byte
)
func file_mcr_v1_registry_proto_rawDescGZIP() []byte {
file_mcr_v1_registry_proto_rawDescOnce.Do(func() {
file_mcr_v1_registry_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_mcr_v1_registry_proto_rawDesc), len(file_mcr_v1_registry_proto_rawDesc)))
})
return file_mcr_v1_registry_proto_rawDescData
}
var file_mcr_v1_registry_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
var file_mcr_v1_registry_proto_goTypes = []any{
(*RepositoryMetadata)(nil), // 0: mcr.v1.RepositoryMetadata
(*TagInfo)(nil), // 1: mcr.v1.TagInfo
(*ManifestInfo)(nil), // 2: mcr.v1.ManifestInfo
(*ListRepositoriesRequest)(nil), // 3: mcr.v1.ListRepositoriesRequest
(*ListRepositoriesResponse)(nil), // 4: mcr.v1.ListRepositoriesResponse
(*GetRepositoryRequest)(nil), // 5: mcr.v1.GetRepositoryRequest
(*GetRepositoryResponse)(nil), // 6: mcr.v1.GetRepositoryResponse
(*DeleteRepositoryRequest)(nil), // 7: mcr.v1.DeleteRepositoryRequest
(*DeleteRepositoryResponse)(nil), // 8: mcr.v1.DeleteRepositoryResponse
(*GarbageCollectRequest)(nil), // 9: mcr.v1.GarbageCollectRequest
(*GarbageCollectResponse)(nil), // 10: mcr.v1.GarbageCollectResponse
(*GetGCStatusRequest)(nil), // 11: mcr.v1.GetGCStatusRequest
(*GCLastRun)(nil), // 12: mcr.v1.GCLastRun
(*GetGCStatusResponse)(nil), // 13: mcr.v1.GetGCStatusResponse
(*PaginationRequest)(nil), // 14: mcr.v1.PaginationRequest
}
var file_mcr_v1_registry_proto_depIdxs = []int32{
14, // 0: mcr.v1.ListRepositoriesRequest.pagination:type_name -> mcr.v1.PaginationRequest
0, // 1: mcr.v1.ListRepositoriesResponse.repositories:type_name -> mcr.v1.RepositoryMetadata
1, // 2: mcr.v1.GetRepositoryResponse.tags:type_name -> mcr.v1.TagInfo
2, // 3: mcr.v1.GetRepositoryResponse.manifests:type_name -> mcr.v1.ManifestInfo
12, // 4: mcr.v1.GetGCStatusResponse.last_run:type_name -> mcr.v1.GCLastRun
3, // 5: mcr.v1.RegistryService.ListRepositories:input_type -> mcr.v1.ListRepositoriesRequest
5, // 6: mcr.v1.RegistryService.GetRepository:input_type -> mcr.v1.GetRepositoryRequest
7, // 7: mcr.v1.RegistryService.DeleteRepository:input_type -> mcr.v1.DeleteRepositoryRequest
9, // 8: mcr.v1.RegistryService.GarbageCollect:input_type -> mcr.v1.GarbageCollectRequest
11, // 9: mcr.v1.RegistryService.GetGCStatus:input_type -> mcr.v1.GetGCStatusRequest
4, // 10: mcr.v1.RegistryService.ListRepositories:output_type -> mcr.v1.ListRepositoriesResponse
6, // 11: mcr.v1.RegistryService.GetRepository:output_type -> mcr.v1.GetRepositoryResponse
8, // 12: mcr.v1.RegistryService.DeleteRepository:output_type -> mcr.v1.DeleteRepositoryResponse
10, // 13: mcr.v1.RegistryService.GarbageCollect:output_type -> mcr.v1.GarbageCollectResponse
13, // 14: mcr.v1.RegistryService.GetGCStatus:output_type -> mcr.v1.GetGCStatusResponse
10, // [10:15] is the sub-list for method output_type
5, // [5:10] is the sub-list for method input_type
5, // [5:5] is the sub-list for extension type_name
5, // [5:5] is the sub-list for extension extendee
0, // [0:5] is the sub-list for field type_name
}
func init() { file_mcr_v1_registry_proto_init() }
func file_mcr_v1_registry_proto_init() {
if File_mcr_v1_registry_proto != nil {
return
}
file_mcr_v1_common_proto_init()
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_mcr_v1_registry_proto_rawDesc), len(file_mcr_v1_registry_proto_rawDesc)),
NumEnums: 0,
NumMessages: 14,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_mcr_v1_registry_proto_goTypes,
DependencyIndexes: file_mcr_v1_registry_proto_depIdxs,
MessageInfos: file_mcr_v1_registry_proto_msgTypes,
}.Build()
File_mcr_v1_registry_proto = out.File
file_mcr_v1_registry_proto_goTypes = nil
file_mcr_v1_registry_proto_depIdxs = nil
}

View File

@@ -1,178 +1,34 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc v6.32.1
// source: mcr/v1/registry.proto
package mcrv1
import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// RegistryServiceServer is the server API for RegistryService.
type RegistryServiceServer interface {
ListRepositories(context.Context, *ListRepositoriesRequest) (*ListRepositoriesResponse, error)
GetRepository(context.Context, *GetRepositoryRequest) (*GetRepositoryResponse, error)
DeleteRepository(context.Context, *DeleteRepositoryRequest) (*DeleteRepositoryResponse, error)
GarbageCollect(context.Context, *GarbageCollectRequest) (*GarbageCollectResponse, error)
GetGCStatus(context.Context, *GetGCStatusRequest) (*GetGCStatusResponse, error)
mustEmbedUnimplementedRegistryServiceServer()
}
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
// UnimplementedRegistryServiceServer should be embedded to have forward
// compatible implementations.
type UnimplementedRegistryServiceServer struct{}
const (
RegistryService_ListRepositories_FullMethodName = "/mcr.v1.RegistryService/ListRepositories"
RegistryService_GetRepository_FullMethodName = "/mcr.v1.RegistryService/GetRepository"
RegistryService_DeleteRepository_FullMethodName = "/mcr.v1.RegistryService/DeleteRepository"
RegistryService_GarbageCollect_FullMethodName = "/mcr.v1.RegistryService/GarbageCollect"
RegistryService_GetGCStatus_FullMethodName = "/mcr.v1.RegistryService/GetGCStatus"
)
func (UnimplementedRegistryServiceServer) ListRepositories(context.Context, *ListRepositoriesRequest) (*ListRepositoriesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListRepositories not implemented")
}
func (UnimplementedRegistryServiceServer) GetRepository(context.Context, *GetRepositoryRequest) (*GetRepositoryResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetRepository not implemented")
}
func (UnimplementedRegistryServiceServer) DeleteRepository(context.Context, *DeleteRepositoryRequest) (*DeleteRepositoryResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteRepository not implemented")
}
func (UnimplementedRegistryServiceServer) GarbageCollect(context.Context, *GarbageCollectRequest) (*GarbageCollectResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GarbageCollect not implemented")
}
func (UnimplementedRegistryServiceServer) GetGCStatus(context.Context, *GetGCStatusRequest) (*GetGCStatusResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetGCStatus not implemented")
}
func (UnimplementedRegistryServiceServer) mustEmbedUnimplementedRegistryServiceServer() {}
// RegisterRegistryServiceServer registers the RegistryServiceServer with the grpc.Server.
func RegisterRegistryServiceServer(s grpc.ServiceRegistrar, srv RegistryServiceServer) {
s.RegisterService(&RegistryService_ServiceDesc, srv)
}
func registryServiceListRepositoriesHandler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(ListRepositoriesRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RegistryServiceServer).ListRepositories(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/mcr.v1.RegistryService/ListRepositories",
}
handler := func(ctx context.Context, req any) (any, error) {
return srv.(RegistryServiceServer).ListRepositories(ctx, req.(*ListRepositoriesRequest))
}
return interceptor(ctx, in, info, handler)
}
func registryServiceGetRepositoryHandler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(GetRepositoryRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RegistryServiceServer).GetRepository(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/mcr.v1.RegistryService/GetRepository",
}
handler := func(ctx context.Context, req any) (any, error) {
return srv.(RegistryServiceServer).GetRepository(ctx, req.(*GetRepositoryRequest))
}
return interceptor(ctx, in, info, handler)
}
func registryServiceDeleteRepositoryHandler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(DeleteRepositoryRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RegistryServiceServer).DeleteRepository(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/mcr.v1.RegistryService/DeleteRepository",
}
handler := func(ctx context.Context, req any) (any, error) {
return srv.(RegistryServiceServer).DeleteRepository(ctx, req.(*DeleteRepositoryRequest))
}
return interceptor(ctx, in, info, handler)
}
func registryServiceGarbageCollectHandler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(GarbageCollectRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RegistryServiceServer).GarbageCollect(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/mcr.v1.RegistryService/GarbageCollect",
}
handler := func(ctx context.Context, req any) (any, error) {
return srv.(RegistryServiceServer).GarbageCollect(ctx, req.(*GarbageCollectRequest))
}
return interceptor(ctx, in, info, handler)
}
func registryServiceGetGCStatusHandler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(GetGCStatusRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RegistryServiceServer).GetGCStatus(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/mcr.v1.RegistryService/GetGCStatus",
}
handler := func(ctx context.Context, req any) (any, error) {
return srv.(RegistryServiceServer).GetGCStatus(ctx, req.(*GetGCStatusRequest))
}
return interceptor(ctx, in, info, handler)
}
// RegistryService_ServiceDesc is the grpc.ServiceDesc for RegistryService.
var RegistryService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "mcr.v1.RegistryService",
HandlerType: (*RegistryServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "ListRepositories",
Handler: registryServiceListRepositoriesHandler,
},
{
MethodName: "GetRepository",
Handler: registryServiceGetRepositoryHandler,
},
{
MethodName: "DeleteRepository",
Handler: registryServiceDeleteRepositoryHandler,
},
{
MethodName: "GarbageCollect",
Handler: registryServiceGarbageCollectHandler,
},
{
MethodName: "GetGCStatus",
Handler: registryServiceGetGCStatusHandler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "mcr/v1/registry.proto",
}
// RegistryServiceClient is the client API for RegistryService.
// RegistryServiceClient is the client API for RegistryService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type RegistryServiceClient interface {
ListRepositories(ctx context.Context, in *ListRepositoriesRequest, opts ...grpc.CallOption) (*ListRepositoriesResponse, error)
GetRepository(ctx context.Context, in *GetRepositoryRequest, opts ...grpc.CallOption) (*GetRepositoryResponse, error)
@@ -185,14 +41,14 @@ type registryServiceClient struct {
cc grpc.ClientConnInterface
}
// NewRegistryServiceClient creates a new RegistryServiceClient.
func NewRegistryServiceClient(cc grpc.ClientConnInterface) RegistryServiceClient {
return &registryServiceClient{cc}
}
func (c *registryServiceClient) ListRepositories(ctx context.Context, in *ListRepositoriesRequest, opts ...grpc.CallOption) (*ListRepositoriesResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListRepositoriesResponse)
err := c.cc.Invoke(ctx, "/mcr.v1.RegistryService/ListRepositories", in, out, opts...)
err := c.cc.Invoke(ctx, RegistryService_ListRepositories_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -200,8 +56,9 @@ func (c *registryServiceClient) ListRepositories(ctx context.Context, in *ListRe
}
func (c *registryServiceClient) GetRepository(ctx context.Context, in *GetRepositoryRequest, opts ...grpc.CallOption) (*GetRepositoryResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetRepositoryResponse)
err := c.cc.Invoke(ctx, "/mcr.v1.RegistryService/GetRepository", in, out, opts...)
err := c.cc.Invoke(ctx, RegistryService_GetRepository_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -209,8 +66,9 @@ func (c *registryServiceClient) GetRepository(ctx context.Context, in *GetReposi
}
func (c *registryServiceClient) DeleteRepository(ctx context.Context, in *DeleteRepositoryRequest, opts ...grpc.CallOption) (*DeleteRepositoryResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(DeleteRepositoryResponse)
err := c.cc.Invoke(ctx, "/mcr.v1.RegistryService/DeleteRepository", in, out, opts...)
err := c.cc.Invoke(ctx, RegistryService_DeleteRepository_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -218,8 +76,9 @@ func (c *registryServiceClient) DeleteRepository(ctx context.Context, in *Delete
}
func (c *registryServiceClient) GarbageCollect(ctx context.Context, in *GarbageCollectRequest, opts ...grpc.CallOption) (*GarbageCollectResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GarbageCollectResponse)
err := c.cc.Invoke(ctx, "/mcr.v1.RegistryService/GarbageCollect", in, out, opts...)
err := c.cc.Invoke(ctx, RegistryService_GarbageCollect_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
@@ -227,10 +86,188 @@ func (c *registryServiceClient) GarbageCollect(ctx context.Context, in *GarbageC
}
func (c *registryServiceClient) GetGCStatus(ctx context.Context, in *GetGCStatusRequest, opts ...grpc.CallOption) (*GetGCStatusResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetGCStatusResponse)
err := c.cc.Invoke(ctx, "/mcr.v1.RegistryService/GetGCStatus", in, out, opts...)
err := c.cc.Invoke(ctx, RegistryService_GetGCStatus_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// RegistryServiceServer is the server API for RegistryService service.
// All implementations must embed UnimplementedRegistryServiceServer
// for forward compatibility.
type RegistryServiceServer interface {
ListRepositories(context.Context, *ListRepositoriesRequest) (*ListRepositoriesResponse, error)
GetRepository(context.Context, *GetRepositoryRequest) (*GetRepositoryResponse, error)
DeleteRepository(context.Context, *DeleteRepositoryRequest) (*DeleteRepositoryResponse, error)
GarbageCollect(context.Context, *GarbageCollectRequest) (*GarbageCollectResponse, error)
GetGCStatus(context.Context, *GetGCStatusRequest) (*GetGCStatusResponse, error)
mustEmbedUnimplementedRegistryServiceServer()
}
// UnimplementedRegistryServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedRegistryServiceServer struct{}
func (UnimplementedRegistryServiceServer) ListRepositories(context.Context, *ListRepositoriesRequest) (*ListRepositoriesResponse, error) {
return nil, status.Error(codes.Unimplemented, "method ListRepositories not implemented")
}
func (UnimplementedRegistryServiceServer) GetRepository(context.Context, *GetRepositoryRequest) (*GetRepositoryResponse, error) {
return nil, status.Error(codes.Unimplemented, "method GetRepository not implemented")
}
func (UnimplementedRegistryServiceServer) DeleteRepository(context.Context, *DeleteRepositoryRequest) (*DeleteRepositoryResponse, error) {
return nil, status.Error(codes.Unimplemented, "method DeleteRepository not implemented")
}
func (UnimplementedRegistryServiceServer) GarbageCollect(context.Context, *GarbageCollectRequest) (*GarbageCollectResponse, error) {
return nil, status.Error(codes.Unimplemented, "method GarbageCollect not implemented")
}
func (UnimplementedRegistryServiceServer) GetGCStatus(context.Context, *GetGCStatusRequest) (*GetGCStatusResponse, error) {
return nil, status.Error(codes.Unimplemented, "method GetGCStatus not implemented")
}
func (UnimplementedRegistryServiceServer) mustEmbedUnimplementedRegistryServiceServer() {}
func (UnimplementedRegistryServiceServer) testEmbeddedByValue() {}
// UnsafeRegistryServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to RegistryServiceServer will
// result in compilation errors.
type UnsafeRegistryServiceServer interface {
mustEmbedUnimplementedRegistryServiceServer()
}
func RegisterRegistryServiceServer(s grpc.ServiceRegistrar, srv RegistryServiceServer) {
// If the following call panics, it indicates UnimplementedRegistryServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&RegistryService_ServiceDesc, srv)
}
func _RegistryService_ListRepositories_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListRepositoriesRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RegistryServiceServer).ListRepositories(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RegistryService_ListRepositories_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RegistryServiceServer).ListRepositories(ctx, req.(*ListRepositoriesRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RegistryService_GetRepository_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetRepositoryRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RegistryServiceServer).GetRepository(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RegistryService_GetRepository_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RegistryServiceServer).GetRepository(ctx, req.(*GetRepositoryRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RegistryService_DeleteRepository_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteRepositoryRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RegistryServiceServer).DeleteRepository(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RegistryService_DeleteRepository_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RegistryServiceServer).DeleteRepository(ctx, req.(*DeleteRepositoryRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RegistryService_GarbageCollect_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GarbageCollectRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RegistryServiceServer).GarbageCollect(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RegistryService_GarbageCollect_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RegistryServiceServer).GarbageCollect(ctx, req.(*GarbageCollectRequest))
}
return interceptor(ctx, in, info, handler)
}
func _RegistryService_GetGCStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetGCStatusRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RegistryServiceServer).GetGCStatus(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RegistryService_GetGCStatus_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RegistryServiceServer).GetGCStatus(ctx, req.(*GetGCStatusRequest))
}
return interceptor(ctx, in, info, handler)
}
// RegistryService_ServiceDesc is the grpc.ServiceDesc for RegistryService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var RegistryService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "mcr.v1.RegistryService",
HandlerType: (*RegistryServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "ListRepositories",
Handler: _RegistryService_ListRepositories_Handler,
},
{
MethodName: "GetRepository",
Handler: _RegistryService_GetRepository_Handler,
},
{
MethodName: "DeleteRepository",
Handler: _RegistryService_DeleteRepository_Handler,
},
{
MethodName: "GarbageCollect",
Handler: _RegistryService_GarbageCollect_Handler,
},
{
MethodName: "GetGCStatus",
Handler: _RegistryService_GetGCStatus_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "mcr/v1/registry.proto",
}

6
go.mod
View File

@@ -1,13 +1,14 @@
module git.wntrmute.dev/kyle/mcr
module git.wntrmute.dev/mc/mcr
go 1.25.7
require (
git.wntrmute.dev/kyle/mcdsl v1.0.0
git.wntrmute.dev/mc/mcdsl v1.2.0
github.com/go-chi/chi/v5 v5.2.5
github.com/google/uuid v1.6.0
github.com/spf13/cobra v1.10.2
google.golang.org/grpc v1.79.3
google.golang.org/protobuf v1.36.11
)
require (
@@ -22,7 +23,6 @@ require (
golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.32.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect
google.golang.org/protobuf v1.36.11 // indirect
modernc.org/libc v1.70.0 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect

4
go.sum
View File

@@ -1,5 +1,5 @@
git.wntrmute.dev/kyle/mcdsl v1.0.0 h1:YB7dx4gdNYKKcVySpL6UkwHqdCJ9Nl1yS0+eHk0hNtk=
git.wntrmute.dev/kyle/mcdsl v1.0.0/go.mod h1:wo0tGfUAxci3XnOe4/rFmR0RjUElKdYUazc+Np986sg=
git.wntrmute.dev/mc/mcdsl v1.2.0 h1:41hep7/PNZJfN0SN/nM+rQpyF1GSZcvNNjyVG81DI7U=
git.wntrmute.dev/mc/mcdsl v1.2.0/go.mod h1:lXYrAt74ZUix6rx9oVN8d2zH1YJoyp4uxPVKQ+SSxuM=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=

View File

@@ -4,7 +4,7 @@ import (
"errors"
"log/slog"
mcdslauth "git.wntrmute.dev/kyle/mcdsl/auth"
mcdslauth "git.wntrmute.dev/mc/mcdsl/auth"
)
// Client communicates with an MCIAS server for authentication and token

View File

@@ -5,7 +5,7 @@ import (
"os"
"path/filepath"
mcdslconfig "git.wntrmute.dev/kyle/mcdsl/config"
mcdslconfig "git.wntrmute.dev/mc/mcdsl/config"
)
// Config is the top-level MCR configuration. It embeds config.Base for
@@ -24,9 +24,10 @@ type StorageConfig struct {
// WebConfig holds the web UI server settings.
type WebConfig struct {
ListenAddr string `toml:"listen_addr"`
GRPCAddr string `toml:"grpc_addr"`
CACert string `toml:"ca_cert"`
ListenAddr string `toml:"listen_addr"`
GRPCAddr string `toml:"grpc_addr"`
CACert string `toml:"ca_cert"`
TLSServerName string `toml:"tls_server_name"`
}
// Load reads a TOML config file, applies environment variable overrides

View File

@@ -23,8 +23,9 @@ type RepoMetadata struct {
// TagInfo is a tag with its manifest digest for repo detail.
type TagInfo struct {
Name string `json:"name"`
Digest string `json:"digest"`
Name string `json:"name"`
Digest string `json:"digest"`
UpdatedAt string `json:"updated_at"`
}
// ManifestInfo is a manifest summary for repo detail.
@@ -112,7 +113,7 @@ func (d *DB) GetRepositoryDetail(name string) (*RepoDetail, error) {
// Tags with manifest digests.
tagRows, err := d.Query(
`SELECT t.name, m.digest
`SELECT t.name, m.digest, t.updated_at
FROM tags t JOIN manifests m ON m.id = t.manifest_id
WHERE t.repository_id = ?
ORDER BY t.name ASC`, repoID,
@@ -124,7 +125,7 @@ func (d *DB) GetRepositoryDetail(name string) (*RepoDetail, error) {
for tagRows.Next() {
var ti TagInfo
if err := tagRows.Scan(&ti.Name, &ti.Digest); err != nil {
if err := tagRows.Scan(&ti.Name, &ti.Digest, &ti.UpdatedAt); err != nil {
return nil, fmt.Errorf("db: scan tag: %w", err)
}
detail.Tags = append(detail.Tags, ti)

View File

@@ -4,7 +4,7 @@ import (
"database/sql"
"fmt"
mcdsldb "git.wntrmute.dev/kyle/mcdsl/db"
mcdsldb "git.wntrmute.dev/mc/mcdsl/db"
)
// DB wraps a SQLite database connection.

View File

@@ -5,7 +5,7 @@ import (
"errors"
"fmt"
"git.wntrmute.dev/kyle/mcr/internal/gc"
"git.wntrmute.dev/mc/mcr/internal/gc"
)
// FindAndDeleteUnreferencedBlobs finds all blob rows with no manifest_blobs

View File

@@ -1,7 +1,7 @@
package db
import (
mcdsldb "git.wntrmute.dev/kyle/mcdsl/db"
mcdsldb "git.wntrmute.dev/mc/mcdsl/db"
)
// Migrations is the ordered list of MCR schema migrations.

View File

@@ -4,7 +4,7 @@ import (
"encoding/json"
"fmt"
"git.wntrmute.dev/kyle/mcr/internal/policy"
"git.wntrmute.dev/mc/mcr/internal/policy"
)
// ruleBody is the JSON structure stored in the rule_json column.

View File

@@ -3,7 +3,7 @@ package db
import (
"testing"
"git.wntrmute.dev/kyle/mcr/internal/policy"
"git.wntrmute.dev/mc/mcr/internal/policy"
)
func TestLoadEnabledPolicyRules(t *testing.T) {

View File

@@ -3,7 +3,7 @@ package grpcserver
import (
"context"
pb "git.wntrmute.dev/kyle/mcr/gen/mcr/v1"
pb "git.wntrmute.dev/mc/mcr/gen/mcr/v1"
)
// adminService implements pb.AdminServiceServer.

View File

@@ -4,7 +4,7 @@ import (
"context"
"testing"
pb "git.wntrmute.dev/kyle/mcr/gen/mcr/v1"
pb "git.wntrmute.dev/mc/mcr/gen/mcr/v1"
)
func TestHealthReturnsOk(t *testing.T) {

View File

@@ -6,8 +6,8 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
pb "git.wntrmute.dev/kyle/mcr/gen/mcr/v1"
"git.wntrmute.dev/kyle/mcr/internal/db"
pb "git.wntrmute.dev/mc/mcr/gen/mcr/v1"
"git.wntrmute.dev/mc/mcr/internal/db"
)
// auditService implements pb.AuditServiceServer.

View File

@@ -3,7 +3,7 @@ package grpcserver
import (
"testing"
pb "git.wntrmute.dev/kyle/mcr/gen/mcr/v1"
pb "git.wntrmute.dev/mc/mcr/gen/mcr/v1"
)
func TestListAuditEventsEmpty(t *testing.T) {

View File

@@ -1,7 +1,7 @@
package grpcserver
import (
mcdslgrpc "git.wntrmute.dev/kyle/mcdsl/grpcserver"
mcdslgrpc "git.wntrmute.dev/mc/mcdsl/grpcserver"
)
// methodMap builds the mcdsl grpcserver.MethodMap for MCR.

View File

@@ -16,10 +16,10 @@ import (
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
mcdslauth "git.wntrmute.dev/kyle/mcdsl/auth"
mcdslauth "git.wntrmute.dev/mc/mcdsl/auth"
pb "git.wntrmute.dev/kyle/mcr/gen/mcr/v1"
"git.wntrmute.dev/kyle/mcr/internal/db"
pb "git.wntrmute.dev/mc/mcr/gen/mcr/v1"
"git.wntrmute.dev/mc/mcr/internal/db"
)
// mockMCIAS starts a fake MCIAS HTTP server for token validation.

View File

@@ -9,11 +9,11 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
mcdslauth "git.wntrmute.dev/kyle/mcdsl/auth"
mcdslauth "git.wntrmute.dev/mc/mcdsl/auth"
pb "git.wntrmute.dev/kyle/mcr/gen/mcr/v1"
"git.wntrmute.dev/kyle/mcr/internal/db"
"git.wntrmute.dev/kyle/mcr/internal/policy"
pb "git.wntrmute.dev/mc/mcr/gen/mcr/v1"
"git.wntrmute.dev/mc/mcr/internal/db"
"git.wntrmute.dev/mc/mcr/internal/policy"
)
var validActions = map[string]bool{

View File

@@ -6,8 +6,8 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
pb "git.wntrmute.dev/kyle/mcr/gen/mcr/v1"
"git.wntrmute.dev/kyle/mcr/internal/policy"
pb "git.wntrmute.dev/mc/mcr/gen/mcr/v1"
"git.wntrmute.dev/mc/mcr/internal/policy"
)
type fakePolicyReloader struct {

View File

@@ -11,11 +11,11 @@ import (
"github.com/google/uuid"
mcdslauth "git.wntrmute.dev/kyle/mcdsl/auth"
mcdslauth "git.wntrmute.dev/mc/mcdsl/auth"
pb "git.wntrmute.dev/kyle/mcr/gen/mcr/v1"
"git.wntrmute.dev/kyle/mcr/internal/db"
"git.wntrmute.dev/kyle/mcr/internal/gc"
pb "git.wntrmute.dev/mc/mcr/gen/mcr/v1"
"git.wntrmute.dev/mc/mcr/internal/db"
"git.wntrmute.dev/mc/mcr/internal/gc"
)
// registryService implements pb.RegistryServiceServer.
@@ -78,8 +78,9 @@ func (s *registryService) GetRepository(_ context.Context, req *pb.GetRepository
}
for _, t := range detail.Tags {
resp.Tags = append(resp.Tags, &pb.TagInfo{
Name: t.Name,
Digest: t.Digest,
Name: t.Name,
Digest: t.Digest,
UpdatedAt: t.UpdatedAt,
})
}
for _, m := range detail.Manifests {

View File

@@ -8,9 +8,9 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
mcdslauth "git.wntrmute.dev/kyle/mcdsl/auth"
mcdslauth "git.wntrmute.dev/mc/mcdsl/auth"
pb "git.wntrmute.dev/kyle/mcr/gen/mcr/v1"
pb "git.wntrmute.dev/mc/mcr/gen/mcr/v1"
)
// testMCIAS is a package-level variable set by adminDeps for reuse.

View File

@@ -11,13 +11,13 @@ import (
"net"
"sync"
mcdslauth "git.wntrmute.dev/kyle/mcdsl/auth"
mcdslgrpc "git.wntrmute.dev/kyle/mcdsl/grpcserver"
mcdslauth "git.wntrmute.dev/mc/mcdsl/auth"
mcdslgrpc "git.wntrmute.dev/mc/mcdsl/grpcserver"
pb "git.wntrmute.dev/kyle/mcr/gen/mcr/v1"
"git.wntrmute.dev/kyle/mcr/internal/db"
"git.wntrmute.dev/kyle/mcr/internal/gc"
"git.wntrmute.dev/kyle/mcr/internal/policy"
pb "git.wntrmute.dev/mc/mcr/gen/mcr/v1"
"git.wntrmute.dev/mc/mcr/internal/db"
"git.wntrmute.dev/mc/mcr/internal/gc"
"git.wntrmute.dev/mc/mcr/internal/policy"
)
// AuditFunc is a callback for recording audit events. It follows the same
@@ -65,7 +65,7 @@ type Server struct {
//
// If certFile or keyFile is empty, TLS is skipped (for testing only).
func New(certFile, keyFile string, deps Deps, logger *slog.Logger) (*Server, error) {
srv, err := mcdslgrpc.New(certFile, keyFile, deps.Authenticator, methodMap(), logger)
srv, err := mcdslgrpc.New(certFile, keyFile, deps.Authenticator, methodMap(), logger, nil)
if err != nil {
return nil, err
}

View File

@@ -7,8 +7,8 @@ import (
"net/http"
"strconv"
"git.wntrmute.dev/kyle/mcr/internal/db"
"git.wntrmute.dev/kyle/mcr/internal/policy"
"git.wntrmute.dev/mc/mcr/internal/db"
"git.wntrmute.dev/mc/mcr/internal/policy"
)
func (h *Handler) handleBlobGet(w http.ResponseWriter, r *http.Request, repo, digest string) {

View File

@@ -6,7 +6,7 @@ import (
"net/http"
"strconv"
"git.wntrmute.dev/kyle/mcr/internal/policy"
"git.wntrmute.dev/mc/mcr/internal/policy"
)
type catalogResponse struct {

View File

@@ -5,8 +5,8 @@ import (
"fmt"
"net/http"
"git.wntrmute.dev/kyle/mcr/internal/db"
"git.wntrmute.dev/kyle/mcr/internal/policy"
"git.wntrmute.dev/mc/mcr/internal/db"
"git.wntrmute.dev/mc/mcr/internal/policy"
)
// handleManifestDelete handles DELETE /v2/<name>/manifests/<digest>.

View File

@@ -6,10 +6,10 @@ import (
"net/http"
"strings"
"git.wntrmute.dev/kyle/mcr/internal/auth"
"git.wntrmute.dev/kyle/mcr/internal/db"
"git.wntrmute.dev/kyle/mcr/internal/policy"
"git.wntrmute.dev/kyle/mcr/internal/storage"
"git.wntrmute.dev/mc/mcr/internal/auth"
"git.wntrmute.dev/mc/mcr/internal/db"
"git.wntrmute.dev/mc/mcr/internal/policy"
"git.wntrmute.dev/mc/mcr/internal/storage"
)
// DBQuerier provides the database operations needed by OCI handlers.

View File

@@ -10,10 +10,10 @@ import (
"github.com/go-chi/chi/v5"
"git.wntrmute.dev/kyle/mcr/internal/auth"
"git.wntrmute.dev/kyle/mcr/internal/db"
"git.wntrmute.dev/kyle/mcr/internal/policy"
"git.wntrmute.dev/kyle/mcr/internal/storage"
"git.wntrmute.dev/mc/mcr/internal/auth"
"git.wntrmute.dev/mc/mcr/internal/db"
"git.wntrmute.dev/mc/mcr/internal/policy"
"git.wntrmute.dev/mc/mcr/internal/storage"
)
// manifestKey uniquely identifies a manifest for test lookup.

View File

@@ -10,9 +10,9 @@ import (
"net/http"
"strconv"
"git.wntrmute.dev/kyle/mcr/internal/auth"
"git.wntrmute.dev/kyle/mcr/internal/db"
"git.wntrmute.dev/kyle/mcr/internal/policy"
"git.wntrmute.dev/mc/mcr/internal/auth"
"git.wntrmute.dev/mc/mcr/internal/db"
"git.wntrmute.dev/mc/mcr/internal/policy"
)
func (h *Handler) handleManifestGet(w http.ResponseWriter, r *http.Request, repo, reference string) {

View File

@@ -7,8 +7,8 @@ import (
"net/http"
"strconv"
"git.wntrmute.dev/kyle/mcr/internal/db"
"git.wntrmute.dev/kyle/mcr/internal/policy"
"git.wntrmute.dev/mc/mcr/internal/db"
"git.wntrmute.dev/mc/mcr/internal/policy"
)
type tagListResponse struct {

View File

@@ -8,9 +8,9 @@ import (
"net/http"
"sync"
"git.wntrmute.dev/kyle/mcr/internal/db"
"git.wntrmute.dev/kyle/mcr/internal/policy"
"git.wntrmute.dev/kyle/mcr/internal/storage"
"git.wntrmute.dev/mc/mcr/internal/db"
"git.wntrmute.dev/mc/mcr/internal/policy"
"git.wntrmute.dev/mc/mcr/internal/storage"
)
// uploadManager tracks in-progress blob writers by UUID.

View File

@@ -12,8 +12,8 @@ import (
"github.com/go-chi/chi/v5"
"git.wntrmute.dev/kyle/mcr/internal/auth"
"git.wntrmute.dev/kyle/mcr/internal/storage"
"git.wntrmute.dev/mc/mcr/internal/auth"
"git.wntrmute.dev/mc/mcr/internal/storage"
)
// testHandlerWithStorage creates a handler with real storage in t.TempDir().

View File

@@ -4,7 +4,7 @@ import (
"encoding/json"
"net/http"
"git.wntrmute.dev/kyle/mcr/internal/auth"
"git.wntrmute.dev/mc/mcr/internal/auth"
)
type adminErrorResponse struct {

View File

@@ -4,7 +4,7 @@ import (
"net/http"
"strconv"
"git.wntrmute.dev/kyle/mcr/internal/db"
"git.wntrmute.dev/mc/mcr/internal/db"
)
// AdminListAuditHandler handles GET /v1/audit.

View File

@@ -4,7 +4,7 @@ import (
"encoding/json"
"testing"
"git.wntrmute.dev/kyle/mcr/internal/db"
"git.wntrmute.dev/mc/mcr/internal/db"
)
func TestAdminListAuditEvents(t *testing.T) {

View File

@@ -6,7 +6,7 @@ import (
"github.com/go-chi/chi/v5"
"git.wntrmute.dev/kyle/mcr/internal/auth"
"git.wntrmute.dev/mc/mcr/internal/auth"
)
func TestAdminHealthHandler(t *testing.T) {

View File

@@ -9,7 +9,7 @@ import (
"github.com/google/uuid"
"git.wntrmute.dev/kyle/mcr/internal/gc"
"git.wntrmute.dev/mc/mcr/internal/gc"
)
// GCLastRun records the result of the last GC run.

View File

@@ -9,9 +9,9 @@ import (
"github.com/go-chi/chi/v5"
"git.wntrmute.dev/kyle/mcr/internal/auth"
"git.wntrmute.dev/kyle/mcr/internal/db"
"git.wntrmute.dev/kyle/mcr/internal/policy"
"git.wntrmute.dev/mc/mcr/internal/auth"
"git.wntrmute.dev/mc/mcr/internal/db"
"git.wntrmute.dev/mc/mcr/internal/policy"
)
// PolicyReloader can reload policy rules from a store.

View File

@@ -5,7 +5,7 @@ import (
"fmt"
"testing"
"git.wntrmute.dev/kyle/mcr/internal/db"
"git.wntrmute.dev/mc/mcr/internal/db"
)
func TestAdminPolicyCRUDCycle(t *testing.T) {

View File

@@ -7,8 +7,8 @@ import (
"github.com/go-chi/chi/v5"
"git.wntrmute.dev/kyle/mcr/internal/auth"
"git.wntrmute.dev/kyle/mcr/internal/db"
"git.wntrmute.dev/mc/mcr/internal/auth"
"git.wntrmute.dev/mc/mcr/internal/db"
)
// AdminListReposHandler handles GET /v1/repositories.

View File

@@ -4,7 +4,7 @@ import (
"encoding/json"
"testing"
"git.wntrmute.dev/kyle/mcr/internal/db"
"git.wntrmute.dev/mc/mcr/internal/db"
)
// seedRepoForAdmin inserts a repository with a manifest and tags into the test DB.

View File

@@ -3,7 +3,7 @@ package server
import (
"github.com/go-chi/chi/v5"
"git.wntrmute.dev/kyle/mcr/internal/db"
"git.wntrmute.dev/mc/mcr/internal/db"
)
// AdminDeps holds the dependencies needed by admin routes.

View File

@@ -10,9 +10,9 @@ import (
"github.com/go-chi/chi/v5"
"git.wntrmute.dev/kyle/mcr/internal/auth"
"git.wntrmute.dev/kyle/mcr/internal/db"
"git.wntrmute.dev/kyle/mcr/internal/policy"
"git.wntrmute.dev/mc/mcr/internal/auth"
"git.wntrmute.dev/mc/mcr/internal/db"
"git.wntrmute.dev/mc/mcr/internal/policy"
)
func openAdminTestDB(t *testing.T) *db.DB {

View File

@@ -5,7 +5,7 @@ import (
"net/http"
"strings"
"git.wntrmute.dev/kyle/mcr/internal/auth"
"git.wntrmute.dev/mc/mcr/internal/auth"
)
// TokenValidator abstracts token validation so the middleware can work

View File

@@ -6,7 +6,7 @@ import (
"net/http/httptest"
"testing"
"git.wntrmute.dev/kyle/mcr/internal/auth"
"git.wntrmute.dev/mc/mcr/internal/auth"
)
type fakeValidator struct {

View File

@@ -5,8 +5,8 @@ import (
"github.com/go-chi/chi/v5"
"git.wntrmute.dev/kyle/mcr/internal/auth"
"git.wntrmute.dev/kyle/mcr/internal/policy"
"git.wntrmute.dev/mc/mcr/internal/auth"
"git.wntrmute.dev/mc/mcr/internal/policy"
)
// PolicyEvaluator abstracts the policy engine for testability.

View File

@@ -8,8 +8,8 @@ import (
"github.com/go-chi/chi/v5"
"git.wntrmute.dev/kyle/mcr/internal/auth"
"git.wntrmute.dev/kyle/mcr/internal/policy"
"git.wntrmute.dev/mc/mcr/internal/auth"
"git.wntrmute.dev/mc/mcr/internal/policy"
)
type fakePolicyEvaluator struct {

View File

@@ -6,7 +6,7 @@ import (
"net/http/httptest"
"testing"
"git.wntrmute.dev/kyle/mcr/internal/auth"
"git.wntrmute.dev/mc/mcr/internal/auth"
)
func TestRoutesV2Authenticated(t *testing.T) {

View File

@@ -6,7 +6,7 @@ import (
"net/http/httptest"
"testing"
"git.wntrmute.dev/kyle/mcr/internal/auth"
"git.wntrmute.dev/mc/mcr/internal/auth"
)
type fakeLoginClient struct {

View File

@@ -8,6 +8,7 @@ import (
"encoding/hex"
"log"
"net/http"
"slices"
"strings"
)
@@ -93,6 +94,31 @@ func (s *Server) handleLoginSubmit(w http.ResponseWriter, r *http.Request) {
return
}
// Validate the token to check roles. Guest accounts are not
// permitted to use the web interface.
roles, err := s.validateFn(token)
if err != nil {
log.Printf("login token validation failed for user %q: %v", username, err)
csrf := s.generateCSRFToken(w)
s.templates.render(w, "login", map[string]any{
"Error": "Login failed. Please try again.",
"CSRFToken": csrf,
"Session": false,
})
return
}
if slices.Contains(roles, "guest") {
log.Printf("login denied for guest user %q", username)
csrf := s.generateCSRFToken(w)
s.templates.render(w, "login", map[string]any{
"Error": "Guest accounts are not permitted to access the web interface.",
"CSRFToken": csrf,
"Session": false,
})
return
}
http.SetCookie(w, &http.Cookie{
Name: "mcr_session",
Value: token,

View File

@@ -7,7 +7,7 @@ import (
"strconv"
"strings"
mcrv1 "git.wntrmute.dev/kyle/mcr/gen/mcr/v1"
mcrv1 "git.wntrmute.dev/mc/mcr/gen/mcr/v1"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"

View File

@@ -14,23 +14,27 @@ import (
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
mcrv1 "git.wntrmute.dev/kyle/mcr/gen/mcr/v1"
"git.wntrmute.dev/kyle/mcr/web"
mcrv1 "git.wntrmute.dev/mc/mcr/gen/mcr/v1"
"git.wntrmute.dev/mc/mcr/web"
)
// LoginFunc authenticates a user and returns a bearer token.
type LoginFunc func(username, password string) (token string, expiresIn int, err error)
// ValidateFunc validates a bearer token and returns the user's roles.
type ValidateFunc func(token string) (roles []string, err error)
// Server is the MCR web UI server.
type Server struct {
router chi.Router
templates *templateSet
registry mcrv1.RegistryServiceClient
policy mcrv1.PolicyServiceClient
audit mcrv1.AuditServiceClient
admin mcrv1.AdminServiceClient
loginFn LoginFunc
csrfKey []byte // 32-byte key for HMAC signing
router chi.Router
templates *templateSet
registry mcrv1.RegistryServiceClient
policy mcrv1.PolicyServiceClient
audit mcrv1.AuditServiceClient
admin mcrv1.AdminServiceClient
loginFn LoginFunc
validateFn ValidateFunc
csrfKey []byte // 32-byte key for HMAC signing
}
// New creates a new web UI server with the given gRPC clients and login function.
@@ -40,6 +44,7 @@ func New(
audit mcrv1.AuditServiceClient,
admin mcrv1.AdminServiceClient,
loginFn LoginFunc,
validateFn ValidateFunc,
csrfKey []byte,
) (*Server, error) {
tmpl, err := loadTemplates()
@@ -48,13 +53,14 @@ func New(
}
s := &Server{
templates: tmpl,
registry: registry,
policy: policy,
audit: audit,
admin: admin,
loginFn: loginFn,
csrfKey: csrfKey,
templates: tmpl,
registry: registry,
policy: policy,
audit: audit,
admin: admin,
loginFn: loginFn,
validateFn: validateFn,
csrfKey: csrfKey,
}
s.router = s.buildRouter()

View File

@@ -15,7 +15,7 @@ import (
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/status"
mcrv1 "git.wntrmute.dev/kyle/mcr/gen/mcr/v1"
mcrv1 "git.wntrmute.dev/mc/mcr/gen/mcr/v1"
)
// fakeRegistryService implements RegistryServiceServer for testing.
@@ -183,15 +183,35 @@ func setupTestEnv(t *testing.T) *testEnv {
if username == "admin" && password == "secret" {
return "test-token-12345", 3600, nil
}
if username == "guest" && password == "secret" {
return "test-token-guest", 3600, nil
}
if username == "user" && password == "secret" {
return "test-token-user", 3600, nil
}
return "", 0, fmt.Errorf("invalid credentials")
}
validateFn := func(token string) ([]string, error) {
switch token {
case "test-token-12345":
return []string{"admin"}, nil
case "test-token-guest":
return []string{"guest"}, nil
case "test-token-user":
return []string{"user"}, nil
default:
return nil, fmt.Errorf("invalid token")
}
}
srv, err := New(
mcrv1.NewRegistryServiceClient(conn),
mcrv1.NewPolicyServiceClient(conn),
mcrv1.NewAuditServiceClient(conn),
mcrv1.NewAdminServiceClient(conn),
loginFn,
validateFn,
csrfKey,
)
if err != nil {
@@ -543,6 +563,59 @@ func TestTruncate(t *testing.T) {
}
}
func TestLoginDeniesGuest(t *testing.T) {
env := setupTestEnv(t)
defer env.close()
// Get CSRF token.
getReq := httptest.NewRequest(http.MethodGet, "/login", nil)
getRec := httptest.NewRecorder()
env.server.Handler().ServeHTTP(getRec, getReq)
var csrfCookie *http.Cookie
for _, c := range getRec.Result().Cookies() {
if c.Name == "csrf_token" {
csrfCookie = c
break
}
}
if csrfCookie == nil {
t.Fatal("no csrf_token cookie")
}
parts := strings.SplitN(csrfCookie.Value, ".", 2)
csrfToken := parts[0]
form := url.Values{
"username": {"guest"},
"password": {"secret"},
"_csrf": {csrfToken},
}
postReq := httptest.NewRequest(http.MethodPost, "/login", strings.NewReader(form.Encode()))
postReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
postReq.AddCookie(csrfCookie)
postRec := httptest.NewRecorder()
env.server.Handler().ServeHTTP(postRec, postReq)
if postRec.Code != http.StatusOK {
t.Fatalf("POST /login as guest: status %d, want %d", postRec.Code, http.StatusOK)
}
body := postRec.Body.String()
if !strings.Contains(body, "Guest accounts are not permitted") {
t.Error("response does not contain guest denial message")
}
// Verify no session cookie was set.
for _, c := range postRec.Result().Cookies() {
if c.Name == "mcr_session" {
t.Error("session cookie should not be set for guest login")
}
}
}
func TestLoginSuccessSetsCookie(t *testing.T) {
env := setupTestEnv(t)
defer env.close()

View File

@@ -8,7 +8,7 @@ import (
"strings"
"time"
"git.wntrmute.dev/kyle/mcr/web"
"git.wntrmute.dev/mc/mcr/web"
)
// templateSet wraps parsed templates and provides a render method.

View File

@@ -2,7 +2,7 @@ syntax = "proto3";
package mcr.v1;
option go_package = "git.wntrmute.dev/kyle/mcr/gen/mcr/v1;mcrv1";
option go_package = "git.wntrmute.dev/mc/mcr/gen/mcr/v1;mcrv1";
service AdminService {
rpc Health(HealthRequest) returns (HealthResponse);

View File

@@ -2,7 +2,7 @@ syntax = "proto3";
package mcr.v1;
option go_package = "git.wntrmute.dev/kyle/mcr/gen/mcr/v1;mcrv1";
option go_package = "git.wntrmute.dev/mc/mcr/gen/mcr/v1;mcrv1";
import "mcr/v1/common.proto";

View File

@@ -2,7 +2,7 @@ syntax = "proto3";
package mcr.v1;
option go_package = "git.wntrmute.dev/kyle/mcr/gen/mcr/v1;mcrv1";
option go_package = "git.wntrmute.dev/mc/mcr/gen/mcr/v1;mcrv1";
// Pagination controls for list RPCs.
message PaginationRequest {

View File

@@ -2,7 +2,7 @@ syntax = "proto3";
package mcr.v1;
option go_package = "git.wntrmute.dev/kyle/mcr/gen/mcr/v1;mcrv1";
option go_package = "git.wntrmute.dev/mc/mcr/gen/mcr/v1;mcrv1";
import "mcr/v1/common.proto";

View File

@@ -2,7 +2,7 @@ syntax = "proto3";
package mcr.v1;
option go_package = "git.wntrmute.dev/kyle/mcr/gen/mcr/v1;mcrv1";
option go_package = "git.wntrmute.dev/mc/mcr/gen/mcr/v1;mcrv1";
import "mcr/v1/common.proto";
@@ -25,6 +25,7 @@ message RepositoryMetadata {
message TagInfo {
string name = 1;
string digest = 2;
string updated_at = 3;
}
message ManifestInfo {

View File

@@ -34,7 +34,7 @@ import (
"github.com/pelletier/go-toml/v2"
"git.wntrmute.dev/kyle/mcdsl/auth"
"git.wntrmute.dev/mc/mcdsl/auth"
)
// Base contains the configuration sections common to all Metacircular
@@ -144,6 +144,8 @@ func Load[T any](path string, envPrefix string) (*T, error) {
applyEnvToStruct(reflect.ValueOf(&cfg).Elem(), envPrefix)
}
applyPortEnv(&cfg)
applyBaseDefaults(&cfg)
if err := validateBase(&cfg); err != nil {
@@ -239,6 +241,70 @@ func findBase(cfg any) *Base {
return nil
}
// applyPortEnv overrides ServerConfig.ListenAddr and ServerConfig.GRPCAddr
// from $PORT and $PORT_GRPC respectively. These environment variables are
// set by the MCP agent to assign authoritative port bindings, so they take
// precedence over both TOML values and generic env overrides.
func applyPortEnv(cfg any) {
sc := findServerConfig(cfg)
if sc == nil {
return
}
if port, ok := os.LookupEnv("PORT"); ok {
sc.ListenAddr = ":" + port
}
if port, ok := os.LookupEnv("PORT_GRPC"); ok {
sc.GRPCAddr = ":" + port
}
}
// findServerConfig returns a pointer to the ServerConfig in the config
// struct. It first checks for an embedded Base (which contains Server),
// then walks the struct tree via reflection to find any ServerConfig field
// directly (e.g., the Metacrypt pattern where ServerConfig is embedded
// without Base).
func findServerConfig(cfg any) *ServerConfig {
if base := findBase(cfg); base != nil {
return &base.Server
}
return findServerConfigReflect(reflect.ValueOf(cfg))
}
// findServerConfigReflect walks the struct tree to find a ServerConfig field.
func findServerConfigReflect(v reflect.Value) *ServerConfig {
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct {
return nil
}
scType := reflect.TypeOf(ServerConfig{})
t := v.Type()
for i := range t.NumField() {
field := t.Field(i)
fv := v.Field(i)
if field.Type == scType {
sc, ok := fv.Addr().Interface().(*ServerConfig)
if ok {
return sc
}
}
// Recurse into embedded or nested structs.
if fv.Kind() == reflect.Struct && field.Type != scType {
if sc := findServerConfigReflect(fv); sc != nil {
return sc
}
}
}
return nil
}
// applyEnvToStruct recursively walks a struct and overrides field values
// from environment variables. The env variable name is built from the
// prefix and the toml tag: PREFIX_SECTION_FIELD (uppercased).

View File

@@ -21,7 +21,7 @@ import (
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"git.wntrmute.dev/kyle/mcdsl/auth"
"git.wntrmute.dev/mc/mcdsl/auth"
)
// MethodMap classifies gRPC methods for access control.
@@ -48,21 +48,45 @@ type Server struct {
listener net.Listener
}
// Options configures optional behavior for the gRPC server.
type Options struct {
// PreInterceptors run before the logging and auth interceptors.
// Use for lifecycle gates like seal checks that should reject
// requests before any auth validation occurs.
PreInterceptors []grpc.UnaryServerInterceptor
// PostInterceptors run after auth but before the handler.
// Use for audit logging, rate limiting, or other cross-cutting
// concerns that need access to the authenticated identity.
PostInterceptors []grpc.UnaryServerInterceptor
}
// New creates a gRPC server with TLS (if certFile and keyFile are
// non-empty) and an interceptor chain: logging → auth → handler.
// non-empty) and an interceptor chain:
//
// [pre-interceptors] → logging → auth → [post-interceptors] → handler
//
// The auth interceptor uses methods to determine the access level for
// each RPC. Methods not in any map are denied by default.
//
// If certFile and keyFile are empty, TLS is skipped (for testing).
func New(certFile, keyFile string, authenticator *auth.Authenticator, methods MethodMap, logger *slog.Logger) (*Server, error) {
chain := grpc.ChainUnaryInterceptor(
// opts is optional; pass nil for the default chain (logging + auth only).
func New(certFile, keyFile string, authenticator *auth.Authenticator, methods MethodMap, logger *slog.Logger, opts *Options) (*Server, error) {
var interceptors []grpc.UnaryServerInterceptor
if opts != nil {
interceptors = append(interceptors, opts.PreInterceptors...)
}
interceptors = append(interceptors,
loggingInterceptor(logger),
authInterceptor(authenticator, methods),
)
if opts != nil {
interceptors = append(interceptors, opts.PostInterceptors...)
}
chain := grpc.ChainUnaryInterceptor(interceptors...)
var opts []grpc.ServerOption
opts = append(opts, chain)
var serverOpts []grpc.ServerOption
serverOpts = append(serverOpts, chain)
if certFile != "" && keyFile != "" {
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
@@ -73,11 +97,11 @@ func New(certFile, keyFile string, authenticator *auth.Authenticator, methods Me
Certificates: []tls.Certificate{cert},
MinVersion: tls.VersionTLS13,
}
opts = append(opts, grpc.Creds(credentials.NewTLS(tlsCfg)))
serverOpts = append(serverOpts, grpc.Creds(credentials.NewTLS(tlsCfg)))
}
return &Server{
GRPCServer: grpc.NewServer(opts...),
GRPCServer: grpc.NewServer(serverOpts...),
Logger: logger,
}, nil
}

10
vendor/modules.txt vendored
View File

@@ -1,9 +1,9 @@
# git.wntrmute.dev/kyle/mcdsl v1.0.0
# git.wntrmute.dev/mc/mcdsl v1.2.0
## explicit; go 1.25.7
git.wntrmute.dev/kyle/mcdsl/auth
git.wntrmute.dev/kyle/mcdsl/config
git.wntrmute.dev/kyle/mcdsl/db
git.wntrmute.dev/kyle/mcdsl/grpcserver
git.wntrmute.dev/mc/mcdsl/auth
git.wntrmute.dev/mc/mcdsl/config
git.wntrmute.dev/mc/mcdsl/db
git.wntrmute.dev/mc/mcdsl/grpcserver
# github.com/dustin/go-humanize v1.0.1
## explicit; go 1.16
github.com/dustin/go-humanize