diff --git a/.github/workflows/audit.yaml b/.github/workflows/audit.yaml index 7c1fab3..fa92dc2 100644 --- a/.github/workflows/audit.yaml +++ b/.github/workflows/audit.yaml @@ -14,7 +14,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: 1.22 + go-version: 1.23 - name: Download dependencies run: go mod download diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 839ea69..9ab0e91 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -29,7 +29,7 @@ jobs: name: Set up Go uses: actions/setup-go@v5 with: - go-version: 1.22 + go-version: 1.23 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/cmd/root.go b/cmd/root.go index f36dc5b..5beb582 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -19,6 +19,7 @@ import ( "bunnyshell.com/cli/cmd/template" "bunnyshell.com/cli/cmd/utils" "bunnyshell.com/cli/cmd/variable" + "bunnyshell.com/cli/cmd/variable_group" "bunnyshell.com/cli/cmd/version" "bunnyshell.com/cli/pkg/build" "bunnyshell.com/cli/pkg/config" @@ -96,6 +97,7 @@ func init() { project_variable.GetMainCommand(), registry_integration.GetMainCommand(), variable.GetMainCommand(), + variable_group.GetMainCommand(), k8sIntegration.GetMainCommand(), pipeline.GetMainCommand(), secret.GetMainCommand(), diff --git a/cmd/variable_group/action/create.go b/cmd/variable_group/action/create.go new file mode 100644 index 0000000..717ce1e --- /dev/null +++ b/cmd/variable_group/action/create.go @@ -0,0 +1,81 @@ +package action + +import ( + "io" + "os" + + "bunnyshell.com/cli/pkg/api/variable_group" + "bunnyshell.com/cli/pkg/config" + "bunnyshell.com/cli/pkg/lib" + "bunnyshell.com/cli/pkg/util" + "github.com/spf13/cobra" +) + +func init() { + options := config.GetOptions() + settings := config.GetSettings() + + createOptions := variable_group.NewCreateOptions() + + command := &cobra.Command{ + Use: "create", + + ValidArgsFunction: cobra.NoFileCompletions, + + PreRunE: func(cmd *cobra.Command, args []string) error { + hasStdin, err := util.IsStdinPresent() + if err != nil { + return err + } + + flags := cmd.Flags() + if !flags.Changed("value") && !hasStdin { + return errMissingValue + } + + if flags.Changed("value") && hasStdin { + return errMultipleValueInputs + } + + return nil + }, + + RunE: func(cmd *cobra.Command, args []string) error { + createOptions.Environment = settings.Profile.Context.Environment + + hasStdin, err := util.IsStdinPresent() + if err != nil { + return err + } + + if hasStdin { + buf, err := io.ReadAll(os.Stdin) + if err != nil { + return err + } + + createOptions.Value = string(buf) + } + + model, err := variable_group.Create(createOptions) + if err != nil { + return lib.FormatCommandError(cmd, err) + } + + return lib.FormatCommandData(cmd, model) + }, + } + + flags := command.Flags() + + flags.AddFlag(options.Environment.AddFlagWithExtraHelp( + "environment", + "Environment for the variable", + "Environments contain multiple variables", + util.FlagRequired, + )) + + createOptions.UpdateFlagSet(flags) + + mainCmd.AddCommand(command) +} diff --git a/cmd/variable_group/action/delete.go b/cmd/variable_group/action/delete.go new file mode 100644 index 0000000..62af436 --- /dev/null +++ b/cmd/variable_group/action/delete.go @@ -0,0 +1,34 @@ +package action + +import ( + "bunnyshell.com/cli/pkg/api/variable_group" + "bunnyshell.com/cli/pkg/lib" + "github.com/spf13/cobra" +) + +func init() { + deleteOptions := variable_group.NewDeleteOptions() + + command := &cobra.Command{ + Use: "delete", + + ValidArgsFunction: cobra.NoFileCompletions, + + RunE: func(cmd *cobra.Command, args []string) error { + err := variable_group.Delete(deleteOptions) + if err != nil { + return lib.FormatCommandError(cmd, err) + } + + cmd.Printf("\nGrouped environment variable %s successfully deleted\n", deleteOptions.ID) + + return nil + }, + } + + flags := command.Flags() + + flags.AddFlag(GetIDOption(&deleteOptions.ID).GetRequiredFlag("id")) + + mainCmd.AddCommand(command) +} diff --git a/cmd/variable_group/action/edit.go b/cmd/variable_group/action/edit.go new file mode 100644 index 0000000..25b7d88 --- /dev/null +++ b/cmd/variable_group/action/edit.go @@ -0,0 +1,70 @@ +package action + +import ( + "io" + "os" + + "bunnyshell.com/cli/pkg/api/variable_group" + "bunnyshell.com/cli/pkg/lib" + "bunnyshell.com/cli/pkg/util" + "github.com/spf13/cobra" +) + +func init() { + editOptions := variable_group.NewEditOptions("") + + command := &cobra.Command{ + Use: "edit", + + ValidArgsFunction: cobra.NoFileCompletions, + + PreRunE: func(cmd *cobra.Command, _ []string) error { + hasStdin, err := util.IsStdinPresent() + if err != nil { + return err + } + + flags := cmd.Flags() + if flags.Changed("value") && hasStdin { + return errMultipleValueInputs + } + + return nil + }, + + RunE: func(cmd *cobra.Command, _ []string) error { + flags := cmd.Flags() + if flags.Changed("value") { + editOptions.EnvironItemEditAction.SetValue(flags.Lookup("value").Value.String()) + } + + hasStdin, err := util.IsStdinPresent() + if err != nil { + return err + } + + if hasStdin { + buf, err := io.ReadAll(os.Stdin) + if err != nil { + return err + } + + editOptions.EnvironItemEditAction.SetValue(string(buf)) + } + + model, err := variable_group.Edit(editOptions) + if err != nil { + return lib.FormatCommandError(cmd, err) + } + + return lib.FormatCommandData(cmd, model) + }, + } + + flags := command.Flags() + + flags.AddFlag(GetIDOption(&editOptions.ID).GetRequiredFlag("id")) + editOptions.UpdateFlagSet(flags) + + mainCmd.AddCommand(command) +} diff --git a/cmd/variable_group/action/root.go b/cmd/variable_group/action/root.go new file mode 100644 index 0000000..9dd1a47 --- /dev/null +++ b/cmd/variable_group/action/root.go @@ -0,0 +1,34 @@ +package action + +import ( + "errors" + "fmt" + + "bunnyshell.com/cli/pkg/build" + "bunnyshell.com/cli/pkg/config/option" + "github.com/spf13/cobra" +) + +var ( + errMissingValue = errors.New("the plain value must be provided") + errMultipleValueInputs = errors.New("the value must be provided either by argument or by stdin, not both") +) + +var mainCmd = &cobra.Command{} + +func GetMainCommand() *cobra.Command { + return mainCmd +} + +func GetIDOption(value *string) *option.String { + help := fmt.Sprintf( + `Find available environment variables with "%s variables list"`, + build.Name, + ) + + idOption := option.NewStringOption(value) + + idOption.AddFlagWithExtraHelp("id", "Environment Variable Id", help) + + return idOption +} diff --git a/cmd/variable_group/list.go b/cmd/variable_group/list.go new file mode 100644 index 0000000..c67ad15 --- /dev/null +++ b/cmd/variable_group/list.go @@ -0,0 +1,39 @@ +package variable_group + +import ( + "bunnyshell.com/cli/pkg/api/variable_group" + "bunnyshell.com/cli/pkg/config" + "bunnyshell.com/cli/pkg/lib" + "github.com/spf13/cobra" +) + +func init() { + options := config.GetOptions() + settings := config.GetSettings() + + listOptions := variable_group.NewListOptions() + + command := &cobra.Command{ + Use: "list", + + ValidArgsFunction: cobra.NoFileCompletions, + + RunE: func(cmd *cobra.Command, _ []string) error { + listOptions.Organization = settings.Profile.Context.Organization + listOptions.Environment = settings.Profile.Context.Environment + + return lib.ShowCollection(cmd, listOptions, func() (lib.ModelWithPagination, error) { + return variable_group.List(listOptions) + }) + }, + } + + flags := command.Flags() + + flags.AddFlag(options.Organization.GetFlag("organization")) + flags.AddFlag(options.Environment.GetFlag("environment")) + + listOptions.UpdateFlagSet(flags) + + mainCmd.AddCommand(command) +} diff --git a/cmd/variable_group/root.go b/cmd/variable_group/root.go new file mode 100644 index 0000000..f79006c --- /dev/null +++ b/cmd/variable_group/root.go @@ -0,0 +1,33 @@ +package variable_group + +import ( + "bunnyshell.com/cli/cmd/variable_group/action" + "bunnyshell.com/cli/pkg/config" + "bunnyshell.com/cli/pkg/util" + "github.com/spf13/cobra" +) + +var mainCmd = &cobra.Command{ + Use: "variables-groups", + Aliases: []string{"variables-group", "var-groups", "var-group", "var-g"}, + + Short: "Grouped Environment Variables", + Long: "Bunnyshell Environment Variables in Groups", +} + +func init() { + config.MainManager.CommandWithAPI(mainCmd) + + util.AddGroupedCommands( + mainCmd, + cobra.Group{ + ID: "actions", + Title: "Commands for Environment Variables:", + }, + action.GetMainCommand().Commands(), + ) +} + +func GetMainCommand() *cobra.Command { + return mainCmd +} diff --git a/cmd/variable_group/show.go b/cmd/variable_group/show.go new file mode 100644 index 0000000..7e557fd --- /dev/null +++ b/cmd/variable_group/show.go @@ -0,0 +1,33 @@ +package variable_group + +import ( + "bunnyshell.com/cli/cmd/variable/action" + "bunnyshell.com/cli/pkg/api/variable_group" + "bunnyshell.com/cli/pkg/lib" + "github.com/spf13/cobra" +) + +func init() { + itemOptions := variable_group.NewItemOptions("") + + command := &cobra.Command{ + Use: "show", + + ValidArgsFunction: cobra.NoFileCompletions, + + RunE: func(cmd *cobra.Command, _ []string) error { + model, err := variable_group.Get(itemOptions) + if err != nil { + return lib.FormatCommandError(cmd, err) + } + + return lib.FormatCommandData(cmd, model) + }, + } + + flags := command.Flags() + + flags.AddFlag(action.GetIDOption(&itemOptions.ID).GetRequiredFlag("id")) + + mainCmd.AddCommand(command) +} diff --git a/go.mod b/go.mod index ad304fa..ef0d66d 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,14 @@ module bunnyshell.com/cli -go 1.22.0 +go 1.23 -toolchain go1.22.3 +toolchain go1.23.2 replace github.com/imdario/mergo => github.com/imdario/mergo v0.3.16 require ( bunnyshell.com/dev v0.6.0 - bunnyshell.com/sdk v0.19.2 + bunnyshell.com/sdk v0.20.0 github.com/AlecAivazis/survey/v2 v2.3.7 github.com/MakeNowJust/heredoc v1.0.0 github.com/avast/retry-go/v4 v4.6.0 diff --git a/go.sum b/go.sum index b1dbe3d..d34ce4e 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ bunnyshell.com/dev v0.6.0 h1:JywvLrzxYKgnxegPByh+ET7CwFme6JVeJpWzRuqQTWc= bunnyshell.com/dev v0.6.0/go.mod h1:+Xk46UXX9AW0nHrFMdO/IwpUPfALrck1/qI+LIXsDmE= -bunnyshell.com/sdk v0.19.2 h1:HcwwD4Pv8itkHtZCxowQMIx+9bIzQedTnlZ9WpBwaTQ= -bunnyshell.com/sdk v0.19.2/go.mod h1:RfgfUzZ4WHZGCkToUfu2/hoQS6XsQc8IdPTVAlpS138= +bunnyshell.com/sdk v0.20.0 h1:xcoDn0x1JqexMy5vYGqTBK4DGdY3juc+5DU7vb1yFeA= +bunnyshell.com/sdk v0.20.0/go.mod h1:RfgfUzZ4WHZGCkToUfu2/hoQS6XsQc8IdPTVAlpS138= github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ= github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= diff --git a/pkg/api/variable_group/action_create.go b/pkg/api/variable_group/action_create.go new file mode 100644 index 0000000..59c4ca1 --- /dev/null +++ b/pkg/api/variable_group/action_create.go @@ -0,0 +1,76 @@ +package variable_group + +import ( + "net/http" + + "bunnyshell.com/cli/pkg/api" + "bunnyshell.com/cli/pkg/api/common" + "bunnyshell.com/cli/pkg/config/enum" + "bunnyshell.com/cli/pkg/lib" + "bunnyshell.com/cli/pkg/util" + "bunnyshell.com/sdk" + "github.com/spf13/pflag" +) + +type CreateOptions struct { + common.Options + + sdk.EnvironItemCreateAction + + Value string + IsSecret enum.Bool +} + +func NewCreateOptions() *CreateOptions { + return &CreateOptions{ + EnvironItemCreateAction: *sdk.NewEnvironItemCreateActionWithDefaults(), + } +} + +func (co *CreateOptions) UpdateFlagSet(flags *pflag.FlagSet) { + flags.StringVar(&co.GroupName, "group", co.GroupName, "Environment variable group name") + util.MarkFlagRequiredWithHelp(flags.Lookup("group"), "The group in which the environment variable should be created") + + flags.StringVar(&co.Name, "name", co.Name, "Unique name for the environment variable") + util.MarkFlagRequiredWithHelp(flags.Lookup("name"), "A unique name within the environment for the new environment variable") + + flags.StringVar(&co.Value, "value", co.Value, "The value of the environment variable") + util.AppendFlagHelp(flags.Lookup("value"), "A value for this environment variable") + util.MarkFlag(flags.Lookup("value"), util.FlagAllowBlank) + + isSecretFlag := enum.BoolFlag( + &co.IsSecret, + "secret", + "Whether the environment variable is secret or not", + ) + flags.AddFlag(isSecretFlag) + isSecretFlag.NoOptDefVal = "true" +} + +func Create(options *CreateOptions) (*sdk.EnvironItemItem, error) { + options.EnvironItemCreateAction.SetValue(options.Value) + + if options.IsSecret == enum.BoolTrue { + options.EnvironItemCreateAction.SetIsSecret(true) + } + + model, resp, err := CreateRaw(options) + if err != nil { + return nil, api.ParseError(resp, err) + } + + return model, nil +} + +func CreateRaw(options *CreateOptions) (*sdk.EnvironItemItem, *http.Response, error) { + profile := options.GetProfile() + + ctx, cancel := lib.GetContextFromProfile(profile) + defer cancel() + + request := lib.GetAPIFromProfile(profile). + EnvironItemAPI.EnvironItemCreate(ctx). + EnvironItemCreateAction(options.EnvironItemCreateAction) + + return request.Execute() +} diff --git a/pkg/api/variable_group/action_delete.go b/pkg/api/variable_group/action_delete.go new file mode 100644 index 0000000..53a5815 --- /dev/null +++ b/pkg/api/variable_group/action_delete.go @@ -0,0 +1,37 @@ +package variable_group + +import ( + "net/http" + + "bunnyshell.com/cli/pkg/api" + "bunnyshell.com/cli/pkg/api/common" + "bunnyshell.com/cli/pkg/lib" +) + +type DeleteOptions struct { + common.ItemOptions +} + +func NewDeleteOptions() *DeleteOptions { + return &DeleteOptions{} +} + +func Delete(options *DeleteOptions) error { + resp, err := DeleteRaw(options) + if err != nil { + return api.ParseError(resp, err) + } + + return nil +} + +func DeleteRaw(options *DeleteOptions) (*http.Response, error) { + profile := options.GetProfile() + + ctx, cancel := lib.GetContextFromProfile(profile) + defer cancel() + + request := lib.GetAPIFromProfile(profile).EnvironItemAPI.EnvironItemDelete(ctx, options.ID) + + return request.Execute() +} diff --git a/pkg/api/variable_group/action_edit.go b/pkg/api/variable_group/action_edit.go new file mode 100644 index 0000000..e3b47dc --- /dev/null +++ b/pkg/api/variable_group/action_edit.go @@ -0,0 +1,82 @@ +package variable_group + +import ( + "net/http" + + "bunnyshell.com/cli/pkg/api" + "bunnyshell.com/cli/pkg/api/common" + "bunnyshell.com/cli/pkg/config/enum" + "bunnyshell.com/cli/pkg/lib" + "bunnyshell.com/sdk" + "github.com/spf13/pflag" +) + +type EditOptions struct { + common.ItemOptions + + sdk.EnvironItemEditAction + + EditData +} + +type EditData struct { + Value string + IsSecret enum.Bool +} + +func NewEditOptions(id string) *EditOptions { + return &EditOptions{ + ItemOptions: *common.NewItemOptions(id), + + EditData: EditData{}, + + EnvironItemEditAction: *sdk.NewEnvironItemEditActionWithDefaults(), + } +} + +func (eso *EditOptions) UpdateFlagSet(flags *pflag.FlagSet) { + data := &eso.EditData + + flags.StringVar(&data.Value, "value", data.Value, "Update the environment variable value") + + isSecretFlag := enum.BoolFlag( + &eso.EditData.IsSecret, + "secret", + "Whether the environment variable is secret or not", + ) + flags.AddFlag(isSecretFlag) + isSecretFlag.NoOptDefVal = "true" +} + +func Edit(options *EditOptions) (*sdk.EnvironItemItem, error) { + model, resp, err := EditRaw(options) + if err != nil { + return nil, api.ParseError(resp, err) + } + + return model, nil +} + +func EditRaw(options *EditOptions) (*sdk.EnvironItemItem, *http.Response, error) { + profile := options.GetProfile() + + ctx, cancel := lib.GetContextFromProfile(profile) + defer cancel() + + request := lib.GetAPIFromProfile(profile).EnvironItemAPI.EnvironItemEdit(ctx, options.ID) + + return applyEditOptions(request, options).Execute() +} + +func applyEditOptions( + request sdk.ApiEnvironItemEditRequest, + options *EditOptions, +) sdk.ApiEnvironItemEditRequest { + if options.EditData.IsSecret != enum.BoolNone { + options.EnvironItemEditAction.SetIsSecret(options.EditData.IsSecret == enum.BoolTrue) + } + + request = request.EnvironItemEditAction(options.EnvironItemEditAction) + + return request +} diff --git a/pkg/api/variable_group/item.go b/pkg/api/variable_group/item.go new file mode 100644 index 0000000..a03d3c7 --- /dev/null +++ b/pkg/api/variable_group/item.go @@ -0,0 +1,34 @@ +package variable_group + +import ( + "net/http" + + "bunnyshell.com/cli/pkg/api" + "bunnyshell.com/cli/pkg/api/common" + "bunnyshell.com/cli/pkg/lib" + "bunnyshell.com/sdk" +) + +func NewItemOptions(id string) *common.ItemOptions { + return common.NewItemOptions(id) +} + +func Get(options *common.ItemOptions) (*sdk.EnvironItemItem, error) { + model, resp, err := GetRaw(options) + if err != nil { + return nil, api.ParseError(resp, err) + } + + return model, nil +} + +func GetRaw(options *common.ItemOptions) (*sdk.EnvironItemItem, *http.Response, error) { + profile := options.GetProfile() + + ctx, cancel := lib.GetContextFromProfile(profile) + defer cancel() + + request := lib.GetAPIFromProfile(profile).EnvironItemAPI.EnvironItemView(ctx, options.ID) + + return request.Execute() +} diff --git a/pkg/api/variable_group/list.go b/pkg/api/variable_group/list.go new file mode 100644 index 0000000..eaa7ba2 --- /dev/null +++ b/pkg/api/variable_group/list.go @@ -0,0 +1,78 @@ +package variable_group + +import ( + "net/http" + + "bunnyshell.com/cli/pkg/api" + "bunnyshell.com/cli/pkg/api/common" + "bunnyshell.com/cli/pkg/lib" + "bunnyshell.com/sdk" + "github.com/spf13/pflag" +) + +type ListOptions struct { + common.ListOptions + + Organization string + Environment string + + Name string + GroupName string +} + +func NewListOptions() *ListOptions { + return &ListOptions{ + ListOptions: *common.NewListOptions(), + } +} + +func (lo *ListOptions) UpdateFlagSet(flags *pflag.FlagSet) { + flags.StringVar(&lo.Name, "name", lo.Name, "Filter by Name") + flags.StringVar(&lo.GroupName, "group", lo.GroupName, "Filter by Group Name") + + lo.ListOptions.UpdateFlagSet(flags) +} + +func List(options *ListOptions) (*sdk.PaginatedEnvironItemCollection, error) { + model, resp, err := ListRaw(options) + if err != nil { + return nil, api.ParseError(resp, err) + } + + return model, nil +} + +func ListRaw(options *ListOptions) (*sdk.PaginatedEnvironItemCollection, *http.Response, error) { + profile := options.GetProfile() + + ctx, cancel := lib.GetContextFromProfile(profile) + defer cancel() + + request := lib.GetAPIFromProfile(profile).EnvironItemAPI.EnvironItemList(ctx) + + return applyOptions(request, options).Execute() +} + +func applyOptions(request sdk.ApiEnvironItemListRequest, options *ListOptions) sdk.ApiEnvironItemListRequest { + if options == nil { + return request + } + + if options.Page > 1 { + request = request.Page(options.Page) + } + + if options.Organization != "" { + request = request.Organization(options.Organization) + } + + if options.Environment != "" { + request = request.Environment(options.Environment) + } + + if options.GroupName != "" { + request = request.GroupName(options.GroupName) + } + + return request +} diff --git a/pkg/formatter/stylish.go b/pkg/formatter/stylish.go index 290a8ad..6e8b9c4 100644 --- a/pkg/formatter/stylish.go +++ b/pkg/formatter/stylish.go @@ -30,6 +30,8 @@ func stylish(data interface{}) ([]byte, error) { tabulateEventCollection(writer, dataType) case *sdk.PaginatedEnvironmentVariableCollection: tabulateEnvironmentVariableCollection(writer, dataType) + case *sdk.PaginatedEnvironItemCollection: + tabulateEnvironCollection(writer, dataType) case *sdk.PaginatedProjectVariableCollection: tabulateProjectVariableCollection(writer, dataType) case *sdk.PaginatedKubernetesIntegrationCollection: @@ -62,6 +64,8 @@ func stylish(data interface{}) ([]byte, error) { tabulateEventItem(writer, dataType) case *sdk.EnvironmentVariableItem: tabulateEnvironmentVariableItem(writer, dataType) + case *sdk.EnvironItemItem: + tabulateEnvironItem(writer, dataType) case *sdk.ProjectVariableItem: tabulateProjectVariableItem(writer, dataType) case *sdk.ServiceComponentVariableItem: diff --git a/pkg/formatter/stylish.variable.groups.go b/pkg/formatter/stylish.variable.groups.go new file mode 100644 index 0000000..6839cef --- /dev/null +++ b/pkg/formatter/stylish.variable.groups.go @@ -0,0 +1,36 @@ +package formatter + +import ( + "fmt" + "text/tabwriter" + + "bunnyshell.com/sdk" +) + +func tabulateEnvironCollection(w *tabwriter.Writer, data *sdk.PaginatedEnvironItemCollection) { + fmt.Fprintf(w, "%v\t %v\t %v\t %v\t %v\n", "EnvVarID", "EnvironmentID", "OrganizationID", "Group", "Name") + + if data.Embedded != nil { + for _, item := range data.Embedded.Item { + fmt.Fprintf( + w, + "%v\t %v\t %v\t %v\t %v\n", + item.GetId(), + item.GetEnvironment(), + item.GetOrganization(), + item.GetGroupName(), + item.GetName(), + ) + } + } +} + +func tabulateEnvironItem(w *tabwriter.Writer, item *sdk.EnvironItemItem) { + fmt.Fprintf(w, "%v\t %v\n", "EnvironmentVariableID", item.GetId()) + fmt.Fprintf(w, "%v\t %v\n", "EnvironmentID", item.GetEnvironment()) + fmt.Fprintf(w, "%v\t %v\n", "OrganizationID", item.GetOrganization()) + fmt.Fprintf(w, "%v\t %v\n", "Group", item.GetGroupName()) + fmt.Fprintf(w, "%v\t %v\n", "Name", item.GetName()) + fmt.Fprintf(w, "%v\t %v\n", "Value", item.GetValue()) + fmt.Fprintf(w, "%v\t %v\n", "Secret", item.GetSecret()) +}