transformers: make Openshift Inherit from Kubernetes

This commit is contained in:
Dusty Mabe 2016-10-26 17:07:12 -04:00
parent 4afb49dcab
commit c5e07f4926
No known key found for this signature in database
GPG Key ID: 3302DBD73952E671
4 changed files with 79 additions and 74 deletions

View File

@ -155,14 +155,10 @@ func Convert(c *cli.Context) {
}
komposeObject = l.LoadFile(opt.InputFile)
// transformer maps komposeObject to provider's primitives
var t transformer.Transformer
if opt.Provider == "kubernetes" {
t = new(kubernetes.Kubernetes)
} else {
t = new(openshift.OpenShift)
}
// Get a transformer that maps komposeObject to provider's primitives
t := getTransformer(opt)
// Do the transformation
objects := t.Transform(komposeObject, opt)
// Print output
@ -190,13 +186,8 @@ func Up(c *cli.Context) {
}
komposeObject = l.LoadFile(opt.InputFile)
//get transfomer
var t transformer.Transformer
if opt.Provider == "kubernetes" {
t = new(kubernetes.Kubernetes)
} else {
t = new(openshift.OpenShift)
}
// Get the transformer
t := getTransformer(opt)
//Submit objects to provider
errDeploy := t.Deploy(komposeObject, opt)
@ -226,13 +217,8 @@ func Down(c *cli.Context) {
}
komposeObject = l.LoadFile(opt.InputFile)
//get transfomer
var t transformer.Transformer
if opt.Provider == "kubernetes" {
t = new(kubernetes.Kubernetes)
} else {
t = new(openshift.OpenShift)
}
// Get the transformer
t := getTransformer(opt)
//Remove deployed application
errUndeploy := t.Undeploy(komposeObject, opt)
@ -242,6 +228,21 @@ func Down(c *cli.Context) {
}
// Convenience method to return the appropriate Transformer based on
// what provider we are using.
func getTransformer(opt kobject.ConvertOptions) transformer.Transformer {
var t transformer.Transformer
if opt.Provider == "kubernetes" {
// Create/Init new Kubernetes object
t = &kubernetes.Kubernetes{}
} else {
// Create/Init new OpenShift object that is initialized with a newly
// created Kubernetes object. Openshift inherits from Kubernetes
t = &openshift.OpenShift{kubernetes.Kubernetes{}}
}
return t
}
func askForConfirmation() bool {
var response string
_, err := fmt.Scanln(&response)

View File

@ -227,7 +227,7 @@ func convertToVersion(obj runtime.Object, groupVersion unversioned.GroupVersion)
return convertedObject, nil
}
func PortsExist(name string, service kobject.ServiceConfig) bool {
func (k *Kubernetes) PortsExist(name string, service kobject.ServiceConfig) bool {
if len(service.Port) == 0 {
logrus.Warningf("[%s] Service cannot be created because of missing port.", name)
return false
@ -237,11 +237,11 @@ func PortsExist(name string, service kobject.ServiceConfig) bool {
}
// create a k8s service
func CreateService(name string, service kobject.ServiceConfig, objects []runtime.Object) *api.Service {
svc := InitSvc(name, service)
func (k *Kubernetes) CreateService(name string, service kobject.ServiceConfig, objects []runtime.Object) *api.Service {
svc := k.InitSvc(name, service)
// Configure the service ports.
servicePorts := ConfigServicePorts(name, service)
servicePorts := k.ConfigServicePorts(name, service)
svc.Spec.Ports = servicePorts
// Configure service types
@ -267,12 +267,12 @@ func CreateService(name string, service kobject.ServiceConfig, objects []runtime
}
// load configurations to k8s objects
func UpdateKubernetesObjects(name string, service kobject.ServiceConfig, objects *[]runtime.Object) {
func (k *Kubernetes) UpdateKubernetesObjects(name string, service kobject.ServiceConfig, objects *[]runtime.Object) {
// Configure the environment variables.
envs := ConfigEnvs(name, service)
envs := k.ConfigEnvs(name, service)
// Configure the container volumes.
volumesMount, volumes, pvc := ConfigVolumes(name, service)
volumesMount, volumes, pvc := k.ConfigVolumes(name, service)
if pvc != nil {
// Looping on the slice pvc instead of `*objects = append(*objects, pvc...)`
// because the type of objects and pvc is different, but when doing append
@ -283,7 +283,7 @@ func UpdateKubernetesObjects(name string, service kobject.ServiceConfig, objects
}
// Configure the container ports.
ports := ConfigPorts(name, service)
ports := k.ConfigPorts(name, service)
// Configure annotations
annotations := transformer.ConfigAnnotations(service)
@ -327,14 +327,14 @@ func UpdateKubernetesObjects(name string, service kobject.ServiceConfig, objects
// update supported controller
for _, obj := range *objects {
UpdateController(obj, fillTemplate, fillObjectMeta)
k.UpdateController(obj, fillTemplate, fillObjectMeta)
}
}
// the objects that we get can be in any order this keeps services first
// according to best practice kubernetes services should be created first
// http://kubernetes.io/docs/user-guide/config-best-practices/
func SortServicesFirst(objs *[]runtime.Object) {
func (k *Kubernetes) SortServicesFirst(objs *[]runtime.Object) {
var svc, others, ret []runtime.Object
for _, obj := range *objs {
@ -349,49 +349,49 @@ func SortServicesFirst(objs *[]runtime.Object) {
*objs = ret
}
func findDependentVolumes(svcname string, komposeObject kobject.KomposeObject) (volumes []api.Volume, volumeMounts []api.VolumeMount) {
func (k *Kubernetes) findDependentVolumes(svcname string, komposeObject kobject.KomposeObject) (volumes []api.Volume, volumeMounts []api.VolumeMount) {
// Get all the volumes and volumemounts this particular service is dependent on
for _, dependentSvc := range komposeObject.ServiceConfigs[svcname].VolumesFrom {
vols, volMounts := findDependentVolumes(dependentSvc, komposeObject)
vols, volMounts := k.findDependentVolumes(dependentSvc, komposeObject)
volumes = append(volumes, vols...)
volumeMounts = append(volumeMounts, volMounts...)
}
// add the volumes info of this service
volMounts, vols, _ := ConfigVolumes(svcname, komposeObject.ServiceConfigs[svcname])
volMounts, vols, _ := k.ConfigVolumes(svcname, komposeObject.ServiceConfigs[svcname])
volumes = append(volumes, vols...)
volumeMounts = append(volumeMounts, volMounts...)
return
}
func VolumesFrom(objects *[]runtime.Object, komposeObject kobject.KomposeObject) {
func (k *Kubernetes) VolumesFrom(objects *[]runtime.Object, komposeObject kobject.KomposeObject) {
for _, obj := range *objects {
switch t := obj.(type) {
case *api.ReplicationController:
svcName := t.ObjectMeta.Name
for _, dependentSvc := range komposeObject.ServiceConfigs[svcName].VolumesFrom {
volumes, volumeMounts := findDependentVolumes(dependentSvc, komposeObject)
volumes, volumeMounts := k.findDependentVolumes(dependentSvc, komposeObject)
t.Spec.Template.Spec.Volumes = append(t.Spec.Template.Spec.Volumes, volumes...)
t.Spec.Template.Spec.Containers[0].VolumeMounts = append(t.Spec.Template.Spec.Containers[0].VolumeMounts, volumeMounts...)
}
case *extensions.Deployment:
svcName := t.ObjectMeta.Name
for _, dependentSvc := range komposeObject.ServiceConfigs[svcName].VolumesFrom {
volumes, volumeMounts := findDependentVolumes(dependentSvc, komposeObject)
volumes, volumeMounts := k.findDependentVolumes(dependentSvc, komposeObject)
t.Spec.Template.Spec.Volumes = append(t.Spec.Template.Spec.Volumes, volumes...)
t.Spec.Template.Spec.Containers[0].VolumeMounts = append(t.Spec.Template.Spec.Containers[0].VolumeMounts, volumeMounts...)
}
case *extensions.DaemonSet:
svcName := t.ObjectMeta.Name
for _, dependentSvc := range komposeObject.ServiceConfigs[svcName].VolumesFrom {
volumes, volumeMounts := findDependentVolumes(dependentSvc, komposeObject)
volumes, volumeMounts := k.findDependentVolumes(dependentSvc, komposeObject)
t.Spec.Template.Spec.Volumes = append(t.Spec.Template.Spec.Volumes, volumes...)
t.Spec.Template.Spec.Containers[0].VolumeMounts = append(t.Spec.Template.Spec.Containers[0].VolumeMounts, volumeMounts...)
}
case *deployapi.DeploymentConfig:
svcName := t.ObjectMeta.Name
for _, dependentSvc := range komposeObject.ServiceConfigs[svcName].VolumesFrom {
volumes, volumeMounts := findDependentVolumes(dependentSvc, komposeObject)
volumes, volumeMounts := k.findDependentVolumes(dependentSvc, komposeObject)
t.Spec.Template.Spec.Volumes = append(t.Spec.Template.Spec.Volumes, volumes...)
t.Spec.Template.Spec.Containers[0].VolumeMounts = append(t.Spec.Template.Spec.Containers[0].VolumeMounts, volumeMounts...)
}

View File

@ -50,7 +50,7 @@ type Kubernetes struct {
const TIMEOUT = 300
// Init RC object
func InitRC(name string, service kobject.ServiceConfig, replicas int) *api.ReplicationController {
func (k *Kubernetes) InitRC(name string, service kobject.ServiceConfig, replicas int) *api.ReplicationController {
rc := &api.ReplicationController{
TypeMeta: unversioned.TypeMeta{
Kind: "ReplicationController",
@ -80,7 +80,7 @@ func InitRC(name string, service kobject.ServiceConfig, replicas int) *api.Repli
}
// Init Svc object
func InitSvc(name string, service kobject.ServiceConfig) *api.Service {
func (k *Kubernetes) InitSvc(name string, service kobject.ServiceConfig) *api.Service {
svc := &api.Service{
TypeMeta: unversioned.TypeMeta{
Kind: "Service",
@ -98,7 +98,7 @@ func InitSvc(name string, service kobject.ServiceConfig) *api.Service {
}
// Init Deployment
func InitD(name string, service kobject.ServiceConfig, replicas int) *extensions.Deployment {
func (k *Kubernetes) InitD(name string, service kobject.ServiceConfig, replicas int) *extensions.Deployment {
dc := &extensions.Deployment{
TypeMeta: unversioned.TypeMeta{
Kind: "Deployment",
@ -125,7 +125,7 @@ func InitD(name string, service kobject.ServiceConfig, replicas int) *extensions
}
// Init DS object
func InitDS(name string, service kobject.ServiceConfig) *extensions.DaemonSet {
func (k *Kubernetes) InitDS(name string, service kobject.ServiceConfig) *extensions.DaemonSet {
ds := &extensions.DaemonSet{
TypeMeta: unversioned.TypeMeta{
Kind: "DaemonSet",
@ -151,7 +151,7 @@ func InitDS(name string, service kobject.ServiceConfig) *extensions.DaemonSet {
}
// Initialize PersistentVolumeClaim
func CreatePVC(name string, mode string) *api.PersistentVolumeClaim {
func (k *Kubernetes) CreatePVC(name string, mode string) *api.PersistentVolumeClaim {
size, err := resource.ParseQuantity("100Mi")
if err != nil {
logrus.Fatalf("Error parsing size")
@ -183,7 +183,7 @@ func CreatePVC(name string, mode string) *api.PersistentVolumeClaim {
}
// Configure the container ports.
func ConfigPorts(name string, service kobject.ServiceConfig) []api.ContainerPort {
func (k *Kubernetes) ConfigPorts(name string, service kobject.ServiceConfig) []api.ContainerPort {
ports := []api.ContainerPort{}
for _, port := range service.Port {
ports = append(ports, api.ContainerPort{
@ -196,7 +196,7 @@ func ConfigPorts(name string, service kobject.ServiceConfig) []api.ContainerPort
}
// Configure the container service ports.
func ConfigServicePorts(name string, service kobject.ServiceConfig) []api.ServicePort {
func (k *Kubernetes) ConfigServicePorts(name string, service kobject.ServiceConfig) []api.ServicePort {
servicePorts := []api.ServicePort{}
for _, port := range service.Port {
if port.HostPort == 0 {
@ -216,7 +216,7 @@ func ConfigServicePorts(name string, service kobject.ServiceConfig) []api.Servic
}
// Configure the container volumes.
func ConfigVolumes(name string, service kobject.ServiceConfig) ([]api.VolumeMount, []api.Volume, []*api.PersistentVolumeClaim) {
func (k *Kubernetes) ConfigVolumes(name string, service kobject.ServiceConfig) ([]api.VolumeMount, []api.Volume, []*api.PersistentVolumeClaim) {
volumesMount := []api.VolumeMount{}
volumes := []api.Volume{}
var pvc []*api.PersistentVolumeClaim
@ -256,13 +256,13 @@ func ConfigVolumes(name string, service kobject.ServiceConfig) ([]api.VolumeMoun
if len(host) > 0 {
logrus.Warningf("Volume mount on the host %q isn't supported - ignoring path on the host", host)
}
pvc = append(pvc, CreatePVC(volumeName, mode))
pvc = append(pvc, k.CreatePVC(volumeName, mode))
}
return volumesMount, volumes, pvc
}
// Configure the environment variables.
func ConfigEnvs(name string, service kobject.ServiceConfig) []api.EnvVar {
func (k *Kubernetes) ConfigEnvs(name string, service kobject.ServiceConfig) []api.EnvVar {
envs := []api.EnvVar{}
for _, v := range service.Environment {
envs = append(envs, api.EnvVar{
@ -275,17 +275,17 @@ func ConfigEnvs(name string, service kobject.ServiceConfig) []api.EnvVar {
}
// Generate a Kubernetes artifact for each input type service
func CreateKubernetesObjects(name string, service kobject.ServiceConfig, opt kobject.ConvertOptions) []runtime.Object {
func (k *Kubernetes) CreateKubernetesObjects(name string, service kobject.ServiceConfig, opt kobject.ConvertOptions) []runtime.Object {
var objects []runtime.Object
if opt.CreateD {
objects = append(objects, InitD(name, service, opt.Replicas))
objects = append(objects, k.InitD(name, service, opt.Replicas))
}
if opt.CreateDS {
objects = append(objects, InitDS(name, service))
objects = append(objects, k.InitDS(name, service))
}
if opt.CreateRC {
objects = append(objects, InitRC(name, service, opt.Replicas))
objects = append(objects, k.InitRC(name, service, opt.Replicas))
}
return objects
@ -298,27 +298,27 @@ func (k *Kubernetes) Transform(komposeObject kobject.KomposeObject, opt kobject.
var allobjects []runtime.Object
for name, service := range komposeObject.ServiceConfigs {
objects := CreateKubernetesObjects(name, service, opt)
objects := k.CreateKubernetesObjects(name, service, opt)
// If ports not provided in configuration we will not make service
if PortsExist(name, service) {
svc := CreateService(name, service, objects)
if k.PortsExist(name, service) {
svc := k.CreateService(name, service, objects)
objects = append(objects, svc)
}
UpdateKubernetesObjects(name, service, &objects)
k.UpdateKubernetesObjects(name, service, &objects)
allobjects = append(allobjects, objects...)
}
// If docker-compose has a volumes_from directive it will be handled here
VolumesFrom(&allobjects, komposeObject)
k.VolumesFrom(&allobjects, komposeObject)
// sort all object so Services are first
SortServicesFirst(&allobjects)
k.SortServicesFirst(&allobjects)
return allobjects
}
// Updates the given object with the given pod template update function and ObjectMeta update function
func UpdateController(obj runtime.Object, updateTemplate func(*api.PodTemplateSpec), updateMeta func(meta *api.ObjectMeta)) {
func (k *Kubernetes) UpdateController(obj runtime.Object, updateTemplate func(*api.PodTemplateSpec), updateMeta func(meta *api.ObjectMeta)) {
switch t := obj.(type) {
case *api.ReplicationController:
if t.Spec.Template == nil {

View File

@ -42,6 +42,10 @@ import (
)
type OpenShift struct {
// Anonymous field allows for inheritance. We are basically inheriting
// all of kubernetes.Kubernetes Methods and variables here. We'll overwite
// some of those methods with our own for openshift.
kubernetes.Kubernetes
}
// getImageTag get tag name from image name
@ -56,7 +60,7 @@ func getImageTag(image string) string {
}
// initImageStream initialize ImageStream object
func initImageStream(name string, service kobject.ServiceConfig) *imageapi.ImageStream {
func (o *OpenShift) initImageStream(name string, service kobject.ServiceConfig) *imageapi.ImageStream {
tag := getImageTag(service.Image)
is := &imageapi.ImageStream{
@ -82,7 +86,7 @@ func initImageStream(name string, service kobject.ServiceConfig) *imageapi.Image
}
// initDeploymentConfig initialize OpenShifts DeploymentConfig object
func initDeploymentConfig(name string, service kobject.ServiceConfig, replicas int) *deployapi.DeploymentConfig {
func (o *OpenShift) initDeploymentConfig(name string, service kobject.ServiceConfig, replicas int) *deployapi.DeploymentConfig {
tag := getImageTag(service.Image)
dc := &deployapi.DeploymentConfig{
@ -137,39 +141,39 @@ func initDeploymentConfig(name string, service kobject.ServiceConfig, replicas i
// Transform maps komposeObject to openshift objects
// returns objects that are already sorted in the way that Services are first
func (k *OpenShift) Transform(komposeObject kobject.KomposeObject, opt kobject.ConvertOptions) []runtime.Object {
func (o *OpenShift) Transform(komposeObject kobject.KomposeObject, opt kobject.ConvertOptions) []runtime.Object {
// this will hold all the converted data
var allobjects []runtime.Object
for name, service := range komposeObject.ServiceConfigs {
objects := kubernetes.CreateKubernetesObjects(name, service, opt)
objects := o.CreateKubernetesObjects(name, service, opt)
if opt.CreateDeploymentConfig {
objects = append(objects, initDeploymentConfig(name, service, opt.Replicas)) // OpenShift DeploymentConfigs
objects = append(objects, o.initDeploymentConfig(name, service, opt.Replicas)) // OpenShift DeploymentConfigs
// create ImageStream after deployment (creating IS will trigger new deployment)
objects = append(objects, initImageStream(name, service))
objects = append(objects, o.initImageStream(name, service))
}
// If ports not provided in configuration we will not make service
if kubernetes.PortsExist(name, service) {
svc := kubernetes.CreateService(name, service, objects)
if o.PortsExist(name, service) {
svc := o.CreateService(name, service, objects)
objects = append(objects, svc)
}
kubernetes.UpdateKubernetesObjects(name, service, &objects)
o.UpdateKubernetesObjects(name, service, &objects)
allobjects = append(allobjects, objects...)
}
// If docker-compose has a volumes_from directive it will be handled here
kubernetes.VolumesFrom(&allobjects, komposeObject)
o.VolumesFrom(&allobjects, komposeObject)
// sort all object so Services are first
kubernetes.SortServicesFirst(&allobjects)
o.SortServicesFirst(&allobjects)
return allobjects
}
func (k *OpenShift) Deploy(komposeObject kobject.KomposeObject, opt kobject.ConvertOptions) error {
func (o *OpenShift) Deploy(komposeObject kobject.KomposeObject, opt kobject.ConvertOptions) error {
//Convert komposeObject
objects := k.Transform(komposeObject, opt)
objects := o.Transform(komposeObject, opt)
fmt.Println("We are going to create OpenShift DeploymentConfigs, Services and PersistentVolumeClaims for your Dockerized application. \n" +
"If you need different kind of resources, use the 'kompose convert' and 'oc create -f' commands instead. \n")
@ -230,6 +234,6 @@ func (k *OpenShift) Deploy(komposeObject kobject.KomposeObject, opt kobject.Conv
return nil
}
func (k *OpenShift) Undeploy(komposeObject kobject.KomposeObject, opt kobject.ConvertOptions) error {
func (o *OpenShift) Undeploy(komposeObject kobject.KomposeObject, opt kobject.ConvertOptions) error {
return errors.New("Not Implemented")
}