forked from LaconicNetwork/kompose
initial cli, picked up from kompose-lite
This commit is contained in:
parent
8cfb216d63
commit
9bdc4cf2dd
780
cli/app/app.go
Normal file
780
cli/app/app.go
Normal file
@ -0,0 +1,780 @@
|
||||
/*
|
||||
Copyright 2016 Skippbox, Ltd 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 app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
"github.com/docker/libcompose/project"
|
||||
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/util/intstr"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
)
|
||||
|
||||
type ProjectAction func(project *project.Project, c *cli.Context)
|
||||
|
||||
const letterBytes = "abcdefghijklmnopqrstuvwxyz0123456789"
|
||||
|
||||
// RandStringBytes generates randomly n-character string
|
||||
func RandStringBytes(n int) string {
|
||||
b := make([]byte, n)
|
||||
for i := range b {
|
||||
b[i] = letterBytes[rand.Intn(len(letterBytes))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// BeforeApp is an action that is executed before any cli command.
|
||||
func BeforeApp(c *cli.Context) error {
|
||||
if c.GlobalBool("verbose") {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
// logrus.Warning("Note: This is an experimental alternate implementation of the Docker Compose CLI (https://github.com/docker/compose)")
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithProject is an helper function to create a cli.Command action with a ProjectFactory.
|
||||
func WithProject(factory ProjectFactory, action ProjectAction) func(context *cli.Context) {
|
||||
return func(context *cli.Context) {
|
||||
p, err := factory.Create(context)
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to read project: %v", err)
|
||||
}
|
||||
action(p, context)
|
||||
}
|
||||
}
|
||||
|
||||
// ProjectKuberPS lists all rc, svc.
|
||||
func ProjectKuberPS(p *project.Project, c *cli.Context) {
|
||||
factory := cmdutil.NewFactory(nil)
|
||||
clientConfig, err := factory.ClientConfig()
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to get Kubernetes client config: %v", err)
|
||||
}
|
||||
client := client.NewOrDie(clientConfig)
|
||||
|
||||
if c.BoolT("svc") {
|
||||
fmt.Printf("%-20s%-20s%-20s%-20s\n", "Name", "Cluster IP", "Ports", "Selectors")
|
||||
for name := range p.Configs {
|
||||
var ports string
|
||||
var selectors string
|
||||
services, err := client.Services(api.NamespaceDefault).Get(name)
|
||||
|
||||
if err != nil {
|
||||
logrus.Debugf("Cannot find service for: ", name)
|
||||
} else {
|
||||
|
||||
for i := range services.Spec.Ports {
|
||||
p := strconv.Itoa(services.Spec.Ports[i].Port)
|
||||
ports += ports + string(services.Spec.Ports[i].Protocol) + "(" + p + "),"
|
||||
}
|
||||
|
||||
for k, v := range services.ObjectMeta.Labels {
|
||||
selectors += selectors + k + "=" + v + ","
|
||||
}
|
||||
|
||||
ports = strings.TrimSuffix(ports, ",")
|
||||
selectors = strings.TrimSuffix(selectors, ",")
|
||||
|
||||
fmt.Printf("%-20s%-20s%-20s%-20s\n", services.ObjectMeta.Name,
|
||||
services.Spec.ClusterIP, ports, selectors)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if c.BoolT("rc") {
|
||||
fmt.Printf("%-15s%-15s%-30s%-10s%-20s\n", "Name", "Containers", "Images",
|
||||
"Replicas", "Selectors")
|
||||
for name := range p.Configs {
|
||||
var selectors string
|
||||
var containers string
|
||||
var images string
|
||||
rc, err := client.ReplicationControllers(api.NamespaceDefault).Get(name)
|
||||
|
||||
/* Should grab controller, container, image, selector, replicas */
|
||||
|
||||
if err != nil {
|
||||
logrus.Debugf("Cannot find rc for: ", string(name))
|
||||
} else {
|
||||
|
||||
for k, v := range rc.Spec.Selector {
|
||||
selectors += selectors + k + "=" + v + ","
|
||||
}
|
||||
|
||||
for i := range rc.Spec.Template.Spec.Containers {
|
||||
c := rc.Spec.Template.Spec.Containers[i]
|
||||
containers += containers + c.Name + ","
|
||||
images += images + c.Image + ","
|
||||
}
|
||||
selectors = strings.TrimSuffix(selectors, ",")
|
||||
containers = strings.TrimSuffix(containers, ",")
|
||||
images = strings.TrimSuffix(images, ",")
|
||||
|
||||
fmt.Printf("%-15s%-15s%-30s%-10d%-20s\n", rc.ObjectMeta.Name, containers,
|
||||
images, rc.Spec.Replicas, selectors)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ProjectKuberDelete deletes all rc, svc.
|
||||
func ProjectKuberDelete(p *project.Project, c *cli.Context) {
|
||||
factory := cmdutil.NewFactory(nil)
|
||||
clientConfig, err := factory.ClientConfig()
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to get Kubernetes client config: %v", err)
|
||||
}
|
||||
client := client.NewOrDie(clientConfig)
|
||||
|
||||
for name := range p.Configs {
|
||||
if len(c.String("name")) > 0 && name != c.String("name") {
|
||||
continue
|
||||
}
|
||||
|
||||
if c.BoolT("svc") {
|
||||
err := client.Services(api.NamespaceDefault).Delete(name)
|
||||
if err != nil {
|
||||
logrus.Fatalf("Unable to delete service %s: %s\n", name, err)
|
||||
}
|
||||
} else if c.BoolT("rc") {
|
||||
err := client.ReplicationControllers(api.NamespaceDefault).Delete(name)
|
||||
if err != nil {
|
||||
logrus.Fatalf("Unable to delete replication controller %s: %s\n", name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ProjectKuberScale scales rc.
|
||||
func ProjectKuberScale(p *project.Project, c *cli.Context) {
|
||||
factory := cmdutil.NewFactory(nil)
|
||||
clientConfig, err := factory.ClientConfig()
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to get Kubernetes client config: %v", err)
|
||||
}
|
||||
client := client.NewOrDie(clientConfig)
|
||||
|
||||
if c.Int("scale") <= 0 {
|
||||
logrus.Fatalf("Scale must be defined and a positive number")
|
||||
}
|
||||
|
||||
for name := range p.Configs {
|
||||
if len(c.String("rc")) == 0 || c.String("rc") == name {
|
||||
s, err := client.ExtensionsClient.Scales(api.NamespaceDefault).Get("ReplicationController", name)
|
||||
if err != nil {
|
||||
logrus.Fatalf("Error retrieving scaling data: %s\n", err)
|
||||
}
|
||||
|
||||
s.Spec.Replicas = c.Int("scale")
|
||||
|
||||
s, err = client.ExtensionsClient.Scales(api.NamespaceDefault).Update("ReplicationController", s)
|
||||
if err != nil {
|
||||
logrus.Fatalf("Error updating scaling data: %s\n", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Scaling %s to: %d\n", name, s.Spec.Replicas)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ProjectKuberConvert tranforms docker compose to k8s objects
|
||||
func ProjectKuberConvert(p *project.Project, c *cli.Context) {
|
||||
generateYaml := false
|
||||
composeFile := c.String("file")
|
||||
|
||||
p = project.NewProject(&project.Context{
|
||||
ProjectName: "kube",
|
||||
ComposeFile: composeFile,
|
||||
})
|
||||
|
||||
if err := p.Parse(); err != nil {
|
||||
logrus.Fatalf("Failed to parse the compose project from %s: %v", composeFile, err)
|
||||
}
|
||||
|
||||
if c.BoolT("yaml") {
|
||||
generateYaml = true
|
||||
}
|
||||
|
||||
var mServices map[string]api.Service = make(map[string]api.Service)
|
||||
var serviceLinks []string
|
||||
|
||||
for name, service := range p.Configs {
|
||||
rc := &api.ReplicationController{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "ReplicationController",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: name,
|
||||
//Labels: map[string]string{"service": name},
|
||||
},
|
||||
Spec: api.ReplicationControllerSpec{
|
||||
Replicas: 1,
|
||||
Selector: map[string]string{"service": name},
|
||||
Template: &api.PodTemplateSpec{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
//Labels: map[string]string{"service": name},
|
||||
},
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: name,
|
||||
Image: service.Image,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
sc := &api.Service{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "Service",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: name,
|
||||
//Labels: map[string]string{"service": name},
|
||||
},
|
||||
Spec: api.ServiceSpec{
|
||||
Selector: map[string]string{"service": name},
|
||||
},
|
||||
}
|
||||
dc := &extensions.Deployment{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "Deployment",
|
||||
APIVersion: "extensions/v1beta1",
|
||||
},
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: name,
|
||||
Labels: map[string]string{"service": name},
|
||||
},
|
||||
Spec: extensions.DeploymentSpec{
|
||||
Replicas: 1,
|
||||
Selector: &unversioned.LabelSelector{
|
||||
MatchLabels: map[string]string{"service": name},
|
||||
},
|
||||
//UniqueLabelKey: p.Name,
|
||||
Template: api.PodTemplateSpec{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Labels: map[string]string{"service": name},
|
||||
},
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: name,
|
||||
Image: service.Image,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
ds := &extensions.DaemonSet{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "DaemonSet",
|
||||
APIVersion: "extensions/v1beta1",
|
||||
},
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
Spec: extensions.DaemonSetSpec{
|
||||
Template: api.PodTemplateSpec{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: name,
|
||||
Image: service.Image,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
rs := &extensions.ReplicaSet{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "ReplicaSet",
|
||||
APIVersion: "extensions/v1beta1",
|
||||
},
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
Spec: extensions.ReplicaSetSpec{
|
||||
Replicas: 1,
|
||||
Selector: &unversioned.LabelSelector{
|
||||
MatchLabels: map[string]string{"service": name},
|
||||
},
|
||||
Template: api.PodTemplateSpec{
|
||||
ObjectMeta: api.ObjectMeta{},
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: name,
|
||||
Image: service.Image,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Configure the environment variables.
|
||||
var envs []api.EnvVar
|
||||
for _, env := range service.Environment.Slice() {
|
||||
var character string = "="
|
||||
if strings.Contains(env, character) {
|
||||
value := env[strings.Index(env, character)+1:]
|
||||
name := env[0:strings.Index(env, character)]
|
||||
name = strings.TrimSpace(name)
|
||||
value = strings.TrimSpace(value)
|
||||
envs = append(envs, api.EnvVar{
|
||||
Name: name,
|
||||
Value: value,
|
||||
})
|
||||
} else {
|
||||
character = ":"
|
||||
if strings.Contains(env, character) {
|
||||
var charQuote string = "'"
|
||||
value := env[strings.Index(env, character)+1:]
|
||||
name := env[0:strings.Index(env, character)]
|
||||
name = strings.TrimSpace(name)
|
||||
value = strings.TrimSpace(value)
|
||||
if strings.Contains(value, charQuote) {
|
||||
value = strings.Trim(value, "'")
|
||||
}
|
||||
envs = append(envs, api.EnvVar{
|
||||
Name: name,
|
||||
Value: value,
|
||||
})
|
||||
} else {
|
||||
logrus.Fatalf("Invalid container env %s for service %s", env, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rc.Spec.Template.Spec.Containers[0].Env = envs
|
||||
dc.Spec.Template.Spec.Containers[0].Env = envs
|
||||
ds.Spec.Template.Spec.Containers[0].Env = envs
|
||||
rs.Spec.Template.Spec.Containers[0].Env = envs
|
||||
|
||||
// Configure the container command.
|
||||
var cmds []string
|
||||
for _, cmd := range service.Command.Slice() {
|
||||
cmds = append(cmds, cmd)
|
||||
}
|
||||
rc.Spec.Template.Spec.Containers[0].Command = cmds
|
||||
dc.Spec.Template.Spec.Containers[0].Command = cmds
|
||||
ds.Spec.Template.Spec.Containers[0].Command = cmds
|
||||
rs.Spec.Template.Spec.Containers[0].Command = cmds
|
||||
|
||||
// Configure the container working dir.
|
||||
rc.Spec.Template.Spec.Containers[0].WorkingDir = service.WorkingDir
|
||||
dc.Spec.Template.Spec.Containers[0].WorkingDir = service.WorkingDir
|
||||
ds.Spec.Template.Spec.Containers[0].WorkingDir = service.WorkingDir
|
||||
rs.Spec.Template.Spec.Containers[0].WorkingDir = service.WorkingDir
|
||||
|
||||
// Configure the container volumes.
|
||||
var volumesMount []api.VolumeMount
|
||||
var volumes []api.Volume
|
||||
for _, volume := range service.Volumes {
|
||||
var character string = ":"
|
||||
if strings.Contains(volume, character) {
|
||||
hostDir := volume[0:strings.Index(volume, character)]
|
||||
hostDir = strings.TrimSpace(hostDir)
|
||||
containerDir := volume[strings.Index(volume, character)+1:]
|
||||
containerDir = strings.TrimSpace(containerDir)
|
||||
|
||||
// check if ro/rw mode is defined
|
||||
var readonly bool = true
|
||||
if strings.Index(volume, character) != strings.LastIndex(volume, character) {
|
||||
mode := volume[strings.LastIndex(volume, character)+1:]
|
||||
if strings.Compare(mode, "rw") == 0 {
|
||||
readonly = false
|
||||
}
|
||||
containerDir = containerDir[0:strings.Index(containerDir, character)]
|
||||
}
|
||||
|
||||
// volumeName = random string of 20 chars
|
||||
volumeName := RandStringBytes(20)
|
||||
|
||||
volumesMount = append(volumesMount, api.VolumeMount{Name: volumeName, ReadOnly: readonly, MountPath: containerDir})
|
||||
p := &api.HostPathVolumeSource{
|
||||
Path: hostDir,
|
||||
}
|
||||
//p.Path = hostDir
|
||||
volumeSource := api.VolumeSource{HostPath: p}
|
||||
volumes = append(volumes, api.Volume{Name: volumeName, VolumeSource: volumeSource})
|
||||
}
|
||||
}
|
||||
|
||||
rc.Spec.Template.Spec.Containers[0].VolumeMounts = volumesMount
|
||||
dc.Spec.Template.Spec.Containers[0].VolumeMounts = volumesMount
|
||||
ds.Spec.Template.Spec.Containers[0].VolumeMounts = volumesMount
|
||||
rs.Spec.Template.Spec.Containers[0].VolumeMounts = volumesMount
|
||||
|
||||
rc.Spec.Template.Spec.Volumes = volumes
|
||||
dc.Spec.Template.Spec.Volumes = volumes
|
||||
ds.Spec.Template.Spec.Volumes = volumes
|
||||
rs.Spec.Template.Spec.Volumes = volumes
|
||||
|
||||
// Configure the container privileged mode
|
||||
if service.Privileged == true {
|
||||
securitycontexts := &api.SecurityContext{
|
||||
Privileged: &service.Privileged,
|
||||
}
|
||||
rc.Spec.Template.Spec.Containers[0].SecurityContext = securitycontexts
|
||||
dc.Spec.Template.Spec.Containers[0].SecurityContext = securitycontexts
|
||||
ds.Spec.Template.Spec.Containers[0].SecurityContext = securitycontexts
|
||||
rs.Spec.Template.Spec.Containers[0].SecurityContext = securitycontexts
|
||||
}
|
||||
|
||||
// Configure the container ports.
|
||||
var ports []api.ContainerPort
|
||||
for _, port := range service.Ports {
|
||||
var character string = ":"
|
||||
if strings.Contains(port, character) {
|
||||
//portNumber := port[0:strings.Index(port, character)]
|
||||
targetPortNumber := port[strings.Index(port, character)+1:]
|
||||
targetPortNumber = strings.TrimSpace(targetPortNumber)
|
||||
targetPortNumberInt, err := strconv.Atoi(targetPortNumber)
|
||||
if err != nil {
|
||||
logrus.Fatalf("Invalid container port %s for service %s", port, name)
|
||||
}
|
||||
ports = append(ports, api.ContainerPort{ContainerPort: targetPortNumberInt})
|
||||
} else {
|
||||
portNumber, err := strconv.Atoi(port)
|
||||
if err != nil {
|
||||
logrus.Fatalf("Invalid container port %s for service %s", port, name)
|
||||
}
|
||||
ports = append(ports, api.ContainerPort{ContainerPort: portNumber})
|
||||
}
|
||||
}
|
||||
|
||||
rc.Spec.Template.Spec.Containers[0].Ports = ports
|
||||
dc.Spec.Template.Spec.Containers[0].Ports = ports
|
||||
ds.Spec.Template.Spec.Containers[0].Ports = ports
|
||||
rs.Spec.Template.Spec.Containers[0].Ports = ports
|
||||
|
||||
// Configure the service ports.
|
||||
var servicePorts []api.ServicePort
|
||||
for _, port := range service.Ports {
|
||||
var character string = ":"
|
||||
if strings.Contains(port, character) {
|
||||
portNumber := port[0:strings.Index(port, character)]
|
||||
portNumber = strings.TrimSpace(portNumber)
|
||||
targetPortNumber := port[strings.Index(port, character)+1:]
|
||||
targetPortNumber = strings.TrimSpace(targetPortNumber)
|
||||
portNumberInt, err := strconv.Atoi(portNumber)
|
||||
if err != nil {
|
||||
logrus.Fatalf("Invalid container port %s for service %s", port, name)
|
||||
}
|
||||
targetPortNumberInt, err1 := strconv.Atoi(targetPortNumber)
|
||||
if err1 != nil {
|
||||
logrus.Fatalf("Invalid container port %s for service %s", port, name)
|
||||
}
|
||||
var targetPort intstr.IntOrString
|
||||
targetPort.StrVal = targetPortNumber
|
||||
targetPort.IntVal = int32(targetPortNumberInt)
|
||||
servicePorts = append(servicePorts, api.ServicePort{Port: portNumberInt, Name: portNumber, Protocol: "TCP", TargetPort: targetPort})
|
||||
} else {
|
||||
portNumber, err := strconv.Atoi(port)
|
||||
if err != nil {
|
||||
logrus.Fatalf("Invalid container port %s for service %s", port, name)
|
||||
}
|
||||
var targetPort intstr.IntOrString
|
||||
targetPort.StrVal = strconv.Itoa(portNumber)
|
||||
targetPort.IntVal = int32(portNumber)
|
||||
servicePorts = append(servicePorts, api.ServicePort{Port: portNumber, Name: strconv.Itoa(portNumber), Protocol: "TCP", TargetPort: targetPort})
|
||||
}
|
||||
}
|
||||
sc.Spec.Ports = servicePorts
|
||||
|
||||
// Configure label
|
||||
labels := map[string]string{"service": name}
|
||||
for key, value := range service.Labels.MapParts() {
|
||||
labels[key] = value
|
||||
}
|
||||
rc.Spec.Template.ObjectMeta.Labels = labels
|
||||
dc.Spec.Template.ObjectMeta.Labels = labels
|
||||
ds.Spec.Template.ObjectMeta.Labels = labels
|
||||
rs.Spec.Template.ObjectMeta.Labels = labels
|
||||
|
||||
rc.ObjectMeta.Labels = labels
|
||||
dc.ObjectMeta.Labels = labels
|
||||
ds.ObjectMeta.Labels = labels
|
||||
rs.ObjectMeta.Labels = labels
|
||||
|
||||
sc.ObjectMeta.Labels = labels
|
||||
|
||||
// Configure the container restart policy.
|
||||
switch service.Restart {
|
||||
case "", "always":
|
||||
rc.Spec.Template.Spec.RestartPolicy = api.RestartPolicyAlways
|
||||
dc.Spec.Template.Spec.RestartPolicy = api.RestartPolicyAlways
|
||||
ds.Spec.Template.Spec.RestartPolicy = api.RestartPolicyAlways
|
||||
rs.Spec.Template.Spec.RestartPolicy = api.RestartPolicyAlways
|
||||
case "no":
|
||||
rc.Spec.Template.Spec.RestartPolicy = api.RestartPolicyNever
|
||||
dc.Spec.Template.Spec.RestartPolicy = api.RestartPolicyNever
|
||||
ds.Spec.Template.Spec.RestartPolicy = api.RestartPolicyNever
|
||||
rs.Spec.Template.Spec.RestartPolicy = api.RestartPolicyNever
|
||||
case "on-failure":
|
||||
rc.Spec.Template.Spec.RestartPolicy = api.RestartPolicyOnFailure
|
||||
dc.Spec.Template.Spec.RestartPolicy = api.RestartPolicyOnFailure
|
||||
ds.Spec.Template.Spec.RestartPolicy = api.RestartPolicyOnFailure
|
||||
rs.Spec.Template.Spec.RestartPolicy = api.RestartPolicyOnFailure
|
||||
default:
|
||||
logrus.Fatalf("Unknown restart policy %s for service %s", service.Restart, name)
|
||||
}
|
||||
|
||||
// convert datarc to json / yaml
|
||||
datarc, err := json.MarshalIndent(rc, "", " ")
|
||||
if generateYaml == true {
|
||||
datarc, err = yaml.Marshal(rc)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to marshal the replication controller: %v", err)
|
||||
}
|
||||
logrus.Debugf("%s\n", datarc)
|
||||
|
||||
// convert datadc to json / yaml
|
||||
datadc, err := json.MarshalIndent(dc, "", " ")
|
||||
if generateYaml == true {
|
||||
datadc, err = yaml.Marshal(dc)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to marshal the deployment container: %v", err)
|
||||
}
|
||||
|
||||
logrus.Debugf("%s\n", datadc)
|
||||
|
||||
//convert datads to json / yaml
|
||||
datads, err := json.MarshalIndent(ds, "", " ")
|
||||
if generateYaml == true {
|
||||
datads, err = yaml.Marshal(ds)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to marshal the daemonSet: %v", err)
|
||||
}
|
||||
|
||||
logrus.Debugf("%s\n", datads)
|
||||
|
||||
//convert datars to json / yaml
|
||||
datars, err := json.MarshalIndent(rs, "", " ")
|
||||
if generateYaml == true {
|
||||
datads, err = yaml.Marshal(rs)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to marshal the replicaSet: %v", err)
|
||||
}
|
||||
|
||||
logrus.Debugf("%s\n", datars)
|
||||
|
||||
mServices[name] = *sc
|
||||
|
||||
if len(service.Links.Slice()) > 0 {
|
||||
for i := 0; i < len(service.Links.Slice()); i++ {
|
||||
var data string = service.Links.Slice()[i]
|
||||
if len(serviceLinks) == 0 {
|
||||
serviceLinks = append(serviceLinks, data)
|
||||
} else {
|
||||
for _, v := range serviceLinks {
|
||||
if v != data {
|
||||
serviceLinks = append(serviceLinks, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileRC := fmt.Sprintf("%s-rc.json", name)
|
||||
if generateYaml == true {
|
||||
fileRC = fmt.Sprintf("%s-rc.yaml", name)
|
||||
}
|
||||
if err := ioutil.WriteFile(fileRC, []byte(datarc), 0644); err != nil {
|
||||
logrus.Fatalf("Failed to write replication controller: %v", err)
|
||||
}
|
||||
|
||||
/* Create the deployment container */
|
||||
if c.BoolT("deployment") {
|
||||
fileDC := fmt.Sprintf("%s-deployment.json", name)
|
||||
if generateYaml == true {
|
||||
fileDC = fmt.Sprintf("%s-deployment.yaml", name)
|
||||
}
|
||||
if err := ioutil.WriteFile(fileDC, []byte(datadc), 0644); err != nil {
|
||||
logrus.Fatalf("Failed to write deployment container: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the daemonset container */
|
||||
if c.BoolT("daemonset") {
|
||||
fileDS := fmt.Sprintf("%s-daemonset.json", name)
|
||||
if generateYaml == true {
|
||||
fileDS = fmt.Sprintf("%s-daemonset.yaml", name)
|
||||
}
|
||||
if err := ioutil.WriteFile(fileDS, []byte(datads), 0644); err != nil {
|
||||
logrus.Fatalf("Failed to write daemonset: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the replicaset container */
|
||||
if c.BoolT("replicaset") {
|
||||
fileRS := fmt.Sprintf("%s-replicaset.json", name)
|
||||
if generateYaml == true {
|
||||
fileRS = fmt.Sprintf("%s-replicaset.yaml", name)
|
||||
}
|
||||
if err := ioutil.WriteFile(fileRS, []byte(datars), 0644); err != nil {
|
||||
logrus.Fatalf("Failed to write replicaset: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range mServices {
|
||||
for i := 0; i < len(serviceLinks); i++ {
|
||||
// convert datasvc to json / yaml
|
||||
datasvc, er := json.MarshalIndent(v, "", " ")
|
||||
if generateYaml == true {
|
||||
datasvc, er = yaml.Marshal(v)
|
||||
}
|
||||
if er != nil {
|
||||
logrus.Fatalf("Failed to marshal the service controller: %v", er)
|
||||
}
|
||||
|
||||
logrus.Debugf("%s\n", datasvc)
|
||||
|
||||
fileSVC := fmt.Sprintf("%s-svc.json", k)
|
||||
if generateYaml == true {
|
||||
fileSVC = fmt.Sprintf("%s-svc.yaml", k)
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(fileSVC, []byte(datasvc), 0644); err != nil {
|
||||
logrus.Fatalf("Failed to write service controller: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Need to iterate through one more time to ensure we capture all service/rc */
|
||||
for name := range p.Configs {
|
||||
if c.BoolT("chart") {
|
||||
err := generateHelm(composeFile, name)
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to create Chart data: %s\n", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ProjectKuberUp brings up rc, svc.
|
||||
func ProjectKuberUp(p *project.Project, c *cli.Context) {
|
||||
factory := cmdutil.NewFactory(nil)
|
||||
clientConfig, err := factory.ClientConfig()
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to get Kubernetes client config: %v", err)
|
||||
}
|
||||
client := client.NewOrDie(clientConfig)
|
||||
|
||||
files, err := ioutil.ReadDir(".")
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to load rc, svc manifest files: %s\n", err)
|
||||
}
|
||||
|
||||
// submit svc first
|
||||
sc := &api.Service{}
|
||||
for _, file := range files {
|
||||
if strings.Contains(file.Name(), "svc") {
|
||||
datasvc, err := ioutil.ReadFile(file.Name())
|
||||
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to load %s: %s\n", file.Name(), err)
|
||||
}
|
||||
|
||||
if strings.Contains(file.Name(), "json") {
|
||||
err := json.Unmarshal(datasvc, &sc)
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to unmarshal file %s to svc object: %s\n", file.Name(), err)
|
||||
}
|
||||
}
|
||||
if strings.Contains(file.Name(), "yaml") {
|
||||
err := yaml.Unmarshal(datasvc, &sc)
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to unmarshal file %s to svc object: %s\n", file.Name(), err)
|
||||
}
|
||||
}
|
||||
// submit sc to k8s
|
||||
scCreated, err := client.Services(api.NamespaceDefault).Create(sc)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
logrus.Debugf("%s\n", scCreated)
|
||||
}
|
||||
}
|
||||
|
||||
// then submit rc
|
||||
rc := &api.ReplicationController{}
|
||||
for _, file := range files {
|
||||
if strings.Contains(file.Name(), "rc") {
|
||||
datarc, err := ioutil.ReadFile(file.Name())
|
||||
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to load %s: %s\n", file.Name(), err)
|
||||
}
|
||||
|
||||
if strings.Contains(file.Name(), "json") {
|
||||
err := json.Unmarshal(datarc, &rc)
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to unmarshal file %s to rc object: %s\n", file.Name(), err)
|
||||
}
|
||||
}
|
||||
if strings.Contains(file.Name(), "yaml") {
|
||||
err := yaml.Unmarshal(datarc, &rc)
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to unmarshal file %s to rc object: %s\n", file.Name(), err)
|
||||
}
|
||||
}
|
||||
// submit rc to k8s
|
||||
rcCreated, err := client.ReplicationControllers(api.NamespaceDefault).Create(rc)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
logrus.Debugf("%s\n", rcCreated)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
110
cli/app/k8sutils.go
Normal file
110
cli/app/k8sutils.go
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
Copyright 2016 Skippbox, Ltd 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 app
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
)
|
||||
|
||||
/* Ancilliary helper functions to interface with the commands interface */
|
||||
|
||||
/**
|
||||
* Generate Helm Chart configuration
|
||||
*/
|
||||
func generateHelm(filename string, svcname string) error {
|
||||
type ChartDetails struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
dirName := strings.Replace(filename, ".yml", "", 1)
|
||||
details := ChartDetails{dirName}
|
||||
manifestDir := dirName + string(os.PathSeparator) + "manifests"
|
||||
dir, err := os.Open(dirName)
|
||||
|
||||
/* Setup the initial directories/files */
|
||||
if err == nil {
|
||||
_ = dir.Close()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
err = os.Mkdir(dirName, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = os.Mkdir(manifestDir, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
/* Create the readme file */
|
||||
readme := "This chart was created by Kompose\n"
|
||||
err = ioutil.WriteFile(dirName+string(os.PathSeparator)+"README.md", []byte(readme), 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
/* Create the Chart.yaml file */
|
||||
chart := `name: {{.Name}}
|
||||
description: A generated Helm Chart from Skippbox Kompose
|
||||
version: 0.0.1
|
||||
source:
|
||||
home:
|
||||
`
|
||||
|
||||
t, err := template.New("ChartTmpl").Parse(chart)
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to generate Chart.yaml template: %s\n", err)
|
||||
}
|
||||
var chartData bytes.Buffer
|
||||
_ = t.Execute(&chartData, details)
|
||||
|
||||
err = ioutil.WriteFile(dirName+string(os.PathSeparator)+"Chart.yaml", chartData.Bytes(), 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy all yaml files into the newly created manifests directory */
|
||||
infile, err := ioutil.ReadFile(svcname + "-rc.json")
|
||||
if err != nil {
|
||||
logrus.Infof("Error reading %s: %s\n", svcname+"-rc.yaml", err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(manifestDir+string(os.PathSeparator)+svcname+"-rc.json", infile, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
/* The svc file is optional */
|
||||
infile, err = ioutil.ReadFile(svcname + "-svc.json")
|
||||
if err == nil {
|
||||
err = ioutil.WriteFile(manifestDir+string(os.PathSeparator)+svcname+"-svc.json", infile, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
28
cli/app/types.go
Normal file
28
cli/app/types.go
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
Copyright 2016 Skippbox, Ltd 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 app
|
||||
|
||||
import (
|
||||
"github.com/urfave/cli"
|
||||
"github.com/docker/libcompose/project"
|
||||
)
|
||||
|
||||
// ProjectFactory is an interface that helps creating libcompose project.
|
||||
type ProjectFactory interface {
|
||||
// Create creates a libcompose project from the command line options (codegangsta cli context).
|
||||
Create(c *cli.Context) (*project.Project, error)
|
||||
}
|
||||
165
cli/command/command.go
Normal file
165
cli/command/command.go
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
Copyright 2016 Skippbox, Ltd 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 command
|
||||
|
||||
import (
|
||||
"github.com/urfave/cli"
|
||||
"github.com/docker/libcompose/project"
|
||||
"github.com/skippbox/kompose2/cli/app"
|
||||
)
|
||||
|
||||
// ConvertCommand defines the kompose convert subcommand.
|
||||
func ConvertCommand(factory app.ProjectFactory) cli.Command {
|
||||
return cli.Command{
|
||||
Name: "convert",
|
||||
Usage: "Convert docker-compose.yml to Kubernetes objects",
|
||||
Action: app.WithProject(factory, app.ProjectKuberConvert),
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "file,f",
|
||||
Usage: "Specify an alternate compose file (default: docker-compose.yml)",
|
||||
Value: "docker-compose.yml",
|
||||
EnvVar: "COMPOSE_FILE",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "deployment,d",
|
||||
Usage: "Generate a deployment resource file",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "daemonset,ds",
|
||||
Usage: "Generate a daemonset resource file",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "replicaset,rs",
|
||||
Usage: "Generate a replicaset resource file",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "chart,c",
|
||||
Usage: "Create a chart deployment",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "yaml, y",
|
||||
Usage: "Generate resource file in yaml format",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// UpCommand defines the kompose up subcommand.
|
||||
func UpCommand(factory app.ProjectFactory) cli.Command {
|
||||
return cli.Command{
|
||||
Name: "up",
|
||||
Usage: "Submit rc, svc objects to kubernetes API endpoint",
|
||||
Action: app.WithProject(factory, app.ProjectKuberUp),
|
||||
}
|
||||
}
|
||||
|
||||
// PsCommand defines the kompose ps subcommand.
|
||||
func PsCommand(factory app.ProjectFactory) cli.Command {
|
||||
return cli.Command{
|
||||
Name: "ps",
|
||||
Usage: "Get active data in the kubernetes cluster",
|
||||
Action: app.WithProject(factory, app.ProjectKuberPS),
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "service,svc",
|
||||
Usage: "Get active services",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "replicationcontroller,rc",
|
||||
Usage: "Get active replication controller",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteCommand defines the kompose delete subcommand.
|
||||
func DeleteCommand(factory app.ProjectFactory) cli.Command {
|
||||
return cli.Command{
|
||||
Name: "delete",
|
||||
Usage: "Remove instantiated services/rc from kubernetes",
|
||||
Action: app.WithProject(factory, app.ProjectKuberDelete),
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "replicationcontroller,rc",
|
||||
Usage: "Remove active replication controllers",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "service,svc",
|
||||
Usage: "Remove active services",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "name",
|
||||
Usage: "Name of the object to remove",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ScaleCommand defines the kompose up subcommand.
|
||||
func ScaleCommand(factory app.ProjectFactory) cli.Command {
|
||||
return cli.Command{
|
||||
Name: "scale",
|
||||
Usage: "Globally scale instantiated replication controllers",
|
||||
Action: app.WithProject(factory, app.ProjectKuberScale),
|
||||
Flags: []cli.Flag{
|
||||
cli.IntFlag{
|
||||
Name: "scale",
|
||||
Usage: "New number of replicas",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "replicationcontroller,rc",
|
||||
Usage: "A specific replication controller to scale",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// CommonFlags defines the flags that are in common for all subcommands.
|
||||
func CommonFlags() []cli.Flag {
|
||||
return []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "verbose,debug",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "file,f",
|
||||
Usage: "Specify an alternate compose file (default: docker-compose.yml)",
|
||||
Value: "docker-compose.yml",
|
||||
EnvVar: "COMPOSE_FILE",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "project-name,p",
|
||||
Usage: "Specify an alternate project name (default: directory name)",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Populate updates the specified project context based on command line arguments and subcommands.
|
||||
func Populate(context *project.Context, c *cli.Context) {
|
||||
context.ComposeFile = c.GlobalString("file")
|
||||
context.ProjectName = c.GlobalString("project-name")
|
||||
|
||||
if c.Command.Name == "logs" {
|
||||
context.Log = true
|
||||
} else if c.Command.Name == "up" {
|
||||
context.Log = !c.Bool("d")
|
||||
context.NoRecreate = c.Bool("no-recreate")
|
||||
context.ForceRecreate = c.Bool("force-recreate")
|
||||
} else if c.Command.Name == "scale" {
|
||||
context.Timeout = uint(c.Int("timeout"))
|
||||
}
|
||||
}
|
||||
39
cli/docker/app/factory.go
Normal file
39
cli/docker/app/factory.go
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright 2016 Skippbox, Ltd 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 app
|
||||
|
||||
import (
|
||||
"github.com/urfave/cli"
|
||||
"github.com/skippbox/kompose2/cli/command"
|
||||
"github.com/docker/libcompose/cli/logger"
|
||||
"github.com/docker/libcompose/docker"
|
||||
"github.com/docker/libcompose/project"
|
||||
)
|
||||
|
||||
// ProjectFactory is a struct that hold the app.ProjectFactory implementation.
|
||||
type ProjectFactory struct {
|
||||
}
|
||||
|
||||
// Create implements ProjectFactory.Create using docker client.
|
||||
func (p *ProjectFactory) Create(c *cli.Context) (*project.Project, error) {
|
||||
context := &docker.Context{}
|
||||
context.LoggerFactory = logger.NewColorLoggerFactory()
|
||||
//Populate(context, c)
|
||||
command.Populate(&context.Context, c)
|
||||
|
||||
return docker.NewProject(context)
|
||||
}
|
||||
49
cli/main/main.go
Normal file
49
cli/main/main.go
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
Copyright 2016 Skippbox, Ltd 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 main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
dockerApp "github.com/skippbox/kompose2/cli/docker/app"
|
||||
"github.com/skippbox/kompose2/version"
|
||||
"github.com/skippbox/kompose2/cli/command"
|
||||
cliApp "github.com/skippbox/kompose2/cli/app"
|
||||
)
|
||||
|
||||
func main() {
|
||||
factory := &dockerApp.ProjectFactory{}
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Name = "kompose"
|
||||
app.Usage = "Command line interface for Skippbox."
|
||||
app.Version = version.VERSION + " (" + version.GITCOMMIT + ")"
|
||||
app.Author = "Skippbox Compose Contributors"
|
||||
app.Email = "https://github.com/skippbox/kompose"
|
||||
app.Before = cliApp.BeforeApp
|
||||
app.Flags = append(command.CommonFlags())
|
||||
app.Commands = []cli.Command{
|
||||
command.ConvertCommand(factory),
|
||||
command.UpCommand(factory),
|
||||
command.PsCommand(factory),
|
||||
command.DeleteCommand(factory),
|
||||
command.ScaleCommand(factory),
|
||||
}
|
||||
|
||||
app.Run(os.Args)
|
||||
}
|
||||
25
version/version.go
Normal file
25
version/version.go
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2016 Skippbox, Ltd 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 version
|
||||
|
||||
var (
|
||||
// VERSION should be updated by hand at each release
|
||||
VERSION = "0.0.5-dev"
|
||||
|
||||
// GITCOMMIT will be overwritten automatically by the build system
|
||||
GITCOMMIT = "HEAD"
|
||||
)
|
||||
Loading…
Reference in New Issue
Block a user