Skip to content

Commit

Permalink
chore(synthetics): resolved merge conflict in go.mod
Browse files Browse the repository at this point in the history
  • Loading branch information
pranav-new-relic committed Aug 29, 2023
2 parents ef51cd1 + 178f2d5 commit 2dc3b68
Show file tree
Hide file tree
Showing 15 changed files with 350 additions and 64 deletions.
17 changes: 15 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
<a name="v0.70.0"></a>
## [v0.70.0] - 2023-08-21
### Features
- Add support for DiscoveryMode Schema Update ([#1502](https://github.com/newrelic/newrelic-cli/issues/1502))

<a name="v0.69.0"></a>
## [v0.69.0] - 2023-08-03
### Features
- custom attributes via stringslicevar ([#1496](https://github.com/newrelic/newrelic-cli/issues/1496))
- entity deployment customattributes ([#1492](https://github.com/newrelic/newrelic-cli/issues/1492))

<a name="v0.68.25"></a>
## [v0.68.25] - 2023-07-24
## [v0.68.25] - 2023-07-31
<a name="v0.68.24"></a>
## [v0.68.24] - 2023-07-24
<a name="v0.68.23"></a>
Expand Down Expand Up @@ -2086,7 +2097,9 @@
- **profile:** Enable reading of profiles and use Region/APIKey from default profile
- **profile:** Add listing of profiles to command

[Unreleased]: https://github.com/newrelic/newrelic-cli/compare/v0.68.25...HEAD
[Unreleased]: https://github.com/newrelic/newrelic-cli/compare/v0.70.0...HEAD
[v0.70.0]: https://github.com/newrelic/newrelic-cli/compare/v0.69.0...v0.70.0
[v0.69.0]: https://github.com/newrelic/newrelic-cli/compare/v0.68.25...v0.69.0
[v0.68.25]: https://github.com/newrelic/newrelic-cli/compare/v0.68.24...v0.68.25
[v0.68.24]: https://github.com/newrelic/newrelic-cli/compare/v0.68.23...v0.68.24
[v0.68.23]: https://github.com/newrelic/newrelic-cli/compare/v0.68.22...v0.68.23
Expand Down
51 changes: 41 additions & 10 deletions internal/entities/command_deployment.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package entities

import (
"errors"
"log"
"strings"
"time"

"github.com/spf13/cobra"
Expand All @@ -17,15 +19,16 @@ import (
)

var (
changelog string
commit string
deepLink string
deploymentType string
description string
groupID string
timestamp int64
user string
version string
changelog string
commit string
customAttribute []string
deepLink string
deploymentType string
description string
groupID string
timestamp int64
user string
version string
)

var cmdEntityDeployment = &cobra.Command{
Expand All @@ -45,7 +48,7 @@ var cmdEntityDeploymentCreate = &cobra.Command{
The deployment command marks a change for a New Relic entity
`,
Example: "newrelic entity deployment create --guid <GUID> --version <0.0.1> --changelog 'what changed' --commit '12345e' --deepLink <link back to deployer> --deploymentType 'BASIC' --description 'about' --timestamp <1668446197100> --user 'jenkins-bot'",
Example: "newrelic entity deployment create --guid <GUID> --version <0.0.1> --changelog 'what changed' --commit '12345e' --customAttribute test1:123,test2:456 --deepLink <link back to deployer> --deploymentType 'BASIC' --description 'about' --timestamp <1668446197100> --user 'jenkins-bot'",
PreRun: client.RequireClient,
Run: func(cmd *cobra.Command, args []string) {
params := changetracking.ChangeTrackingDeploymentInput{}
Expand All @@ -60,8 +63,15 @@ The deployment command marks a change for a New Relic entity
log.Fatal("--version cannot be empty")
}

customAttributes, err := parseCustomAttributes(&customAttribute)

if err != nil {
log.Fatal(err)
}

params.Changelog = changelog
params.Commit = commit
params.CustomAttributes = customAttributes
params.DeepLink = deepLink
params.DeploymentType = changetracking.ChangeTrackingDeploymentType(deploymentType)
params.Description = description
Expand Down Expand Up @@ -89,10 +99,31 @@ func init() {

cmdEntityDeploymentCreate.Flags().StringVar(&changelog, "changelog", "", "a URL for the changelog or list of changes if not linkable")
cmdEntityDeploymentCreate.Flags().StringVar(&commit, "commit", "", "the commit identifier, for example, a Git commit SHA")
cmdEntityDeploymentCreate.Flags().StringSliceVar(&customAttribute, "customAttribute", []string{}, "(EARLY ACCESS) a comma separated list of key:value custom attributes to apply to the deployment")
cmdEntityDeploymentCreate.Flags().StringVar(&deepLink, "deepLink", "", "a link back to the system generating the deployment")
cmdEntityDeploymentCreate.Flags().StringVar(&deploymentType, "deploymentType", "", "type of deployment, one of BASIC, BLUE_GREEN, CANARY, OTHER, ROLLING or SHADOW")
cmdEntityDeploymentCreate.Flags().StringVar(&description, "description", "", "a description of the deployment")
cmdEntityDeploymentCreate.Flags().StringVar(&groupID, "groupId", "", "string that can be used to correlate two or more events")
cmdEntityDeploymentCreate.Flags().Int64VarP(&timestamp, "timestamp", "t", 0, "the start time of the deployment, the number of milliseconds since the Unix epoch, defaults to now")
cmdEntityDeploymentCreate.Flags().StringVarP(&user, "user", "u", "", "username of the deployer or bot")
}

func parseCustomAttributes(a *[]string) (*map[string]string, error) {
customAttributeMap := make(map[string]string)

if len(*a) < 1 {
return nil, nil
}

for _, v := range *a {
pair := strings.Split(v, ":")

if len(pair) != 2 {
return nil, errors.New("invalid format, please use comma separated key-value pairs (--customAttribute key1:value1,key2:value2)")
}

customAttributeMap[pair[0]] = pair[1]
}

return &customAttributeMap, nil
}
79 changes: 79 additions & 0 deletions internal/entities/command_deployment_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package entities

import (
"errors"
"testing"

"github.com/newrelic/newrelic-cli/internal/testcobra"
Expand All @@ -21,3 +22,81 @@ func TestEntityDeploymentCreate(t *testing.T) {
testcobra.CheckCobraRequiredFlags(t, cmdEntityDeploymentCreate,
[]string{"guid", "version"})
}

func TestParseAttributesSingleKeyValue(t *testing.T) {
a := []string{
"key:value",
}

var want = map[string]string{
"key": "value",
}
var errWant error

got, errGot := parseCustomAttributes(&a)

assert.Equal(t, errWant, errGot)
assert.Equal(t, want, *got)
}

func TestParseAttributesTwoKeyValues(t *testing.T) {
a := []string{
"key:value",
"key2:value2",
}

var want = map[string]string{
"key": "value",
"key2": "value2",
}
var errWant error

got, errGot := parseCustomAttributes(&a)

assert.Equal(t, errWant, errGot)
assert.Equal(t, want, *got)
}

func TestParseAttributesKeyNoValue(t *testing.T) {
a := []string{
"key",
}

want := nilPointerMapStringString()
errWant := errors.New("invalid format, please use comma separated key-value pairs (--customAttribute key1:value1,key2:value2)")

got, errGot := parseCustomAttributes(&a)

assert.Equal(t, errWant, errGot)
assert.Equal(t, want, got)
}

func TestParseAttributesTooManyColons(t *testing.T) {
a := []string{
"key:value:extra",
}

want := nilPointerMapStringString()
errWant := errors.New("invalid format, please use comma separated key-value pairs (--customAttribute key1:value1,key2:value2)")

got, errGot := parseCustomAttributes(&a)

assert.Equal(t, errWant, errGot)
assert.Equal(t, want, got)
}

func TestParseAttributesEmptyStringSlice(t *testing.T) {
a := []string{}

want := nilPointerMapStringString()
var errWant error

got, errGot := parseCustomAttributes(&a)

assert.Equal(t, errWant, errGot)
assert.Equal(t, want, got)
}

func nilPointerMapStringString() *map[string]string {
return nil
}
2 changes: 1 addition & 1 deletion internal/install/recipe_install_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ func (rib *RecipeInstallBuilder) Build() *RecipeInstall {
recipeInstall.progressIndicator = rib.progressIndicator
recipeInstall.agentValidator = rib.agentValidator
recipeInstall.recipeValidator = rib.recipeValidator
recipeInstall.recipeDetectorFactory = func(ctx context.Context, repo *recipes.RecipeRepository) RecipeStatusDetector {
recipeInstall.recipeDetectorFactory = func(ctx context.Context, repo *recipes.RecipeRepository, ic *types.InstallerContext) RecipeStatusDetector {
return rib.recipeDetector
}
mockProcessEvaluator := recipes.NewMockProcessEvaluator()
Expand Down
36 changes: 6 additions & 30 deletions internal/install/recipe_installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ type RecipeInstall struct {
bundlerFactory func(ctx context.Context, availableRecipes recipes.RecipeDetectionResults) RecipeBundler
bundleInstallerFactory func(ctx context.Context, manifest *types.DiscoveryManifest, recipeInstallerInterface RecipeInstaller, statusReporter StatusReporter) RecipeBundleInstaller
progressIndicator ux.ProgressIndicator
recipeDetectorFactory func(ctx context.Context, repo *recipes.RecipeRepository) RecipeStatusDetector
recipeDetectorFactory func(ctx context.Context, repo *recipes.RecipeRepository, ic *types.InstallerContext) RecipeStatusDetector
processEvaluator recipes.ProcessEvaluatorInterface
}

Expand Down Expand Up @@ -118,8 +118,8 @@ func NewRecipeInstaller(ic types.InstallerContext, nrClient *newrelic.NewRelic,
i.bundleInstallerFactory = func(ctx context.Context, manifest *types.DiscoveryManifest, recipeInstallerInterface RecipeInstaller, statusReporter StatusReporter) RecipeBundleInstaller {
return NewBundleInstaller(ctx, manifest, recipeInstallerInterface, statusReporter)
}
i.recipeDetectorFactory = func(ctx context.Context, repo *recipes.RecipeRepository) RecipeStatusDetector {
return recipes.NewRecipeDetector(ctx, repo, i.processEvaluator)
i.recipeDetectorFactory = func(ctx context.Context, repo *recipes.RecipeRepository, ic *types.InstallerContext) RecipeStatusDetector {
return recipes.NewRecipeDetector(ctx, repo, i.processEvaluator, ic)
}
return &i
}
Expand Down Expand Up @@ -284,7 +284,6 @@ func (i *RecipeInstall) connectToPlatform() error {
}

func (i *RecipeInstall) install(ctx context.Context) error {

installLibraryVersion := i.recipeFetcher.FetchLibraryVersion(ctx)
log.Debugf("Using open-install-library version %s", installLibraryVersion)
i.status.SetVersions(installLibraryVersion)
Expand All @@ -302,32 +301,12 @@ func (i *RecipeInstall) install(ctx context.Context) error {

i.printStartInstallingMessage(repo)

recipeDetector := i.recipeDetectorFactory(ctx, repo)
recipeDetector := i.recipeDetectorFactory(ctx, repo, &i.InstallerContext)
availableRecipes, unavailableRecipes, err := recipeDetector.GetDetectedRecipes()
if err != nil {
return err
}

isTargetedInstall := i.RecipeNamesProvided() && len(i.RecipeNames) > 0
isTargetingOTEL := false

for _, r := range i.RecipeNames {
if r == types.OTELRecipeName {
isTargetingOTEL = true
break
}
}

if !isTargetedInstall || !isTargetingOTEL {
availableRecipesMinusExclusions := recipes.RecipeDetectionResults{}
for _, ar := range availableRecipes {
if ar.Recipe.Name != types.OTELRecipeName {
availableRecipesMinusExclusions = append(availableRecipesMinusExclusions, ar)
}
}
availableRecipes = availableRecipesMinusExclusions
}

i.reportRecipeStatuses(availableRecipes, unavailableRecipes)

if len(availableRecipes) == 0 && !i.RecipeNamesProvided() {
Expand Down Expand Up @@ -368,8 +347,8 @@ func (i *RecipeInstall) printStartInstallingMessage(repo *recipes.RecipeReposito
}

func (i *RecipeInstall) reportRecipeStatuses(availableRecipes recipes.RecipeDetectionResults,
unavailableRecipes recipes.RecipeDetectionResults) {

unavailableRecipes recipes.RecipeDetectionResults,
) {
for _, d := range unavailableRecipes {
e := execution.RecipeStatusEvent{Recipe: *d.Recipe, ValidationDurationMs: d.DurationMs}
i.status.ReportStatus(d.Status, e)
Expand Down Expand Up @@ -420,7 +399,6 @@ func (i *RecipeInstall) isTargetInstallRecipe(recipeName string) bool {
}

func (i *RecipeInstall) installAdditionalBundle(bundler RecipeBundler, bundleInstaller RecipeBundleInstaller, repo *recipes.RecipeRepository) error {

var additionalBundle *recipes.Bundle
if i.RecipeNamesProvided() {
additionalBundle = bundler.CreateAdditionalTargetedBundle(i.RecipeNames)
Expand All @@ -447,7 +425,6 @@ func (i *RecipeInstall) installAdditionalBundle(bundler RecipeBundler, bundleIns
}

func (i *RecipeInstall) installCoreBundle(bundler RecipeBundler, bundleInstaller RecipeBundleInstaller) error {

if i.shouldInstallCore() {
coreBundle := bundler.CreateCoreBundle()
log.Debugf("Core bundle recipes:%s", coreBundle)
Expand Down Expand Up @@ -706,7 +683,6 @@ func (i *RecipeInstall) executeAndValidateWithProgress(ctx context.Context, m *t
}

entityGUID, err := i.executeAndValidate(ctx, m, r, vars, assumeYes)

if err != nil {
errorChan <- err
return
Expand Down
13 changes: 7 additions & 6 deletions internal/install/recipe_installer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,14 +168,17 @@ func TestInstallGuidedShouldNotSkipCoreInstall(t *testing.T) {
assert.Equal(t, 1, statusReporter.ReportInstalled[r.Recipe.Name], "Recipe1 Installed")
assert.Equal(t, 1, statusReporter.ReportInstalled[r2.Recipe.Name], "Recipe2 Installed")
}

func TestInstallGuidedShouldSkipOTEL(t *testing.T) {
r := &recipes.RecipeDetectionResult{
Recipe: recipes.NewRecipeBuilder().Name(types.InfraAgentRecipeName).Build(),
Status: execution.RecipeStatusTypes.AVAILABLE,
}
r2 := &recipes.RecipeDetectionResult{
Recipe: recipes.NewRecipeBuilder().Name(types.OTELRecipeName).Build(),
Status: execution.RecipeStatusTypes.AVAILABLE,
Recipe: recipes.NewRecipeBuilder().Name("OTEL").WithDiscoveryMode([]types.OpenInstallationDiscoveryMode{
types.OpenInstallationDiscoveryModeTypes.TARGETED,
}).Build(),
Status: execution.RecipeStatusTypes.NULL,
}
statusReporter := execution.NewMockStatusReporter()
recipeInstall := NewRecipeInstallBuilder().WithRecipeDetectionResult(r).WithRecipeDetectionResult(r2).WithStatusReporter(statusReporter).Build()
Expand Down Expand Up @@ -257,11 +260,11 @@ func TestInstallTargetedInstallShouldInstallWithRecomendataion(t *testing.T) {

func TestInstallTargetedShouldNotSkipOTEL(t *testing.T) {
r := &recipes.RecipeDetectionResult{
Recipe: recipes.NewRecipeBuilder().Name(types.OTELRecipeName).Build(),
Recipe: recipes.NewRecipeBuilder().Name("OTEL").Build(),
Status: execution.RecipeStatusTypes.AVAILABLE,
}
statusReporter := execution.NewMockStatusReporter()
recipeInstall := NewRecipeInstallBuilder().WithRecipeDetectionResult(r).WithTargetRecipeName(types.OTELRecipeName).WithStatusReporter(statusReporter).Build()
recipeInstall := NewRecipeInstallBuilder().WithRecipeDetectionResult(r).WithTargetRecipeName("OTEL").WithStatusReporter(statusReporter).Build()
recipeInstall.AssumeYes = true
err := recipeInstall.Install()

Expand Down Expand Up @@ -534,7 +537,6 @@ func TestInstallWhenInstallIsCancelled(t *testing.T) {
}

func TestInstallWhenInstallIsUnsupported(t *testing.T) {

expected := &types.UnsupportedOperatingSystemError{Err: errors.New("Unsupported")}
r := &recipes.RecipeDetectionResult{
Recipe: recipes.NewRecipeBuilder().Name("Other").Build(),
Expand All @@ -555,7 +557,6 @@ func TestInstallWhenInstallIsUnsupported(t *testing.T) {
assert.Equal(t, 0, statusReporter.RecipeRecommendedCallCount, "Recommendation Count")
assert.Equal(t, 0, statusReporter.RecipeSkippedCallCount, "Skipped Count")
assert.Equal(t, 0, statusReporter.RecipeCanceledCallCount, "Cancelled Count")

}

func TestExecuteAndValidateWithProgressWhenInstallWithNoValidationMethod(t *testing.T) {
Expand Down
Loading

0 comments on commit 2dc3b68

Please sign in to comment.