diff --git a/utils/icinga2_client.go b/utils/icinga2_client.go index ebe2134..d19ff59 100644 --- a/utils/icinga2_client.go +++ b/utils/icinga2_client.go @@ -178,6 +178,68 @@ func (c *Icinga2Client) DeleteService(t testing.TB, host string, service string, c.DeleteObject(t, "services", host+"!"+service, cascade) } +// CreateConfigPackage creates a new Config Pack with the given name. +// +// After creating a config pack, stages need to be configured. To do so, use Icinga2Client.CreateConfigPackage. +// +// https://icinga.com/docs/icinga-2/latest/doc/12-icinga2-api/#create-a-config-package +func (c *Icinga2Client) CreateConfigPackage(t testing.TB, name string) { + url := "/v1/config/packages/" + name + res, err := c.PostJson(url, nil) + require.NoErrorf(t, err, "POST request for %s should succeed", url) + defer func() { _ = res.Body.Close() }() + if !assert.Equalf(t, http.StatusOK, res.StatusCode, "POST request for %s should return OK", url) { + body, err := io.ReadAll(res.Body) + require.NoError(t, err, "reading response for POST request for %s", url) + t.Logf("\nAPI response: %s\n\n%s", res.Status, body) + } +} + +// CreateConfigPackageStage creates a new Config Pack Stage and instructs Icinga 2 to reload. +// +// The parameters are the Config Pack name - created via Icinga2Client.CreateConfigPackageStage - and a map +// of filenames to their content in the Icinga 2 DSL. The files should be located either in "conf.d/" or +// "zones.d", as documented in the Icinga 2 docs. +// +// Note: After deploying the Config Pack Stage, Icinga 2 performs a reload and only then verifies the +// uploaded files. This happens AFTER this function returns. Thus, an invalid configuration cannot be +// detected by this function. +// +// https://icinga.com/docs/icinga-2/latest/doc/12-icinga2-api/#create-a-stage-upload-configuration +func (c *Icinga2Client) CreateConfigPackageStage(t testing.TB, name string, files map[string]string) { + body := map[string]interface{}{"files": files} + bodyJson, err := json.Marshal(body) + require.NoError(t, err, "json.Marshal() should succeed") + + url := "/v1/config/stages/" + name + res, err := c.PostJson(url, bytes.NewBuffer(bodyJson)) + require.NoErrorf(t, err, "POST request for %s should succeed", url) + defer func() { _ = res.Body.Close() }() + if !assert.Equalf(t, http.StatusOK, res.StatusCode, "POST request for %s should return OK", url) { + body, err := io.ReadAll(res.Body) + require.NoError(t, err, "reading response for POST request for %s", url) + t.Logf("\nAPI response: %s\n\n%s\n\nRequest body:\n\n%s", res.Status, body, bodyJson) + } +} + +// DeleteConfigPackage deletes a Config Pack by its name. +// +// Note: Deleting a Config Pack does not trigger an Icinga 2 reload. Thus, consider creating an empty +// Config Pack Stage - Icinga2Client.CreateConfigPackageStage with an empty files map. +// +// https://icinga.com/docs/icinga-2/latest/doc/12-icinga2-api/#deleting-configuration-package +func (c *Icinga2Client) DeleteConfigPackage(t testing.TB, name string) { + url := "/v1/config/packages/" + name + res, err := c.DeleteJson(url) + require.NoErrorf(t, err, "DELETE request for %s should succeed", url) + defer func() { _ = res.Body.Close() }() + if !assert.Equalf(t, http.StatusOK, res.StatusCode, "DELETE request for %s should return OK", url) { + body, err := io.ReadAll(res.Body) + require.NoError(t, err, "reading response for DELETE request for %s", url) + t.Logf("\nAPI response: %s\n\n%s", res.Status, body) + } +} + type icinga2ClientHttpTransport struct { host string username string