-
Notifications
You must be signed in to change notification settings - Fork 124
Asset loading test runner #168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
05c160c
Refactoring: extracting common code
ycombinator ebf3a50
Adding skeleton for asset loading test runner
ycombinator 27e1a08
Refactoring: defining and implementing TestRunner interface
ycombinator 2dfb9f8
More fleshing out
ycombinator e13e739
More fleshing out
ycombinator eefad58
Adding HOWTO
ycombinator 459df7e
Refactoring: make ingest pipeline name method of DataStreamManifest
ycombinator af707f3
Adding assertions
ycombinator 1f0e17f
More fleshing out
ycombinator 33c2ca4
Better test result reporting
ycombinator faba5b5
Fix issue with kibana assets being ignored
ycombinator 4157710
Add data stream to asset
ycombinator 8a58f8e
Adding entry to README
ycombinator c525f0d
Making language consistent
ycombinator 0b12387
Adding godoc comments
ycombinator 8a8aa95
More godoc comments
ycombinator 9c91335
Build packages before starting up stack
ycombinator f482e49
Adding license headers
ycombinator 778b9cf
Using nil slices
ycombinator b3f752b
Move settings to stack package
ycombinator 8af8e4b
Refactoring: merging packages API into Kibana client
ycombinator 5aecd27
Use multierror to collect all errors
ycombinator 4ec725f
Removing IsConfigRequired
ycombinator 91fd2c8
Bumping up apache version to something very large
ycombinator c0014db
Adding comment for large version
ycombinator dfd0503
Fixing paths
ycombinator 93cff73
Check errors length
ycombinator 5d14f10
Fixing typo
ycombinator 4760e8c
Initialize OLDPWD
ycombinator 1bfb2c0
Check for existence of flag before trying to parse it
ycombinator 3d11f91
Adding comment to explain check
ycombinator 010d452
Setting large versions for all test packages
ycombinator cef5f22
Removing vestigial stack settings code
ycombinator 133e50e
Adding lens asset
ycombinator File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# HOWTO: Writing asset loading tests for a package | ||
|
||
## Introduction | ||
|
||
Elastic Packages define assets to be loaded into Elasticsearch and Kibana. Asset loading tests exercise installing a package to ensure that its assets are loaded into Elasticsearch and Kibana as expected. | ||
|
||
## Conceptual process | ||
|
||
Conceptually, running an asset load test involves the following steps: | ||
|
||
1. Build the package. | ||
1. Deploy Elasticsearch, Kibana, and the Package Registry (all part of the Elastic Stack). This step takes time so it should typically be done once as a pre-requisite to running asset loading tests on multiple packages. | ||
1. Install the package. | ||
1. Use various Kibana and Elasticsearch APIs to assert that the package's assets were loaded into Kibana and Elasticsearch as expected. | ||
1. Remove the package. | ||
|
||
## Defining an asset loading test | ||
|
||
As a package developer, you do not need to do any work to define an asset loading test for your package. All the necessary information is already present in the package's files. | ||
|
||
## Running an asset loading test | ||
|
||
First, you must build your package. This corresponds to step 1 as described in the [_Conceptual process_](#Conceptual-process) section. | ||
|
||
Navigate to the package's root folder (or any sub-folder under it) and run the following command. | ||
|
||
``` | ||
elastic-package build | ||
``` | ||
|
||
Next, you must deploy Elasticsearch, Kibana, and the Package Registry. This corresponds to step 2 as described in the [_Conceptual process_](#Conceptual-process) section. | ||
|
||
``` | ||
elastic-package stack up -d | ||
``` | ||
|
||
For a complete listing of options available for this command, run `elastic-package stack up -h` or `elastic-package help stack up`. | ||
|
||
Next, you must set environment variables needed for further `elastic-package` commands. | ||
|
||
``` | ||
$(elastic-package stack shellinit) | ||
``` | ||
|
||
Next, you must invoke the asset loading test runner. This corresponds to steps 3 through 5 as described in the [_Conceptual process_](#Conceptual-process) section. | ||
|
||
Navigate to the package's root folder (or any sub-folder under it) and run the following command. | ||
|
||
``` | ||
elastic-package test asset | ||
``` | ||
|
||
Finally, when you are done running all asset loading tests, bring down the Elastic Stack. This corresponds to step 4 as described in the [_Conceptual process_](#Conceptual-process) section. | ||
|
||
``` | ||
elastic-package stack down | ||
``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
// or more contributor license agreements. Licensed under the Elastic License; | ||
// you may not use this file except in compliance with the Elastic License. | ||
|
||
package kibana | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
|
||
"github.com/pkg/errors" | ||
|
||
"github.com/elastic/elastic-package/internal/packages" | ||
) | ||
|
||
// InstallPackage installs the given package in Fleet. | ||
func (c *Client) InstallPackage(pkg packages.PackageManifest) ([]packages.Asset, error) { | ||
path := fmt.Sprintf("%s/epm/packages/%s-%s", FleetAPI, pkg.Name, pkg.Version) | ||
statusCode, respBody, err := c.post(path, nil) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "could not install package") | ||
} | ||
|
||
return processResults("install", statusCode, respBody) | ||
} | ||
|
||
// RemovePackage removes the given package from Fleet. | ||
func (c *Client) RemovePackage(pkg packages.PackageManifest) ([]packages.Asset, error) { | ||
path := fmt.Sprintf("%s/epm/packages/%s-%s", FleetAPI, pkg.Name, pkg.Version) | ||
statusCode, respBody, err := c.delete(path) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "could not delete package") | ||
} | ||
|
||
return processResults("remove", statusCode, respBody) | ||
} | ||
|
||
func processResults(action string, statusCode int, respBody []byte) ([]packages.Asset, error) { | ||
if statusCode != 200 { | ||
return nil, fmt.Errorf("could not %s package; API status code = %d; response body = %s", action, statusCode, respBody) | ||
} | ||
|
||
var resp struct { | ||
Assets []packages.Asset `json:"response"` | ||
} | ||
|
||
if err := json.Unmarshal(respBody, &resp); err != nil { | ||
return nil, errors.Wrapf(err, "could not convert %s package (response) to JSON", action) | ||
} | ||
|
||
return resp.Assets, nil | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
// or more contributor license agreements. Licensed under the Elastic License; | ||
// you may not use this file except in compliance with the Elastic License. | ||
|
||
package packages | ||
|
||
import ( | ||
"fmt" | ||
"io/ioutil" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
|
||
"github.com/pkg/errors" | ||
|
||
"github.com/elastic/elastic-package/internal/multierror" | ||
) | ||
|
||
// AssetType represents the type of package asset. | ||
type AssetType string | ||
|
||
// Supported asset types. | ||
const ( | ||
AssetTypeElasticsearchIndexTemplate AssetType = "index_template" | ||
AssetTypeElasticsearchIngestPipeline AssetType = "ingest_pipeline" | ||
|
||
AssetTypeKibanaSavedSearch AssetType = "search" | ||
AssetTypeKibanaVisualization AssetType = "visualization" | ||
AssetTypeKibanaDashboard AssetType = "dashboard" | ||
AssetTypeKibanaMap AssetType = "map" | ||
AssetTypeKibanaLens AssetType = "lens" | ||
) | ||
|
||
// Asset represents a package asset to be loaded into Kibana or Elasticsearch. | ||
type Asset struct { | ||
ID string `json:"id"` | ||
Type AssetType `json:"type"` | ||
DataStream string | ||
} | ||
|
||
// LoadPackageAssets parses the package contents and returns a list of assets defined by the package. | ||
func LoadPackageAssets(pkgRootPath string) ([]Asset, error) { | ||
assets, err := loadKibanaAssets(pkgRootPath) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "could not load kibana assets") | ||
} | ||
|
||
a, err := loadElasticsearchAssets(pkgRootPath) | ||
if err != nil { | ||
return a, errors.Wrap(err, "could not load elasticsearch assets") | ||
} | ||
assets = append(assets, a...) | ||
|
||
return assets, nil | ||
} | ||
|
||
func loadKibanaAssets(pkgRootPath string) ([]Asset, error) { | ||
kibanaAssetsFolderPath := filepath.Join(pkgRootPath, "kibana") | ||
|
||
var ( | ||
errs multierror.Error | ||
|
||
assetTypes = []AssetType{ | ||
AssetTypeKibanaDashboard, | ||
AssetTypeKibanaVisualization, | ||
AssetTypeKibanaSavedSearch, | ||
AssetTypeKibanaMap, | ||
AssetTypeKibanaLens, | ||
} | ||
|
||
assets []Asset | ||
) | ||
|
||
for _, assetType := range assetTypes { | ||
a, err := loadFileBasedAssets(kibanaAssetsFolderPath, assetType) | ||
if err != nil { | ||
errs = append(errs, errors.Wrapf(err, "could not load kibana %s assets", assetType)) | ||
continue | ||
} | ||
|
||
assets = append(assets, a...) | ||
} | ||
|
||
if len(errs) > 0 { | ||
return nil, errs | ||
} | ||
|
||
return assets, nil | ||
} | ||
|
||
func loadElasticsearchAssets(pkgRootPath string) ([]Asset, error) { | ||
packageManifestPath := filepath.Join(pkgRootPath, PackageManifestFile) | ||
pkgManifest, err := ReadPackageManifest(packageManifestPath) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "reading package manifest file failed") | ||
} | ||
|
||
dataStreamManifestPaths, err := filepath.Glob(filepath.Join(pkgRootPath, "data_stream", "*", DataStreamManifestFile)) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "could not read data stream manifest file paths") | ||
} | ||
|
||
var assets []Asset | ||
for _, dsManifestPath := range dataStreamManifestPaths { | ||
dsManifest, err := ReadDataStreamManifest(dsManifestPath) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "reading data stream manifest failed") | ||
} | ||
|
||
indexTemplateName := fmt.Sprintf("%s-%s.%s", dsManifest.Type, pkgManifest.Name, dsManifest.Name) | ||
asset := Asset{ | ||
ID: indexTemplateName, | ||
Type: AssetTypeElasticsearchIndexTemplate, | ||
DataStream: dsManifest.Name, | ||
} | ||
assets = append(assets, asset) | ||
|
||
if dsManifest.Type == dataStreamTypeLogs { | ||
ingestPipelineName := dsManifest.GetPipelineNameOrDefault() | ||
if ingestPipelineName == defaultPipelineName { | ||
ingestPipelineName = fmt.Sprintf("%s-%s.%s-%s", dsManifest.Type, pkgManifest.Name, dsManifest.Name, pkgManifest.Version) | ||
} | ||
asset = Asset{ | ||
ID: ingestPipelineName, | ||
Type: AssetTypeElasticsearchIngestPipeline, | ||
DataStream: dsManifest.Name, | ||
} | ||
assets = append(assets, asset) | ||
} | ||
} | ||
|
||
return assets, nil | ||
} | ||
|
||
func loadFileBasedAssets(kibanaAssetsFolderPath string, assetType AssetType) ([]Asset, error) { | ||
assetsFolderPath := filepath.Join(kibanaAssetsFolderPath, string(assetType)) | ||
_, err := os.Stat(assetsFolderPath) | ||
if err != nil && os.IsNotExist(err) { | ||
// No assets folder defined; nothing to load | ||
return nil, nil | ||
} | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "error finding kibana %s assets folder", assetType) | ||
} | ||
|
||
files, err := ioutil.ReadDir(assetsFolderPath) | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "could not read %s files", assetType) | ||
} | ||
|
||
var assets []Asset | ||
for _, f := range files { | ||
if f.IsDir() { | ||
continue | ||
} | ||
|
||
name := f.Name() | ||
id := strings.TrimSuffix(name, ".json") | ||
|
||
asset := Asset{ | ||
ID: id, | ||
Type: assetType, | ||
} | ||
assets = append(assets, asset) | ||
} | ||
|
||
return assets, nil | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed in 133e50e.