diff --git a/cmd/serve.go b/cmd/serve.go index f32ca56..82e6510 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -90,6 +90,9 @@ func init() { serveCmd.Flags().StringSlice("gin-trusted-proxies", []string{}, "Comma-separated list of IP addresses, like `\"192.168.1.1,10.0.0.1\"`. When running the Metadata Service behind something like a reverse proxy or load balancer, you may need to set this so that gin's `(*Context).ClientIP()` method returns a value provided by the proxy in a header like `X-Forwarded-For`.") viperBindFlag("gin.trustedproxies", serveCmd.Flags().Lookup("gin-trusted-proxies")) + serveCmd.Flags().String("api-url", "", "An optional golang template string used to build a URL which instances can use as a reference to the Metadata Service API itself. This template string will be evaluated against the instance metadata, and appended as an 'api_url' field on the metadata document served to instances. If no template string is specified, the 'api_url' field will not be added to the metadata document.") + viperBindFlag("metadata.api_url", serveCmd.Flags().Lookup("api-url")) + serveCmd.Flags().String("phone-home-url", "", "An optional golang template string used to build a URL which instances can use as part of a 'phone home' process. This template string will be evaluated against the instance metadata, and appended as a 'phone_home_url' field on the metadata document served to instances. If no template string is specified, the 'phone_home_url' field will not be added to the metadata document.") viperBindFlag("metadata.phone_home_url", serveCmd.Flags().Lookup("phone-home-url")) @@ -180,9 +183,19 @@ func getLookupClient(ctx context.Context) (*lookup.ServiceClient, error) { func getTemplateFields() map[string]template.Template { templates := make(map[string]template.Template) + apiURL := viper.GetString("metadata.api_url") phoneHomeURL := viper.GetString("metadata.phone_home_url") userStateURL := viper.GetString("metadata.user_state_url") + if len(apiURL) > 0 { + apiURLTempl, err := template.New("apiURL").Parse(apiURL) + if err != nil { + logger.Fatalf("failed to parse API URL template (%s)", apiURL, "error", err) + } + + templates["api_url"] = *apiURLTempl + } + if len(phoneHomeURL) > 0 { phoneHomeTempl, err := template.New("phoneHomeURL").Parse(phoneHomeURL) if err != nil { diff --git a/pkg/api/v1/router_instance_metadata_test.go b/pkg/api/v1/router_instance_metadata_test.go index fc2ce31..aff4841 100644 --- a/pkg/api/v1/router_instance_metadata_test.go +++ b/pkg/api/v1/router_instance_metadata_test.go @@ -116,6 +116,11 @@ func TestGetMetadataByIP(t *testing.T) { } func TestGetMetadataByIPWithTemplateFields(t *testing.T) { + apiURLTmpl, err := template.New("apiURL").Parse("https://metadata-service") + if err != nil { + t.Error(err) + } + phoneHomeTmpl, err := template.New("phoneHomeURL").Parse("https://{{.facility}}.phone.home/phone-home") if err != nil { t.Error(err) @@ -145,6 +150,7 @@ func TestGetMetadataByIPWithTemplateFields(t *testing.T) { config := TestServerConfig{ TemplateFields: map[string]template.Template{ + "api_url": *apiURLTmpl, "phone_home_url": *phoneHomeTmpl, "user_state_url": *userStateTmpl, "missing_field": *missingFieldTmpl, @@ -171,6 +177,7 @@ func TestGetMetadataByIPWithTemplateFields(t *testing.T) { t.Fatal(err) } + assert.Equal(t, "https://metadata-service", resultMap["api_url"]) assert.Equal(t, "https://da11.phone.home/phone-home", resultMap["phone_home_url"]) assert.Equal(t, fmt.Sprintf("https://da.user.state/events/%s", dbtools.FixtureInstanceA.InstanceID), resultMap["user_state_url"]) assert.Equal(t, "instance-a", resultMap["hostname"])