// Copyright 2020 The Monogon Project Authors.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// This package launches a Metropolis cluster with two nodes and spawns in the
// CTS container. Then it streams its output to the console. When the CTS has
// finished it exits with the appropriate error code.
package main

import (
	"context"
	"io"
	"log"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	corev1 "k8s.io/api/core/v1"
	rbacv1 "k8s.io/api/rbac/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	common "source.monogon.dev/metropolis/node"
	"source.monogon.dev/metropolis/test/e2e"
	"source.monogon.dev/metropolis/test/launch/cluster"
)

// makeCTSPodSpec generates a spec for a standalone pod running the Kubernetes
// CTS. It also sets the test configuration for the Kubernetes E2E test suite
// to only run CTS tests and excludes known-broken ones.
func makeCTSPodSpec(name string, saName string) *corev1.Pod {
	skipRegexes := []string{
		// hostNetworking cannot be supported since we run different network
		// stacks for the host and containers
		"should function for node-pod communication",
		// gVisor misreports statfs() syscalls:
		//   https://github.com/google/gvisor/issues/3339
		`should support \((non-)?root,`,
		"volume on tmpfs should have the correct mode",
		"volume on default medium should have the correct mode",
		// gVisor doesn't support the full Linux privilege machinery including
		// SUID and NewPrivs:
		//   https://github.com/google/gvisor/issues/189#issuecomment-481064000
		"should run the container as unprivileged when false",
	}
	return &corev1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name: name,
			Labels: map[string]string{
				"name": name,
			},
		},
		Spec: corev1.PodSpec{
			Containers: []corev1.Container{
				{
					Name:  "cts",
					Image: "bazel/metropolis/test/e2e/k8s_cts:k8s_cts_image",
					Args: []string{
						"-cluster-ip-range=10.0.0.0/17",
						"-dump-systemd-journal=false",
						"-ginkgo.focus=\\[Conformance\\]",
						"-ginkgo.skip=" + strings.Join(skipRegexes, "|"),
						"-test.parallel=8",
					},
					ImagePullPolicy: corev1.PullNever,
				},
			},
			// Tolerate all taints, otherwise the CTS likes to self-evict.
			Tolerations: []corev1.Toleration{{
				Operator: "Exists",
			}},
			// Don't evict the CTS pod.
			PriorityClassName:  "system-cluster-critical",
			RestartPolicy:      corev1.RestartPolicyNever,
			ServiceAccountName: saName,
		},
	}
}

func main() {
	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
	ctx, cancel := context.WithCancel(context.Background())
	go func() {
		sig := <-sigs
		log.Printf("Got signal %s, aborting test", sig)
		cancel()
	}()

	// TODO(q3k): bump up number of nodes after multi-node workflow gets reimplemented.
	cl, err := cluster.LaunchCluster(ctx, cluster.ClusterOptions{NumNodes: 1})
	if err != nil {
		log.Fatalf("Failed to launch cluster: %v", err)
	}
	log.Println("Cluster initialized")
	// TODO(q3k): use SOCKS proxy instead.
	clientSet, err := e2e.GetKubeClientSet(cl, cl.Ports[uint16(common.KubernetesAPIWrappedPort)])
	if err != nil {
		log.Fatalf("Failed to get clientSet: %v", err)
	}
	log.Println("Credentials available")

	saName := "cts"
	ctsSA := &corev1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Name: saName}}
	for {
		if _, err := clientSet.CoreV1().ServiceAccounts("default").Create(ctx, ctsSA, metav1.CreateOptions{}); err != nil {
			log.Printf("Failed to create ServiceAccount: %v", err)
			time.Sleep(1 * time.Second)
			continue
		}
		break
	}
	ctsRoleBinding := &rbacv1.ClusterRoleBinding{
		ObjectMeta: metav1.ObjectMeta{
			Name: saName,
		},
		Subjects: []rbacv1.Subject{
			{
				Namespace: "default",
				Name:      saName,
				Kind:      rbacv1.ServiceAccountKind,
			},
		},
		RoleRef: rbacv1.RoleRef{
			Kind: "ClusterRole",
			Name: "cluster-admin",
		},
	}
	podName := "cts"
	if _, err := clientSet.RbacV1().ClusterRoleBindings().Create(ctx, ctsRoleBinding, metav1.CreateOptions{}); err != nil {
		log.Fatalf("Failed to create ClusterRoleBinding: %v", err)
	}
	for {
		if _, err := clientSet.CoreV1().Pods("default").Create(ctx, makeCTSPodSpec(podName, saName), metav1.CreateOptions{}); err != nil {
			log.Printf("Failed to create Pod: %v", err)
			time.Sleep(1 * time.Second)
			continue
		}
		break
	}
	var logs io.ReadCloser
	go func() {
		// This loops the whole .Stream()/io.Copy process because the API
		// sometimes returns streams that immediately return EOF
		for {
			logs, err = clientSet.CoreV1().Pods("default").GetLogs(podName, &corev1.PodLogOptions{Follow: true}).Stream(ctx)
			if err == nil {
				if _, err := io.Copy(os.Stdout, logs); err != nil {
					log.Printf("Log pump error: %v", err)
				}
				logs.Close()
			} else if err == ctx.Err() {
				return // Exit if the context has been cancelled
			} else {
				log.Printf("Pod logs not ready yet: %v", err)
			}
			time.Sleep(1 * time.Second)
		}
	}()
	for {
		time.Sleep(1 * time.Second)
		pod, err := clientSet.CoreV1().Pods("default").Get(ctx, podName, metav1.GetOptions{})
		if err != nil && err == ctx.Err() {
			return // Exit if the context has been cancelled
		} else if err != nil {
			log.Printf("Failed to get CTS pod: %v", err)
			continue
		}
		if pod.Status.Phase == corev1.PodSucceeded {
			return
		}
		if pod.Status.Phase == corev1.PodFailed {
			log.Fatalf("CTS failed")
		}
	}
}
