mirror of https://github.com/knative/func.git
src!: revert bump to go 1.16 and template changes (#340)
* Revert "src: rename boson import 'fn'" This reverts commitc0a6f561c0
. * Revert "src: all test dirs set to 0700" This reverts commit99f01220c2
. * Revert "src: better error when custom template not found" This reverts commit6673395834
. * Revert "src: better errors when custom runtime not found" This reverts commita31a6f67a1
. * Revert "build: create separate target for templates.tgz" This reverts commit11164bf8d9
. * Revert "src: use consistent separators for fs.FS instances" This reverts commit4db07b412f
. * Revert "src: update go event template dependencies" This reverts commit3bfc13380f
. * Revert "src: tarfs assumes forward slashes internally" This reverts commit6cc0e67b1c
. * Revert "feat: support windows paths in embedded templates FS" This reverts commitc2b216857b
. * Revert "feat: positive error when runtimme or template unrecognized" This reverts commitacc56b0900
. * Revert "fix: lint issues" This reverts commit895872aee7
. * Revert "ci: go 1.16 compatiblity updates" This reverts commit1e3959c045
. * Revert "feat: preserve file modes using in-memory tar FS" This reverts commit7dc772ec62
. * Revert "feat: create templates archive on go generate" This reverts commit63b7f11471
. * Revert "ci: remove pkger from ci" This reverts commit876b0dd0f7
. * Revert "src: remove pkger dependency and tidy" This reverts commitf006ab1e32
. * Revert "src: remove packaging artifact" This reverts commit4d9d0a7b4e
. * Revert "src: remove pkger from make targets" This reverts commite44c1ad74c
. * Revert "src: replace pkger with embed.FS" This reverts commit38874a4afd
. * Revert "src: update references to deprecated ioutil" This reverts commit4025460f73
. * Revert "src: require go 1.16" This reverts commit512d4c2580
. * chore: update pkged.go Signed-off-by: Lance Ball <lball@redhat.com>
This commit is contained in:
parent
c5d31c5691
commit
2b025df199
|
@ -10,22 +10,38 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-go@v2
|
||||
- name: Determine download URL for pkger
|
||||
id: pkger-download-url
|
||||
uses: actions/github-script@v2
|
||||
with:
|
||||
go-version: '^1.16'
|
||||
result-encoding: string
|
||||
script: |
|
||||
return github.repos.getReleaseByTag({
|
||||
owner: "markbates",
|
||||
repo: "pkger",
|
||||
tag: "v0.17.1"
|
||||
}).then(result => {
|
||||
return result.data.assets
|
||||
.filter(a => a.name.includes('Linux_x86'))
|
||||
.map(a => a.browser_download_url)[0];
|
||||
})
|
||||
- name: Install pkger
|
||||
run: |
|
||||
curl -s -L -o pkger.tgz ${{ steps.pkger-download-url.outputs.result }}
|
||||
tar xvzf pkger.tgz
|
||||
- name: Test
|
||||
run: make test
|
||||
env:
|
||||
PKGER: "./${{ steps.pkger-binaries.outputs.binary }}"
|
||||
- name: Lint
|
||||
run: make check
|
||||
outputs:
|
||||
pkger: ${{ steps.pkger-download-url.outputs.result }}
|
||||
|
||||
build-and-publish:
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '^1.16'
|
||||
# Release
|
||||
# Create a release, or update the release PR
|
||||
- uses: GoogleCloudPlatform/release-please-action@v2.24.1
|
||||
id: release
|
||||
|
@ -33,6 +49,8 @@ jobs:
|
|||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
release-type: simple
|
||||
bump-minor-pre-major: true
|
||||
# Checkout
|
||||
- uses: actions/checkout@v2
|
||||
# Tag
|
||||
# If a release was created, tag `vX.Y.Z` synchronously which:
|
||||
# 1. Triggers release-please to create draft release, allowing manual
|
||||
|
@ -52,23 +70,28 @@ jobs:
|
|||
git push origin :v${{steps.release.outputs.major}}.${{steps.release.outputs.minor}}.${{steps.release.outputs.patch}} || true
|
||||
git tag -a v${{steps.release.outputs.major}}.${{steps.release.outputs.minor}}.${{steps.release.outputs.patch}} -m "Release v${{steps.release.outputs.major}}.${{steps.release.outputs.minor}}.${{steps.release.outputs.patch}}"
|
||||
git push origin v${{steps.release.outputs.major}}.${{steps.release.outputs.minor}}.${{steps.release.outputs.patch}} || true
|
||||
# Build
|
||||
|
||||
- uses: actions/setup-go@v2
|
||||
- name: Install pkger
|
||||
run: |
|
||||
curl -s -L -o pkger.tgz ${{ needs.test.outputs.pkger }}
|
||||
tar xvzf pkger.tgz
|
||||
|
||||
# Standard build tasks
|
||||
- name: Build
|
||||
run: make cross-platform
|
||||
# NOTE:
|
||||
# release-please adds the version asynchronously. Without using the
|
||||
# synchonous tagging step above, the version can be explicitly passed
|
||||
# to the build using the following environment variable. However this
|
||||
# has the side-effect of causing inter-relese binaries to not include
|
||||
# verbose version information, because the special version `tip` is
|
||||
# overriden with a blank string in those cases.
|
||||
# env:
|
||||
# VERS: ${{ steps.release.outputs.tag_name }}
|
||||
env:
|
||||
PKGER: "./pkger"
|
||||
# NOTE:
|
||||
# release-please adds the version asynchronously. Without using the
|
||||
# synchonous tagging step above, the version can be explicitly passed
|
||||
# to the build using the following environment variable. However this
|
||||
# has the side-effect of causing inter-relese binaries to not include
|
||||
# verbose version information, because the special version `tip` is
|
||||
# overriden with a blank string in those cases.
|
||||
# VERS: ${{ steps.release.outputs.tag_name }}
|
||||
|
||||
# Upload
|
||||
# All build artifacts are uploaded whether release or not
|
||||
# Non-release binaries have a verbose version `tip-[git hash]-[build timestamp]`
|
||||
# Upload all build artifacts whether it's a release or not
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: OSX Binary
|
||||
|
|
|
@ -12,12 +12,61 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-go@v2
|
||||
- name: Determine platform binaries
|
||||
id: pkger-binaries
|
||||
uses: actions/github-script@v2
|
||||
with:
|
||||
go-version: '^1.16'
|
||||
result-encoding: string
|
||||
script: |
|
||||
let platform, binary;
|
||||
switch ('${{matrix.os}}') {
|
||||
case 'ubuntu-latest':
|
||||
platform = 'Linux_x86'
|
||||
binary = 'pkger'
|
||||
break
|
||||
case 'windows-latest':
|
||||
platform = 'Windows_x86'
|
||||
binary = 'pkger.exe'
|
||||
break
|
||||
case 'macos-latest':
|
||||
platform = 'Darwin_x86'
|
||||
binary = 'pkger'
|
||||
break
|
||||
}
|
||||
core.setOutput('platform', platform)
|
||||
core.setOutput('binary', binary)
|
||||
- name: Determine download URL for latest pkger
|
||||
id: pkger-download-url
|
||||
uses: actions/github-script@v2
|
||||
with:
|
||||
result-encoding: string
|
||||
script: |
|
||||
let platform = "${{ steps.pkger-binaries.outputs.platform }}"
|
||||
let binary = "${{ steps.pkger-binaries.outputs.binary }}"
|
||||
core.info('PLATFORM: ' + platform)
|
||||
core.info('BINARY: ' + binary)
|
||||
return github.repos.getReleaseByTag({
|
||||
owner: "markbates",
|
||||
repo: "pkger",
|
||||
tag: "v0.17.1"
|
||||
}).then(result => {
|
||||
return result.data.assets
|
||||
.filter(a => a.name.includes(platform))
|
||||
.map(a => a.browser_download_url)[0];
|
||||
})
|
||||
- name: Install pkger
|
||||
run: |
|
||||
curl -s -L -o pkger.tgz ${{ steps.pkger-download-url.outputs.result }}
|
||||
tar xvzf pkger.tgz
|
||||
|
||||
- name: Test
|
||||
run: make test
|
||||
env:
|
||||
PKGER: "./${{ steps.pkger-binaries.outputs.binary }}"
|
||||
- name: Build
|
||||
run: make build
|
||||
env:
|
||||
PKGER: "./${{ steps.pkger-binaries.outputs.binary }}"
|
||||
- name: Lint
|
||||
run: make check
|
||||
|
||||
|
@ -28,8 +77,6 @@ jobs:
|
|||
uses: actions/checkout@v2
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '^1.16'
|
||||
- name: Provision Cluster
|
||||
uses: lkingland/kind-action@v1 # use ./hack/allocate.sh locally
|
||||
with:
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/func
|
||||
/func_*
|
||||
/templates.tgz
|
||||
/templates/go/events/go.sum
|
||||
/templates/go/http/go.sum
|
||||
/coverage.out
|
||||
/bin
|
||||
|
||||
|
|
47
Makefile
47
Makefile
|
@ -1,9 +1,11 @@
|
|||
REPO := quay.io/boson/func
|
||||
BIN := func
|
||||
|
||||
BIN := func
|
||||
DARWIN :=$(BIN)_darwin_amd64
|
||||
LINUX :=$(BIN)_linux_amd64
|
||||
WINDOWS :=$(BIN)_windows_amd64.exe
|
||||
PKGER?=pkger
|
||||
|
||||
DARWIN=$(BIN)_darwin_amd64
|
||||
LINUX=$(BIN)_linux_amd64
|
||||
WINDOWS=$(BIN)_windows_amd64.exe
|
||||
|
||||
CODE := $(shell find . -name '*.go')
|
||||
DATE := $(shell date -u +"%Y%m%dT%H%M%SZ")
|
||||
|
@ -14,21 +16,23 @@ VTAG := $(shell git tag --points-at HEAD)
|
|||
# unless explicitly, synchronously tagging as is done in ci.yaml
|
||||
VERS ?= $(shell [ -z $(VTAG) ] && echo 'tip' || echo $(VTAG) )
|
||||
|
||||
LDFLAGS := -X main.date=$(DATE) -X main.vers=$(VERS) -X main.hash=$(HASH)
|
||||
TEMPLATE_DIRS=$(shell find templates -type d)
|
||||
TEMPLATE_FILES=$(shell find templates -type f -name '*')
|
||||
TEMPLATE_PACKAGE=pkged.go
|
||||
|
||||
build: all
|
||||
all: $(BIN)
|
||||
all: $(TEMPLATE_PACKAGE) $(BIN)
|
||||
|
||||
templates.tgz:
|
||||
# ensure no cached dependencies are added to the binary
|
||||
$(TEMPLATE_PACKAGE): templates $(TEMPLATE_DIRS) $(TEMPLATE_FILES)
|
||||
# ensure no cached dependencies are added to the binary
|
||||
rm -rf templates/node/events/node_modules
|
||||
rm -rf templates/node/http/node_modules
|
||||
rm -rf templates/python/events/__pycache__
|
||||
rm -rf templates/python/http/__pycache__
|
||||
# see generate.go for details
|
||||
go generate
|
||||
# to install pkger: go get github.com/markbates/pkger/cmd/pkger
|
||||
$(PKGER)
|
||||
|
||||
cross-platform: $(DARWIN) $(LINUX) $(WINDOWS)
|
||||
cross-platform: $(TEMPLATE_PACKAGE) $(DARWIN) $(LINUX) $(WINDOWS)
|
||||
|
||||
darwin: $(DARWIN) ## Build for Darwin (macOS)
|
||||
|
||||
|
@ -36,21 +40,21 @@ linux: $(LINUX) ## Build for Linux
|
|||
|
||||
windows: $(WINDOWS) ## Build for Windows
|
||||
|
||||
$(BIN): templates.tgz $(CODE) ## Build using environment defaults
|
||||
env CGO_ENABLED=0 go build -ldflags "$(LDFLAGS)" ./cmd/$(BIN)
|
||||
$(BIN): $(CODE) ## Build using environment defaults
|
||||
env CGO_ENABLED=0 go build -ldflags "-X main.date=$(DATE) -X main.vers=$(VERS) -X main.hash=$(HASH)" ./cmd/$(BIN)
|
||||
|
||||
$(DARWIN): templates.tgz
|
||||
env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o $(DARWIN) -ldflags "$(LDFLAGS)" ./cmd/$(BIN)
|
||||
$(DARWIN):
|
||||
env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o $(DARWIN) -ldflags "-X main.date=$(DATE) -X main.vers=$(VERS) -X main.hash=$(HASH)" ./cmd/$(BIN)
|
||||
|
||||
$(LINUX): templates.tgz
|
||||
env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $(LINUX) -ldflags "$(LDFLAGS)" ./cmd/$(BIN)
|
||||
$(LINUX):
|
||||
env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $(LINUX) -ldflags "-X main.date=$(DATE) -X main.vers=$(VERS) -X main.hash=$(HASH)" ./cmd/$(BIN)
|
||||
|
||||
$(WINDOWS): templates.tgz
|
||||
env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o $(WINDOWS) -ldflags "$(LDFLAGS)" ./cmd/$(BIN)
|
||||
$(WINDOWS):
|
||||
env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o $(WINDOWS) -ldflags "-X main.date=$(DATE) -X main.vers=$(VERS) -X main.hash=$(HASH)" ./cmd/$(BIN)
|
||||
|
||||
test: test-binary test-node test-python test-quarkus test-go
|
||||
|
||||
test-binary: templates.tgz
|
||||
test-binary:
|
||||
go test -race -cover -coverprofile=coverage.out ./...
|
||||
|
||||
test-node:
|
||||
|
@ -69,7 +73,7 @@ test-go:
|
|||
cd templates/go/events && go test
|
||||
cd templates/go/http && go test
|
||||
|
||||
test-integration: templates.tgz
|
||||
test-integration:
|
||||
go test -tags integration ./...
|
||||
|
||||
bin/golangci-lint:
|
||||
|
@ -91,5 +95,4 @@ cluster: ## Set up a local cluster for integraiton tests.
|
|||
|
||||
clean:
|
||||
rm -f $(BIN) $(WINDOWS) $(LINUX) $(DARWIN)
|
||||
rm -f templates.tgz
|
||||
-rm -f coverage.out
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
"github.com/buildpacks/pack"
|
||||
"github.com/buildpacks/pack/logging"
|
||||
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
)
|
||||
|
||||
//Builder holds the configuration that will be passed to
|
||||
|
@ -37,7 +37,7 @@ var RuntimeToBuildpack = map[string]string{
|
|||
}
|
||||
|
||||
// Build the Function at path.
|
||||
func (builder *Builder) Build(ctx context.Context, f fn.Function) (err error) {
|
||||
func (builder *Builder) Build(ctx context.Context, f bosonFunc.Function) (err error) {
|
||||
|
||||
// Use the builder found in the Function configuration file
|
||||
// If one isn't found, use the defaults
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
|
@ -339,14 +340,14 @@ func (c *Client) Create(cfg Function) (err error) {
|
|||
}
|
||||
|
||||
// Write out a template.
|
||||
w := templateWriter{repositories: c.templates, verbose: c.verbose}
|
||||
w := templateWriter{templates: c.templates, verbose: c.verbose}
|
||||
if err = w.Write(f.Runtime, f.Trigger, f.Root); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if template specifies a builder image. If so, add to configuration
|
||||
builderFilePath := filepath.Join(f.Root, ".builders.yaml")
|
||||
if builderConfig, err := os.ReadFile(builderFilePath); err == nil {
|
||||
if builderConfig, err := ioutil.ReadFile(builderFilePath); err == nil {
|
||||
// A .builder file was found. Read the default builder and set in the config file
|
||||
// TODO: A command line flag could be used to specify non-default builders
|
||||
builders := make(map[string]string)
|
||||
|
|
249
client_test.go
249
client_test.go
|
@ -6,11 +6,12 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
"github.com/boson-project/func/mock"
|
||||
)
|
||||
|
||||
|
@ -31,10 +32,10 @@ func TestNew(t *testing.T) {
|
|||
defer os.RemoveAll(root)
|
||||
|
||||
// New Client
|
||||
client := fn.New(fn.WithRegistry(TestRegistry))
|
||||
client := bosonFunc.New(bosonFunc.WithRegistry(TestRegistry))
|
||||
|
||||
// New Function using Client
|
||||
if err := client.New(context.Background(), fn.Function{Root: root}); err != nil {
|
||||
if err := client.New(context.Background(), bosonFunc.Function{Root: root}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
@ -42,19 +43,19 @@ func TestNew(t *testing.T) {
|
|||
// TestTemplateWrites ensures a template is written.
|
||||
func TestTemplateWrites(t *testing.T) {
|
||||
root := "testdata/example.com/testCreateWrites"
|
||||
if err := os.MkdirAll(root, 0700); err != nil {
|
||||
if err := os.MkdirAll(root, 0744); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(root)
|
||||
|
||||
client := fn.New(fn.WithRegistry(TestRegistry))
|
||||
if err := client.Create(fn.Function{Root: root}); err != nil {
|
||||
client := bosonFunc.New(bosonFunc.WithRegistry(TestRegistry))
|
||||
if err := client.Create(bosonFunc.Function{Root: root}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Assert file was written
|
||||
if _, err := os.Stat(filepath.Join(root, fn.ConfigFile)); os.IsNotExist(err) {
|
||||
t.Fatalf("Initialize did not result in '%v' being written to '%v'", fn.ConfigFile, root)
|
||||
if _, err := os.Stat(filepath.Join(root, bosonFunc.ConfigFile)); os.IsNotExist(err) {
|
||||
t.Fatalf("Initialize did not result in '%v' being written to '%v'", bosonFunc.ConfigFile, root)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,19 +63,19 @@ func TestTemplateWrites(t *testing.T) {
|
|||
// Function does not reinitialize
|
||||
func TestExtantAborts(t *testing.T) {
|
||||
root := "testdata/example.com/testCreateInitializedAborts"
|
||||
if err := os.MkdirAll(root, 0700); err != nil {
|
||||
if err := os.MkdirAll(root, 0744); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(root)
|
||||
|
||||
// New once
|
||||
client := fn.New(fn.WithRegistry(TestRegistry))
|
||||
if err := client.New(context.Background(), fn.Function{Root: root}); err != nil {
|
||||
client := bosonFunc.New(bosonFunc.WithRegistry(TestRegistry))
|
||||
if err := client.New(context.Background(), bosonFunc.Function{Root: root}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// New again should fail as already initialized
|
||||
if err := client.New(context.Background(), fn.Function{Root: root}); err == nil {
|
||||
if err := client.New(context.Background(), bosonFunc.Function{Root: root}); err == nil {
|
||||
t.Fatal("error expected initilizing a path already containing an initialized Function")
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +84,7 @@ func TestExtantAborts(t *testing.T) {
|
|||
// visible files aborts.
|
||||
func TestNonemptyDirectoryAborts(t *testing.T) {
|
||||
root := "testdata/example.com/testCreateNonemptyDirectoryAborts" // contains only a single visible file.
|
||||
if err := os.MkdirAll(root, 0700); err != nil {
|
||||
if err := os.MkdirAll(root, 0744); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(root)
|
||||
|
@ -94,8 +95,8 @@ func TestNonemptyDirectoryAborts(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
client := fn.New(fn.WithRegistry(TestRegistry))
|
||||
if err := client.New(context.Background(), fn.Function{Root: root}); err == nil {
|
||||
client := bosonFunc.New(bosonFunc.WithRegistry(TestRegistry))
|
||||
if err := client.New(context.Background(), bosonFunc.Function{Root: root}); err == nil {
|
||||
t.Fatal("error expected initilizing a Function in a nonempty directory")
|
||||
}
|
||||
}
|
||||
|
@ -108,19 +109,19 @@ func TestNonemptyDirectoryAborts(t *testing.T) {
|
|||
func TestHiddenFilesIgnored(t *testing.T) {
|
||||
// Create a directory for the Function
|
||||
root := "testdata/example.com/testCreateHiddenFilesIgnored"
|
||||
if err := os.MkdirAll(root, 0700); err != nil {
|
||||
if err := os.MkdirAll(root, 0744); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(root)
|
||||
|
||||
// Create a hidden file that should be ignored.
|
||||
hiddenFile := filepath.Join(root, ".envrc")
|
||||
if err := os.WriteFile(hiddenFile, []byte{}, 0644); err != nil {
|
||||
if err := ioutil.WriteFile(hiddenFile, []byte{}, 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
client := fn.New(fn.WithRegistry(TestRegistry))
|
||||
if err := client.New(context.Background(), fn.Function{Root: root}); err != nil {
|
||||
client := bosonFunc.New(bosonFunc.WithRegistry(TestRegistry))
|
||||
if err := client.New(context.Background(), bosonFunc.Function{Root: root}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
@ -130,25 +131,25 @@ func TestHiddenFilesIgnored(t *testing.T) {
|
|||
func TestDefaultRuntime(t *testing.T) {
|
||||
// Create a root for the new Function
|
||||
root := "testdata/example.com/testCreateDefaultRuntime"
|
||||
if err := os.MkdirAll(root, 0700); err != nil {
|
||||
if err := os.MkdirAll(root, 0744); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(root)
|
||||
|
||||
// Create a new function at root with all defaults.
|
||||
client := fn.New(fn.WithRegistry(TestRegistry))
|
||||
if err := client.New(context.Background(), fn.Function{Root: root}); err != nil {
|
||||
client := bosonFunc.New(bosonFunc.WithRegistry(TestRegistry))
|
||||
if err := client.New(context.Background(), bosonFunc.Function{Root: root}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Load the function
|
||||
f, err := fn.NewFunction(root)
|
||||
f, err := bosonFunc.NewFunction(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Ensure it has defaulted runtime
|
||||
if f.Runtime != fn.DefaultRuntime {
|
||||
if f.Runtime != bosonFunc.DefaultRuntime {
|
||||
t.Fatal("The default runtime was not applied or persisted.")
|
||||
}
|
||||
}
|
||||
|
@ -172,18 +173,18 @@ func TestDefaultTrigger(t *testing.T) {
|
|||
func TestExtensibleTemplates(t *testing.T) {
|
||||
// Create a directory for the new Function
|
||||
root := "testdata/example.com/testExtensibleTemplates"
|
||||
if err := os.MkdirAll(root, 0700); err != nil {
|
||||
if err := os.MkdirAll(root, 0744); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(root)
|
||||
|
||||
// Create a new client with a path to the extensible templates
|
||||
client := fn.New(
|
||||
fn.WithTemplates("testdata/repositories"),
|
||||
fn.WithRegistry(TestRegistry))
|
||||
client := bosonFunc.New(
|
||||
bosonFunc.WithTemplates("testdata/templates"),
|
||||
bosonFunc.WithRegistry(TestRegistry))
|
||||
|
||||
// Create a Function specifying a template, 'json' that only exists in the extensible set
|
||||
if err := client.New(context.Background(), fn.Function{Root: root, Trigger: "customProvider/json"}); err != nil {
|
||||
if err := client.New(context.Background(), bosonFunc.Function{Root: root, Trigger: "boson-experimental/json"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -195,91 +196,21 @@ func TestExtensibleTemplates(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestRuntimeNotFound generates an error (embedded default repository).
|
||||
func TestRuntimeNotFound(t *testing.T) {
|
||||
// TestUnsupportedRuntime generates an error.
|
||||
func TestUnsupportedRuntime(t *testing.T) {
|
||||
// Create a directory for the Function
|
||||
root := "testdata/example.com/testRuntimeNotFound"
|
||||
root := "testdata/example.com/testUnsupportedRuntime"
|
||||
if err := os.MkdirAll(root, 0700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(root)
|
||||
|
||||
client := fn.New(fn.WithRegistry(TestRegistry))
|
||||
client := bosonFunc.New(bosonFunc.WithRegistry(TestRegistry))
|
||||
|
||||
// creating a Function with an unsupported runtime should bubble
|
||||
// the error generated by the underlying template initializer.
|
||||
f := fn.Function{Root: root, Runtime: "invalid"}
|
||||
err := client.New(context.Background(), f)
|
||||
if !errors.Is(err, fn.ErrRuntimeNotFound) {
|
||||
t.Fatalf("Expected ErrRuntimeNotFound, got %T", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestRuntimeNotFoundCustom ensures that the correct error is returned
|
||||
// when the requested runtime is not found in a given custom repository
|
||||
func TestRuntimeNotFoundCustom(t *testing.T) {
|
||||
root := "testdata/example.com/testRuntimeNotFoundCustom"
|
||||
if err := os.MkdirAll(root, 0700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(root)
|
||||
|
||||
// Create a new client with path to extensible templates
|
||||
client := fn.New(
|
||||
fn.WithTemplates("testdata/repositories"),
|
||||
fn.WithRegistry(TestRegistry))
|
||||
|
||||
// Create a Function specifying a runtime, 'python' that does not exist
|
||||
// in the custom (testdata) repository but does in the embedded.
|
||||
f := fn.Function{Root: root, Runtime: "python", Trigger: "customProvider/event"}
|
||||
|
||||
// creating should error as runtime not found
|
||||
err := client.New(context.Background(), f)
|
||||
if !errors.Is(err, fn.ErrRuntimeNotFound) {
|
||||
t.Fatalf("Expected ErrRuntimeNotFound, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestTemplateNotFound generates an error (embedded default repository).
|
||||
func TestTemplateNotFound(t *testing.T) {
|
||||
root := "testdata/example.com/testTemplateNotFound"
|
||||
if err := os.MkdirAll(root, 0700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(root)
|
||||
|
||||
client := fn.New(fn.WithRegistry(TestRegistry))
|
||||
|
||||
// Creating a function with an invalid template shulid generate the
|
||||
// appropriate error.
|
||||
f := fn.Function{Root: root, Runtime: "go", Trigger: "invalid"}
|
||||
err := client.New(context.Background(), f)
|
||||
if !errors.Is(err, fn.ErrTemplateNotFound) {
|
||||
t.Fatalf("Expected ErrTemplateNotFound, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestTemplateNotFoundCustom ensures that the correct error is returned
|
||||
// when the requested template is not found in the given custom repository.
|
||||
func TestTemplateNotFoundCustom(t *testing.T) {
|
||||
root := "testdata/example.com/testTemplateNotFoundCustom"
|
||||
if err := os.MkdirAll(root, 0700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(root)
|
||||
|
||||
// Create a new client with path to extensible templates
|
||||
client := fn.New(
|
||||
fn.WithTemplates("testdata/repositories"),
|
||||
fn.WithRegistry(TestRegistry))
|
||||
|
||||
// An invalid template, but a valid custom provider
|
||||
f := fn.Function{Root: root, Runtime: "test", Trigger: "customProvider/invalid"}
|
||||
|
||||
// Creation should generate the correct error of template not being found.
|
||||
err := client.New(context.Background(), f)
|
||||
if !errors.Is(err, fn.ErrTemplateNotFound) {
|
||||
t.Fatalf("Expected ErrTemplateNotFound, got %v", err)
|
||||
// create a Function call witn an unsupported runtime should bubble
|
||||
// the error generated by the underlying initializer.
|
||||
if err := client.New(context.Background(), bosonFunc.Function{Root: root, Runtime: "invalid"}); err == nil {
|
||||
t.Fatal("unsupported runtime did not generate error")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -299,13 +230,13 @@ func TestNamed(t *testing.T) {
|
|||
}
|
||||
defer os.RemoveAll(root)
|
||||
|
||||
client := fn.New(fn.WithRegistry(TestRegistry))
|
||||
client := bosonFunc.New(bosonFunc.WithRegistry(TestRegistry))
|
||||
|
||||
if err := client.New(context.Background(), fn.Function{Root: root, Name: name}); err != nil {
|
||||
if err := client.New(context.Background(), bosonFunc.Function{Root: root, Name: name}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
f, err := fn.NewFunction(root)
|
||||
f, err := bosonFunc.NewFunction(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -333,9 +264,9 @@ func TestRegistryRequired(t *testing.T) {
|
|||
}
|
||||
defer os.RemoveAll(root)
|
||||
|
||||
client := fn.New()
|
||||
client := bosonFunc.New()
|
||||
var err error
|
||||
if err = client.New(context.Background(), fn.Function{Root: root}); err == nil {
|
||||
if err = client.New(context.Background(), bosonFunc.Function{Root: root}); err == nil {
|
||||
t.Fatal("did not receive expected error creating a Function without specifying Registry")
|
||||
}
|
||||
fmt.Println(err)
|
||||
|
@ -353,13 +284,13 @@ func TestDeriveImage(t *testing.T) {
|
|||
defer os.RemoveAll(root)
|
||||
|
||||
// Create the function which calculates fields such as name and image.
|
||||
client := fn.New(fn.WithRegistry(TestRegistry))
|
||||
if err := client.New(context.Background(), fn.Function{Root: root}); err != nil {
|
||||
client := bosonFunc.New(bosonFunc.WithRegistry(TestRegistry))
|
||||
if err := client.New(context.Background(), bosonFunc.Function{Root: root}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Load the function with the now-populated fields.
|
||||
f, err := fn.NewFunction(root)
|
||||
f, err := bosonFunc.NewFunction(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -385,18 +316,18 @@ func TestDeriveImageDefaultRegistry(t *testing.T) {
|
|||
// Create the function which calculates fields such as name and image.
|
||||
// Rather than use TestRegistry, use a single-token name and expect
|
||||
// the DefaultRegistry to be prepended.
|
||||
client := fn.New(fn.WithRegistry("alice"))
|
||||
if err := client.New(context.Background(), fn.Function{Root: root}); err != nil {
|
||||
client := bosonFunc.New(bosonFunc.WithRegistry("alice"))
|
||||
if err := client.New(context.Background(), bosonFunc.Function{Root: root}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Load the function with the now-populated fields.
|
||||
f, err := fn.NewFunction(root)
|
||||
f, err := bosonFunc.NewFunction(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Expected image is [DefaultRegistry]/[namespace]/[servicename]:latest
|
||||
expected := fn.DefaultRegistry + "/alice/" + f.Name + ":latest"
|
||||
expected := bosonFunc.DefaultRegistry + "/alice/" + f.Name + ":latest"
|
||||
if f.Image != expected {
|
||||
t.Fatalf("expected image '%v' got '%v'", expected, f.Image)
|
||||
}
|
||||
|
@ -422,11 +353,11 @@ func TestNewDelegates(t *testing.T) {
|
|||
defer os.RemoveAll(root)
|
||||
|
||||
// Create a client with mocks for each of the subcomponents.
|
||||
client := fn.New(
|
||||
fn.WithRegistry(TestRegistry),
|
||||
fn.WithBuilder(builder), // builds an image
|
||||
fn.WithPusher(pusher), // pushes images to a registry
|
||||
fn.WithDeployer(deployer), // deploys images as a running service
|
||||
client := bosonFunc.New(
|
||||
bosonFunc.WithRegistry(TestRegistry),
|
||||
bosonFunc.WithBuilder(builder), // builds an image
|
||||
bosonFunc.WithPusher(pusher), // pushes images to a registry
|
||||
bosonFunc.WithDeployer(deployer), // deploys images as a running service
|
||||
)
|
||||
|
||||
// Register Function delegates on the mocks which validate assertions
|
||||
|
@ -434,7 +365,7 @@ func TestNewDelegates(t *testing.T) {
|
|||
|
||||
// The builder should be invoked with a path to a Function project's source
|
||||
// An example image name is returned.
|
||||
builder.BuildFn = func(f fn.Function) error {
|
||||
builder.BuildFn = func(f bosonFunc.Function) error {
|
||||
expectedPath, err := filepath.Abs(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -445,14 +376,14 @@ func TestNewDelegates(t *testing.T) {
|
|||
return nil
|
||||
}
|
||||
|
||||
pusher.PushFn = func(f fn.Function) (string, error) {
|
||||
pusher.PushFn = func(f bosonFunc.Function) (string, error) {
|
||||
if f.Image != expectedImage {
|
||||
t.Fatalf("pusher expected image '%v', got '%v'", expectedImage, f.Image)
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
deployer.DeployFn = func(f fn.Function) error {
|
||||
deployer.DeployFn = func(f bosonFunc.Function) error {
|
||||
if f.Name != expectedName {
|
||||
t.Fatalf("deployer expected name '%v', got '%v'", expectedName, f.Name)
|
||||
}
|
||||
|
@ -467,7 +398,7 @@ func TestNewDelegates(t *testing.T) {
|
|||
|
||||
// Invoke the creation, triggering the Function delegates, and
|
||||
// perform follow-up assertions that the Functions were indeed invoked.
|
||||
if err := client.New(context.Background(), fn.Function{Root: root}); err != nil {
|
||||
if err := client.New(context.Background(), bosonFunc.Function{Root: root}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -494,8 +425,8 @@ func TestRun(t *testing.T) {
|
|||
|
||||
// Create a client with the mock runner and the new test Function
|
||||
runner := mock.NewRunner()
|
||||
client := fn.New(fn.WithRegistry(TestRegistry), fn.WithRunner(runner))
|
||||
if err := client.New(context.Background(), fn.Function{Root: root}); err != nil {
|
||||
client := bosonFunc.New(bosonFunc.WithRegistry(TestRegistry), bosonFunc.WithRunner(runner))
|
||||
if err := client.New(context.Background(), bosonFunc.Function{Root: root}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -536,19 +467,19 @@ func TestUpdate(t *testing.T) {
|
|||
defer os.RemoveAll(root)
|
||||
|
||||
// A client with mocks whose implementaton will validate input.
|
||||
client := fn.New(
|
||||
fn.WithRegistry(TestRegistry),
|
||||
fn.WithBuilder(builder),
|
||||
fn.WithPusher(pusher),
|
||||
fn.WithDeployer(deployer))
|
||||
client := bosonFunc.New(
|
||||
bosonFunc.WithRegistry(TestRegistry),
|
||||
bosonFunc.WithBuilder(builder),
|
||||
bosonFunc.WithPusher(pusher),
|
||||
bosonFunc.WithDeployer(deployer))
|
||||
|
||||
// create the new Function which will be updated
|
||||
if err := client.New(context.Background(), fn.Function{Root: root}); err != nil {
|
||||
if err := client.New(context.Background(), bosonFunc.Function{Root: root}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Builder whose implementation verifies the expected root
|
||||
builder.BuildFn = func(f fn.Function) error {
|
||||
builder.BuildFn = func(f bosonFunc.Function) error {
|
||||
rootPath, err := filepath.Abs(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -560,7 +491,7 @@ func TestUpdate(t *testing.T) {
|
|||
}
|
||||
|
||||
// Pusher whose implementaiton verifies the expected image
|
||||
pusher.PushFn = func(f fn.Function) (string, error) {
|
||||
pusher.PushFn = func(f bosonFunc.Function) (string, error) {
|
||||
if f.Image != expectedImage {
|
||||
t.Fatalf("pusher expected image '%v', got '%v'", expectedImage, f.Image)
|
||||
}
|
||||
|
@ -569,7 +500,7 @@ func TestUpdate(t *testing.T) {
|
|||
}
|
||||
|
||||
// Update whose implementaiton verifed the expected name and image
|
||||
deployer.DeployFn = func(f fn.Function) error {
|
||||
deployer.DeployFn = func(f bosonFunc.Function) error {
|
||||
if f.Name != expectedName {
|
||||
t.Fatalf("updater expected name '%v', got '%v'", expectedName, f.Name)
|
||||
}
|
||||
|
@ -610,11 +541,11 @@ func TestRemoveByPath(t *testing.T) {
|
|||
}
|
||||
defer os.RemoveAll(root)
|
||||
|
||||
client := fn.New(
|
||||
fn.WithRegistry(TestRegistry),
|
||||
fn.WithRemover(remover))
|
||||
client := bosonFunc.New(
|
||||
bosonFunc.WithRegistry(TestRegistry),
|
||||
bosonFunc.WithRemover(remover))
|
||||
|
||||
if err := client.New(context.Background(), fn.Function{Root: root}); err != nil {
|
||||
if err := client.New(context.Background(), bosonFunc.Function{Root: root}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -625,7 +556,7 @@ func TestRemoveByPath(t *testing.T) {
|
|||
return nil
|
||||
}
|
||||
|
||||
if err := client.Remove(context.Background(), fn.Function{Root: root}); err != nil {
|
||||
if err := client.Remove(context.Background(), bosonFunc.Function{Root: root}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -649,11 +580,11 @@ func TestRemoveByName(t *testing.T) {
|
|||
}
|
||||
defer os.RemoveAll(root)
|
||||
|
||||
client := fn.New(
|
||||
fn.WithRegistry(TestRegistry),
|
||||
fn.WithRemover(remover))
|
||||
client := bosonFunc.New(
|
||||
bosonFunc.WithRegistry(TestRegistry),
|
||||
bosonFunc.WithRemover(remover))
|
||||
|
||||
if err := client.Create(fn.Function{Root: root}); err != nil {
|
||||
if err := client.Create(bosonFunc.Function{Root: root}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -665,12 +596,12 @@ func TestRemoveByName(t *testing.T) {
|
|||
}
|
||||
|
||||
// Run remove with only a name
|
||||
if err := client.Remove(context.Background(), fn.Function{Name: expectedName}); err != nil {
|
||||
if err := client.Remove(context.Background(), bosonFunc.Function{Name: expectedName}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Run remove with a name and a root, which should be ignored in favor of the name.
|
||||
if err := client.Remove(context.Background(), fn.Function{Name: expectedName, Root: root}); err != nil {
|
||||
if err := client.Remove(context.Background(), bosonFunc.Function{Name: expectedName, Root: root}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -700,12 +631,12 @@ func TestRemoveUninitializedFails(t *testing.T) {
|
|||
}
|
||||
|
||||
// Instantiate the client with the failing remover.
|
||||
client := fn.New(
|
||||
fn.WithRegistry(TestRegistry),
|
||||
fn.WithRemover(remover))
|
||||
client := bosonFunc.New(
|
||||
bosonFunc.WithRegistry(TestRegistry),
|
||||
bosonFunc.WithRemover(remover))
|
||||
|
||||
// Attempt to remove by path (uninitialized), expecting an error.
|
||||
if err := client.Remove(context.Background(), fn.Function{Root: root}); err == nil {
|
||||
if err := client.Remove(context.Background(), bosonFunc.Function{Root: root}); err == nil {
|
||||
t.Fatalf("did not received expeced error removing an uninitialized func")
|
||||
}
|
||||
}
|
||||
|
@ -714,7 +645,7 @@ func TestRemoveUninitializedFails(t *testing.T) {
|
|||
func TestList(t *testing.T) {
|
||||
lister := mock.NewLister()
|
||||
|
||||
client := fn.New(fn.WithLister(lister)) // lists deployed Functions.
|
||||
client := bosonFunc.New(bosonFunc.WithLister(lister)) // lists deployed Functions.
|
||||
|
||||
if _, err := client.List(context.Background()); err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -733,7 +664,7 @@ func TestListOutsideRoot(t *testing.T) {
|
|||
lister := mock.NewLister()
|
||||
|
||||
// Instantiate in the current working directory, with no name.
|
||||
client := fn.New(fn.WithLister(lister))
|
||||
client := bosonFunc.New(bosonFunc.WithLister(lister))
|
||||
|
||||
if _, err := client.List(context.Background()); err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -755,10 +686,10 @@ func TestDeployUnbuilt(t *testing.T) {
|
|||
defer os.RemoveAll(root)
|
||||
|
||||
// New Client
|
||||
client := fn.New(fn.WithRegistry(TestRegistry))
|
||||
client := bosonFunc.New(bosonFunc.WithRegistry(TestRegistry))
|
||||
|
||||
// Initialize (half-create) a new Function at root
|
||||
if err := client.Create(fn.Function{Root: root}); err != nil {
|
||||
if err := client.Create(bosonFunc.Function{Root: root}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -768,7 +699,7 @@ func TestDeployUnbuilt(t *testing.T) {
|
|||
t.Fatal("did not receive an error attempting to deploy an unbuilt Function")
|
||||
}
|
||||
|
||||
if !errors.Is(err, fn.ErrNotBuilt) {
|
||||
if !errors.Is(err, bosonFunc.ErrNotBuilt) {
|
||||
t.Fatalf("did not receive expected error type. Expected ErrNotBuilt, got %T", err)
|
||||
}
|
||||
}
|
||||
|
|
12
cmd/build.go
12
cmd/build.go
|
@ -6,7 +6,7 @@ import (
|
|||
"github.com/ory/viper"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
"github.com/boson-project/func/buildpacks"
|
||||
"github.com/boson-project/func/progress"
|
||||
"github.com/boson-project/func/prompt"
|
||||
|
@ -106,11 +106,11 @@ func runBuild(cmd *cobra.Command, _ []string) (err error) {
|
|||
listener.Done()
|
||||
}()
|
||||
|
||||
client := fn.New(
|
||||
fn.WithVerbose(config.Verbose),
|
||||
fn.WithRegistry(config.Registry), // for deriving image name when --image not provided explicitly.
|
||||
fn.WithBuilder(builder),
|
||||
fn.WithProgressListener(listener))
|
||||
client := bosonFunc.New(
|
||||
bosonFunc.WithVerbose(config.Verbose),
|
||||
bosonFunc.WithRegistry(config.Registry), // for deriving image name when --image not provided explicitly.
|
||||
bosonFunc.WithBuilder(builder),
|
||||
bosonFunc.WithProgressListener(listener))
|
||||
|
||||
return client.Build(context, config.Path)
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
"github.com/boson-project/func/buildpacks"
|
||||
"github.com/boson-project/func/knative"
|
||||
)
|
||||
|
@ -79,7 +79,7 @@ func CompleteBuilderList(cmd *cobra.Command, args []string, complete string) (st
|
|||
var (
|
||||
err error
|
||||
path string
|
||||
f fn.Function
|
||||
f bosonFunc.Function
|
||||
)
|
||||
|
||||
path, err = cmd.Flags().GetString("path")
|
||||
|
@ -87,7 +87,7 @@ func CompleteBuilderList(cmd *cobra.Command, args []string, complete string) (st
|
|||
return
|
||||
}
|
||||
|
||||
f, err = fn.NewFunction(path)
|
||||
f, err = bosonFunc.NewFunction(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"github.com/ory/viper"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
"github.com/boson-project/func/prompt"
|
||||
"github.com/boson-project/func/utils"
|
||||
)
|
||||
|
@ -15,9 +15,9 @@ import (
|
|||
func init() {
|
||||
root.AddCommand(createCmd)
|
||||
createCmd.Flags().BoolP("confirm", "c", false, "Prompt to confirm all configuration options (Env: $FUNC_CONFIRM)")
|
||||
createCmd.Flags().StringP("runtime", "l", fn.DefaultRuntime, "Function runtime language/framework. Available runtimes: "+utils.RuntimeList()+" (Env: $FUNC_RUNTIME)")
|
||||
createCmd.Flags().StringP("runtime", "l", bosonFunc.DefaultRuntime, "Function runtime language/framework. Available runtimes: "+utils.RuntimeList()+" (Env: $FUNC_RUNTIME)")
|
||||
createCmd.Flags().StringP("templates", "", filepath.Join(configPath(), "templates"), "Path to additional templates (Env: $FUNC_TEMPLATES)")
|
||||
createCmd.Flags().StringP("trigger", "t", fn.DefaultTrigger, "Function trigger. Available triggers: 'http' and 'events' (Env: $FUNC_TRIGGER)")
|
||||
createCmd.Flags().StringP("trigger", "t", bosonFunc.DefaultTrigger, "Function trigger. Available triggers: 'http' and 'events' (Env: $FUNC_TRIGGER)")
|
||||
|
||||
if err := createCmd.RegisterFlagCompletionFunc("runtime", CompleteRuntimeList); err != nil {
|
||||
fmt.Println("internal: error while calling RegisterFlagCompletionFunc: ", err)
|
||||
|
@ -60,16 +60,16 @@ func runCreate(cmd *cobra.Command, args []string) error {
|
|||
|
||||
config = config.Prompt()
|
||||
|
||||
function := fn.Function{
|
||||
function := bosonFunc.Function{
|
||||
Name: config.Name,
|
||||
Root: config.Path,
|
||||
Runtime: config.Runtime,
|
||||
Trigger: config.Trigger,
|
||||
}
|
||||
|
||||
client := fn.New(
|
||||
fn.WithTemplates(config.Templates),
|
||||
fn.WithVerbose(config.Verbose))
|
||||
client := bosonFunc.New(
|
||||
bosonFunc.WithTemplates(config.Templates),
|
||||
bosonFunc.WithVerbose(config.Verbose))
|
||||
|
||||
return client.Create(function)
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package cmd
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ory/viper"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
"golang.org/x/term"
|
||||
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
"github.com/boson-project/func/buildpacks"
|
||||
"github.com/boson-project/func/docker"
|
||||
"github.com/boson-project/func/knative"
|
||||
|
@ -132,13 +132,13 @@ func runDeploy(cmd *cobra.Command, _ []string) (err error) {
|
|||
listener.Done()
|
||||
}()
|
||||
|
||||
client := fn.New(
|
||||
fn.WithVerbose(config.Verbose),
|
||||
fn.WithRegistry(config.Registry), // for deriving image name when --image not provided explicitly.
|
||||
fn.WithBuilder(builder),
|
||||
fn.WithPusher(pusher),
|
||||
fn.WithDeployer(deployer),
|
||||
fn.WithProgressListener(listener))
|
||||
client := bosonFunc.New(
|
||||
bosonFunc.WithVerbose(config.Verbose),
|
||||
bosonFunc.WithRegistry(config.Registry), // for deriving image name when --image not provided explicitly.
|
||||
bosonFunc.WithBuilder(builder),
|
||||
bosonFunc.WithPusher(pusher),
|
||||
bosonFunc.WithDeployer(deployer),
|
||||
bosonFunc.WithProgressListener(listener))
|
||||
|
||||
if config.Build {
|
||||
if err := client.Build(context, config.Path); err != nil {
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
"github.com/boson-project/func/knative"
|
||||
)
|
||||
|
||||
|
@ -51,7 +51,7 @@ kn func describe --output yaml --path myotherfunc
|
|||
func runDescribe(cmd *cobra.Command, args []string) (err error) {
|
||||
config := newDescribeConfig(args)
|
||||
|
||||
function, err := fn.NewFunction(config.Path)
|
||||
function, err := bosonFunc.NewFunction(config.Path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -67,9 +67,9 @@ func runDescribe(cmd *cobra.Command, args []string) (err error) {
|
|||
}
|
||||
describer.Verbose = config.Verbose
|
||||
|
||||
client := fn.New(
|
||||
fn.WithVerbose(config.Verbose),
|
||||
fn.WithDescriber(describer))
|
||||
client := bosonFunc.New(
|
||||
bosonFunc.WithVerbose(config.Verbose),
|
||||
bosonFunc.WithDescriber(describer))
|
||||
|
||||
d, err := client.Describe(config.Name, config.Path)
|
||||
if err != nil {
|
||||
|
@ -109,7 +109,7 @@ func newDescribeConfig(args []string) describeConfig {
|
|||
// Output Formatting (serializers)
|
||||
// -------------------------------
|
||||
|
||||
type description fn.Description
|
||||
type description bosonFunc.Description
|
||||
|
||||
func (d description) Human(w io.Writer) error {
|
||||
fmt.Fprintln(w, "Function name:")
|
||||
|
|
10
cmd/list.go
10
cmd/list.go
|
@ -12,7 +12,7 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
"github.com/boson-project/func/knative"
|
||||
)
|
||||
|
||||
|
@ -66,9 +66,9 @@ func runList(cmd *cobra.Command, args []string) (err error) {
|
|||
lister.Namespace = ""
|
||||
}
|
||||
|
||||
client := fn.New(
|
||||
fn.WithVerbose(config.Verbose),
|
||||
fn.WithLister(lister))
|
||||
client := bosonFunc.New(
|
||||
bosonFunc.WithVerbose(config.Verbose),
|
||||
bosonFunc.WithLister(lister))
|
||||
|
||||
items, err := client.List(cmd.Context())
|
||||
if err != nil {
|
||||
|
@ -105,7 +105,7 @@ func newListConfig() listConfig {
|
|||
// Output Formatting (serializers)
|
||||
// -------------------------------
|
||||
|
||||
type listItems []fn.ListItem
|
||||
type listItems []bosonFunc.ListItem
|
||||
|
||||
func (items listItems) Human(w io.Writer) error {
|
||||
return items.Plain(w)
|
||||
|
|
12
cmd/root.go
12
cmd/root.go
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/ory/viper"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
)
|
||||
|
||||
// The root of the command tree defines the command name, descriotion, globally
|
||||
|
@ -150,8 +150,8 @@ type functionOverrides struct {
|
|||
// Function project at root, if provided, and returns the Function
|
||||
// configuration values.
|
||||
// Please note that When this function is called, the overrides are not persisted.
|
||||
func functionWithOverrides(root string, overrides functionOverrides) (f fn.Function, err error) {
|
||||
f, err = fn.NewFunction(root)
|
||||
func functionWithOverrides(root string, overrides functionOverrides) (f bosonFunc.Function, err error) {
|
||||
f, err = bosonFunc.NewFunction(root)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ func deriveName(explicitName string, path string) string {
|
|||
}
|
||||
|
||||
// If the directory at path contains an initialized Function, use the name therein
|
||||
f, err := fn.NewFunction(path)
|
||||
f, err := bosonFunc.NewFunction(path)
|
||||
if err == nil && f.Name != "" {
|
||||
return f.Name
|
||||
}
|
||||
|
@ -240,14 +240,14 @@ func deriveImage(explicitImage, defaultRegistry, path string) string {
|
|||
if explicitImage != "" {
|
||||
return explicitImage // use the explicit value provided.
|
||||
}
|
||||
f, err := fn.NewFunction(path)
|
||||
f, err := bosonFunc.NewFunction(path)
|
||||
if err != nil {
|
||||
return "" // unable to derive due to load error (uninitialized?)
|
||||
}
|
||||
if f.Image != "" {
|
||||
return f.Image // use value previously provided or derived.
|
||||
}
|
||||
derivedValue, _ := fn.DerivedImage(path, defaultRegistry)
|
||||
derivedValue, _ := bosonFunc.DerivedImage(path, defaultRegistry)
|
||||
return derivedValue // Use the func system's derivation logic.
|
||||
}
|
||||
|
||||
|
|
10
cmd/run.go
10
cmd/run.go
|
@ -6,7 +6,7 @@ import (
|
|||
"github.com/ory/viper"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
"github.com/boson-project/func/docker"
|
||||
)
|
||||
|
||||
|
@ -40,7 +40,7 @@ kn func run
|
|||
func runRun(cmd *cobra.Command, args []string) (err error) {
|
||||
config := newRunConfig(cmd)
|
||||
|
||||
function, err := fn.NewFunction(config.Path)
|
||||
function, err := bosonFunc.NewFunction(config.Path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -60,9 +60,9 @@ func runRun(cmd *cobra.Command, args []string) (err error) {
|
|||
runner := docker.NewRunner()
|
||||
runner.Verbose = config.Verbose
|
||||
|
||||
client := fn.New(
|
||||
fn.WithRunner(runner),
|
||||
fn.WithVerbose(config.Verbose))
|
||||
client := bosonFunc.New(
|
||||
bosonFunc.WithRunner(runner),
|
||||
bosonFunc.WithVerbose(config.Verbose))
|
||||
|
||||
err = client.Run(cmd.Context(), config.Path)
|
||||
return
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package function
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
|
@ -40,7 +41,7 @@ func newConfig(root string) (c config, err error) {
|
|||
}
|
||||
return
|
||||
}
|
||||
bb, err := os.ReadFile(filename)
|
||||
bb, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -89,5 +90,5 @@ func writeConfig(f Function) (err error) {
|
|||
if bb, err = yaml.Marshal(&c); err != nil {
|
||||
return
|
||||
}
|
||||
return os.WriteFile(path, bb, 0644)
|
||||
return ioutil.WriteFile(path, bb, 0644)
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ import (
|
|||
"github.com/docker/docker/client"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
)
|
||||
|
||||
type Opt func(*Pusher) error
|
||||
|
@ -30,7 +30,7 @@ type CredentialsProvider func(ctx context.Context, registry string) (Credentials
|
|||
// Pusher of images from local to remote registry.
|
||||
type Pusher struct {
|
||||
// Verbose logging.
|
||||
Verbose bool
|
||||
Verbose bool
|
||||
credentialsProvider CredentialsProvider
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ func EmptyCredentialsProvider(ctx context.Context, registry string) (Credentials
|
|||
// NewPusher creates an instance of a docker-based image pusher.
|
||||
func NewPusher(opts ...Opt) (*Pusher, error) {
|
||||
result := &Pusher{
|
||||
Verbose: false,
|
||||
Verbose: false,
|
||||
credentialsProvider: EmptyCredentialsProvider,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
|
@ -61,7 +61,7 @@ func NewPusher(opts ...Opt) (*Pusher, error) {
|
|||
}
|
||||
|
||||
// Push the image of the Function.
|
||||
func (n *Pusher) Push(ctx context.Context, f fn.Function) (digest string, err error) {
|
||||
func (n *Pusher) Push(ctx context.Context, f bosonFunc.Function) (digest string, err error) {
|
||||
|
||||
if f.Image == "" {
|
||||
return "", errors.New("Function has no associated image. Has it been built?")
|
||||
|
@ -71,7 +71,7 @@ func (n *Pusher) Push(ctx context.Context, f fn.Function) (digest string, err er
|
|||
parts := strings.Split(f.Image, "/")
|
||||
switch len(parts) {
|
||||
case 2:
|
||||
registry = fn.DefaultRegistry
|
||||
registry = bosonFunc.DefaultRegistry
|
||||
case 3:
|
||||
registry = parts[0]
|
||||
default:
|
||||
|
|
|
@ -15,7 +15,7 @@ import (
|
|||
|
||||
"github.com/docker/docker/client"
|
||||
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
)
|
||||
|
||||
// Runner of functions using the docker command.
|
||||
|
@ -30,7 +30,7 @@ func NewRunner() *Runner {
|
|||
}
|
||||
|
||||
// Run the function at path
|
||||
func (n *Runner) Run(ctx context.Context, f fn.Function) error {
|
||||
func (n *Runner) Run(ctx context.Context, f bosonFunc.Function) error {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
"github.com/boson-project/func/docker"
|
||||
)
|
||||
|
||||
|
@ -27,7 +27,7 @@ func TestDockerRun(t *testing.T) {
|
|||
t.Skip()
|
||||
}
|
||||
|
||||
f, err := fn.NewFunction("testdata/example.com/runnable")
|
||||
f, err := bosonFunc.NewFunction("testdata/example.com/runnable")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ To create a Client which uses the included buildpacks-based function builder, pu
|
|||
package main
|
||||
|
||||
import (
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
"github.com/boson-project/func/buildpacks"
|
||||
"github.com/boson-project/func/docker"
|
||||
"github.com/boson-project/func/knative"
|
||||
|
@ -28,16 +28,16 @@ func main() {
|
|||
// A client which uses embedded function templates,
|
||||
// Quay.io/alice for interstitial build artifacts.
|
||||
// Docker to build and push, and a Knative client for deployment.
|
||||
client := fn.New(
|
||||
fn.WithBuilder(buildpacks.NewBuilder()),
|
||||
fn.WithPusher(pusher),
|
||||
fn.WithDeployer(deployer),
|
||||
fn.WithRegistry("quay.io/alice"))
|
||||
client := bosonFunc.New(
|
||||
bosonFunc.WithBuilder(buildpacks.NewBuilder()),
|
||||
bosonFunc.WithPusher(pusher),
|
||||
bosonFunc.WithDeployer(deployer),
|
||||
bosonFunc.WithRegistry("quay.io/alice"))
|
||||
|
||||
// Create a Go function which listens for CloudEvents.
|
||||
// Publicly routable as https://www.example.com.
|
||||
// Local implementation is written to the current working directory.
|
||||
funcTest := fn.Function{
|
||||
funcTest := bosonFunc.Function{
|
||||
Runtime: "go",
|
||||
Trigger: "events",
|
||||
Name: "my-function",
|
||||
|
|
|
@ -3,6 +3,7 @@ package function
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
@ -222,7 +223,7 @@ var contentiousFiles = []string{
|
|||
|
||||
// contentiousFilesIn the given directoy
|
||||
func contentiousFilesIn(dir string) (contentious []string, err error) {
|
||||
files, err := os.ReadDir(dir)
|
||||
files, err := ioutil.ReadDir(dir)
|
||||
for _, file := range files {
|
||||
for _, name := range contentiousFiles {
|
||||
if file.Name() == name {
|
||||
|
@ -236,7 +237,7 @@ func contentiousFilesIn(dir string) (contentious []string, err error) {
|
|||
// effectivelyEmpty directories are those which have no visible files
|
||||
func isEffectivelyEmpty(dir string) (bool, error) {
|
||||
// Check for any non-hidden files
|
||||
files, err := os.ReadDir(dir)
|
||||
files, err := ioutil.ReadDir(dir)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
77
generate.go
77
generate.go
|
@ -1,77 +0,0 @@
|
|||
// +build generate
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const (
|
||||
archive = "templates.tgz"
|
||||
files = "templates"
|
||||
)
|
||||
|
||||
// on 'go generate' create templates archive (tar -czf templates.tgz templates)
|
||||
func main() {
|
||||
if err := create(archive, files); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func create(name, source string) (err error) {
|
||||
// Create file on disk
|
||||
tarball, err := os.Create(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer tarball.Close()
|
||||
|
||||
// A gzip compressor which writes to the file
|
||||
compressor := gzip.NewWriter(tarball)
|
||||
defer compressor.Close()
|
||||
|
||||
// A tar writer which writes to gzip compressor
|
||||
w := tar.NewWriter(compressor)
|
||||
defer w.Close()
|
||||
|
||||
// File walking function which writes tar entries for each file.
|
||||
return filepath.WalkDir(source, func(path string, d fs.DirEntry, e error) (err error) {
|
||||
if e != nil {
|
||||
return e // abort on any failed ReadDir calls.
|
||||
}
|
||||
|
||||
// Header
|
||||
fi, err := d.Info()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
h, err := tar.FileInfoHeader(fi, d.Name())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
h.Name = filepath.ToSlash(path)
|
||||
if err = w.WriteHeader(h); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Done if directory
|
||||
if d.IsDir() {
|
||||
return
|
||||
}
|
||||
|
||||
// Data
|
||||
data, err := os.Open(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = io.Copy(w, data)
|
||||
return
|
||||
})
|
||||
}
|
3
go.mod
3
go.mod
|
@ -1,12 +1,13 @@
|
|||
module github.com/boson-project/func
|
||||
|
||||
go 1.16
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/buildpacks/pack v0.18.0
|
||||
github.com/containers/image/v5 v5.10.5
|
||||
github.com/docker/docker v20.10.2+incompatible
|
||||
github.com/docker/go-connections v0.4.0
|
||||
github.com/markbates/pkger v0.17.1
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/ory/viper v1.7.4
|
||||
github.com/pkg/errors v0.9.1
|
||||
|
|
6
go.sum
6
go.sum
|
@ -302,6 +302,7 @@ github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi
|
|||
github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses=
|
||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||
|
@ -377,6 +378,8 @@ github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG
|
|||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gobuffalo/flect v0.2.2/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc=
|
||||
github.com/gobuffalo/here v0.6.0 h1:hYrd0a6gDmWxBM4TnrGw8mQg24iSVoIkHEk7FodQcBI=
|
||||
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
|
||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
|
@ -625,6 +628,8 @@ github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7
|
|||
github.com/mailru/easyjson v0.7.1-0.20191009090205-6c0755d89d1e h1:jcoUdG1TzY/M/eM5BLFLP8DJeMximx5NQYSlLL9YeWc=
|
||||
github.com/mailru/easyjson v0.7.1-0.20191009090205-6c0755d89d1e/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
|
||||
github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ=
|
||||
github.com/markbates/pkger v0.17.1 h1:/MKEtWqtc0mZvu9OinB9UzVN9iYCwLWuyUv4Bw+PCno=
|
||||
github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
|
@ -1465,6 +1470,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
v1 "knative.dev/client/pkg/serving/v1"
|
||||
"knative.dev/eventing/pkg/apis/eventing/v1beta1"
|
||||
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
)
|
||||
|
||||
type Describer struct {
|
||||
|
@ -28,7 +28,7 @@ func NewDescriber(namespaceOverride string) (describer *Describer, err error) {
|
|||
// restricts to label-syntax, which is thus escaped. Therefore as a knative (kube) implementation
|
||||
// detal proper full names have to be escaped on the way in and unescaped on the way out. ex:
|
||||
// www.example-site.com -> www-example--site-com
|
||||
func (d *Describer) Describe(name string) (description fn.Description, err error) {
|
||||
func (d *Describer) Describe(name string) (description bosonFunc.Description, err error) {
|
||||
|
||||
servingClient, err := NewServingClient(d.namespace)
|
||||
if err != nil {
|
||||
|
@ -68,11 +68,11 @@ func (d *Describer) Describe(name string) (description fn.Description, err error
|
|||
|
||||
}
|
||||
|
||||
subscriptions := make([]fn.Subscription, 0, len(triggers.Items))
|
||||
subscriptions := make([]bosonFunc.Subscription, 0, len(triggers.Items))
|
||||
for _, trigger := range triggers.Items {
|
||||
if triggerMatches(&trigger) {
|
||||
filterAttrs := trigger.Spec.Filter.Attributes
|
||||
subscription := fn.Subscription{
|
||||
subscription := bosonFunc.Subscription{
|
||||
Source: filterAttrs["source"],
|
||||
Type: filterAttrs["type"],
|
||||
Broker: trigger.Spec.Broker,
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
clientservingv1 "knative.dev/client/pkg/serving/v1"
|
||||
"knative.dev/pkg/apis"
|
||||
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -31,7 +31,7 @@ func NewLister(namespaceOverride string) (l *Lister, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (l *Lister) List(context.Context) (items []fn.ListItem, err error) {
|
||||
func (l *Lister) List(context.Context) (items []bosonFunc.ListItem, err error) {
|
||||
|
||||
client, err := NewServingClient(l.Namespace)
|
||||
if err != nil {
|
||||
|
@ -54,7 +54,7 @@ func (l *Lister) List(context.Context) (items []fn.ListItem, err error) {
|
|||
}
|
||||
}
|
||||
|
||||
listItem := fn.ListItem{
|
||||
listItem := bosonFunc.ListItem{
|
||||
Name: service.Name,
|
||||
Namespace: service.Namespace,
|
||||
Runtime: service.Labels["boson.dev/runtime"],
|
||||
|
|
|
@ -2,21 +2,21 @@ package mock
|
|||
|
||||
import (
|
||||
"context"
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
)
|
||||
|
||||
type Builder struct {
|
||||
BuildInvoked bool
|
||||
BuildFn func(fn.Function) error
|
||||
BuildFn func(bosonFunc.Function) error
|
||||
}
|
||||
|
||||
func NewBuilder() *Builder {
|
||||
return &Builder{
|
||||
BuildFn: func(fn.Function) error { return nil },
|
||||
BuildFn: func(bosonFunc.Function) error { return nil },
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Builder) Build(ctx context.Context, f fn.Function) error {
|
||||
func (i *Builder) Build(ctx context.Context, f bosonFunc.Function) error {
|
||||
i.BuildInvoked = true
|
||||
return i.BuildFn(f)
|
||||
}
|
||||
|
|
|
@ -3,21 +3,21 @@ package mock
|
|||
import (
|
||||
"context"
|
||||
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
)
|
||||
|
||||
type Deployer struct {
|
||||
DeployInvoked bool
|
||||
DeployFn func(fn.Function) error
|
||||
DeployFn func(bosonFunc.Function) error
|
||||
}
|
||||
|
||||
func NewDeployer() *Deployer {
|
||||
return &Deployer{
|
||||
DeployFn: func(fn.Function) error { return nil },
|
||||
DeployFn: func(bosonFunc.Function) error { return nil },
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Deployer) Deploy(ctx context.Context, f fn.Function) (fn.DeploymentResult, error) {
|
||||
func (i *Deployer) Deploy(ctx context.Context, f bosonFunc.Function) (bosonFunc.DeploymentResult, error) {
|
||||
i.DeployInvoked = true
|
||||
return fn.DeploymentResult{}, i.DeployFn(f)
|
||||
return bosonFunc.DeploymentResult{}, i.DeployFn(f)
|
||||
}
|
||||
|
|
|
@ -2,21 +2,21 @@ package mock
|
|||
|
||||
import (
|
||||
"context"
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
)
|
||||
|
||||
type Lister struct {
|
||||
ListInvoked bool
|
||||
ListFn func() ([]fn.ListItem, error)
|
||||
ListFn func() ([]bosonFunc.ListItem, error)
|
||||
}
|
||||
|
||||
func NewLister() *Lister {
|
||||
return &Lister{
|
||||
ListFn: func() ([]fn.ListItem, error) { return []fn.ListItem{}, nil },
|
||||
ListFn: func() ([]bosonFunc.ListItem, error) { return []bosonFunc.ListItem{}, nil },
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Lister) List(context.Context) ([]fn.ListItem, error) {
|
||||
func (l *Lister) List(context.Context) ([]bosonFunc.ListItem, error) {
|
||||
l.ListInvoked = true
|
||||
return l.ListFn()
|
||||
}
|
||||
|
|
|
@ -3,21 +3,21 @@ package mock
|
|||
import (
|
||||
"context"
|
||||
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
)
|
||||
|
||||
type Pusher struct {
|
||||
PushInvoked bool
|
||||
PushFn func(fn.Function) (string, error)
|
||||
PushFn func(bosonFunc.Function) (string, error)
|
||||
}
|
||||
|
||||
func NewPusher() *Pusher {
|
||||
return &Pusher{
|
||||
PushFn: func(fn.Function) (string, error) { return "", nil },
|
||||
PushFn: func(bosonFunc.Function) (string, error) { return "", nil },
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Pusher) Push(ctx context.Context, f fn.Function) (string, error) {
|
||||
func (i *Pusher) Push(ctx context.Context, f bosonFunc.Function) (string, error) {
|
||||
i.PushInvoked = true
|
||||
return i.PushFn(f)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package mock
|
|||
|
||||
import (
|
||||
"context"
|
||||
fn "github.com/boson-project/func"
|
||||
bosonFunc "github.com/boson-project/func"
|
||||
)
|
||||
|
||||
type Runner struct {
|
||||
|
@ -14,7 +14,7 @@ func NewRunner() *Runner {
|
|||
return &Runner{}
|
||||
}
|
||||
|
||||
func (r *Runner) Run(ctx context.Context, f fn.Function) error {
|
||||
func (r *Runner) Run(ctx context.Context, f bosonFunc.Function) error {
|
||||
r.RunInvoked = true
|
||||
r.RootRequested = f.Root
|
||||
return nil
|
||||
|
|
224
tarfs/tarfs.go
224
tarfs/tarfs.go
|
@ -1,224 +0,0 @@
|
|||
package tarfs
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"io"
|
||||
"io/fs"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// FS is a tar-backed fs.FS
|
||||
// adapted from testing/fstest.MapFS
|
||||
type FS map[string]*file
|
||||
|
||||
// file can be any file within the FS
|
||||
type file struct {
|
||||
Data []byte
|
||||
Mode fs.FileMode
|
||||
ModTime time.Time
|
||||
Sys interface{}
|
||||
}
|
||||
|
||||
var _ fs.FS = FS(nil)
|
||||
var _ fs.File = (*openFile)(nil)
|
||||
|
||||
// New tar FS from a reader attached to a tarball.
|
||||
func New(r io.Reader) (FS, error) {
|
||||
mapfs := make(map[string]*file)
|
||||
|
||||
tr := tar.NewReader(r)
|
||||
for {
|
||||
header, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
return mapfs, nil
|
||||
}
|
||||
if err != nil {
|
||||
return mapfs, err
|
||||
}
|
||||
|
||||
// Create the file entry in the memory FS
|
||||
mapfs[header.Name] = &file{
|
||||
Mode: header.FileInfo().Mode(),
|
||||
ModTime: header.FileInfo().ModTime(),
|
||||
Sys: header.FileInfo().Sys,
|
||||
}
|
||||
|
||||
// Done if directory
|
||||
if header.FileInfo().IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Copy over the data as well
|
||||
buf := bytes.Buffer{}
|
||||
if _, err = buf.ReadFrom(tr); err != nil {
|
||||
return mapfs, err
|
||||
}
|
||||
mapfs[header.Name].Data = buf.Bytes()
|
||||
}
|
||||
}
|
||||
|
||||
func (fsys FS) Open(name string) (fs.File, error) {
|
||||
if !fs.ValidPath(name) {
|
||||
return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrNotExist}
|
||||
}
|
||||
f := fsys[name]
|
||||
if f != nil && f.Mode&fs.ModeDir == 0 {
|
||||
// Ordinary file
|
||||
return &openFile{fileInfo{path.Base(name), f}, name, 0}, nil
|
||||
}
|
||||
|
||||
// Directory, possibly synthesized.
|
||||
// Note that file can be nil here: the map need not contain explicit parent directories for all its files.
|
||||
// But file can also be non-nil, in case the user wants to set metadata for the directory explicitly.
|
||||
// Either way, we need to construct the list of children of this directory.
|
||||
list := []fileInfo{}
|
||||
elem := ""
|
||||
need := make(map[string]bool)
|
||||
if name == "." {
|
||||
elem = "."
|
||||
for fname, f := range fsys {
|
||||
i := strings.Index(fname, "/")
|
||||
if i < 0 {
|
||||
list = append(list, fileInfo{fname, f})
|
||||
} else {
|
||||
need[fname[:i]] = true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
elem = name[strings.LastIndex(name, "/")+1:]
|
||||
prefix := name + "/"
|
||||
for fname, f := range fsys {
|
||||
if strings.HasPrefix(fname, prefix) {
|
||||
felem := fname[len(prefix):]
|
||||
i := strings.Index(felem, "/")
|
||||
if i < 0 {
|
||||
list = append(list, fileInfo{felem, f})
|
||||
} else {
|
||||
need[fname[len(prefix):len(prefix)+i]] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
// If the directory name is not in the map,
|
||||
// and there are no children of the name in the map,
|
||||
// then the directory is treated as not existing.
|
||||
if f == nil && len(list) == 0 && len(need) == 0 {
|
||||
return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrNotExist}
|
||||
}
|
||||
}
|
||||
for _, fi := range list {
|
||||
delete(need, fi.name)
|
||||
}
|
||||
for name := range need {
|
||||
list = append(list, fileInfo{name, &file{Mode: fs.ModeDir}})
|
||||
}
|
||||
sort.Slice(list, func(i, j int) bool {
|
||||
return list[i].name < list[j].name
|
||||
})
|
||||
|
||||
if f == nil {
|
||||
f = &file{Mode: fs.ModeDir}
|
||||
}
|
||||
return &dir{fileInfo{elem, f}, name, list, 0, sync.Mutex{}}, nil
|
||||
}
|
||||
|
||||
// dir represents a directory in the FS
|
||||
type dir struct {
|
||||
fileInfo
|
||||
path string
|
||||
entries []fileInfo
|
||||
offset int
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func (d *dir) Stat() (fs.FileInfo, error) { return &d.fileInfo, nil }
|
||||
func (d *dir) Close() error { return nil }
|
||||
func (d *dir) Read(b []byte) (int, error) {
|
||||
return 0, &fs.PathError{Op: "read", Path: d.path, Err: fs.ErrInvalid}
|
||||
}
|
||||
func (d *dir) ReadDir(count int) (entries []fs.DirEntry, err error) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
n := len(d.entries) - d.offset
|
||||
if count > 0 && n > count {
|
||||
n = count
|
||||
}
|
||||
if n == 0 && count > 0 {
|
||||
return nil, io.EOF
|
||||
}
|
||||
list := make([]fs.DirEntry, n)
|
||||
for i := range list {
|
||||
list[i] = &d.entries[d.offset+i]
|
||||
}
|
||||
d.offset += n
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// fileInfo wraps files with metadata
|
||||
type fileInfo struct {
|
||||
name string
|
||||
f *file
|
||||
}
|
||||
|
||||
func (i *fileInfo) Name() string { return i.name }
|
||||
func (i *fileInfo) Size() int64 { return int64(len(i.f.Data)) }
|
||||
func (i *fileInfo) Mode() fs.FileMode { return i.f.Mode }
|
||||
func (i *fileInfo) Type() fs.FileMode { return i.f.Mode.Type() }
|
||||
func (i *fileInfo) ModTime() time.Time { return i.f.ModTime }
|
||||
func (i *fileInfo) IsDir() bool { return i.f.Mode&fs.ModeDir != 0 }
|
||||
func (i *fileInfo) Sys() interface{} { return i.f.Sys }
|
||||
func (i *fileInfo) Info() (fs.FileInfo, error) { return i, nil }
|
||||
|
||||
// openFile decorates a fileInfo with accessors to the underlying data for use
|
||||
// by Open
|
||||
type openFile struct {
|
||||
fileInfo
|
||||
path string
|
||||
offset int64
|
||||
}
|
||||
|
||||
func (f *openFile) Stat() (fs.FileInfo, error) { return &f.fileInfo, nil }
|
||||
func (f *openFile) Close() error { return nil }
|
||||
|
||||
func (f *openFile) Read(b []byte) (int, error) {
|
||||
if f.offset >= int64(len(f.f.Data)) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
if f.offset < 0 {
|
||||
return 0, &fs.PathError{Op: "read", Path: f.path, Err: fs.ErrInvalid}
|
||||
}
|
||||
n := copy(b, f.f.Data[f.offset:])
|
||||
f.offset += int64(n)
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (f *openFile) Seek(offset int64, whence int) (int64, error) {
|
||||
switch whence {
|
||||
case 0:
|
||||
// offset += 0
|
||||
case 1:
|
||||
offset += f.offset
|
||||
case 2:
|
||||
offset += int64(len(f.f.Data))
|
||||
}
|
||||
if offset < 0 || offset > int64(len(f.f.Data)) {
|
||||
return 0, &fs.PathError{Op: "seek", Path: f.path, Err: fs.ErrInvalid}
|
||||
}
|
||||
f.offset = offset
|
||||
return offset, nil
|
||||
}
|
||||
|
||||
func (f *openFile) ReadAt(b []byte, offset int64) (int, error) {
|
||||
if offset < 0 || offset > int64(len(f.f.Data)) {
|
||||
return 0, &fs.PathError{Op: "read", Path: f.path, Err: fs.ErrInvalid}
|
||||
}
|
||||
n := copy(b, f.f.Data[offset:])
|
||||
if n < len(b) {
|
||||
return n, io.EOF
|
||||
}
|
||||
return n, nil
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
package tarfs
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"testing/fstest"
|
||||
)
|
||||
|
||||
// TestEmpty ensures that an empty TarFS behaves itself.
|
||||
func TestEmpty(t *testing.T) {
|
||||
f, err := os.Open("testdata/empty.tar")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
tfs, err := New(f)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := fstest.TestFS(tfs); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestFile ensures that a reader of a single file tarball proffers that file.
|
||||
func TestSingle(t *testing.T) {
|
||||
f, err := os.Open("testdata/single.tar")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
tfs, err := New(f)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := fstest.TestFS(tfs, "single.txt"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestIsNotExist ensures that a request to read a file or directory which does not
|
||||
// exist returns the appropriate error.
|
||||
func TestIsNotExist(t *testing.T) {
|
||||
f, err := os.Open("testdata/empty.tar")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
tfs, err := New(f)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := fstest.TestFS(tfs, "invalid"); err == nil {
|
||||
t.Fatalf("did not receive expected error testing for a missing file")
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
306
templates.go
306
templates.go
|
@ -1,231 +1,181 @@
|
|||
package function
|
||||
|
||||
// Updating Templates:
|
||||
// See documentation in ./templates/README.md
|
||||
// go get github.com/markbates/pkger
|
||||
//go:generate pkger
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
_ "embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/boson-project/func/tarfs"
|
||||
"github.com/markbates/pkger"
|
||||
)
|
||||
|
||||
// Generate templates.tgz
|
||||
//go:generate go run generate.go
|
||||
|
||||
// Embed the templates tarball
|
||||
//go:embed templates.tgz
|
||||
var embedded []byte
|
||||
|
||||
// DefaultTemplate is the default Function signature / environmental context
|
||||
// DefautlTemplate is the default Function signature / environmental context
|
||||
// of the resultant template. All runtimes are expected to have at least
|
||||
// an HTTP Handler ("http") and Cloud Events ("events")
|
||||
const DefaultTemplate = "http"
|
||||
|
||||
type templateWriter struct {
|
||||
// Extensible Template Repositories
|
||||
// templates on disk (extensible templates)
|
||||
// Stored on disk at path:
|
||||
// [customTemplatesPath]/[repository]/[runtime]/[template]
|
||||
// For example
|
||||
// ~/.config/func/boson/go/http"
|
||||
// Specified when writing templates as simply:
|
||||
// Write([runtime], [repository], [path])
|
||||
// For example
|
||||
// w := templateWriter{templates:"/home/username/.config/func/templates")
|
||||
// w.Write("go", "boson/http")
|
||||
// Ie. "Using the custom templates in the func configuration directory,
|
||||
// write the Boson HTTP template for the Go runtime."
|
||||
repositories string
|
||||
templates fs.FS
|
||||
verbose bool
|
||||
// fileAccessor encapsulates methods for accessing template files.
|
||||
type fileAccessor interface {
|
||||
Stat(name string) (os.FileInfo, error)
|
||||
Open(p string) (file, error)
|
||||
}
|
||||
|
||||
var (
|
||||
ErrRepositoryNotFound = errors.New("repository not found")
|
||||
ErrRepositoriesNotDefined = errors.New("custom template location not specified")
|
||||
ErrRuntimeNotFound = errors.New("runtime not found")
|
||||
ErrTemplateNotFound = errors.New("template not found")
|
||||
ErrTemplateMissingRepository = errors.New("template name missing repository prefix")
|
||||
)
|
||||
type file interface {
|
||||
Readdir(int) ([]os.FileInfo, error)
|
||||
Read([]byte) (int, error)
|
||||
Close() error
|
||||
}
|
||||
|
||||
// Decompress into an in-memory FS which implements fs.ReadDirFS
|
||||
func (t *templateWriter) load() (err error) {
|
||||
// When pkger is run, code analysis detects this Include statement,
|
||||
// triggering the serializaation of the templates directory and all
|
||||
// its contents into pkged.go, which is then made available via
|
||||
// a pkger fileAccessor.
|
||||
// Path is relative to the go module root.
|
||||
func init() {
|
||||
_ = pkger.Include("/templates")
|
||||
}
|
||||
|
||||
// Templates are stored as an embedded byte slice gzip encoded.
|
||||
zr, err := gzip.NewReader(bytes.NewReader(embedded))
|
||||
type templateWriter struct {
|
||||
verbose bool
|
||||
templates string
|
||||
}
|
||||
|
||||
func (n templateWriter) Write(runtime, template string, dest string) error {
|
||||
if template == "" {
|
||||
template = DefaultTemplate
|
||||
}
|
||||
|
||||
// TODO: Confirm the dest path is empty? This is currently in an earlier
|
||||
// step of the create process but future calls directly to initialize would
|
||||
// be better off being made safe.
|
||||
|
||||
if isEmbedded(runtime, template) {
|
||||
return copyEmbedded(runtime, template, dest)
|
||||
}
|
||||
if n.templates != "" {
|
||||
return copyFilesystem(n.templates, runtime, template, dest)
|
||||
}
|
||||
return fmt.Errorf("A template for runtime '%v' template '%v' was not found internally and no custom template path was defined.", runtime, template)
|
||||
}
|
||||
|
||||
func copyEmbedded(runtime, template, dest string) error {
|
||||
// Copy files to the destination
|
||||
// Example embedded path:
|
||||
// /templates/go/http
|
||||
src := filepath.Join("/templates", runtime, template)
|
||||
return copy(src, dest, embeddedAccessor{})
|
||||
}
|
||||
|
||||
func copyFilesystem(templatesPath, runtime, templateFullName, dest string) error {
|
||||
// ensure that the templateFullName is of the format "repoName/templateName"
|
||||
cc := strings.Split(templateFullName, "/")
|
||||
if len(cc) != 2 {
|
||||
return errors.New("Template name must be in the format 'REPO/NAME'")
|
||||
}
|
||||
repo := cc[0]
|
||||
template := cc[1]
|
||||
|
||||
// Example FileSystem path:
|
||||
// /home/alice/.config/func/templates/boson-experimental/go/json
|
||||
src := filepath.Join(templatesPath, repo, runtime, template)
|
||||
return copy(src, dest, filesystemAccessor{})
|
||||
}
|
||||
|
||||
func isEmbedded(runtime, template string) bool {
|
||||
_, err := pkger.Stat(filepath.Join("/templates", runtime, template))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
type embeddedAccessor struct{}
|
||||
|
||||
func (a embeddedAccessor) Stat(path string) (os.FileInfo, error) {
|
||||
return pkger.Stat(path)
|
||||
}
|
||||
|
||||
func (a embeddedAccessor) Open(path string) (file, error) {
|
||||
return pkger.Open(path)
|
||||
}
|
||||
|
||||
type filesystemAccessor struct{}
|
||||
|
||||
func (a filesystemAccessor) Stat(path string) (os.FileInfo, error) {
|
||||
return os.Stat(path)
|
||||
}
|
||||
|
||||
func (a filesystemAccessor) Open(path string) (file, error) {
|
||||
return os.Open(path)
|
||||
}
|
||||
|
||||
func copy(src, dest string, accessor fileAccessor) (err error) {
|
||||
node, err := accessor.Stat(src)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if node.IsDir() {
|
||||
return copyNode(src, dest, accessor)
|
||||
} else {
|
||||
return copyLeaf(src, dest, accessor)
|
||||
}
|
||||
}
|
||||
|
||||
func copyNode(src, dest string, accessor fileAccessor) (err error) {
|
||||
node, err := accessor.Stat(src)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
t.templates, err = tarfs.New(zr)
|
||||
return
|
||||
}
|
||||
err = os.MkdirAll(dest, node.Mode())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Write the template for the given runtime to the destination specified.
|
||||
// Template may be prefixed with a custom repo name.
|
||||
func (t *templateWriter) Write(runtime, template, dest string) (err error) {
|
||||
if t.templates == nil {
|
||||
// load static embedded templates into t.templates as an fs.FS
|
||||
if err = t.load(); err != nil {
|
||||
children, err := readDir(src, accessor)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, child := range children {
|
||||
if err = copy(filepath.Join(src, child.Name()), filepath.Join(dest, child.Name()), accessor); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if template == "" {
|
||||
template = DefaultTemplate
|
||||
}
|
||||
if isCustom(template) {
|
||||
return t.writeCustom(t.repositories, runtime, template, dest)
|
||||
}
|
||||
return t.writeEmbedded(runtime, template, dest)
|
||||
return
|
||||
}
|
||||
|
||||
func isCustom(template string) bool {
|
||||
return len(strings.Split(template, "/")) > 1
|
||||
}
|
||||
|
||||
func (t *templateWriter) writeCustom(repositoriesPath, runtime, template, dest string) (err error) {
|
||||
if repositoriesPath == "" {
|
||||
return ErrRepositoriesNotDefined
|
||||
}
|
||||
if !repositoryExists(repositoriesPath, template) {
|
||||
return ErrRepositoryNotFound
|
||||
}
|
||||
cc := strings.Split(template, "/")
|
||||
if len(cc) < 2 {
|
||||
return ErrTemplateMissingRepository
|
||||
}
|
||||
repositoriesFS := os.DirFS(repositoriesPath)
|
||||
|
||||
runtimePath := cc[0] + "/" + runtime
|
||||
_, err = fs.Stat(repositoriesFS, runtimePath)
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
return ErrRuntimeNotFound
|
||||
}
|
||||
|
||||
templatePath := runtimePath + "/" + cc[1]
|
||||
_, err = fs.Stat(repositoriesFS, templatePath)
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
return ErrTemplateNotFound
|
||||
}
|
||||
|
||||
// ex: /home/alice/.config/func/repositories/boson/go/http
|
||||
// Note that the FS instance returned by os.DirFS uses forward slashes
|
||||
// internally, so source paths do not use the os path separator due to
|
||||
// that breaking Windows.
|
||||
src := cc[0] + "/" + runtime + "/" + cc[1]
|
||||
return t.cp(src, dest, repositoriesFS)
|
||||
}
|
||||
|
||||
func (t *templateWriter) writeEmbedded(runtime, template, dest string) error {
|
||||
runtimePath := "templates/" + runtime // embedded FS alwas uses '/'
|
||||
_, err := fs.Stat(t.templates, runtimePath)
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
return ErrRuntimeNotFound
|
||||
}
|
||||
|
||||
templatePath := "templates/" + runtime + "/" + template // always '/' in embedded fs
|
||||
_, err = fs.Stat(t.templates, templatePath)
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
return ErrTemplateNotFound
|
||||
}
|
||||
|
||||
return t.cp(templatePath, dest, t.templates)
|
||||
}
|
||||
|
||||
func repositoryExists(repositories, template string) bool {
|
||||
cc := strings.Split(template, "/")
|
||||
_, err := fs.Stat(os.DirFS(repositories), cc[0])
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func (t *templateWriter) cp(src, dest string, files fs.FS) error {
|
||||
node, err := fs.Stat(files, src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if node.IsDir() {
|
||||
return t.copyNode(src, dest, files)
|
||||
} else {
|
||||
return t.copyLeaf(src, dest, files)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *templateWriter) copyNode(src, dest string, files fs.FS) error {
|
||||
node, err := fs.Stat(files, src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mode := node.Mode()
|
||||
|
||||
err = os.MkdirAll(dest, mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
children, err := readDir(src, files)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, child := range children {
|
||||
// NOTE: instances of fs.FS use forward slashes,
|
||||
// even on Windows.
|
||||
childSrc := src + "/" + child.Name()
|
||||
childDest := filepath.Join(dest, child.Name())
|
||||
if err = t.cp(childSrc, childDest, files); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func readDir(src string, files fs.FS) ([]fs.DirEntry, error) {
|
||||
f, err := files.Open(src)
|
||||
func readDir(src string, accessor fileAccessor) ([]os.FileInfo, error) {
|
||||
f, err := accessor.Open(src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
fi, err := f.Stat()
|
||||
list, err := f.Readdir(-1)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !fi.IsDir() {
|
||||
return nil, fmt.Errorf("%v must be a directory", fi.Name())
|
||||
}
|
||||
list, err := f.(fs.ReadDirFile).ReadDir(-1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sort.Slice(list, func(i, j int) bool { return list[i].Name() < list[j].Name() })
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (t *templateWriter) copyLeaf(src, dest string, files fs.FS) (err error) {
|
||||
srcFile, err := files.Open(src)
|
||||
func copyLeaf(src, dest string, accessor fileAccessor) (err error) {
|
||||
srcFile, err := accessor.Open(src)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer srcFile.Close()
|
||||
|
||||
srcFileInfo, err := fs.Stat(files, src)
|
||||
srcFileInfo, err := accessor.Stat(src)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Use the original's mode unless a nonzero mode was explicitly provided.
|
||||
mode := srcFileInfo.Mode()
|
||||
|
||||
destFile, err := os.OpenFile(dest, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode)
|
||||
destFile, err := os.OpenFile(dest, os.O_RDWR|os.O_CREATE|os.O_TRUNC, srcFileInfo.Mode())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,4 +1,24 @@
|
|||
# Templates
|
||||
|
||||
This templates directory is embedded entirely into any resultant binaries
|
||||
using the go:embed directive introduced in Go 1.16
|
||||
## Packaging
|
||||
|
||||
When updates are made to these templates, they must be packaged (serialized as
|
||||
a Go struture) by running `make`, and checking in the resultant `pkged.go` file.
|
||||
|
||||
## How it works
|
||||
|
||||
running `make` in turn installs the `pkger` binary, which can be installed via:
|
||||
`go get github.com/markbates/pkger/cmd/pkger`
|
||||
Make then invokes `pkger` before `go build`.
|
||||
|
||||
The resulting `pkged.go` file includes the contents of the templates directory,
|
||||
encoded as a Go strucutres which is then makde available in code using an API
|
||||
similar to the standard library's `os` package.
|
||||
|
||||
## Rationale
|
||||
|
||||
Until such time as embedding static assets in binaries is included in the
|
||||
base `go build` functionality (see https://github.com/golang/go/issues/35950)
|
||||
a third-party tool is required and pkger provides an API very similar
|
||||
to the `os` package.
|
||||
|
||||
|
|
|
@ -1,118 +0,0 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudevents/sdk-go/v2 v2.3.1 h1:QRTu0yRA4FbznjRSds0/4Hy6cVYpWV2wInlNJSHWAtw=
|
||||
github.com/cloudevents/sdk-go/v2 v2.3.1/go.mod h1:4fO2UjPMYYR1/7KPJQCwTPb0lFA8zYuitkUpAZFSY1Q=
|
||||
github.com/cloudevents/sdk-go/v2 v2.4.0 h1:IkzAOizTvn+M13KWDLFOiTb44YBuwAvbenzSg43bWM4=
|
||||
github.com/cloudevents/sdk-go/v2 v2.4.0/go.mod h1:MZiMwmAh5tGj+fPFvtHv9hKurKqXtdB9haJYMJ/7GJY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk=
|
||||
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lightstep/tracecontext.go v0.0.0-20181129014701-1757c391b1ac h1:+2b6iGRJe3hvV/yVXrd41yVEjxuFHxasJqDhkIjS4gk=
|
||||
github.com/lightstep/tracecontext.go v0.0.0-20181129014701-1757c391b1ac/go.mod h1:Frd2bnT3w5FB5q49ENTfVlztJES+1k/7lyWX2+9gq/M=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.2 h1:uqH7bpe+ERSiDa34FDOF7RikN6RzXgduUF8yarlZp94=
|
||||
github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
@ -1,86 +0,0 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudevents/sdk-go/v2 v2.3.1/go.mod h1:4fO2UjPMYYR1/7KPJQCwTPb0lFA8zYuitkUpAZFSY1Q=
|
||||
github.com/cloudevents/sdk-go/v2 v2.4.0 h1:IkzAOizTvn+M13KWDLFOiTb44YBuwAvbenzSg43bWM4=
|
||||
github.com/cloudevents/sdk-go/v2 v2.4.0/go.mod h1:MZiMwmAh5tGj+fPFvtHv9hKurKqXtdB9haJYMJ/7GJY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lightstep/tracecontext.go v0.0.0-20181129014701-1757c391b1ac/go.mod h1:Frd2bnT3w5FB5q49ENTfVlztJES+1k/7lyWX2+9gq/M=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
@ -1,2 +0,0 @@
|
|||
Runtime A
|
||||
Template HTTP (Default)
|
|
@ -1,2 +0,0 @@
|
|||
Runtime A
|
||||
Template A
|
|
@ -1,2 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
echo "example executable script provided by a template"
|
|
@ -1,2 +0,0 @@
|
|||
Runtime A
|
||||
Template B
|
|
@ -3,186 +3,75 @@
|
|||
package function
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestRuntime consists of a specially designed templates directory
|
||||
// used exclusively for embedded template write tests.
|
||||
const TestRuntime = "test"
|
||||
|
||||
// TestWriteEmbedded ensures that embedded templates are copied.
|
||||
func TestWriteEmbedded(t *testing.T) {
|
||||
// create test directory
|
||||
root := "testdata/testWriteEmbedded"
|
||||
defer using(t, root)()
|
||||
|
||||
// write out a template
|
||||
w := templateWriter{}
|
||||
err := w.Write(TestRuntime, "tpla", root)
|
||||
// TestTemplatesEmbeddedFileMode ensures that files from the embedded templates are
|
||||
// written with the same mode from whence they came
|
||||
func TestTemplatesEmbeddedFileMode(t *testing.T) {
|
||||
var path = "testdata/example.com/www"
|
||||
err := os.MkdirAll(path, 0744)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer os.RemoveAll(path)
|
||||
|
||||
client := New()
|
||||
function := Function{Root: path, Runtime: "quarkus", Trigger: "events"}
|
||||
if err := client.Create(function); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Assert file exists as expected
|
||||
_, err = os.Stat(filepath.Join(root, "rtAtplA.txt"))
|
||||
// The file mode of the embedded mvnw should be -rwxr-xr-x
|
||||
// See source file at: templates/quarkus/events/mvnw
|
||||
// Assert mode is preserved
|
||||
sourceMode := os.FileMode(0755)
|
||||
dest, err := os.Stat(filepath.Join(path, "mvnw"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if runtime.GOOS != "windows" {
|
||||
if dest.Mode() != sourceMode {
|
||||
t.Fatalf("The dest mode should be %v but was %v", sourceMode, dest.Mode())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestWriteCustom ensures that a template from a filesystem source (ie. custom
|
||||
// provider on disk) can be specified as the source for a template.
|
||||
func TestWriteCustom(t *testing.T) {
|
||||
// Create test directory
|
||||
root := "testdata/testWriteFilesystem"
|
||||
defer using(t, root)()
|
||||
// TestTemplatesExtensibleFileMode ensures that files from a file-system
|
||||
// derived template is written with mode retained.
|
||||
func TestTemplatesExtensibleFileMode(t *testing.T) {
|
||||
var (
|
||||
path = "testdata/example.com/www"
|
||||
template = "boson-experimental/http"
|
||||
templates = "testdata/templates"
|
||||
)
|
||||
err := os.MkdirAll(path, 0744)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer os.RemoveAll(path)
|
||||
|
||||
// Writer which includes reference to custom repositories location
|
||||
w := templateWriter{repositories: "testdata/repositories"}
|
||||
// template, in form [provider]/[template], on disk the template is
|
||||
// located at testdata/repositories/[provider]/[runtime]/[template]
|
||||
tpl := "customProvider/tpla"
|
||||
err := w.Write(TestRuntime, tpl, root)
|
||||
client := New(WithTemplates(templates))
|
||||
function := Function{Root: path, Runtime: "quarkus", Trigger: template}
|
||||
if err := client.Create(function); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Assert mode is preserved
|
||||
source, err := os.Stat(filepath.Join("testdata/templates/boson-experimental/quarkus/http/mvnw"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Assert file exists as expected
|
||||
_, err = os.Stat(filepath.Join(root, "customtpl.txt"))
|
||||
dest, err := os.Stat(filepath.Join(path, "mvnw"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWriteDefault ensures that the default template is used when not specified.
|
||||
func TestWriteDefault(t *testing.T) {
|
||||
// create test directory
|
||||
root := "testdata/testWriteDefault"
|
||||
defer using(t, root)()
|
||||
|
||||
// write out a template
|
||||
w := templateWriter{}
|
||||
err := w.Write(TestRuntime, "", root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Assert file exists as expected
|
||||
_, err = os.Stat(filepath.Join(root, "rtAtplDefault.txt"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWriteInvalid ensures that specifying unrecgognized runtime/template errors
|
||||
func TestWriteInvalid(t *testing.T) {
|
||||
// create test directory
|
||||
root := "testdata/testWriteInvalid"
|
||||
defer using(t, root)()
|
||||
|
||||
w := templateWriter{}
|
||||
var err error // should be populated with the correct error type
|
||||
|
||||
// Test for error writing an invalid runtime
|
||||
// (the http template
|
||||
err = w.Write("invalid", DefaultTemplate, root)
|
||||
if !errors.Is(err, ErrRuntimeNotFound) {
|
||||
t.Fatalf("Expected ErrRuntimeNotFound, got %T", err)
|
||||
}
|
||||
|
||||
// Test for error writing an invalid template
|
||||
err = w.Write(TestRuntime, "invalid", root)
|
||||
if !errors.Is(err, ErrTemplateNotFound) {
|
||||
t.Fatalf("Expected ErrTemplateNotFound, got %T", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWriteModeEmbedded ensures that templates written from the embedded
|
||||
// templates retain their mode.
|
||||
func TestWriteModeEmbedded(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
return
|
||||
// not applicable
|
||||
}
|
||||
|
||||
// set up test directory
|
||||
var err error
|
||||
root := "testdata/testWriteModeEmbedded"
|
||||
defer using(t, root)()
|
||||
|
||||
// Write the embedded template that contains an executable script
|
||||
w := templateWriter{}
|
||||
err = w.Write(TestRuntime, "tplb", root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Verify file mode was preserved
|
||||
file, err := os.Stat(filepath.Join(root, "executable.sh"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if file.Mode() != os.FileMode(0755) {
|
||||
t.Fatalf("The embedded executable's mode should be 0755 but was %v", file.Mode())
|
||||
}
|
||||
}
|
||||
|
||||
// TestWriteModeCustom ensures that templates written from custom templates
|
||||
// retain their mode.
|
||||
func TestWriteModeCustom(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
return // not applicable
|
||||
}
|
||||
|
||||
// test directories
|
||||
var err error
|
||||
root := "testdata/testWriteModeCustom"
|
||||
defer using(t, root)()
|
||||
|
||||
// Write executable from custom repo
|
||||
w := templateWriter{repositories: "testdata/repositories"}
|
||||
err = w.Write(TestRuntime, "customProvider/tplb", root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Verify custom file mode was preserved.
|
||||
file, err := os.Stat(filepath.Join(root, "executable.sh"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if file.Mode() != os.FileMode(0755) {
|
||||
t.Fatalf("The custom executable file's mode should be 0755 but was %v", file.Mode())
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers
|
||||
// -------
|
||||
|
||||
// using the given directory (creating it) returns a closure which removes the
|
||||
// directory, intended to be run in a defer statement.
|
||||
func using(t *testing.T, root string) func() {
|
||||
t.Helper()
|
||||
mkdir(t, root)
|
||||
return func() {
|
||||
rm(t, root)
|
||||
}
|
||||
}
|
||||
|
||||
func mkdir(t *testing.T, dir string) {
|
||||
t.Helper()
|
||||
if err := os.MkdirAll(dir, 0700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func rm(t *testing.T, dir string) {
|
||||
t.Helper()
|
||||
if err := os.RemoveAll(dir); err != nil {
|
||||
t.Fatal(err)
|
||||
if runtime.GOOS != "windows" {
|
||||
if dest.Mode() != source.Mode() {
|
||||
t.Fatalf("The dest mode should be %v but was %v", source.Mode(), dest.Mode())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
Custom Provider
|
||||
Runtime A
|
||||
Template A
|
|
@ -1,2 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
echo "example executable script provided by a template"
|
Loading…
Reference in New Issue