forked from TrueCloudLab/distribution
Enable Go build tags
This enables go build tags so the GCS and OSS driver support is available in the binary distributed via the image build by Dockerfile. This led to quite a few fixes in the GCS and OSS packages raised as warning by golang-ci linter. Signed-off-by: Milos Gajdos <milosthegajdos@gmail.com>
This commit is contained in:
parent
71a6c56fbf
commit
6b388b1ba6
7 changed files with 40 additions and 30 deletions
|
@ -97,7 +97,7 @@ Run `make validate` to run the validators, including the linter and vendor valid
|
||||||
### Optional build tags
|
### Optional build tags
|
||||||
|
|
||||||
Optional [build tags](http://golang.org/pkg/go/build/) can be provided using
|
Optional [build tags](http://golang.org/pkg/go/build/) can be provided using
|
||||||
the environment variable `DOCKER_BUILDTAGS`.
|
the environment variable `BUILDTAGS`.
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt>noresumabledigest</dt>
|
<dt>noresumabledigest</dt>
|
||||||
|
|
|
@ -22,12 +22,12 @@ RUN --mount=target=. \
|
||||||
FROM base AS build
|
FROM base AS build
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
ARG LDFLAGS="-s -w"
|
ARG LDFLAGS="-s -w"
|
||||||
ARG BUILDTAGS="include_oss include_gcs"
|
ARG BUILDTAGS="include_oss,include_gcs"
|
||||||
RUN --mount=type=bind,target=/src,rw \
|
RUN --mount=type=bind,target=/src,rw \
|
||||||
--mount=type=cache,target=/root/.cache/go-build \
|
--mount=type=cache,target=/root/.cache/go-build \
|
||||||
--mount=target=/go/pkg/mod,type=cache \
|
--mount=target=/go/pkg/mod,type=cache \
|
||||||
--mount=type=bind,source=/tmp/.ldflags,target=/tmp/.ldflags,from=version \
|
--mount=type=bind,source=/tmp/.ldflags,target=/tmp/.ldflags,from=version \
|
||||||
set -x ; xx-go build -trimpath -ldflags "$(cat /tmp/.ldflags) ${LDFLAGS}" -o /usr/bin/registry ./cmd/registry \
|
set -x ; xx-go build -tags "${BUILDTAGS}" -trimpath -ldflags "$(cat /tmp/.ldflags) ${LDFLAGS}" -o /usr/bin/registry ./cmd/registry \
|
||||||
&& xx-verify --static /usr/bin/registry
|
&& xx-verify --static /usr/bin/registry
|
||||||
|
|
||||||
FROM scratch AS binary
|
FROM scratch AS binary
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
ARG GO_VERSION=1.19.9
|
ARG GO_VERSION=1.19.9
|
||||||
ARG ALPINE_VERSION=3.16
|
ARG ALPINE_VERSION=3.16
|
||||||
ARG GOLANGCI_LINT_VERSION=v1.52
|
ARG GOLANGCI_LINT_VERSION=v1.52
|
||||||
|
ARG BUILDTAGS="include_oss,include_gcs"
|
||||||
|
|
||||||
FROM golangci/golangci-lint:${GOLANGCI_LINT_VERSION}-alpine AS golangci-lint
|
FROM golangci/golangci-lint:${GOLANGCI_LINT_VERSION}-alpine AS golangci-lint
|
||||||
|
|
||||||
|
@ -15,4 +16,4 @@ ENV GOFLAGS="-buildvcs=false"
|
||||||
RUN --mount=type=bind,target=. \
|
RUN --mount=type=bind,target=. \
|
||||||
--mount=type=cache,target=/root/.cache \
|
--mount=type=cache,target=/root/.cache \
|
||||||
--mount=from=golangci-lint,source=/usr/bin/golangci-lint,target=/usr/bin/golangci-lint \
|
--mount=from=golangci-lint,source=/usr/bin/golangci-lint,target=/usr/bin/golangci-lint \
|
||||||
golangci-lint run
|
golangci-lint --build-tags "${BUILDTAGS}" run
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
//go:build include_gcs
|
||||||
|
// +build include_gcs
|
||||||
|
|
||||||
// Package gcs provides a storagedriver.StorageDriver implementation to
|
// Package gcs provides a storagedriver.StorageDriver implementation to
|
||||||
// store blobs in Google cloud storage.
|
// store blobs in Google cloud storage.
|
||||||
//
|
//
|
||||||
|
@ -9,10 +12,6 @@
|
||||||
//
|
//
|
||||||
// Note that the contents of incomplete uploads are not accessible even though
|
// Note that the contents of incomplete uploads are not accessible even though
|
||||||
// Stat returns their length
|
// Stat returns their length
|
||||||
//
|
|
||||||
//go:build include_gcs
|
|
||||||
// +build include_gcs
|
|
||||||
|
|
||||||
package gcs
|
package gcs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -66,7 +65,6 @@ var _ storagedriver.FileWriter = &writer{}
|
||||||
// driverParameters is a struct that encapsulates all of the driver parameters after all values have been set
|
// driverParameters is a struct that encapsulates all of the driver parameters after all values have been set
|
||||||
type driverParameters struct {
|
type driverParameters struct {
|
||||||
bucket string
|
bucket string
|
||||||
config *jwt.Config
|
|
||||||
email string
|
email string
|
||||||
privateKey []byte
|
privateKey []byte
|
||||||
client *http.Client
|
client *http.Client
|
||||||
|
@ -93,6 +91,8 @@ func (factory *gcsDriverFactory) Create(parameters map[string]interface{}) (stor
|
||||||
return FromParameters(parameters)
|
return FromParameters(parameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ storagedriver.StorageDriver = &driver{}
|
||||||
|
|
||||||
// driver is a storagedriver.StorageDriver implementation backed by GCS
|
// driver is a storagedriver.StorageDriver implementation backed by GCS
|
||||||
// Objects are stored at absolute keys in the provided bucket.
|
// Objects are stored at absolute keys in the provided bucket.
|
||||||
type driver struct {
|
type driver struct {
|
||||||
|
@ -289,6 +289,8 @@ func (d *driver) GetContent(ctx context.Context, path string) ([]byte, error) {
|
||||||
// PutContent stores the []byte content at a location designated by "path".
|
// PutContent stores the []byte content at a location designated by "path".
|
||||||
// This should primarily be used for small objects.
|
// This should primarily be used for small objects.
|
||||||
func (d *driver) PutContent(ctx context.Context, path string, contents []byte) error {
|
func (d *driver) PutContent(ctx context.Context, path string, contents []byte) error {
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
defer cancel()
|
||||||
wc := d.gcs.Bucket(d.bucket).Object(d.pathToKey(path)).NewWriter(ctx)
|
wc := d.gcs.Bucket(d.bucket).Object(d.pathToKey(path)).NewWriter(ctx)
|
||||||
wc.ContentType = "application/octet-stream"
|
wc.ContentType = "application/octet-stream"
|
||||||
return putContentsClose(wc, contents)
|
return putContentsClose(wc, contents)
|
||||||
|
@ -312,7 +314,7 @@ func (d *driver) Reader(ctx context.Context, path string, offset int64) (io.Read
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if offset == int64(obj.Size) {
|
if offset == obj.Size {
|
||||||
return io.NopCloser(bytes.NewReader([]byte{})), nil
|
return io.NopCloser(bytes.NewReader([]byte{})), nil
|
||||||
}
|
}
|
||||||
return nil, storagedriver.InvalidOffsetError{Path: path, Offset: offset}
|
return nil, storagedriver.InvalidOffsetError{Path: path, Offset: offset}
|
||||||
|
@ -450,7 +452,6 @@ func putContentsClose(wc *storage.Writer, contents []byte) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
wc.CloseWithError(err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return wc.Close()
|
return wc.Close()
|
||||||
|
@ -630,9 +631,9 @@ func (d *driver) Stat(ctx context.Context, path string) (storagedriver.FileInfo,
|
||||||
// try to get as folder
|
// try to get as folder
|
||||||
dirpath := d.pathToDirKey(path)
|
dirpath := d.pathToDirKey(path)
|
||||||
|
|
||||||
var query *storage.Query
|
query := &storage.Query{
|
||||||
query = &storage.Query{}
|
Prefix: dirpath,
|
||||||
query.Prefix = dirpath
|
}
|
||||||
|
|
||||||
objects, err := storageListObjects(ctx, d.bucket, query, d.gcs)
|
objects, err := storageListObjects(ctx, d.bucket, query, d.gcs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -656,10 +657,10 @@ func (d *driver) Stat(ctx context.Context, path string) (storagedriver.FileInfo,
|
||||||
// List returns a list of the objects that are direct descendants of the
|
// List returns a list of the objects that are direct descendants of the
|
||||||
// given path.
|
// given path.
|
||||||
func (d *driver) List(ctx context.Context, path string) ([]string, error) {
|
func (d *driver) List(ctx context.Context, path string) ([]string, error) {
|
||||||
var query *storage.Query
|
query := &storage.Query{
|
||||||
query = &storage.Query{}
|
Delimiter: "/",
|
||||||
query.Delimiter = "/"
|
Prefix: d.pathToDirKey(path),
|
||||||
query.Prefix = d.pathToDirKey(path)
|
}
|
||||||
list := make([]string, 0, 64)
|
list := make([]string, 0, 64)
|
||||||
objects, err := storageListObjects(ctx, d.bucket, query, d.gcs)
|
objects, err := storageListObjects(ctx, d.bucket, query, d.gcs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -690,7 +691,7 @@ func (d *driver) List(ctx context.Context, path string) ([]string, error) {
|
||||||
// Move moves an object stored at sourcePath to destPath, removing the
|
// Move moves an object stored at sourcePath to destPath, removing the
|
||||||
// original object.
|
// original object.
|
||||||
func (d *driver) Move(ctx context.Context, sourcePath string, destPath string) error {
|
func (d *driver) Move(ctx context.Context, sourcePath string, destPath string) error {
|
||||||
_, err := storageCopyObject(ctx, d.bucket, d.pathToKey(sourcePath), d.bucket, d.pathToKey(destPath), nil, d.gcs)
|
_, err := storageCopyObject(ctx, d.bucket, d.pathToKey(sourcePath), d.bucket, d.pathToKey(destPath), d.gcs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if status, ok := err.(*googleapi.Error); ok {
|
if status, ok := err.(*googleapi.Error); ok {
|
||||||
if status.Code == http.StatusNotFound {
|
if status.Code == http.StatusNotFound {
|
||||||
|
@ -794,7 +795,7 @@ func storageListObjects(ctx context.Context, bucket string, q *storage.Query, gc
|
||||||
return objs, nil
|
return objs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func storageCopyObject(ctx context.Context, srcBucket, srcName string, destBucket, destName string, attrs *storage.ObjectAttrs, gcs *storage.Client) (*storage.ObjectAttrs, error) {
|
func storageCopyObject(ctx context.Context, srcBucket, srcName string, destBucket, destName string, gcs *storage.Client) (*storage.ObjectAttrs, error) {
|
||||||
src := gcs.Bucket(srcBucket).Object(srcName)
|
src := gcs.Bucket(srcBucket).Object(srcName)
|
||||||
dst := gcs.Bucket(destBucket).Object(destName)
|
dst := gcs.Bucket(destBucket).Object(destName)
|
||||||
attrs, err := dst.CopierFrom(src).Run(ctx)
|
attrs, err := dst.CopierFrom(src).Run(ctx)
|
||||||
|
|
|
@ -66,7 +66,7 @@ func init() {
|
||||||
panic(fmt.Sprintf("Error reading JWT config : %s", err))
|
panic(fmt.Sprintf("Error reading JWT config : %s", err))
|
||||||
}
|
}
|
||||||
email = jwtConfig.Email
|
email = jwtConfig.Email
|
||||||
privateKey = []byte(jwtConfig.PrivateKey)
|
privateKey = jwtConfig.PrivateKey
|
||||||
if len(privateKey) == 0 {
|
if len(privateKey) == 0 {
|
||||||
panic("Error reading JWT config : missing private_key property")
|
panic("Error reading JWT config : missing private_key property")
|
||||||
}
|
}
|
||||||
|
@ -262,6 +262,9 @@ func TestEmptyRootList(t *testing.T) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
keys, err := emptyRootDriver.List(ctx, "/")
|
keys, err := emptyRootDriver.List(ctx, "/")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error listing empty root content: %v", err)
|
||||||
|
}
|
||||||
for _, path := range keys {
|
for _, path := range keys {
|
||||||
if !storagedriver.PathRegexp.MatchString(path) {
|
if !storagedriver.PathRegexp.MatchString(path) {
|
||||||
t.Fatalf("unexpected string in path: %q != %q", path, storagedriver.PathRegexp)
|
t.Fatalf("unexpected string in path: %q != %q", path, storagedriver.PathRegexp)
|
||||||
|
@ -269,6 +272,9 @@ func TestEmptyRootList(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
keys, err = slashRootDriver.List(ctx, "/")
|
keys, err = slashRootDriver.List(ctx, "/")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error listing slash root content: %v", err)
|
||||||
|
}
|
||||||
for _, path := range keys {
|
for _, path := range keys {
|
||||||
if !storagedriver.PathRegexp.MatchString(path) {
|
if !storagedriver.PathRegexp.MatchString(path) {
|
||||||
t.Fatalf("unexpected string in path: %q != %q", path, storagedriver.PathRegexp)
|
t.Fatalf("unexpected string in path: %q != %q", path, storagedriver.PathRegexp)
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
//go:build include_oss
|
||||||
|
// +build include_oss
|
||||||
|
|
||||||
// Package oss provides a storagedriver.StorageDriver implementation to
|
// Package oss provides a storagedriver.StorageDriver implementation to
|
||||||
// store blobs in Aliyun OSS cloud storage.
|
// store blobs in Aliyun OSS cloud storage.
|
||||||
//
|
//
|
||||||
|
@ -6,10 +9,6 @@
|
||||||
//
|
//
|
||||||
// Because OSS is a key, value store the Stat call does not support last modification
|
// Because OSS is a key, value store the Stat call does not support last modification
|
||||||
// time for directories (directories are an abstraction for key, value stores)
|
// time for directories (directories are an abstraction for key, value stores)
|
||||||
//
|
|
||||||
//go:build include_oss
|
|
||||||
// +build include_oss
|
|
||||||
|
|
||||||
package oss
|
package oss
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -70,6 +69,8 @@ func (factory *ossDriverFactory) Create(parameters map[string]interface{}) (stor
|
||||||
return FromParameters(parameters)
|
return FromParameters(parameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ storagedriver.StorageDriver = &driver{}
|
||||||
|
|
||||||
type driver struct {
|
type driver struct {
|
||||||
Client *oss.Client
|
Client *oss.Client
|
||||||
Bucket *oss.Bucket
|
Bucket *oss.Bucket
|
||||||
|
@ -507,11 +508,6 @@ func parseError(path string, err error) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasCode(err error, code string) bool {
|
|
||||||
ossErr, ok := err.(*oss.Error)
|
|
||||||
return ok && ossErr.Code == code
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *driver) getOptions() oss.Options {
|
func (d *driver) getOptions() oss.Options {
|
||||||
return oss.Options{
|
return oss.Options{
|
||||||
ServerSideEncryption: d.Encrypt,
|
ServerSideEncryption: d.Encrypt,
|
||||||
|
|
|
@ -128,6 +128,9 @@ func TestEmptyRootList(t *testing.T) {
|
||||||
defer rootedDriver.Delete(ctx, filename)
|
defer rootedDriver.Delete(ctx, filename)
|
||||||
|
|
||||||
keys, err := emptyRootDriver.List(ctx, "/")
|
keys, err := emptyRootDriver.List(ctx, "/")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error listing empty root content: %v", err)
|
||||||
|
}
|
||||||
for _, path := range keys {
|
for _, path := range keys {
|
||||||
if !storagedriver.PathRegexp.MatchString(path) {
|
if !storagedriver.PathRegexp.MatchString(path) {
|
||||||
t.Fatalf("unexpected string in path: %q != %q", path, storagedriver.PathRegexp)
|
t.Fatalf("unexpected string in path: %q != %q", path, storagedriver.PathRegexp)
|
||||||
|
@ -135,6 +138,9 @@ func TestEmptyRootList(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
keys, err = slashRootDriver.List(ctx, "/")
|
keys, err = slashRootDriver.List(ctx, "/")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error listing slash root content: %v", err)
|
||||||
|
}
|
||||||
for _, path := range keys {
|
for _, path := range keys {
|
||||||
if !storagedriver.PathRegexp.MatchString(path) {
|
if !storagedriver.PathRegexp.MatchString(path) {
|
||||||
t.Fatalf("unexpected string in path: %q != %q", path, storagedriver.PathRegexp)
|
t.Fatalf("unexpected string in path: %q != %q", path, storagedriver.PathRegexp)
|
||||||
|
|
Loading…
Reference in a new issue