diff --git a/cmd/dump.go b/cmd/dump.go index 1a3e24a7cb..75ae705242 100644 --- a/cmd/dump.go +++ b/cmd/dump.go @@ -78,11 +78,9 @@ func dumpInstalledObjectsCmdAction(cmd *cobra.Command, args []string) error { return cobraext.FlagParsingError(err, cobraext.DumpOutputFlagName) } - tlsSkipVerify, _ := cmd.Flags().GetBool(cobraext.TLSSkipVerifyFlagName) - - var clientOptions []elasticsearch.ClientOption - if tlsSkipVerify { - clientOptions = append(clientOptions, elasticsearch.OptionWithSkipTLSVerify()) + tlsSkipVerify, err := cmd.Flags().GetBool(cobraext.TLSSkipVerifyFlagName) + if err != nil { + return cobraext.FlagParsingError(err, cobraext.TLSSkipVerifyFlagName) } profile, err := cobraext.GetProfileFlag(cmd) @@ -90,6 +88,27 @@ func dumpInstalledObjectsCmdAction(cmd *cobra.Command, args []string) error { return err } + var kibanaOptions []kibana.ClientOption + if tlsSkipVerify { + kibanaOptions = append(kibanaOptions, kibana.TLSSkipVerify()) + } + kibanaClient, err := stack.NewKibanaClientFromProfile(profile, kibanaOptions...) + if err != nil { + return fmt.Errorf("failed to initialize Kibana client: %w", err) + } + installedPackage, err := kibanaClient.GetPackage(packageName) + if err != nil { + return fmt.Errorf("failed to get package status: %w", err) + } + if installedPackage.Status == "not_installed" { + cmd.Printf("Package %s is not installed.\n", packageName) + return nil + } + + var clientOptions []elasticsearch.ClientOption + if tlsSkipVerify { + clientOptions = append(clientOptions, elasticsearch.OptionWithSkipTLSVerify()) + } client, err := stack.NewElasticsearchClientFromProfile(profile, clientOptions...) if err != nil { return fmt.Errorf("failed to initialize Elasticsearch client: %w", err) @@ -101,8 +120,11 @@ func dumpInstalledObjectsCmdAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("dump failed: %w", err) } if n == 0 { - cmd.Printf("No objects were dumped for package %s, is it installed?\n", packageName) - return nil + if installedPackage.Type == "input" { + cmd.Printf("No objects installed for input package %s unless a policy is created.\n", packageName) + return nil + } + return fmt.Errorf("no objects found for package %s", packageName) } cmd.Printf("Dumped %d installed objects for package %s to %s\n", n, packageName, outputPath) return nil diff --git a/internal/kibana/packages.go b/internal/kibana/packages.go index 057c630b67..ba6d2d5735 100644 --- a/internal/kibana/packages.go +++ b/internal/kibana/packages.go @@ -62,7 +62,51 @@ func (c *Client) RemovePackage(name, version string) ([]packages.Asset, error) { return processResults("remove", statusCode, respBody) } +// FleetPackage contains information about a package in Fleet. +type FleetPackage struct { + Name string `json:"string"` + Type string `json:"type"` + Status string `json:"status"` +} + +// GetPackage obtains information about a package from Fleet. +func (c *Client) GetPackage(name string) (*FleetPackage, error) { + path := c.epmPackageUrl(name, "") + statusCode, respBody, err := c.get(path) + if err != nil { + return nil, fmt.Errorf("could not get package: %w", err) + } + if statusCode == http.StatusNotFound { + return nil, fmt.Errorf("package %s not found", name) + } + if statusCode != http.StatusOK { + return nil, fmt.Errorf("could not get package; API status code = %d; response body = %s", statusCode, string(respBody)) + } + + var response struct { + // Response is here when old packages API is used (before 8.0) + Response *FleetPackage `json:"response"` + + // Response is here when new packages API is used (since 8.0) + Item *FleetPackage `json:"item"` + } + err = json.Unmarshal(respBody, &response) + switch { + case err != nil: + return nil, fmt.Errorf("failed to decode package response: %w", err) + case response.Response != nil: + return response.Response, nil + case response.Item != nil: + return response.Item, nil + default: + return nil, fmt.Errorf("package %s not found in response: %s", name, string(respBody)) + } +} + func (c *Client) epmPackageUrl(name, version string) string { + if version == "" { + return fmt.Sprintf("%s/epm/packages/%s", FleetAPI, name) + } switch { case c.semver.Major() < 8: return fmt.Sprintf("%s/epm/packages/%s-%s", FleetAPI, name, version)