diff --git a/.travis.yml b/.travis.yml index c656d9d1..a13e1376 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,11 +3,11 @@ dist: trusty language: go go: - - 1.9.x + - 1.12.x script: - export TAG=${TRAVIS_BRANCH} - - make check all-ci container && + - make all check container && if [ "${TRAVIS_BRANCH}" == "master" ] && [ "${TRAVIS_PULL_REQUEST}" == "false" ]; then docker login -u "${DOCKER_USER}" -p "${DOCKER_PASSWORD}"; make deploy; diff --git a/Dockerfile b/Dockerfile index 352ebf32..327bd1c3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,8 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM alpine:3.6 +FROM debian:stretch-slim RUN mkdir /plugins -ADD ark-* /plugins/ +ADD velero-* /plugins/ USER nobody:nobody -ENTRYPOINT ["/bin/ash", "-c", "cp -a /plugins/* /target/."] +ENTRYPOINT ["/bin/bash", "-c", "cp -a /plugins/* /target/."] diff --git a/Makefile b/Makefile index 856d53eb..c4b6c184 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -# Copyright 2018 Portworx. -# Copyright 2017 the Heptio Ark contributors. +# Copyright 2018-2019 Portworx. +# Copyright 2017, 2019 the Velero contributors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,76 +13,114 @@ # See the License for the specific language governing permissions and # limitations under the License. -BINS = $(wildcard ark-*) +# The binary to build (just the basename). +BIN ?= $(wildcard velero-*) -REPO ?= github.com/portworx/ark-plugin +# This repo's root import path (under GOPATH). +PKG := github.com/portworx/ark-plugin -BUILD_IMAGE ?= gcr.io/heptio-images/golang:1.9-alpine3.6 +BUILD_IMAGE ?= golang:1.12-stretch -IMAGE ?= portworx/ark-plugin +IMAGE ?= portworx/velero-plugin TAG ?= latest -ARCH ?= amd64 +# Which architecture to build - see $(ALL_ARCH) for options. +# if the 'local' rule is being run, detect the ARCH from 'go env' +# if it wasn't specified by the caller. +local : ARCH ?= $(shell go env GOOS)-$(shell go env GOARCH) +ARCH ?= linux-amd64 + +platform_temp = $(subst -, ,$(ARCH)) +GOOS = $(word 1, $(platform_temp)) +GOARCH = $(word 2, $(platform_temp)) ifndef PKGS PKGS := $(shell go list ./... 2>&1 | grep -v 'github.com/portworx/ark-plugin/vendor') endif -all: $(addprefix build-, $(BINS)) +all: $(addprefix build-, $(BIN)) build-%: $(MAKE) --no-print-directory BIN=$* build -build: _output/$(BIN) - -_output/$(BIN): $(BIN)/*.go - mkdir -p .go/src/$(REPO) .go/pkg .go/std/$(ARCH) _output - docker run \ - --rm \ - -u $$(id -u):$$(id -g) \ - -v $$(pwd)/.go/pkg:/go/pkg \ - -v $$(pwd)/.go/src:/go/src \ - -v $$(pwd)/.go/std:/go/std \ - -v $$(pwd):/go/src/$(REPO) \ - -v $$(pwd)/.go/std/$(ARCH):/usr/local/go/pkg/linux_$(ARCH)_static \ - -e CGO_ENABLED=0 \ - -w /go/src/$(REPO) \ - $(BUILD_IMAGE) \ - go build -installsuffix "static" -i -v -o _output/$(BIN) ./$(BIN) - -lint: - go get -v github.com/golang/lint/golint - for file in $$(find . -name '*.go' | grep -v vendor | grep -v '\.pb\.go' | grep -v '\.pb\.gw\.go'); do \ - golint $${file}; \ - if [ -n "$$(golint $${file})" ]; then \ - exit 1; \ - fi; \ - done - -vet: - go vet $(PKGS) - -errcheck: - go get -v github.com/kisielk/errcheck - errcheck -verbose -blank $(PKGS) - -check: lint errcheck vet +local: build-dirs + GOOS=$(GOOS) \ + GOARCH=$(GOARCH) \ + PKG=$(PKG) \ + BIN=$(BIN) \ + OUTPUT_DIR=$$(pwd)/_output/bin/$(GOOS)/$(GOARCH) \ + ./hack/build.sh + +build: _output/bin/$(GOOS)/$(GOARCH)/$(BIN) + +_output/bin/$(GOOS)/$(GOARCH)/$(BIN): build-dirs + @echo "building: $@" + $(MAKE) shell CMD="-c '\ + GOOS=$(GOOS) \ + GOARCH=$(GOARCH) \ + PKG=$(PKG) \ + BIN=$(BIN) \ + OUTPUT_DIR=/output/$(GOOS)/$(GOARCH) \ + ./hack/build.sh'" + +TTY := $(shell tty -s && echo "-t") + +shell: build-dirs + @echo "running docker: $@" + @docker run \ + -e GOFLAGS \ + -i $(TTY) \ + --rm \ + -u $$(id -u):$$(id -g) \ + -v $$(pwd)/.go/pkg:/go/pkg \ + -v $$(pwd)/.go/src:/go/src \ + -v $$(pwd)/.go/std:/go/std \ + -v $$(pwd):/go/src/$(PKG) \ + -v $$(pwd)/.go/std/$(GOOS)/$(GOARCH):/usr/local/go/pkg/$(GOOS)_$(GOARCH)_static:delegated \ + -v "$$(pwd)/.go/go-build:/.cache/go-build:delegated" \ + -e CGO_ENABLED=0 \ + -w /go/src/$(PKG) \ + $(BUILD_IMAGE) \ + go build -installsuffix "static" -i -v -o _output/bin/$(GOOS)/$(GOARCH)/$(BIN) ./$(BIN) + +build-dirs: + @mkdir -p _output/bin/$(GOOS)/$(GOARCH) + @mkdir -p .go/src/$(PKG) .go/pkg .go/bin .go/std/$(GOOS)/$(GOARCH) .go/go-build container: all - cp Dockerfile _output/Dockerfile - docker build -t $(IMAGE):$(TAG) -f _output/Dockerfile _output + cp Dockerfile _output/bin/$(GOOS)/$(GOARCH)/Dockerfile + docker build --no-cache -t $(IMAGE):$(TAG) -f _output/bin/$(GOOS)/$(GOARCH)/Dockerfile _output/bin/$(GOOS)/$(GOARCH) deploy: docker push $(IMAGE):$(TAG) -all-ci: $(addprefix ci-, $(BINS)) +all-ci: $(addprefix ci-, $(BIN)) ci-%: $(MAKE) --no-print-directory BIN=$* ci ci: mkdir -p _output - CGO_ENABLED=0 go build -v -o _output/$(BIN) ./$(BIN) + CGO_ENABLED=0 go build -v -o _output/bin/$(GOOS)/$(GOARCH)/$(BIN) ./$(BIN) clean: + @echo "cleaning" rm -rf .go _output + +lint: + go get -u golang.org/x/lint/golint + for file in $$(find . -name '*.go' | grep -v vendor | grep -v '\.pb\.go' | grep -v '\.pb\.gw\.go'); do \ + golint $${file}; \ + if [ -n "$$(golint $${file})" ]; then \ + exit 1; \ + fi; \ + done + +vet: + go vet $(PKGS) + +errcheck: + go get -v -u github.com/kisielk/errcheck + errcheck -verbose -blank $(PKGS) + +check: lint errcheck vet diff --git a/README.md b/README.md index 49c31458..529e994b 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Go Report Card](https://goreportcard.com/badge/github.com/portworx/ark-plugin)](https://goreportcard.com/report/portworx/ark-plugin) -# ark-plugin -Portworx plugin for Heptio Ark +# velero-plugin +Portworx plugin for Heptio Velero (formerly known as Ark) Instructions to deploy and use can be found here: https://docs.portworx.com/scheduler/kubernetes/ark.html diff --git a/pkg/snapshot/cloudsnap.go b/pkg/snapshot/cloudsnap.go index 088db580..20cf53fe 100644 --- a/pkg/snapshot/cloudsnap.go +++ b/pkg/snapshot/cloudsnap.go @@ -104,7 +104,7 @@ func (c *cloudSnapshotPlugin) CreateSnapshot(volumeID, volumeAZ string, tags map return "", err } statusResponse, err := volDriver.CloudBackupStatus(&api.CloudBackupStatusRequest{ - Name: createResp.Name, + ID: createResp.Name, }) if err != nil { return "", err diff --git a/pkg/snapshot/localsnap.go b/pkg/snapshot/localsnap.go index 7b2d000c..3a9dc260 100644 --- a/pkg/snapshot/localsnap.go +++ b/pkg/snapshot/localsnap.go @@ -2,6 +2,7 @@ package snapshot import ( "fmt" + "strings" "github.com/libopenstorage/openstorage/api" "github.com/sirupsen/logrus" @@ -59,8 +60,9 @@ func (l *localSnapshotPlugin) CreateSnapshot(volumeID, volumeAZ string, tags map } tags["pvName"] = vols[0].Locator.Name + l.log.Infof("Tags: %v", tags) locator := &api.VolumeLocator{ - Name: tags["ark.heptio.com/backup"] + "_" + vols[0].Locator.Name, + Name: strings.TrimSpace(tags["velero.io/backup"]) + "_" + vols[0].Locator.Name, VolumeLabels: tags, } snapshotID, err := volDriver.Snapshot(volumeID, true, locator, true) diff --git a/pkg/snapshot/plugin.go b/pkg/snapshot/plugin.go index fb5c2522..8d49bf1c 100644 --- a/pkg/snapshot/plugin.go +++ b/pkg/snapshot/plugin.go @@ -3,12 +3,14 @@ package snapshot import ( "fmt" - "github.com/heptio/ark/pkg/cloudprovider" - "github.com/heptio/ark/pkg/util/collections" + "github.com/heptio/velero/pkg/plugin/velero" volumeclient "github.com/libopenstorage/openstorage/api/client/volume" "github.com/libopenstorage/openstorage/volume" + "github.com/pkg/errors" "github.com/portworx/sched-ops/k8s" "github.com/sirupsen/logrus" + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" ) @@ -51,7 +53,7 @@ func getVolumeDriver() (volume.VolumeDriver, error) { // Plugin for managing Portworx snapshots type Plugin struct { Log logrus.FieldLogger - plugin cloudprovider.BlockStore + plugin velero.VolumeSnapshotter } // Init the plugin @@ -91,22 +93,40 @@ func (p *Plugin) DeleteSnapshot(snapshotID string) error { } // GetVolumeID Get the volume ID from the spec -func (p *Plugin) GetVolumeID(pv runtime.Unstructured) (string, error) { - if !collections.Exists(pv.UnstructuredContent(), "spec.portworxVolume") { +func (p *Plugin) GetVolumeID(unstructuredPV runtime.Unstructured) (string, error) { + pv := new(v1.PersistentVolume) + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredPV.UnstructuredContent(), pv); err != nil { + return "", errors.WithStack(err) + } + + if pv.Spec.PortworxVolume == nil { return "", nil } - return collections.GetString(pv.UnstructuredContent(), "spec.portworxVolume.volumeID") + if pv.Spec.PortworxVolume.VolumeID == "" { + return "", errors.New("spec.portworxVolume.volumeID") + } + + return pv.Spec.PortworxVolume.VolumeID, nil } // SetVolumeID Set the volume ID in the spec -func (p *Plugin) SetVolumeID(pv runtime.Unstructured, volumeID string) (runtime.Unstructured, error) { - pwx, err := collections.GetMap(pv.UnstructuredContent(), "spec.portworxVolume") - if err != nil { - return nil, err +func (p *Plugin) SetVolumeID(unstructuredPV runtime.Unstructured, volumeID string) (runtime.Unstructured, error) { + pv := new(v1.PersistentVolume) + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredPV.UnstructuredContent(), pv); err != nil { + return nil, errors.WithStack(err) } - pwx["volumeID"] = volumeID + if pv.Spec.PortworxVolume == nil { + return nil, errors.New("spec.portworxVolume not found") + } + + pv.Spec.PortworxVolume.VolumeID = volumeID + + res, err := runtime.DefaultUnstructuredConverter.ToUnstructured(pv) + if err != nil { + return nil, errors.WithStack(err) + } - return pv, nil + return &unstructured.Unstructured{Object: res}, nil } diff --git a/ark-blockstore-portworx/main.go b/velero-blockstore-portworx/main.go similarity index 60% rename from ark-blockstore-portworx/main.go rename to velero-blockstore-portworx/main.go index 81aa4198..dd6a93fa 100644 --- a/ark-blockstore-portworx/main.go +++ b/velero-blockstore-portworx/main.go @@ -1,14 +1,14 @@ package main import ( - "github.com/heptio/ark/pkg/plugin" + veleroplugin "github.com/heptio/velero/pkg/plugin/framework" "github.com/portworx/ark-plugin/pkg/snapshot" "github.com/sirupsen/logrus" ) func main() { - plugin.NewServer(plugin.NewLogger()). - RegisterBlockStore("portworx", newSnapshotPlugin). + veleroplugin.NewServer(). + RegisterVolumeSnapshotter("velero.io/portworx", newSnapshotPlugin). Serve() }