-
Notifications
You must be signed in to change notification settings - Fork 764
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat: add kompose client PoC (#1593)
* fix: support host port and protocol in functional tests * feat: add kompose client with options Signed-off-by: AhmedGrati <ahmedgrati1999@gmail.com> * test: add options unit tests Signed-off-by: AhmedGrati <ahmedgrati1999@gmail.com> * feat: add partial convert options Signed-off-by: AhmedGrati <ahmedgrati1999@gmail.com> * feat: finish convert process Signed-off-by: AhmedGrati <ahmedgrati1999@gmail.com> * test: finish unit tests of the kompose client Signed-off-by: AhmedGrati <ahmedgrati1999@gmail.com> * remove unecessary changes Signed-off-by: AhmedGrati <ahmedgrati1999@gmail.com> * feat: add generate network policies to client Signed-off-by: AhmedGrati <ahmedgrati1999@gmail.com> * update go mod Signed-off-by: AhmedGrati <ahmedgrati1999@gmail.com> --------- Signed-off-by: AhmedGrati <ahmedgrati1999@gmail.com>
- Loading branch information
1 parent
b83d4d4
commit ea80734
Showing
12 changed files
with
530 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -76,3 +76,6 @@ tags | |
.idea | ||
|
||
.DS_Store | ||
|
||
# Client Test generated files | ||
client/testdata/generated |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package client | ||
|
||
type Kompose struct { | ||
suppressWarnings bool | ||
verbose bool | ||
errorOnWarning bool | ||
} | ||
|
||
func NewClient(opts ...Opt) (*Kompose, error) { | ||
k := &Kompose{ | ||
suppressWarnings: false, | ||
verbose: false, | ||
errorOnWarning: false, | ||
} | ||
for _, op := range opts { | ||
if err := op(k); err != nil { | ||
return nil, err | ||
} | ||
} | ||
return k, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,248 @@ | ||
package client | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/kubernetes/kompose/pkg/app" | ||
"github.com/kubernetes/kompose/pkg/kobject" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
) | ||
|
||
func (k *Kompose) Convert(options ConvertOptions) ([]runtime.Object, error) { | ||
options = k.setDefaultValues(options) | ||
err := k.validateOptions(options) | ||
if err != nil { | ||
return nil, err | ||
} | ||
kobjectConvertOptions := kobject.ConvertOptions{ | ||
ToStdout: options.ToStdout, | ||
CreateChart: k.createChart(options), | ||
GenerateYaml: true, | ||
GenerateJSON: options.GenerateJson, | ||
Replicas: *options.Replicas, | ||
InputFiles: options.InputFiles, | ||
OutFile: options.OutFile, | ||
Provider: k.getProvider(options), | ||
CreateD: k.createDeployment(options), | ||
CreateDS: k.createDaemonSet(options), | ||
CreateRC: k.createReplicationController(options), | ||
Build: *options.Build, | ||
BuildRepo: k.buildRepo(options), | ||
BuildBranch: k.buildBranch(options), | ||
PushImage: options.PushImage, | ||
PushImageRegistry: options.PushImageRegistry, | ||
CreateDeploymentConfig: k.createDeploymentConfig(options), | ||
EmptyVols: false, | ||
Volumes: *options.VolumeType, | ||
PVCRequestSize: options.PvcRequestSize, | ||
InsecureRepository: k.insecureRepository(options), | ||
IsDeploymentFlag: k.createDeployment(options), | ||
IsDaemonSetFlag: k.createDaemonSet(options), | ||
IsReplicationControllerFlag: k.createReplicationController(options), | ||
Controller: k.getController(options), | ||
IsReplicaSetFlag: *options.Replicas != 0, | ||
IsDeploymentConfigFlag: k.createDeploymentConfig(options), | ||
YAMLIndent: 2, | ||
WithKomposeAnnotation: *options.WithKomposeAnnotations, | ||
MultipleContainerMode: k.multiContainerMode(options), | ||
ServiceGroupMode: k.serviceGroupMode(options), | ||
ServiceGroupName: k.serviceGroupName(options), | ||
SecretsAsFiles: k.secretsAsFiles(options), | ||
GenerateNetworkPolicies: options.GenerateNetworkPolicies, | ||
} | ||
err = app.ValidateComposeFile(&kobjectConvertOptions) | ||
if err != nil { | ||
return nil, err | ||
} | ||
objects, err := app.Convert(kobjectConvertOptions) | ||
return objects, err | ||
} | ||
|
||
func (k *Kompose) setDefaultValues(options ConvertOptions) ConvertOptions { | ||
replicasDefaultValue := 1 | ||
buildDefaultValue := "none" | ||
volumeTypeDefaultValue := "persistentVolumeClaim" | ||
withKomposeAnnotationsDefaultValue := true | ||
kubernetesControllerDefaultValue := "deployment" | ||
kubernetesServiceGroupModeDefaultValue := "" | ||
|
||
if options.Replicas == nil { | ||
options.Replicas = &replicasDefaultValue | ||
} | ||
if options.Build == nil { | ||
options.Build = &buildDefaultValue | ||
} | ||
if options.VolumeType == nil { | ||
options.VolumeType = &volumeTypeDefaultValue | ||
} | ||
if options.WithKomposeAnnotations == nil { | ||
options.WithKomposeAnnotations = &withKomposeAnnotationsDefaultValue | ||
} | ||
if options.Provider == nil { | ||
options.Provider = Kubernetes{ | ||
Controller: &kubernetesControllerDefaultValue, | ||
} | ||
} | ||
if kubernetesProvider, ok := options.Provider.(Kubernetes); ok { | ||
if kubernetesProvider.Controller == nil { | ||
options.Provider = Kubernetes{ | ||
Controller: &kubernetesControllerDefaultValue, | ||
Chart: options.Provider.(Kubernetes).Chart, | ||
MultiContainerMode: options.Provider.(Kubernetes).MultiContainerMode, | ||
ServiceGroupMode: options.Provider.(Kubernetes).ServiceGroupMode, | ||
ServiceGroupName: options.Provider.(Kubernetes).ServiceGroupName, | ||
SecretsAsFiles: options.Provider.(Kubernetes).SecretsAsFiles, | ||
} | ||
} | ||
if kubernetesProvider.ServiceGroupMode == nil { | ||
options.Provider = Kubernetes{ | ||
Controller: options.Provider.(Kubernetes).Controller, | ||
Chart: options.Provider.(Kubernetes).Chart, | ||
MultiContainerMode: options.Provider.(Kubernetes).MultiContainerMode, | ||
ServiceGroupMode: &kubernetesServiceGroupModeDefaultValue, | ||
ServiceGroupName: options.Provider.(Kubernetes).ServiceGroupName, | ||
SecretsAsFiles: options.Provider.(Kubernetes).SecretsAsFiles, | ||
} | ||
} | ||
} | ||
return options | ||
} | ||
|
||
func (k *Kompose) validateOptions(options ConvertOptions) error { | ||
build := options.Build | ||
if *build != string(LOCAL) && *build != string(BUILD_CONFIG) && *build != string(NONE) { | ||
return fmt.Errorf( | ||
"unexpected Value for Build field. Possible values are: %v, %v, and %v", string(LOCAL), string(BUILD_CONFIG), string(NONE), | ||
) | ||
} | ||
|
||
volumeType := options.VolumeType | ||
if *volumeType != string(PVC) && *volumeType != string(EMPTYDIR) && *volumeType != string(HOSTPATH) && *volumeType != string(CONFIGMAP) { | ||
return fmt.Errorf( | ||
"unexpected Value for VolumeType field. Possible values are: %v, %v, %v, %v", string(PVC), string(EMPTYDIR), string(HOSTPATH), string(CONFIGMAP), | ||
) | ||
} | ||
|
||
if kubernetesProvider, ok := options.Provider.(Kubernetes); ok { | ||
kubernetesController := kubernetesProvider.Controller | ||
if *kubernetesController != string(DEPLOYMENT) && *kubernetesController != string(DAEMONSET) && *kubernetesController != string(REPLICATION_CONTROLLER) { | ||
return fmt.Errorf( | ||
"unexpected Value for Kubernetes Controller field. Possible values are: %v, %v, and %v", string(DEPLOYMENT), string(DAEMONSET), string(REPLICATION_CONTROLLER), | ||
) | ||
} | ||
|
||
kubernetesServiceGroupMode := kubernetesProvider.ServiceGroupMode | ||
if *kubernetesServiceGroupMode != string(LABEL) && *kubernetesServiceGroupMode != string(VOLUME) && *kubernetesServiceGroupMode != "" { | ||
return fmt.Errorf( | ||
"unexpected Value for Kubernetes Service Groupe Mode field. Possible values are: %v, %v, ''", string(LABEL), string(VOLUME), | ||
) | ||
} | ||
|
||
if *build == string(BUILD_CONFIG) { | ||
return fmt.Errorf("the build value %v is only supported for Openshift provider", string(BUILD_CONFIG)) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (k *Kompose) createDeployment(options ConvertOptions) bool { | ||
if kubernetesProvider, ok := options.Provider.(Kubernetes); ok { | ||
return *kubernetesProvider.Controller == string(DEPLOYMENT) | ||
} | ||
return false | ||
} | ||
|
||
func (k *Kompose) createDaemonSet(options ConvertOptions) bool { | ||
if kubernetesProvider, ok := options.Provider.(Kubernetes); ok { | ||
return *kubernetesProvider.Controller == string(DAEMONSET) | ||
} | ||
return false | ||
} | ||
|
||
func (k *Kompose) createReplicationController(options ConvertOptions) bool { | ||
if kubernetesProvider, ok := options.Provider.(Kubernetes); ok { | ||
return *kubernetesProvider.Controller == string(REPLICATION_CONTROLLER) | ||
} | ||
return false | ||
} | ||
|
||
func (k *Kompose) createChart(options ConvertOptions) bool { | ||
if kubernetesProvider, ok := options.Provider.(Kubernetes); ok { | ||
return kubernetesProvider.Chart | ||
} | ||
return false | ||
} | ||
|
||
func (k *Kompose) multiContainerMode(options ConvertOptions) bool { | ||
if kubernetesProvider, ok := options.Provider.(Kubernetes); ok { | ||
return kubernetesProvider.MultiContainerMode | ||
} | ||
return false | ||
} | ||
|
||
func (k *Kompose) serviceGroupMode(options ConvertOptions) string { | ||
if kubernetesProvider, ok := options.Provider.(Kubernetes); ok { | ||
return *kubernetesProvider.ServiceGroupMode | ||
} | ||
return "" | ||
} | ||
|
||
func (k *Kompose) serviceGroupName(options ConvertOptions) string { | ||
if kubernetesProvider, ok := options.Provider.(Kubernetes); ok { | ||
return kubernetesProvider.ServiceGroupName | ||
} | ||
return "" | ||
} | ||
|
||
func (k *Kompose) secretsAsFiles(options ConvertOptions) bool { | ||
if kubernetesProvider, ok := options.Provider.(Kubernetes); ok { | ||
return kubernetesProvider.SecretsAsFiles | ||
} | ||
return false | ||
} | ||
|
||
func (k *Kompose) createDeploymentConfig(options ConvertOptions) bool { | ||
if _, ok := options.Provider.(Openshift); ok { | ||
return true | ||
} | ||
return false | ||
} | ||
|
||
func (k *Kompose) insecureRepository(options ConvertOptions) bool { | ||
if openshiftProvider, ok := options.Provider.(Openshift); ok { | ||
return openshiftProvider.InsecureRepository | ||
} | ||
return false | ||
} | ||
|
||
func (k *Kompose) buildRepo(options ConvertOptions) string { | ||
if openshiftProvider, ok := options.Provider.(Openshift); ok { | ||
return openshiftProvider.BuildRepo | ||
} | ||
return "" | ||
} | ||
|
||
func (k *Kompose) buildBranch(options ConvertOptions) string { | ||
if openshiftProvider, ok := options.Provider.(Openshift); ok { | ||
return openshiftProvider.BuildRepo | ||
} | ||
return "" | ||
} | ||
|
||
func (k *Kompose) getProvider(options ConvertOptions) string { | ||
if _, ok := options.Provider.(Openshift); ok { | ||
return "openshift" | ||
} | ||
if _, ok := options.Provider.(Kubernetes); ok { | ||
return "kubernetes" | ||
} | ||
return "kubernetes" | ||
} | ||
|
||
func (k *Kompose) getController(options ConvertOptions) string { | ||
if kubernetesProvider, ok := options.Provider.(Kubernetes); ok { | ||
return *kubernetesProvider.Controller | ||
} | ||
return "" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package client | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"gotest.tools/v3/assert" | ||
is "gotest.tools/v3/assert/cmp" | ||
appsv1 "k8s.io/api/apps/v1" | ||
) | ||
|
||
func TestConvertError(t *testing.T) { | ||
randomBuildValue := "random-build" | ||
randomVolumeTypeValue := "random-volume-type" | ||
randomKubernetesControllerValue := "random-controller" | ||
randomKubernetesServiceGroupModeValue := "random-group-mode" | ||
buildConfigValue := string(BUILD_CONFIG) | ||
testCases := []struct { | ||
options ConvertOptions | ||
errorMessage string | ||
}{ | ||
{ | ||
options: ConvertOptions{ | ||
Build: &randomBuildValue, | ||
}, | ||
errorMessage: fmt.Sprintf("unexpected Value for Build field. Possible values are: %v, %v, and %v", string(LOCAL), string(BUILD_CONFIG), string(NONE)), | ||
}, | ||
{ | ||
options: ConvertOptions{ | ||
VolumeType: &randomVolumeTypeValue, | ||
}, | ||
errorMessage: fmt.Sprintf("unexpected Value for VolumeType field. Possible values are: %v, %v, %v, %v", string(PVC), string(EMPTYDIR), string(HOSTPATH), string(CONFIGMAP)), | ||
}, | ||
{ | ||
options: ConvertOptions{ | ||
Provider: Kubernetes{ | ||
Controller: &randomKubernetesControllerValue, | ||
}, | ||
}, | ||
errorMessage: fmt.Sprintf("unexpected Value for Kubernetes Controller field. Possible values are: %v, %v, and %v", string(DEPLOYMENT), string(DAEMONSET), string(REPLICATION_CONTROLLER)), | ||
}, | ||
{ | ||
options: ConvertOptions{ | ||
Provider: Kubernetes{ | ||
ServiceGroupMode: &randomKubernetesServiceGroupModeValue, | ||
}, | ||
}, | ||
errorMessage: fmt.Sprintf("unexpected Value for Kubernetes Service Groupe Mode field. Possible values are: %v, %v, ''", string(LABEL), string(VOLUME)), | ||
}, | ||
{ | ||
options: ConvertOptions{ | ||
Provider: Kubernetes{}, | ||
Build: &buildConfigValue, | ||
}, | ||
errorMessage: fmt.Sprintf("the build value %v is only supported for Openshift provider", string(BUILD_CONFIG)), | ||
}, | ||
} | ||
|
||
client, err := NewClient() | ||
assert.Check(t, is.Equal(err, nil)) | ||
for _, tc := range testCases { | ||
_, err := client.Convert(tc.options) | ||
|
||
assert.Check(t, is.Equal(err.Error(), tc.errorMessage)) | ||
} | ||
} | ||
|
||
func TestConvertWithDefaultOptions(t *testing.T) { | ||
client, err := NewClient(WithErrorOnWarning()) | ||
assert.Check(t, is.Equal(err, nil)) | ||
objects, err := client.Convert(ConvertOptions{ | ||
OutFile: "./testdata/generated/", | ||
InputFiles: []string{ | ||
"./testdata/docker-compose.yaml", | ||
}, | ||
}) | ||
assert.Check(t, is.Equal(err, nil)) | ||
for _, object := range objects { | ||
if deployment, ok := object.(*appsv1.Deployment); ok { | ||
assert.Check(t, is.Equal(int(*deployment.Spec.Replicas), 1)) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package client | ||
|
||
// Opt is a configuration option to initialize a client | ||
type Opt func(*Kompose) error | ||
|
||
func WithSuppressWarnings() Opt { | ||
return func(k *Kompose) error { | ||
k.suppressWarnings = true | ||
return nil | ||
} | ||
} | ||
|
||
func WithVerboseOutput() Opt { | ||
return func(k *Kompose) error { | ||
k.verbose = true | ||
return nil | ||
} | ||
} | ||
|
||
func WithErrorOnWarning() Opt { | ||
return func(k *Kompose) error { | ||
k.errorOnWarning = true | ||
return nil | ||
} | ||
} |
Oops, something went wrong.