mirror of
https://github.com/hashicorp/packer.git
synced 2026-03-01 21:10:58 -05:00
feat: allow additional methods in http datasource
This adds support for additional http methods for the http datasource. Fixes #13169 Signed-off-by: Henrik Gerdes <hegerdes@outlook.de>
This commit is contained in:
parent
6e417bb883
commit
6c40bfb0cd
6 changed files with 79 additions and 4 deletions
|
|
@ -24,10 +24,14 @@ import (
|
|||
|
||||
type Config struct {
|
||||
common.PackerConfig `mapstructure:",squash"`
|
||||
// The URL to request data from. This URL must respond with a `200 OK` response and a `text/*` or `application/json` Content-Type.
|
||||
// The URL to request data from. This URL must respond with a `2xx` range response code and a `text/*` or `application/json` Content-Type.
|
||||
Url string `mapstructure:"url" required:"true"`
|
||||
// HTTP method used for the request. Supported methods are `HEAD`, `GET`, `POST`, `PUT`, `DELETE`, `OPTIONS`, `PATCH`. Default is `GET`.
|
||||
Method string `mapstructure:"method" required:"false"`
|
||||
// A map of strings representing additional HTTP headers to include in the request.
|
||||
RequestHeaders map[string]string `mapstructure:"request_headers" required:"false"`
|
||||
// HTTP request payload send with the request. Default is empty.
|
||||
RequestBody string `mapstructure:"request_body" required:"false"`
|
||||
}
|
||||
|
||||
type Datasource struct {
|
||||
|
|
@ -62,6 +66,26 @@ func (d *Datasource) Configure(raws ...interface{}) error {
|
|||
fmt.Errorf("the `url` must be specified"))
|
||||
}
|
||||
|
||||
// Default to GET if no method is specified
|
||||
if d.config.Method == "" {
|
||||
d.config.Method = "GET"
|
||||
}
|
||||
|
||||
// Check if the input is in the list of allowed methods
|
||||
validMethod := false
|
||||
allowedMethods := []string{"HEAD", "GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"}
|
||||
for _, method := range allowedMethods {
|
||||
if method == d.config.Method {
|
||||
validMethod = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !validMethod {
|
||||
errs = packersdk.MultiErrorAppend(
|
||||
errs,
|
||||
fmt.Errorf("the `method` must be one of %v", allowedMethods))
|
||||
}
|
||||
|
||||
if errs != nil && len(errs.Errors) > 0 {
|
||||
return errs
|
||||
}
|
||||
|
|
@ -102,10 +126,16 @@ func isContentTypeText(contentType string) bool {
|
|||
// https://github.com/hashicorp/terraform-provider-http/blob/main/internal/provider/data_source.go
|
||||
func (d *Datasource) Execute() (cty.Value, error) {
|
||||
ctx := context.TODO()
|
||||
url, headers := d.config.Url, d.config.RequestHeaders
|
||||
url, method, headers := d.config.Url, d.config.Method, d.config.RequestHeaders
|
||||
client := &http.Client{}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
||||
// Create request body if it is provided
|
||||
var requestBody io.Reader
|
||||
if d.config.RequestBody != "" {
|
||||
requestBody = strings.NewReader(d.config.RequestBody)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, method, url, requestBody)
|
||||
// TODO: How to make a test case for this?
|
||||
if err != nil {
|
||||
fmt.Println("Error creating http request")
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@ type FlatConfig struct {
|
|||
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"`
|
||||
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"`
|
||||
Url *string `mapstructure:"url" required:"true" cty:"url" hcl:"url"`
|
||||
Method *string `mapstructure:"method" required:"false" cty:"method" hcl:"method"`
|
||||
RequestHeaders map[string]string `mapstructure:"request_headers" required:"false" cty:"request_headers" hcl:"request_headers"`
|
||||
RequestBody *string `mapstructure:"request_body" required:"false" cty:"request_body" hcl:"request_body"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatConfig.
|
||||
|
|
@ -43,7 +45,9 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"url": &hcldec.AttrSpec{Name: "url", Type: cty.String, Required: false},
|
||||
"method": &hcldec.AttrSpec{Name: "method", Type: cty.String, Required: false},
|
||||
"request_headers": &hcldec.AttrSpec{Name: "request_headers", Type: cty.Map(cty.String), Required: false},
|
||||
"request_body": &hcldec.AttrSpec{Name: "request_body", Type: cty.String, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ var testDatasourceEmptyUrl string
|
|||
//go:embed test-fixtures/404_url.pkr.hcl
|
||||
var testDatasource404Url string
|
||||
|
||||
//go:embed test-fixtures/invalid_method.pkr.hcl
|
||||
var testDatasourceInvalidMethod string
|
||||
|
||||
func TestHttpDataSource(t *testing.T) {
|
||||
tests := []struct {
|
||||
Name string
|
||||
|
|
@ -49,6 +52,14 @@ func TestHttpDataSource(t *testing.T) {
|
|||
"error": "the `url` must be specified",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "method_is_invalid",
|
||||
Path: testDatasourceInvalidMethod,
|
||||
Error: true,
|
||||
Outputs: map[string]string{
|
||||
"error": "the `method` must be one of [HEAD GET POST PUT DELETE OPTIONS PATCH]",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "404_url",
|
||||
Path: testDatasource404Url,
|
||||
|
|
|
|||
26
datasource/http/test-fixtures/invalid_method.pkr.hcl
Normal file
26
datasource/http/test-fixtures/invalid_method.pkr.hcl
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
source "null" "example" {
|
||||
communicator = "none"
|
||||
}
|
||||
|
||||
data "http" "basic" {
|
||||
url = "https://www.packer.io/"
|
||||
method = "NONEEXISTING"
|
||||
}
|
||||
|
||||
locals {
|
||||
url = "${data.http.basic.url}"
|
||||
body = "${data.http.basic.body}" != ""
|
||||
}
|
||||
|
||||
build {
|
||||
name = "mybuild"
|
||||
sources = [
|
||||
"source.null.example"
|
||||
]
|
||||
provisioner "shell-local" {
|
||||
inline = [
|
||||
"echo url is ${local.url}",
|
||||
"echo body is ${local.body}"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,9 @@
|
|||
<!-- Code generated from the comments of the Config struct in datasource/http/data.go; DO NOT EDIT MANUALLY -->
|
||||
|
||||
- `method` (string) - HTTP method used for the request. Supported methods are `HEAD`, `GET`, `POST`, `PUT`, `DELETE`, `OPTIONS`, `PATCH`. Default is `GET`.
|
||||
|
||||
- `request_headers` (map[string]string) - A map of strings representing additional HTTP headers to include in the request.
|
||||
|
||||
- `request_body` (string) - HTTP request payload send with the request. Default is empty.
|
||||
|
||||
<!-- End of code generated from the comments of the Config struct in datasource/http/data.go; -->
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<!-- Code generated from the comments of the Config struct in datasource/http/data.go; DO NOT EDIT MANUALLY -->
|
||||
|
||||
- `url` (string) - The URL to request data from. This URL must respond with a `200 OK` response and a `text/*` or `application/json` Content-Type.
|
||||
- `url` (string) - The URL to request data from. This URL must respond with a `2xx` range response code and a `text/*` or `application/json` Content-Type.
|
||||
|
||||
<!-- End of code generated from the comments of the Config struct in datasource/http/data.go; -->
|
||||
|
|
|
|||
Loading…
Reference in a new issue