summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
authorbaude <bbaude@redhat.com>2018-11-21 16:00:50 -0600
committerbaude <bbaude@redhat.com>2018-12-04 08:03:49 -0600
commitc8436b4912656766df79c37aed3479afe72ca111 (patch)
tree290ddb53830a866a9893e0a80faff9ea766240d1 /libpod
parent5f6ad82524ca7a3281c8464c84b4f9be4ff90aef (diff)
downloadpodman-c8436b4912656766df79c37aed3479afe72ca111.tar.gz
podman-c8436b4912656766df79c37aed3479afe72ca111.tar.bz2
podman-c8436b4912656766df79c37aed3479afe72ca111.zip
generate kube
add the ability to generate kubernetes pod and service yaml representations of libpod containers and pods. Signed-off-by: baude <bbaude@redhat.com>
Diffstat (limited to 'libpod')
-rw-r--r--libpod/kube.go142
1 files changed, 131 insertions, 11 deletions
diff --git a/libpod/kube.go b/libpod/kube.go
index 1a5f80878..05a6537c4 100644
--- a/libpod/kube.go
+++ b/libpod/kube.go
@@ -2,7 +2,10 @@ package libpod
import (
"fmt"
+ "math/rand"
+ "strconv"
"strings"
+ "time"
"github.com/containers/libpod/pkg/lookup"
"github.com/containers/libpod/pkg/util"
@@ -15,23 +18,127 @@ import (
v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
-// InspectForKube takes a slice of libpod containers and generates
+// GenerateForKube takes a slice of libpod containers and generates
// one v1.Pod description that includes just a single container.
-func (c *Container) InspectForKube() (*v1.Pod, error) {
+func (c *Container) GenerateForKube() (*v1.Pod, error) {
// Generate the v1.Pod yaml description
return simplePodWithV1Container(c)
}
-// simplePodWithV1Container is a function used by inspect when kube yaml needs to be generated
-// for a single container. we "insert" that container description in a pod.
-func simplePodWithV1Container(ctr *Container) (*v1.Pod, error) {
- var containers []v1.Container
- result, err := containerToV1Container(ctr)
+// GenerateForKube takes a slice of libpod containers and generates
+// one v1.Pod description
+func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) {
+ // Generate the v1.Pod yaml description
+ var servicePorts []v1.ServicePort
+
+ allContainers, err := p.allContainers()
+ if err != nil {
+ return nil, servicePorts, err
+ }
+ // If the pod has no containers, no sense to generate YAML
+ if len(allContainers) == 0 {
+ return nil, servicePorts, errors.Errorf("pod %s has no containers", p.ID())
+ }
+ // If only an infra container is present, makes no sense to generate YAML
+ if len(allContainers) == 1 && p.HasInfraContainer() {
+ return nil, servicePorts, errors.Errorf("pod %s only has an infra container", p.ID())
+ }
+
+ if p.HasInfraContainer() {
+ infraContainer, err := p.getInfraContainer()
+ if err != nil {
+ return nil, servicePorts, err
+ }
+
+ ports, err := ocicniPortMappingToContainerPort(infraContainer.config.PortMappings)
+ if err != nil {
+ return nil, servicePorts, err
+ }
+ servicePorts = containerPortsToServicePorts(ports)
+ }
+ pod, err := p.podWithContainers(allContainers)
+ return pod, servicePorts, err
+}
+
+func (p *Pod) getInfraContainer() (*Container, error) {
+ infraID, err := p.InfraContainerID()
if err != nil {
return nil, err
}
- containers = append(containers, result)
+ return p.runtime.LookupContainer(infraID)
+}
+
+// GenerateKubeServiceFromV1Pod creates a v1 service object from a v1 pod object
+func GenerateKubeServiceFromV1Pod(pod *v1.Pod, servicePorts []v1.ServicePort) v1.Service {
+ service := v1.Service{}
+ selector := make(map[string]string)
+ selector["app"] = pod.Labels["app"]
+ ports := servicePorts
+ if len(ports) == 0 {
+ ports = containersToServicePorts(pod.Spec.Containers)
+ }
+ serviceSpec := v1.ServiceSpec{
+ Ports: ports,
+ Selector: selector,
+ Type: v1.ServiceTypeNodePort,
+ }
+ service.Spec = serviceSpec
+ service.ObjectMeta = pod.ObjectMeta
+ tm := v12.TypeMeta{
+ Kind: "Service",
+ APIVersion: pod.TypeMeta.APIVersion,
+ }
+ service.TypeMeta = tm
+ return service
+}
+// containerPortsToServicePorts takes a slice of containerports and generates a
+// slice of service ports
+func containerPortsToServicePorts(containerPorts []v1.ContainerPort) []v1.ServicePort {
+ var sps []v1.ServicePort
+ for _, cp := range containerPorts {
+ nodePort := 30000 + rand.Intn(32767-30000+1)
+ servicePort := v1.ServicePort{
+ Protocol: cp.Protocol,
+ Port: cp.ContainerPort,
+ NodePort: int32(nodePort),
+ Name: strconv.Itoa(int(cp.ContainerPort)),
+ }
+ sps = append(sps, servicePort)
+ }
+ return sps
+}
+
+// containersToServicePorts takes a slice of v1.Containers and generates an
+// inclusive list of serviceports to expose
+func containersToServicePorts(containers []v1.Container) []v1.ServicePort {
+ var sps []v1.ServicePort
+ // Without the call to rand.Seed, a program will produce the same sequence of pseudo-random numbers
+ // for each execution. Legal nodeport range is 30000-32767
+ rand.Seed(time.Now().UnixNano())
+
+ for _, ctr := range containers {
+ sps = append(sps, containerPortsToServicePorts(ctr.Ports)...)
+ }
+ return sps
+}
+
+func (p *Pod) podWithContainers(containers []*Container) (*v1.Pod, error) {
+ var podContainers []v1.Container
+ for _, ctr := range containers {
+ result, err := containerToV1Container(ctr)
+ if err != nil {
+ return nil, err
+ }
+ if !ctr.IsInfra() {
+ podContainers = append(podContainers, result)
+ }
+ }
+
+ return addContainersToPodObject(podContainers, p.Name()), nil
+}
+
+func addContainersToPodObject(containers []v1.Container, podName string) *v1.Pod {
tm := v12.TypeMeta{
Kind: "Pod",
APIVersion: "v1",
@@ -39,10 +146,10 @@ func simplePodWithV1Container(ctr *Container) (*v1.Pod, error) {
// Add a label called "app" with the containers name as a value
labels := make(map[string]string)
- labels["app"] = removeUnderscores(ctr.Name())
+ labels["app"] = removeUnderscores(podName)
om := v12.ObjectMeta{
// The name of the pod is container_name-libpod
- Name: fmt.Sprintf("%s-libpod", removeUnderscores(ctr.Name())),
+ Name: fmt.Sprintf("%s-libpod", removeUnderscores(podName)),
Labels: labels,
// CreationTimestamp seems to be required, so adding it; in doing so, the timestamp
// will reflect time this is run (not container create time) because the conversion
@@ -57,7 +164,20 @@ func simplePodWithV1Container(ctr *Container) (*v1.Pod, error) {
ObjectMeta: om,
Spec: ps,
}
- return &p, nil
+ return &p
+}
+
+// simplePodWithV1Container is a function used by inspect when kube yaml needs to be generated
+// for a single container. we "insert" that container description in a pod.
+func simplePodWithV1Container(ctr *Container) (*v1.Pod, error) {
+ var containers []v1.Container
+ result, err := containerToV1Container(ctr)
+ if err != nil {
+ return nil, err
+ }
+ containers = append(containers, result)
+ return addContainersToPodObject(containers, ctr.Name()), nil
+
}
// containerToV1Container converts information we know about a libpod container