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>
pull/13197/head
Henrik Gerdes 1 year ago committed by Lucas Bajolet
parent 6e417bb883
commit 6c40bfb0cd

@ -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,

@ -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…
Cancel
Save