cmd/create_package.go (246 lines of code) (raw):
// 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 cmd
import (
"fmt"
"github.com/AlecAivazis/survey/v2"
"github.com/spf13/cobra"
"github.com/elastic/elastic-package/internal/licenses"
"github.com/elastic/elastic-package/internal/packages"
"github.com/elastic/elastic-package/internal/packages/archetype"
"github.com/elastic/elastic-package/internal/surveyext"
)
const createPackageLongDescription = `Use this command to create a new package.
The command can bootstrap the first draft of a package using embedded package template and wizard.`
const (
noLicenseValue = "None"
noLicenseOnCreationMessage = "I will add a license later."
)
type newPackageAnswers struct {
Name string
Type string
Version string
SourceLicense string `survey:"source_license"`
Title string
Description string
Categories []string
KibanaVersion string `survey:"kibana_version"`
ElasticSubscription string `survey:"elastic_subscription"`
GithubOwner string `survey:"github_owner"`
OwnerType string `survey:"owner_type"`
DataStreamType string `survey:"datastream_type"`
Subobjects bool
}
func createPackageCommandAction(cmd *cobra.Command, args []string) error {
cmd.Println("Create a new package")
qs := []*survey.Question{
{
Name: "type",
Prompt: &survey.Select{
Message: "Package type:",
Options: []string{"input", "integration", "content"},
Default: "integration",
},
Validate: survey.Required,
},
}
var answers newPackageAnswers
err := survey.Ask(qs, &answers)
if err != nil {
return fmt.Errorf("prompt failed: %w", err)
}
qs = []*survey.Question{
{
Name: "name",
Prompt: &survey.Input{
Message: "Package name:",
Default: "new_package",
},
Validate: survey.ComposeValidators(survey.Required, surveyext.PackageDoesNotExistValidator, surveyext.PackageNameValidator),
},
{
Name: "version",
Prompt: &survey.Input{
Message: "Version:",
Default: "0.0.1",
},
Validate: survey.ComposeValidators(survey.Required, surveyext.SemverValidator),
},
{
Name: "source_license",
Prompt: &survey.Select{
Message: "License:",
Options: []string{
licenses.Elastic20,
licenses.Apache20,
noLicenseValue,
},
Description: func(value string, _ int) string {
if value == noLicenseValue {
return noLicenseOnCreationMessage
}
return ""
},
Default: licenses.Elastic20,
},
},
{
Name: "title",
Prompt: &survey.Input{
Message: "Package title:",
Default: "New Package",
},
Validate: survey.Required,
},
{
Name: "description",
Prompt: &survey.Input{
Message: "Description:",
Default: "This is a new package.",
},
Validate: survey.Required,
},
{
Name: "categories",
Prompt: &survey.MultiSelect{
Message: "Categories:",
Options: []string{"aws", "azure", "cloud", "config_management", "containers", "crm", "custom",
"datastore", "elastic_stack", "google_cloud", "kubernetes", "languages", "message_queue",
"monitoring", "network", "notification", "os_system", "productivity", "security", "support",
"ticketing", "version_control", "web"},
Default: []string{"custom"},
PageSize: 50,
},
Validate: survey.Required,
},
{
Name: "kibana_version",
Prompt: &survey.Input{
Message: "Kibana version constraint:",
Default: surveyext.DefaultKibanaVersionConditionValue(),
},
Validate: survey.ComposeValidators(survey.Required, surveyext.ConstraintValidator),
},
{
Name: "elastic_subscription",
Prompt: &survey.Select{
Message: "Required Elastic subscription:",
Options: []string{"basic", "gold", "platinum", "enterprise"},
Default: "basic",
},
Validate: survey.Required,
},
{
Name: "github_owner",
Prompt: &survey.Input{
Message: "Github owner:",
Default: "elastic/integrations",
},
Validate: survey.ComposeValidators(survey.Required, surveyext.GithubOwnerValidator),
},
{
Name: "owner_type",
Prompt: &survey.Select{
Message: "Owner type:",
Options: []string{"elastic", "partner", "community"},
Description: func(value string, _ int) string {
switch value {
case "elastic":
return "Owned and supported by Elastic"
case "partner":
return "Vendor-owned with support from Elastic"
case "community":
return "Supported by the community"
}
return ""
},
Default: "elastic",
},
Validate: survey.Required,
},
}
if answers.Type == "input" {
inputQs := []*survey.Question{
{
Name: "datastream_type",
Prompt: &survey.Select{
Message: "Input Data Stream type:",
Options: []string{"logs", "metrics"},
Default: "logs",
},
Validate: survey.Required,
},
{
Name: "subobjects",
Prompt: &survey.Confirm{
Message: "Enable creation of subobjects for fields with dots in their names?",
Default: false,
},
Validate: survey.Required,
},
}
qs = append(qs, inputQs...)
}
err = survey.Ask(qs, &answers)
if err != nil {
return fmt.Errorf("prompt failed: %w", err)
}
descriptor := createPackageDescriptorFromAnswers(answers)
specVersion, err := archetype.GetLatestStableSpecVersion()
if err != nil {
return fmt.Errorf("failed to get spec version: %w", err)
}
descriptor.Manifest.SpecVersion = specVersion.String()
err = archetype.CreatePackage(descriptor)
if err != nil {
return fmt.Errorf("can't create new package: %w", err)
}
cmd.Println("Done")
return nil
}
func createPackageDescriptorFromAnswers(answers newPackageAnswers) archetype.PackageDescriptor {
sourceLicense := ""
if answers.SourceLicense != noLicenseValue {
sourceLicense = answers.SourceLicense
}
var elasticsearch *packages.Elasticsearch
inputDataStreamType := ""
if answers.Type == "input" {
inputDataStreamType = answers.DataStreamType
if !answers.Subobjects {
elasticsearch = &packages.Elasticsearch{
IndexTemplate: &packages.ManifestIndexTemplate{
Mappings: &packages.ManifestMappings{
Subobjects: false,
},
},
}
}
}
return archetype.PackageDescriptor{
Manifest: packages.PackageManifest{
Name: answers.Name,
Title: answers.Title,
Type: answers.Type,
Version: answers.Version,
Source: packages.Source{
License: sourceLicense,
},
Conditions: packages.Conditions{
Kibana: packages.KibanaConditions{
Version: answers.KibanaVersion,
},
Elastic: packages.ElasticConditions{
Subscription: answers.ElasticSubscription,
},
},
Owner: packages.Owner{
Github: answers.GithubOwner,
Type: answers.OwnerType,
},
License: answers.ElasticSubscription,
Description: answers.Description,
Categories: answers.Categories,
Elasticsearch: elasticsearch,
},
InputDataStreamType: inputDataStreamType,
}
}