Browse Source

add pack support for porter deploy

Alexander Belanger 5 years ago
parent
commit
15a1710959

+ 30 - 0
cli/cmd/create/create.go

@@ -0,0 +1,30 @@
+package create
+
+import (
+	"github.com/porter-dev/porter/cli/cmd/api"
+	"github.com/porter-dev/porter/cli/cmd/docker"
+)
+
+// CreateAgent handles the creation of a new application on Porter
+type CreateAgent struct {
+	client *api.Client
+	agent  *docker.Agent
+	opts   *CreateOpts
+}
+
+// CreateOpts are the options for creating a new CreateAgent
+type CreateOpts struct {
+	ProjectID uint
+	ClusterID uint
+	Namespace string
+}
+
+func (c *CreateAgent) CreateFromDocker() error {
+	// read values from local file
+
+	// overwrite with docker image repository and tag
+
+	// call subdomain creation if necessary
+
+	return nil
+}

+ 32 - 3
cli/cmd/deploy.go

@@ -63,6 +63,9 @@ var deployBuildCmd = &cobra.Command{
 
 var app string
 var getEnvFileDest string
+var local bool
+var localPath string
+var tag string
 
 func init() {
 	rootCmd.AddCommand(deployCmd)
@@ -81,6 +84,29 @@ func init() {
 		"Namespace of the application",
 	)
 
+	deployCmd.PersistentFlags().BoolVar(
+		&local,
+		"local",
+		false,
+		"Whether local context should be used for build",
+	)
+
+	deployCmd.PersistentFlags().StringVarP(
+		&localPath,
+		"path",
+		"p",
+		".",
+		"If local build, the path to the build directory",
+	)
+
+	deployCmd.PersistentFlags().StringVarP(
+		&tag,
+		"tag",
+		"t",
+		"",
+		"If local build, the specified tag to use, if not \"latest\"",
+	)
+
 	deployCmd.AddCommand(deployGetEnvCmd)
 
 	deployGetEnvCmd.PersistentFlags().StringVar(
@@ -98,9 +124,12 @@ func deployFull(resp *api.AuthCheckResponse, client *api.Client, args []string)
 
 	// initialize the deploy agent
 	deployAgent, err := deploy.NewDeployAgent(client, app, &deploy.DeployOpts{
-		ProjectID: config.Project,
-		ClusterID: config.Cluster,
-		Namespace: namespace,
+		ProjectID:   config.Project,
+		ClusterID:   config.Cluster,
+		Namespace:   namespace,
+		Local:       local,
+		LocalPath:   localPath,
+		OverrideTag: tag,
 	})
 
 	if err != nil {

+ 124 - 46
cli/cmd/deploy/deploy.go

@@ -12,28 +12,48 @@ import (
 	"github.com/porter-dev/porter/cli/cmd/api"
 	"github.com/porter-dev/porter/cli/cmd/docker"
 	"github.com/porter-dev/porter/cli/cmd/github"
+	"github.com/porter-dev/porter/cli/cmd/pack"
 	"k8s.io/client-go/util/homedir"
 )
 
+// deployBuildType is the option to use as a builder
+type deployBuildType string
+
+const (
+	// uses local Docker daemon to build and push images
+	deployBuildTypeDocker deployBuildType = "docker"
+
+	// uses cloud-native build pack to build and push images
+	deployBuildTypePack deployBuildType = "pack"
+)
+
 // DeployAgent handles the deployment and redeployment of an application on Porter
 type DeployAgent struct {
 	App string
 
-	client    *api.Client
-	release   *api.GetReleaseResponse
-	agent     *docker.Agent
-	opts      *DeployOpts
-	tag       string
-	envPrefix string
+	buildType   deployBuildType
+	client      *api.Client
+	release     *api.GetReleaseResponse
+	agent       *docker.Agent
+	opts        *DeployOpts
+	tag         string
+	envPrefix   string
+	env         map[string]string
+	imageExists bool
 }
 
 // DeployOpts are the options for creating a new DeployAgent
 type DeployOpts struct {
-	ProjectID uint
-	ClusterID uint
-	Namespace string
+	ProjectID   uint
+	ClusterID   uint
+	Namespace   string
+	Local       bool
+	LocalPath   string
+	OverrideTag string
 }
 
+var ErrNoGitActionConfig error = fmt.Errorf("specified release does not have a git action config")
+
 // NewDeployAgent creates a new DeployAgent given a Porter API client, application
 // name, and DeployOpts.
 func NewDeployAgent(client *api.Client, app string, opts *DeployOpts) (*DeployAgent, error) {
@@ -41,6 +61,7 @@ func NewDeployAgent(client *api.Client, app string, opts *DeployOpts) (*DeployAg
 		App:    app,
 		opts:   opts,
 		client: client,
+		env:    make(map[string]string),
 	}
 
 	// get release from Porter API
@@ -50,6 +71,11 @@ func NewDeployAgent(client *api.Client, app string, opts *DeployOpts) (*DeployAg
 		return nil, err
 	}
 
+	// if the git action config is nil, return an error
+	if release.GitActionConfig == nil {
+		return nil, ErrNoGitActionConfig
+	}
+
 	deployAgent.release = release
 
 	// set an environment prefix to avoid collisions
@@ -66,6 +92,14 @@ func NewDeployAgent(client *api.Client, app string, opts *DeployOpts) (*DeployAg
 
 	deployAgent.agent = agent
 
+	if release.GitActionConfig.DockerfilePath != "" {
+		deployAgent.buildType = deployBuildTypeDocker
+	} else {
+		deployAgent.buildType = deployBuildTypePack
+	}
+
+	deployAgent.tag = opts.OverrideTag
+
 	return deployAgent, nil
 }
 
@@ -74,8 +108,11 @@ func (d *DeployAgent) GetBuildEnv() (map[string]string, error) {
 }
 
 func (d *DeployAgent) SetBuildEnv(envVars map[string]string) error {
+	d.env = envVars
+
 	// iterate through env and set the environment variables for the process
-	// these are prefixed with PORTER_<RELEASE> to avoid collisions
+	// these are prefixed with PORTER_<RELEASE> to avoid collisions. We use
+	// these prefixed env when calling a custom build command as a child process.
 	for key, val := range envVars {
 		prefixedKey := fmt.Sprintf("%s_%s", d.envPrefix, key)
 
@@ -113,29 +150,38 @@ func (d *DeployAgent) WriteBuildEnv(fileDest string) error {
 }
 
 func (d *DeployAgent) Build() error {
-	zipResp, err := d.client.GetRepoZIPDownloadURL(
-		context.Background(),
-		d.opts.ProjectID,
-		d.release.GitActionConfig,
-	)
+	// if build is not local, fetch remote source
+	var dst string
+	var err error
+
+	if !d.opts.Local {
+		zipResp, err := d.client.GetRepoZIPDownloadURL(
+			context.Background(),
+			d.opts.ProjectID,
+			d.release.GitActionConfig,
+		)
 
-	if err != nil {
-		return err
-	}
+		if err != nil {
+			return err
+		}
 
-	// download the repository from remote source into a temp directory
-	dst, err := d.downloadRepoToDir(zipResp.URLString)
+		// download the repository from remote source into a temp directory
+		dst, err = d.downloadRepoToDir(zipResp.URLString)
 
-	shortRef := fmt.Sprintf("%.7s", zipResp.LatestCommitSHA)
+		if d.tag == "" {
+			shortRef := fmt.Sprintf("%.7s", zipResp.LatestCommitSHA)
+			d.tag = shortRef
+		}
 
-	if err != nil {
-		return err
+		if err != nil {
+			return err
+		}
+	} else {
+		dst = filepath.Dir(d.opts.LocalPath)
 	}
 
-	agent, err := docker.NewAgentWithAuthGetter(d.client, d.opts.ProjectID)
-
-	if err != nil {
-		return err
+	if d.tag == "" {
+		d.tag = "latest"
 	}
 
 	err = d.pullCurrentReleaseImage()
@@ -145,14 +191,36 @@ func (d *DeployAgent) Build() error {
 		return err
 	} else if err != nil && err == docker.PullImageErrNotFound {
 		fmt.Println("could not find image, moving to build step")
+		d.imageExists = false
 	}
 
-	// case on Dockerfile path
-	if d.release.GitActionConfig.DockerfilePath != "" {
-		err = agent.BuildLocal(
-			d.release.GitActionConfig.DockerfilePath,
-			fmt.Sprintf("%s:%s", d.release.GitActionConfig.ImageRepoURI, shortRef),
-			dst,
+	if d.buildType == deployBuildTypeDocker {
+		return d.BuildDocker(dst, d.tag)
+	}
+
+	return d.BuildPack(dst, d.tag)
+}
+
+func (d *DeployAgent) BuildDocker(dst, tag string) error {
+	opts := &docker.BuildOpts{
+		ImageRepo:    d.release.GitActionConfig.ImageRepoURI,
+		Tag:          tag,
+		BuildContext: dst,
+		Env:          d.env,
+	}
+
+	return d.agent.BuildLocal(
+		opts,
+		d.release.GitActionConfig.DockerfilePath,
+	)
+}
+
+func (d *DeployAgent) BuildPack(dst, tag string) error {
+	// retag the image with "pack-cache" tag so that it doesn't re-pull from the registry
+	if d.imageExists {
+		err := d.agent.TagImage(
+			fmt.Sprintf("%s:%s", d.release.GitActionConfig.ImageRepoURI, tag),
+			fmt.Sprintf("%s:%s", d.release.GitActionConfig.ImageRepoURI, "pack-cache"),
 		)
 
 		if err != nil {
@@ -160,9 +228,30 @@ func (d *DeployAgent) Build() error {
 		}
 	}
 
-	d.tag = shortRef
+	// create pack agent and build opts
+	packAgent := &pack.Agent{}
+
+	opts := &docker.BuildOpts{
+		ImageRepo: d.release.GitActionConfig.ImageRepoURI,
+		// We tag the image with a stable param "pack-cache" so that pack can use the
+		// local image without attempting to re-pull from registry. We handle getting
+		// registry credentials and pushing/pulling the image.
+		Tag:          "pack-cache",
+		BuildContext: dst,
+		Env:          d.env,
+	}
 
-	return nil
+	// call builder
+	err := packAgent.Build(opts)
+
+	if err != nil {
+		return err
+	}
+
+	return d.agent.TagImage(
+		fmt.Sprintf("%s:%s", d.release.GitActionConfig.ImageRepoURI, "pack-cache"),
+		fmt.Sprintf("%s:%s", d.release.GitActionConfig.ImageRepoURI, tag),
+	)
 }
 
 func (d *DeployAgent) Deploy() error {
@@ -192,17 +281,6 @@ func (d *DeployAgent) Deploy() error {
 	)
 }
 
-// func deployWithNewTag(resp *api.AuthCheckResponse, client *api.Client, args []string) error {
-// 	if release == nil {
-// 		err := deployInit(resp, client, args)
-
-// 		if err != nil {
-// 			return err
-// 		}
-// 	}
-
-// }
-
 // HELPER METHODS
 func (d *DeployAgent) getEnvFromRelease() (map[string]string, error) {
 	envConfig, err := getNestedMap(d.release.Config, "container", "env", "normal")

+ 14 - 22
cli/cmd/docker/agent.go

@@ -139,6 +139,10 @@ func (a *Agent) ConnectContainerToNetwork(networkID, containerID, containerName
 	return a.client.NetworkConnect(a.ctx, networkID, containerID, &network.EndpointSettings{})
 }
 
+func (a *Agent) TagImage(old, new string) error {
+	return a.client.ImageTag(a.ctx, old, new)
+}
+
 // PullImageEvent represents a response from the Docker API with an image pull event
 type PullImageEvent struct {
 	Status         string `json:"status"`
@@ -152,6 +156,8 @@ type PullImageEvent struct {
 
 var PullImageErrNotFound = fmt.Errorf("Requested image not found")
 
+var PullImageErrUnauthorized = fmt.Errorf("Could not pull image: unauthorized")
+
 // PullImage pulls an image specified by the image string
 func (a *Agent) PullImage(image string) error {
 	opts, err := a.getPullOptions(image)
@@ -163,10 +169,14 @@ func (a *Agent) PullImage(image string) error {
 	// pull the specified image
 	out, err := a.client.ImagePull(a.ctx, image, opts)
 
-	if err != nil && strings.Contains(err.Error(), "Requested image not found") {
-		return PullImageErrNotFound
-	} else if err != nil {
-		return a.handleDockerClientErr(err, "Could not pull image "+image)
+	if err != nil {
+		if client.IsErrNotFound(err) {
+			return PullImageErrNotFound
+		} else if client.IsErrUnauthorized(err) {
+			return PullImageErrUnauthorized
+		} else {
+			return a.handleDockerClientErr(err, "Could not pull image "+image)
+		}
 	}
 
 	defer out.Close()
@@ -174,24 +184,6 @@ func (a *Agent) PullImage(image string) error {
 	termFd, isTerm := term.GetFdInfo(os.Stderr)
 
 	return jsonmessage.DisplayJSONMessagesStream(out, os.Stderr, termFd, isTerm, nil)
-
-	// decoder := json.NewDecoder(out)
-
-	// var event *PullImageEvent
-
-	// for {
-	// 	if err := decoder.Decode(&event); err != nil {
-	// 		if err == io.EOF {
-	// 			break
-	// 		}
-
-	// 		return err
-	// 	}
-
-	// 	fmt.Println(event.Status)
-	// }
-
-	return nil
 }
 
 // PushImage pushes an image specified by the image string

+ 22 - 4
cli/cmd/docker/builder.go

@@ -2,6 +2,7 @@ package docker
 
 import (
 	"context"
+	"fmt"
 	"os"
 
 	"github.com/docker/docker/api/types"
@@ -10,18 +11,35 @@ import (
 	"github.com/moby/term"
 )
 
+type BuildOpts struct {
+	ImageRepo    string
+	Tag          string
+	BuildContext string
+	Env          map[string]string
+}
+
 // BuildLocal
-func (a *Agent) BuildLocal(dockerfilePath, tag, buildContext string) error {
-	tar, err := archive.TarWithOptions(buildContext, &archive.TarOptions{})
+func (a *Agent) BuildLocal(opts *BuildOpts, dockerfilePath string) error {
+	tar, err := archive.TarWithOptions(opts.BuildContext, &archive.TarOptions{})
 
 	if err != nil {
 		return err
 	}
 
+	buildArgs := make(map[string]*string)
+
+	for key, val := range opts.Env {
+		valCopy := val
+		buildArgs[key] = &valCopy
+	}
+
 	out, err := a.client.ImageBuild(context.Background(), tar, types.ImageBuildOptions{
 		Dockerfile: dockerfilePath,
-		Tags:       []string{tag},
-		Remove:     true,
+		BuildArgs:  buildArgs,
+		Tags: []string{
+			fmt.Sprintf("%s:%s", opts.ImageRepo, opts.Tag),
+		},
+		Remove: true,
 	})
 
 	if err != nil {

+ 4 - 2
cli/cmd/docker/porter.go

@@ -9,6 +9,8 @@ import (
 	"github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/api/types/mount"
 	"github.com/docker/go-connections/nat"
+
+	specs "github.com/opencontainers/image-spec/specs-go/v1"
 )
 
 // PorterDB is used for enumerating DB types
@@ -261,7 +263,7 @@ func (a *Agent) pullAndCreatePorterContainer(opts PorterServerStartOpts) (id str
 	}, &container.HostConfig{
 		PortBindings: portBindings,
 		Mounts:       opts.Mounts,
-	}, nil, opts.Name)
+	}, nil, &specs.Platform{}, opts.Name)
 
 	if err != nil {
 		return "", a.handleDockerClientErr(err, "Could not create Porter container")
@@ -364,7 +366,7 @@ func (a *Agent) pullAndCreatePostgresContainer(opts PostgresOpts) (id string, er
 		},
 	}, &container.HostConfig{
 		Mounts: opts.Mounts,
-	}, nil, opts.Name)
+	}, nil, &specs.Platform{}, opts.Name)
 
 	if err != nil {
 		return "", a.handleDockerClientErr(err, "Could not create Porter container")

+ 32 - 0
cli/cmd/pack/pack.go

@@ -0,0 +1,32 @@
+package pack
+
+import (
+	"context"
+	"fmt"
+
+	"github.com/buildpacks/pack"
+	"github.com/porter-dev/porter/cli/cmd/docker"
+)
+
+type Agent struct{}
+
+func (a *Agent) Build(opts *docker.BuildOpts) error {
+	//create a context object
+	context := context.Background()
+
+	//initialize a pack client
+	client, err := pack.NewClient()
+	if err != nil {
+		panic(err)
+	}
+
+	buildOpts := pack.BuildOptions{
+		Image:        fmt.Sprintf("%s:%s", opts.ImageRepo, opts.Tag),
+		Builder:      "heroku/buildpacks:18",
+		AppPath:      opts.BuildContext,
+		TrustBuilder: true,
+		Env:          opts.Env,
+	}
+
+	return client.Build(context, buildOpts)
+}

+ 16 - 47
go.mod

@@ -5,96 +5,65 @@ go 1.15
 require (
 	cloud.google.com/go v0.65.0
 	github.com/AlecAivazis/survey/v2 v2.2.9
-	github.com/Azure/go-autorest/autorest v0.11.1 // indirect
-	github.com/Azure/go-autorest/autorest/adal v0.9.5 // indirect
 	github.com/DATA-DOG/go-sqlmock v1.5.0
-	github.com/Masterminds/semver v1.5.0 // indirect
 	github.com/aws/aws-sdk-go v1.35.4
-	github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20201113001948-d77edb6d2e47
-	github.com/containerd/containerd v1.4.1 // indirect
-	github.com/coreos/rkt v1.30.0
-	github.com/creack/pty v1.1.11 // indirect
+	github.com/buildpacks/pack v0.19.0
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/digitalocean/godo v1.56.0
-	github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492
+	github.com/docker/cli v20.10.5+incompatible
 	github.com/docker/distribution v2.7.1+incompatible
-	github.com/docker/docker v1.4.2-0.20200203170920-46ec8731fbce
+	github.com/docker/docker v20.10.0-beta1.0.20201110211921-af34b94a78a1+incompatible
 	github.com/docker/docker-credential-helpers v0.6.3
 	github.com/docker/go-connections v0.4.0
-	github.com/evanphx/json-patch v4.9.0+incompatible // indirect
 	github.com/fatih/color v1.9.0
 	github.com/go-chi/chi v4.1.2+incompatible
 	github.com/go-playground/locales v0.13.0
 	github.com/go-playground/universal-translator v0.17.0
 	github.com/go-playground/validator/v10 v10.3.0
-	github.com/go-redis/redis v6.15.9+incompatible
-	github.com/go-redis/redis/v7 v7.4.0
 	github.com/go-redis/redis/v8 v8.3.1
 	github.com/go-test/deep v1.0.7
-	github.com/google/go-cmp v0.5.2
 	github.com/google/go-github v17.0.0+incompatible
-	github.com/google/go-github/v32 v32.1.0
 	github.com/google/go-github/v33 v33.0.0
-	github.com/google/go-querystring v1.0.0 // indirect
-	github.com/googleapis/gnostic v0.2.2 // indirect
 	github.com/gorilla/schema v1.2.0
 	github.com/gorilla/securecookie v1.1.1
 	github.com/gorilla/sessions v1.2.1
 	github.com/gorilla/websocket v1.4.2
-	github.com/hashicorp/go-getter v1.5.3
 	github.com/hashicorp/golang-lru v0.5.3 // indirect
-	github.com/imdario/mergo v0.3.11 // indirect
 	github.com/itchyny/gojq v0.11.1
 	github.com/itchyny/timefmt-go v0.1.1 // indirect
 	github.com/jinzhu/gorm v1.9.16
 	github.com/joeshaw/envdecode v0.0.0-20200121155833-099f1fc765bd
-	github.com/json-iterator/go v1.1.10 // indirect
-	github.com/kr/pretty v0.2.0 // indirect
-	github.com/kr/text v0.2.0 // indirect
 	github.com/kris-nova/logger v0.0.0-20181127235838-fd0d87064b06
 	github.com/kris-nova/lolgopher v0.0.0-20180921204813-313b3abb0d9b // indirect
 	github.com/moby/moby v20.10.6+incompatible
 	github.com/moby/term v0.0.0-20201216013528-df9cb8a40635
-	github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
-	github.com/onsi/ginkgo v1.14.2 // indirect
-	github.com/opentracing/opentracing-go v1.2.0 // indirect
-	github.com/pelletier/go-toml v1.8.1 // indirect
+	github.com/opencontainers/image-spec v1.0.1
 	github.com/pkg/errors v0.9.1
 	github.com/rs/zerolog v1.20.0
 	github.com/segmentio/backo-go v0.0.0-20200129164019-23eae7c10bd3 // indirect
 	github.com/sendgrid/rest v2.6.3+incompatible // indirect
 	github.com/sendgrid/sendgrid-go v3.8.0+incompatible
-	github.com/sirupsen/logrus v1.7.0
-	github.com/spf13/cobra v1.0.0
+	github.com/spf13/cobra v1.1.3
 	github.com/spf13/pflag v1.0.5
-	github.com/spf13/viper v1.4.0
-	github.com/stretchr/testify v1.6.1
+	github.com/spf13/viper v1.7.0
+	github.com/stretchr/testify v1.7.0
 	github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect
-	go.opentelemetry.io/otel v0.13.0 // indirect
-	golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0
-	golang.org/x/exp v0.0.0-20200908183739-ae8ad444f925 // indirect
+	golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83
 	golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
-	golang.org/x/sys v0.0.0-20210108172913-0df2131ae363 // indirect
-	golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect
 	google.golang.org/api v0.30.0
-	google.golang.org/genproto v0.0.0-20201014134559-03b6142f0dc9
-	google.golang.org/grpc v1.33.0 // indirect
-	gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
+	google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a
 	gopkg.in/segmentio/analytics-go.v3 v3.1.0
-	gopkg.in/yaml.v2 v2.3.0
+	gopkg.in/yaml.v2 v2.4.0
 	gorm.io/driver/postgres v1.0.2
 	gorm.io/driver/sqlite v1.1.3
 	gorm.io/gorm v1.20.2
-	gotest.tools/v3 v3.0.3 // indirect
-	helm.sh/helm/v3 v3.3.4
-	k8s.io/api v0.18.8
-	k8s.io/apimachinery v0.18.8
-	k8s.io/cli-runtime v0.18.8
-	k8s.io/client-go v0.18.8
+	helm.sh/helm/v3 v3.6.0
+	k8s.io/api v0.21.0
+	k8s.io/apimachinery v0.21.0
+	k8s.io/cli-runtime v0.21.0
+	k8s.io/client-go v0.21.0
 	k8s.io/helm v2.16.12+incompatible
-	k8s.io/klog/v2 v2.2.0 // indirect
-	k8s.io/kubectl v0.18.8
-	k8s.io/utils v0.0.0-20200912215256-4140de9c8800 // indirect
+	k8s.io/kubectl v0.21.0
 	rsc.io/letsencrypt v0.0.3 // indirect
 	sigs.k8s.io/aws-iam-authenticator v0.5.2
 	sigs.k8s.io/yaml v1.2.0

File diff suppressed because it is too large
+ 172 - 151
go.sum


+ 1 - 1
internal/helm/agent_test.go

@@ -21,7 +21,7 @@ func newAgentFixture(t *testing.T, namespace string) *helm.Agent {
 		Namespace: namespace,
 	}
 
-	return helm.GetAgentTesting(form, nil, l)
+	return helm.GetAgentTesting(form, nil, l, nil)
 }
 
 type releaseStub struct {

+ 2 - 1
internal/helm/config.go

@@ -104,7 +104,7 @@ func GetAgentInClusterConfig(form *Form, l *logger.Logger) (*Agent, error) {
 }
 
 // GetAgentTesting creates a new Agent using an optional existing storage class
-func GetAgentTesting(form *Form, storage *storage.Storage, l *logger.Logger) *Agent {
+func GetAgentTesting(form *Form, storage *storage.Storage, l *logger.Logger, k8sAgent *kubernetes.Agent) *Agent {
 	testStorage := storage
 
 	if testStorage == nil {
@@ -122,5 +122,6 @@ func GetAgentTesting(form *Form, storage *storage.Storage, l *logger.Logger) *Ag
 			Capabilities: chartutil.DefaultCapabilities,
 			Log:          l.Printf,
 		},
+		K8sAgent: k8sAgent,
 	}
 }

+ 9 - 3
server/api/helpers_test.go

@@ -39,12 +39,16 @@ func (t *tester) reset() {
 }
 
 func (t *tester) createUserSession(email string, pw string) {
-	req, _ := http.NewRequest(
+	req, err := http.NewRequest(
 		"POST",
 		"/api/users",
 		strings.NewReader(`{"email":"`+email+`","password":"`+pw+`"}`),
 	)
 
+	if err != nil {
+		panic(err)
+	}
+
 	t.req = req
 	t.execute()
 
@@ -67,6 +71,7 @@ func newTester(canQuery bool) *tester {
 			TimeoutIdle:          time.Second * 15,
 			IsTesting:            true,
 			TokenGeneratorSecret: "secret",
+			BasicLoginEnabled:    true,
 		},
 		// unimportant here
 		Db: config.DBConf{},
@@ -79,15 +84,16 @@ func newTester(canQuery bool) *tester {
 	logger := lr.NewConsole(appConf.Debug)
 	repo := memory.NewRepository(canQuery)
 	store, _ := sessionstore.NewStore(repo, appConf.Server)
+	k8sAgent := kubernetes.GetAgentTesting()
 
 	app, _ := api.New(&api.AppConfig{
 		Logger:     logger,
 		Repository: repo,
 		ServerConf: appConf.Server,
 		TestAgents: &api.TestAgents{
-			HelmAgent:             helm.GetAgentTesting(&helm.Form{}, nil, logger),
+			HelmAgent:             helm.GetAgentTesting(&helm.Form{}, nil, logger, k8sAgent),
 			HelmTestStorageDriver: helm.StorageMap["memory"](nil, nil, ""),
-			K8sAgent:              kubernetes.GetAgentTesting(),
+			K8sAgent:              k8sAgent,
 		},
 	})
 

+ 5 - 1
server/api/project_handler_test.go

@@ -141,7 +141,11 @@ func TestHandleDeleteProject(t *testing.T) {
 // ------------------------- INITIALIZERS AND VALIDATORS ------------------------- //
 
 func initProject(tester *tester) {
-	user, _ := tester.repo.User.ReadUserByEmail("belanger@getporter.dev")
+	user, err := tester.repo.User.ReadUserByEmail("belanger@getporter.dev")
+
+	if err != nil {
+		panic(err)
+	}
 
 	// handle write to the database
 	projModel, _ := tester.repo.Project.CreateProject(&models.Project{

Some files were not shown because too many files changed in this diff