ctc_lib/container_tool_list_command.go (107 lines of code) (raw):
/*
Copyright 2018 Google Inc. All Rights Reserved.
Licensed 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 ctc_lib
import (
"bytes"
"errors"
"fmt"
"github.com/GoogleCloudPlatform/runtimes-common/ctc_lib/flags"
"github.com/GoogleCloudPlatform/runtimes-common/ctc_lib/constants"
"github.com/GoogleCloudPlatform/runtimes-common/ctc_lib/util"
"github.com/spf13/cobra"
)
type ListCommandOutputObject struct {
OutputList []interface{}
SummaryObject interface{}
}
type ContainerToolListCommand struct {
*ContainerToolCommandBase
OutputList []interface{}
// RunO Executes cobra.Command.Run and returns an List[Output]
RunO func(command *cobra.Command, args []string) ([]interface{}, error)
// When defined, StreamO Executes cobra.Command.Run and streams each item in the List as its added.
// This will ignore the RunO function.
StreamO func(command *cobra.Command, args []string)
// This function will execute over the output list and return a Summary Object which can be printed.
// The SummaryTemplate Field can be used to print the Object.
TotalO func(list []interface{}) (interface{}, error)
SummaryObject interface{}
SummaryTemplate string
// Defines the stream to write objects to when using StreamO
Stream chan interface{}
}
func (commandList ContainerToolListCommand) ReadFromStream(streamOutput bool) ([]interface{}, error) {
results := make([]interface{}, 0)
for obj := range commandList.Stream {
if _, ok := obj.(string); ok {
// Display any Arbitary strings written to the channel as is.
// These could be headers or any text.
// TODO: Provide a callback for users to overwrite this default behavior.
if streamOutput {
util.ExecuteTemplate(constants.EmptyTemplate,
obj, commandList.TemplateFuncMap, commandList.OutOrStdout())
}
continue
}
results = append(results, obj)
if streamOutput {
err := util.ExecuteTemplate(commandList.ReadTemplateFromFlagOrCmdDefault(),
obj, commandList.TemplateFuncMap, commandList.OutOrStdout())
if err != nil {
return nil, err
}
}
}
return results, nil
}
func (commandList ContainerToolListCommand) isRunODefined() bool {
return commandList.RunO != nil || commandList.StreamO != nil
}
func (ctc *ContainerToolListCommand) ValidateCommand() error {
if (ctc.Run != nil || ctc.RunE != nil) && ctc.isRunODefined() {
return errors.New(`Cannot provide both Command.Run and RunO implementation.
Either implement Command.Run implementation or RunO implemetation`)
}
return nil
}
func (ctc *ContainerToolListCommand) printO(c *cobra.Command, args []string) error {
var commandError, totalFuncError, totalDisplayError error
var totalDisplayString string
if ctc.StreamO != nil {
// Stream Objects only when JsonOutput = False
ctc.StreamO(c, args)
ctc.OutputList, commandError = ctc.ReadFromStream(!flags.JsonOutput)
} else {
// Run RunO function.
ctc.OutputList, commandError = ctc.RunO(c, args)
LogIfErr(commandError, Log)
}
totalDisplayString, totalFuncError, totalDisplayError = ctc.runTotalIfDefined()
LogIfErr(totalFuncError, Log)
ctc.printResult(totalDisplayString)
LogIfErr(totalDisplayError, Log)
if commandError == nil && totalDisplayError == nil && totalFuncError == nil {
return nil
} else if commandError != nil {
// Return Command Error if occurred
return commandError
} else if totalFuncError != nil {
// Return TotalFuncError if occurred
return totalFuncError
} else {
return totalDisplayError
}
}
func (ctc *ContainerToolListCommand) runTotalIfDefined() (string, error, error) {
var totalCommandError, totalError error
var OutputBuffer bytes.Buffer
// If TotalO function defined & Summary Template provided, get the summary text
if ctc.TotalO != nil && ctc.SummaryTemplate != "" {
ctc.SummaryObject, totalCommandError = ctc.TotalO(ctc.OutputList)
totalError = util.ExecuteTemplate(ctc.SummaryTemplate,
ctc.SummaryObject, ctc.TemplateFuncMap, &OutputBuffer)
}
return OutputBuffer.String(), totalCommandError, totalError
}
func (ctc *ContainerToolListCommand) printResult(totalDisplayString string) {
if flags.JsonOutput {
data := ListCommandOutputObject{
OutputList: ctc.OutputList,
SummaryObject: ctc.SummaryObject,
}
util.PrintJson(data, ctc.OutOrStdout())
} else {
if ctc.StreamO == nil {
err := util.ExecuteTemplate(ctc.ReadTemplateFromFlagOrCmdDefault(),
ctc.OutputList, ctc.TemplateFuncMap, ctc.OutOrStdout())
LogIfErr(err, Log)
}
// Display total if defined.
if totalDisplayString != "" {
fmt.Fprintln(ctc.OutOrStdout(), totalDisplayString)
}
}
}