Tarun Pothulapati 05f06ee744 Make the job work inside a cluster
Signed-off-by: Tarun Pothulapati <tarun@gitpod.io>
2023-01-23 18:01:31 +01:00

122 lines
3.7 KiB
Go

// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License-AGPL.txt in the project root for license information.
package cmd
import (
"context"
"fmt"
"os"
"time"
"github.com/gitpod-io/gitpod/common-go/baseserver"
"github.com/gitpod-io/gitpod/common-go/log"
"github.com/gitpod-io/gitpod/workspace-rollout-job/pkg/analysis"
"github.com/gitpod-io/gitpod/workspace-rollout-job/pkg/rollout"
"github.com/gitpod-io/gitpod/workspace-rollout-job/pkg/wsbridge"
"github.com/spf13/cobra"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)
var rootCmd = &cobra.Command{
Use: "workspace-rollout-job",
Short: "Rollout from old to a new cluster while monitoring metrics",
Run: func(cmd *cobra.Command, args []string) {
log.Info("Starting workspace-rollout-job")
ctx := context.Background()
var err error
old, presence := os.LookupEnv("OLD_CLUSTER")
if !presence {
log.Fatal("cannot get old cluster name. Please set using OLD_CLUSTER environment variable.")
}
new, presence := os.LookupEnv("NEW_CLUSTER")
if !presence {
log.Fatal("cannot get new cluster name. Please set using NEW_CLUSTER environment variable.")
}
// Get kubeconfig
config, err := getKubeConfig()
if err != nil {
log.WithError(err).Fatal("failed to retrieve kube config")
}
version := "v0.1.0"
serverOpts := []baseserver.Option{
baseserver.WithVersion(version),
}
srv, err := baseserver.New("workspace-rollout-job", serverOpts...)
if err != nil {
log.WithError(err).Fatal("failed to initialize server")
return
}
// Run in a separate routine as this is not the main purpose
go srv.ListenAndServe()
if err != nil {
log.WithError(err).Fatal("failed to listen and serve")
return
}
rollout.RegisterMetrics(srv.MetricsRegistry())
// 30304 is the port where ws-manager-bridge will be accessible
wsManagerBridgeClient, err := wsbridge.NewWsManagerBridgeClient(context.Background(), config, 30304)
if err != nil {
log.WithError(err).Fatal("failed to create a ws-manager-bridge client")
return
}
// Check if the old cluster has a 100 score.
if score, err := wsManagerBridgeClient.GetScore(ctx, old); err != nil || score != 100 {
log.WithError(err).Fatal("init condition does not satisfy")
}
// Check if the new cluster has a 0 zero score.
// TODO: Check if the new cluster has no constraints.
if score, err := wsManagerBridgeClient.GetScore(ctx, new); err != nil || score != 0 {
log.WithError(err).Fatal("init condition does not satisfy")
}
prometheusResource, presence := os.LookupEnv("PROMETHEUS_RESOURCE")
if !presence {
log.Fatal("cannot get prometheus resource. Please set using PROMETHEUS_RESOURCE environment variable in the format <namespace>/<kind>/<name>.")
}
// Start the rollout process
prometheusAnalyzer, err := analysis.NewPrometheusAnalyzer(ctx, config, prometheusResource, 30305)
if err != nil {
log.WithError(err).Fatal("failed to create a prometheus client")
return
}
job := rollout.New(old, new, 20*time.Second, 1*time.Second, 10, prometheusAnalyzer, wsManagerBridgeClient)
job.Start(ctx)
},
}
func getKubeConfig() (*rest.Config, error) {
var config *rest.Config
config, err := rest.InClusterConfig()
if err != nil {
kubeConfig := clientcmd.NewDefaultClientConfigLoadingRules().GetDefaultFilename()
config, err = clientcmd.BuildConfigFromFlags("", kubeConfig)
if err != nil {
return nil, err
}
}
return config, nil
}
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}