11package main
22
33import (
4- "crypto/tls"
5- "crypto/x509"
4+ "context"
65 "errors"
76 "log"
87 "log/slog"
9- "net"
8+ "net/http "
109 "os"
10+ "os/signal"
11+ "syscall"
1112
12- "google.golang.org/grpc"
13- "google.golang.org/grpc/credentials"
13+ "github.com/prometheus/client_golang/prometheus/promhttp"
14+ "k8s.io/client-go/kubernetes"
15+ "k8s.io/client-go/rest"
16+ "k8s.io/client-go/tools/clientcmd"
1417
18+ "github.com/containeroo/terrascaler/internal/autoscaler"
1519 "github.com/containeroo/terrascaler/internal/config"
16- "github.com/containeroo/terrascaler/internal/externalgrpc"
1720 "github.com/containeroo/terrascaler/internal/gitlab"
18- "github.com/containeroo/terrascaler/internal/provider"
1921 "github.com/containeroo/terrascaler/internal/terraform"
2022)
2123
@@ -32,12 +34,31 @@ func main() {
3234 log .Fatalf ("load config: %v" , err )
3335 }
3436
37+ kubeConfig , err := loadKubeConfig (cfg .Kubeconfig )
38+ if err != nil {
39+ log .Fatalf ("load Kubernetes config: %v" , err )
40+ }
41+ kubeClient , err := kubernetes .NewForConfig (kubeConfig )
42+ if err != nil {
43+ log .Fatalf ("create Kubernetes client: %v" , err )
44+ }
45+
3546 gitlabClient , err := gitlab .New (gitlab.Config {
3647 BaseURL : cfg .GitLabBaseURL ,
3748 Token : cfg .GitLabToken ,
3849 Project : cfg .GitLabProject ,
3950 Branch : cfg .GitLabBranch ,
40- File : cfg .FilePath ,
51+ MR : gitlab.MergeRequestConfig {
52+ Enabled : cfg .GitLabMR .Enabled ,
53+ BranchPrefix : cfg .GitLabMR .BranchPrefix ,
54+ Title : cfg .GitLabMR .Title ,
55+ Description : cfg .GitLabMR .Description ,
56+ Labels : cfg .GitLabMR .Labels ,
57+ AssigneeIDs : cfg .GitLabMR .AssigneeIDs ,
58+ ReviewerIDs : cfg .GitLabMR .ReviewerIDs ,
59+ RemoveSourceBranch : cfg .GitLabMR .RemoveSourceBranch ,
60+ },
61+ File : cfg .FilePath ,
4162 Target : terraform.Target {
4263 BlockType : cfg .BlockType ,
4364 Labels : cfg .Labels ,
@@ -48,68 +69,89 @@ func main() {
4869 log .Fatalf ("create GitLab client: %v" , err )
4970 }
5071
51- listener , err := net .Listen ("tcp" , cfg .ListenAddress )
52- if err != nil {
53- log .Fatalf ("listen on %s: %v" , cfg .ListenAddress , err )
54- }
55-
56- serverOptions , err := grpcServerOptions (cfg )
72+ runner , err := autoscaler .NewRunner (cfg , kubeClient , gitlabClient , logger .With ("component" , "autoscaler" ))
5773 if err != nil {
58- log .Fatalf ("configure gRPC server : %v" , err )
74+ log .Fatalf ("create autoscaler : %v" , err )
5975 }
76+ runner .SetMetrics (autoscaler .NewMetrics (nil ))
6077
61- grpcServer := grpc .NewServer (serverOptions ... )
62- providerServer := provider .New (cfg , gitlabClient , logger .With ("component" , "provider" ))
63- externalgrpc .RegisterCloudProviderServer (grpcServer , providerServer )
78+ ctx , stop := signal .NotifyContext (context .Background (), syscall .SIGINT , syscall .SIGTERM )
79+ defer stop ()
6480
6581 logger .Info ("starting terrascaler" ,
6682 "version" , Version ,
67- "listen_address" , cfg .ListenAddress ,
68- "node_group" , cfg .NodeGroupID ,
83+ "check_interval" , cfg .CheckInterval .String (),
84+ "scale_up_cooldown" , cfg .ScaleUpCooldown .String (),
85+ "pending_pod_min_age" , cfg .PendingPodMinAge .String (),
86+ "metrics_address" , cfg .MetricsAddress ,
6987 "min_size" , cfg .MinSize ,
7088 "max_size" , cfg .MaxSize ,
89+ "dry_run" , cfg .DryRun ,
90+ "once" , cfg .Once ,
7191 "gitlab_base_url" , cfg .GitLabBaseURL ,
7292 "gitlab_project" , cfg .GitLabProject ,
7393 "gitlab_branch" , cfg .GitLabBranch ,
94+ "gitlab_merge_request" , cfg .GitLabMR .Enabled ,
95+ "gitlab_mr_branch_prefix" , cfg .GitLabMR .BranchPrefix ,
7496 "terraform_file" , cfg .FilePath ,
7597 "terraform_block_type" , cfg .BlockType ,
7698 "terraform_block_labels" , cfg .Labels ,
7799 "terraform_attribute" , cfg .Attribute ,
78- "tls_enabled" , cfg .TLSCertFile != "" ,
79- "mtls_enabled" , cfg .TLSClientCA != "" ,
100+ "node_selector" , cfg .NodeSelector ,
101+ "template_cpu" , cfg .TemplateCPU ,
102+ "template_memory" , cfg .TemplateMemory ,
103+ "template_pods" , cfg .TemplatePods ,
80104 )
81- if err := grpcServer .Serve (listener ); err != nil {
82- log .Fatalf ("serve gRPC: %v" , err )
105+
106+ metricsServer := startMetricsServer (cfg .MetricsAddress , logger )
107+ if metricsServer != nil {
108+ defer func () {
109+ if err := metricsServer .Shutdown (context .Background ()); err != nil {
110+ logger .Error ("shutdown metrics server" , "error" , err )
111+ }
112+ }()
113+ }
114+
115+ if err := runner .Run (ctx ); err != nil && ! errors .Is (err , context .Canceled ) {
116+ log .Fatalf ("run autoscaler: %v" , err )
83117 }
84118}
85119
86- func grpcServerOptions (cfg config.Config ) ([]grpc.ServerOption , error ) {
87- if cfg .TLSCertFile == "" {
88- return nil , nil
120+ func startMetricsServer (address string , logger * slog.Logger ) * http.Server {
121+ if address == "" {
122+ logger .Info ("metrics server disabled" )
123+ return nil
89124 }
90125
91- cert , err := tls .LoadX509KeyPair (cfg .TLSCertFile , cfg .TLSKeyFile )
92- if err != nil {
93- return nil , err
126+ mux := http .NewServeMux ()
127+ mux .Handle ("/metrics" , promhttp .Handler ())
128+ server := & http.Server {
129+ Addr : address ,
130+ Handler : mux ,
94131 }
132+ go func () {
133+ logger .Info ("starting metrics server" , "address" , address )
134+ if err := server .ListenAndServe (); err != nil && ! errors .Is (err , http .ErrServerClosed ) {
135+ logger .Error ("metrics server failed" , "error" , err )
136+ }
137+ }()
138+ return server
139+ }
95140
96- tlsConfig := & tls .Config {
97- MinVersion : tls . VersionTLS12 ,
98- Certificates : []tls. Certificate { cert },
141+ func loadKubeConfig ( path string ) ( * rest .Config , error ) {
142+ if path != "" {
143+ return clientcmd . BuildConfigFromFlags ( "" , path )
99144 }
100145
101- if cfg .TLSClientCA != "" {
102- caPEM , err := os .ReadFile (cfg .TLSClientCA )
103- if err != nil {
104- return nil , err
105- }
106- pool := x509 .NewCertPool ()
107- if ! pool .AppendCertsFromPEM (caPEM ) {
108- return nil , errors .New ("failed to parse client CA" )
109- }
110- tlsConfig .ClientAuth = tls .RequireAndVerifyClientCert
111- tlsConfig .ClientCAs = pool
146+ config , err := rest .InClusterConfig ()
147+ if err == nil {
148+ return config , nil
112149 }
113150
114- return []grpc.ServerOption {grpc .Creds (credentials .NewTLS (tlsConfig ))}, nil
151+ loadingRules := clientcmd .NewDefaultClientConfigLoadingRules ()
152+ clientConfig := clientcmd .NewNonInteractiveDeferredLoadingClientConfig (
153+ loadingRules ,
154+ & clientcmd.ConfigOverrides {},
155+ )
156+ return clientConfig .ClientConfig ()
115157}
0 commit comments