This commit is contained in:
Tomer Zait
2024-01-16 23:44:49 +02:00
parent 770da91eec
commit cd6a318896
11 changed files with 255 additions and 30 deletions
+15 -11
View File
@@ -26,6 +26,7 @@ import (
"github.com/pkg/errors"
"github.com/spf13/cast"
v1 "k8s.io/api/apps/v1"
batchv1 "k8s.io/api/batch/v1"
"k8s.io/apimachinery/pkg/util/intstr"
)
@@ -153,17 +154,20 @@ type ServiceConfig struct {
DeployMode string `compose:""`
VolumeMountSubPath string `compose:"kompose.volume.subpath"`
// DeployLabels mapping to kubernetes labels
DeployLabels map[string]string `compose:""`
DeployUpdateConfig types.UpdateConfig `compose:""`
TmpFs []string `compose:"tmpfs"`
Dockerfile string `compose:"dockerfile"`
Replicas int `compose:"replicas"`
GroupAdd []int64 `compose:"group_add"`
FsGroup int64 `compose:"kompose.security-context.fsgroup"`
Volumes []Volumes `compose:""`
Secrets []types.ServiceSecretConfig
HealthChecks HealthChecks `compose:""`
Placement Placement `compose:""`
DeployLabels map[string]string `compose:""`
DeployUpdateConfig types.UpdateConfig `compose:""`
TmpFs []string `compose:"tmpfs"`
Dockerfile string `compose:"dockerfile"`
Replicas int `compose:"replicas"`
GroupAdd []int64 `compose:"group_add"`
FsGroup int64 `compose:"kompose.security-context.fsgroup"`
CronJobSchedule string `compose:"kompose.cronjob.schedule"`
CronJobConcurrencyPolicy batchv1.ConcurrencyPolicy `compose:"kompose.cronjob.concurrency_policy"`
CronJobBackoffLimit *int32 `compose:"kompose.cronjob.backoff_limit"`
Volumes []Volumes `compose:""`
Secrets []types.ServiceSecretConfig
HealthChecks HealthChecks `compose:""`
Placement Placement `compose:""`
//This is for long LONG SYNTAX link(https://docs.docker.com/compose/compose-file/#long-syntax)
Configs []types.ServiceConfigObjConfig `compose:""`
//This is for SHORT SYNTAX link(https://docs.docker.com/compose/compose-file/#configs)
+63
View File
@@ -33,6 +33,7 @@ import (
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/spf13/cast"
batchv1 "k8s.io/api/batch/v1"
api "k8s.io/api/core/v1"
)
@@ -693,6 +694,42 @@ func parseEnvironment(composeServiceConfig *types.ServiceConfig, serviceConfig *
}
}
func handleCronJobConcurrencyPolicy(policy string) (batchv1.ConcurrencyPolicy, error) {
switch policy {
case "Allow":
return batchv1.AllowConcurrent, nil
case "Forbid":
return batchv1.ForbidConcurrent, nil
case "Replace":
return batchv1.ReplaceConcurrent, nil
case "":
return "", nil
default:
return "", fmt.Errorf("invalid cronjob concurrency policy: %s", policy)
}
}
func handleCronJobBackoffLimit(backoffLimit string) (*int32, error) {
if backoffLimit == "" {
return nil, nil
}
limit, err := cast.ToInt32E(backoffLimit)
if err != nil {
return nil, fmt.Errorf("invalid cronjob backoff limit: %s", backoffLimit)
}
return &limit, nil
}
func handleCronJobSchedule(schedule string) (string, error) {
if schedule == "" {
return "", fmt.Errorf("cronjob schedule cannot be empty")
}
return schedule, nil
}
// parseKomposeLabels parse kompose labels, also do some validation
func parseKomposeLabels(labels map[string]string, serviceConfig *kobject.ServiceConfig) error {
// Label handler
@@ -734,6 +771,27 @@ func parseKomposeLabels(labels map[string]string, serviceConfig *kobject.Service
serviceConfig.ImagePullPolicy = value
case LabelContainerVolumeSubpath:
serviceConfig.VolumeMountSubPath = value
case LabelCronJobSchedule:
cronJobSchedule, err := handleCronJobSchedule(value)
if err != nil {
return errors.Wrap(err, "handleCronJobSchedule failed")
}
serviceConfig.CronJobSchedule = cronJobSchedule
case LabelCronJobConcurrencyPolicy:
cronJobConcurrencyPolicy, err := handleCronJobConcurrencyPolicy(value)
if err != nil {
return errors.Wrap(err, "handleCronJobConcurrencyPolicy failed")
}
serviceConfig.CronJobConcurrencyPolicy = cronJobConcurrencyPolicy
case LabelCronJobBackoffLimit:
cronJobBackoffLimit, err := handleCronJobBackoffLimit(value)
if err != nil {
return errors.Wrap(err, "handleCronJobBackoffLimit failed")
}
serviceConfig.CronJobBackoffLimit = cronJobBackoffLimit
default:
serviceConfig.Labels[key] = value
}
@@ -755,6 +813,11 @@ func parseKomposeLabels(labels map[string]string, serviceConfig *kobject.Service
return errors.New("cannot set kompose.service.nodeport.port when service has multiple ports")
}
if serviceConfig.Restart == "always" && serviceConfig.CronJobConcurrencyPolicy != "" {
log.Infof("cronjob restart policy will be converted from '%s' to 'on-failure'", serviceConfig.Restart)
serviceConfig.Restart = "on-failure"
}
return nil
}
+6 -2
View File
@@ -76,14 +76,18 @@ const (
HealthCheckLivenessHTTPGetPort = "kompose.service.healthcheck.liveness.http_get_port"
// HealthCheckLivenessTCPPort defines liveness health check tcp port
HealthCheckLivenessTCPPort = "kompose.service.healthcheck.liveness.tcp_port"
// ServiceTypeHeadless ...
ServiceTypeHeadless = "Headless"
// LabelSecurityContextFsGroup defines the pod FsGroup
LabelSecurityContextFsGroup = "kompose.security-context.fsgroup"
// LabelContainerVolumeSubpath defines the volume mount subpath inside container
LabelContainerVolumeSubpath = "kompose.volume.subpath"
// LabelCronJobSchedule defines the cron job schedule
LabelCronJobSchedule = "kompose.cronjob.schedule"
// LabelCronJobConcurrencyPolicy defines the cron job concurrency policy
LabelCronJobConcurrencyPolicy = "kompose.cronjob.concurrency_policy"
// LabelCronJobBackoffLimit defines the job backoff limit
LabelCronJobBackoffLimit = "kompose.cronjob.backoff_limit"
)
// load environment variables from compose file
+43 -4
View File
@@ -42,6 +42,7 @@ import (
"github.com/spf13/cast"
"golang.org/x/tools/godoc/util"
appsv1 "k8s.io/api/apps/v1"
batchv1 "k8s.io/api/batch/v1"
api "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
"k8s.io/apimachinery/pkg/api/resource"
@@ -470,6 +471,33 @@ func (k *Kubernetes) InitSS(name string, service kobject.ServiceConfig, replicas
return ds
}
// InitCJ initializes Kubernetes CronJob object
func (k *Kubernetes) InitCJ(name string, service kobject.ServiceConfig, schedule string, concurrencyPolicy batchv1.ConcurrencyPolicy, backoffLimit *int32) *batchv1.CronJob {
cj := &batchv1.CronJob{
TypeMeta: metav1.TypeMeta{
Kind: "CronJob",
APIVersion: "batch/v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Labels: transformer.ConfigAllLabels(name, &service),
},
Spec: batchv1.CronJobSpec{
Schedule: schedule,
ConcurrencyPolicy: concurrencyPolicy,
JobTemplate: batchv1.JobTemplateSpec{
Spec: batchv1.JobSpec{
BackoffLimit: backoffLimit,
Template: api.PodTemplateSpec{
Spec: k.InitPodSpec(name, service.Image, service.ImagePullSecret),
},
},
},
},
}
return cj
}
func (k *Kubernetes) initIngress(name string, service kobject.ServiceConfig, port int32) *networkingv1.Ingress {
hosts := regexp.MustCompile("[ ,]*,[ ,]*").Split(service.ExposeService, -1)
@@ -1587,11 +1615,16 @@ func (k *Kubernetes) Transform(komposeObject kobject.KomposeObject, opt kobject.
return nil, err
}
// Generate pod and configmap objects
// Generate pod or cronjob and configmap objects
if (service.Restart == "no" || service.Restart == "on-failure") && !opt.IsPodController() {
log.Infof("Create kubernetes pod instead of pod controller due to restart policy: %s", service.Restart)
pod := k.InitPod(name, service)
objects = append(objects, pod)
if service.CronJobSchedule != "" {
log.Infof("Create kubernetes pod instead of pod controller due to restart policy: %s", service.Restart)
cronJob := k.InitCJ(name, service, service.CronJobSchedule, service.CronJobConcurrencyPolicy, service.CronJobBackoffLimit)
objects = append(objects, cronJob)
} else {
pod := k.InitPod(name, service)
objects = append(objects, pod)
}
if len(service.EnvFile) > 0 {
for _, envFile := range service.EnvFile {
@@ -1651,6 +1684,12 @@ func (k *Kubernetes) UpdateController(obj runtime.Object, updateTemplate func(*a
return errors.Wrap(err, "updateTemplate failed")
}
updateMeta(&t.ObjectMeta)
case *batchv1.CronJob:
err = updateTemplate(&t.Spec.JobTemplate.Spec.Template)
if err != nil {
return errors.Wrap(err, "updateTemplate failed")
}
updateMeta(&t.ObjectMeta)
case *deployapi.DeploymentConfig:
err = updateTemplate(t.Spec.Template)
if err != nil {
+9 -3
View File
@@ -325,14 +325,20 @@ func (o *OpenShift) Transform(komposeObject kobject.KomposeObject, opt kobject.C
}
}
// Generate pod and configmap objects
// Generate pod or cronjob and configmap objects
if service.Restart == "no" || service.Restart == "on-failure" {
// Error out if Controller Object is specified with restart: 'on-failure'
if opt.IsDeploymentConfigFlag {
return nil, errors.New("Controller object cannot be specified with restart: 'on-failure'")
}
pod := o.InitPod(name, service)
objects = append(objects, pod)
if service.CronJobSchedule != "" {
cronJob := o.InitCJ(name, service, service.CronJobSchedule, service.CronJobConcurrencyPolicy, service.CronJobBackoffLimit)
objects = append(objects, cronJob)
} else {
pod := o.InitPod(name, service)
objects = append(objects, pod)
}
if len(service.EnvFile) > 0 {
for _, envFile := range service.EnvFile {