diff --git a/cmd/azure/main.go b/cmd/azure/main.go index 18e37af..35b0455 100644 --- a/cmd/azure/main.go +++ b/cmd/azure/main.go @@ -2,28 +2,63 @@ package main import ( "bytes" + "context" + "fmt" "io" "os" + "runtime/debug" "get.porter.sh/plugin/azure/pkg/azure" + "get.porter.sh/porter/pkg/cli" "github.com/spf13/cobra" + "go.opentelemetry.io/otel/attribute" ) func main() { - in := getInput() - cmd := buildRootCommand(in) - if err := cmd.Execute(); err != nil { - os.Exit(1) + run := func() int { + ctx := context.Background() + m := azure.New() + ctx, err := m.ConfigureLogging(ctx) + if err != nil { + fmt.Println(err) + os.Exit(cli.ExitCodeErr) + } + cmd := buildRootCommand(m, getInput()) + + ctx, log := m.StartRootSpan(ctx, "azure") + defer func() { + // Capture panics and trace them + if panicErr := recover(); panicErr != nil { + log.Error(fmt.Errorf("%s", panicErr), + attribute.Bool("panic", true), + attribute.String("stackTrace", string(debug.Stack()))) + log.EndSpan() + m.Close() + os.Exit(cli.ExitCodeErr) + } else { + log.Close() + m.Close() + } + }() + + if err := cmd.ExecuteContext(ctx); err != nil { + return cli.ExitCodeErr + } + return cli.ExitCodeSuccess } + os.Exit(run()) } -func buildRootCommand(in io.Reader) *cobra.Command { - m := azure.New() - m.In = in - +func buildRootCommand(m *azure.Plugin, in io.Reader) *cobra.Command { cmd := &cobra.Command{ Use: "azure", Short: "Azure plugin for Porter", + PersistentPreRun: func(cmd *cobra.Command, args []string) { + // Enable swapping out stdout/stderr for testing + m.In = in + m.Out = cmd.OutOrStdout() + m.Err = cmd.OutOrStderr() + }, } cmd.AddCommand(buildVersionCommand(m)) @@ -31,7 +66,6 @@ func buildRootCommand(in io.Reader) *cobra.Command { return cmd } - func getInput() io.Reader { s, _ := os.Stdin.Stat() if (s.Mode() & os.ModeCharDevice) == 0 { diff --git a/pkg/azure/helpers.go b/pkg/azure/helpers.go index 7ae39a1..4cb1065 100644 --- a/pkg/azure/helpers.go +++ b/pkg/azure/helpers.go @@ -4,6 +4,7 @@ import ( "testing" "get.porter.sh/porter/pkg/portercontext" + "get.porter.sh/porter/pkg/runtime" ) type TestPlugin struct { @@ -16,7 +17,7 @@ func NewTestPlugin(t *testing.T) *TestPlugin { c := portercontext.NewTestContext(t) m := &TestPlugin{ Plugin: &Plugin{ - Context: c.Context, + RuntimeConfig: runtime.NewConfigFor(c.Context), }, TestContext: c, } diff --git a/pkg/azure/plugin.go b/pkg/azure/plugin.go index ce9ea9d..0a2ecef 100644 --- a/pkg/azure/plugin.go +++ b/pkg/azure/plugin.go @@ -6,20 +6,26 @@ import ( "io/ioutil" "get.porter.sh/plugin/azure/pkg/azure/azureconfig" - "get.porter.sh/porter/pkg/portercontext" + "get.porter.sh/porter/pkg/runtime" "github.com/pkg/errors" ) type Plugin struct { - *portercontext.Context + runtime.RuntimeConfig azureconfig.Config } // New azure plugin client, initialized with useful defaults. func New() *Plugin { - return &Plugin{ - Context: portercontext.New(), + p := &Plugin{ + RuntimeConfig: runtime.NewConfig(), } + + // Tell porter that we are running inside a plugin + p.IsInternalPlugin = true + p.InternalPluginKey = "porter.plugins.azure" + + return p } func (p *Plugin) LoadConfig() error { diff --git a/pkg/azure/plugin_test.go b/pkg/azure/plugin_test.go new file mode 100644 index 0000000..cede6c8 --- /dev/null +++ b/pkg/azure/plugin_test.go @@ -0,0 +1,13 @@ +package azure + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestNew(t *testing.T) { + p := New() + assert.True(t, p.IsInternalPlugin, "expected tracing to be configured as a plugin") + assert.Equal(t, "porter.plugins.azure", p.InternalPluginKey, "expected the plugin to have its on tracing service name") +}