Skip to content

Commit

Permalink
Add mv command (#93)
Browse files Browse the repository at this point in the history
* Added new enum value BIN_MV to Bin enum in command.proto and updated corresponding Go file.

* Added arg function to builder struct

A new method 'arg' has been added to the builder struct. This method appends a given string value to the 'args' slice of the builder instance.

* Updated error messages in rm command

The error messages in the Create, Update, and Delete methods of the rm command were previously prefixed with "wget". This has been corrected to prefix them with "rm" instead.

* Added support for mv command in binPath function

The binPath function now includes a case for the 'mv' command. This allows the system to return "mv" when this particular binary is requested, expanding the range of commands supported by our provisioner service.

* Added 'mv' command functionality

A new file, mv.go, has been added to the cmd package. This file includes the implementation of a 'mv' command with various options such as backup, destination, directory, force and more. The MvArgs struct is defined to hold these options. Two methods Cmd() and ExpectedFiles() are implemented on this struct.

The Mv type is also introduced with Create(), Update(), and Delete() methods implementing respective interfaces from infer package.

Finally, the newly created 'mv' command is registered in provider.go by adding it to the list of inferred resources.

* WIP adding test

* Regen SDKs

* Refactor proto schema and add moved files

* Fix compilation errors

* Added property value matcher in tests

A new GomegaMatcher, 'havePropertyValue', has been added to the testing suite. This matcher checks if a given property has a specific value. Currently, it only supports string values. The implementation includes methods for matching, failure messages and negated failure messages.

* Added test for file move operation

A new test case has been added to the service tests. This test checks the functionality of moving a file from one location to another. It creates a temporary directory and a file within it, moves the file to a new location within the same directory, and then verifies that the move was successful by checking various conditions such as exit code, stdout content, created files list, moved files map and existence of old/new files. The temporary directory is cleaned up after each test run.

* Added file movement tracking in service creation

The service creation function now tracks not only the files it creates, but also those it moves. This is done by creating a map of source and destination paths for moved files. The existence of these paths is checked and logged before they are added to the map. The response from the create function now includes this map of moved files along with previously returned created files list.

* Updated argument handling in builder

Enhanced the 'arg' function within the builder struct to only append non-empty strings to the 'args' slice. This prevents unnecessary empty string entries, improving efficiency and cleanliness of code.

* Refactored test hooks in lifecycle tests

The hooks within the lifecycle tests have been restructured for better readability and maintainability. The changes include:
- Moved some hook functions to more appropriate locations within the code.
- Added new checks in certain hook functions to validate output properties and file contents.
- Removed redundant hook functions that were performing similar checks.

* Struct initializer

* Regen SDKs
  • Loading branch information
UnstoppableMango authored Aug 4, 2024
1 parent 77e047f commit 83b9513
Show file tree
Hide file tree
Showing 28 changed files with 2,057 additions and 247 deletions.
464 changes: 314 additions & 150 deletions gen/go/unmango/baremetal/v1alpha1/command.pb.go

Large diffs are not rendered by default.

26 changes: 18 additions & 8 deletions proto/unmango/baremetal/v1alpha1/command.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,38 +10,47 @@ service CommandService {

message CreateRequest {
Command command = 1;
repeated string expect_files = 2;
repeated string expect_created = 2;
map<string, string> expect_moved = 3;
}

message CreateResponse {
Result result = 1;
repeated string files = 2;
repeated string created_files = 2;
map<string, string> moved_files = 3;
}

message UpdateRequest {
Command command = 1;
repeated string expect_files = 2;
Operation create = 3;
repeated string expect_created = 2;
map<string, string> expect_moved = 3;
Operation create = 4;
}

message UpdateResponse {
Result result = 1;
repeated string files = 2;
optional Operation delete = 3;
repeated string created_files = 2;
map<string, string> moved_files = 3;
optional Operation delete = 4;
}

message DeleteRequest {
Operation create = 1;
repeated Operation updates = 2;
}

message DeleteResponse {
optional Operation op = 1;
optional Result result = 1;
optional Command command = 2;
repeated string created_files = 3;
map<string, string> moved_files = 4;
}

message Operation {
Result result = 1;
Command command = 2;
repeated string files = 3;
repeated string created_files = 3;
map<string, string> moved_files = 4;
}

message Command {
Expand All @@ -61,4 +70,5 @@ enum Bin {
BIN_TEE = 1;
BIN_RM = 2;
BIN_WGET = 3;
BIN_MV = 4;
}
6 changes: 6 additions & 0 deletions provider/pkg/provider/cmd/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ type builder struct {
args []string
}

func (b *builder) arg(value string) {
if value != "" {
b.args = append(b.args, value)
}
}

func (b *builder) op(input bool, name string) {
if input {
b.add(name)
Expand Down
30 changes: 15 additions & 15 deletions provider/pkg/provider/cmd/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,23 @@ func (s *CommandState[T]) Create(ctx context.Context, inputs T, preview bool) er

log.Debug("sending create request")
res, err := p.Create(ctx, &pb.CreateRequest{
Command: inputs.Cmd(),
ExpectFiles: inputs.ExpectedFiles(),
Command: inputs.Cmd(),
ExpectCreated: inputs.ExpectedFiles(),
})
if err != nil {
return fmt.Errorf("sending create request: %w", err)
}

if res.Files == nil {
if res.CreatedFiles == nil {
log.Debug("files was empty, this is probably a bug somewhere else")
res.Files = []string{}
res.CreatedFiles = []string{}
}

s.Args = inputs
s.ExitCode = int(res.Result.ExitCode)
s.Stdout = res.Result.Stdout
s.Stderr = res.Result.Stderr
s.CreatedFiles = res.Files
s.CreatedFiles = res.CreatedFiles

log.Info("create success")
return nil
Expand All @@ -72,11 +72,11 @@ func (s *CommandState[T]) Update(ctx context.Context, inputs T, preview bool) (C

log.Debug("sending update request")
res, err := p.Update(ctx, &pb.UpdateRequest{
Command: inputs.Cmd(),
ExpectFiles: inputs.ExpectedFiles(),
Command: inputs.Cmd(),
ExpectCreated: inputs.ExpectedFiles(),
Create: &pb.Operation{
Files: s.CreatedFiles,
Command: s.Args.Cmd(),
CreatedFiles: s.CreatedFiles,
Command: s.Args.Cmd(),
Result: &pb.Result{
ExitCode: int32(s.ExitCode),
Stdout: s.Stdout,
Expand All @@ -92,7 +92,7 @@ func (s *CommandState[T]) Update(ctx context.Context, inputs T, preview bool) (C
result.ExitCode = int(res.Result.ExitCode)
result.Stdout = res.Result.Stdout
result.Stderr = res.Result.Stderr
result.CreatedFiles = res.Files
result.CreatedFiles = res.CreatedFiles

log.Info("update success")
return result, nil
Expand All @@ -109,8 +109,8 @@ func (s *CommandState[T]) Delete(ctx context.Context) error {
log.Debug("sending delete request")
res, err := p.Delete(ctx, &pb.DeleteRequest{
Create: &pb.Operation{
Files: s.CreatedFiles,
Command: s.Args.Cmd(),
CreatedFiles: s.CreatedFiles,
Command: s.Args.Cmd(),
Result: &pb.Result{
ExitCode: int32(s.ExitCode),
Stdout: s.Stdout,
Expand All @@ -122,14 +122,14 @@ func (s *CommandState[T]) Delete(ctx context.Context) error {
return fmt.Errorf("sending delete request: %w", err)
}

if res.Op == nil {
if res.Command == nil {
log.Info("provisioner did not perform any operations")
return nil
}

if res.Op.Result.ExitCode > 0 {
if res.Result.ExitCode > 0 {
log.Error("provisioner returned a non-success status code")
return fmt.Errorf("delete operation failed exit code: %d", res.Op.Result.ExitCode)
return fmt.Errorf("delete operation failed exit code: %d", res.Result.ExitCode)
}

log.Info("delete success")
Expand Down
112 changes: 112 additions & 0 deletions provider/pkg/provider/cmd/mv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package cmd

import (
"context"
"fmt"
"path"

"github.com/pulumi/pulumi-go-provider/infer"
pb "github.com/unmango/pulumi-baremetal/gen/go/unmango/baremetal/v1alpha1"
)

type MvArgs struct {
Backup string `pulumi:"backup,optional"`
Destination string `pulumi:"destination,optional"`
Directory string `pulumi:"directory,optional"`
Force bool `pulumi:"force,optional"`
Help bool `pulumi:"help,optional"`
NoClobber bool `pulumi:"noClobber,optional"`
NoTargetDirectory bool `pulumi:"noTargetDirectory,optional"`
Source []string `pulumi:"source"`
StripTrailingSlashes bool `pulumi:"stripTrailingSlashes,optional"`
Suffix string `pulumi:"suffix,optional"`
TargetDirectory string `pulumi:"targetDirectory,optional"`
Update bool `pulumi:"update,optional"`
Verbose bool `pulumi:"verbose,optional"`
Version bool `pulumi:"version,optional"`
}

// Cmd implements CommandArgs.
func (m MvArgs) Cmd() *pb.Command {
b := builder{m.Source}
b.opv(m.Backup, "--backup")
b.op(m.Force, "--force")
b.op(m.NoClobber, "--no-clobber")
b.op(m.StripTrailingSlashes, "--strip-trailing-slashes")
b.opv(m.Suffix, "--suffix")
b.op(m.Update, "--update")
b.op(m.Verbose, "--verbose")
b.op(m.Version, "--version")

b.opv(m.TargetDirectory, "--target-directory")
b.op(m.NoTargetDirectory, "--no-target-directory")

b.arg(m.Destination)
b.arg(m.Directory)

return &pb.Command{
Bin: pb.Bin_BIN_MV,
Args: b.args,
}
}

// ExpectedFiles implements CommandArgs.
func (m MvArgs) ExpectedFiles() []string {
files := []string{}

mvSrc := func(d string) {
for _, f := range m.Source {
t := path.Join(d, path.Base(f))
files = append(files, t)
}
}

if m.Destination != "" {
files = append(files, m.Destination)
} else if m.Directory != "" {
mvSrc(m.Directory)
} else if m.TargetDirectory != "" {
mvSrc(m.TargetDirectory)
}

return files
}

var _ CommandArgs = MvArgs{}

type Mv struct{}

type MvState = CommandState[MvArgs]

// Create implements infer.CustomCreate.
func (Mv) Create(ctx context.Context, name string, inputs MvArgs, preview bool) (id string, output MvState, err error) {
state := MvState{}
if err := state.Create(ctx, inputs, preview); err != nil {
return name, state, fmt.Errorf("mv: %w", err)
}

return name, state, nil
}

// Update implements infer.CustomUpdate.
func (Mv) Update(ctx context.Context, id string, olds MvState, news MvArgs, preview bool) (MvState, error) {
state, err := olds.Update(ctx, news, preview)
if err != nil {
return olds, fmt.Errorf("mv: %w", err)
}

return state, nil
}

// Delete implements infer.CustomDelete.
func (Mv) Delete(ctx context.Context, id string, props MvState) error {
if err := props.Delete(ctx); err != nil {
return fmt.Errorf("mv: %w", err)
}

return nil
}

var _ = (infer.CustomCreate[MvArgs, MvState])((*Mv)(nil))
var _ = (infer.CustomUpdate[MvArgs, MvState])((*Mv)(nil))
var _ = (infer.CustomDelete[MvState])((*Mv)(nil))
6 changes: 3 additions & 3 deletions provider/pkg/provider/cmd/rm.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ type RmState = CommandState[RmArgs]
func (Rm) Create(ctx context.Context, name string, inputs RmArgs, preview bool) (id string, output RmState, err error) {
state := RmState{}
if err := state.Create(ctx, inputs, preview); err != nil {
return name, state, fmt.Errorf("wget: %w", err)
return name, state, fmt.Errorf("rm: %w", err)
}

return name, state, nil
Expand All @@ -58,7 +58,7 @@ func (Rm) Create(ctx context.Context, name string, inputs RmArgs, preview bool)
func (Rm) Update(ctx context.Context, id string, olds RmState, news RmArgs, preview bool) (RmState, error) {
state, err := olds.Update(ctx, news, preview)
if err != nil {
return olds, fmt.Errorf("wget: %w", err)
return olds, fmt.Errorf("rm: %w", err)
}

return state, nil
Expand All @@ -67,7 +67,7 @@ func (Rm) Update(ctx context.Context, id string, olds RmState, news RmArgs, prev
// Delete implements infer.CustomDelete.
func (Rm) Delete(ctx context.Context, id string, props RmState) error {
if err := props.Delete(ctx); err != nil {
return fmt.Errorf("wget: %w", err)
return fmt.Errorf("rm: %w", err)
}

return nil
Expand Down
4 changes: 1 addition & 3 deletions provider/pkg/provider/internal/provisioner/provisioner.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ type provisioner struct {

func New(conn *grpc.ClientConn) *provisioner {
cmd := pb.NewCommandServiceClient(conn)
return &provisioner{conn: conn,
CommandServiceClient: cmd,
}
return &provisioner{cmd, conn}
}

// Close implements io.Closer.
Expand Down
Loading

0 comments on commit 83b9513

Please sign in to comment.