pull/31555/merge
Maxim Samoilov 3 days ago committed by GitHub
commit 8f554707df
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -16,9 +16,6 @@ limitations under the License.
package plugin
import (
"os"
"os/exec"
"path/filepath"
"testing"
extism "github.com/extism/go-sdk"
@ -29,34 +26,6 @@ import (
"github.com/stretchr/testify/require"
)
type pluginRaw struct {
Metadata Metadata
Dir string
}
func buildLoadExtismPlugin(t *testing.T, dir string) pluginRaw {
t.Helper()
pluginFile := filepath.Join(dir, PluginFileName)
metadataData, err := os.ReadFile(pluginFile)
require.NoError(t, err)
m, err := loadMetadata(metadataData)
require.NoError(t, err)
require.Equal(t, "extism/v1", m.Runtime, "expected plugin runtime to be extism/v1")
cmd := exec.Command("make", "-C", dir)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
require.NoError(t, cmd.Run(), "failed to build plugin in %q", dir)
return pluginRaw{
Metadata: *m,
Dir: dir,
}
}
func TestRuntimeConfigExtismV1Validate(t *testing.T) {
rc := RuntimeConfigExtismV1{}
err := rc.Validate()
@ -66,7 +35,7 @@ func TestRuntimeConfigExtismV1Validate(t *testing.T) {
func TestRuntimeExtismV1InvokePlugin(t *testing.T) {
r := RuntimeExtismV1{}
pr := buildLoadExtismPlugin(t, "testdata/src/extismv1-test")
pr := BuildLoadExtismPlugin(t, "testdata/src/extismv1-test")
require.Equal(t, "test/v1", pr.Metadata.Type)
p, err := r.CreatePlugin(pr.Dir, &pr.Metadata)

@ -0,0 +1,53 @@
/*
Copyright The Helm 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 plugin
import (
"os"
"os/exec"
"path/filepath"
"testing"
"github.com/stretchr/testify/require"
)
type RawPlugin struct {
Metadata Metadata
Dir string
}
func BuildLoadExtismPlugin(t *testing.T, dir string) RawPlugin {
t.Helper()
pluginFile := filepath.Join(dir, PluginFileName)
metadataData, err := os.ReadFile(pluginFile)
require.NoError(t, err)
m, err := loadMetadata(metadataData)
require.NoError(t, err)
require.Equal(t, "extism/v1", m.Runtime, "expected plugin runtime to be extism/v1")
cmd := exec.Command("make", "-C", dir)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
require.NoError(t, cmd.Run(), "failed to build plugin in %q", dir)
return RawPlugin{
Metadata: *m,
Dir: dir,
}
}

@ -255,7 +255,7 @@ func (r *SubprocessPluginRuntime) runPostrenderer(input *Input) (*Output, error)
go func() {
defer stdin.Close()
io.Copy(stdin, msg.Manifests)
io.Copy(stdin, bytes.NewBufferString(msg.Manifests))
}()
postRendered := &bytes.Buffer{}
@ -272,7 +272,7 @@ func (r *SubprocessPluginRuntime) runPostrenderer(input *Input) (*Output, error)
return &Output{
Message: schema.OutputMessagePostRendererV1{
Manifests: postRendered,
Manifests: postRendered.String(),
},
}, nil
}

@ -16,19 +16,15 @@ limitations under the License.
package schema
import (
"bytes"
)
// InputMessagePostRendererV1 implements Input.Message
type InputMessagePostRendererV1 struct {
Manifests *bytes.Buffer `json:"manifests"`
Manifests string `json:"manifests"`
// from CLI --post-renderer-args
ExtraArgs []string `json:"extraArgs"`
}
type OutputMessagePostRendererV1 struct {
Manifests *bytes.Buffer `json:"manifests"`
Manifests string `json:"manifests"`
}
type ConfigPostRendererV1 struct{}

@ -18,6 +18,7 @@ import (
"context"
"fmt"
"path/filepath"
"strings"
"helm.sh/helm/v4/internal/plugin/schema"
@ -64,9 +65,10 @@ func (r *postRendererPlugin) Run(renderedManifests *bytes.Buffer) (*bytes.Buffer
input := &plugin.Input{
Message: schema.InputMessagePostRendererV1{
ExtraArgs: r.args,
Manifests: renderedManifests,
Manifests: renderedManifests.String(),
},
}
output, err := r.plugin.Invoke(context.Background(), input)
if err != nil {
return nil, fmt.Errorf("failed to invoke post-renderer plugin %q: %w", r.plugin.Metadata().Name, err)
@ -76,9 +78,9 @@ func (r *postRendererPlugin) Run(renderedManifests *bytes.Buffer) (*bytes.Buffer
// If the binary returned almost nothing, it's likely that it didn't
// successfully render anything
if len(bytes.TrimSpace(outputMessage.Manifests.Bytes())) == 0 {
if len(strings.TrimSpace(outputMessage.Manifests)) == 0 {
return nil, fmt.Errorf("post-renderer %q produced empty output", r.plugin.Metadata().Name)
}
return outputMessage.Manifests, nil
return bytes.NewBufferString(outputMessage.Manifests), nil
}

@ -18,15 +18,37 @@ package postrenderer
import (
"bytes"
"path"
"runtime"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"helm.sh/helm/v4/internal/plugin"
"helm.sh/helm/v4/pkg/cli"
)
func buildLoadExtismPostRendererPlugin(t *testing.T, dir string, args ...string) PostRenderer {
t.Helper()
r := plugin.RuntimeExtismV1{}
pr := plugin.BuildLoadExtismPlugin(t, dir)
require.Equal(t, "postrenderer/v1", pr.Metadata.Type)
p, err := r.CreatePlugin(pr.Dir, &pr.Metadata)
assert.NoError(t, err, "expected no error creating plugin")
assert.NotNil(t, p, "expected plugin to be created")
s := cli.New()
s.PluginsDirectory = path.Dir(p.Dir())
renderer, err := NewPostRendererPlugin(s, p.Metadata().Name, args...)
require.NoError(t, err)
return renderer
}
func TestNewPostRenderPluginRunWithNoOutput(t *testing.T) {
if runtime.GOOS == "windows" {
// the actual Run test uses a basic sed example, so skip this test on windows
@ -59,7 +81,7 @@ func TestNewPostRenderPluginWithOneArgsRun(t *testing.T) {
output, err := renderer.Run(bytes.NewBufferString("FOOTEST"))
is.NoError(err)
is.Contains(output.String(), "ARG1")
is.Contains(output, "ARG1")
}
func TestNewPostRenderPluginWithTwoArgsRun(t *testing.T) {
@ -77,5 +99,32 @@ func TestNewPostRenderPluginWithTwoArgsRun(t *testing.T) {
output, err := renderer.Run(bytes.NewBufferString("FOOTEST"))
is.NoError(err)
is.Contains(output.String(), "ARG1 ARG2")
is.Contains(output, "ARG1 ARG2")
}
func TestExtismPostRenderPluginRunWithNoArgsRun(t *testing.T) {
is := assert.New(t)
renderer := buildLoadExtismPostRendererPlugin(t, "testdata/plugins/extismv1-str-replace")
output, err := renderer.Run(bytes.NewBufferString("FOOTEST"))
is.NoError(err)
is.Equal(output, "BARTEST")
}
func TestExtismPostRenderPluginWithOneArgsRun(t *testing.T) {
is := assert.New(t)
renderer := buildLoadExtismPostRendererPlugin(t, "testdata/plugins/extismv1-str-replace", "ARG1")
output, err := renderer.Run(bytes.NewBufferString("FOOTEST"))
is.NoError(err)
is.Equal(output, "ARG1")
}
func TestExtismPostRenderPluginWithTwoArgsRun(t *testing.T) {
is := assert.New(t)
renderer := buildLoadExtismPostRendererPlugin(t, "testdata/plugins/extismv1-str-replace", "ARG1", "ARG2")
output, err := renderer.Run(bytes.NewBufferString("FOOTEST"))
is.NoError(err)
is.Equal(output, "ARG1 ARG2")
}

@ -0,0 +1,11 @@
.DEFAULT: build
.PHONY: build test vet
.PHONY: plugin.wasm
plugin.wasm:
GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o plugin.wasm .
build: plugin.wasm
vet:
GOOS=wasip1 GOARCH=wasm go vet ./...

@ -0,0 +1,10 @@
module helm.sh/helm/v4/pkg/postrenderer/testdata/plugins/postrenderer-v1-extism
go 1.25.0
require (
github.com/extism/go-pdk v1.1.3
helm.sh/helm/v4 v4.0.0
)
replace helm.sh/helm/v4 => ../../../../..

@ -0,0 +1,2 @@
github.com/extism/go-pdk v1.1.3 h1:hfViMPWrqjN6u67cIYRALZTZLk/enSPpNKa+rZ9X2SQ=
github.com/extism/go-pdk v1.1.3/go.mod h1:Gz+LIU/YCKnKXhgge8yo5Yu1F/lbv7KtKFkiCSzW/P4=

@ -0,0 +1,51 @@
package main
import (
"fmt"
"strings"
pdk "github.com/extism/go-pdk"
"helm.sh/helm/v4/internal/plugin/schema"
)
func RunPlugin() error {
var input schema.InputMessagePostRendererV1
if err := pdk.InputJSON(&input); err != nil {
return fmt.Errorf("failed to parse input json: %w", err)
}
replacement := "BARTEST"
if len(input.ExtraArgs) > 0 {
replacement = strings.Join(input.ExtraArgs, " ")
}
updatedManifests := strings.ReplaceAll(input.Manifests, "FOOTEST", replacement)
result := schema.OutputMessagePostRendererV1{
Manifests: updatedManifests,
}
if err := pdk.OutputJSON(&result); err != nil {
return fmt.Errorf("failed to write output json: %w", err)
}
return nil
}
//go:wasmexport helm_plugin_main
func HelmChartRenderer() uint64 {
pdk.Log(pdk.LogDebug, "running postrenderer-v1-extism plugin")
if err := RunPlugin(); err != nil {
pdk.Log(pdk.LogError, err.Error())
pdk.SetError(err)
return 1
}
return 0
}
func main() {}

@ -0,0 +1,5 @@
name: extismv1-str-replace
version: 1.2.3
type: postrenderer/v1
apiVersion: v1
runtime: extism/v1
Loading…
Cancel
Save