Merge pull request #825 from sargun/add-pods-api

Add /pods HTTP endpoint
This commit is contained in:
Brian Goff
2020-03-20 14:28:02 -07:00
committed by GitHub
5 changed files with 82 additions and 15 deletions

View File

@@ -58,7 +58,7 @@ func loadTLSConfig(certPath, keyPath string) (*tls.Config, error) {
}, nil
}
func setupHTTPServer(ctx context.Context, p provider.Provider, cfg *apiServerConfig) (_ func(), retErr error) {
func setupHTTPServer(ctx context.Context, p provider.Provider, cfg *apiServerConfig, getPodsFromKubernetes api.PodListerFunc) (_ func(), retErr error) {
var closers []io.Closer
cancel := func() {
for _, c := range closers {
@@ -91,6 +91,7 @@ func setupHTTPServer(ctx context.Context, p provider.Provider, cfg *apiServerCon
podRoutes := api.PodHandlerConfig{
RunInContainer: p.RunInContainer,
GetContainerLogs: p.GetContainerLogs,
GetPodsFromKubernetes: getPodsFromKubernetes,
GetPods: p.GetPods,
StreamIdleTimeout: cfg.StreamIdleTimeout,
StreamCreationTimeout: cfg.StreamCreationTimeout,

View File

@@ -193,7 +193,9 @@ func runRootCommand(ctx context.Context, s *provider.Store, c Opts) error {
go podInformerFactory.Start(ctx.Done())
go scmInformerFactory.Start(ctx.Done())
cancelHTTP, err := setupHTTPServer(ctx, p, apiConfig)
cancelHTTP, err := setupHTTPServer(ctx, p, apiConfig, func(context.Context) ([]*corev1.Pod, error) {
return rm.GetPods(), nil
})
if err != nil {
return err
}

View File

@@ -164,8 +164,8 @@ func (f *Framework) WaitUntilPodEventWithReason(pod *corev1.Pod, reason string)
return nil
}
// GetRunningPods gets the running pods from the provider of the virtual kubelet
func (f *Framework) GetRunningPods() (*corev1.PodList, error) {
// GetRunningPodsFromProvider gets the running pods from the provider of the virtual kubelet
func (f *Framework) GetRunningPodsFromProvider() (*corev1.PodList, error) {
result := &corev1.PodList{}
err := f.KubeClient.CoreV1().
@@ -181,6 +181,23 @@ func (f *Framework) GetRunningPods() (*corev1.PodList, error) {
return result, err
}
// GetRunningPodsFromProvider gets the running pods from the provider of the virtual kubelet
func (f *Framework) GetRunningPodsFromKubernetes() (*corev1.PodList, error) {
result := &corev1.PodList{}
err := f.KubeClient.CoreV1().
RESTClient().
Get().
Resource("nodes").
Name(f.NodeName).
SubResource("proxy").
Suffix("pods").
Do().
Into(result)
return result, err
}
// stripParentTestName strips out the parent's test name from the input (in the form of 'TestParent/TestChild').
// Some test cases use their name as the pod name for testing purpose, and sometimes it might exceed 63
// characters (Kubernetes's limit for pod name). This function ensures that we strip out the parent's

View File

@@ -34,9 +34,12 @@ type ServeMux interface {
}
type PodHandlerConfig struct {
RunInContainer ContainerExecHandlerFunc
GetContainerLogs ContainerLogsHandlerFunc
GetPods PodListerFunc
RunInContainer ContainerExecHandlerFunc
GetContainerLogs ContainerLogsHandlerFunc
// GetPods is meant to enumerate the pods that the provider knows about
GetPods PodListerFunc
// GetPodsFromKubernetes is meant to enumerate the pods that the node is meant to be running
GetPodsFromKubernetes PodListerFunc
StreamIdleTimeout time.Duration
StreamCreationTimeout time.Duration
}
@@ -51,6 +54,7 @@ func PodHandler(p PodHandlerConfig, debug bool) http.Handler {
r.HandleFunc("/runningpods/", HandleRunningPods(p.GetPods)).Methods("GET")
}
r.HandleFunc("/pods", HandleRunningPods(p.GetPodsFromKubernetes)).Methods("GET")
r.HandleFunc("/containerLogs/{namespace}/{pod}/{container}", HandleContainerLogs(p.GetContainerLogs)).Methods("GET")
r.HandleFunc(
"/exec/{namespace}/{pod}/{container}",

View File

@@ -18,6 +18,49 @@ const (
deleteGracePeriodForProvider = 1 * time.Second
)
// TestGetPods tests that the /pods endpoint works, and only returns pods for our kubelet
func (ts *EndToEndTestSuite) TestGetPods(t *testing.T) {
// Create a pod with prefix "nginx-" having a single container.
podSpec := f.CreateDummyPodObjectWithPrefix(t.Name(), "nginx", "foo")
podSpec.Spec.NodeName = f.NodeName
nginx, err := f.CreatePod(podSpec)
if err != nil {
t.Fatal(err)
}
// Delete the pod after the test finishes.
defer func() {
if err := f.DeletePodImmediately(nginx.Namespace, nginx.Name); err != nil && !apierrors.IsNotFound(err) {
t.Error(err)
}
}()
t.Logf("Created pod: %s", nginx.Name)
// Wait for the "nginx-" pod to be reported as running and ready.
if _, err := f.WaitUntilPodReady(nginx.Namespace, nginx.Name); err != nil {
t.Fatal(err)
}
t.Logf("Pod %s ready", nginx.Name)
k8sPods, err := f.GetRunningPodsFromKubernetes()
if err != nil {
t.Fatal(err)
}
podFound := false
for _, pod := range k8sPods.Items {
if pod.Spec.NodeName != f.NodeName {
t.Fatalf("Found pod with node name %s, whereas expected %s", pod.Spec.NodeName, f.NodeName)
}
if pod.UID == nginx.UID {
podFound = true
}
}
if !podFound {
t.Fatal("Nginx pod not found")
}
}
// TestGetStatsSummary creates a pod having two containers and queries the /stats/summary endpoint of the virtual-kubelet.
// It expects this endpoint to return stats for the current node, as well as for the aforementioned pod and each of its two containers.
func (ts *EndToEndTestSuite) TestGetStatsSummary(t *testing.T) {
@@ -91,7 +134,7 @@ func (ts *EndToEndTestSuite) TestPodLifecycleGracefulDelete(t *testing.T) {
t.Logf("Pod %s ready", pod.Name)
// Grab the pods from the provider.
pods, err := f.GetRunningPods()
pods, err := f.GetRunningPodsFromProvider()
assert.NilError(t, err)
// Check if the pod exists in the slice of PodStats.
@@ -125,7 +168,7 @@ func (ts *EndToEndTestSuite) TestPodLifecycleGracefulDelete(t *testing.T) {
time.Sleep(deleteGracePeriodForProvider)
// Give the provider some time to react to the MODIFIED/DELETED events before proceeding.
// Grab the pods from the provider.
pods, err = f.GetRunningPods()
pods, err = f.GetRunningPodsFromProvider()
assert.NilError(t, err)
// Make sure the pod DOES NOT exist in the provider's set of running pods
@@ -162,7 +205,7 @@ func (ts *EndToEndTestSuite) TestPodLifecycleForceDelete(t *testing.T) {
t.Logf("Pod %s ready", pod.Name)
// Grab the pods from the provider.
pods, err := f.GetRunningPods()
pods, err := f.GetRunningPodsFromProvider()
assert.NilError(t, err)
// Check if the pod exists in the slice of Pods.
@@ -203,7 +246,7 @@ func (ts *EndToEndTestSuite) TestPodLifecycleForceDelete(t *testing.T) {
time.Sleep(deleteGracePeriodForProvider)
// Grab the pods from the provider.
pods, err = f.GetRunningPods()
pods, err = f.GetRunningPodsFromProvider()
assert.NilError(t, err)
// Make sure the "nginx-" pod DOES NOT exist in the slice of Pods anymore.
@@ -240,7 +283,7 @@ func (ts *EndToEndTestSuite) TestCreatePodWithOptionalInexistentSecrets(t *testi
}
// Grab the pods from the provider.
pods, err := f.GetRunningPods()
pods, err := f.GetRunningPodsFromProvider()
assert.NilError(t, err)
// Check if the pod exists in the slice of Pods.
@@ -269,7 +312,7 @@ func (ts *EndToEndTestSuite) TestCreatePodWithMandatoryInexistentSecrets(t *test
}
// Grab the pods from the provider.
pods, err := f.GetRunningPods()
pods, err := f.GetRunningPodsFromProvider()
assert.NilError(t, err)
// Check if the pod exists in the slice of PodStats.
@@ -303,7 +346,7 @@ func (ts *EndToEndTestSuite) TestCreatePodWithOptionalInexistentConfigMap(t *tes
}
// Grab the pods from the provider.
pods, err := f.GetRunningPods()
pods, err := f.GetRunningPodsFromProvider()
assert.NilError(t, err)
// Check if the pod exists in the slice of PodStats.
@@ -332,7 +375,7 @@ func (ts *EndToEndTestSuite) TestCreatePodWithMandatoryInexistentConfigMap(t *te
}
// Grab the pods from the provider.
pods, err := f.GetRunningPods()
pods, err := f.GetRunningPodsFromProvider()
assert.NilError(t, err)
// Check if the pod exists in the slice of PodStats.