contrib/podex: switch to go-yaml to manage ordering

pull/6/head
Johan Euphrosine 2015-01-09 14:54:54 +00:00
parent 686b187067
commit 1f0d0cdc31
1 changed files with 53 additions and 32 deletions

View File

@ -37,15 +37,17 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
goyaml "gopkg.in/v2/yaml"
) )
const usage = "usage: podex [-json|-yaml] [-id PODNAME] IMAGES" const usage = "usage: podex [-yaml|-json] [-pod|-container] [-id PODNAME] IMAGES..."
var generateJSON = flag.Bool("json", false, "generate json manifest")
var generateYAML = flag.Bool("yaml", false, "generate yaml manifest") var generateYAML = flag.Bool("yaml", false, "generate yaml manifest")
var podName = flag.String("id", "", "set pod name") var generateJSON = flag.Bool("json", false, "generate json manifest")
var pod = flag.Bool("pod", false, "generate pod manifest")
var container = flag.Bool("container", false, "generate container manifest")
var id = flag.String("id", "", "set id")
type image struct { type image struct {
Host string Host string
@ -60,26 +62,26 @@ func main() {
if flag.NArg() < 1 { if flag.NArg() < 1 {
log.Fatal(usage) log.Fatal(usage)
} }
if *podName == "" { if *id == "" {
if flag.NArg() > 1 { if flag.NArg() > 1 {
log.Print(usage) log.Print(usage)
log.Fatal("podex: -id arg is required when passing more than one image") log.Fatal("podex: -id arg is required when passing more than one image")
} }
_, _, *podName, _ = splitDockerImageName(flag.Arg(0)) _, _, *id, _ = splitDockerImageName(flag.Arg(0))
} }
if (!*generateJSON && !*generateYAML) || (*generateJSON && *generateYAML) { if (!*generateYAML && !*generateJSON) || (*generateYAML && *generateJSON) || (!*pod && !*container) || (*pod && *container) {
log.Fatal(usage) log.Fatal(usage)
} }
podContainers := []v1beta1.Container{} podContainers := []goyaml.MapSlice{}
for _, imageName := range flag.Args() { for _, imageName := range flag.Args() {
host, namespace, repo, tag := splitDockerImageName(imageName) host, namespace, repo, tag := splitDockerImageName(imageName)
container := v1beta1.Container{ container := goyaml.MapSlice{
Name: repo, {Key: "name", Value: repo},
Image: imageName, {Key: "image", Value: imageName},
} }
img, err := getImageMetadata(host, namespace, repo, tag) img, err := getImageMetadata(host, namespace, repo, tag)
@ -87,44 +89,63 @@ func main() {
if err != nil { if err != nil {
log.Fatalf("failed to get image metadata %q: %v", imageName, err) log.Fatalf("failed to get image metadata %q: %v", imageName, err)
} }
portSlice := []goyaml.MapSlice{}
for p := range img.ContainerConfig.ExposedPorts { for p := range img.ContainerConfig.ExposedPorts {
port, err := strconv.Atoi(p.Port()) port, err := strconv.Atoi(p.Port())
if err != nil { if err != nil {
log.Fatalf("failed to parse port %q: %v", p.Port(), err) log.Fatalf("failed to parse port %q: %v", p.Port(), err)
} }
container.Ports = append(container.Ports, v1beta1.Port{ portEntry := goyaml.MapSlice{{
Name: strings.Join([]string{repo, p.Proto(), p.Port()}, "-"), Key: "name", Value: strings.Join([]string{repo, p.Proto(), p.Port()}, "-")}, {Key: "containerPort", Value: port}}
ContainerPort: port, portSlice = append(portSlice, portEntry)
Protocol: v1beta1.Protocol(strings.ToUpper(p.Proto())), if p.Proto() != "tcp" {
}) portEntry = append(portEntry, goyaml.MapItem{Key: "protocol", Value: strings.ToUpper(p.Proto())})
}
}
if len(img.ContainerConfig.ExposedPorts) > 0 {
container = append(container, goyaml.MapItem{Key: "ports", Value: portSlice})
} }
podContainers = append(podContainers, container) podContainers = append(podContainers, container)
} }
// TODO(proppy): add flag to handle multiple version // TODO(proppy): add flag to handle multiple version
manifest := v1beta1.ContainerManifest{ containerManifest := goyaml.MapSlice{
Version: "v1beta1", {Key: "version", Value: "v1beta1"},
ID: *podName + "-pod", {Key: "containers", Value: podContainers},
Containers: podContainers,
RestartPolicy: v1beta1.RestartPolicy{
Always: &v1beta1.RestartPolicyAlways{},
},
} }
if *generateJSON { var data interface{}
bs, err := json.MarshalIndent(manifest, "", " ")
if err != nil { switch {
log.Fatalf("failed to render JSON container manifest: %v", err) case *container:
containerManifest = append(goyaml.MapSlice{
{Key: "id", Value: *id},
}, containerManifest...)
data = containerManifest
case *pod:
data = goyaml.MapSlice{
{Key: "id", Value: *id},
{Key: "kind", Value: "Pod"},
{Key: "apiVersion", Value: "v1beta1"},
{Key: "desiredState", Value: goyaml.MapSlice{
{Key: "manifest", Value: containerManifest},
}},
} }
os.Stdout.Write(bs)
} }
if *generateYAML {
bs, err := yaml.Marshal(manifest) bs, err := goyaml.Marshal(data)
if err != nil {
log.Fatalf("failed to marshal container manifest: %v", err)
}
switch {
case *generateJSON:
bs, err = yaml.YAMLToJSON(bs)
if err != nil { if err != nil {
log.Fatalf("failed to render YAML container manifest: %v", err) log.Fatalf("failed to marshal container manifest into JSON: %v", err)
} }
os.Stdout.Write(bs)
} }
os.Stdout.Write(bs)
} }
// splitDockerImageName split a docker image name of the form [HOST/][NAMESPACE/]REPOSITORY[:TAG] // splitDockerImageName split a docker image name of the form [HOST/][NAMESPACE/]REPOSITORY[:TAG]