Adds both build and push support

This adds support for building and pushing docker containers
when you perform either `kompose convert` or `kompose up`.

Docker Compose files who have build parameters with their respective
image and build keys will automatically be both built and pushed.
This commit is contained in:
Charlie Drage 2017-06-09 09:58:01 -04:00
parent 49ada134ae
commit e2f9084003
26 changed files with 1664 additions and 555 deletions

View File

@ -19,6 +19,7 @@ package cmd
import (
"strings"
log "github.com/Sirupsen/logrus"
"github.com/kubernetes-incubator/kompose/pkg/app"
"github.com/kubernetes-incubator/kompose/pkg/kobject"
"github.com/spf13/cobra"
@ -30,6 +31,7 @@ var (
ConvertOut string
ConvertBuildRepo string
ConvertBuildBranch string
ConvertBuild string
ConvertChart bool
ConvertDeployment bool
ConvertDaemonSet bool
@ -52,6 +54,12 @@ var convertCmd = &cobra.Command{
Short: "Convert a Docker Compose file",
PreRun: func(cmd *cobra.Command, args []string) {
// Check that build-config wasn't passed in with --provider=kubernetes
provider := strings.ToLower(GlobalProvider)
if provider == "kubernetes" && UpBuild == "build-config" {
log.Fatalf("build-config is not a valid --build parameter with provider Kubernetes")
}
// Create the Convert Options.
ConvertOpt = kobject.ConvertOptions{
ToStdout: ConvertStdout,
@ -65,6 +73,7 @@ var convertCmd = &cobra.Command{
CreateD: ConvertDeployment,
CreateDS: ConvertDaemonSet,
CreateRC: ConvertReplicationController,
Build: ConvertBuild,
BuildRepo: ConvertBuildRepo,
BuildBranch: ConvertBuildBranch,
CreateDeploymentConfig: ConvertDeploymentConfig,
@ -112,6 +121,7 @@ func init() {
convertCmd.Flags().MarkHidden("build-branch")
// Standard between the two
convertCmd.Flags().StringVar(&ConvertBuild, "build", "none", `Set the type of build ("local"|"build-config" (OpenShift only)|"none")`)
convertCmd.Flags().BoolVarP(&ConvertYaml, "yaml", "y", false, "Generate resource files into YAML format")
convertCmd.Flags().MarkDeprecated("yaml", "YAML is the default format now.")
convertCmd.Flags().MarkShorthandDeprecated("y", "YAML is the default format now.")
@ -135,15 +145,17 @@ Examples:
Available Commands:{{range .Commands}}{{if .IsAvailableCommand}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}}
Resource Flags:
--build-branch Specify repository branch to use for buildconfig (default is current branch name)
--build-repo Specify source repository for buildconfig (default is current branch's remote url
-c, --chart Create a Helm chart for converted objects
Kubernetes Flags:
--daemon-set Generate a Kubernetes daemonset object
-d, --deployment Generate a Kubernetes deployment object
-c, --chart Create a Helm chart for converted objects
--replication-controller Generate a Kubernetes replication controller object
OpenShift Flags:
--build-branch Specify repository branch to use for buildconfig (default is current branch name)
--build-repo Specify source repository for buildconfig (default is current branch's remote url
--deployment-config Generate an OpenShift deployment config object
--insecure-repository Specify to use insecure docker repository while generating Openshift image stream object
--replication-controller Generate a Kubernetes replication controller object
Flags:
{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableInheritedFlags}}

View File

@ -17,6 +17,7 @@ limitations under the License.
package cmd
import (
log "github.com/Sirupsen/logrus"
"strings"
"github.com/kubernetes-incubator/kompose/pkg/app"
@ -31,6 +32,7 @@ var (
UpInsecureRepo bool
UpNamespace string
UpOpt kobject.ConvertOptions
UpBuild string
)
var upCmd = &cobra.Command{
@ -39,8 +41,15 @@ var upCmd = &cobra.Command{
Long: `Deploy your Dockerized application to a container orchestrator. (default "kubernetes")`,
PreRun: func(cmd *cobra.Command, args []string) {
// Check that build-config wasn't passed in with --provider=kubernetes
provider := strings.ToLower(GlobalProvider)
if provider == "kubernetes" && UpBuild == "build-config" {
log.Fatalf("build-config is not a valid --build parameter with provider Kubernetes")
}
// Create the Convert options.
UpOpt = kobject.ConvertOptions{
Build: UpBuild,
Replicas: UpReplicas,
InputFiles: GlobalFiles,
Provider: strings.ToLower(GlobalProvider),
@ -63,5 +72,6 @@ func init() {
upCmd.Flags().IntVar(&UpReplicas, "replicas", 1, "Specify the number of replicas generated")
upCmd.Flags().BoolVar(&UpInsecureRepo, "insecure-repository", false, "Use an insecure Docker repository for OpenShift ImageStream")
upCmd.Flags().StringVar(&UpNamespace, "namespace", "default", "Specify Namespace to deploy your application")
upCmd.Flags().StringVar(&UpBuild, "build", "local", `Set the type of build ("local"|"build-config" (OpenShift only)|"none")`)
RootCmd.AddCommand(upCmd)
}

View File

@ -3,5 +3,4 @@ version: "2"
services:
foo:
build: "./build"
command: "sleep 3600"
image: docker.io/cdrage/foobar

View File

@ -39,6 +39,7 @@ type ConvertOptions struct {
CreateDeploymentConfig bool
BuildRepo string
BuildBranch string
Build string
CreateChart bool
GenerateYaml bool
GenerateJSON bool

View File

@ -64,15 +64,6 @@ const TIMEOUT = 300
//default size of Persistent Volume Claim
const PVCRequestSize = "100Mi"
// list of all unsupported keys for this transformer
// Keys are names of variables in kobject struct.
// this is map to make searching for keys easier
// to make sure that unsupported key is not going to be reported twice
// by keeping record if already saw this key in another service
var unsupportedKey = map[string]bool{
"Build": false,
}
// CheckUnsupportedKey checks if given komposeObject contains
// keys that are not supported by this tranfomer.
// list of all unsupported keys are stored in unsupportedKey variable
@ -532,11 +523,6 @@ func (k *Kubernetes) InitPod(name string, service kobject.ServiceConfig) *api.Po
// returns object that are already sorted in the way that Services are first
func (k *Kubernetes) Transform(komposeObject kobject.KomposeObject, opt kobject.ConvertOptions) ([]runtime.Object, error) {
noSupKeys := k.CheckUnsupportedKey(&komposeObject, unsupportedKey)
for _, keyName := range noSupKeys {
log.Warningf("Kubernetes provider doesn't support %s key - ignoring", keyName)
}
// this will hold all the converted data
var allobjects []runtime.Object
@ -545,6 +531,44 @@ func (k *Kubernetes) Transform(komposeObject kobject.KomposeObject, opt kobject.
service := komposeObject.ServiceConfigs[name]
var objects []runtime.Object
// Must build the images before conversion (got to add service.Image in case 'image' key isn't provided
// Check that --build is set to true
// Check to see if there is an InputFile (required!) before we build the container
// Check that there's actually a Build key
// Lastly, we must have an Image name to continue
if opt.Build == "local" && opt.InputFiles != nil && service.Build != "" {
if service.Image == "" {
return nil, fmt.Errorf("image key required within build parameters in order to build and push service '%s'", name)
}
log.Infof("Build key detected. Attempting to build and push image '%s'", service.Image)
// Get the directory where the compose file is
composeFileDir, err := transformer.GetComposeFileDir(opt.InputFiles)
if err != nil {
return nil, err
}
// Build the container!
err = transformer.BuildDockerImage(service, name, composeFileDir)
if err != nil {
return nil, errors.Wrapf(err, "Unable to build Docker image for service %v", name)
}
// Push the built container to the repo!
err = transformer.PushDockerImage(service, name)
if err != nil {
return nil, errors.Wrapf(err, "Unable to push Docker image for service %v", name)
}
}
// If there's no "image" key, use the name of the container that's built
if service.Image == "" {
service.Image = name
}
// Generate pod only and nothing more
if service.Restart == "no" || service.Restart == "on-failure" {
// Error out if Controller Object is specified with restart: 'on-failure'

View File

@ -19,7 +19,6 @@ package kubernetes
import (
"fmt"
"reflect"
"strings"
"testing"
deployapi "github.com/openshift/origin/pkg/deploy/api"
@ -428,39 +427,6 @@ func TestConvertRestartOptions(t *testing.T) {
}
}
// TestUnsupportedKeys test checkUnsupportedKey function
func TestUnsupportedKeys(t *testing.T) {
kobjectWithBuild := newKomposeObject()
kobjectWithBuild.LoadedFrom = "compose"
serviceConfig := kobjectWithBuild.ServiceConfigs["app"]
serviceConfig.Build = "./asdf"
serviceConfig.Network = []string{}
kobjectWithBuild.ServiceConfigs = map[string]kobject.ServiceConfig{"app": serviceConfig}
// define all test cases for checkUnsupportedKey function
testCases := map[string]struct {
bundleFile kobject.KomposeObject
expectedUnsupportedKeys []string
}{
"Full Bundle": {
kobjectWithBuild,
[]string{"build"},
},
}
k := Kubernetes{}
for name, test := range testCases {
t.Log("Test case:", name)
keys := k.CheckUnsupportedKey(&test.bundleFile, unsupportedKey)
if !reflect.DeepEqual(keys, test.expectedUnsupportedKeys) {
t.Errorf("ERROR: Expecting unsupported keys: ['%s']. Got: ['%s']", strings.Join(test.expectedUnsupportedKeys, "', '"), strings.Join(keys, "', '"))
}
}
}
func TestRestartOnFailure(t *testing.T) {
kobjectWithRestartOnFailure := newKomposeObject()

View File

@ -20,7 +20,6 @@ import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/kubernetes-incubator/kompose/pkg/kobject"
@ -100,6 +99,27 @@ func getImageTag(image string) string {
}
// Inputs name of the service + provided image
// Outputs name is image is blank, but still provide a tag.
func taggedImage(name string, serviceImage string) string {
var image string
tag := getImageTag(serviceImage)
// Use the image name if not blank
if serviceImage != "" {
image = serviceImage
} else {
image = name
}
// Add a tag if not present
if !strings.Contains(image, ":") {
image = image + ":" + tag
}
return image
}
// hasGitBinary checks if the 'git' binary is available on the system
func hasGitBinary() bool {
_, err := exec.LookPath("git")
@ -134,20 +154,6 @@ func getGitCurrentBranch(composeFileDir string) (string, error) {
return strings.TrimRight(string(out), "\n"), nil
}
// getComposeFileDir returns compose file directory
func getComposeFileDir(inputFiles []string) (string, error) {
// Lets assume all the docker-compose files are in the same directory
inputFile := inputFiles[0]
if strings.Index(inputFile, "/") != 0 {
workDir, err := os.Getwd()
if err != nil {
return "", err
}
inputFile = filepath.Join(workDir, inputFile)
}
return filepath.Dir(inputFile), nil
}
// getAbsBuildContext returns build context relative to project root dir
func getAbsBuildContext(context string) (string, error) {
cmd := exec.Command("git", "rev-parse", "--show-prefix")
@ -163,6 +169,8 @@ func getAbsBuildContext(context string) (string, error) {
// initImageStream initialize ImageStream object
func (o *OpenShift) initImageStream(name string, service kobject.ServiceConfig, opt kobject.ConvertOptions) *imageapi.ImageStream {
// Retrieve tags and image name for mapping
tag := getImageTag(service.Image)
var importPolicy imageapi.TagImportPolicy
@ -171,7 +179,8 @@ func (o *OpenShift) initImageStream(name string, service kobject.ServiceConfig,
}
var tags map[string]imageapi.TagReference
if service.Build == "" {
if service.Build != "" || opt.Build != "build-config" {
tags = map[string]imageapi.TagReference{
tag: imageapi.TagReference{
From: &kapi.ObjectReference{
@ -199,7 +208,6 @@ func (o *OpenShift) initImageStream(name string, service kobject.ServiceConfig,
return is
}
// initBuildConfig initialize Openshifts BuildConfig Object
func initBuildConfig(name string, service kobject.ServiceConfig, repo string, branch string) (*buildapi.BuildConfig, error) {
contextDir, err := getAbsBuildContext(service.Build)
envList := transformer.EnvSort{}
@ -230,7 +238,6 @@ func initBuildConfig(name string, service kobject.ServiceConfig, repo string, br
Spec: buildapi.BuildConfigSpec{
Triggers: []buildapi.BuildTriggerPolicy{
{Type: "ConfigChange"},
{Type: "ImageChange"},
},
RunPolicy: "Serial",
CommonSpec: buildapi.CommonSpec{
@ -261,9 +268,11 @@ func initBuildConfig(name string, service kobject.ServiceConfig, repo string, br
// initDeploymentConfig initialize OpenShifts DeploymentConfig object
func (o *OpenShift) initDeploymentConfig(name string, service kobject.ServiceConfig, replicas int) *deployapi.DeploymentConfig {
tag := getImageTag(service.Image)
containerName := []string{name}
// Properly add tags to the image name
tag := getImageTag(service.Image)
// Use ContainerName if it was set
if service.ContainerName != "" {
containerName = []string{service.ContainerName}
@ -351,7 +360,6 @@ func (o *OpenShift) Transform(komposeObject kobject.KomposeObject, opt kobject.C
var allobjects []runtime.Object
var err error
var composeFileDir string
hasBuild := false
buildRepo := opt.BuildRepo
buildBranch := opt.BuildBranch
@ -360,6 +368,41 @@ func (o *OpenShift) Transform(komposeObject kobject.KomposeObject, opt kobject.C
service := komposeObject.ServiceConfigs[name]
var objects []runtime.Object
// Must build the images before conversion (got to add service.Image in case 'image' key isn't provided
// Check to see if there is an InputFile (required!) before we build the container
// Check that there's actually a Build key
// Lastly, we must have an Image name to continue
if opt.Build == "local" && opt.InputFiles != nil && service.Build != "" {
if service.Image == "" {
return nil, fmt.Errorf("image key required within build parameters in order to build and push service '%s'", name)
}
// Get the directory where the compose file is
composeFileDir, err := transformer.GetComposeFileDir(opt.InputFiles)
if err != nil {
return nil, err
}
// Build the container!
err = transformer.BuildDockerImage(service, name, composeFileDir)
if err != nil {
log.Fatalf("Unable to build Docker container for service %v: %v", name, err)
}
// Push the built container to the repo!
err = transformer.PushDockerImage(service, name)
if err != nil {
log.Fatalf("Unable to push Docker image for service %v: %v", name, err)
}
}
// If there's no "image" key, use the name of the container that's built
if service.Image == "" {
service.Image = name
}
// Generate pod only and nothing more
if service.Restart == "no" || service.Restart == "on-failure" {
// Error out if Controller Object is specified with restart: 'on-failure'
@ -378,38 +421,49 @@ func (o *OpenShift) Transform(komposeObject kobject.KomposeObject, opt kobject.C
}
// buildconfig needs to be added to objects after imagestream because of this Openshift bug: https://github.com/openshift/origin/issues/4518
if service.Build != "" {
if !hasBuild {
composeFileDir, err = getComposeFileDir(opt.InputFiles)
if err != nil {
log.Warningf("Error in detecting compose file's directory.")
continue
}
if !hasGitBinary() && (buildRepo == "" || buildBranch == "") {
return nil, errors.New("Git is not installed! Please install Git to create buildconfig, else supply source repository and branch to use for build using '--build-repo', '--build-branch' options respectively")
}
if buildBranch == "" {
buildBranch, err = getGitCurrentBranch(composeFileDir)
if err != nil {
return nil, errors.Wrap(err, "Buildconfig cannot be created because current git branch couldn't be detected.")
}
}
if opt.BuildRepo == "" {
if err != nil {
return nil, errors.Wrap(err, "Buildconfig cannot be created because remote for current git branch couldn't be detected.")
}
buildRepo, err = getGitCurrentRemoteURL(composeFileDir)
if err != nil {
return nil, errors.Wrap(err, "Buildconfig cannot be created because git remote origin repo couldn't be detected.")
}
}
hasBuild = true
// Generate BuildConfig if the parameter has been passed
if service.Build != "" && opt.Build == "build-config" {
// Get the compose file directory
composeFileDir, err = transformer.GetComposeFileDir(opt.InputFiles)
if err != nil {
log.Warningf("Error in detecting compose file's directory.")
continue
}
// Check for Git
if !hasGitBinary() && (buildRepo == "" || buildBranch == "") {
return nil, errors.New("Git is not installed! Please install Git to create buildconfig, else supply source repository and branch to use for build using '--build-repo', '--build-branch' options respectively")
}
// Check the Git branch
if buildBranch == "" {
buildBranch, err = getGitCurrentBranch(composeFileDir)
if err != nil {
return nil, errors.Wrap(err, "Buildconfig cannot be created because current git branch couldn't be detected.")
}
}
// Detect the remote branches
if opt.BuildRepo == "" {
if err != nil {
return nil, errors.Wrap(err, "Buildconfig cannot be created because remote for current git branch couldn't be detected.")
}
buildRepo, err = getGitCurrentRemoteURL(composeFileDir)
if err != nil {
return nil, errors.Wrap(err, "Buildconfig cannot be created because git remote origin repo couldn't be detected.")
}
}
// Initialize and build BuildConfig
bc, err := initBuildConfig(name, service, buildRepo, buildBranch)
if err != nil {
return nil, errors.Wrap(err, "initBuildConfig failed")
}
objects = append(objects, bc) // Openshift BuildConfigs
// Log what we're doing
log.Infof("Buildconfig using %s::%s as source.", buildRepo, buildBranch)
}
// If ports not provided in configuration we will not make service
@ -425,18 +479,18 @@ func (o *OpenShift) Transform(komposeObject kobject.KomposeObject, opt kobject.C
objects = append(objects, svc)
}
}
o.UpdateKubernetesObjects(name, service, &objects)
// Update and then append the objects (we're done generating)
o.UpdateKubernetesObjects(name, service, &objects)
allobjects = append(allobjects, objects...)
}
if hasBuild {
log.Infof("Buildconfig using %s::%s as source.", buildRepo, buildBranch)
}
// If docker-compose has a volumes_from directive it will be handled here
o.VolumesFrom(&allobjects, komposeObject)
// sort all object so Services are first
// sort all object so all services are first
o.SortServicesFirst(&allobjects)
return allobjects, nil
}

View File

@ -28,6 +28,7 @@ import (
"github.com/kubernetes-incubator/kompose/pkg/kobject"
"github.com/kubernetes-incubator/kompose/pkg/testutils"
"github.com/kubernetes-incubator/kompose/pkg/transformer"
"github.com/kubernetes-incubator/kompose/pkg/transformer/kubernetes"
"github.com/pkg/errors"
)
@ -223,7 +224,7 @@ func TestGetComposeFileDir(t *testing.T) {
for name, test := range testCases {
t.Log("Test case: ", name)
output, err = getComposeFileDir(test.inputFiles)
output, err = transformer.GetComposeFileDir(test.inputFiles)
if err != nil {
t.Errorf("Expected success, got error: %#v", err)

View File

@ -20,11 +20,13 @@ import (
"fmt"
"io/ioutil"
"os"
"path"
"strings"
log "github.com/Sirupsen/logrus"
"github.com/kubernetes-incubator/kompose/pkg/kobject"
"github.com/kubernetes-incubator/kompose/pkg/utils/docker"
"path/filepath"
"github.com/pkg/errors"
@ -171,3 +173,80 @@ func (env EnvSort) Less(i, j int) bool {
func (env EnvSort) Swap(i, j int) {
env[i], env[j] = env[j], env[i]
}
// GetComposeFileDir returns compose file directory
func GetComposeFileDir(inputFiles []string) (string, error) {
// Lets assume all the docker-compose files are in the same directory
inputFile := inputFiles[0]
if strings.Index(inputFile, "/") != 0 {
workDir, err := os.Getwd()
if err != nil {
return "", err
}
inputFile = filepath.Join(workDir, inputFile)
}
log.Debugf("Compose file dir: %s", filepath.Dir(inputFile))
return filepath.Dir(inputFile), nil
}
func BuildDockerImage(service kobject.ServiceConfig, name string, relativePath string) error {
// First, let's figure out the relative path of the Dockerfile!
// else, we error out.
if _, err := os.Stat(service.Build); err != nil {
return errors.Wrapf(err, "%s is not a valid path for building image %s. Check if this dir exists.", service.Build, name)
}
// Get the appropriate image source and name
// use path.Base to get the last element of the relative build path
imagePath := path.Join(relativePath, path.Base(service.Build))
imageName := name
if service.Image != "" {
imageName = service.Image
}
// Connect to the Docker client
client, err := docker.DockerClient()
if err != nil {
return err
}
// Use the build struct function to build the image
// Build the image!
build := docker.Build{*client}
err = build.BuildImage(imagePath, imageName)
if err != nil {
return err
}
return nil
}
func PushDockerImage(service kobject.ServiceConfig, serviceName string) error {
log.Debugf("Pushing Docker image '%s'", service.Image)
// Don't do anything if service.Image is blank, but at least WARN about it
// lse, let's push the image
if service.Image == "" {
log.Warnf("No image name has been passed for service %s, skipping pushing to repository", serviceName)
return nil
} else {
// Connect to the Docker client
client, err := docker.DockerClient()
if err != nil {
return err
}
push := docker.Push{*client}
err = push.PushImage(service.Image)
if err != nil {
return err
}
}
return nil
}

View File

@ -18,6 +18,7 @@ package transformer
import (
"fmt"
"strings"
"testing"
)
@ -138,3 +139,13 @@ func TestParseVolume(t *testing.T) {
}
}
}
func TestGetComposeFileDir(t *testing.T) {
output, err := GetComposeFileDir([]string{"foobar/docker-compose.yaml"})
if err != nil {
t.Errorf("Error with GetComposeFileDir %v", err)
}
if !strings.Contains(output, "foobar") {
t.Errorf("Expected $PWD/foobar, got %v", output)
}
}

90
pkg/utils/archive/tar.go Normal file
View File

@ -0,0 +1,90 @@
/*
Copyright 2016 The Kubernetes Authors 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 archive
import (
"archive/tar"
"io"
"os"
"path/filepath"
"strings"
)
/*
CreateTarball creates a tarball for source and dumps it to target path
Function modified and added from https://github.com/mholt/archiver/blob/master/tar.go
*/
func CreateTarball(source, target string) error {
tarfile, err := os.Create(target)
if err != nil {
return err
}
defer tarfile.Close()
tarball := tar.NewWriter(tarfile)
defer tarball.Close()
info, err := os.Stat(source)
if err != nil {
return nil
}
var baseDir string
if info.IsDir() {
baseDir = filepath.Base(source)
}
return filepath.Walk(source,
func(path string, info os.FileInfo, err error) error {
if baseDir == path {
return nil
}
if err != nil {
return err
}
header, err := tar.FileInfoHeader(info, info.Name())
if err != nil {
return err
}
if baseDir != "" {
if strings.HasSuffix(source, "/") {
header.Name = strings.TrimPrefix(path, source)
} else {
header.Name = filepath.Join(baseDir, strings.TrimPrefix(path, source))
}
//println("Header name", header.Name)
}
if err := tarball.WriteHeader(header); err != nil {
return err
}
if info.IsDir() {
return nil
}
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(tarball, file)
return err
})
}

80
pkg/utils/docker/build.go Normal file
View File

@ -0,0 +1,80 @@
/*
Copyright 2016 The Kubernetes Authors 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 docker
import (
"bytes"
log "github.com/Sirupsen/logrus"
dockerlib "github.com/fsouza/go-dockerclient"
"github.com/kubernetes-incubator/kompose/pkg/utils/archive"
"github.com/pkg/errors"
"io/ioutil"
"os"
"path"
"strings"
)
type Build struct {
Client dockerlib.Client
}
/*
Build a Docker image via the Docker API. Takes the source directory
and image name and then builds the appropriate image. Tarball is utilized
in order to make building easier.
*/
func (c *Build) BuildImage(source string, image string) error {
log.Infof("Building image '%s' from directory '%s'", image, path.Base(source))
// Create a temporary file for tarball image packaging
tmpFile, err := ioutil.TempFile("/tmp", "kompose-image-build-")
if err != nil {
return err
}
log.Debugf("Created temporary file %v for Docker image tarballing", tmpFile.Name())
// Create a tarball of the source directory in order to build the resulting image
err = archive.CreateTarball(strings.Join([]string{source, ""}, "/"), tmpFile.Name())
if err != nil {
return errors.Wrap(err, "Unable to create a tarball")
}
// Load the file into memory
tarballSource, err := os.Open(tmpFile.Name())
if err != nil {
return errors.Wrap(err, "Unable to load tarball into memory")
}
// Let's create all the options for the image building.
outputBuffer := bytes.NewBuffer(nil)
opts := dockerlib.BuildImageOptions{
Name: image,
InputStream: tarballSource,
OutputStream: outputBuffer,
}
// Build it!
if err := c.Client.BuildImage(opts); err != nil {
return errors.Wrap(err, "Unable to build image. For more output, use -v or --verbose when converting.")
}
log.Infof("Image '%s' from directory '%s' built successfully", image, path.Base(source))
log.Debugf("Image %s build output:\n%s", image, outputBuffer)
return nil
}

View File

@ -0,0 +1,36 @@
/*
Copyright 2016 The Kubernetes Authors 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 docker
import (
"github.com/fsouza/go-dockerclient"
)
func DockerClient() (*docker.Client, error) {
// Default end-point, HTTP + TLS support to be added in the future
// Eventually functionality to specify end-point added to command-line
endpoint := "unix:///var/run/docker.sock"
// Use the unix socker end-point. No support for TLS (yet)
client, err := docker.NewClient(endpoint)
if err != nil {
return client, err
}
return client, nil
}

84
pkg/utils/docker/push.go Normal file
View File

@ -0,0 +1,84 @@
/*
Copyright 2016 The Kubernetes Authors 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 docker
import (
"bytes"
log "github.com/Sirupsen/logrus"
dockerlib "github.com/fsouza/go-dockerclient"
"github.com/novln/docker-parser"
"github.com/pkg/errors"
)
type Push struct {
Client dockerlib.Client
}
/*
Push a Docker image via the Docker API. Takes the image name,
parses the URL details and then push based on environment authentication
credentials.
*/
func (c *Push) PushImage(fullImageName string) error {
outputBuffer := bytes.NewBuffer(nil)
// Using https://github.com/novln/docker-parser in order to parse the appropriate
// name and registry.
parsedImage, err := dockerparser.Parse(fullImageName)
if err != nil {
return err
}
image, registry := parsedImage.Name(), parsedImage.Registry()
log.Infof("Pushing image '%s' to registry '%s'", image, registry)
// Let's setup the push and authentication options
options := dockerlib.PushImageOptions{
Name: parsedImage.Name(),
Registry: parsedImage.Registry(),
OutputStream: outputBuffer,
}
// Retrieve the authentication configuration file
// Files checked as per https://godoc.org/github.com/fsouza/go-dockerclient#NewAuthConfigurationsFromFile
// $DOCKER_CONFIG/config.json, $HOME/.docker/config.json , $HOME/.dockercfg
credentials, err := dockerlib.NewAuthConfigurationsFromDockerCfg()
if err != nil {
return errors.Wrap(err, "Unable to retrieve .docker/config.json authentication details. Check that 'docker login' works successfully on the command line.")
}
// Push the image to the repository (based on the URL)
// We will iterate through all available authentication configurations until we find one that pushes successfully
// and then return nil.
if len(credentials.Configs) > 1 {
log.Info("Multiple authentication credentials detected. Will try each configuration.")
}
for k, v := range credentials.Configs {
log.Infof("Attempting authentication credentials '%s", k)
err = c.Client.PushImage(options, v)
if err != nil {
log.Errorf("Unable to push image '%s' to registry '%s'. Error: %s", image, registry, err)
} else {
log.Debugf("Image '%s' push output:\n%s", image, outputBuffer)
log.Infof("Successfully pushed image '%s' to registry '%s'", image, registry)
return nil
}
}
return errors.New("Unable to push docker image(s). Check that `docker login` works successfully on the command line.")
}

View File

@ -27,6 +27,8 @@ fi
# Warning Template
warning="Buildconfig using $uri::$branch as source."
# Replacing variables with current branch and uri
sed -e "s;%URI%;$uri;g" -e "s;%REF%;$branch;g" $KOMPOSE_ROOT/script/test/fixtures/nginx-node-redis/output-os-template.json > /tmp/output-os.json
#######
# Tests related to docker-compose file in /script/test/fixtures/etherpad
@ -54,11 +56,13 @@ unset $(cat $KOMPOSE_ROOT/script/test/fixtures/gitlab/envs | cut -d'=' -f1)
######
# Tests related to docker-compose file in /script/test/fixtures/nginx-node-redis
# kubernetes test
convert::expect_success_and_warning "kompose -f $KOMPOSE_ROOT/script/test/fixtures/nginx-node-redis/docker-compose.yml convert --stdout -j" "$KOMPOSE_ROOT/script/test/fixtures/nginx-node-redis/output-k8s.json" "Kubernetes provider doesn't support build key - ignoring"
convert::expect_success "kompose -f $KOMPOSE_ROOT/script/test/fixtures/nginx-node-redis/docker-compose.yml convert --stdout -j" "$KOMPOSE_ROOT/script/test/fixtures/nginx-node-redis/output-k8s.json"
# openshift test
# Replacing variables with current branch and uri
# Test BuildConfig
sed -e "s;%URI%;$uri;g" -e "s;%REF%;$branch;g" $KOMPOSE_ROOT/script/test/fixtures/nginx-node-redis/output-os-template.json > /tmp/output-os.json
convert::expect_success_and_warning "kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/nginx-node-redis/docker-compose.yml convert --stdout -j" "/tmp/output-os.json" "$warning"
convert::expect_success_and_warning "kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/nginx-node-redis/docker-compose.yml convert --stdout -j --build build-config" "/tmp/output-os.json" "$warning"
rm /tmp/output-os.json
######
@ -214,23 +218,25 @@ convert::check_artifacts_generated "kompose -f $KOMPOSE_ROOT/script/test/fixture
####
# Test regarding build context (running kompose from various directories)
# Replacing variables with current branch and uri
# Test BuildConfig
sed -e "s;%URI%;$uri;g" -e "s;%REF%;$branch;g" $KOMPOSE_ROOT/script/test/fixtures/nginx-node-redis/output-os-template.json > /tmp/output-os.json
CURRENT_DIR=$(pwd)
cd "$KOMPOSE_ROOT/script/test/fixtures/nginx-node-redis/"
convert::expect_success_and_warning "kompose convert --provider openshift --stdout -j" "/tmp/output-os.json" "$warning"
convert::expect_success_and_warning "kompose convert --provider openshift --stdout -j --build build-config" "/tmp/output-os.json" "$warning"
cd "$KOMPOSE_ROOT/script/test/fixtures/"
convert::expect_success_and_warning "kompose convert --provider openshift --stdout -j -f nginx-node-redis/docker-compose.yml" "/tmp/output-os.json" "$warning"
convert::expect_success_and_warning "kompose convert --provider openshift --stdout -j -f nginx-node-redis/docker-compose.yml --build build-config" "/tmp/output-os.json" "$warning"
cd "$KOMPOSE_ROOT/script/test/fixtures/nginx-node-redis/node"
convert::expect_success_and_warning "kompose convert --provider openshift --stdout -j -f ../docker-compose.yml" "/tmp/output-os.json" "$warning"
convert::expect_success_and_warning "kompose convert --provider openshift --stdout -j -f ../docker-compose.yml --build build-config" "/tmp/output-os.json" "$warning"
cd $CURRENT_DIR
rm /tmp/output-os.json
# Test the presence of build args in buildconfig
# Replacing variables with current branch and uri
# Test BuildConfig
sed -e "s;%URI%;$uri;g" -e "s;%REF%;$branch;g" $KOMPOSE_ROOT/script/test/fixtures/buildargs/output-os-template.json > /tmp/output-buildarg-os.json
export $(cat $KOMPOSE_ROOT/script/test/fixtures/buildargs/envs)
convert::expect_success_and_warning "kompose --provider openshift -f $KOMPOSE_ROOT/script/test/fixtures/buildargs/docker-compose.yml convert --stdout -j" "/tmp/output-buildarg-os.json" "$warning"
convert::expect_success_and_warning "kompose --provider openshift -f $KOMPOSE_ROOT/script/test/fixtures/buildargs/docker-compose.yml convert --stdout -j --build build-config" "/tmp/output-buildarg-os.json" "$warning"
rm /tmp/output-buildarg-os.json
# Test related to support docker-compose.yaml beside docker-compose.yml

View File

@ -3,33 +3,6 @@
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "foo1",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "foo1"
}
},
"spec": {
"ports": [
{
"name": "headless",
"port": 55555,
"targetPort": 0
}
],
"selector": {
"io.kompose.service": "foo1"
},
"clusterIP": "None"
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Service",
"apiVersion": "v1",
@ -58,7 +31,7 @@
}
},
{
"kind": "DeploymentConfig",
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "foo1",
@ -68,127 +41,20 @@
}
},
"spec": {
"strategy": {
"resources": {}
},
"triggers": [
"ports": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"foo1"
],
"from": {
"kind": "ImageStreamTag",
"name": "foo1:latest"
}
}
"name": "headless",
"port": 55555,
"targetPort": 0
}
],
"replicas": 1,
"test": false,
"selector": {
"io.kompose.service": "foo1"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "foo1"
}
},
"spec": {
"containers": [
{
"name": "foo1",
"image": " ",
"args": [
"sleep",
"3600"
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "foo1",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "foo1"
}
},
"spec": {},
"status": {
"dockerImageRepository": ""
}
},
{
"kind": "BuildConfig",
"apiVersion": "v1",
"metadata": {
"name": "foo1",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "foo1"
}
},
"spec": {
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange"
}
],
"runPolicy": "Serial",
"source": {
"type": "Git",
"git": {
"uri": "%URI%",
"ref": "%REF%"
},
"contextDir": "script/test/fixtures/buildargs/build/"
},
"strategy": {
"type": "Docker",
"dockerStrategy": {
"env": [
{
"name": "NAME",
"value": "web"
},
{
"name": "foo",
"value": "bar"
}
]
}
},
"output": {
"to": {
"kind": "ImageStreamTag",
"name": "foo1:latest"
}
},
"resources": {},
"postCommit": {},
"nodeSelector": null
"clusterIP": "None"
},
"status": {
"lastVersion": 0
"loadBalancer": {}
}
},
{
@ -263,7 +129,20 @@
"io.kompose.service": "foo"
}
},
"spec": {},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "foo"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
@ -282,9 +161,6 @@
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange"
}
],
"runPolicy": "Serial",
@ -320,6 +196,150 @@
"status": {
"lastVersion": 0
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "foo1",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "foo1"
}
},
"spec": {
"strategy": {
"resources": {}
},
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"foo1"
],
"from": {
"kind": "ImageStreamTag",
"name": "foo1:latest"
}
}
}
],
"replicas": 1,
"test": false,
"selector": {
"io.kompose.service": "foo1"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "foo1"
}
},
"spec": {
"containers": [
{
"name": "foo1",
"image": " ",
"args": [
"sleep",
"3600"
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "foo1",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "foo1"
}
},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "foo1"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
},
{
"kind": "BuildConfig",
"apiVersion": "v1",
"metadata": {
"name": "foo1",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "foo1"
}
},
"spec": {
"triggers": [
{
"type": "ConfigChange"
}
],
"runPolicy": "Serial",
"source": {
"type": "Git",
"git": {
"uri": "%URI%",
"ref": "%REF%"
},
"contextDir": "script/test/fixtures/buildargs/build/"
},
"strategy": {
"type": "Docker",
"dockerStrategy": {
"env": [
{
"name": "NAME",
"value": "web"
},
{
"name": "foo",
"value": "bar"
}
]
}
},
"output": {
"to": {
"kind": "ImageStreamTag",
"name": "foo1:latest"
}
},
"resources": {},
"postCommit": {},
"nodeSelector": null
},
"status": {
"lastVersion": 0
}
}
]
}

View File

@ -0,0 +1,2 @@
FROM busybox
RUN touch /test

View File

@ -0,0 +1,5 @@
version: "2"
services:
foo:
build: "./build"

View File

@ -0,0 +1,6 @@
version: "2"
services:
foo:
build: "./build"
image: docker.io/cdrage/foobar

View File

@ -110,14 +110,6 @@
}
],
"env": [
{
"name": "DB_DBID",
"value": "etherpad"
},
{
"name": "DB_HOST",
"value": "mariadb"
},
{
"name": "DB_PASS",
"value": "etherpad"
@ -129,6 +121,14 @@
{
"name": "DB_USER",
"value": "etherpad"
},
{
"name": "DB_DBID",
"value": "etherpad"
},
{
"name": "DB_HOST",
"value": "mariadb"
}
],
"resources": {}

View File

@ -3,6 +3,42 @@
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "gitlab",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "gitlab"
}
},
"spec": {
"ports": [
{
"name": "30000",
"port": 30000,
"targetPort": 80
},
{
"name": "30001",
"port": 30001,
"targetPort": 443
},
{
"name": "30002",
"port": 30002,
"targetPort": 22
}
],
"selector": {
"io.kompose.service": "gitlab"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Service",
"apiVersion": "v1",
@ -56,7 +92,7 @@
}
},
{
"kind": "Service",
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "gitlab",
@ -66,29 +102,124 @@
}
},
"spec": {
"ports": [
"strategy": {
"resources": {}
},
"triggers": [
{
"name": "30000",
"port": 30000,
"targetPort": 80
"type": "ConfigChange"
},
{
"name": "30001",
"port": 30001,
"targetPort": 443
},
{
"name": "30002",
"port": 30002,
"targetPort": 22
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"gitlab"
],
"from": {
"kind": "ImageStreamTag",
"name": "gitlab:latest"
}
}
}
],
"replicas": 1,
"test": false,
"selector": {
"io.kompose.service": "gitlab"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "gitlab"
}
},
"spec": {
"containers": [
{
"name": "gitlab",
"image": " ",
"ports": [
{
"containerPort": 80
},
{
"containerPort": 443
},
{
"containerPort": 22
}
],
"env": [
{
"name": "DB_HOST",
"value": "postgresql"
},
{
"name": "DB_NAME",
"value": "gitlab"
},
{
"name": "DB_PASS",
"value": "gitlab"
},
{
"name": "DB_PORT",
"value": "5432"
},
{
"name": "DB_TYPE",
"value": "postgres"
},
{
"name": "DB_USER",
"value": "gitlab"
},
{
"name": "REDIS_HOST",
"value": "redis"
},
{
"name": "REDIS_PORT",
"value": "6379"
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "gitlab",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "gitlab"
}
},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "swordphilic/gitlab"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"loadBalancer": {}
"dockerImageRepository": ""
}
},
{
@ -286,137 +417,6 @@
"status": {
"dockerImageRepository": ""
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "gitlab",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "gitlab"
}
},
"spec": {
"strategy": {
"resources": {}
},
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"gitlab"
],
"from": {
"kind": "ImageStreamTag",
"name": "gitlab:latest"
}
}
}
],
"replicas": 1,
"test": false,
"selector": {
"io.kompose.service": "gitlab"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "gitlab"
}
},
"spec": {
"containers": [
{
"name": "gitlab",
"image": " ",
"ports": [
{
"containerPort": 80
},
{
"containerPort": 443
},
{
"containerPort": 22
}
],
"env": [
{
"name": "DB_TYPE",
"value": "postgres"
},
{
"name": "DB_USER",
"value": "gitlab"
},
{
"name": "REDIS_HOST",
"value": "redis"
},
{
"name": "REDIS_PORT",
"value": "6379"
},
{
"name": "DB_HOST",
"value": "postgresql"
},
{
"name": "DB_NAME",
"value": "gitlab"
},
{
"name": "DB_PASS",
"value": "gitlab"
},
{
"name": "DB_PORT",
"value": "5432"
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "gitlab",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "gitlab"
}
},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "swordphilic/gitlab"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
}
]
}

View File

@ -123,6 +123,14 @@
}
],
"env": [
{
"name": "DB_HOST",
"value": "openshift"
},
{
"name": "DB_PASS",
"value": "openshift"
},
{
"name": "DB_PORT",
"value": "openshift"
@ -134,14 +142,6 @@
{
"name": "DB_DBID",
"value": "openshift"
},
{
"name": "DB_HOST",
"value": "openshift"
},
{
"name": "DB_PASS",
"value": "openshift"
}
],
"resources": {}
@ -254,14 +254,6 @@
}
],
"env": [
{
"name": "MYSQL_PASSWORD",
"value": "openshift"
},
{
"name": "MYSQL_ROOT_PASSWORD",
"value": "openshift"
},
{
"name": "MYSQL_USER",
"value": "openshift"
@ -269,6 +261,14 @@
{
"name": "MYSQL_DATABASE",
"value": "openshift"
},
{
"name": "MYSQL_PASSWORD",
"value": "openshift"
},
{
"name": "MYSQL_ROOT_PASSWORD",
"value": "openshift"
}
],
"resources": {},

View File

@ -156,6 +156,7 @@
"containers": [
{
"name": "nginx",
"image": "nginx",
"ports": [
{
"containerPort": 80
@ -194,6 +195,7 @@
"containers": [
{
"name": "node1",
"image": "node1",
"ports": [
{
"containerPort": 8080
@ -232,6 +234,7 @@
"containers": [
{
"name": "node2",
"image": "node2",
"ports": [
{
"containerPort": 8080
@ -270,6 +273,7 @@
"containers": [
{
"name": "node3",
"image": "node3",
"ports": [
{
"containerPort": 8080

View File

@ -206,7 +206,20 @@
"io.kompose.service": "nginx"
}
},
"spec": {},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "nginx"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
@ -225,9 +238,6 @@
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange"
}
],
"runPolicy": "Serial",
@ -330,7 +340,20 @@
"io.kompose.service": "node1"
}
},
"spec": {},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "node1"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
@ -349,9 +372,6 @@
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange"
}
],
"runPolicy": "Serial",
@ -454,7 +474,20 @@
"io.kompose.service": "node2"
}
},
"spec": {},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "node2"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
@ -473,9 +506,6 @@
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange"
}
],
"runPolicy": "Serial",
@ -578,7 +608,20 @@
"io.kompose.service": "node3"
}
},
"spec": {},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "node3"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
@ -597,9 +640,6 @@
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange"
}
],
"runPolicy": "Serial",
@ -702,23 +742,10 @@
"io.kompose.service": "redis"
}
},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "redis"
},
"generation": null,
"importPolicy": {}
}
]
},
"spec": {},
"status": {
"dockerImageRepository": ""
}
}
]
}
}

