Merge pull request #21 from ritazh/feat-logs

Enable kubectl logs
This commit is contained in:
Erik St. Martin
2018-01-04 10:56:35 -05:00
committed by GitHub
14 changed files with 207 additions and 24 deletions

View File

@@ -7,8 +7,8 @@ import (
"errors"
"fmt"
"log"
"net/http"
"os"
"strings"
"time"
"github.com/virtual-kubelet/virtual-kubelet/manager"
@@ -31,6 +31,8 @@ type ACIProvider struct {
cpu string
memory string
pods string
internalIP string
daemonEndpointPort int32
}
// AuthConfig is the secret returned from an ImageRegistryCredential
@@ -45,7 +47,7 @@ type AuthConfig struct {
}
// NewACIProvider creates a new ACIProvider.
func NewACIProvider(config string, rm *manager.ResourceManager, nodeName, operatingSystem string) (*ACIProvider, error) {
func NewACIProvider(config string, rm *manager.ResourceManager, nodeName, operatingSystem string, internalIP string, daemonEndpointPort int32) (*ACIProvider, error) {
var p ACIProvider
var err error
@@ -89,6 +91,8 @@ func NewACIProvider(config string, rm *manager.ResourceManager, nodeName, operat
p.operatingSystem = operatingSystem
p.nodeName = nodeName
p.internalIP = internalIP
p.daemonEndpointPort = daemonEndpointPort
return &p, err
}
@@ -177,10 +181,9 @@ func (p *ACIProvider) DeletePod(pod *v1.Pod) error {
// GetPod returns a pod by name that is running inside ACI
// returns nil if a pod by that name is not found.
func (p *ACIProvider) GetPod(namespace, name string) (*v1.Pod, error) {
cg, err := p.aciClient.GetContainerGroup(p.resourceGroup, fmt.Sprintf("%s-%s", namespace, name))
cg, err, status := p.aciClient.GetContainerGroup(p.resourceGroup, fmt.Sprintf("%s-%s", namespace, name))
if err != nil {
// Trap error for 404 and return gracefully
if strings.Contains(err.Error(), "ResourceNotFound") {
if *status == http.StatusNotFound {
return nil, nil
}
return nil, err
@@ -193,6 +196,33 @@ func (p *ACIProvider) GetPod(namespace, name string) (*v1.Pod, error) {
return containerGroupToPod(cg)
}
// GetPodLogs returns the logs of a pod by name that is running inside ACI.
func (p *ACIProvider) GetContainerLogs(namespace, podName, containerName string, tail int) (string, error) {
logContent := ""
cg, err, _ := p.aciClient.GetContainerGroup(p.resourceGroup, fmt.Sprintf("%s-%s", namespace, podName))
if err != nil {
return logContent, err
}
if cg.Tags["NodeName"] != p.nodeName {
return logContent, nil
}
// get logs from cg
retry := 10
for i := 0; i < retry; i++ {
cLogs, err := p.aciClient.GetContainerLogs(p.resourceGroup, cg.Name, containerName, tail)
if err != nil {
log.Println(err)
time.Sleep(5000 * time.Millisecond)
} else {
logContent = cLogs.Content
break
}
}
return logContent, err
}
// GetPodStatus returns the status of a pod by name that is running inside ACI
// returns nil if a pod by that name is not found.
func (p *ACIProvider) GetPodStatus(namespace, name string) (*v1.PodStatus, error) {
@@ -290,6 +320,28 @@ func (p *ACIProvider) NodeConditions() []v1.NodeCondition {
}
}
// NodeAddresses returns a list of addresses for the node status
// within Kuberentes.
func (p *ACIProvider) NodeAddresses() []v1.NodeAddress {
// TODO: Make these dynamic and augment with custom ACI specific conditions of interest
return []v1.NodeAddress{
{
Type: "InternalIP",
Address: p.internalIP,
},
}
}
// NodeDaemonEndpoints returns NodeDaemonEndpoints for the node status
// within Kuberentes.
func (p *ACIProvider) NodeDaemonEndpoints() *v1.NodeDaemonEndpoints {
return &v1.NodeDaemonEndpoints{
KubeletEndpoint: v1.DaemonEndpoint{
Port: p.daemonEndpointPort,
},
}
}
// OperatingSystem returns the operating system that was provided by the config.
func (p *ACIProvider) OperatingSystem() string {
return p.operatingSystem

View File

@@ -163,7 +163,7 @@ func TestCreateContainerGroup(t *testing.T) {
}
func TestGetContainerGroup(t *testing.T) {
cg, err := client.GetContainerGroup(resourceGroup, containerGroup)
cg, err, _ := client.GetContainerGroup(resourceGroup, containerGroup)
if err != nil {
t.Fatal(err)
}

View File

@@ -13,7 +13,7 @@ import (
// GetContainerGroup gets an Azure Container Instance in the provided
// resource group with the given container group name.
// From: https://docs.microsoft.com/en-us/rest/api/container-instances/containergroups/get
func (c *Client) GetContainerGroup(resourceGroup, containerGroupName string) (*ContainerGroup, error) {
func (c *Client) GetContainerGroup(resourceGroup, containerGroupName string) (*ContainerGroup, error, *int) {
urlParams := url.Values{
"api-version": []string{apiVersion},
}
@@ -25,7 +25,7 @@ func (c *Client) GetContainerGroup(resourceGroup, containerGroupName string) (*C
// Create the request.
req, err := http.NewRequest("GET", uri, nil)
if err != nil {
return nil, fmt.Errorf("Creating get container group uri request failed: %v", err)
return nil, fmt.Errorf("Creating get container group uri request failed: %v", err), nil
}
// Add the parameters to the url.
@@ -34,29 +34,29 @@ func (c *Client) GetContainerGroup(resourceGroup, containerGroupName string) (*C
"resourceGroup": resourceGroup,
"containerGroupName": containerGroupName,
}); err != nil {
return nil, fmt.Errorf("Expanding URL with parameters failed: %v", err)
return nil, fmt.Errorf("Expanding URL with parameters failed: %v", err), nil
}
// Send the request.
resp, err := c.hc.Do(req)
if err != nil {
return nil, fmt.Errorf("Sending get container group request failed: %v", err)
return nil, fmt.Errorf("Sending get container group request failed: %v", err), &resp.StatusCode
}
defer resp.Body.Close()
// 200 (OK) is a success response.
if err := api.CheckResponse(resp); err != nil {
return nil, err
return nil, err, &resp.StatusCode
}
// Decode the body from the response.
if resp.Body == nil {
return nil, errors.New("Create container group returned an empty body in the response")
return nil, errors.New("Create container group returned an empty body in the response"), &resp.StatusCode
}
var cg ContainerGroup
if err := json.NewDecoder(resp.Body).Decode(&cg); err != nil {
return nil, fmt.Errorf("Decoding get container group response body failed: %v", err)
return nil, fmt.Errorf("Decoding get container group response body failed: %v", err), &resp.StatusCode
}
return &cg, nil
return &cg, nil, &resp.StatusCode
}

View File

@@ -313,6 +313,11 @@ func (p *HyperProvider) GetPod(namespace, name string) (pod *v1.Pod, err error)
}
}
// GetContainerLogs retrieves the logs of a container by name from the provider.
func (p *HyperProvider) GetContainerLogs(namespace, podName, containerName string, tail int) (string, error) {
return "", nil
}
// GetPodStatus returns the status of a pod by name that is running inside hyper.sh
// returns nil if a pod by that name is not found.
func (p *HyperProvider) GetPodStatus(namespace, name string) (*v1.PodStatus, error) {
@@ -411,6 +416,18 @@ func (p *HyperProvider) NodeConditions() []v1.NodeCondition {
}
// NodeAddresses returns a list of addresses for the node status
// within Kuberentes.
func (p *HyperProvider) NodeAddresses() []v1.NodeAddress {
return nil
}
// NodeDaemonEndpoints returns NodeDaemonEndpoints for the node status
// within Kuberentes.
func (p *HyperProvider) NodeDaemonEndpoints() *v1.NodeDaemonEndpoints {
return nil
}
// OperatingSystem returns the operating system for this provider.
// This is a noop to default to Linux for now.
func (p *HyperProvider) OperatingSystem() string {