From 6ef2fe7e1ac495200365ec2d113c37a5b77067cc Mon Sep 17 00:00:00 2001 From: Taimoor Ahmad Date: Thu, 14 Sep 2023 17:59:12 -0400 Subject: [PATCH] enable opslevel get tag --type resource alias [key] --- src/cmd/tag.go | 88 ++++++++++++++++++++++++++++++++++++++ src/submodules/opslevel-go | 2 +- 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/src/cmd/tag.go b/src/cmd/tag.go index 2e2a74e4..63491c29 100644 --- a/src/cmd/tag.go +++ b/src/cmd/tag.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + "reflect" "strings" "github.com/opslevel/cli/common" @@ -13,6 +14,42 @@ import ( "github.com/spf13/cobra" ) +type TaggableResourceFetchFunction func(id opslevel.ID) (any, error) + +var TaggableResourceFetchFunctions = map[opslevel.TaggableResource]TaggableResourceFetchFunction{ + opslevel.TaggableResourceService: func(id opslevel.ID) (any, error) { return getClientGQL().GetService(id) }, + opslevel.TaggableResourceRepository: func(id opslevel.ID) (any, error) { return getClientGQL().GetRepository(id) }, + opslevel.TaggableResourceTeam: func(id opslevel.ID) (any, error) { return getClientGQL().GetTeam(id) }, + opslevel.TaggableResourceUser: func(id opslevel.ID) (any, error) { return getClientGQL().GetUser(string(id)) }, + opslevel.TaggableResourceDomain: func(id opslevel.ID) (any, error) { return getClientGQL().GetDomain(string(id)) }, + opslevel.TaggableResourceSystem: func(id opslevel.ID) (any, error) { return getClientGQL().GetSystem(string(id)) }, + opslevel.TaggableResourceInfrastructureresource: func(id opslevel.ID) (any, error) { return getClientGQL().GetInfrastructure(string(id)) }, +} + +type TaggableResourceFetchAliasFunction func(alias string) (any, error) + +var TaggableResourceFetchAliasFunctions = map[opslevel.TaggableResource]TaggableResourceFetchAliasFunction{ + opslevel.TaggableResourceService: func(alias string) (any, error) { return getClientGQL().GetServiceWithAlias(alias) }, + opslevel.TaggableResourceRepository: func(alias string) (any, error) { return getClientGQL().GetRepositoryWithAlias(alias) }, + opslevel.TaggableResourceTeam: func(alias string) (any, error) { return getClientGQL().GetTeamWithAlias(alias) }, + opslevel.TaggableResourceUser: func(alias string) (any, error) { return getClientGQL().GetUser(alias) }, + opslevel.TaggableResourceDomain: func(alias string) (any, error) { return getClientGQL().GetDomain(alias) }, + opslevel.TaggableResourceSystem: func(alias string) (any, error) { return getClientGQL().GetSystem(alias) }, + opslevel.TaggableResourceInfrastructureresource: func(alias string) (any, error) { return getClientGQL().GetInfrastructure(alias) }, +} + +func GetTags(obj interface{}) (*opslevel.TagConnection, error) { + // call Elem because input is a ptr + v := reflect.ValueOf(obj).Elem() + tagsField := v.FieldByName("Tags") + + if tagsField.IsValid() { + return tagsField.Interface().(*opslevel.TagConnection), nil + } else { + return nil, errors.New("reflection error") + } +} + var resourceType string var createTagCmd = &cobra.Command{ @@ -68,6 +105,54 @@ opslevel create tag --type=Team ID|ALIAS KEY VALUE }, } +var getObjectTagCmd = &cobra.Command{ + Use: "tag --type=RESOURCE_TYPE RESOURCE_ID [KEY]", + Short: "Get values of tags on objects", + Long: "Get values of tags on objects", + Example: ` +opslevel get tag --type=Service ID|ALIAS KEY # search for values of a specific key +opslevel get tag --type=Team ID|ALIAS | jq 'from_entries' # values of all keys +`, + Args: cobra.MinimumNArgs(1), + ArgAliases: []string{"RESOURCE_ID", "KEY"}, + Run: func(cmd *cobra.Command, args []string) { + err := validateResourceTypeArg() + cobra.CheckErr(err) + + resource := args[0] + singleTag := len(args) == 2 + var tagKey string + if singleTag { + tagKey = args[1] + } + + var result any + if opslevel.IsID(resource) { + id := opslevel.ID(resource) + result, err = TaggableResourceFetchFunctions[opslevel.TaggableResource(resourceType)](id) + } else { + alias := args[0] + result, err = TaggableResourceFetchAliasFunctions[opslevel.TaggableResource(resourceType)](alias) + } + + tags, err := GetTags(result) + cobra.CheckErr(err) + + var output []opslevel.Tag + for _, tag := range tags.Nodes { + if !singleTag || tagKey == tag.Key { + output = append(output, tag) + } + } + + if singleTag && len(output) == 0 { + err := fmt.Errorf("tag with key '%s' not found on %s '%s'", tagKey, resourceType, resource) + cobra.CheckErr(err) + } + common.PrettyPrint(output) + }, +} + var updateTagCmd = &cobra.Command{ Use: "tag TAG_ID KEY VALUE", Short: "Update a tag", @@ -117,6 +202,9 @@ func init() { createTagCmd.Flags().StringVar(&resourceType, "type", "", "resource type") createTagCmd.Flags().Bool("assign", false, "assign a tag instead of creating it") + getCmd.AddCommand(getObjectTagCmd) + getObjectTagCmd.Flags().StringVar(&resourceType, "type", "", "resource type") + updateCmd.AddCommand(updateTagCmd) deleteCmd.AddCommand(deleteTagCmd) diff --git a/src/submodules/opslevel-go b/src/submodules/opslevel-go index 7a400c8d..1d7b1435 160000 --- a/src/submodules/opslevel-go +++ b/src/submodules/opslevel-go @@ -1 +1 @@ -Subproject commit 7a400c8d396bcf17a2408f7776545a8aee911e53 +Subproject commit 1d7b1435b388d5677c22234654145de9adc8a76d