Skip to content

Commit

Permalink
Allow downstream projects to import func-e
Browse files Browse the repository at this point in the history
* Define an api that allows go projects to use func-e as a library

Takes #434 forward

Fixes: #433

Signed-off-by: Arko Dasgupta <[email protected]>
  • Loading branch information
arkodg committed Aug 9, 2023
1 parent 82577c9 commit 8b44356
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 0 deletions.
111 changes: 111 additions & 0 deletions api/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright 2022 Tetrate
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package api allows go projects to use func-e as a library.
package api

import (
"context"
"io"
"os"
"runtime"

"github.com/tetratelabs/func-e/internal/cmd"
"github.com/tetratelabs/func-e/internal/globals"
"github.com/tetratelabs/func-e/internal/version"
)

// HomeDir is an absolute path which most importantly contains "versions"
// installed from EnvoyVersionsURL. Defaults to "${HOME}/.func-e"
func HomeDir(homeDir string) RunOption {
return func(o *runOpts) {
o.homeDir = homeDir
}
}

// EnvoyVersionsURL is the path to the envoy-versions.json.
// Defaults to "https://archive.tetratelabs.io/envoy/envoy-versions.json"
func EnvoyVersionsURL(envoyVersionsURL string) RunOption {
return func(o *runOpts) {
o.envoyVersionsURL = envoyVersionsURL
}
}

// EnvoyVersion overrides the version of Envoy to run. Defaults to the
// contents of "$HomeDir/versions/version".
//
// When that file is missing, it is generated from ".latestVersion" from the
// EnvoyVersionsURL. Its value can be in full version major.minor.patch format,
// e.g. 1.18.1 or without patch component, major.minor, e.g. 1.18.
func EnvoyVersion(envoyVersion string) RunOption {
return func(o *runOpts) {
o.envoyVersion = envoyVersion
}
}

// Out is where status messages are written. Defaults to os.Stdout
func Out(out io.Writer) RunOption {
return func(o *runOpts) {
o.out = out
}
}

// RunOption is configuration for Run.
type RunOption func(*runOpts)

type runOpts struct {
homeDir string
envoyVersion string
envoyVersionsURL string
out io.Writer
}

// Run downloads Envoy and runs it as a process with the arguments
// passed to it. Use RunOption for configuration options.
func Run(ctx context.Context, args []string, options ...RunOption) error {
ro := &runOpts{
homeDir: globals.DefaultHomeDir,
envoyVersion: "", // default to lookup
envoyVersionsURL: globals.DefaultEnvoyVersionsURL,
out: os.Stdout,
}
for _, option := range options {
option(ro)
}

o := globals.GlobalOpts{
HomeDir: ro.homeDir,
EnvoyVersion: version.PatchVersion(ro.envoyVersion),
EnvoyVersionsURL: ro.envoyVersion,
Out: ro.out,
}

funcECmd := cmd.NewApp(&o)

funcERunArgs := []string{"func-e", "--platform", runtime.GOOS + "/" + runtime.GOARCH, "run"}
funcERunArgs = append(funcERunArgs, args...)

errChan := make(chan error)
go func() {
errChan <- funcECmd.RunContext(ctx, funcERunArgs)
}()

// Wait for run to exit or an explicit stop.
select {
case <-ctx.Done():
return nil
case err := <-errChan:
return err
}
}
55 changes: 55 additions & 0 deletions api/run_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2022 Tetrate
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package api

import (
"bytes"
"context"
"os"
"path/filepath"
"testing"
"time"

"github.com/stretchr/testify/require"

"github.com/tetratelabs/func-e/internal/test"
"github.com/tetratelabs/func-e/internal/version"
)

var (
runArgs = []string{"--version"}
)

func TestRun(t *testing.T) {

tmpDir := t.TempDir()
envoyVersion := version.LastKnownEnvoy
versionsServer := test.RequireEnvoyVersionsTestServer(t, envoyVersion)
defer versionsServer.Close()
envoyVersionsURL := versionsServer.URL + "/envoy-versions.json"
b := bytes.NewBufferString("")

require.Equal(t, 0, b.Len())

ctx := context.Background()
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
defer cancel()
err := Run(ctx, runArgs, Out(b), HomeDir(tmpDir), EnvoyVersionsURL(envoyVersionsURL))
require.NoError(t, err)

require.NotEqual(t, 0, b.Len())
_, err = os.Stat(filepath.Join(tmpDir, "versions"))
require.NoError(t, err)
}

0 comments on commit 8b44356

Please sign in to comment.