Skip to content

Commit

Permalink
Support custom updates on commands (#149)
Browse files Browse the repository at this point in the history
* Support custom updates on commands

* Regen SDKs
  • Loading branch information
UnstoppableMango authored Aug 18, 2024
1 parent ec96fa1 commit b123366
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 3 deletions.
53 changes: 51 additions & 2 deletions provider/pkg/provider/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

type CommandArgs struct {
Create []string `pulumi:"create"`
Update []string `pulumi:"update,optional"`
Delete []string `pulumi:"delete,optional"`
Triggers []any `pulumi:"triggers,optional"`
}
Expand Down Expand Up @@ -70,14 +71,61 @@ func (Command) Create(ctx context.Context, name string, inputs CommandArgs, prev
return name, state, nil
}

// Update implements infer.CustomUpdate.
func (Command) Update(ctx context.Context, id string, olds CommandState, news CommandArgs, preview bool) (CommandState, error) {
log := logger.FromContext(ctx)
state := CommandState{
CommandArgs: olds.CommandArgs,
ExitCode: olds.ExitCode,
Stdout: olds.Stdout,
Stderr: olds.Stderr,
}

p, err := provisioner.FromContext(ctx)
if err != nil {
log.Error("Failed creating provisioner")
return state, fmt.Errorf("creating provisioner: %w", err)
}

if preview {
if _, err = p.Ping(ctx, &pb.PingRequest{}); err != nil {
log.WarningStatusf("Failed pinging provisioner: %s", err)
}

return state, nil
}

display := display(news.Update)
log.DebugStatus("Sending exec request to provisioner")
res, err := p.Exec(ctx, &pb.ExecRequest{
Args: news.Update,
})
if err != nil {
log.Errorf("command:%s %s", display, err)
return state, fmt.Errorf("sending exec request: %w", err)
}

if res.Result.ExitCode > 0 {
log.Error(display)
return state, fmt.Errorf("exec failed: %s", res.Result)
}

state.CommandArgs = news
state.ExitCode = int(res.Result.ExitCode)
state.Stdout = res.Result.Stdout
state.Stderr = res.Result.Stderr

log.InfoStatus(display)
return state, nil
}

// Delete implements infer.CustomDelete.
func (Command) Delete(ctx context.Context, id string, props CommandState) error {
log := logger.FromContext(ctx)
log.Error("WTF MAN")
if len(props.Delete) == 0 {
log.DebugStatus("No custom delete provided")
return nil
}
log.Error("WTF MAN2")

p, err := provisioner.FromContext(ctx)
if err != nil {
Expand Down Expand Up @@ -105,6 +153,7 @@ func (Command) Delete(ctx context.Context, id string, props CommandState) error
}

var _ = (infer.CustomCreate[CommandArgs, CommandState])((*Command)(nil))
var _ = (infer.CustomUpdate[CommandArgs, CommandState])((*Command)(nil))
var _ = (infer.CustomDelete[CommandState])((*Command)(nil))

func display(args []string) string {
Expand Down
11 changes: 11 additions & 0 deletions sdk/dotnet/Command.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ public partial class Command : global::Pulumi.CustomResource
[Output("triggers")]
public Output<ImmutableArray<object>> Triggers { get; private set; } = null!;

[Output("update")]
public Output<ImmutableArray<string>> Update { get; private set; } = null!;


/// <summary>
/// Create a Command resource with the given unique name, arguments, and options.
Expand Down Expand Up @@ -101,6 +104,14 @@ public InputList<object> Triggers
set => _triggers = value;
}

[Input("update")]
private InputList<string>? _update;
public InputList<string> Update
{
get => _update ?? (_update = new InputList<string>());
set => _update = value;
}

public CommandArgs()
{
}
Expand Down
7 changes: 7 additions & 0 deletions sdk/go/baremetal/command.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions sdk/go/baremetal/x/command.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions sdk/nodejs/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export class Command extends pulumi.CustomResource {
public /*out*/ readonly stderr!: pulumi.Output<string>;
public /*out*/ readonly stdout!: pulumi.Output<string>;
public readonly triggers!: pulumi.Output<any[] | undefined>;
public readonly update!: pulumi.Output<string[] | undefined>;

/**
* Create a Command resource with the given unique name, arguments, and options.
Expand All @@ -55,6 +56,7 @@ export class Command extends pulumi.CustomResource {
resourceInputs["create"] = args ? args.create : undefined;
resourceInputs["delete"] = args ? args.delete : undefined;
resourceInputs["triggers"] = args ? args.triggers : undefined;
resourceInputs["update"] = args ? args.update : undefined;
resourceInputs["exitCode"] = undefined /*out*/;
resourceInputs["stderr"] = undefined /*out*/;
resourceInputs["stdout"] = undefined /*out*/;
Expand All @@ -65,6 +67,7 @@ export class Command extends pulumi.CustomResource {
resourceInputs["stderr"] = undefined /*out*/;
resourceInputs["stdout"] = undefined /*out*/;
resourceInputs["triggers"] = undefined /*out*/;
resourceInputs["update"] = undefined /*out*/;
}
opts = pulumi.mergeOptions(utilities.resourceOptsDefaults(), opts);
super(Command.__pulumiType, name, resourceInputs, opts);
Expand All @@ -78,4 +81,5 @@ export interface CommandArgs {
create: pulumi.Input<pulumi.Input<string>[]>;
delete?: pulumi.Input<pulumi.Input<string>[]>;
triggers?: pulumi.Input<any[]>;
update?: pulumi.Input<pulumi.Input<string>[]>;
}
23 changes: 22 additions & 1 deletion sdk/python/unmango_baremetal/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ class CommandArgs:
def __init__(__self__, *,
create: pulumi.Input[Sequence[pulumi.Input[str]]],
delete: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]] = None,
triggers: Optional[pulumi.Input[Sequence[Any]]] = None):
triggers: Optional[pulumi.Input[Sequence[Any]]] = None,
update: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]] = None):
"""
The set of arguments for constructing a Command resource.
"""
Expand All @@ -25,6 +26,8 @@ def __init__(__self__, *,
pulumi.set(__self__, "delete", delete)
if triggers is not None:
pulumi.set(__self__, "triggers", triggers)
if update is not None:
pulumi.set(__self__, "update", update)

@property
@pulumi.getter
Expand Down Expand Up @@ -53,6 +56,15 @@ def triggers(self) -> Optional[pulumi.Input[Sequence[Any]]]:
def triggers(self, value: Optional[pulumi.Input[Sequence[Any]]]):
pulumi.set(self, "triggers", value)

@property
@pulumi.getter
def update(self) -> Optional[pulumi.Input[Sequence[pulumi.Input[str]]]]:
return pulumi.get(self, "update")

@update.setter
def update(self, value: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]]):
pulumi.set(self, "update", value)


