diff --git a/go.mod b/go.mod index 84dadaf5..a0833e53 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/hashicorp/vault/api v1.9.0 github.com/joho/godotenv v1.5.1 github.com/kubefirst/metrics-client v0.2.8 - github.com/kubefirst/runtime v0.3.30 + github.com/kubefirst/runtime v0.3.31 github.com/minio/minio-go/v7 v7.0.49 github.com/otiai10/copy v1.7.0 github.com/rs/zerolog v1.29.1 diff --git a/go.sum b/go.sum index 37752cb7..6f32f1af 100644 --- a/go.sum +++ b/go.sum @@ -740,8 +740,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kubefirst/metrics-client v0.2.8 h1:JfaeiBifZD/DpyYW2QVHcrhH/KWA98OmM+7c7M12qMc= github.com/kubefirst/metrics-client v0.2.8/go.mod h1:GR7wsMcyYhd+EU67PeuMCBYFE6OJ7P/j5OI5BLOoRMc= -github.com/kubefirst/runtime v0.3.30 h1:faMT6w//vyt7v4qeBwh74SCNDoIv/+AWTWOnG9XyzOc= -github.com/kubefirst/runtime v0.3.30/go.mod h1:9egAgF5cF594mIzra5nTB1kfE57Hr/Nvl79tjLsAWCQ= +github.com/kubefirst/runtime v0.3.31 h1:8UT6nwrCqCYRc6rQWQsPsUo+EPd6xZULzkYamSIucWE= +github.com/kubefirst/runtime v0.3.31/go.mod h1:9egAgF5cF594mIzra5nTB1kfE57Hr/Nvl79tjLsAWCQ= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= diff --git a/internal/aws/aws.go b/internal/aws/aws.go index 2c904be2..0fd8f351 100644 --- a/internal/aws/aws.go +++ b/internal/aws/aws.go @@ -18,6 +18,7 @@ import ( "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/route53" route53Types "github.com/aws/aws-sdk-go-v2/service/route53/types" + "github.com/kubefirst/kubefirst-api/internal/constants" "github.com/kubefirst/kubefirst-api/internal/env" "github.com/kubefirst/kubefirst-api/internal/utils" log "github.com/sirupsen/logrus" @@ -35,7 +36,7 @@ var Conf AWSConfiguration = AWSConfiguration{ // NewAws instantiates a new AWS configuration func NewAws() aws.Config { - env, _ := env.GetEnv() + env, _ := env.GetEnv(constants.SilenceGetEnv) awsClient, err := config.LoadDefaultConfig( context.Background(), diff --git a/internal/constants/global.go b/internal/constants/global.go index 796a46d7..902f02e7 100644 --- a/internal/constants/global.go +++ b/internal/constants/global.go @@ -19,4 +19,6 @@ const ( ClusterStatusError = "error" ClusterStatusProvisioned = "provisioned" ClusterStatusProvisioning = "provisioning" + + SilenceGetEnv = true ) diff --git a/internal/controller/argocd.go b/internal/controller/argocd.go index b445ded2..9fb8c039 100644 --- a/internal/controller/argocd.go +++ b/internal/controller/argocd.go @@ -47,7 +47,6 @@ func (clctrl *ClusterController) InstallArgoCD() error { case "civo", "digitalocean", "vultr": kcfg = k8s.CreateKubeConfig(false, clctrl.ProviderConfig.Kubeconfig) case "google": - var err error kcfg, err = clctrl.GoogleClient.GetContainerClusterAuth(clctrl.ClusterName, []byte(clctrl.GoogleAuth.KeyFile)) if err != nil { return err diff --git a/internal/controller/cluster.go b/internal/controller/cluster.go index 860c1536..8d64163f 100644 --- a/internal/controller/cluster.go +++ b/internal/controller/cluster.go @@ -18,6 +18,7 @@ import ( googleext "github.com/kubefirst/kubefirst-api/extensions/google" terraformext "github.com/kubefirst/kubefirst-api/extensions/terraform" vultrext "github.com/kubefirst/kubefirst-api/extensions/vultr" + "github.com/kubefirst/kubefirst-api/internal/constants" "github.com/kubefirst/kubefirst-api/internal/env" gitShim "github.com/kubefirst/kubefirst-api/internal/gitShim" "github.com/kubefirst/kubefirst-api/pkg/providerConfigs" @@ -158,7 +159,7 @@ func (clctrl *ClusterController) CreateTokens(kind string) interface{} { return err } - env, _ := env.GetEnv() + env, _ := env.GetEnv(constants.SilenceGetEnv) // Default gitopsTemplateTokens gitopsTemplateTokens := &providerConfigs.GitopsDirectoryValues{ diff --git a/internal/controller/controller.go b/internal/controller/controller.go index e9106b05..3622ff70 100644 --- a/internal/controller/controller.go +++ b/internal/controller/controller.go @@ -144,7 +144,7 @@ func (clctrl *ClusterController) InitController(def *pkgtypes.ClusterDefinition) clusterID = runtime.GenerateClusterID() } - env, _ := env.GetEnv() + env, _ := env.GetEnv(constants.SilenceGetEnv) telemetryEvent := telemetry.TelemetryEvent{ CliVersion: env.KubefirstVersion, @@ -177,6 +177,8 @@ func (clctrl *ClusterController) InitController(def *pkgtypes.ClusterDefinition) clctrl.DnsProvider = def.DnsProvider clctrl.ClusterType = def.Type clctrl.HttpClient = http.DefaultClient + clctrl.NodeType = def.NodeType + clctrl.NodeCount = def.NodeCount clctrl.AWSAuth = def.AWSAuth clctrl.CivoAuth = def.CivoAuth @@ -303,6 +305,8 @@ func (clctrl *ClusterController) InitController(def *pkgtypes.ClusterDefinition) DigitaloceanAuth: clctrl.DigitaloceanAuth, VultrAuth: clctrl.VultrAuth, CloudflareAuth: clctrl.CloudflareAuth, + NodeType: clctrl.NodeType, + NodeCount: clctrl.NodeCount, } err = clctrl.MdbCl.InsertCluster(cl) if err != nil { diff --git a/internal/db/mongo.go b/internal/db/mongo.go index c54822fe..0a32d1d7 100644 --- a/internal/db/mongo.go +++ b/internal/db/mongo.go @@ -11,6 +11,7 @@ import ( "fmt" "os" + "github.com/kubefirst/kubefirst-api/internal/constants" "github.com/kubefirst/kubefirst-api/internal/env" pkgtypes "github.com/kubefirst/kubefirst-api/pkg/types" "github.com/kubefirst/runtime/pkg/k8s" @@ -35,7 +36,7 @@ var Client = Connect() // Connect func Connect() *MongoDBClient { - env, getEnvError := env.GetEnv() + env, getEnvError := env.GetEnv(constants.SilenceGetEnv) if getEnvError != nil { log.Fatal(getEnvError.Error()) @@ -88,7 +89,7 @@ func (mdbcl *MongoDBClient) TestDatabaseConnection(silent bool) error { log.Fatalf("error connecting to mongodb: %s", err) } if !silent { - env, _ := env.GetEnv() + env, _ := env.GetEnv(constants.SilenceGetEnv) log.Infof("connected to mongodb host %s", env.MongoDBHost) } @@ -98,7 +99,7 @@ func (mdbcl *MongoDBClient) TestDatabaseConnection(silent bool) error { // ImportClusterIfEmpty func (mdbcl *MongoDBClient) ImportClusterIfEmpty(silent bool) (pkgtypes.Cluster, error) { - env, _ := env.GetEnv() + env, _ := env.GetEnv(constants.SilenceGetEnv) log.SetFormatter(&log.TextFormatter{ FullTimestamp: true, @@ -175,7 +176,7 @@ type EstablishConnectArgs struct { } func (mdbcl *MongoDBClient) EstablishMongoConnection(args EstablishConnectArgs) error { - env, _ := env.GetEnv() + env, _ := env.GetEnv(constants.SilenceGetEnv) var pingError error diff --git a/internal/env/env.go b/internal/env/env.go index d061941a..f61f0579 100644 --- a/internal/env/env.go +++ b/internal/env/env.go @@ -29,15 +29,15 @@ type Env struct { EnterpriseApiUrl string `env:"ENTERPRISE_API_URL"` } -func GetEnv() (Env, error) { - envError := godotenv.Load(".env") +func GetEnv(silent bool)(Env,error) { + err := godotenv.Load(".env") - if envError != nil { + if err != nil && !silent { log.Info("error loading .env file, using local environment variables") } environment := Env{} - err := env.Parse(&environment) + err = env.Parse(&environment) if err != nil { return Env{}, err } diff --git a/internal/env/env_test.go b/internal/env/env_test.go index 2d014fa8..905d363b 100644 --- a/internal/env/env_test.go +++ b/internal/env/env_test.go @@ -51,7 +51,7 @@ func TestEnv(t *testing.T) { }() env := Env{} - env, err := GetEnv() + env, err := GetEnv(true) if err != nil { t.Errorf("unexpected error: %v", err) } diff --git a/internal/environments/defaultEnvironments.go b/internal/environments/defaultEnvironments.go index 6cbe0e2b..c23514e0 100644 --- a/internal/environments/defaultEnvironments.go +++ b/internal/environments/defaultEnvironments.go @@ -16,6 +16,7 @@ import ( "os" "time" + "github.com/kubefirst/kubefirst-api/internal/constants" "github.com/kubefirst/kubefirst-api/internal/db" "github.com/kubefirst/kubefirst-api/internal/env" "github.com/kubefirst/kubefirst-api/pkg/types" @@ -107,7 +108,7 @@ func callApiEE(goPayload types.WorkloadClusterSet) error { return err } - env, _ := env.GetEnv() + env, _ := env.GetEnv(constants.SilenceGetEnv) req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/api/v1/environments/%s", env.EnterpriseApiUrl, env.ClusterId), bytes.NewReader(payload)) diff --git a/internal/middleware/auth.go b/internal/middleware/auth.go index 0e23b559..082c872b 100644 --- a/internal/middleware/auth.go +++ b/internal/middleware/auth.go @@ -11,6 +11,7 @@ import ( "strings" "github.com/gin-gonic/gin" + "github.com/kubefirst/kubefirst-api/internal/constants" "github.com/kubefirst/kubefirst-api/internal/env" "github.com/rs/zerolog/log" ) @@ -29,7 +30,7 @@ func ValidateAPIKey() gin.HandlerFunc { return } - env, _ := env.GetEnv() + env, _ := env.GetEnv(constants.SilenceGetEnv) if APIKey != env.K1AccessToken { c.JSON(http.StatusUnauthorized, gin.H{"status": 401, "message": "Authentication failed - not a valid API key"}) diff --git a/internal/router/api/v1/cluster.go b/internal/router/api/v1/cluster.go index a9e642f6..ad537b2f 100644 --- a/internal/router/api/v1/cluster.go +++ b/internal/router/api/v1/cluster.go @@ -7,6 +7,7 @@ See the LICENSE file for more details. package api import ( + "context" "fmt" "net/http" @@ -26,7 +27,10 @@ import ( "github.com/kubefirst/kubefirst-api/providers/google" "github.com/kubefirst/kubefirst-api/providers/vultr" "github.com/kubefirst/metrics-client/pkg/telemetry" + civoruntime "github.com/kubefirst/runtime/pkg/civo" + digioceanruntime "github.com/kubefirst/runtime/pkg/digitalocean" "github.com/kubefirst/runtime/pkg/k8s" + vultrruntime "github.com/kubefirst/runtime/pkg/vultr" log "github.com/sirupsen/logrus" ) @@ -60,7 +64,7 @@ func DeleteCluster(c *gin.Context) { return } - env, _ := env.GetEnv() + env, _ := env.GetEnv(constants.SilenceGetEnv) telemetryEvent := telemetry.TelemetryEvent{ CliVersion: env.KubefirstVersion, @@ -283,7 +287,7 @@ func PostCreateCluster(c *gin.Context) { useSecretForAuth := false var k1AuthSecret = map[string]string{} - env, _ := env.GetEnv() + env, _ := env.GetEnv(constants.SilenceGetEnv) if env.InCluster { kcfg := k8s.CreateKubeConfig(env.InCluster, "") @@ -497,8 +501,92 @@ func GetExportCluster(c *gin.Context) { // return json of cluster c.IndentedJSON(http.StatusOK, cluster) - return +} +func GetClusterKubeconfig(c *gin.Context) { + clusterName, param := c.Params.Get("cluster_name") + if !param { + c.JSON(http.StatusBadRequest, types.JSONFailureResponse{ + Message: ":cluster_name not provided", + }) + return + } + + cloudProvider, param := c.Params.Get("cloud_provider") + if !param { + c.JSON(http.StatusBadRequest, types.JSONFailureResponse{ + Message: ":cloud_provider not provided", + }) + return + } + + var instanceSizesRequest types.InstanceSizesRequest + err := c.Bind(&instanceSizesRequest) + if err != nil { + c.JSON(http.StatusBadRequest, types.JSONFailureResponse{ + Message: err.Error(), + }) + return + } + + switch cloudProvider { + case "civo": + civoConfig := civoruntime.CivoConfiguration{ + Client: civoruntime.NewCivo(instanceSizesRequest.CivoAuth.Token, instanceSizesRequest.CloudRegion), + Context: context.Background(), + } + + kubeConfig, cfgError := civoConfig.GetKubeconfig(clusterName) + if err != nil { + c.JSON(http.StatusBadRequest, types.JSONFailureResponse{ + Message: cfgError.Error(), + }) + return + } + + c.IndentedJSON(http.StatusOK, kubeConfig) + + case "digitalocean": + digitaloceanConf := digioceanruntime.DigitaloceanConfiguration{ + Client: digioceanruntime.NewDigitalocean(instanceSizesRequest.DigitaloceanAuth.Token), + Context: context.Background(), + } + + kubeConfig, err := digitaloceanConf.GetKubeconfig(clusterName) + + if err != nil { + c.JSON(http.StatusBadRequest, types.JSONFailureResponse{ + Message: err.Error(), + }) + return + } + + c.IndentedJSON(http.StatusOK, kubeConfig) + + case "vultr": + + vultrConf := vultrruntime.VultrConfiguration{ + Client: vultrruntime.NewVultr(instanceSizesRequest.VultrAuth.Token), + Context: context.Background(), + } + + kubeConfig, err := vultrConf.GetKubeconfig(clusterName) + + if err != nil { + c.JSON(http.StatusBadRequest, types.JSONFailureResponse{ + Message: err.Error(), + }) + return + } + + c.IndentedJSON(http.StatusOK, kubeConfig) + + default: + c.JSON(http.StatusBadRequest, types.JSONFailureResponse{ + Message: fmt.Sprintf("provided cloud provider: %v not implemented", cloudProvider), + }) + return + } } // PostImportCluster godoc diff --git a/internal/router/api/v1/telemetry.go b/internal/router/api/v1/telemetry.go index b9d90678..d297e31d 100644 --- a/internal/router/api/v1/telemetry.go +++ b/internal/router/api/v1/telemetry.go @@ -10,6 +10,7 @@ import ( "net/http" "github.com/gin-gonic/gin" + "github.com/kubefirst/kubefirst-api/internal/constants" "github.com/kubefirst/kubefirst-api/internal/db" "github.com/kubefirst/kubefirst-api/internal/env" "github.com/kubefirst/kubefirst-api/internal/types" @@ -45,7 +46,7 @@ func PostTelemetry(c *gin.Context) { return } - env, _ := env.GetEnv() + env, _ := env.GetEnv(constants.SilenceGetEnv) telEvent := telemetry.TelemetryEvent{ CliVersion: env.KubefirstVersion, diff --git a/internal/router/router.go b/internal/router/router.go index 1c61cb69..962f38ed 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -53,6 +53,7 @@ func SetupRouter() *gin.Engine { v1.POST("/cluster/:cluster_name", middleware.ValidateAPIKey(), router.PostCreateCluster) v1.GET("/cluster/:cluster_name/export", middleware.ValidateAPIKey(), router.GetExportCluster) v1.POST("/cluster/:cluster_name/reset_progress", middleware.ValidateAPIKey(), router.PostResetClusterProgress) + v1.POST("/cluster/:cluster_name/:cloud_provider/kubeconfig", middleware.ValidateAPIKey(), router.GetClusterKubeconfig) // Gitops Catalog v1.GET("/gitops-catalog/apps", middleware.ValidateAPIKey(), router.GetGitopsCatalogApps) diff --git a/internal/services/services.go b/internal/services/services.go index 9302622a..629fafb8 100644 --- a/internal/services/services.go +++ b/internal/services/services.go @@ -95,7 +95,7 @@ func CreateService(cl *pkgtypes.Cluster, serviceName string, appDef *types.Gitop var kcfg *k8s.KubernetesClient - env, _ := env.GetEnv() + env, _ := env.GetEnv(constants.SilenceGetEnv) kcfg = k8s.CreateKubeConfig(env.InCluster, fmt.Sprintf("%s/kubeconfig", tmpGitopsDir)) diff --git a/main.go b/main.go index b5804ebd..8f573035 100644 --- a/main.go +++ b/main.go @@ -32,7 +32,7 @@ import ( func main() { - env, err := env.GetEnv() + env, err := env.GetEnv(false) if err != nil { log.Fatal(err.Error())