Skip to content

Commit

Permalink
Merge pull request #21 from pulumi/iwahbe/remote-file-copy
Browse files Browse the repository at this point in the history
Add Remote FileCopy
  • Loading branch information
iwahbe authored Dec 16, 2021
2 parents 03b703b + 26ce495 commit cb10cd8
Show file tree
Hide file tree
Showing 38 changed files with 1,265 additions and 352 deletions.
16 changes: 14 additions & 2 deletions examples/ec2_remote/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,29 @@ const hostname = new remote.Command("hostname", {
create: "hostname",
});

const remotePrivateIP = new remote.Command("remotePrivateIP", {
new remote.Command("remotePrivateIP", {
connection,
create: interpolate`echo ${server.privateIp} > private_ip.txt`,
delete: `rm private_ip.txt`,
}, { deleteBeforeReplace: true });

const localPrivateIP = new local.Command("localPrivateIP", {
new local.Command("localPrivateIP", {
create: interpolate`echo ${server.privateIp} > private_ip.txt`,
delete: `rm private_ip.txt`,
}, { deleteBeforeReplace: true });

const sizeFile = new remote.CopyFile("size", {
connection,
localPath: "./size.ts",
remotePath: "size.ts",
})

const catSize = new remote.Command("checkSize", {
connection,
create: "cat size.ts",
}, { dependsOn: sizeFile })

export const confirmSize = catSize.stdout;
export const publicIp = server.publicIp;
export const publicHostName = server.publicDns;
export const hostnameStdout = hostname.stdout;
2 changes: 1 addition & 1 deletion examples/ec2_remote/size.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const size = "t2.nano";
export const size = "t2.nano";
49 changes: 46 additions & 3 deletions provider/cmd/pulumi-resource-command/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"properties": {
"user": {
"type": "string",
"descripton": "The user that we should use for the connection. Defaults to `root`."
"descripton": "The user that we should use for the connection.",
"default": "root"
},
"password": {
"type": "string",
Expand All @@ -20,7 +21,8 @@
},
"port": {
"type": "number",
"description": "The port to connect to. Defaults to 22."
"description": "The port to connect to.",
"default": 22
},
"privateKey": {
"type": "string",
Expand Down Expand Up @@ -154,7 +156,7 @@
],
"inputProperties": {
"connection": {
"description": "The parameters with which to connect to the remote host",
"description": "The parameters with which to connect to the remote host.",
"$ref": "#/types/command:remote:Connection"
},
"environment": {
Expand All @@ -180,6 +182,47 @@
"requiredInputs": [
"connection"
]
},
"command:remote:CopyFile": {
"description": "Copy a local file to a remote host.",
"inputProperties": {
"connection": {
"description": "The parameters with which to connect to the remote host.",
"$ref": "#/types/command:remote:Connection"
},
"localPath": {
"description": "The path of the file to be copied.",
"type": "string"
},
"remotePath": {
"description": "The destination path in the remote host.",
"type": "string"
}
},
"requiredInputs": [
"connection",
"localPath",
"remotePath"
],
"properties": {
"connection": {
"description": "The parameters with which to connect to the remote host.",
"$ref": "#/types/command:remote:Connection"
},
"localPath": {
"description": "The path of the file to be copied.",
"type": "string"
},
"remotePath": {
"description": "The destination path in the remote host.",
"type": "string"
}
},
"required": [
"connection",
"localPath",
"remotePath"
]
}
},
"language": {
Expand Down
5 changes: 3 additions & 2 deletions provider/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ go 1.16

require (
github.com/golang/protobuf v1.5.2
github.com/pulumi/pulumi/pkg/v3 v3.9.1
github.com/pulumi/pulumi/sdk/v3 v3.9.1
github.com/pkg/sftp v1.13.4 // indirect
github.com/pulumi/pulumi/pkg/v3 v3.19.0
github.com/pulumi/pulumi/sdk/v3 v3.19.0
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e
google.golang.org/grpc v1.37.0
)
100 changes: 93 additions & 7 deletions provider/go.sum

Large diffs are not rendered by default.

94 changes: 65 additions & 29 deletions provider/pkg/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,17 @@ func (k *commandProvider) StreamInvoke(req *pulumirpc.InvokeRequest, server pulu
return fmt.Errorf("unknown StreamInvoke token %q", tok)
}

func check(urn resource.URN) error {
ty := urn.Type()
valid := []string{"local:Command", "remote:Command", "remote:CopyFile"}
for _, v := range valid {
if "command:"+v == string(ty) {
return nil
}
}
return fmt.Errorf("unknown resource type %q", ty)
}

// Check validates that the given property bag is valid for a resource of the given type and returns
// the inputs that should be passed to successive calls to Diff, Create, or Update for this
// resource. As a rule, the provider inputs returned by a call to Check should preserve the original
Expand All @@ -95,19 +106,17 @@ func (k *commandProvider) StreamInvoke(req *pulumirpc.InvokeRequest, server pulu
// the provider inputs are using for detecting and rendering diffs.
func (k *commandProvider) Check(ctx context.Context, req *pulumirpc.CheckRequest) (*pulumirpc.CheckResponse, error) {
urn := resource.URN(req.GetUrn())
ty := urn.Type()
if ty != "command:local:Command" && ty != "command:remote:Command" {
return nil, fmt.Errorf("unknown resource type %q", ty)
if err := check(urn); err != nil {
return nil, err
}
return &pulumirpc.CheckResponse{Inputs: req.News, Failures: nil}, nil
}

// Diff checks what impacts a hypothetical update will have on the resource's properties.
func (k *commandProvider) Diff(ctx context.Context, req *pulumirpc.DiffRequest) (*pulumirpc.DiffResponse, error) {
urn := resource.URN(req.GetUrn())
ty := urn.Type()
if ty != "command:local:Command" && ty != "command:remote:Command" {
return nil, fmt.Errorf("unknown resource type %q", ty)
if err := check(urn); err != nil {
return nil, err
}

olds, err := plugin.UnmarshalProperties(req.GetOlds(), plugin.MarshalOptions{KeepUnknowns: true, SkipNulls: true})
Expand All @@ -120,21 +129,21 @@ func (k *commandProvider) Diff(ctx context.Context, req *pulumirpc.DiffRequest)
return nil, err
}

d := olds.Diff(news)
changes := pulumirpc.DiffResponse_DIFF_NONE
var replaces []string
// TODO: Non-replace changes
for _, replaceKey := range []string{"environment", "dir", "interpreter", "create", "connection"} {
i := sort.SearchStrings(req.IgnoreChanges, replaceKey)
if i < len(req.IgnoreChanges) && req.IgnoreChanges[i] == replaceKey {
continue
}
if d.Changed(resource.PropertyKey(replaceKey)) {
changes = pulumirpc.DiffResponse_DIFF_SOME
replaces = append(replaces, replaceKey)
replaces := []string{}
if d := olds.Diff(news); d != nil {
// TODO: Non-replace changes
for _, replaceKey := range []string{"environment", "dir", "interpreter", "create", "connection", "localPath", "remotePath"} {
i := sort.SearchStrings(req.IgnoreChanges, replaceKey)
if i < len(req.IgnoreChanges) && req.IgnoreChanges[i] == replaceKey {
continue
}
if d.Changed(resource.PropertyKey(replaceKey)) {
changes = pulumirpc.DiffResponse_DIFF_SOME
replaces = append(replaces, replaceKey)
}
}
}

// TODO: Detailed diffs

return &pulumirpc.DiffResponse{
Expand All @@ -149,8 +158,8 @@ func (k *commandProvider) Create(ctx context.Context, req *pulumirpc.CreateReque
defer k.removeContext(ctx)
urn := resource.URN(req.GetUrn())
ty := urn.Type()
if ty != "command:local:Command" && ty != "command:remote:Command" {
return nil, fmt.Errorf("unknown resource type %q", ty)
if err := check(urn); err != nil {
return nil, err
}

inputProps, err := plugin.UnmarshalProperties(req.GetProperties(), plugin.MarshalOptions{KeepUnknowns: true, SkipNulls: true})
Expand Down Expand Up @@ -195,6 +204,22 @@ func (k *commandProvider) Create(ctx context.Context, req *pulumirpc.CreateReque
if err != nil {
return nil, err
}
case "command:remote:CopyFile":
var cpf remotefilecopy
err = mapper.MapI(inputs, &cpf)
if err != nil {
return nil, err
}

id, err = cpf.RunCreate(ctx, k.host, urn)
if err != nil {
return nil, err
}

outputs, err = mapper.New(&mapper.Opts{IgnoreMissing: true, IgnoreUnrecognized: true}).Encode(cpf)
if err != nil {
return nil, err
}
}

outputProperties, err := plugin.MarshalProperties(
Expand All @@ -215,9 +240,8 @@ func (k *commandProvider) Read(ctx context.Context, req *pulumirpc.ReadRequest)
ctx = k.addContext(ctx)
defer k.removeContext(ctx)
urn := resource.URN(req.GetUrn())
ty := urn.Type()
if ty != "command:local:Command" && ty != "command:remote:Command" {
return nil, fmt.Errorf("unknown resource type '%q'", ty)
if err := check(urn); err != nil {
return nil, err
}

return &pulumirpc.ReadResponse{
Expand All @@ -233,8 +257,8 @@ func (k *commandProvider) Update(ctx context.Context, req *pulumirpc.UpdateReque
defer k.removeContext(ctx)
urn := resource.URN(req.GetUrn())
ty := urn.Type()
if ty != "command:local:Command" && ty != "command:remote:Command" {
return nil, fmt.Errorf("unknown resource type %q", ty)
if err := check(urn); err != nil {
return nil, err
}

// Our Random resource will never be updated - if there is a diff, it will be a replacement.
Expand All @@ -248,8 +272,8 @@ func (k *commandProvider) Delete(ctx context.Context, req *pulumirpc.DeleteReque
defer k.removeContext(ctx)
urn := resource.URN(req.GetUrn())
ty := urn.Type()
if ty != "command:local:Command" && ty != "command:remote:Command" {
return nil, fmt.Errorf("unknown resource type %q", ty)
if err := check(urn); err != nil {
return nil, err
}

inputProps, err := plugin.UnmarshalProperties(req.GetProperties(), plugin.MarshalOptions{KeepUnknowns: true, SkipNulls: true})
Expand All @@ -258,10 +282,12 @@ func (k *commandProvider) Delete(ctx context.Context, req *pulumirpc.DeleteReque
}
inputs := inputProps.Mappable()

decoder := mapper.New(&mapper.Opts{IgnoreMissing: true, IgnoreUnrecognized: true})

switch ty {
case "command:local:Command":
var cmd command
err = mapper.New(&mapper.Opts{IgnoreMissing: true, IgnoreUnrecognized: true}).Decode(inputs, &cmd)
err = decoder.Decode(inputs, &cmd)
if err != nil {
return nil, err
}
Expand All @@ -272,7 +298,7 @@ func (k *commandProvider) Delete(ctx context.Context, req *pulumirpc.DeleteReque
}
case "command:remote:Command":
var cmd remotecommand
err = mapper.New(&mapper.Opts{IgnoreMissing: true, IgnoreUnrecognized: true}).Decode(inputs, &cmd)
err = decoder.Decode(inputs, &cmd)
if err != nil {
return nil, err
}
Expand All @@ -281,6 +307,16 @@ func (k *commandProvider) Delete(ctx context.Context, req *pulumirpc.DeleteReque
if err != nil {
return nil, err
}
case "command:remote:CopyFile":
var cpf remotefilecopy
err = decoder.Decode(inputs, &cpf)
if err != nil {
return nil, err
}
err = cpf.RunDelete(ctx, k.host, urn)
if err != nil {
return nil, err
}
}

return &pbempty.Empty{}, nil
Expand Down
Loading

0 comments on commit cb10cd8

Please sign in to comment.