class Command(pulumi.CustomResource):
@overload
Expand All @@ -62,6 +74,7 @@ def __init__(__self__,
create: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]] = None,
delete: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]] = None,
triggers: Optional[pulumi.Input[Sequence[Any]]] = None,
update: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]] = None,
__props__=None):
"""
Create a Command resource with the given unique name, props, and options.
Expand Down Expand Up @@ -94,6 +107,7 @@ def _internal_init(__self__,
create: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]] = None,
delete: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]] = None,
triggers: Optional[pulumi.Input[Sequence[Any]]] = None,
update: Optional[pulumi.Input[Sequence[pulumi.Input[str]]]] = None,
__props__=None):
opts = pulumi.ResourceOptions.merge(_utilities.get_resource_opts_defaults(), opts)
if not isinstance(opts, pulumi.ResourceOptions):
Expand All @@ -108,6 +122,7 @@ def _internal_init(__self__,
__props__.__dict__["create"] = create
__props__.__dict__["delete"] = delete
__props__.__dict__["triggers"] = triggers
__props__.__dict__["update"] = update
__props__.__dict__["exit_code"] = None
__props__.__dict__["stderr"] = None
__props__.__dict__["stdout"] = None
Expand Down Expand Up @@ -139,6 +154,7 @@ def get(resource_name: str,
__props__.__dict__["stderr"] = None
__props__.__dict__["stdout"] = None
__props__.__dict__["triggers"] = None
__props__.__dict__["update"] = None
return Command(resource_name, opts=opts, __props__=__props__)

@property
Expand Down Expand Up @@ -171,3 +187,8 @@ def stdout(self) -> pulumi.Output[str]:
def triggers(self) -> pulumi.Output[Optional[Sequence[Any]]]:
return pulumi.get(self, "triggers")

@property
@pulumi.getter
def update(self) -> pulumi.Output[Optional[Sequence[str]]]:
return pulumi.get(self, "update")

38 changes: 38 additions & 0 deletions tests/lifecycle/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,42 @@ var _ = Describe("Command", func() {

Expect(provisioner).NotTo(ContainFile(ctx, expectedFile))
})

It("should execute custom update", func(ctx context.Context) {
expectedFile := "/tmp/custom-update-test.txt"

run(server, integration.LifeCycleTest{
Resource: resource,
Create: integration.Operation{
Inputs: pr.NewPropertyMapFromMap(map[string]interface{}{
"create": []string{"touch", expectedFile},
"update": []string{"rm", expectedFile},
"triggers": []string{"a"},
}),
Hook: func(inputs, output pr.PropertyMap) {
Expect(output["stderr"]).To(HavePropertyValue(""))
Expect(output["stdout"]).To(HavePropertyValue(""))
Expect(output["exitCode"]).To(HavePropertyValue(0))
Expect(output["create"]).To(Equal(inputs["create"]))
Expect(output["delete"]).To(Equal(inputs["delete"]))
},
},
Updates: []integration.Operation{{
Inputs: pr.NewPropertyMapFromMap(map[string]interface{}{
"create": []string{"touch", expectedFile},
"update": []string{"rm", expectedFile},
"triggers": []string{"b"},
}),
Hook: func(inputs, output pr.PropertyMap) {
Expect(output["stderr"]).To(HavePropertyValue(""))
Expect(output["stdout"]).To(HavePropertyValue(""))
Expect(output["exitCode"]).To(HavePropertyValue(0))
Expect(output["create"]).To(Equal(inputs["create"]))
Expect(output["delete"]).To(Equal(inputs["delete"]))
},
}},
})

Expect(provisioner).NotTo(ContainFile(ctx, expectedFile))
})
})

0 comments on commit b123366

Please sign in to comment.