Skip to content

Commit

Permalink
Apply proposal (knative#14)
Browse files Browse the repository at this point in the history
* WIP: Apply proposal

* fix build
  • Loading branch information
lionelvillard committed Oct 1, 2020
1 parent a566af4 commit 8a22ebf
Show file tree
Hide file tree
Showing 14 changed files with 452 additions and 29 deletions.
12 changes: 7 additions & 5 deletions pkg/components/eventing/sources/github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ package github
import (
"fmt"

"knative.dev/reconciler-test/pkg/manifest"

"knative.dev/reconciler-test/pkg/config"
"knative.dev/reconciler-test/pkg/framework"
)

const (
artifactURITemplate = "https://github.com/knative/eventing-contrib/releases/download/v%s/github.yaml"
artifactURLTemplate = "https://github.com/knative/eventing-contrib/releases/download/v%s/github.yaml"
)

var (
Expand All @@ -45,8 +47,8 @@ func (s *githubComponent) Required(rc framework.ResourceContext, cfg config.Conf
ghcfg := config.GetConfig(cfg, "components/eventing/sources/github").(GithubConfig)

// TODO: validate configuration

artifactURI := fmt.Sprintf(artifactURITemplate, ghcfg.Version)
rc.CreateFromURIOrFail(artifactURI, false)

// TODO: check cluster for existing source
artifactURL := fmt.Sprintf(artifactURLTemplate, ghcfg.Version)
rc.Logf("installing GitHubSource release ", ghcfg.Version)
rc.Apply(manifest.FromURL(artifactURL))
}
13 changes: 11 additions & 2 deletions pkg/components/sequencestepper/sequencestepper.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package sequencestepper
import (
corev1 "k8s.io/api/core/v1"
"knative.dev/reconciler-test/pkg/config"
"knative.dev/reconciler-test/pkg/manifest"

"knative.dev/reconciler-test/pkg/framework"
"knative.dev/reconciler-test/pkg/installer"
Expand All @@ -36,8 +37,16 @@ func Deploy(rc framework.ResourceContext) corev1.ObjectReference {
image := rc.ImageName(packageName)
name := helpers.AppendRandomString("seq-stepper")

rc.CreateFromYAMLOrFail(installer.ExecuteTemplate(podTemplate, map[string]interface{}{"Name": name, "Image": image}))
rc.CreateFromYAMLOrFail(installer.ExecuteTemplate(serviceTemplate, map[string]interface{}{"Name": name}))
data := struct {
Name string
Image string
}{
Name: name,
Image: image,
}

rc.Apply(manifest.FromString(podTemplate), data)
rc.Apply(manifest.FromString(serviceTemplate), data)

return corev1.ObjectReference{
Namespace: rc.Namespace(),
Expand Down
2 changes: 1 addition & 1 deletion pkg/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ import (
// Can be embedded by downstream projects.
type AllConfig struct {
framework.BaseConfig
Component components.ComponentConfig
Components components.ComponentConfig
}
144 changes: 128 additions & 16 deletions pkg/framework/resourcecontext.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@ package framework
import (
"context"
"encoding/json"
"errors"
"fmt"
"os"
"strings"
"time"

"knative.dev/reconciler-test/pkg/installer"

"knative.dev/reconciler-test/pkg/manifest"

"k8s.io/apimachinery/pkg/api/meta"
Expand All @@ -40,12 +43,60 @@ import (
type ResourceContext interface {
context.Context

// --- Context getters

// Namespace returns the current namespace
Namespace() string

// ImageName returns the image name corresponding to the given Go package name
ImageName(packageName string) string

// --- Context operations

// Apply applies the manifest returned by provider.
// When data is set, it instantiates the manifest template
// before applying it.
// When the manifest includes import path references, it
// builds them into Go binaries, containerizes them, publishes them,
// before applying it. Current limitation: can only be used with local, non-templated manifest.
//
// The test is marked as Fail when Apply fails
Apply(provider manifest.Provider, data ...interface{})

// ApplyOrError applies the manifest returned by provider. after
// When data is set, it instantiates the manifest template
// before applying it.
// When the manifest includes import path references, it
// builds them into Go binaries, containerizes them, publishes them,
// before applying it. Current limitation: can only be used with local, non-templated manifest.
//
// Returns an error when ApplyOrError fails
ApplyOrError(provider manifest.Provider, data ...interface{}) error

// Delete deletes the resources returned by provider.
// When data is set, it instantiates the manifest template
// before deleting it.
// The test is marked as Fail when Delete fails
Delete(provider manifest.Provider, data ...interface{})

// DeleteOrError deletes the resources returned by provider.
// When data is set, it instantiates the manifest template
// before deleting it.
// Returns an error when DeleteOrError fails
DeleteOrError(provider manifest.Provider, data ...interface{}) error

// --- Logging, Failures. Subset of testing.T

Helper()
Log(args ...interface{})
Logf(format string, args ...interface{})
Error(args ...interface{})
Errorf(format string, args ...interface{})
Fatal(args ...interface{})
Fatalf(format string, args ...interface{})

// --- Deprecation

// Create a resource from the given object (or fail)
CreateOrFail(obj runtime.Object)

Expand All @@ -62,22 +113,6 @@ type ResourceContext interface {
// 5. pathname = combination of all previous cases, the string can contain
// multiple records (file, directory or url) separated by comma
CreateFromURIOrFail(uri string, recursive bool)

// Delete deletes the resource specified in the given YAML
DeleteFromYAML(yaml string) error

// Delete deletes the resource specified in the given YAML (or fail)
DeleteFromYAMLOrFail(yaml string)

// TODO: Get, Update, Apply

// --- Failures. Subset of testing.T

Helper()
Error(args ...interface{})
Errorf(format string, args ...interface{})
Fatal(args ...interface{})
Fatalf(format string, args ...interface{})
}

// --- Default implementation
Expand All @@ -103,6 +138,75 @@ func (c *resourceContextImpl) ImageName(packageName string) string {
return fmt.Sprintf("%s/%s", repository, parts[len(parts)-1])
}

func (c *resourceContextImpl) Apply(provider manifest.Provider, data ...interface{}) {
c.Helper()
err := c.ApplyOrError(provider, data...)
if err != nil {
c.Fatal(err)
}
}

func (c *resourceContextImpl) ApplyOrError(provider manifest.Provider, data ...interface{}) error {
c.Helper()
path, err := provider.GetPath()
if err != nil {
return err
}

if len(data) > 0 {
path, err = installer.ParseTemplates(path, data)
if err != nil {
return err
}
}

// Attempt to run ko apply -f path
c.Logf("running ko apply -f %s\n", path)
o, err := installer.KoApply(path)
if err != nil {
// We care about the command output more than the exit code
c.Logf("running ko apply -f %s\n", path)

return errors.New(o)
}
return nil
}

// Delete deletes the resources returned by provider.
// The test is marked as Fail when Delete fails
func (c *resourceContextImpl) Delete(provider manifest.Provider, data ...interface{}) {
err := c.DeleteOrError(provider, data...)
if err != nil {
c.Fatal(err)
}
}

// DeleteOrError deletes the resources returned by provider.
// Returns an error when DeleteOrError fails
func (c *resourceContextImpl) DeleteOrError(provider manifest.Provider, data ...interface{}) error {
path, err := provider.GetPath()
if err != nil {
return err
}

if len(data) > 0 {
path, err = installer.ParseTemplates(path, data)
if err != nil {
return err
}
}

// Attempt to run ko delete -f path
o, err := installer.KoDelete(path)
if err != nil {
// We care about the command output more than the exit code
return errors.New(o)
}
return nil
}

// --- Deprecated

func (c *resourceContextImpl) CreateOrFail(obj runtime.Object) {
c.Helper()
gvr, _ := meta.UnsafeGuessKindToResource(obj.GetObjectKind().GroupVersionKind())
Expand Down Expand Up @@ -205,6 +309,14 @@ func (c *resourceContextImpl) Fatalf(format string, args ...interface{}) {
c.Errorf(format, args...)
}

func (c *resourceContextImpl) Log(args ...interface{}) {
fmt.Println(args...)
}

func (c *resourceContextImpl) Logf(format string, args ...interface{}) {
fmt.Printf(format, args...)
}

// --- context.Context

func (c *resourceContextImpl) Deadline() (deadline time.Time, ok bool) {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func (t *test) Run(fn func(TestContext)) {
}

// TODO: validate feature to match DNS-1123 label
namespace := helpers.AppendRandomString(strings.ToLower(t.feature))
namespace := helpers.AppendRandomString(strings.ToLower(t.t.Name()))
ctx := withInjection(context.Background())

tc := &testContextImpl{
Expand Down
44 changes: 44 additions & 0 deletions pkg/installer/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright 2020 The Knative Authors
*
* 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 installer

import (
"os"
"os/exec"
"strings"
)

// Helper functions to run shell commands.

func cmd(dir string, cmdLine string) *exec.Cmd {
cmdSplit := strings.Split(cmdLine, " ")
cmd := cmdSplit[0]
args := cmdSplit[1:]
c := exec.Command(cmd, args...)
c.Dir = dir
return c
}

func runCmd(cmdLine string) (string, error) {
dir, err := os.Getwd()
if err != nil {
return "", err
}
cmd := cmd(dir, cmdLine)

cmdOut, err := cmd.CombinedOutput()
return string(cmdOut), err
}
47 changes: 47 additions & 0 deletions pkg/installer/ko.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright 2020 The Knative Authors
*
* 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 installer

import (
"fmt"
)

// Use ko to publish the image.
func KoPublish(path string) (string, error) {
out, err := runCmd(fmt.Sprintf("ko publish %s", path))
if err != nil {
return "", err
}
return out, nil
}

// Use ko to apply filename
func KoApply(filename string) (string, error) {
out, err := runCmd(fmt.Sprintf("ko apply -f %s", filename))
if err != nil {
return out, err
}
return out, nil
}

// Use ko to delete filename
func KoDelete(filename string) (string, error) {
out, err := runCmd(fmt.Sprintf("ko delete -f %s", filename))
if err != nil {
return out, err
}
return out, nil
}
6 changes: 3 additions & 3 deletions pkg/installer/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (
// ParseTemplates walks through all the template yaml file in the given directory
// and produces instantiated yaml file in a temporary directory.
// Return the name of the temporary directory
func ParseTemplates(path string, config map[string]interface{}) string {
func ParseTemplates(path string, config interface{}) (string, error) {
dir, err := ioutil.TempDir("", "processed_yaml")
if err != nil {
panic(err)
Expand Down Expand Up @@ -59,9 +59,9 @@ func ParseTemplates(path string, config map[string]interface{}) string {
})
log.Print("new files in ", dir)
if err != nil {
panic(err)
return "", err
}
return dir
return dir, nil
}

// ExecuteTemplate instantiates the given template with data
Expand Down
Loading

0 comments on commit 8a22ebf

Please sign in to comment.