Skip to content

Commit

Permalink
apmpackage: disallow multiple "apm" integrations (#4694) (#4851)
Browse files Browse the repository at this point in the history
  • Loading branch information
axw authored Feb 20, 2021
1 parent 7269807 commit 55206be
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 46 deletions.
1 change: 1 addition & 0 deletions apmpackage/apm/0.1.0/manifest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ policy_templates:
- name: apmserver
title: Elastic APM Integration
description: Elastic APM Integration
multiple: false
inputs:
- type: apm
title: Collect application traces
Expand Down
105 changes: 70 additions & 35 deletions systemtest/fleet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,43 +51,14 @@ func TestFleetIntegration(t *testing.T) {
agentPolicy, enrollmentAPIKey, err := fleet.CreateAgentPolicy("apm_systemtest", "default", "Agent policy for APM Server system tests")
require.NoError(t, err)

// Find the "apm" package to install.
var apmPackage *fleettest.Package
packages, err := fleet.ListPackages()
require.NoError(t, err)
for _, pkg := range packages {
if pkg.Name == "apm" {
apmPackage = &pkg
break
}
}
require.NotNil(t, apmPackage)

// Add the "apm" integration to the agent policy.
packagePolicy := fleettest.PackagePolicy{
Name: "apm",
Namespace: "default",
Enabled: true,
AgentPolicyID: agentPolicy.ID,
}
apmPackage := getAPMIntegrationPackage(t, fleet)
packagePolicy := fleettest.NewPackagePolicy(apmPackage, "apm", "default", agentPolicy.ID)
packagePolicy.Package.Name = apmPackage.Name
packagePolicy.Package.Version = apmPackage.Version
packagePolicy.Package.Title = apmPackage.Title
packagePolicy.Inputs = []fleettest.PackagePolicyInput{{
Type: "apm",
Enabled: true,
Streams: []interface{}{},
Vars: map[string]interface{}{
"enable_rum": map[string]interface{}{
"type": "bool",
"value": false,
},
"host": map[string]interface{}{
"type": "string",
"value": ":8200",
},
},
}}
initAPMIntegrationPackagePolicyInputs(t, packagePolicy, apmPackage)

err = fleet.CreatePackagePolicy(packagePolicy)
require.NoError(t, err)

Expand Down Expand Up @@ -151,6 +122,71 @@ func TestFleetIntegration(t *testing.T) {
systemtest.Elasticsearch.ExpectDocs(t, "traces-*", nil)
}

func TestFleetPackageNonMultiple(t *testing.T) {
systemtest.CleanupElasticsearch(t)

fleet := fleettest.NewClient(systemtest.KibanaURL.String())
require.NoError(t, fleet.Setup())
cleanupFleet(t, fleet)
defer cleanupFleet(t, fleet)

agentPolicy, _, err := fleet.CreateAgentPolicy("apm_systemtest", "default", "Agent policy for APM Server system tests")
require.NoError(t, err)

apmPackage := getAPMIntegrationPackage(t, fleet)
packagePolicy := fleettest.NewPackagePolicy(apmPackage, "apm", "default", agentPolicy.ID)
initAPMIntegrationPackagePolicyInputs(t, packagePolicy, apmPackage)

err = fleet.CreatePackagePolicy(packagePolicy)
require.NoError(t, err)

// Attempting to add the "apm" integration to the agent policy twice should fail.
packagePolicy.Name = "apm-2"
err = fleet.CreatePackagePolicy(packagePolicy)
require.Error(t, err)
assert.EqualError(t, err, "Unable to create package policy. Package 'apm' already exists on this agent policy.")
}

func initAPMIntegrationPackagePolicyInputs(t *testing.T, packagePolicy *fleettest.PackagePolicy, apmPackage *fleettest.Package) {
assert.Len(t, apmPackage.PolicyTemplates, 1)
assert.Len(t, apmPackage.PolicyTemplates[0].Inputs, 1)
for _, input := range apmPackage.PolicyTemplates[0].Inputs {
vars := make(map[string]interface{})
for _, inputVar := range input.Vars {
varMap := map[string]interface{}{"type": inputVar.Type}
switch inputVar.Name {
case "host":
varMap["value"] = ":8200"
}
vars[inputVar.Name] = varMap
}
packagePolicy.Inputs = append(packagePolicy.Inputs, fleettest.PackagePolicyInput{
Type: input.Type,
Enabled: true,
Streams: []interface{}{},
Vars: vars,
})
}
}

func getAPMIntegrationPackage(t *testing.T, fleet *fleettest.Client) *fleettest.Package {
var apmPackage *fleettest.Package
packages, err := fleet.ListPackages()
require.NoError(t, err)
for _, pkg := range packages {
if pkg.Name != "apm" {
continue
}
// ListPackages does not return all package details,
// so we call Package to get them.
apmPackage, err = fleet.Package(pkg.Name, pkg.Version)
require.NoError(t, err)
return apmPackage
}
t.Fatal("could not find package 'apm'")
panic("unreachable")
}

func cleanupFleet(t testing.TB, fleet *fleettest.Client) {
apmAgentPolicies, err := fleet.AgentPolicies("ingest-agent-policies.name:apm_systemtest")
require.NoError(t, err)
Expand All @@ -175,8 +211,7 @@ func cleanupFleet(t testing.TB, fleet *fleettest.Client) {
}
// BUG(axw) the Fleet API is returning 404 when deleting agent policies
// in some circumstances: https://github.com/elastic/kibana/issues/90544
err := fleet.DeleteAgentPolicy(p.ID)
require.Error(t, err)
fleet.DeleteAgentPolicy(p.ID)
var fleetError *fleettest.Error
if errors.As(err, &fleetError) {
assert.Equal(t, http.StatusNotFound, fleetError.StatusCode)
Expand Down
20 changes: 18 additions & 2 deletions systemtest/fleettest/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,22 @@ func (c *Client) ListPackages() ([]Package, error) {
return result.Response, nil
}

// Package returns information about the package with the given name and version.
func (c *Client) Package(name, version string) (*Package, error) {
resp, err := http.Get(c.fleetURL + "/epm/packages/" + name + "-" + version)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var result struct {
Response Package `json:"response"`
}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, err
}
return &result.Response, nil
}

// PackagePolicy returns information about the package policy with the given ID.
func (c *Client) PackagePolicy(id string) (*PackagePolicy, error) {
resp, err := http.Get(c.fleetURL + "/package_policies/" + id)
Expand All @@ -240,9 +256,9 @@ func (c *Client) PackagePolicy(id string) (*PackagePolicy, error) {
}

// CreatePackagePolicy adds an integration to a policy.
func (c *Client) CreatePackagePolicy(p PackagePolicy) error {
func (c *Client) CreatePackagePolicy(p *PackagePolicy) error {
var body bytes.Buffer
if err := json.NewEncoder(&body).Encode(&p); err != nil {
if err := json.NewEncoder(&body).Encode(p); err != nil {
return err
}
req := c.newFleetRequest("POST", "/package_policies", &body)
Expand Down
33 changes: 33 additions & 0 deletions systemtest/fleettest/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package fleettest

// NewPackagePolicy returns a new PackagePolicy for the package,
// with the given name, namespace, and agent policy ID.
func NewPackagePolicy(pkg *Package, name, namespace, agentPolicyID string) *PackagePolicy {
out := &PackagePolicy{
Name: name,
Namespace: namespace,
AgentPolicyID: agentPolicyID,
Enabled: true,
}
out.Package.Name = pkg.Name
out.Package.Version = pkg.Version
out.Package.Title = pkg.Title
return out
}
36 changes: 27 additions & 9 deletions systemtest/fleettest/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,33 @@ type PackagePolicyInput struct {
}

type Package struct {
Name string `json:"name"`
Version string `json:"version"`
Release string `json:"release"`
Type string `json:"type"`
Title string `json:"title"`
Description string `json:"description"`
Download string `json:"download"`
Path string `json:"path"`
Status string `json:"status"`
Name string `json:"name"`
Version string `json:"version"`
Release string `json:"release"`
Type string `json:"type"`
Title string `json:"title"`
Description string `json:"description"`
Download string `json:"download"`
Path string `json:"path"`
Status string `json:"status"`
PolicyTemplates []PackagePolicyTemplate `json:"policy_templates"`
}

type PackagePolicyTemplate struct {
Inputs []PackagePolicyTemplateInput `json:"inputs"`
}

type PackagePolicyTemplateInput struct {
Type string `json:"type"`
Title string `json:"title"`
TemplatePath string `json:"template_path"`
Description string `json:"description"`
Vars []PackagePolicyTemplateInputVar `json:"vars"`
}

type PackagePolicyTemplateInputVar struct {
Name string `json:"name"`
Type string `json:"type"`
}

type EnrollmentAPIKey struct {
Expand Down

0 comments on commit 55206be

Please sign in to comment.