-
Notifications
You must be signed in to change notification settings - Fork 46
Add support for using goss to target Windows #39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,8 +19,12 @@ import ( | |
| "github.com/hashicorp/packer/template/interpolate" | ||
| ) | ||
|
|
||
| const gossSpecFile = "/tmp/goss-spec.yaml" | ||
| const gossDebugSpecFile = "/tmp/debug-goss-spec.yaml" | ||
| const ( | ||
| gossSpecFile = "/tmp/goss-spec.yaml" | ||
| gossDebugSpecFile = "/tmp/debug-goss-spec.yaml" | ||
| linux = "Linux" | ||
| windows = "Windows" | ||
| ) | ||
|
|
||
| // GossConfig holds the config data coming in from the packer template | ||
| type GossConfig struct { | ||
|
|
@@ -33,6 +37,7 @@ type GossConfig struct { | |
| Password string | ||
| SkipInstall bool | ||
| Inspect bool | ||
| TargetOs string | ||
|
|
||
| // An array of tests to run. | ||
| Tests []string | ||
|
|
@@ -126,20 +131,31 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { | |
| p.config.Arch = "amd64" | ||
| } | ||
|
|
||
| if p.config.TargetOs == "" { | ||
| p.config.TargetOs = linux | ||
| } | ||
|
|
||
| if p.config.URL == "" { | ||
| p.config.URL = fmt.Sprintf( | ||
| "https://github.com/aelsabbahy/goss/releases/download/v%s/goss-linux-%s", | ||
| p.config.Version, p.config.Arch) | ||
| p.config.URL = p.getDownloadUrl() | ||
| } | ||
|
|
||
| if p.config.DownloadPath == "" { | ||
| os := strings.ToLower(p.config.TargetOs) | ||
| if p.config.URL == "" { | ||
| p.config.DownloadPath = fmt.Sprintf("/tmp/goss-%s-linux-%s", p.config.Version, p.config.Arch) | ||
| p.config.DownloadPath = fmt.Sprintf("/tmp/goss-%s-%s-%s", p.config.Version, os, p.config.Arch) | ||
| } else { | ||
| list := strings.Split(p.config.URL, "/") | ||
| arch := strings.Split(list[len(list)-1], "-")[2] | ||
|
|
||
| file := strings.Split(list[len(list)-1], "-") | ||
| arch := file[2] | ||
| if p.isGossAlpha() { | ||
| // The format of the alpha files includes an additional entry | ||
| // ex: goss-alpha-windows-amd64.exe | ||
| arch = file[3] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the comment confused me at first (I thought maybe this was only to support windows with the |
||
| } | ||
|
|
||
| version := strings.TrimPrefix(list[len(list)-2], "v") | ||
| p.config.DownloadPath = fmt.Sprintf("/tmp/goss-%s-linux-%s", version, arch) | ||
| p.config.DownloadPath = fmt.Sprintf("/tmp/goss-%s-%s-%s", version, os, arch) | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -202,6 +218,11 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { | |
| } | ||
| } | ||
|
|
||
| if p.config.TargetOs != linux && p.config.TargetOs != windows { | ||
| errs = packer.MultiErrorAppend(errs, | ||
| fmt.Errorf("Os must be %s or %s", linux, windows)) | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
|
|
||
| if errs != nil && len(errs.Errors) > 0 { | ||
| return errs | ||
| } | ||
|
|
@@ -212,6 +233,12 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { | |
| // Provision runs the Goss Provisioner | ||
| func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, generatedData map[string]interface{}) error { | ||
| ui.Say("Provisioning with Goss") | ||
| ui.Say(fmt.Sprintf("Configured to run on %s", string(p.config.TargetOs))) | ||
|
|
||
| // For Windows need to create the target directory before download | ||
| if err := p.createDir(ui, comm, p.config.RemotePath); err != nil { | ||
| return fmt.Errorf("Error creating remote directory: %s", err) | ||
| } | ||
|
|
||
| if !p.config.SkipInstall { | ||
| if err := p.installGoss(ui, comm); err != nil { | ||
|
|
@@ -222,10 +249,6 @@ func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.C | |
| } | ||
|
|
||
| ui.Say("Uploading goss tests...") | ||
| if err := p.createDir(ui, comm, p.config.RemotePath); err != nil { | ||
| return fmt.Errorf("Error creating remote directory: %s", err) | ||
| } | ||
|
|
||
| if p.config.VarsFile != "" { | ||
| vf, err := os.Stat(p.config.VarsFile) | ||
| if err != nil { | ||
|
|
@@ -416,18 +439,50 @@ func (p *Provisioner) inline_vars() string { | |
| if len(p.config.VarsInline) != 0 { | ||
| inlineVarsJson, err := json.Marshal(p.config.VarsInline) | ||
| if err == nil { | ||
| return fmt.Sprintf("--vars-inline '%s'", string(inlineVarsJson)) | ||
| switch p.config.TargetOs { | ||
| case windows: | ||
| // don't include single quotes which confused cmd parsing | ||
| return fmt.Sprintf("--vars-inline %s", string(inlineVarsJson)) | ||
| default: | ||
| return fmt.Sprintf("--vars-inline '%s'", string(inlineVarsJson)) | ||
| } | ||
| } else { | ||
| fmt.Errorf("Error converting inline vars to json string %v", err) | ||
| } | ||
| } | ||
| return "" | ||
| } | ||
|
|
||
| func (p *Provisioner) getDownloadUrl() string { | ||
| os := strings.ToLower(string(p.config.TargetOs)) | ||
| filename := fmt.Sprintf("goss-%s-%s", os, p.config.Arch) | ||
|
|
||
| if p.isGossAlpha() { | ||
| filename = fmt.Sprintf("goss-alpha-%s-%s", os, p.config.Arch) | ||
| } | ||
|
|
||
| if p.config.TargetOs == windows { | ||
| filename = fmt.Sprintf("%s.exe", filename) | ||
| } | ||
|
|
||
| return fmt.Sprintf("https://github.com/aelsabbahy/goss/releases/download/v%s/%s", p.config.Version, filename) | ||
| } | ||
|
|
||
| func (p *Provisioner) isGossAlpha() bool { | ||
| return p.config.VarsEnv["GOSS_USE_ALPHA"] == "1" | ||
| } | ||
|
|
||
| func (p *Provisioner) envVars() string { | ||
| var sb strings.Builder | ||
| for env_var, value := range p.config.VarsEnv { | ||
| sb.WriteString(fmt.Sprintf("%s=\"%s\" ", env_var, value)) | ||
| switch p.config.TargetOs { | ||
| case windows: | ||
| // Windows requires a call to "set" as separate command seperated by && for each env variable | ||
| sb.WriteString(fmt.Sprintf("set \"%s=%s\" && ", env_var, value)) | ||
| default: | ||
| sb.WriteString(fmt.Sprintf("%s=\"%s\" ", env_var, value)) | ||
| } | ||
|
|
||
| } | ||
| return sb.String() | ||
| } | ||
|
|
@@ -481,7 +536,7 @@ func (p *Provisioner) createDir(ui packer.Ui, comm packer.Communicator, dir stri | |
| ctx := context.TODO() | ||
|
|
||
| cmd := &packer.RemoteCmd{ | ||
| Command: fmt.Sprintf("mkdir -p '%s'", dir), | ||
| Command: p.mkDir(dir), | ||
| } | ||
| if err := cmd.RunWithUi(ctx, comm, ui); err != nil { | ||
| return err | ||
|
|
@@ -492,6 +547,15 @@ func (p *Provisioner) createDir(ui packer.Ui, comm packer.Communicator, dir stri | |
| return nil | ||
| } | ||
|
|
||
| func (p *Provisioner) mkDir(dir string) string { | ||
| switch p.config.TargetOs { | ||
| case windows: | ||
| return fmt.Sprintf("powershell /c mkdir -p '%s'", dir) | ||
| default: | ||
| return fmt.Sprintf("mkdir -p '%s'", dir) | ||
| } | ||
| } | ||
|
|
||
| // uploadFile uploads a file | ||
| func (p *Provisioner) uploadFile(ui packer.Ui, comm packer.Communicator, dst, src string) error { | ||
| f, err := os.Open(src) | ||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I understand why you did this, but I'm inclined to simplify this and just use a string and get rid of the const. It will simplify the code below as well. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which logic? I think we still need all the checks in place as well as the
ToLowerto ensure the url is written properly. I could replace theOsTypetype and make it just a string?