View File

@ -0,0 +1,592 @@
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "nginx",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "nginx"
}
},
"spec": {
"ports": [
{
"name": "80",
"port": 80,
"targetPort": 80
}
],
"selector": {
"io.kompose.service": "nginx"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "node1",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "node1"
}
},
"spec": {
"ports": [
{
"name": "8080",
"port": 8080,
"targetPort": 8080
}
],
"selector": {
"io.kompose.service": "node1"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "node2",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "node2"
}
},
"spec": {
"ports": [
{
"name": "8080",
"port": 8080,
"targetPort": 8080
}
],
"selector": {
"io.kompose.service": "node2"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "node3",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "node3"
}
},
"spec": {
"ports": [
{
"name": "8080",
"port": 8080,
"targetPort": 8080
}
],
"selector": {
"io.kompose.service": "node3"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "redis"
}
},
"spec": {
"ports": [
{
"name": "6379",
"port": 6379,
"targetPort": 6379
}
],
"selector": {
"io.kompose.service": "redis"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "nginx",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "nginx"
}
},
"spec": {
"strategy": {
"resources": {}
},
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"nginx"
],
"from": {
"kind": "ImageStreamTag",
"name": "nginx:latest"
}
}
}
],
"replicas": 1,
"test": false,
"selector": {
"io.kompose.service": "nginx"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "nginx"
}
},
"spec": {
"containers": [
{
"name": "nginx",
"image": " ",
"ports": [
{
"containerPort": 80
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "nginx",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "nginx"
}
},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "nginx"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "node1",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "node1"
}
},
"spec": {
"strategy": {
"resources": {}
},
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"node1"
],
"from": {
"kind": "ImageStreamTag",
"name": "node1:latest"
}
}
}
],
"replicas": 1,
"test": false,
"selector": {
"io.kompose.service": "node1"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "node1"
}
},
"spec": {
"containers": [
{
"name": "node1",
"image": " ",
"ports": [
{
"containerPort": 8080
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "node1",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "node1"
}
},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "node1"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "node2",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "node2"
}
},
"spec": {
"strategy": {
"resources": {}
},
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"node2"
],
"from": {
"kind": "ImageStreamTag",
"name": "node2:latest"
}
}
}
],
"replicas": 1,
"test": false,
"selector": {
"io.kompose.service": "node2"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "node2"
}
},
"spec": {
"containers": [
{
"name": "node2",
"image": " ",
"ports": [
{
"containerPort": 8080
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "node2",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "node2"
}
},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "node2"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "node3",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "node3"
}
},
"spec": {
"strategy": {
"resources": {}
},
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"node3"
],
"from": {
"kind": "ImageStreamTag",
"name": "node3:latest"
}
}
}
],
"replicas": 1,
"test": false,
"selector": {
"io.kompose.service": "node3"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "node3"
}
},
"spec": {
"containers": [
{
"name": "node3",
"image": " ",
"ports": [
{
"containerPort": 8080
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "node3",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "node3"
}
},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "node3"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "redis"
}
},
"spec": {
"strategy": {
"resources": {}
},
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"redis"
],
"from": {
"kind": "ImageStreamTag",
"name": "redis:latest"
}
}
}
],
"replicas": 1,
"test": false,
"selector": {
"io.kompose.service": "redis"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "redis"
}
},
"spec": {
"containers": [
{
"name": "redis",
"image": " ",
"ports": [
{
"containerPort": 6379
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "redis"
}
},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "redis"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
}
]
}

