summaryrefslogtreecommitdiff
path: root/pkg/domain/infra/abi/play.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/domain/infra/abi/play.go')
-rw-r--r--pkg/domain/infra/abi/play.go124
1 files changed, 100 insertions, 24 deletions
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index efc7c86e3..7d87fc83a 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -1,6 +1,7 @@
package abi
import (
+ "bytes"
"context"
"fmt"
"io"
@@ -20,46 +21,79 @@ import (
"github.com/ghodss/yaml"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
+ yamlv3 "gopkg.in/yaml.v3"
v1apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
)
func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
- var (
- kubeObject v1.ObjectReference
- )
+ report := &entities.PlayKubeReport{}
+ validKinds := 0
+ // read yaml document
content, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
- if err := yaml.Unmarshal(content, &kubeObject); err != nil {
- return nil, errors.Wrapf(err, "unable to read %q as YAML", path)
+ // split yaml document
+ documentList, err := splitMultiDocYAML(content)
+ if err != nil {
+ return nil, err
}
- // NOTE: pkg/bindings/play is also parsing the file.
- // A pkg/kube would be nice to refactor and abstract
- // parts of the K8s-related code.
- switch kubeObject.Kind {
- case "Pod":
- var podYAML v1.Pod
- var podTemplateSpec v1.PodTemplateSpec
- if err := yaml.Unmarshal(content, &podYAML); err != nil {
- return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Pod", path)
+ // create pod on each document if it is a pod or deployment
+ // any other kube kind will be skipped
+ for _, document := range documentList {
+ kind, err := getKubeKind(document)
+ if err != nil {
+ return nil, errors.Wrapf(err, "unable to read %q as kube YAML", path)
}
- podTemplateSpec.ObjectMeta = podYAML.ObjectMeta
- podTemplateSpec.Spec = podYAML.Spec
- return ic.playKubePod(ctx, podTemplateSpec.ObjectMeta.Name, &podTemplateSpec, options)
- case "Deployment":
- var deploymentYAML v1apps.Deployment
- if err := yaml.Unmarshal(content, &deploymentYAML); err != nil {
- return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Deployment", path)
+
+ switch kind {
+ case "Pod":
+ var podYAML v1.Pod
+ var podTemplateSpec v1.PodTemplateSpec
+
+ if err := yaml.Unmarshal(document, &podYAML); err != nil {
+ return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Pod", path)
+ }
+
+ podTemplateSpec.ObjectMeta = podYAML.ObjectMeta
+ podTemplateSpec.Spec = podYAML.Spec
+
+ r, err := ic.playKubePod(ctx, podTemplateSpec.ObjectMeta.Name, &podTemplateSpec, options)
+ if err != nil {
+ return nil, err
+ }
+
+ report.Pods = append(report.Pods, r.Pods...)
+ validKinds++
+ case "Deployment":
+ var deploymentYAML v1apps.Deployment
+
+ if err := yaml.Unmarshal(document, &deploymentYAML); err != nil {
+ return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Deployment", path)
+ }
+
+ r, err := ic.playKubeDeployment(ctx, &deploymentYAML, options)
+ if err != nil {
+ return nil, err
+ }
+
+ report.Pods = append(report.Pods, r.Pods...)
+ validKinds++
+ default:
+ logrus.Infof("kube kind %s not supported", kind)
+ continue
}
- return ic.playKubeDeployment(ctx, &deploymentYAML, options)
- default:
- return nil, errors.Errorf("invalid YAML kind: %q. [Pod|Deployment] are the only supported Kubernetes Kinds", kubeObject.Kind)
}
+
+ if validKinds == 0 {
+ return nil, fmt.Errorf("YAML document does not contain any supported kube kind")
+ }
+
+ return report, nil
}
func (ic *ContainerEngine) playKubeDeployment(ctx context.Context, deploymentYAML *v1apps.Deployment, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
@@ -290,3 +324,45 @@ func readConfigMapFromFile(r io.Reader) (v1.ConfigMap, error) {
return cm, nil
}
+
+// splitMultiDocYAML reads mutiple documents in a YAML file and
+// returns them as a list.
+func splitMultiDocYAML(yamlContent []byte) ([][]byte, error) {
+ var documentList [][]byte
+
+ d := yamlv3.NewDecoder(bytes.NewReader(yamlContent))
+ for {
+ var o interface{}
+ // read individual document
+ err := d.Decode(&o)
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return nil, errors.Wrapf(err, "multi doc yaml could not be split")
+ }
+
+ if o != nil {
+ // back to bytes
+ document, err := yamlv3.Marshal(o)
+ if err != nil {
+ return nil, errors.Wrapf(err, "individual doc yaml could not be marshalled")
+ }
+
+ documentList = append(documentList, document)
+ }
+ }
+
+ return documentList, nil
+}
+
+// getKubeKind unmarshals a kube YAML document and returns its kind.
+func getKubeKind(obj []byte) (string, error) {
+ var kubeObject v1.ObjectReference
+
+ if err := yaml.Unmarshal(obj, &kubeObject); err != nil {
+ return "", err
+ }
+
+ return kubeObject.Kind, nil
+}