mirror of
https://github.com/project-zot/zot.git
synced 2025-01-13 22:50:38 -05:00
ext: use distribution spec route prefix for extension api
Following the spec defined here https://github.com/opencontainers/distribution-spec/tree/main/extensions Signed-off-by: Shivam Mishra <shimish2@cisco.com>
This commit is contained in:
parent
c1bf4456d0
commit
36c9631000
50 changed files with 1076 additions and 395 deletions
2
.github/workflows/ci-cd.yml
vendored
2
.github/workflows/ci-cd.yml
vendored
|
@ -56,7 +56,7 @@ jobs:
|
||||||
- name: Install other dependencies
|
- name: Install other dependencies
|
||||||
run: |
|
run: |
|
||||||
cd $GITHUB_WORKSPACE
|
cd $GITHUB_WORKSPACE
|
||||||
go install github.com/swaggo/swag/cmd/swag@latest
|
go install github.com/swaggo/swag/cmd/swag@v1.6.3
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install rpm
|
sudo apt-get install rpm
|
||||||
sudo apt-get install snapd
|
sudo apt-get install snapd
|
||||||
|
|
4
Makefile
4
Makefile
|
@ -102,11 +102,11 @@ check: ./golangcilint.yaml $(GOLINTER)
|
||||||
$(GOLINTER) --config ./golangcilint.yaml run --enable-all --out-format=colored-line-number --build-tags stress,extended,containers_image_openpgp ./...
|
$(GOLINTER) --config ./golangcilint.yaml run --enable-all --out-format=colored-line-number --build-tags stress,extended,containers_image_openpgp ./...
|
||||||
|
|
||||||
swagger/docs.go:
|
swagger/docs.go:
|
||||||
swag -v || go install github.com/swaggo/swag/cmd/swag
|
swag -v || go install github.com/swaggo/swag/cmd/swag@1.6.3
|
||||||
swag init -o swagger -g pkg/api/routes.go
|
swag init -o swagger -g pkg/api/routes.go
|
||||||
|
|
||||||
.PHONY: swagger
|
.PHONY: swagger
|
||||||
swagger: swagger/docs.go
|
swagger: swagger/docs.go pkg/api/routes.go
|
||||||
|
|
||||||
.PHONY: update-licenses
|
.PHONY: update-licenses
|
||||||
update-licenses:
|
update-licenses:
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
godigest "github.com/opencontainers/go-digest"
|
godigest "github.com/opencontainers/go-digest"
|
||||||
"gopkg.in/resty.v1"
|
"gopkg.in/resty.v1"
|
||||||
|
"zotregistry.io/zot/pkg/api/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -323,7 +324,7 @@ func GetCatalog(workdir, url, auth, repo string, requests int, config testConfig
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// send request and get response
|
// send request and get response
|
||||||
resp, err := client.R().Get(url + "/v2/_catalog")
|
resp, err := client.R().Get(url + constants.RoutePrefix + constants.ExtCatalogPrefix)
|
||||||
|
|
||||||
latency = time.Since(start)
|
latency = time.Since(start)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion": "1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage": {
|
"storage": {
|
||||||
"rootDirectory": "/tmp/zot"
|
"rootDirectory": "/tmp/zot"
|
||||||
},
|
},
|
||||||
|
@ -11,31 +11,34 @@
|
||||||
"level": "debug"
|
"level": "debug"
|
||||||
},
|
},
|
||||||
"extensions": {
|
"extensions": {
|
||||||
"metrics": {
|
"metrics": {},
|
||||||
},
|
|
||||||
"sync": {
|
"sync": {
|
||||||
"credentialsFile": "./examples/sync-auth-filepath.json",
|
"credentialsFile": "./examples/sync-auth-filepath.json",
|
||||||
"registries": [{
|
"registries": [
|
||||||
"urls": ["https://registry1:5000"],
|
{
|
||||||
"onDemand": false,
|
"urls": [
|
||||||
"pollInterval": "6h",
|
"https://registry1:5000"
|
||||||
"tlsVerify": true,
|
],
|
||||||
"certDir": "/home/user/certs",
|
"onDemand": false,
|
||||||
"maxRetries": 3,
|
"pollInterval": "6h",
|
||||||
"retryDelay": "15m",
|
"tlsVerify": true,
|
||||||
"content":[
|
"certDir": "/home/user/certs",
|
||||||
{
|
"maxRetries": 3,
|
||||||
"prefix":"/repo1/repo",
|
"retryDelay": "15m",
|
||||||
"tags":{
|
"content": [
|
||||||
"regex":"4.*",
|
{
|
||||||
"semver":true
|
"prefix": "/repo1/repo",
|
||||||
|
"tags": {
|
||||||
|
"regex": "4.*",
|
||||||
|
"semver": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"prefix": "/repo2/repo"
|
||||||
}
|
}
|
||||||
},
|
]
|
||||||
{
|
}
|
||||||
"prefix":"/repo2/repo"
|
]
|
||||||
}
|
|
||||||
]
|
|
||||||
}]
|
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"cve": {
|
"cve": {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion":"1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage":{
|
"storage": {
|
||||||
"rootDirectory":"/tmp/zot"
|
"rootDirectory": "/tmp/zot"
|
||||||
},
|
},
|
||||||
"http": {
|
"http": {
|
||||||
"address":"127.0.0.1",
|
"address": "127.0.0.1",
|
||||||
"port":"8080",
|
"port": "8080",
|
||||||
"auth": {
|
"auth": {
|
||||||
"bearer": {
|
"bearer": {
|
||||||
"realm": "https://auth.myreg.io/auth/token",
|
"realm": "https://auth.myreg.io/auth/token",
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"log":{
|
"log": {
|
||||||
"level":"debug"
|
"level": "debug"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion": "1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage": {
|
"storage": {
|
||||||
"rootDirectory": "/tmp/zot"
|
"rootDirectory": "/tmp/zot"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion": "1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage": {
|
"storage": {
|
||||||
"rootDirectory": "/tmp/zot",
|
"rootDirectory": "/tmp/zot",
|
||||||
"commit": true
|
"commit": true
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion":"1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage":{
|
"storage": {
|
||||||
"rootDirectory":"/tmp/zot",
|
"rootDirectory": "/tmp/zot",
|
||||||
"gc": false,
|
"gc": false,
|
||||||
"dedupe": false
|
"dedupe": false
|
||||||
},
|
},
|
||||||
"http": {
|
"http": {
|
||||||
"address":"0.0.0.0",
|
"address": "0.0.0.0",
|
||||||
"port":"8080"
|
"port": "8080"
|
||||||
},
|
},
|
||||||
"log":{
|
"log": {
|
||||||
"level":"debug"
|
"level": "debug"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion": "1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage": {
|
"storage": {
|
||||||
"rootDirectory": "/tmp/zot"
|
"rootDirectory": "/tmp/zot"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,30 +1,39 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion": "1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage": {
|
"storage": {
|
||||||
"rootDirectory": "/tmp/zot"
|
"rootDirectory": "/tmp/zot"
|
||||||
},
|
},
|
||||||
"http": {
|
"http": {
|
||||||
"address": "127.0.0.1",
|
"address": "127.0.0.1",
|
||||||
"port": "8080",
|
"port": "8080",
|
||||||
"realm": "zot",
|
"realm": "zot",
|
||||||
"accessControl": {
|
"accessControl": {
|
||||||
"**": {
|
"**": {
|
||||||
"defaultPolicy": ["read", "create"]
|
"defaultPolicy": [
|
||||||
},
|
"read",
|
||||||
"tmp/**": {
|
"create"
|
||||||
"defaultPolicy": ["read", "create", "update"]
|
]
|
||||||
},
|
},
|
||||||
"infra/**": {
|
"tmp/**": {
|
||||||
"defaultPolicy": ["read"]
|
"defaultPolicy": [
|
||||||
},
|
"read",
|
||||||
"repos2/repo": {
|
"create",
|
||||||
"defaultPolicy": ["read"]
|
"update"
|
||||||
}
|
]
|
||||||
|
},
|
||||||
|
"infra/**": {
|
||||||
|
"defaultPolicy": [
|
||||||
|
"read"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"repos2/repo": {
|
||||||
|
"defaultPolicy": [
|
||||||
|
"read"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"log": {
|
|
||||||
"level": "debug"
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"log": {
|
||||||
|
"level": "debug"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion":"1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage":{
|
"storage": {
|
||||||
"rootDirectory":"/tmp/zot"
|
"rootDirectory": "/tmp/zot"
|
||||||
},
|
},
|
||||||
"http": {
|
"http": {
|
||||||
"address":"127.0.0.1",
|
"address": "127.0.0.1",
|
||||||
"port":"8080",
|
"port": "8080",
|
||||||
"realm":"zot",
|
"realm": "zot",
|
||||||
"tls": {
|
"tls": {
|
||||||
"cert":"test/data/server.cert",
|
"cert": "test/data/server.cert",
|
||||||
"key":"test/data/server.key"
|
"key": "test/data/server.key"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"address":"ldap.example.org",
|
"address": "ldap.example.org",
|
||||||
"port":389,
|
"port": 389,
|
||||||
"startTLS":false,
|
"startTLS": false,
|
||||||
"baseDN":"ou=Users,dc=example,dc=org",
|
"baseDN": "ou=Users,dc=example,dc=org",
|
||||||
"userAttribute":"uid",
|
"userAttribute": "uid",
|
||||||
"bindDN":"cn=ldap-searcher,ou=Users,dc=example,dc=org",
|
"bindDN": "cn=ldap-searcher,ou=Users,dc=example,dc=org",
|
||||||
"bindPassword":"ldap-searcher-password",
|
"bindPassword": "ldap-searcher-password",
|
||||||
"skipVerify":false,
|
"skipVerify": false,
|
||||||
"subtreeSearch":true
|
"subtreeSearch": true
|
||||||
},
|
},
|
||||||
"htpasswd": {
|
"htpasswd": {
|
||||||
"path": "test/data/htpasswd"
|
"path": "test/data/htpasswd"
|
||||||
|
@ -30,9 +30,9 @@
|
||||||
},
|
},
|
||||||
"allowReadAccess": false
|
"allowReadAccess": false
|
||||||
},
|
},
|
||||||
"log":{
|
"log": {
|
||||||
"level":"debug",
|
"level": "debug",
|
||||||
"output":"/tmp/zot.log",
|
"output": "/tmp/zot.log",
|
||||||
"audit": "/tmp/zot-audit.log"
|
"audit": "/tmp/zot-audit.log"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
distspecversion: 1.0.1
|
distspecversion: 1.0.1-dev
|
||||||
http:
|
http:
|
||||||
address: 127.0.0.1
|
address: 127.0.0.1
|
||||||
allowreadaccess: false
|
allowreadaccess: false
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion":"1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage": {
|
"storage": {
|
||||||
"rootDirectory": "/tmp/zot",
|
"rootDirectory": "/tmp/zot",
|
||||||
"gc": true,
|
"gc": true,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion": "1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage": {
|
"storage": {
|
||||||
"rootDirectory": "/tmp/zot",
|
"rootDirectory": "/tmp/zot",
|
||||||
"gc": true,
|
"gc": true,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion": "1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage": {
|
"storage": {
|
||||||
"rootDirectory": "/tmp/zot"
|
"rootDirectory": "/tmp/zot"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion": "1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage": {
|
"storage": {
|
||||||
"rootDirectory": "/tmp/zot"
|
"rootDirectory": "/tmp/zot"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion": "1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage": {
|
"storage": {
|
||||||
"rootDirectory": "/tmp/zot",
|
"rootDirectory": "/tmp/zot",
|
||||||
"dedupe": true,
|
"dedupe": true,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion": "1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage": {
|
"storage": {
|
||||||
"rootDirectory": "/tmp/zot",
|
"rootDirectory": "/tmp/zot",
|
||||||
"dedupe": true,
|
"dedupe": true,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion": "1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage": {
|
"storage": {
|
||||||
"rootDirectory": "/tmp/zot"
|
"rootDirectory": "/tmp/zot"
|
||||||
},
|
},
|
||||||
|
@ -17,44 +17,91 @@
|
||||||
"**": {
|
"**": {
|
||||||
"policies": [
|
"policies": [
|
||||||
{
|
{
|
||||||
"users": ["charlie"],
|
"users": [
|
||||||
"actions": ["read", "create", "update"]
|
"charlie"
|
||||||
|
],
|
||||||
|
"actions": [
|
||||||
|
"read",
|
||||||
|
"create",
|
||||||
|
"update"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"defaultPolicy": ["read", "create"]
|
"defaultPolicy": [
|
||||||
|
"read",
|
||||||
|
"create"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"tmp/**": {
|
"tmp/**": {
|
||||||
"defaultPolicy": ["read", "create", "update"]
|
"defaultPolicy": [
|
||||||
|
"read",
|
||||||
|
"create",
|
||||||
|
"update"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"infra/**": {
|
"infra/**": {
|
||||||
"policies": [
|
"policies": [
|
||||||
{
|
{
|
||||||
"users": ["alice", "bob"],
|
"users": [
|
||||||
"actions": ["create", "read", "update", "delete"]
|
"alice",
|
||||||
|
"bob"
|
||||||
|
],
|
||||||
|
"actions": [
|
||||||
|
"create",
|
||||||
|
"read",
|
||||||
|
"update",
|
||||||
|
"delete"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"users": ["mallory"],
|
"users": [
|
||||||
"actions": ["create", "read"]
|
"mallory"
|
||||||
|
],
|
||||||
|
"actions": [
|
||||||
|
"create",
|
||||||
|
"read"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"defaultPolicy": ["read"]
|
"defaultPolicy": [
|
||||||
|
"read"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"repos2/repo": {
|
"repos2/repo": {
|
||||||
"policies": [
|
"policies": [
|
||||||
{
|
{
|
||||||
"users": ["charlie"],
|
"users": [
|
||||||
"actions": ["read", "create"]
|
"charlie"
|
||||||
|
],
|
||||||
|
"actions": [
|
||||||
|
"read",
|
||||||
|
"create"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"users": ["mallory"],
|
"users": [
|
||||||
"actions": ["create", "read"]
|
"mallory"
|
||||||
|
],
|
||||||
|
"actions": [
|
||||||
|
"create",
|
||||||
|
"read"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"defaultPolicy": ["read"]
|
"defaultPolicy": [
|
||||||
|
"read"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"adminPolicy": {
|
"adminPolicy": {
|
||||||
"users": ["admin"],
|
"users": [
|
||||||
"actions": ["read", "create", "update", "delete"]
|
"admin"
|
||||||
|
],
|
||||||
|
"actions": [
|
||||||
|
"read",
|
||||||
|
"create",
|
||||||
|
"update",
|
||||||
|
"delete"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -63,4 +110,3 @@
|
||||||
"output": "/tmp/zot.log"
|
"output": "/tmp/zot.log"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion": "1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage": {
|
"storage": {
|
||||||
"rootDirectory": "/tmp/zot"
|
"rootDirectory": "/tmp/zot"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion": "1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage": {
|
"storage": {
|
||||||
"rootDirectory": "/zot",
|
"rootDirectory": "/zot",
|
||||||
"storageDriver": {
|
"storageDriver": {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion":"1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage": {
|
"storage": {
|
||||||
"rootDirectory": "/tmp/zot"
|
"rootDirectory": "/tmp/zot"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,68 +1,76 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion":"1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage":{
|
"storage": {
|
||||||
"rootDirectory":"/tmp/zot"
|
"rootDirectory": "/tmp/zot"
|
||||||
},
|
},
|
||||||
"http":{
|
"http": {
|
||||||
"address":"127.0.0.1",
|
"address": "127.0.0.1",
|
||||||
"port":"8080"
|
"port": "8080"
|
||||||
},
|
},
|
||||||
"log":{
|
"log": {
|
||||||
"level":"debug"
|
"level": "debug"
|
||||||
},
|
},
|
||||||
"extensions":{
|
"extensions": {
|
||||||
"sync": {
|
"sync": {
|
||||||
"enable": true,
|
"enable": true,
|
||||||
"credentialsFile": "./examples/sync-auth-filepath.json",
|
"credentialsFile": "./examples/sync-auth-filepath.json",
|
||||||
"registries": [{
|
"registries": [
|
||||||
"urls": ["https://registry1:5000"],
|
{
|
||||||
"onDemand": false,
|
"urls": [
|
||||||
"pollInterval": "6h",
|
"https://registry1:5000"
|
||||||
"tlsVerify": true,
|
],
|
||||||
"certDir": "/home/user/certs",
|
"onDemand": false,
|
||||||
"maxRetries": 3,
|
"pollInterval": "6h",
|
||||||
"retryDelay": "5m",
|
"tlsVerify": true,
|
||||||
"onlySigned": true,
|
"certDir": "/home/user/certs",
|
||||||
"content":[
|
"maxRetries": 3,
|
||||||
{
|
"retryDelay": "5m",
|
||||||
"prefix":"/repo1/repo",
|
"onlySigned": true,
|
||||||
"tags":{
|
"content": [
|
||||||
"regex":"4.*",
|
{
|
||||||
"semver":true
|
"prefix": "/repo1/repo",
|
||||||
|
"tags": {
|
||||||
|
"regex": "4.*",
|
||||||
|
"semver": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"prefix": "/repo1/repo",
|
||||||
|
"destination": "/repo",
|
||||||
|
"stripPrefix": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"prefix": "/repo2/repo"
|
||||||
}
|
}
|
||||||
},
|
]
|
||||||
{
|
},
|
||||||
"prefix":"/repo1/repo",
|
{
|
||||||
"destination": "/repo",
|
"urls": [
|
||||||
"stripPrefix": true
|
"https://registry2:5000",
|
||||||
},
|
"https://registry3:5000"
|
||||||
{
|
],
|
||||||
"prefix":"/repo2/repo"
|
"pollInterval": "12h",
|
||||||
}
|
"tlsVerify": false,
|
||||||
]
|
"onDemand": false,
|
||||||
},
|
"content": [
|
||||||
{
|
{
|
||||||
"urls": ["https://registry2:5000", "https://registry3:5000"],
|
"prefix": "/repo2",
|
||||||
"pollInterval": "12h",
|
"tags": {
|
||||||
"tlsVerify": false,
|
"semver": true
|
||||||
"onDemand": false,
|
}
|
||||||
"content":[
|
|
||||||
{
|
|
||||||
"prefix":"/repo2",
|
|
||||||
"tags":{
|
|
||||||
"semver":true
|
|
||||||
}
|
}
|
||||||
}
|
]
|
||||||
]
|
},
|
||||||
},
|
{
|
||||||
{
|
"urls": [
|
||||||
"urls": ["https://docker.io/library"],
|
"https://docker.io/library"
|
||||||
"onDemand": true,
|
],
|
||||||
"tlsVerify": true,
|
"onDemand": true,
|
||||||
"maxRetries": 6,
|
"tlsVerify": true,
|
||||||
"retryDelay": "5m"
|
"maxRetries": 6,
|
||||||
}
|
"retryDelay": "5m"
|
||||||
]
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion":"1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage":{
|
"storage": {
|
||||||
"rootDirectory":"/tmp/zot"
|
"rootDirectory": "/tmp/zot"
|
||||||
},
|
},
|
||||||
"http": {
|
"http": {
|
||||||
"address":"127.0.0.1",
|
"address": "127.0.0.1",
|
||||||
"port":"8080"
|
"port": "8080"
|
||||||
},
|
},
|
||||||
"log":{
|
"log": {
|
||||||
"level":"debug"
|
"level": "debug"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
{
|
{
|
||||||
"distSpecVersion":"1.0.1",
|
"distSpecVersion": "1.0.1-dev",
|
||||||
"storage":{
|
"storage": {
|
||||||
"rootDirectory":"/tmp/zot"
|
"rootDirectory": "/tmp/zot"
|
||||||
},
|
},
|
||||||
"http": {
|
"http": {
|
||||||
"address":"127.0.0.1",
|
"address": "127.0.0.1",
|
||||||
"port":"8080",
|
"port": "8080",
|
||||||
"realm":"zot",
|
"realm": "zot",
|
||||||
"tls": {
|
"tls": {
|
||||||
"cert":"test/data/server.cert",
|
"cert": "test/data/server.cert",
|
||||||
"key":"test/data/server.key"
|
"key": "test/data/server.key"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"log":{
|
"log": {
|
||||||
"level":"debug"
|
"level": "debug"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
17
go.mod
17
go.mod
|
@ -47,7 +47,6 @@ require (
|
||||||
github.com/spf13/cobra v1.4.0
|
github.com/spf13/cobra v1.4.0
|
||||||
github.com/spf13/viper v1.11.0
|
github.com/spf13/viper v1.11.0
|
||||||
github.com/stretchr/testify v1.7.1
|
github.com/stretchr/testify v1.7.1
|
||||||
github.com/swaggo/http-swagger v1.2.6
|
|
||||||
github.com/swaggo/swag v1.8.1
|
github.com/swaggo/swag v1.8.1
|
||||||
github.com/urfave/cli/v2 v2.4.0
|
github.com/urfave/cli/v2 v2.4.0
|
||||||
github.com/vektah/gqlparser/v2 v2.4.1
|
github.com/vektah/gqlparser/v2 v2.4.1
|
||||||
|
@ -57,9 +56,11 @@ require (
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
require github.com/open-policy-agent/opa v0.37.0 // indirect
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/open-policy-agent/opa v0.37.0 // indirect
|
github.com/opencontainers/distribution-spec/specs-go v0.0.0-20220217185014-dd38b7ed8a99
|
||||||
github.com/opencontainers/distribution-spec v1.0.1
|
github.com/swaggo/http-swagger v1.2.8
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
@ -90,8 +91,6 @@ require (
|
||||||
github.com/PaesslerAG/gval v1.0.0 // indirect
|
github.com/PaesslerAG/gval v1.0.0 // indirect
|
||||||
github.com/PaesslerAG/jsonpath v0.1.1 // indirect
|
github.com/PaesslerAG/jsonpath v0.1.1 // indirect
|
||||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
|
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
|
||||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
|
||||||
github.com/ThalesIgnite/crypto11 v1.2.5 // indirect
|
github.com/ThalesIgnite/crypto11 v1.2.5 // indirect
|
||||||
github.com/VividCortex/ewma v1.2.0 // indirect
|
github.com/VividCortex/ewma v1.2.0 // indirect
|
||||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
|
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
|
||||||
|
@ -179,10 +178,10 @@ require (
|
||||||
github.com/go-openapi/analysis v0.21.2 // indirect
|
github.com/go-openapi/analysis v0.21.2 // indirect
|
||||||
github.com/go-openapi/errors v0.20.2 // indirect
|
github.com/go-openapi/errors v0.20.2 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||||
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
github.com/go-openapi/jsonreference v0.20.0 // indirect
|
||||||
github.com/go-openapi/loads v0.21.1 // indirect
|
github.com/go-openapi/loads v0.21.1 // indirect
|
||||||
github.com/go-openapi/runtime v0.23.3 // indirect
|
github.com/go-openapi/runtime v0.23.3 // indirect
|
||||||
github.com/go-openapi/spec v0.20.4 // indirect
|
github.com/go-openapi/spec v0.20.6 // indirect
|
||||||
github.com/go-openapi/strfmt v0.21.2 // indirect
|
github.com/go-openapi/strfmt v0.21.2 // indirect
|
||||||
github.com/go-openapi/swag v0.21.1 // indirect
|
github.com/go-openapi/swag v0.21.1 // indirect
|
||||||
github.com/go-openapi/validate v0.21.0 // indirect
|
github.com/go-openapi/validate v0.21.0 // indirect
|
||||||
|
@ -361,10 +360,10 @@ require (
|
||||||
go.uber.org/multierr v1.7.0 // indirect
|
go.uber.org/multierr v1.7.0 // indirect
|
||||||
go.uber.org/zap v1.21.0 // indirect
|
go.uber.org/zap v1.21.0 // indirect
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
|
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
|
||||||
golang.org/x/net v0.0.0-20220412020605-290c469a71a5 // indirect
|
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect
|
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect
|
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect
|
||||||
|
|
25
go.sum
25
go.sum
|
@ -303,10 +303,8 @@ github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C6
|
||||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
||||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||||
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
|
||||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||||
github.com/ReneKroon/ttlcache/v2 v2.10.0/go.mod h1:mBxvsNY+BT8qLLd6CuAJubbKo6r0jh3nb5et22bbfGY=
|
github.com/ReneKroon/ttlcache/v2 v2.10.0/go.mod h1:mBxvsNY+BT8qLLd6CuAJubbKo6r0jh3nb5et22bbfGY=
|
||||||
github.com/ReneKroon/ttlcache/v2 v2.11.0 h1:OvlcYFYi941SBN3v9dsDcC2N8vRxyHcCmJb3Vl4QMoM=
|
github.com/ReneKroon/ttlcache/v2 v2.11.0 h1:OvlcYFYi941SBN3v9dsDcC2N8vRxyHcCmJb3Vl4QMoM=
|
||||||
|
@ -1068,8 +1066,9 @@ github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3Hfo
|
||||||
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
|
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
|
||||||
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
|
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
|
||||||
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
|
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
|
||||||
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
|
|
||||||
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
|
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
|
||||||
|
github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA=
|
||||||
|
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
|
||||||
github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
|
github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
|
||||||
github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
|
github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
|
||||||
github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
|
github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
|
||||||
|
@ -1103,8 +1102,10 @@ github.com/go-openapi/spec v0.19.15/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFu
|
||||||
github.com/go-openapi/spec v0.20.0/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFutcFKaVbmU=
|
github.com/go-openapi/spec v0.20.0/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFutcFKaVbmU=
|
||||||
github.com/go-openapi/spec v0.20.1/go.mod h1:93x7oh+d+FQsmsieroS4cmR3u0p/ywH649a3qwC9OsQ=
|
github.com/go-openapi/spec v0.20.1/go.mod h1:93x7oh+d+FQsmsieroS4cmR3u0p/ywH649a3qwC9OsQ=
|
||||||
github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg=
|
github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg=
|
||||||
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
|
|
||||||
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
|
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
|
||||||
|
github.com/go-openapi/spec v0.20.5/go.mod h1:QbfOSIVt3/sac+a1wzmKbbcLXm5NdZnyBZYtCijp43o=
|
||||||
|
github.com/go-openapi/spec v0.20.6 h1:ich1RQ3WDbfoeTqTAb+5EIxNmpKVJZWBNah9RAT0jIQ=
|
||||||
|
github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
|
||||||
github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
|
github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
|
||||||
github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
|
github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
|
||||||
github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY=
|
github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY=
|
||||||
|
@ -2142,8 +2143,8 @@ github.com/open-policy-agent/opa v0.32.0/go.mod h1:5sJdtc+1/U8zy/j30njpQl6u9rM4M
|
||||||
github.com/open-policy-agent/opa v0.35.0/go.mod h1:xEmekKlk6/c+so5HF9wtPnGPXDfBuBsrMGhSHOHEF+U=
|
github.com/open-policy-agent/opa v0.35.0/go.mod h1:xEmekKlk6/c+so5HF9wtPnGPXDfBuBsrMGhSHOHEF+U=
|
||||||
github.com/open-policy-agent/opa v0.37.0 h1:OUXB+RAcxQpmXeNW2BN1wYzQQvVCPF1T9zv+QXGr9Wg=
|
github.com/open-policy-agent/opa v0.37.0 h1:OUXB+RAcxQpmXeNW2BN1wYzQQvVCPF1T9zv+QXGr9Wg=
|
||||||
github.com/open-policy-agent/opa v0.37.0/go.mod h1:xX3NUCZuXK8f0CNhFQvhm4495mZLptf94pIkWRLaFqo=
|
github.com/open-policy-agent/opa v0.37.0/go.mod h1:xX3NUCZuXK8f0CNhFQvhm4495mZLptf94pIkWRLaFqo=
|
||||||
github.com/opencontainers/distribution-spec v1.0.1 h1:hT6tF6uKZAQh+HH3BrJqn7/xHhMoDHzahIg4KxD2DqM=
|
github.com/opencontainers/distribution-spec/specs-go v0.0.0-20220217185014-dd38b7ed8a99 h1:yGqpYh1h3ZXxGg4Mqd5ZwhlwQ9wXOgvuodxbxJA7iMY=
|
||||||
github.com/opencontainers/distribution-spec v1.0.1/go.mod h1:copR2flp+jTEvQIFMb6MIx45OkrxzqyjszPDT3hx/5Q=
|
github.com/opencontainers/distribution-spec/specs-go v0.0.0-20220217185014-dd38b7ed8a99/go.mod h1:aA4vdXRS8E1TG7pLZOz85InHi3BiPdErh8IpJN6E0x4=
|
||||||
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
|
@ -2546,9 +2547,8 @@ github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s
|
||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2 h1:+iNTcqQJy0OZ5jk6a5NLib47eqXK8uYcPX+O4+cBpEM=
|
github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2 h1:+iNTcqQJy0OZ5jk6a5NLib47eqXK8uYcPX+O4+cBpEM=
|
||||||
github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w=
|
github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w=
|
||||||
github.com/swaggo/http-swagger v1.2.6 h1:ihTjChUoSRMpFMjWw+0AkL1Ti4r6v8pCgVYLmQVRlRw=
|
github.com/swaggo/http-swagger v1.2.8 h1:TVjxLU7qoqofJ9qynJazmpTGs/p4Kx9FTp7YYwOkJb0=
|
||||||
github.com/swaggo/http-swagger v1.2.6/go.mod h1:CcoICgY3yVDk2u1LQUCMHbAj0fjlxIX+873psXlIKNA=
|
github.com/swaggo/http-swagger v1.2.8/go.mod h1:FrQwV7rx+A5t11PIX8d+tFJa2GKx11RdAXQptllPQHg=
|
||||||
github.com/swaggo/swag v1.7.9/go.mod h1:gZ+TJ2w/Ve1RwQsA2IRoSOTidHz6DX+PIG8GWvbnoLU=
|
|
||||||
github.com/swaggo/swag v1.8.1 h1:JuARzFX1Z1njbCGz+ZytBR15TFJwF2Q7fu8puJHhQYI=
|
github.com/swaggo/swag v1.8.1 h1:JuARzFX1Z1njbCGz+ZytBR15TFJwF2Q7fu8puJHhQYI=
|
||||||
github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ=
|
github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ=
|
||||||
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
|
@ -3099,8 +3099,10 @@ golang.org/x/net v0.0.0-20220127074510-2fabfed7e28f/go.mod h1:CfG3xpIq0wQ8r1q4Su
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220412020605-290c469a71a5 h1:bRb386wvrE+oBNdF1d/Xh9mQrfQ4ecYhW5qJ5GvTGT4=
|
|
||||||
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 h1:NWy5+hlRbC7HK+PmcXVUmW1IMyFce7to56IUvhUFm7Y=
|
||||||
|
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
@ -3310,8 +3312,9 @@ golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
|
|
||||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
|
|
@ -3,6 +3,7 @@ package api
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -10,6 +11,7 @@ import (
|
||||||
glob "github.com/bmatcuk/doublestar/v4"
|
glob "github.com/bmatcuk/doublestar/v4"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"zotregistry.io/zot/pkg/api/config"
|
"zotregistry.io/zot/pkg/api/config"
|
||||||
|
"zotregistry.io/zot/pkg/api/constants"
|
||||||
"zotregistry.io/zot/pkg/common"
|
"zotregistry.io/zot/pkg/common"
|
||||||
"zotregistry.io/zot/pkg/log"
|
"zotregistry.io/zot/pkg/log"
|
||||||
)
|
)
|
||||||
|
@ -191,7 +193,7 @@ func AuthzHandler(ctlr *Controller) mux.MiddlewareFunc {
|
||||||
ctx := acCtrlr.getContext(username, request)
|
ctx := acCtrlr.getContext(username, request)
|
||||||
|
|
||||||
// will return only repos on which client is authorized to read
|
// will return only repos on which client is authorized to read
|
||||||
if request.RequestURI == "/v2/_catalog" {
|
if request.RequestURI == fmt.Sprintf("%s%s", constants.RoutePrefix, constants.ExtCatalogPrefix) {
|
||||||
next.ServeHTTP(response, request.WithContext(ctx))
|
next.ServeHTTP(response, request.WithContext(ctx))
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
package constants
|
package constants
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ArtifactSpecRoutePrefix = "/oras/artifacts/v1"
|
ArtifactSpecRoutePrefix = "/oras/artifacts/v1"
|
||||||
RoutePrefix = "/v2"
|
RoutePrefix = "/v2"
|
||||||
DistAPIVersion = "Docker-Distribution-API-Version"
|
DistAPIVersion = "Docker-Distribution-API-Version"
|
||||||
DistContentDigestKey = "Docker-Content-Digest"
|
DistContentDigestKey = "Docker-Content-Digest"
|
||||||
BlobUploadUUID = "Blob-Upload-UUID"
|
BlobUploadUUID = "Blob-Upload-UUID"
|
||||||
DefaultMediaType = "application/json"
|
DefaultMediaType = "application/json"
|
||||||
BinaryMediaType = "application/octet-stream"
|
BinaryMediaType = "application/octet-stream"
|
||||||
|
DefaultMetricsExtensionRoute = "/metrics"
|
||||||
)
|
)
|
||||||
|
|
9
pkg/api/constants/extensions.go
Normal file
9
pkg/api/constants/extensions.go
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package constants
|
||||||
|
|
||||||
|
// https://github.com/opencontainers/distribution-spec/tree/main/extensions#extensions-api-for-distribution
|
||||||
|
const (
|
||||||
|
ExtCatalogPrefix = "/_catalog"
|
||||||
|
ExtOciDiscoverPrefix = "/_oci/ext/discover"
|
||||||
|
// zot specific extensions.
|
||||||
|
ExtSearchPrefix = RoutePrefix + "/_search"
|
||||||
|
)
|
|
@ -32,6 +32,7 @@ import (
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
vldap "github.com/nmcclain/ldap"
|
vldap "github.com/nmcclain/ldap"
|
||||||
notreg "github.com/notaryproject/notation/pkg/registry"
|
notreg "github.com/notaryproject/notation/pkg/registry"
|
||||||
|
distext "github.com/opencontainers/distribution-spec/specs-go/v1/extensions"
|
||||||
godigest "github.com/opencontainers/go-digest"
|
godigest "github.com/opencontainers/go-digest"
|
||||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
artifactspec "github.com/oras-project/artifacts-spec/specs-go/v1"
|
artifactspec "github.com/oras-project/artifacts-spec/specs-go/v1"
|
||||||
|
@ -47,6 +48,7 @@ import (
|
||||||
"zotregistry.io/zot/pkg/api"
|
"zotregistry.io/zot/pkg/api"
|
||||||
"zotregistry.io/zot/pkg/api/config"
|
"zotregistry.io/zot/pkg/api/config"
|
||||||
"zotregistry.io/zot/pkg/api/constants"
|
"zotregistry.io/zot/pkg/api/constants"
|
||||||
|
extconf "zotregistry.io/zot/pkg/extensions/config"
|
||||||
"zotregistry.io/zot/pkg/storage"
|
"zotregistry.io/zot/pkg/storage"
|
||||||
"zotregistry.io/zot/pkg/test"
|
"zotregistry.io/zot/pkg/test"
|
||||||
)
|
)
|
||||||
|
@ -1878,7 +1880,7 @@ func TestAuthorizationWithBasicAuth(t *testing.T) {
|
||||||
|
|
||||||
// everybody should have access to /v2/_catalog
|
// everybody should have access to /v2/_catalog
|
||||||
resp, err = resty.R().SetBasicAuth(username, passphrase).
|
resp, err = resty.R().SetBasicAuth(username, passphrase).
|
||||||
Get(baseURL + "/v2/_catalog")
|
Get(baseURL + constants.RoutePrefix + constants.ExtCatalogPrefix)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||||||
|
@ -3195,7 +3197,7 @@ func TestParallelRequests(t *testing.T) {
|
||||||
assert.Equal(t, tagResponse.StatusCode(), http.StatusOK, "response status code should return success code")
|
assert.Equal(t, tagResponse.StatusCode(), http.StatusOK, "response status code should return success code")
|
||||||
|
|
||||||
repoResponse, err := client.R().SetBasicAuth(username, passphrase).
|
repoResponse, err := client.R().SetBasicAuth(username, passphrase).
|
||||||
Get(baseURL + "/v2/_catalog")
|
Get(baseURL + constants.RoutePrefix + constants.ExtCatalogPrefix)
|
||||||
assert.Equal(t, err, nil, "Error should be nil")
|
assert.Equal(t, err, nil, "Error should be nil")
|
||||||
assert.Equal(t, repoResponse.StatusCode(), http.StatusOK, "response status code should return success code")
|
assert.Equal(t, repoResponse.StatusCode(), http.StatusOK, "response status code should return success code")
|
||||||
})
|
})
|
||||||
|
@ -4812,6 +4814,80 @@ func TestPeriodicGC(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDistSpecExtensions(t *testing.T) {
|
||||||
|
Convey("start zot server with search extension", t, func(c C) {
|
||||||
|
conf := config.New()
|
||||||
|
port := test.GetFreePort()
|
||||||
|
baseURL := test.GetBaseURL(port)
|
||||||
|
|
||||||
|
conf.HTTP.Port = port
|
||||||
|
|
||||||
|
defaultVal := true
|
||||||
|
|
||||||
|
searchConfig := &extconf.SearchConfig{
|
||||||
|
Enable: &defaultVal,
|
||||||
|
}
|
||||||
|
|
||||||
|
conf.Extensions = &extconf.ExtensionConfig{
|
||||||
|
Search: searchConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
logFile, err := ioutil.TempFile("", "zot-log*.txt")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
conf.Log.Output = logFile.Name()
|
||||||
|
defer os.Remove(logFile.Name()) // clean up
|
||||||
|
|
||||||
|
ctlr := api.NewController(conf)
|
||||||
|
|
||||||
|
ctlr.Config.Storage.RootDirectory = t.TempDir()
|
||||||
|
|
||||||
|
go startServer(ctlr)
|
||||||
|
defer stopServer(ctlr)
|
||||||
|
test.WaitTillServerReady(baseURL)
|
||||||
|
|
||||||
|
var extensionList distext.ExtensionList
|
||||||
|
|
||||||
|
resp, err := resty.R().Get(baseURL + constants.RoutePrefix + constants.ExtOciDiscoverPrefix)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(resp, ShouldNotBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
err = json.Unmarshal(resp.Body(), &extensionList)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(len(extensionList.Extensions), ShouldEqual, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("start minimal zot server", t, func(c C) {
|
||||||
|
conf := config.New()
|
||||||
|
port := test.GetFreePort()
|
||||||
|
baseURL := test.GetBaseURL(port)
|
||||||
|
|
||||||
|
conf.HTTP.Port = port
|
||||||
|
|
||||||
|
logFile, err := ioutil.TempFile("", "zot-log*.txt")
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
conf.Log.Output = logFile.Name()
|
||||||
|
defer os.Remove(logFile.Name()) // clean up
|
||||||
|
|
||||||
|
ctlr := api.NewController(conf)
|
||||||
|
|
||||||
|
ctlr.Config.Storage.RootDirectory = t.TempDir()
|
||||||
|
|
||||||
|
go startServer(ctlr)
|
||||||
|
defer stopServer(ctlr)
|
||||||
|
test.WaitTillServerReady(baseURL)
|
||||||
|
|
||||||
|
var extensionList distext.ExtensionList
|
||||||
|
resp, err := resty.R().Get(baseURL + constants.RoutePrefix + constants.ExtOciDiscoverPrefix)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(resp, ShouldNotBeNil)
|
||||||
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
|
err = json.Unmarshal(resp.Body(), &extensionList)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(len(extensionList.Extensions), ShouldEqual, 0)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func getAllBlobs(imagePath string) []string {
|
func getAllBlobs(imagePath string) []string {
|
||||||
blobList := make([]string, 0)
|
blobList := make([]string, 0)
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
notreg "github.com/notaryproject/notation/pkg/registry"
|
notreg "github.com/notaryproject/notation/pkg/registry"
|
||||||
|
"github.com/opencontainers/distribution-spec/specs-go/v1/extensions"
|
||||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
artifactspec "github.com/oras-project/artifacts-spec/specs-go/v1"
|
artifactspec "github.com/oras-project/artifacts-spec/specs-go/v1"
|
||||||
httpSwagger "github.com/swaggo/http-swagger"
|
httpSwagger "github.com/swaggo/http-swagger"
|
||||||
|
@ -69,6 +70,7 @@ func (rh *RouteHandler) SetupRoutes() {
|
||||||
rh.c.Router.Use(AuthzHandler(rh.c))
|
rh.c.Router.Use(AuthzHandler(rh.c))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/opencontainers/distribution-spec/blob/main/spec.md#endpoints
|
||||||
prefixedRouter := rh.c.Router.PathPrefix(constants.RoutePrefix).Subrouter()
|
prefixedRouter := rh.c.Router.PathPrefix(constants.RoutePrefix).Subrouter()
|
||||||
{
|
{
|
||||||
prefixedRouter.HandleFunc(fmt.Sprintf("/{name:%s}/tags/list", NameRegexp.String()),
|
prefixedRouter.HandleFunc(fmt.Sprintf("/{name:%s}/tags/list", NameRegexp.String()),
|
||||||
|
@ -97,8 +99,10 @@ func (rh *RouteHandler) SetupRoutes() {
|
||||||
rh.UpdateBlobUpload).Methods("PUT")
|
rh.UpdateBlobUpload).Methods("PUT")
|
||||||
prefixedRouter.HandleFunc(fmt.Sprintf("/{name:%s}/blobs/uploads/{session_id}", NameRegexp.String()),
|
prefixedRouter.HandleFunc(fmt.Sprintf("/{name:%s}/blobs/uploads/{session_id}", NameRegexp.String()),
|
||||||
rh.DeleteBlobUpload).Methods("DELETE")
|
rh.DeleteBlobUpload).Methods("DELETE")
|
||||||
prefixedRouter.HandleFunc("/_catalog",
|
prefixedRouter.HandleFunc(constants.ExtCatalogPrefix,
|
||||||
rh.ListRepositories).Methods(allowedMethods("GET")...)
|
rh.ListRepositories).Methods(allowedMethods("GET")...)
|
||||||
|
prefixedRouter.HandleFunc(constants.ExtOciDiscoverPrefix,
|
||||||
|
rh.ListExtensions).Methods(allowedMethods("GET")...)
|
||||||
prefixedRouter.HandleFunc("/",
|
prefixedRouter.HandleFunc("/",
|
||||||
rh.CheckVersionSupport).Methods(allowedMethods("GET")...)
|
rh.CheckVersionSupport).Methods(allowedMethods("GET")...)
|
||||||
}
|
}
|
||||||
|
@ -336,6 +340,10 @@ type ImageManifest struct {
|
||||||
ispec.Manifest
|
ispec.Manifest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExtensionList struct {
|
||||||
|
extensions.ExtensionList
|
||||||
|
}
|
||||||
|
|
||||||
// GetManifest godoc
|
// GetManifest godoc
|
||||||
// @Summary Get image manifest
|
// @Summary Get image manifest
|
||||||
// @Description Get an image's manifest given a reference or a digest
|
// @Description Get an image's manifest given a reference or a digest
|
||||||
|
@ -1249,6 +1257,19 @@ func (rh *RouteHandler) ListRepositories(response http.ResponseWriter, request *
|
||||||
WriteJSON(response, http.StatusOK, is)
|
WriteJSON(response, http.StatusOK, is)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListExtensions godoc
|
||||||
|
// @Summary List Registry level extensions
|
||||||
|
// @Description List all extensions present on registry
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Success 200 {object} api.ExtensionList
|
||||||
|
// @Router /v2/_oci/ext/discover [get].
|
||||||
|
func (rh *RouteHandler) ListExtensions(w http.ResponseWriter, r *http.Request) {
|
||||||
|
extensionList := ext.GetExtensions(rh.c.Config)
|
||||||
|
|
||||||
|
WriteJSON(w, http.StatusOK, extensionList)
|
||||||
|
}
|
||||||
|
|
||||||
func (rh *RouteHandler) GetMetrics(w http.ResponseWriter, r *http.Request) {
|
func (rh *RouteHandler) GetMetrics(w http.ResponseWriter, r *http.Request) {
|
||||||
m := rh.c.Metrics.ReceiveMetrics()
|
m := rh.c.Metrics.ReceiveMetrics()
|
||||||
WriteJSON(w, http.StatusOK, m)
|
WriteJSON(w, http.StatusOK, m)
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"gopkg.in/resty.v1"
|
"gopkg.in/resty.v1"
|
||||||
"zotregistry.io/zot/pkg/api"
|
"zotregistry.io/zot/pkg/api"
|
||||||
"zotregistry.io/zot/pkg/api/config"
|
"zotregistry.io/zot/pkg/api/config"
|
||||||
|
"zotregistry.io/zot/pkg/api/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestElevatedPrivilegesTLSNewControllerPrivilegedCert(t *testing.T) {
|
func TestElevatedPrivilegesTLSNewControllerPrivilegedCert(t *testing.T) {
|
||||||
|
@ -106,8 +107,8 @@ func TestElevatedPrivilegesTLSNewControllerPrivilegedCert(t *testing.T) {
|
||||||
|
|
||||||
Convey("Certs in privileged path", func() {
|
Convey("Certs in privileged path", func() {
|
||||||
configPath := makeConfigFile(
|
configPath := makeConfigFile(
|
||||||
fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s/v2/_catalog","showspinner":false}]}`,
|
fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s%s%s","showspinner":false}]}`,
|
||||||
BaseSecureURL2))
|
BaseSecureURL2, constants.RoutePrefix, constants.ExtCatalogPrefix))
|
||||||
defer os.Remove(configPath)
|
defer os.Remove(configPath)
|
||||||
|
|
||||||
args := []string{"imagetest"}
|
args := []string{"imagetest"}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"gopkg.in/resty.v1"
|
"gopkg.in/resty.v1"
|
||||||
"zotregistry.io/zot/pkg/api"
|
"zotregistry.io/zot/pkg/api"
|
||||||
"zotregistry.io/zot/pkg/api/config"
|
"zotregistry.io/zot/pkg/api/config"
|
||||||
|
"zotregistry.io/zot/pkg/api/constants"
|
||||||
"zotregistry.io/zot/pkg/test"
|
"zotregistry.io/zot/pkg/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -114,8 +115,8 @@ func TestTLSWithAuth(t *testing.T) {
|
||||||
|
|
||||||
args = []string{"imagetest"}
|
args = []string{"imagetest"}
|
||||||
configPath = makeConfigFile(
|
configPath = makeConfigFile(
|
||||||
fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s/v2/_catalog","showspinner":false}]}`,
|
fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s%s%s","showspinner":false}]}`,
|
||||||
BaseSecureURL1))
|
BaseSecureURL1, constants.RoutePrefix, constants.ExtCatalogPrefix))
|
||||||
defer os.Remove(configPath)
|
defer os.Remove(configPath)
|
||||||
imageCmd = NewImageCommand(new(searchService))
|
imageCmd = NewImageCommand(new(searchService))
|
||||||
imageBuff = bytes.NewBufferString("")
|
imageBuff = bytes.NewBufferString("")
|
||||||
|
@ -129,8 +130,8 @@ func TestTLSWithAuth(t *testing.T) {
|
||||||
user := fmt.Sprintf("%s:%s", username, passphrase)
|
user := fmt.Sprintf("%s:%s", username, passphrase)
|
||||||
args = []string{"imagetest", "-u", user}
|
args = []string{"imagetest", "-u", user}
|
||||||
configPath = makeConfigFile(
|
configPath = makeConfigFile(
|
||||||
fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s/v2/_catalog","showspinner":false}]}`,
|
fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s%s%s","showspinner":false}]}`,
|
||||||
BaseSecureURL1))
|
BaseSecureURL1, constants.RoutePrefix, constants.ExtCatalogPrefix))
|
||||||
defer os.Remove(configPath)
|
defer os.Remove(configPath)
|
||||||
imageCmd = NewImageCommand(new(searchService))
|
imageCmd = NewImageCommand(new(searchService))
|
||||||
imageBuff = bytes.NewBufferString("")
|
imageBuff = bytes.NewBufferString("")
|
||||||
|
@ -185,8 +186,8 @@ func TestTLSWithoutAuth(t *testing.T) {
|
||||||
|
|
||||||
Convey("Certs in user's home", func() {
|
Convey("Certs in user's home", func() {
|
||||||
configPath := makeConfigFile(
|
configPath := makeConfigFile(
|
||||||
fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s/v2/_catalog","showspinner":false}]}`,
|
fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s%s%s","showspinner":false}]}`,
|
||||||
BaseSecureURL1))
|
BaseSecureURL1, constants.RoutePrefix, constants.ExtCatalogPrefix))
|
||||||
defer os.Remove(configPath)
|
defer os.Remove(configPath)
|
||||||
|
|
||||||
home := os.Getenv("HOME")
|
home := os.Getenv("HOME")
|
||||||
|
@ -250,8 +251,8 @@ func TestTLSBadCerts(t *testing.T) {
|
||||||
|
|
||||||
Convey("Test with system certs", func() {
|
Convey("Test with system certs", func() {
|
||||||
configPath := makeConfigFile(
|
configPath := makeConfigFile(
|
||||||
fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s/v2/_catalog","showspinner":false}]}`,
|
fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s%s%s","showspinner":false}]}`,
|
||||||
BaseSecureURL3))
|
BaseSecureURL3, constants.RoutePrefix, constants.ExtCatalogPrefix))
|
||||||
defer os.Remove(configPath)
|
defer os.Remove(configPath)
|
||||||
|
|
||||||
args := []string{"imagetest"}
|
args := []string{"imagetest"}
|
||||||
|
|
|
@ -5,7 +5,6 @@ package cli //nolint:testpackage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -216,8 +215,6 @@ func TestConfigCmdMain(t *testing.T) {
|
||||||
cmd.SetArgs(args)
|
cmd.SetArgs(args)
|
||||||
err := cmd.Execute()
|
err := cmd.Execute()
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
fmt.Println(err)
|
|
||||||
fmt.Println(buff.String())
|
|
||||||
So(buff.String(), ShouldContainSubstring, "does not exist")
|
So(buff.String(), ShouldContainSubstring, "does not exist")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -254,8 +251,6 @@ func TestConfigCmdMain(t *testing.T) {
|
||||||
cmd.SetArgs(args)
|
cmd.SetArgs(args)
|
||||||
err := cmd.Execute()
|
err := cmd.Execute()
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
fmt.Println(err)
|
|
||||||
fmt.Println(buff.String())
|
|
||||||
So(buff.String(), ShouldContainSubstring, "does not exist")
|
So(buff.String(), ShouldContainSubstring, "does not exist")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
zotErrors "zotregistry.io/zot/errors"
|
zotErrors "zotregistry.io/zot/errors"
|
||||||
"zotregistry.io/zot/pkg/api"
|
"zotregistry.io/zot/pkg/api"
|
||||||
"zotregistry.io/zot/pkg/api/config"
|
"zotregistry.io/zot/pkg/api/config"
|
||||||
|
"zotregistry.io/zot/pkg/api/constants"
|
||||||
extconf "zotregistry.io/zot/pkg/extensions/config"
|
extconf "zotregistry.io/zot/pkg/extensions/config"
|
||||||
"zotregistry.io/zot/pkg/test"
|
"zotregistry.io/zot/pkg/test"
|
||||||
)
|
)
|
||||||
|
@ -320,7 +321,7 @@ func TestServerCVEResponse(t *testing.T) {
|
||||||
}(ctlr)
|
}(ctlr)
|
||||||
// wait till ready
|
// wait till ready
|
||||||
for {
|
for {
|
||||||
res, err := resty.R().Get(url + "/query")
|
res, err := resty.R().Get(url + constants.ExtSearchPrefix)
|
||||||
if err == nil && res.StatusCode() == 200 {
|
if err == nil && res.StatusCode() == 200 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"zotregistry.io/zot/errors"
|
"zotregistry.io/zot/errors"
|
||||||
"zotregistry.io/zot/pkg/api"
|
"zotregistry.io/zot/pkg/api"
|
||||||
"zotregistry.io/zot/pkg/api/config"
|
"zotregistry.io/zot/pkg/api/config"
|
||||||
|
"zotregistry.io/zot/pkg/api/constants"
|
||||||
extconf "zotregistry.io/zot/pkg/extensions/config"
|
extconf "zotregistry.io/zot/pkg/extensions/config"
|
||||||
"zotregistry.io/zot/pkg/extensions/monitoring"
|
"zotregistry.io/zot/pkg/extensions/monitoring"
|
||||||
"zotregistry.io/zot/pkg/storage"
|
"zotregistry.io/zot/pkg/storage"
|
||||||
|
@ -332,7 +333,7 @@ func applyDefaultValues(config *config.Config, viperInstance *viper.Viper) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Extensions.Metrics.Prometheus == nil {
|
if config.Extensions.Metrics.Prometheus == nil {
|
||||||
config.Extensions.Metrics.Prometheus = &extconf.PrometheusConfig{Path: "/metrics"}
|
config.Extensions.Metrics.Prometheus = &extconf.PrometheusConfig{Path: constants.DefaultMetricsExtensionRoute}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"github.com/olekukonko/tablewriter"
|
"github.com/olekukonko/tablewriter"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
zotErrors "zotregistry.io/zot/errors"
|
zotErrors "zotregistry.io/zot/errors"
|
||||||
|
"zotregistry.io/zot/pkg/api/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SearchService interface {
|
type SearchService interface {
|
||||||
|
@ -70,7 +71,8 @@ func (service searchService) getAllImages(ctx context.Context, config searchConf
|
||||||
|
|
||||||
catalog := &catalogResponse{}
|
catalog := &catalogResponse{}
|
||||||
|
|
||||||
catalogEndPoint, err := combineServerAndEndpointURL(*config.servURL, "/v2/_catalog")
|
catalogEndPoint, err := combineServerAndEndpointURL(*config.servURL, fmt.Sprintf("%s%s",
|
||||||
|
constants.RoutePrefix, constants.ExtCatalogPrefix))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if isContextDone(ctx) {
|
if isContextDone(ctx) {
|
||||||
return
|
return
|
||||||
|
@ -453,7 +455,7 @@ func (service searchService) makeGraphQLQuery(ctx context.Context, config search
|
||||||
username, password, query string,
|
username, password, query string,
|
||||||
resultPtr interface{},
|
resultPtr interface{},
|
||||||
) error {
|
) error {
|
||||||
endPoint, err := combineServerAndEndpointURL(*config.servURL, "/query")
|
endPoint, err := combineServerAndEndpointURL(*config.servURL, constants.ExtSearchPrefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,14 +50,14 @@ func CheckWorkflows(t *testing.T, config *compliance.Config) {
|
||||||
Convey("Make API calls to the controller", t, func(c C) {
|
Convey("Make API calls to the controller", t, func(c C) {
|
||||||
Convey("Check version", func() {
|
Convey("Check version", func() {
|
||||||
_, _ = Print("\nCheck version")
|
_, _ = Print("\nCheck version")
|
||||||
resp, err := resty.R().Get(baseURL + "/v2/")
|
resp, err := resty.R().Get(baseURL + constants.RoutePrefix + "/")
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("Get repository catalog", func() {
|
Convey("Get repository catalog", func() {
|
||||||
_, _ = Print("\nGet repository catalog")
|
_, _ = Print("\nGet repository catalog")
|
||||||
resp, err := resty.R().Get(baseURL + "/v2/_catalog")
|
resp, err := resty.R().Get(baseURL + constants.RoutePrefix + constants.ExtCatalogPrefix)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||||||
So(resp.String(), ShouldNotBeEmpty)
|
So(resp.String(), ShouldNotBeEmpty)
|
||||||
|
@ -77,7 +77,8 @@ func CheckWorkflows(t *testing.T, config *compliance.Config) {
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, http.StatusAccepted)
|
So(resp.StatusCode(), ShouldEqual, http.StatusAccepted)
|
||||||
|
|
||||||
resp, err = resty.R().SetResult(&api.RepositoryList{}).Get(baseURL + "/v2/_catalog")
|
resp, err = resty.R().SetResult(&api.RepositoryList{}).Get(baseURL +
|
||||||
|
constants.RoutePrefix + constants.ExtCatalogPrefix)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||||||
So(resp.String(), ShouldNotBeEmpty)
|
So(resp.String(), ShouldNotBeEmpty)
|
||||||
|
|
194
pkg/extensions/_search.md
Normal file
194
pkg/extensions/_search.md
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
`search` extension
|
||||||
|
===
|
||||||
|
|
||||||
|
`search` extension provides efficient and enhanced registry search capabilities using graphQL backend.
|
||||||
|
|
||||||
|
|
||||||
|
Table of Contents
|
||||||
|
===
|
||||||
|
|
||||||
|
| Supported queries | Input | Ouput | Description | graphQL query |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| [Search images by digest](#search-images-by-digest) | digest | image list | Search all repositories in the registry and return list of images that matches given digest (manifest, config or layers) | ImageListForDigest |
|
||||||
|
| [Search images affected by a given CVE id](#search-images-affected-by-a-given-cve-id) | CVE id | image list | Search the entire registry and return list of images affected by given CVE | ImagesListForCVE |
|
||||||
|
| [List CVEs for a given image](#list-cves-of-given-image) | image | CVE list | Scan given image and return list of CVEs affecting the image | CVEListForImage |
|
||||||
|
| [List images not affected by a given CVE id](#list-images-not-affected-by-a-given-cve-id) | repository, CVE id | image list | Scan all images in a given repository and return list of latest (by date) images not affected by the given CVE |ImagesListWithCVEFixed|
|
||||||
|
| [List the latest image across every repository](#list-the-latest-image-across-every-repository) | \<none\> | image list | Search entire registry and return a list containing the latest (by date) image in each repository | ImageListWithLatestTag |
|
||||||
|
| [List all images with expanded information for a given repository](#list-all-images-with-expanded-information-for-a-given-repository) | repository | image list | List expanded image information for all images (including manifest, all layers, etc) in a given repository | ExpandedRepoInfo |
|
||||||
|
|
||||||
|
# Search images by digest
|
||||||
|
|
||||||
|
**Sample request**
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ ImageListForDigest (id:\"63a795ca90aa6e7cca60941e826810a4cd0a2e73ea02bf458241df2a5c973e29\") { Name Tags } }" }' http://localhost:8080/v2/_search
|
||||||
|
```
|
||||||
|
|
||||||
|
**Sample response**
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"ImageListForDigest": [{
|
||||||
|
"Name": "centos",
|
||||||
|
"Tags": ["8"]
|
||||||
|
}, {
|
||||||
|
"Name": "v2/centos",
|
||||||
|
"Tags": ["8"]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Search images affected by a given CVE id
|
||||||
|
|
||||||
|
**Sample request**
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ ImageListForCVE (id:\"CVE-2002-1119\") { Name Tags } }" }' http://localhost:8080/v2/_search
|
||||||
|
```
|
||||||
|
|
||||||
|
**Sample response**
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"ImageListForCVE": [{
|
||||||
|
"Name": "centos",
|
||||||
|
"Tags": ["8"]
|
||||||
|
}, {
|
||||||
|
"Name": "v2/centos",
|
||||||
|
"Tags": ["7", "8"]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
# List CVEs of given image
|
||||||
|
|
||||||
|
**Sample reques**t
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ CVEListForImage (image:\"centos\" ) { Tag CVEList { Id Title Description Severity PackageList {Name InstalledVersion FixedVersion } } } }" }' http://localhost:8080/v2/_search
|
||||||
|
```
|
||||||
|
|
||||||
|
**Sample response**
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"CVEListForImage": {
|
||||||
|
"Tag": "",
|
||||||
|
"CVEList": [{
|
||||||
|
"Id": "CVE-2021-3712",
|
||||||
|
"Title": "openssl: Read buffer overruns processing ASN.1 strings",
|
||||||
|
"Description": "ASN.1 strings are represented internally within OpenSSL as an ASN1_STRING structure which contains a buffer. Fixed in OpenSSL 1.1.1l (Affected 1.1.1-1.1.1k). Fixed in OpenSSL 1.0.2za (Affected 1.0.2-1.0.2y).",
|
||||||
|
"Severity": "MEDIUM",
|
||||||
|
"PackageList": [{
|
||||||
|
"Name": "openssl-libs",
|
||||||
|
"InstalledVersion": "1:1.1.1g-11.el8",
|
||||||
|
"FixedVersion": "1:1.1.1k-5.el8_5"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
# List images not affected by a given CVE id
|
||||||
|
|
||||||
|
**Sample request**
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ ImageListWithCVEFixed (id:\"CVE-2021-3713\",image:\"centos\") { Tags {Name Digest Timestamp} } }" }' http://localhost:8080/v2/_search
|
||||||
|
```
|
||||||
|
|
||||||
|
**Sample response**
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"ImageListWithCVEFixed": {
|
||||||
|
"Tags": [{
|
||||||
|
"Name": "8",
|
||||||
|
"Digest": "sha256:63a795ca90aa6e7cca60941e826810a4cd0a2e73ea02bf458241df2a5c973e29",
|
||||||
|
"Timestamp": "2020-12-08T00:22:52.526672082Z"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# List the latest image across every repository
|
||||||
|
|
||||||
|
**Sample request**
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ ImageListWithLatestTag () { Name Latest LastUpdated Description Licenses Vendor Size Labels} }" }' http://localhost:8080/v2/_search
|
||||||
|
```
|
||||||
|
|
||||||
|
**Sample response**
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"ImageListWithLatestTag": [{
|
||||||
|
"Name": "centos",
|
||||||
|
"Latest": "8",
|
||||||
|
"LastUpdated": "2020-12-08T00:22:52.526672082Z",
|
||||||
|
"Description": "",
|
||||||
|
"Licenses": "GPLv2",
|
||||||
|
"Vendor": "CentOS",
|
||||||
|
"Size": "1074",
|
||||||
|
"Labels": ""
|
||||||
|
}, {
|
||||||
|
"Name": "v2/centos",
|
||||||
|
"Latest": "8",
|
||||||
|
"LastUpdated": "2020-12-08T00:22:52.526672082Z",
|
||||||
|
"Description": "",
|
||||||
|
"Licenses": "GPLv2",
|
||||||
|
"Vendor": "CentOS",
|
||||||
|
"Size": "1074",
|
||||||
|
"Labels": ""
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# List all images with expanded information for a given repository
|
||||||
|
|
||||||
|
Sample request
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ ExpandedRepoInfo (repo:\"v2/centos\") { Manifests {Digest Tag IsSigned Layers {Size Digest}}} }" }' http://localhost:8080/v2/_search
|
||||||
|
```
|
||||||
|
|
||||||
|
**Sample response**
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"ExpandedRepoInfo": {
|
||||||
|
"Manifests": [{
|
||||||
|
"Digest": "2bacca16b9df395fc855c14ccf50b12b58d35d468b8e7f25758aff90f89bf396",
|
||||||
|
"Tag": "7",
|
||||||
|
"IsSigned": false,
|
||||||
|
"Layers": [{
|
||||||
|
"Size": "76097157",
|
||||||
|
"Digest": "2d473b07cdd5f0912cd6f1a703352c82b512407db6b05b43f2553732b55df3bc"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"Digest": "63a795ca90aa6e7cca60941e826810a4cd0a2e73ea02bf458241df2a5c973e29",
|
||||||
|
"Tag": "8",
|
||||||
|
"IsSigned": false,
|
||||||
|
"Layers": [{
|
||||||
|
"Size": "75181999",
|
||||||
|
"Digest": "7a0437f04f83f084b7ed68ad9c4a4947e12fc4e1b006b38129bac89114ec3621"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# References
|
||||||
|
[1] https://github.com/opencontainers/distribution-spec/tree/main/extensions
|
|
@ -5,13 +5,16 @@ package extensions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
goSync "sync"
|
goSync "sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
gqlHandler "github.com/99designs/gqlgen/graphql/handler"
|
gqlHandler "github.com/99designs/gqlgen/graphql/handler"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
distext "github.com/opencontainers/distribution-spec/specs-go/v1/extensions"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
"zotregistry.io/zot/pkg/api/config"
|
"zotregistry.io/zot/pkg/api/config"
|
||||||
|
"zotregistry.io/zot/pkg/api/constants"
|
||||||
"zotregistry.io/zot/pkg/extensions/scrub"
|
"zotregistry.io/zot/pkg/extensions/scrub"
|
||||||
"zotregistry.io/zot/pkg/extensions/search"
|
"zotregistry.io/zot/pkg/extensions/search"
|
||||||
cveinfo "zotregistry.io/zot/pkg/extensions/search/cve"
|
cveinfo "zotregistry.io/zot/pkg/extensions/search/cve"
|
||||||
|
@ -61,9 +64,10 @@ func EnableExtensions(config *config.Config, log log.Logger, rootDir string) {
|
||||||
*config.Extensions.Metrics.Enable &&
|
*config.Extensions.Metrics.Enable &&
|
||||||
config.Extensions.Metrics.Prometheus != nil {
|
config.Extensions.Metrics.Prometheus != nil {
|
||||||
if config.Extensions.Metrics.Prometheus.Path == "" {
|
if config.Extensions.Metrics.Prometheus.Path == "" {
|
||||||
config.Extensions.Metrics.Prometheus.Path = "/metrics"
|
config.Extensions.Metrics.Prometheus.Path = constants.DefaultMetricsExtensionRoute
|
||||||
|
|
||||||
log.Warn().Msg("Prometheus instrumentation Path not set, changing to '/metrics'.")
|
log.Warn().Msg(fmt.Sprintf("Prometheus instrumentation Path not set, changing to %s.",
|
||||||
|
constants.DefaultMetricsExtensionRoute))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Info().Msg("Metrics config not provided, skipping Metrics config update")
|
log.Info().Msg("Metrics config not provided, skipping Metrics config update")
|
||||||
|
@ -108,9 +112,34 @@ func EnableScrubExtension(config *config.Config, storeController storage.StoreCo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getExtension(name, url, description string) distext.Extension {
|
||||||
|
return distext.Extension{
|
||||||
|
Name: name,
|
||||||
|
URL: url,
|
||||||
|
Description: description,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetExtensions(config *config.Config) distext.ExtensionList {
|
||||||
|
extensionList := distext.ExtensionList{}
|
||||||
|
|
||||||
|
extensions := make([]distext.Extension, 0)
|
||||||
|
|
||||||
|
if config.Extensions != nil && config.Extensions.Search != nil {
|
||||||
|
searchExt := getExtension("search",
|
||||||
|
"https://github.com/project-zot/zot/tree/main/pkg/extensions/search/_search.md",
|
||||||
|
"search extension to provide various search feature e.g cve")
|
||||||
|
|
||||||
|
extensions = append(extensions, searchExt)
|
||||||
|
}
|
||||||
|
|
||||||
|
extensionList.Extensions = extensions
|
||||||
|
|
||||||
|
return extensionList
|
||||||
|
}
|
||||||
|
|
||||||
// SetupRoutes ...
|
// SetupRoutes ...
|
||||||
func SetupRoutes(config *config.Config, router *mux.Router, storeController storage.StoreController,
|
func SetupRoutes(config *config.Config, router *mux.Router, storeController storage.StoreController, l log.Logger,
|
||||||
l log.Logger,
|
|
||||||
) {
|
) {
|
||||||
// fork a new zerolog child to avoid data race
|
// fork a new zerolog child to avoid data race
|
||||||
log := log.Logger{Logger: l.With().Caller().Timestamp().Logger()}
|
log := log.Logger{Logger: l.With().Caller().Timestamp().Logger()}
|
||||||
|
@ -125,7 +154,7 @@ func SetupRoutes(config *config.Config, router *mux.Router, storeController stor
|
||||||
resConfig = search.GetResolverConfig(log, storeController, false)
|
resConfig = search.GetResolverConfig(log, storeController, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
router.PathPrefix("/query").Methods("GET", "POST", "OPTIONS").
|
router.PathPrefix(constants.ExtSearchPrefix).Methods("OPTIONS", "GET", "POST").
|
||||||
Handler(gqlHandler.NewDefaultServer(search.NewExecutableSchema(resConfig)))
|
Handler(gqlHandler.NewDefaultServer(search.NewExecutableSchema(resConfig)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
distext "github.com/opencontainers/distribution-spec/specs-go/v1/extensions"
|
||||||
"zotregistry.io/zot/pkg/api/config"
|
"zotregistry.io/zot/pkg/api/config"
|
||||||
"zotregistry.io/zot/pkg/log"
|
"zotregistry.io/zot/pkg/log"
|
||||||
"zotregistry.io/zot/pkg/storage"
|
"zotregistry.io/zot/pkg/storage"
|
||||||
|
@ -25,6 +26,11 @@ func EnableExtensions(config *config.Config, log log.Logger, rootDir string) {
|
||||||
"any extensions, please build zot full binary for this feature")
|
"any extensions, please build zot full binary for this feature")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetExtensions...
|
||||||
|
func GetExtensions(config *config.Config) distext.ExtensionList {
|
||||||
|
return distext.ExtensionList{}
|
||||||
|
}
|
||||||
|
|
||||||
// EnableSyncExtension ...
|
// EnableSyncExtension ...
|
||||||
func EnableSyncExtension(ctx context.Context, config *config.Config, wg *goSync.WaitGroup,
|
func EnableSyncExtension(ctx context.Context, config *config.Config, wg *goSync.WaitGroup,
|
||||||
storeController storage.StoreController, log log.Logger,
|
storeController storage.StoreController, log log.Logger,
|
||||||
|
@ -42,7 +48,8 @@ func EnableScrubExtension(config *config.Config, storeController storage.StoreCo
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetupRoutes ...
|
// SetupRoutes ...
|
||||||
func SetupRoutes(conf *config.Config, router *mux.Router, storeController storage.StoreController, log log.Logger) {
|
func SetupRoutes(conf *config.Config, router *mux.Router, storeController storage.StoreController, log log.Logger,
|
||||||
|
) {
|
||||||
log.Warn().Msg("skipping setting up extensions routes because given zot binary doesn't support " +
|
log.Warn().Msg("skipping setting up extensions routes because given zot binary doesn't support " +
|
||||||
"any extensions, please build zot full binary for this feature")
|
"any extensions, please build zot full binary for this feature")
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"gopkg.in/resty.v1"
|
"gopkg.in/resty.v1"
|
||||||
"zotregistry.io/zot/pkg/api"
|
"zotregistry.io/zot/pkg/api"
|
||||||
"zotregistry.io/zot/pkg/api/config"
|
"zotregistry.io/zot/pkg/api/config"
|
||||||
|
"zotregistry.io/zot/pkg/api/constants"
|
||||||
extconf "zotregistry.io/zot/pkg/extensions/config"
|
extconf "zotregistry.io/zot/pkg/extensions/config"
|
||||||
"zotregistry.io/zot/pkg/extensions/monitoring"
|
"zotregistry.io/zot/pkg/extensions/monitoring"
|
||||||
"zotregistry.io/zot/pkg/extensions/search/common"
|
"zotregistry.io/zot/pkg/extensions/search/common"
|
||||||
|
@ -24,6 +25,10 @@ import (
|
||||||
. "zotregistry.io/zot/pkg/test"
|
. "zotregistry.io/zot/pkg/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
graphqlQueryPrefix = constants.ExtSearchPrefix
|
||||||
|
)
|
||||||
|
|
||||||
// nolint:gochecknoglobals
|
// nolint:gochecknoglobals
|
||||||
var (
|
var (
|
||||||
rootDir string
|
rootDir string
|
||||||
|
@ -225,12 +230,12 @@ func TestLatestTagSearchHTTP(t *testing.T) {
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, err = resty.R().Get(baseURL + "/query")
|
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix)
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, err = resty.R().Get(baseURL + "/query?query={ImageListWithLatestTag(){Name%20Latest}}")
|
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query={ImageListWithLatestTag(){Name%20Latest}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
@ -243,7 +248,7 @@ func TestLatestTagSearchHTTP(t *testing.T) {
|
||||||
images := responseStruct.ImgListWithLatestTag.Images
|
images := responseStruct.ImgListWithLatestTag.Images
|
||||||
So(images[0].Latest, ShouldEqual, "0.0.1")
|
So(images[0].Latest, ShouldEqual, "0.0.1")
|
||||||
|
|
||||||
resp, err = resty.R().Get(baseURL + "/query?query={ImageListWithLatestTag(){Name%20Latest}}")
|
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query={ImageListWithLatestTag(){Name%20Latest}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
@ -252,7 +257,7 @@ func TestLatestTagSearchHTTP(t *testing.T) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err = resty.R().Get(baseURL + "/query?query={ImageListWithLatestTag(){Name%20Latest}}")
|
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query={ImageListWithLatestTag(){Name%20Latest}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
@ -273,7 +278,7 @@ func TestLatestTagSearchHTTP(t *testing.T) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err = resty.R().Get(baseURL + "/query?query={ImageListWithLatestTag(){Name%20Latest}}")
|
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query={ImageListWithLatestTag(){Name%20Latest}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
@ -284,7 +289,7 @@ func TestLatestTagSearchHTTP(t *testing.T) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err = resty.R().Get(baseURL + "/query?query={ImageListWithLatestTag(){Name%20Latest}}")
|
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query={ImageListWithLatestTag(){Name%20Latest}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
@ -295,7 +300,7 @@ func TestLatestTagSearchHTTP(t *testing.T) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err = resty.R().Get(baseURL + "/query?query={ImageListWithLatestTag(){Name%20Latest}}")
|
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query={ImageListWithLatestTag(){Name%20Latest}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
@ -307,7 +312,7 @@ func TestLatestTagSearchHTTP(t *testing.T) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err = resty.R().Get(baseURL + "/query?query={ImageListWithLatestTag(){Name%20Latest}}")
|
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query={ImageListWithLatestTag(){Name%20Latest}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
@ -363,14 +368,14 @@ func TestExpandedRepoInfo(t *testing.T) {
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, err = resty.R().Get(baseURL + "/query")
|
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix)
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
query := "{ExpandedRepoInfo(repo:\"zot-test\"){Manifests%20{Digest%20IsSigned%20Tag%20Layers%20{Size%20Digest}}}}"
|
query := "{ExpandedRepoInfo(repo:\"zot-test\"){Manifests%20{Digest%20IsSigned%20Tag%20Layers%20{Size%20Digest}}}}"
|
||||||
|
|
||||||
resp, err = resty.R().Get(baseURL + "/query?query=" + query)
|
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + query)
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
@ -384,13 +389,13 @@ func TestExpandedRepoInfo(t *testing.T) {
|
||||||
|
|
||||||
query = "{ExpandedRepoInfo(repo:\"\"){Manifests%20{Digest%20Tag%20IsSigned%20Layers%20{Size%20Digest}}}}"
|
query = "{ExpandedRepoInfo(repo:\"\"){Manifests%20{Digest%20Tag%20IsSigned%20Layers%20{Size%20Digest}}}}"
|
||||||
|
|
||||||
resp, err = resty.R().Get(baseURL + "/query?query=" + query)
|
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + query)
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
query = "{ExpandedRepoInfo(repo:\"a/zot-test\"){Manifests%20{Digest%20Tag%20IsSigned%20%Layers%20{Size%20Digest}}}}"
|
query = "{ExpandedRepoInfo(repo:\"a/zot-test\"){Manifests%20{Digest%20Tag%20IsSigned%20%Layers%20{Size%20Digest}}}}"
|
||||||
resp, err = resty.R().Get(baseURL + "/query?query=" + query)
|
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + query)
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
@ -408,7 +413,7 @@ func TestExpandedRepoInfo(t *testing.T) {
|
||||||
|
|
||||||
query = "{ExpandedRepoInfo(repo:\"zot-test\"){Manifests%20{Digest%20Tag%20IsSigned%20%Layers%20{Size%20Digest}}}}"
|
query = "{ExpandedRepoInfo(repo:\"zot-test\"){Manifests%20{Digest%20Tag%20IsSigned%20%Layers%20{Size%20Digest}}}}"
|
||||||
|
|
||||||
resp, err = resty.R().Get(baseURL + "/query?query=" + query)
|
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + query)
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"gopkg.in/resty.v1"
|
"gopkg.in/resty.v1"
|
||||||
"zotregistry.io/zot/pkg/api"
|
"zotregistry.io/zot/pkg/api"
|
||||||
"zotregistry.io/zot/pkg/api/config"
|
"zotregistry.io/zot/pkg/api/config"
|
||||||
|
"zotregistry.io/zot/pkg/api/constants"
|
||||||
extconf "zotregistry.io/zot/pkg/extensions/config"
|
extconf "zotregistry.io/zot/pkg/extensions/config"
|
||||||
"zotregistry.io/zot/pkg/extensions/monitoring"
|
"zotregistry.io/zot/pkg/extensions/monitoring"
|
||||||
"zotregistry.io/zot/pkg/extensions/search/common"
|
"zotregistry.io/zot/pkg/extensions/search/common"
|
||||||
|
@ -430,7 +431,7 @@ func TestCVESearch(t *testing.T) {
|
||||||
err = json.Unmarshal(resp.Body(), &apiErr)
|
err = json.Unmarshal(resp.Body(), &apiErr)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
resp, err = resty.R().Get(baseURL + "/query/")
|
resp, err = resty.R().Get(baseURL + constants.ExtSearchPrefix)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 401)
|
So(resp.StatusCode(), ShouldEqual, 401)
|
||||||
|
@ -446,11 +447,11 @@ func TestCVESearch(t *testing.T) {
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix)
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={CVEListForImage(image:\"zot-test:0.0.1\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
|
@ -461,7 +462,7 @@ func TestCVESearch(t *testing.T) {
|
||||||
|
|
||||||
cvid := cveResult.ImgList.CVEResultForImage.CVEList[0].ID
|
cvid := cveResult.ImgList.CVEResultForImage.CVEList[0].ID
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={ImageListWithCVEFixed(id:\"" + cvid + "\",image:\"zot-test\"){Tags{Name%20Timestamp}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cvid + "\",image:\"zot-test\"){Tags{Name%20Timestamp}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
|
@ -470,7 +471,7 @@ func TestCVESearch(t *testing.T) {
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(len(imgFixedCVEResult.ImgResults.ImgResultForFixedCVE.Tags), ShouldEqual, 0)
|
So(len(imgFixedCVEResult.ImgResults.ImgResultForFixedCVE.Tags), ShouldEqual, 0)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={ImageListWithCVEFixed(id:\"" + cvid + "\",image:\"zot-cve-test\"){Tags{Name%20Timestamp}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cvid + "\",image:\"zot-cve-test\"){Tags{Name%20Timestamp}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
|
@ -478,11 +479,11 @@ func TestCVESearch(t *testing.T) {
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(len(imgFixedCVEResult.ImgResults.ImgResultForFixedCVE.Tags), ShouldEqual, 0)
|
So(len(imgFixedCVEResult.ImgResults.ImgResultForFixedCVE.Tags), ShouldEqual, 0)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={ImageListWithCVEFixed(id:\"" + cvid + "\",image:\"zot-test\"){Tags{Name%20Timestamp}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cvid + "\",image:\"zot-test\"){Tags{Name%20Timestamp}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={CVEListForImage(image:\"b/zot-squashfs-test:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={CVEListForImage(image:\"b/zot-squashfs-test:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
|
@ -491,108 +492,108 @@ func TestCVESearch(t *testing.T) {
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(len(cveSquashFSResult.ImgList.CVEResultForImage.CVEList), ShouldBeZeroValue)
|
So(len(cveSquashFSResult.ImgList.CVEResultForImage.CVEList), ShouldBeZeroValue)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={CVEListForImage(image:\"zot-squashfs-noindex:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={CVEListForImage(image:\"zot-squashfs-noindex:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={ImageListWithCVEFixed(id:\"" + cvid + "\",image:\"zot-squashfs-noindex\"){Tags{Name%20Timestamp}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cvid + "\",image:\"zot-squashfs-noindex\"){Tags{Name%20Timestamp}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={CVEListForImage(image:\"zot-squashfs-invalid-index:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={CVEListForImage(image:\"zot-squashfs-invalid-index:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={ImageListWithCVEFixed(id:\"" + cvid + "\",image:\"zot-squashfs-invalid-index\"){Tags{Name%20Timestamp}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cvid + "\",image:\"zot-squashfs-invalid-index\"){Tags{Name%20Timestamp}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={CVEListForImage(image:\"zot-squashfs-noblobs:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={CVEListForImage(image:\"zot-squashfs-noblobs:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={ImageListWithCVEFixed(id:\"" + cvid + "\",image:\"zot-squashfs-noblob\"){Tags{Name%20Timestamp}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cvid + "\",image:\"zot-squashfs-noblob\"){Tags{Name%20Timestamp}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={ImageListWithCVEFixed(id:\"" + cvid + "\",image:\"zot-squashfs-test\"){Tags{Name%20Timestamp}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cvid + "\",image:\"zot-squashfs-test\"){Tags{Name%20Timestamp}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={CVEListForImage(image:\"zot-squashfs-invalid-blob:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={CVEListForImage(image:\"zot-squashfs-invalid-blob:commit-aaa7c6e7-squashfs\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={ImageListWithCVEFixed(id:\"" + cvid + "\",image:\"zot-squashfs-invalid-blob\"){Tags{Name%20Timestamp}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={ImageListWithCVEFixed(id:\"" + cvid + "\",image:\"zot-squashfs-invalid-blob\"){Tags{Name%20Timestamp}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={CVEListForImage(image:\"zot-squashfs-test\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={CVEListForImage(image:\"zot-squashfs-test\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={CVEListForImage(image:\"cntos\"){Tag%20CVEList{Id%20Description%20Severity}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={CVEListForImage(image:\"cntos\"){Tag%20CVEList{Id%20Description%20Severity}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={ImageListForCVE(id:\"CVE-201-20482\"){Name%20Tags}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={ImageListForCVE(id:\"CVE-201-20482\"){Name%20Tags}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={CVEListForImage(image:\"zot-test\"){Tag%20CVEList{Id%20Description}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={CVEListForImage(image:\"zot-test\"){Tag%20CVEList{Id%20Description}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={CVEListForImage(image:\"zot-test:0.0.1\"){Tag}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){Tag}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id%20Description%20Severity}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id%20Description%20Severity}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Description%20Severity}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Description%20Severity}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id%20Severity}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id%20Severity}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id%20Description}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id%20Description}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Id}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Description}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){CVEList{Description}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
// Testing Invalid Search URL
|
// Testing Invalid Search URL
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={CVEListForImage(image:\"zot-test:0.0.1\"){Ta%20CVEList{Id%20Description%20Severity}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){Ta%20CVEList{Id%20Description%20Severity}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 422)
|
So(resp.StatusCode(), ShouldEqual, 422)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={ImageListForCVE(tet:\"CVE-2018-20482\"){Name%20Tags}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={ImageListForCVE(tet:\"CVE-2018-20482\"){Name%20Tags}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 422)
|
So(resp.StatusCode(), ShouldEqual, 422)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={ImageistForCVE(id:\"CVE-2018-20482\"){Name%20Tags}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={ImageistForCVE(id:\"CVE-2018-20482\"){Name%20Tags}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 422)
|
So(resp.StatusCode(), ShouldEqual, 422)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={ImageListForCVE(id:\"CVE-2018-20482\"){ame%20Tags}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={ImageListForCVE(id:\"CVE-2018-20482\"){ame%20Tags}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 422)
|
So(resp.StatusCode(), ShouldEqual, 422)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={CVEListForImage(reo:\"zot-test:1.0.0\"){Tag%20CVEList{Id%20Description%20Severity}}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={CVEListForImage(reo:\"zot-test:1.0.0\"){Tag%20CVEList{Id%20Description%20Severity}}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 422)
|
So(resp.StatusCode(), ShouldEqual, 422)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/query?query={ImageListForCVE(id:\"" + cvid + "\"){Name%20Tags}}")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.ExtSearchPrefix + "?query={ImageListForCVE(id:\"" + cvid + "\"){Name%20Tags}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
})
|
})
|
||||||
|
@ -648,11 +649,11 @@ func TestCVEConfig(t *testing.T) {
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, _ := resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/v2/")
|
resp, _ := resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.RoutePrefix + "/")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + "/v2/_catalog")
|
resp, _ = resty.R().SetBasicAuth(username, passphrase).Get(baseURL + constants.RoutePrefix + constants.ExtCatalogPrefix)
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
|
@ -721,7 +722,7 @@ func TestHTTPOptionsResponse(t *testing.T) {
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, _ := resty.R().Options(baseURL + "/v2/_catalog")
|
resp, _ := resty.R().Options(baseURL + constants.RoutePrefix + constants.ExtCatalogPrefix)
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, http.StatusNoContent)
|
So(resp.StatusCode(), ShouldEqual, http.StatusNoContent)
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"gopkg.in/resty.v1"
|
"gopkg.in/resty.v1"
|
||||||
"zotregistry.io/zot/pkg/api"
|
"zotregistry.io/zot/pkg/api"
|
||||||
"zotregistry.io/zot/pkg/api/config"
|
"zotregistry.io/zot/pkg/api/config"
|
||||||
|
"zotregistry.io/zot/pkg/api/constants"
|
||||||
extconf "zotregistry.io/zot/pkg/extensions/config"
|
extconf "zotregistry.io/zot/pkg/extensions/config"
|
||||||
"zotregistry.io/zot/pkg/extensions/monitoring"
|
"zotregistry.io/zot/pkg/extensions/monitoring"
|
||||||
digestinfo "zotregistry.io/zot/pkg/extensions/search/digest"
|
digestinfo "zotregistry.io/zot/pkg/extensions/search/digest"
|
||||||
|
@ -179,13 +180,14 @@ func TestDigestSearchHTTP(t *testing.T) {
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, err = resty.R().Get(baseURL + "/query")
|
resp, err = resty.R().Get(baseURL + constants.ExtSearchPrefix)
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
// "sha" should match all digests in all images
|
// "sha" should match all digests in all images
|
||||||
resp, err = resty.R().Get(baseURL + "/query?query={ImageListForDigest(id:\"sha\"){Name%20Tags}}")
|
resp, err = resty.R().Get(baseURL + constants.ExtSearchPrefix +
|
||||||
|
"?query={ImageListForDigest(id:\"sha\"){Name%20Tags}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
@ -200,7 +202,8 @@ func TestDigestSearchHTTP(t *testing.T) {
|
||||||
|
|
||||||
// Call should return {"data":{"ImageListForDigest":[{"Name":"zot-test","Tags":["0.0.1"]}]}}
|
// Call should return {"data":{"ImageListForDigest":[{"Name":"zot-test","Tags":["0.0.1"]}]}}
|
||||||
// "2bacca16" should match the manifest of 1 image
|
// "2bacca16" should match the manifest of 1 image
|
||||||
resp, err = resty.R().Get(baseURL + "/query?query={ImageListForDigest(id:\"2bacca16\"){Name%20Tags}}")
|
resp, err = resty.R().Get(baseURL + constants.ExtSearchPrefix +
|
||||||
|
"?query={ImageListForDigest(id:\"2bacca16\"){Name%20Tags}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
@ -215,7 +218,8 @@ func TestDigestSearchHTTP(t *testing.T) {
|
||||||
|
|
||||||
// Call should return {"data":{"ImageListForDigest":[{"Name":"zot-test","Tags":["0.0.1"]}]}}
|
// Call should return {"data":{"ImageListForDigest":[{"Name":"zot-test","Tags":["0.0.1"]}]}}
|
||||||
// "adf3bb6c" should match the config of 1 image
|
// "adf3bb6c" should match the config of 1 image
|
||||||
resp, err = resty.R().Get(baseURL + "/query?query={ImageListForDigest(id:\"adf3bb6c\"){Name%20Tags}}")
|
resp, err = resty.R().Get(baseURL + constants.ExtSearchPrefix +
|
||||||
|
"?query={ImageListForDigest(id:\"adf3bb6c\"){Name%20Tags}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
@ -230,7 +234,8 @@ func TestDigestSearchHTTP(t *testing.T) {
|
||||||
|
|
||||||
// Call should return {"data":{"ImageListForDigest":[{"Name":"zot-cve-test","Tags":["0.0.1"]}]}}
|
// Call should return {"data":{"ImageListForDigest":[{"Name":"zot-cve-test","Tags":["0.0.1"]}]}}
|
||||||
// "7a0437f0" should match the layer of 1 image
|
// "7a0437f0" should match the layer of 1 image
|
||||||
resp, err = resty.R().Get(baseURL + "/query?query={ImageListForDigest(id:\"7a0437f0\"){Name%20Tags}}")
|
resp, err = resty.R().Get(baseURL + constants.ExtSearchPrefix +
|
||||||
|
"?query={ImageListForDigest(id:\"7a0437f0\"){Name%20Tags}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
@ -245,7 +250,8 @@ func TestDigestSearchHTTP(t *testing.T) {
|
||||||
|
|
||||||
// Call should return {"data":{"ImageListForDigest":[]}}
|
// Call should return {"data":{"ImageListForDigest":[]}}
|
||||||
// "1111111" should match 0 images
|
// "1111111" should match 0 images
|
||||||
resp, err = resty.R().Get(baseURL + "/query?query={ImageListForDigest(id:\"1111111\"){Name%20Tags}}")
|
resp, err = resty.R().Get(baseURL + constants.ExtSearchPrefix +
|
||||||
|
"?query={ImageListForDigest(id:\"1111111\"){Name%20Tags}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
@ -256,7 +262,8 @@ func TestDigestSearchHTTP(t *testing.T) {
|
||||||
So(len(responseStruct.ImgListForDigest.Images), ShouldEqual, 0)
|
So(len(responseStruct.ImgListForDigest.Images), ShouldEqual, 0)
|
||||||
|
|
||||||
// Call should return {"errors": [{....}]", data":null}}
|
// Call should return {"errors": [{....}]", data":null}}
|
||||||
resp, err = resty.R().Get(baseURL + "/query?query={ImageListForDigest(id:\"1111111\"){Name%20Tag343s}}")
|
resp, err = resty.R().Get(baseURL + constants.ExtSearchPrefix +
|
||||||
|
"?query={ImageListForDigest(id:\"1111111\"){Name%20Tag343s}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 422)
|
So(resp.StatusCode(), ShouldEqual, 422)
|
||||||
|
@ -321,12 +328,13 @@ func TestDigestSearchHTTPSubPaths(t *testing.T) {
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, err = resty.R().Get(baseURL + "/query")
|
resp, err = resty.R().Get(baseURL + constants.ExtSearchPrefix)
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, err = resty.R().Get(baseURL + "/query?query={ImageListForDigest(id:\"sha\"){Name%20Tags}}")
|
resp, err = resty.R().Get(baseURL + constants.ExtSearchPrefix +
|
||||||
|
"?query={ImageListForDigest(id:\"sha\"){Name%20Tags}}")
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
@ -380,7 +388,7 @@ func TestDigestSearchDisabled(t *testing.T) {
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
|
||||||
resp, err = resty.R().Get(baseURL + "/query")
|
resp, err = resty.R().Get(baseURL + constants.ExtSearchPrefix)
|
||||||
So(resp, ShouldNotBeNil)
|
So(resp, ShouldNotBeNil)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 404)
|
So(resp.StatusCode(), ShouldEqual, 404)
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"gopkg.in/resty.v1"
|
"gopkg.in/resty.v1"
|
||||||
zerr "zotregistry.io/zot/errors"
|
zerr "zotregistry.io/zot/errors"
|
||||||
|
"zotregistry.io/zot/pkg/api/constants"
|
||||||
"zotregistry.io/zot/pkg/log"
|
"zotregistry.io/zot/pkg/log"
|
||||||
"zotregistry.io/zot/pkg/storage"
|
"zotregistry.io/zot/pkg/storage"
|
||||||
"zotregistry.io/zot/pkg/test"
|
"zotregistry.io/zot/pkg/test"
|
||||||
|
@ -77,7 +78,7 @@ type Tags struct {
|
||||||
func getUpstreamCatalog(client *resty.Client, upstreamURL string, log log.Logger) (catalog, error) {
|
func getUpstreamCatalog(client *resty.Client, upstreamURL string, log log.Logger) (catalog, error) {
|
||||||
var catalog catalog
|
var catalog catalog
|
||||||
|
|
||||||
registryCatalogURL := fmt.Sprintf("%s%s", upstreamURL, "/v2/_catalog")
|
registryCatalogURL := fmt.Sprintf("%s%s%s", upstreamURL, constants.RoutePrefix, constants.ExtCatalogPrefix)
|
||||||
|
|
||||||
resp, err := client.R().SetHeader("Content-Type", "application/json").Get(registryCatalogURL)
|
resp, err := client.R().SetHeader("Content-Type", "application/json").Get(registryCatalogURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -37,6 +37,7 @@ import (
|
||||||
"gopkg.in/resty.v1"
|
"gopkg.in/resty.v1"
|
||||||
"zotregistry.io/zot/pkg/api"
|
"zotregistry.io/zot/pkg/api"
|
||||||
"zotregistry.io/zot/pkg/api/config"
|
"zotregistry.io/zot/pkg/api/config"
|
||||||
|
"zotregistry.io/zot/pkg/api/constants"
|
||||||
"zotregistry.io/zot/pkg/cli"
|
"zotregistry.io/zot/pkg/cli"
|
||||||
extconf "zotregistry.io/zot/pkg/extensions/config"
|
extconf "zotregistry.io/zot/pkg/extensions/config"
|
||||||
"zotregistry.io/zot/pkg/extensions/sync"
|
"zotregistry.io/zot/pkg/extensions/sync"
|
||||||
|
@ -1315,11 +1316,11 @@ func TestNoImagesByRegex(t *testing.T) {
|
||||||
dctlr.Shutdown()
|
dctlr.Shutdown()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
resp, err := destClient.R().Get(destBaseURL + "/v2/" + testImage + "/manifests/" + testImageTag)
|
resp, err := destClient.R().Get(destBaseURL + constants.RoutePrefix + testImage + "/manifests/" + testImageTag)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp.StatusCode(), ShouldEqual, 404)
|
So(resp.StatusCode(), ShouldEqual, 404)
|
||||||
|
|
||||||
resp, err = destClient.R().Get(destBaseURL + "/v2/_catalog")
|
resp, err = destClient.R().Get(destBaseURL + constants.RoutePrefix + constants.ExtCatalogPrefix)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(resp, ShouldNotBeEmpty)
|
So(resp, ShouldNotBeEmpty)
|
||||||
So(resp.StatusCode(), ShouldEqual, 200)
|
So(resp.StatusCode(), ShouldEqual, 200)
|
||||||
|
@ -1743,7 +1744,7 @@ func TestSubPaths(t *testing.T) {
|
||||||
var destTagsList TagsList
|
var destTagsList TagsList
|
||||||
|
|
||||||
for {
|
for {
|
||||||
resp, err := resty.R().Get(destBaseURL + "/v2" + path.Join(subpath, testImage) + "/tags/list")
|
resp, err := resty.R().Get(destBaseURL + constants.RoutePrefix + path.Join(subpath, testImage) + "/tags/list")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -2169,7 +2170,7 @@ func TestPeriodicallySignaturesErr(t *testing.T) {
|
||||||
cosignTag := string(imageManifestDigest.Algorithm()) + "-" + imageManifestDigest.Hex() +
|
cosignTag := string(imageManifestDigest.Algorithm()) + "-" + imageManifestDigest.Hex() +
|
||||||
"." + remote.SignatureTagSuffix
|
"." + remote.SignatureTagSuffix
|
||||||
|
|
||||||
getCosignManifestURL := srcBaseURL + path.Join("/v2", repoName, "manifests", cosignTag)
|
getCosignManifestURL := srcBaseURL + path.Join(constants.RoutePrefix, repoName, "manifests", cosignTag)
|
||||||
mResp, err := resty.R().Get(getCosignManifestURL)
|
mResp, err := resty.R().Get(getCosignManifestURL)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
@ -2444,7 +2445,7 @@ func TestSignatures(t *testing.T) {
|
||||||
// test cosign signatures errors
|
// test cosign signatures errors
|
||||||
// based on manifest digest get cosign manifest
|
// based on manifest digest get cosign manifest
|
||||||
cosignEncodedDigest := strings.Replace(digest.String(), ":", "-", 1) + ".sig"
|
cosignEncodedDigest := strings.Replace(digest.String(), ":", "-", 1) + ".sig"
|
||||||
getCosignManifestURL := srcBaseURL + path.Join("/v2", repoName, "manifests", cosignEncodedDigest)
|
getCosignManifestURL := srcBaseURL + path.Join(constants.RoutePrefix, repoName, "manifests", cosignEncodedDigest)
|
||||||
|
|
||||||
mResp, err := resty.R().Get(getCosignManifestURL)
|
mResp, err := resty.R().Get(getCosignManifestURL)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
@ -3057,7 +3058,7 @@ func TestSignaturesOnDemand(t *testing.T) {
|
||||||
|
|
||||||
// test negative case
|
// test negative case
|
||||||
cosignEncodedDigest := strings.Replace(digest.String(), ":", "-", 1) + ".sig"
|
cosignEncodedDigest := strings.Replace(digest.String(), ":", "-", 1) + ".sig"
|
||||||
getCosignManifestURL := srcBaseURL + path.Join("/v2", repoName, "manifests", cosignEncodedDigest)
|
getCosignManifestURL := srcBaseURL + path.Join(constants.RoutePrefix, repoName, "manifests", cosignEncodedDigest)
|
||||||
|
|
||||||
mResp, err := resty.R().Get(getCosignManifestURL)
|
mResp, err := resty.R().Get(getCosignManifestURL)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
163
swagger/docs.go
163
swagger/docs.go
|
@ -1,12 +1,13 @@
|
||||||
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
// This file was generated by swaggo/swag at
|
// This file was generated by swaggo/swag at
|
||||||
// 2019-12-11 12:03:05.055900322 -0800 PST m=+0.052058015
|
// 2022-05-20 22:28:21.990630149 +0000 UTC m=+0.151110280
|
||||||
|
|
||||||
package swagger
|
package swagger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/template"
|
"github.com/alecthomas/template"
|
||||||
"github.com/swaggo/swag"
|
"github.com/swaggo/swag"
|
||||||
|
@ -16,8 +17,8 @@ var doc = `{
|
||||||
"schemes": {{ marshal .Schemes }},
|
"schemes": {{ marshal .Schemes }},
|
||||||
"swagger": "2.0",
|
"swagger": "2.0",
|
||||||
"info": {
|
"info": {
|
||||||
"description": "APIs for Open Container Initiative Distribution Specification",
|
"description": "{{.Description}}",
|
||||||
"title": "Open Container Initiative Distribution Specification",
|
"title": "{{.Title}}",
|
||||||
"contact": {
|
"contact": {
|
||||||
"name": "API Support",
|
"name": "API Support",
|
||||||
"url": "http://www.swagger.io/support",
|
"url": "http://www.swagger.io/support",
|
||||||
|
@ -27,11 +28,66 @@ var doc = `{
|
||||||
"name": "Apache 2.0",
|
"name": "Apache 2.0",
|
||||||
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
|
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
|
||||||
},
|
},
|
||||||
"version": "v0.1.0-dev"
|
"version": "{{.Version}}"
|
||||||
},
|
},
|
||||||
"host": "{{.Host}}",
|
"host": "{{.Host}}",
|
||||||
"basePath": "{{.BasePath}}",
|
"basePath": "{{.BasePath}}",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
"/oras/artifacts/v1/{name": {
|
||||||
|
"get": {
|
||||||
|
"description": "Get references for an image given a digest and artifact type",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"summary": "Get references for an image",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "repository name",
|
||||||
|
"name": "name",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "image digest",
|
||||||
|
"name": "digest",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "artifact type",
|
||||||
|
"name": "artifactType",
|
||||||
|
"in": "query",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "ok",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "not found",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "internal server error",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/v2/": {
|
"/v2/": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "Check if this API version is supported",
|
"description": "Check if this API version is supported",
|
||||||
|
@ -44,7 +100,7 @@ var doc = `{
|
||||||
"summary": "Check API support",
|
"summary": "Check API support",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "ok",
|
"description": "ok\".",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
|
@ -66,7 +122,6 @@ var doc = `{
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
|
||||||
"$ref": "#/definitions/api.RepositoryList"
|
"$ref": "#/definitions/api.RepositoryList"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -79,6 +134,26 @@ var doc = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/v2/_oci/ext/discover": {
|
||||||
|
"get": {
|
||||||
|
"description": "List all extensions present on registry",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"summary": "List Registry level extensions",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/api.ExtensionList"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/v2/{name}/blobs/uploads": {
|
"/v2/{name}/blobs/uploads": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "Create a new image blob/layer upload",
|
"description": "Create a new image blob/layer upload",
|
||||||
|
@ -107,7 +182,7 @@ var doc = `{
|
||||||
"headers": {
|
"headers": {
|
||||||
"Location": {
|
"Location": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "/v2/{name}/blobs/uploads/{uuid}"
|
"description": "/v2/{name}/blobs/uploads/{session_id}"
|
||||||
},
|
},
|
||||||
"Range": {
|
"Range": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -130,9 +205,9 @@ var doc = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/v2/{name}/blobs/uploads/{uuid}": {
|
"/v2/{name}/blobs/uploads/{session_id}": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "Get an image's blob/layer upload given a uuid",
|
"description": "Get an image's blob/layer upload given a session_id",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
|
@ -150,8 +225,8 @@ var doc = `{
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "upload uuid",
|
"description": "upload session_id",
|
||||||
"name": "uuid",
|
"name": "session_id",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
|
@ -196,8 +271,8 @@ var doc = `{
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "upload uuid",
|
"description": "upload session_id",
|
||||||
"name": "uuid",
|
"name": "session_id",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
|
@ -249,8 +324,8 @@ var doc = `{
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "upload uuid",
|
"description": "upload session_id",
|
||||||
"name": "uuid",
|
"name": "session_id",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
|
@ -277,7 +352,7 @@ var doc = `{
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"patch": {
|
"patch": {
|
||||||
"description": "Resume an image's blob/layer upload given an uuid",
|
"description": "Resume an image's blob/layer upload given an session_id",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
|
@ -295,8 +370,8 @@ var doc = `{
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "upload uuid",
|
"description": "upload session_id",
|
||||||
"name": "uuid",
|
"name": "session_id",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
|
@ -310,7 +385,7 @@ var doc = `{
|
||||||
"headers": {
|
"headers": {
|
||||||
"Location": {
|
"Location": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "/v2/{name}/blobs/uploads/{uuid}"
|
"description": "/v2/{name}/blobs/uploads/{session_id}"
|
||||||
},
|
},
|
||||||
"Range": {
|
"Range": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -375,7 +450,6 @@ var doc = `{
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
|
||||||
"$ref": "#/definitions/api.ImageManifest"
|
"$ref": "#/definitions/api.ImageManifest"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -444,11 +518,10 @@ var doc = `{
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
|
||||||
"$ref": "#/definitions/api.ImageManifest"
|
"$ref": "#/definitions/api.ImageManifest"
|
||||||
},
|
},
|
||||||
"headers": {
|
"headers": {
|
||||||
"api.DistContentDigestKey": {
|
"constants.DistContentDigestKey": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "OK"
|
"description": "OK"
|
||||||
}
|
}
|
||||||
|
@ -487,11 +560,10 @@ var doc = `{
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
|
||||||
"$ref": "#/definitions/api.ImageManifest"
|
"$ref": "#/definitions/api.ImageManifest"
|
||||||
},
|
},
|
||||||
"headers": {
|
"headers": {
|
||||||
"api.DistContentDigestKey": {
|
"constants.DistContentDigestKey": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "OK"
|
"description": "OK"
|
||||||
}
|
}
|
||||||
|
@ -629,7 +701,7 @@ var doc = `{
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"headers": {
|
"headers": {
|
||||||
"api.DistContentDigestKey": {
|
"cosntants.DistContentDigestKey": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "OK"
|
"description": "OK"
|
||||||
}
|
}
|
||||||
|
@ -642,7 +714,7 @@ var doc = `{
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"500": {
|
"500": {
|
||||||
"description": "internal server error",
|
"description": "internal server error\".",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
|
@ -667,16 +739,35 @@ var doc = `{
|
||||||
"name": "name",
|
"name": "name",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "limit entries for pagination",
|
||||||
|
"name": "n",
|
||||||
|
"in": "query",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "last tag value for pagination",
|
||||||
|
"name": "last",
|
||||||
|
"in": "query",
|
||||||
|
"required": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
|
||||||
"$ref": "#/definitions/api.ImageTags"
|
"$ref": "#/definitions/api.ImageTags"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "bad request\".",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
"404": {
|
"404": {
|
||||||
"description": "not found",
|
"description": "not found",
|
||||||
"schema": {
|
"schema": {
|
||||||
|
@ -688,6 +779,9 @@ var doc = `{
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
|
"api.ExtensionList": {
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"api.ImageManifest": {
|
"api.ImageManifest": {
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
@ -729,7 +823,14 @@ type swaggerInfo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SwaggerInfo holds exported Swagger Info so clients can modify it
|
// SwaggerInfo holds exported Swagger Info so clients can modify it
|
||||||
var SwaggerInfo = swaggerInfo{Schemes: []string{}}
|
var SwaggerInfo = swaggerInfo{
|
||||||
|
Version: "v0.1.0-dev",
|
||||||
|
Host: "",
|
||||||
|
BasePath: "",
|
||||||
|
Schemes: []string{},
|
||||||
|
Title: "Open Container Initiative Distribution Specification",
|
||||||
|
Description: "APIs for Open Container Initiative Distribution Specification",
|
||||||
|
}
|
||||||
|
|
||||||
type s struct{}
|
type s struct{}
|
||||||
|
|
||||||
|
@ -737,7 +838,11 @@ func New() *s {
|
||||||
return &s{}
|
return &s{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (s *s) ReadDoc() string {
|
func (s *s) ReadDoc() string {
|
||||||
|
sInfo := SwaggerInfo
|
||||||
|
sInfo.Description = strings.Replace(sInfo.Description, "\n", "\\n", -1)
|
||||||
|
|
||||||
t, err := template.New("swagger_info").Funcs(template.FuncMap{
|
t, err := template.New("swagger_info").Funcs(template.FuncMap{
|
||||||
"marshal": func(v interface{}) string {
|
"marshal": func(v interface{}) string {
|
||||||
a, _ := json.Marshal(v)
|
a, _ := json.Marshal(v)
|
||||||
|
@ -749,7 +854,7 @@ func (s *s) ReadDoc() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
var tpl bytes.Buffer
|
var tpl bytes.Buffer
|
||||||
if err := t.Execute(&tpl, SwaggerInfo); err != nil {
|
if err := t.Execute(&tpl, sInfo); err != nil {
|
||||||
return doc
|
return doc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,62 @@
|
||||||
},
|
},
|
||||||
"version": "v0.1.0-dev"
|
"version": "v0.1.0-dev"
|
||||||
},
|
},
|
||||||
"host": "{{.Host}}",
|
|
||||||
"basePath": "{{.BasePath}}",
|
|
||||||
"paths": {
|
"paths": {
|
||||||
|
"/oras/artifacts/v1/{name": {
|
||||||
|
"get": {
|
||||||
|
"description": "Get references for an image given a digest and artifact type",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"summary": "Get references for an image",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "repository name",
|
||||||
|
"name": "name",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "image digest",
|
||||||
|
"name": "digest",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "artifact type",
|
||||||
|
"name": "artifactType",
|
||||||
|
"in": "query",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "ok",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "not found",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "internal server error",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/v2/": {
|
"/v2/": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "Check if this API version is supported",
|
"description": "Check if this API version is supported",
|
||||||
|
@ -29,7 +82,7 @@
|
||||||
"summary": "Check API support",
|
"summary": "Check API support",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "ok",
|
"description": "ok\".",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
|
@ -51,7 +104,6 @@
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
|
||||||
"$ref": "#/definitions/api.RepositoryList"
|
"$ref": "#/definitions/api.RepositoryList"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -64,6 +116,26 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/v2/_oci/ext/discover": {
|
||||||
|
"get": {
|
||||||
|
"description": "List all extensions present on registry",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"summary": "List Registry level extensions",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/api.ExtensionList"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/v2/{name}/blobs/uploads": {
|
"/v2/{name}/blobs/uploads": {
|
||||||
"post": {
|
"post": {
|
||||||
"description": "Create a new image blob/layer upload",
|
"description": "Create a new image blob/layer upload",
|
||||||
|
@ -92,7 +164,7 @@
|
||||||
"headers": {
|
"headers": {
|
||||||
"Location": {
|
"Location": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "/v2/{name}/blobs/uploads/{uuid}"
|
"description": "/v2/{name}/blobs/uploads/{session_id}"
|
||||||
},
|
},
|
||||||
"Range": {
|
"Range": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -115,9 +187,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/v2/{name}/blobs/uploads/{uuid}": {
|
"/v2/{name}/blobs/uploads/{session_id}": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "Get an image's blob/layer upload given a uuid",
|
"description": "Get an image's blob/layer upload given a session_id",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
|
@ -135,8 +207,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "upload uuid",
|
"description": "upload session_id",
|
||||||
"name": "uuid",
|
"name": "session_id",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
|
@ -181,8 +253,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "upload uuid",
|
"description": "upload session_id",
|
||||||
"name": "uuid",
|
"name": "session_id",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
|
@ -234,8 +306,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "upload uuid",
|
"description": "upload session_id",
|
||||||
"name": "uuid",
|
"name": "session_id",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
|
@ -262,7 +334,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"patch": {
|
"patch": {
|
||||||
"description": "Resume an image's blob/layer upload given an uuid",
|
"description": "Resume an image's blob/layer upload given an session_id",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
|
@ -280,8 +352,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "upload uuid",
|
"description": "upload session_id",
|
||||||
"name": "uuid",
|
"name": "session_id",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
|
@ -295,7 +367,7 @@
|
||||||
"headers": {
|
"headers": {
|
||||||
"Location": {
|
"Location": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "/v2/{name}/blobs/uploads/{uuid}"
|
"description": "/v2/{name}/blobs/uploads/{session_id}"
|
||||||
},
|
},
|
||||||
"Range": {
|
"Range": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -360,7 +432,6 @@
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
|
||||||
"$ref": "#/definitions/api.ImageManifest"
|
"$ref": "#/definitions/api.ImageManifest"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -429,11 +500,10 @@
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
|
||||||
"$ref": "#/definitions/api.ImageManifest"
|
"$ref": "#/definitions/api.ImageManifest"
|
||||||
},
|
},
|
||||||
"headers": {
|
"headers": {
|
||||||
"api.DistContentDigestKey": {
|
"constants.DistContentDigestKey": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "OK"
|
"description": "OK"
|
||||||
}
|
}
|
||||||
|
@ -472,11 +542,10 @@
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
|
||||||
"$ref": "#/definitions/api.ImageManifest"
|
"$ref": "#/definitions/api.ImageManifest"
|
||||||
},
|
},
|
||||||
"headers": {
|
"headers": {
|
||||||
"api.DistContentDigestKey": {
|
"constants.DistContentDigestKey": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "OK"
|
"description": "OK"
|
||||||
}
|
}
|
||||||
|
@ -614,7 +683,7 @@
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"headers": {
|
"headers": {
|
||||||
"api.DistContentDigestKey": {
|
"cosntants.DistContentDigestKey": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "OK"
|
"description": "OK"
|
||||||
}
|
}
|
||||||
|
@ -627,7 +696,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"500": {
|
"500": {
|
||||||
"description": "internal server error",
|
"description": "internal server error\".",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
|
@ -652,16 +721,35 @@
|
||||||
"name": "name",
|
"name": "name",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "limit entries for pagination",
|
||||||
|
"name": "n",
|
||||||
|
"in": "query",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "last tag value for pagination",
|
||||||
|
"name": "last",
|
||||||
|
"in": "query",
|
||||||
|
"required": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
|
||||||
"$ref": "#/definitions/api.ImageTags"
|
"$ref": "#/definitions/api.ImageTags"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "bad request\".",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
"404": {
|
"404": {
|
||||||
"description": "not found",
|
"description": "not found",
|
||||||
"schema": {
|
"schema": {
|
||||||
|
@ -673,6 +761,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
|
"api.ExtensionList": {
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"api.ImageManifest": {
|
"api.ImageManifest": {
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
basePath: '{{.BasePath}}'
|
|
||||||
definitions:
|
definitions:
|
||||||
|
api.ExtensionList:
|
||||||
|
type: object
|
||||||
api.ImageManifest:
|
api.ImageManifest:
|
||||||
type: object
|
type: object
|
||||||
api.ImageTags:
|
api.ImageTags:
|
||||||
|
@ -18,7 +19,6 @@ definitions:
|
||||||
type: string
|
type: string
|
||||||
type: array
|
type: array
|
||||||
type: object
|
type: object
|
||||||
host: '{{.Host}}'
|
|
||||||
info:
|
info:
|
||||||
contact:
|
contact:
|
||||||
email: support@swagger.io
|
email: support@swagger.io
|
||||||
|
@ -31,6 +31,43 @@ info:
|
||||||
title: Open Container Initiative Distribution Specification
|
title: Open Container Initiative Distribution Specification
|
||||||
version: v0.1.0-dev
|
version: v0.1.0-dev
|
||||||
paths:
|
paths:
|
||||||
|
/oras/artifacts/v1/{name:
|
||||||
|
get:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: Get references for an image given a digest and artifact type
|
||||||
|
parameters:
|
||||||
|
- description: repository name
|
||||||
|
in: path
|
||||||
|
name: name
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- description: image digest
|
||||||
|
in: path
|
||||||
|
name: digest
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- description: artifact type
|
||||||
|
in: query
|
||||||
|
name: artifactType
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: ok
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
"404":
|
||||||
|
description: not found
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
"500":
|
||||||
|
description: internal server error
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
summary: Get references for an image
|
||||||
/v2/:
|
/v2/:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
|
@ -40,7 +77,7 @@ paths:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: ok
|
description: ok".
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
summary: Check API support
|
summary: Check API support
|
||||||
|
@ -56,12 +93,24 @@ paths:
|
||||||
description: OK
|
description: OK
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/api.RepositoryList'
|
$ref: '#/definitions/api.RepositoryList'
|
||||||
type: object
|
|
||||||
"500":
|
"500":
|
||||||
description: internal server error
|
description: internal server error
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
summary: List image repositories
|
summary: List image repositories
|
||||||
|
/v2/_oci/ext/discover:
|
||||||
|
get:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: List all extensions present on registry
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/api.ExtensionList'
|
||||||
|
summary: List Registry level extensions
|
||||||
/v2/{name}/blobs/{digest}:
|
/v2/{name}/blobs/{digest}:
|
||||||
delete:
|
delete:
|
||||||
consumes:
|
consumes:
|
||||||
|
@ -108,7 +157,6 @@ paths:
|
||||||
description: OK
|
description: OK
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/api.ImageManifest'
|
$ref: '#/definitions/api.ImageManifest'
|
||||||
type: object
|
|
||||||
summary: Get image blob/layer
|
summary: Get image blob/layer
|
||||||
head:
|
head:
|
||||||
consumes:
|
consumes:
|
||||||
|
@ -131,12 +179,11 @@ paths:
|
||||||
"200":
|
"200":
|
||||||
description: OK
|
description: OK
|
||||||
headers:
|
headers:
|
||||||
api.DistContentDigestKey:
|
constants.DistContentDigestKey:
|
||||||
description: OK
|
description: OK
|
||||||
type: object
|
type: object
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/api.ImageManifest'
|
$ref: '#/definitions/api.ImageManifest'
|
||||||
type: object
|
|
||||||
summary: Check image blob/layer
|
summary: Check image blob/layer
|
||||||
/v2/{name}/blobs/uploads:
|
/v2/{name}/blobs/uploads:
|
||||||
post:
|
post:
|
||||||
|
@ -156,7 +203,7 @@ paths:
|
||||||
description: accepted
|
description: accepted
|
||||||
headers:
|
headers:
|
||||||
Location:
|
Location:
|
||||||
description: /v2/{name}/blobs/uploads/{uuid}
|
description: /v2/{name}/blobs/uploads/{session_id}
|
||||||
type: string
|
type: string
|
||||||
Range:
|
Range:
|
||||||
description: bytes=0-0
|
description: bytes=0-0
|
||||||
|
@ -172,7 +219,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
summary: Create image blob/layer upload
|
summary: Create image blob/layer upload
|
||||||
/v2/{name}/blobs/uploads/{uuid}:
|
/v2/{name}/blobs/uploads/{session_id}:
|
||||||
delete:
|
delete:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
|
@ -183,9 +230,9 @@ paths:
|
||||||
name: name
|
name: name
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
- description: upload uuid
|
- description: upload session_id
|
||||||
in: path
|
in: path
|
||||||
name: uuid
|
name: session_id
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
produces:
|
produces:
|
||||||
|
@ -207,16 +254,16 @@ paths:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: Get an image's blob/layer upload given a uuid
|
description: Get an image's blob/layer upload given a session_id
|
||||||
parameters:
|
parameters:
|
||||||
- description: repository name
|
- description: repository name
|
||||||
in: path
|
in: path
|
||||||
name: name
|
name: name
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
- description: upload uuid
|
- description: upload session_id
|
||||||
in: path
|
in: path
|
||||||
name: uuid
|
name: session_id
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
produces:
|
produces:
|
||||||
|
@ -238,16 +285,16 @@ paths:
|
||||||
patch:
|
patch:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: Resume an image's blob/layer upload given an uuid
|
description: Resume an image's blob/layer upload given an session_id
|
||||||
parameters:
|
parameters:
|
||||||
- description: repository name
|
- description: repository name
|
||||||
in: path
|
in: path
|
||||||
name: name
|
name: name
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
- description: upload uuid
|
- description: upload session_id
|
||||||
in: path
|
in: path
|
||||||
name: uuid
|
name: session_id
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
produces:
|
produces:
|
||||||
|
@ -257,7 +304,7 @@ paths:
|
||||||
description: accepted
|
description: accepted
|
||||||
headers:
|
headers:
|
||||||
Location:
|
Location:
|
||||||
description: /v2/{name}/blobs/uploads/{uuid}
|
description: /v2/{name}/blobs/uploads/{session_id}
|
||||||
type: string
|
type: string
|
||||||
Range:
|
Range:
|
||||||
description: bytes=0-128
|
description: bytes=0-128
|
||||||
|
@ -291,9 +338,9 @@ paths:
|
||||||
name: name
|
name: name
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
- description: upload uuid
|
- description: upload session_id
|
||||||
in: path
|
in: path
|
||||||
name: uuid
|
name: session_id
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
- description: blob/layer digest
|
- description: blob/layer digest
|
||||||
|
@ -362,12 +409,11 @@ paths:
|
||||||
"200":
|
"200":
|
||||||
description: OK
|
description: OK
|
||||||
headers:
|
headers:
|
||||||
api.DistContentDigestKey:
|
constants.DistContentDigestKey:
|
||||||
description: OK
|
description: OK
|
||||||
type: object
|
type: object
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/api.ImageManifest'
|
$ref: '#/definitions/api.ImageManifest'
|
||||||
type: object
|
|
||||||
"404":
|
"404":
|
||||||
description: not found
|
description: not found
|
||||||
schema:
|
schema:
|
||||||
|
@ -398,7 +444,7 @@ paths:
|
||||||
"200":
|
"200":
|
||||||
description: ok
|
description: ok
|
||||||
headers:
|
headers:
|
||||||
api.DistContentDigestKey:
|
cosntants.DistContentDigestKey:
|
||||||
description: OK
|
description: OK
|
||||||
type: object
|
type: object
|
||||||
schema:
|
schema:
|
||||||
|
@ -408,7 +454,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
"500":
|
"500":
|
||||||
description: internal server error
|
description: internal server error".
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
summary: Check image manifest
|
summary: Check image manifest
|
||||||
|
@ -458,6 +504,16 @@ paths:
|
||||||
name: name
|
name: name
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
|
- description: limit entries for pagination
|
||||||
|
in: query
|
||||||
|
name: "n"
|
||||||
|
required: true
|
||||||
|
type: integer
|
||||||
|
- description: last tag value for pagination
|
||||||
|
in: query
|
||||||
|
name: last
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
|
@ -465,7 +521,10 @@ paths:
|
||||||
description: OK
|
description: OK
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/api.ImageTags'
|
$ref: '#/definitions/api.ImageTags'
|
||||||
type: object
|
"400":
|
||||||
|
description: bad request".
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
"404":
|
"404":
|
||||||
description: not found
|
description: not found
|
||||||
schema:
|
schema:
|
||||||
|
|
Loading…
Add table
Reference in a new issue