in cmd/hub/state/explain.go [48:206]
func Explain(elaborateManifests, stateFilenames []string, opLog, global bool, componentName string, rawOutputs bool,
format string /*text, kv, sh, json, yaml*/, color bool) {
if (color || config.Tty) && format == "text" {
headColor = func(str string) string {
return aurora.Green(str).String()
}
}
if format != "text" && config.Verbose && !config.Debug {
config.Verbose = false
}
if opLog && format != "text" {
log.Fatal("Lifecycle operations log can only be explained in text format")
}
state := MustParseStateFiles(stateFilenames)
components := state.Lifecycle.Order
if opLog {
printOpLog(state)
return
}
var stackManifest *manifest.Manifest
if len(elaborateManifests) > 0 {
var err error
stackManifest, _, _, err = manifest.ParseManifest(elaborateManifests)
if err != nil {
util.Warn("Unable to parse: %v", err)
} else if stackManifest != nil {
order, err := manifest.GenerateLifecycleOrder(stackManifest)
if err != nil {
log.Fatal(err)
}
stackManifest.Lifecycle.Order = order
components = stackManifest.Lifecycle.Order
}
}
var prevOutputs []parameters.CapturedOutput
if componentName != "" {
if stackManifest != nil {
manifest.CheckComponentsExist(stackManifest.Components, componentName)
}
for i, c := range components {
if c == componentName {
if i > 0 {
prevComponentState, exist := state.Components[components[i-1]]
if exist {
prevOutputs = prevComponentState.CapturedOutputs
}
}
}
}
components = []string{componentName}
}
if format == "text" {
if global || componentName == "" {
fmt.Printf("Kind: %s\n", state.Meta.Kind)
fmt.Printf("Name: %s\n", state.Meta.Name)
fmt.Printf("Timestamp: %v\n", state.Timestamp.Truncate(time.Second))
fmt.Printf("Status: %s\n", state.Status)
if state.Message != "" {
fmt.Printf("Message: %s\n", state.Message)
}
fmt.Print(headColor("Stack parameters:\n"))
printLockedParameters(state.StackParameters)
printStackOutputs(state.StackOutputs)
printProvides(state.Provides)
}
if !global || componentName != "" {
for _, component := range components {
if step, exist := state.Components[component]; exist {
fmt.Printf("Component: %s\n", headColor(component))
printComponenentState(component, step, prevOutputs, rawOutputs)
prevOutputs = step.CapturedOutputs
}
}
}
} else {
explained := ExplainedState{
Meta: state.Meta,
Timestamp: state.Timestamp,
Status: state.Status,
Message: state.Message,
StackParameters: make(map[string]string),
StackOutputs: make(map[string]string),
Components: make(map[string]ExplainedComponent),
}
if global || componentName == "" {
for _, parameter := range state.StackParameters {
explained.StackParameters[parameter.QName()] = util.String(parameter.Value)
}
for _, output := range state.StackOutputs {
explained.StackOutputs[output.Name] = util.String(output.Value)
}
explained.Provides = state.Provides
}
if !global || componentName != "" {
for _, component := range components {
if step, exist := state.Components[component]; exist {
comp := ExplainedComponent{
Timestamp: step.Timestamp,
Timestamps: step.Timestamps,
Status: step.Status,
Message: step.Message,
Parameters: make(map[string]string),
Outputs: make(map[string]string),
RawOutputs: make(map[string]string),
}
for _, parameter := range step.Parameters {
comp.Parameters[parameter.Name] = util.String(parameter.Value)
}
for _, output := range DiffOutputs(step.CapturedOutputs, prevOutputs) {
comp.Outputs[output.Name] = util.String(output.Value)
}
prevOutputs = step.CapturedOutputs
if rawOutputs {
for _, output := range step.RawOutputs {
comp.RawOutputs[output.Name] = output.Value
}
}
explained.Components[component] = comp
}
}
}
var bytes []byte
var err error
switch format {
case "json":
bytes, err = json.MarshalIndent(&explained, "", " ")
case "yaml":
bytes, err = yaml.Marshal(&explained)
// case "sh":
default:
log.Fatalf("`%s` output format is not implemented", format)
}
if err != nil {
log.Fatalf("Unable to explain in `%s` format: %v", format, err)
}
written, err := os.Stdout.Write(bytes)
if err != nil || written != len(bytes) {
log.Fatalf("Error writting output (wrote %d of ouf %d bytes): %v", written, len(bytes), err)
}
}
}