View File

@ -3,32 +3,6 @@
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "web"
}
},
"spec": {
"ports": [
{
"name": "5000",
"port": 5000,
"targetPort": 5000
}
],
"selector": {
"io.kompose.service": "web"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Service",
"apiVersion": "v1",
@ -56,7 +30,7 @@
}
},
{
"kind": "DeploymentConfig",
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "web",
@ -66,84 +40,19 @@
}
},
"spec": {
"strategy": {
"resources": {}
},
"triggers": [
"ports": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"web"
],
"from": {
"kind": "ImageStreamTag",
"name": "web:latest"
}
}
"name": "5000",
"port": 5000,
"targetPort": 5000
}
],
"replicas": 1,
"test": false,
"selector": {
"io.kompose.service": "web"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "web"
}
},
"spec": {
"containers": [
{
"name": "web",
"image": " ",
"ports": [
{
"containerPort": 5000
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "web"
}
},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "tuna/docker-counter23"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
"loadBalancer": {}
}
},
{
@ -236,6 +145,97 @@
"status": {
"dockerImageRepository": ""
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "web"
}
},
"spec": {
"strategy": {
"resources": {}
},
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"web"
],
"from": {
"kind": "ImageStreamTag",
"name": "web:latest"
}
}
}
],
"replicas": 1,
"test": false,
"selector": {
"io.kompose.service": "web"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"io.kompose.service": "web"
}
},
"spec": {
"containers": [
{
"name": "web",
"image": " ",
"ports": [
{
"containerPort": 5000
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"io.kompose.service": "web"
}
},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "tuna/docker-counter23"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
}
]
}