From 1b3d6eae8284f548b3fca1074580ea3308fc7b21 Mon Sep 17 00:00:00 2001 From: Jimmy Xu Date: Thu, 21 Dec 2017 22:33:58 +0800 Subject: [PATCH] [hyper-provider] 1. support pull image 2. improve containerJSONToPod() --- providers/hypersh/hypersh.go | 135 ++++++++++++++++++++++++++++++----- 1 file changed, 118 insertions(+), 17 deletions(-) diff --git a/providers/hypersh/hypersh.go b/providers/hypersh/hypersh.go index ae70e0819..dd2521e2b 100755 --- a/providers/hypersh/hypersh.go +++ b/providers/hypersh/hypersh.go @@ -21,6 +21,8 @@ import ( "github.com/hyperhq/hyper-api/types/network" "github.com/hyperhq/hypercli/cliconfig" "github.com/hyperhq/hypercli/opts" + "github.com/hyperhq/hypercli/pkg/jsonmessage" + "github.com/hyperhq/hypercli/pkg/term" "github.com/virtual-kubelet/virtual-kubelet/manager" "github.com/virtual-kubelet/virtual-kubelet/providers" "k8s.io/api/core/v1" @@ -221,6 +223,10 @@ func (p *HyperProvider) CreatePod(pod *v1.Pod) error { //one container in a Pod in hyper.sh currently containerName := fmt.Sprintf("pod-%s-%s", pod.Name, pod.Spec.Containers[k].Name) + if err = p.ensureImage(ctr.Image); err != nil { + return err + } + // Add labels to the pod containers. ctr.Labels = map[string]string{ containerLabel: pod.Name, @@ -475,7 +481,6 @@ func getContainers(pod *v1.Pod) ([]container.Config, []container.HostConfig, err } func containerJSONToPod(container *types.ContainerJSON) (*v1.Pod, error) { - // TODO: convert containers into pods podName, found := container.Config.Labels[containerLabel] if !found { return nil, fmt.Errorf("can not found podName: key %q not found in container label", containerLabel) @@ -490,6 +495,68 @@ func containerJSONToPod(container *types.ContainerJSON) (*v1.Pod, error) { if err != nil { return nil, fmt.Errorf("parse Created time failed:%v", container.Created) } + startedAt, err := time.Parse(time.RFC3339, container.State.StartedAt) + if err != nil { + return nil, fmt.Errorf("parse StartedAt time failed:%v", container.State.StartedAt) + } + finishedAt, err := time.Parse(time.RFC3339, container.State.FinishedAt) + if err != nil { + return nil, fmt.Errorf("parse FinishedAt time failed:%v", container.State.FinishedAt) + } + + var ( + podCondition v1.PodCondition + containerState v1.ContainerState + ) + switch hyperStateToPodPhase(container.State.Status) { + case v1.PodPending: + podCondition = v1.PodCondition{ + Type: v1.PodInitialized, + Status: v1.ConditionFalse, + } + containerState = v1.ContainerState{ + Waiting: &v1.ContainerStateWaiting{}, + } + case v1.PodRunning: // running + podCondition = v1.PodCondition{ + Type: v1.PodReady, + Status: v1.ConditionTrue, + } + containerState = v1.ContainerState{ + Running: &v1.ContainerStateRunning{ + StartedAt: metav1.NewTime(startedAt), + }, + } + case v1.PodSucceeded: // normal exit + podCondition = v1.PodCondition{ + Type: v1.PodReasonUnschedulable, + Status: v1.ConditionFalse, + } + containerState = v1.ContainerState{ + Terminated: &v1.ContainerStateTerminated{ + ExitCode: int32(container.State.ExitCode), + FinishedAt: metav1.NewTime(finishedAt), + }, + } + case v1.PodFailed: // exit with error + podCondition = v1.PodCondition{ + Type: v1.PodReasonUnschedulable, + Status: v1.ConditionFalse, + } + containerState = v1.ContainerState{ + Terminated: &v1.ContainerStateTerminated{ + ExitCode: int32(container.State.ExitCode), + FinishedAt: metav1.NewTime(finishedAt), + Reason: container.State.Error, + }, + } + default: //unkown + podCondition = v1.PodCondition{ + Type: v1.PodReasonUnschedulable, + Status: v1.ConditionUnknown, + } + containerState = v1.ContainerState{} + } p := v1.Pod{ TypeMeta: metav1.TypeMeta{ @@ -514,25 +581,24 @@ func containerJSONToPod(container *types.ContainerJSON) (*v1.Pod, error) { }, Status: v1.PodStatus{ Phase: hyperStateToPodPhase(container.State.Status), - Conditions: []v1.PodCondition{}, + Conditions: []v1.PodCondition{podCondition}, Message: "", Reason: "", HostIP: "", PodIP: container.NetworkSettings.IPAddress, ContainerStatuses: []v1.ContainerStatus{ { - Name: "", - State: v1.ContainerState{}, - Ready: container.State.Running, + Name: podName, RestartCount: int32(container.RestartCount), Image: container.Config.Image, ImageID: container.Image, ContainerID: container.ID, + Ready: container.State.Running, + State: containerState, }, }, }, } - return &p, nil } @@ -548,6 +614,23 @@ func containerToPod(container *types.Container) (*v1.Pod, error) { return nil, fmt.Errorf("can not found nodeName: key %q not found in container label", containerLabel) } + var ( + podCondition v1.PodCondition + isReady bool = true + ) + if strings.ToLower(string(container.State)) == strings.ToLower(string(v1.PodRunning)) { + podCondition = v1.PodCondition{ + Type: v1.PodReady, + Status: v1.ConditionTrue, + } + } else { + podCondition = v1.PodCondition{ + Type: v1.PodReasonUnschedulable, + Status: v1.ConditionFalse, + } + isReady = false + } + p := v1.Pod{ TypeMeta: metav1.TypeMeta{ Kind: "Pod", @@ -574,7 +657,7 @@ func containerToPod(container *types.Container) (*v1.Pod, error) { }, Status: v1.PodStatus{ //Phase: "", - Conditions: []v1.PodCondition{}, + Conditions: []v1.PodCondition{podCondition}, Message: "", Reason: "", HostIP: "", @@ -582,31 +665,31 @@ func containerToPod(container *types.Container) (*v1.Pod, error) { ContainerStatuses: []v1.ContainerStatus{ { Name: container.Names[0], - Ready: string(container.State) == string(v1.PodRunning), Image: container.Image, ImageID: container.ImageID, ContainerID: container.ID, + Ready: isReady, + State: v1.ContainerState{}, }, }, }, } - return &p, nil } func hyperStateToPodPhase(state string) v1.PodPhase { switch strings.ToLower(state) { - case "running": - return v1.PodRunning - case "paused": - return v1.PodSucceeded - case "restarting": - return v1.PodPending case "created": return v1.PodPending - case "dead": - return v1.PodFailed + case "restarting": + return v1.PodPending + case "running": + return v1.PodRunning case "exited": + return v1.PodSucceeded + case "paused": + return v1.PodSucceeded + case "dead": return v1.PodFailed } return v1.PodUnknown @@ -634,3 +717,21 @@ func (p *HyperProvider) getDefaultRegion() string { } return cliconfig.DefaultHyperRegion } + +func (p *HyperProvider) ensureImage(image string) error { + responseBody, err := p.hyperClient.ImagePull(context.Background(), image, types.ImagePullOptions{}) + if err != nil { + return err + } + defer responseBody.Close() + var ( + outFd uintptr + isTerminalOut bool + ) + _, stdout, _ := term.StdStreams() + if stdout != nil { + outFd, isTerminalOut = term.GetFdInfo(stdout) + } + jsonmessage.DisplayJSONMessagesStream(responseBody, stdout, outFd, isTerminalOut, nil) + return nil +}