Skip to content

Commit

Permalink
Merge pull request #211 from Random-Liu/rewrite-container-status
Browse files Browse the repository at this point in the history
Rewrite timestamps in container/sandbox status.
  • Loading branch information
feiskyer authored Dec 6, 2017
2 parents 6462875 + 5d3d7e0 commit 23a53d2
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 11 deletions.
26 changes: 25 additions & 1 deletion cmd/crictl/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package main

import (
"encoding/json"
"fmt"
"log"
"os"
Expand Down Expand Up @@ -459,6 +460,24 @@ func RemoveContainer(client pb.RuntimeServiceClient, ID string) error {
return nil
}

// marshalContainerStatus converts container status into string and converts
// the timestamps into readable format.
func marshalContainerStatus(cs *pb.ContainerStatus) (string, error) {
statusStr, err := protobufObjectToJSON(cs)
if err != nil {
return "", err
}
jsonMap := make(map[string]interface{})
err = json.Unmarshal([]byte(statusStr), &jsonMap)
if err != nil {
return "", err
}
jsonMap["createdAt"] = time.Unix(0, cs.CreatedAt).Format(time.RFC3339Nano)
jsonMap["startedAt"] = time.Unix(0, cs.StartedAt).Format(time.RFC3339Nano)
jsonMap["finishedAt"] = time.Unix(0, cs.FinishedAt).Format(time.RFC3339Nano)
return marshalMapInOrder(jsonMap, *cs)
}

// ContainerStatus sends a ContainerStatusRequest to the server, and parses
// the returned ContainerStatusResponse.
func ContainerStatus(client pb.RuntimeServiceClient, ID, output string, quiet bool) error {
Expand All @@ -480,9 +499,14 @@ func ContainerStatus(client pb.RuntimeServiceClient, ID, output string, quiet bo
return err
}

status, err := marshalContainerStatus(r.Status)
if err != nil {
return err
}

switch output {
case "json", "yaml":
return outputStatusInfo(r.Status, r.Info, output)
return outputStatusInfo(status, r.Info, output)
case "table": // table output is after this switch block
default:
return fmt.Errorf("output option cannot be %s", output)
Expand Down
6 changes: 5 additions & 1 deletion cmd/crictl/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,9 +217,13 @@ var imageStatusCommand = cli.Command{
output = "json"
}

status, err := protobufObjectToJSON(r.Image)
if err != nil {
return err
}
switch output {
case "json", "yaml":
return outputStatusInfo(r.Image, r.Info, output)
return outputStatusInfo(status, r.Info, output)
case "table": // table output is after this switch block
default:
return fmt.Errorf("output option cannot be %s", output)
Expand Down
6 changes: 5 additions & 1 deletion cmd/crictl/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,9 @@ func Info(cliContext *cli.Context, client pb.RuntimeServiceClient) error {
return err
}

return outputStatusInfo(r.Status, r.Info, cliContext.String("output"))
status, err := protobufObjectToJSON(r.Status)
if err != nil {
return err
}
return outputStatusInfo(status, r.Info, cliContext.String("output"))
}
23 changes: 22 additions & 1 deletion cmd/crictl/sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package main

import (
"encoding/json"
"fmt"
"log"
"os"
Expand Down Expand Up @@ -272,6 +273,22 @@ func RemovePodSandbox(client pb.RuntimeServiceClient, ID string) error {
return nil
}

// marshalPodSandboxStatus converts pod sandbox status into string and converts
// the timestamps into readable format.
func marshalPodSandboxStatus(ps *pb.PodSandboxStatus) (string, error) {
statusStr, err := protobufObjectToJSON(ps)
if err != nil {
return "", err
}
jsonMap := make(map[string]interface{})
err = json.Unmarshal([]byte(statusStr), &jsonMap)
if err != nil {
return "", err
}
jsonMap["createdAt"] = time.Unix(0, ps.CreatedAt).Format(time.RFC3339Nano)
return marshalMapInOrder(jsonMap, *ps)
}

// PodSandboxStatus sends a PodSandboxStatusRequest to the server, and parses
// the returned PodSandboxStatusResponse.
func PodSandboxStatus(client pb.RuntimeServiceClient, ID, output string, quiet bool) error {
Expand All @@ -294,9 +311,13 @@ func PodSandboxStatus(client pb.RuntimeServiceClient, ID, output string, quiet b
return err
}

status, err := marshalPodSandboxStatus(r.Status)
if err != nil {
return err
}
switch output {
case "json", "yaml":
return outputStatusInfo(r.Status, r.Info, output)
return outputStatusInfo(status, r.Info, output)
case "table": // table output is after this switch block
default:
return fmt.Errorf("output option cannot be %s", output)
Expand Down
55 changes: 48 additions & 7 deletions cmd/crictl/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"encoding/json"
"fmt"
"os"
"reflect"
"sort"
"strings"

Expand Down Expand Up @@ -207,14 +208,17 @@ func outputProtobufObjAsYAML(obj proto.Message) error {
return nil
}

func outputStatusInfo(status proto.Message, info map[string]string, format string) error {
statusByte, err := protobufObjectToJSON(status)
if err != nil {
return err
func outputStatusInfo(status string, info map[string]string, format string) error {
// Sort all keys
var keys []string
for k := range info {
keys = append(keys, k)
}
jsonInfo := "{" + "\"status\":" + string(statusByte) + ","
for k, v := range info {
jsonInfo += "\"" + k + "\"" + ":" + v + ","
sort.Strings(keys)

jsonInfo := "{" + "\"status\":" + status + ","
for _, k := range keys {
jsonInfo += "\"" + k + "\"" + ":" + info[k] + ","
}
jsonInfo = jsonInfo[:len(jsonInfo)-1]
jsonInfo += "}"
Expand Down Expand Up @@ -249,3 +253,40 @@ func parseLabelStringSlice(ss []string) (map[string]string, error) {
}
return labels, nil
}

// marshalMapInOrder marshalls a map into json in the order of the original
// data structure.
func marshalMapInOrder(m map[string]interface{}, t interface{}) (string, error) {
s := "{"
v := reflect.ValueOf(t)
for i := 0; i < v.Type().NumField(); i++ {
field := jsonFieldFromTag(v.Type().Field(i).Tag)
if field == "" {
continue
}
value, err := json.Marshal(m[field])
if err != nil {
return "", err
}
s += fmt.Sprintf("%q:%s,", field, value)
}
s = s[:len(s)-1]
s += "}"
var buf bytes.Buffer
if err := json.Indent(&buf, []byte(s), "", " "); err != nil {
return "", err
}
return buf.String(), nil
}

// jsonFieldFromTag gets json field name from field tag.
func jsonFieldFromTag(tag reflect.StructTag) string {
field := strings.Split(tag.Get("json"), ",")[0]
for _, f := range strings.Split(tag.Get("protobuf"), ",") {
if !strings.HasPrefix(f, "json=") {
continue
}
field = strings.TrimPrefix(f, "json=")
}
return field
}

0 comments on commit 23a53d2

Please sign in to comment.