github.com/kyma-project/kyma-environment-broker@v0.0.1/common/setup/builder.go (about)

     1  package setup
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"time"
     7  
     8  	"github.com/dlmiddlecote/sqlstats"
     9  	"github.com/gocraft/dbr"
    10  	"github.com/kyma-project/control-plane/components/schema-migrator/cleaner"
    11  	"github.com/kyma-project/kyma-environment-broker/common/gardener"
    12  	"github.com/kyma-project/kyma-environment-broker/internal/broker"
    13  	"github.com/kyma-project/kyma-environment-broker/internal/environmentscleanup"
    14  	"github.com/kyma-project/kyma-environment-broker/internal/events"
    15  	"github.com/kyma-project/kyma-environment-broker/internal/provisioner"
    16  	"github.com/kyma-project/kyma-environment-broker/internal/storage"
    17  	"github.com/prometheus/client_golang/prometheus"
    18  	"github.com/sirupsen/logrus"
    19  	log "github.com/sirupsen/logrus"
    20  	"github.com/vrischmann/envconfig"
    21  	"golang.org/x/oauth2/clientcredentials"
    22  	"k8s.io/client-go/dynamic"
    23  )
    24  
    25  type config struct {
    26  	MaxAgeHours   time.Duration `envconfig:"default=24h"`
    27  	LabelSelector string        `envconfig:"default=owner.do-not-delete!=true"`
    28  	Gardener      gardener.Config
    29  	Database      storage.Config
    30  	Broker        broker.ClientConfig
    31  	Provisioner   provisionerConfig
    32  }
    33  
    34  type provisionerConfig struct {
    35  	URL          string `envconfig:"default=kcp-provisioner:3000"`
    36  	QueryDumping bool   `envconfig:"default=false"`
    37  }
    38  
    39  type AppBuilder struct {
    40  	cfg            config
    41  	gardenerClient dynamic.ResourceInterface
    42  	db             storage.BrokerStorage
    43  	conn           *dbr.Connection
    44  	logger         *logrus.Logger
    45  
    46  	brokerClient      *broker.Client
    47  	provisionerClient provisioner.Client
    48  }
    49  
    50  type App interface {
    51  	Run() error
    52  }
    53  
    54  func NewAppBuilder() AppBuilder {
    55  	return AppBuilder{}
    56  }
    57  
    58  func (b *AppBuilder) WithConfig() {
    59  	b.cfg = config{}
    60  	err := envconfig.InitWithPrefix(&b.cfg, "APP")
    61  	if err != nil {
    62  		FatalOnError(fmt.Errorf("while loading cleanup config: %w", err))
    63  	}
    64  }
    65  
    66  func (b *AppBuilder) WithGardenerClient() {
    67  	clusterCfg, err := gardener.NewGardenerClusterConfig(b.cfg.Gardener.KubeconfigPath)
    68  	if err != nil {
    69  		FatalOnError(fmt.Errorf("while creating Gardener cluster config: %w", err))
    70  	}
    71  	cli, err := dynamic.NewForConfig(clusterCfg)
    72  	if err != nil {
    73  		FatalOnError(fmt.Errorf("while creating Gardener client: %w", err))
    74  	}
    75  	gardenerNamespace := fmt.Sprintf("garden-%s", b.cfg.Gardener.Project)
    76  	b.gardenerClient = cli.Resource(gardener.ShootResource).Namespace(gardenerNamespace)
    77  }
    78  
    79  func (b *AppBuilder) WithBrokerClient() {
    80  	ctx := context.Background()
    81  	b.brokerClient = broker.NewClient(ctx, b.cfg.Broker)
    82  
    83  	clientCfg := clientcredentials.Config{
    84  		ClientID:     b.cfg.Broker.ClientID,
    85  		ClientSecret: b.cfg.Broker.ClientSecret,
    86  		TokenURL:     b.cfg.Broker.TokenURL,
    87  		Scopes:       []string{b.cfg.Broker.Scope},
    88  	}
    89  	httpClientOAuth := clientCfg.Client(ctx)
    90  	httpClientOAuth.Timeout = 30 * time.Second
    91  }
    92  
    93  func (b *AppBuilder) WithProvisionerClient() {
    94  	b.provisionerClient = provisioner.NewProvisionerClient(b.cfg.Provisioner.URL, b.cfg.Provisioner.QueryDumping)
    95  }
    96  
    97  func (b *AppBuilder) WithStorage() {
    98  	// Init Storage
    99  	cipher := storage.NewEncrypter(b.cfg.Database.SecretKey)
   100  	var err error
   101  	b.db, b.conn, err = storage.NewFromConfig(b.cfg.Database, events.Config{}, cipher, log.WithField("service", "storage"))
   102  	if err != nil {
   103  		FatalOnError(err)
   104  	}
   105  	dbStatsCollector := sqlstats.NewStatsCollector("broker", b.conn)
   106  	prometheus.MustRegister(dbStatsCollector)
   107  
   108  }
   109  
   110  func (b *AppBuilder) WithLogger() {
   111  	b.logger = log.New()
   112  }
   113  
   114  func (b *AppBuilder) Cleanup() {
   115  	err := b.conn.Close()
   116  	if err != nil {
   117  		FatalOnError(err)
   118  	}
   119  
   120  	cleaner.HaltIstioSidecar()
   121  	// do not use defer, close must be done before halting
   122  	err = cleaner.Halt()
   123  	if err != nil {
   124  		FatalOnError(err)
   125  	}
   126  }
   127  
   128  func (b *AppBuilder) Create() App {
   129  	return environmentscleanup.NewService(
   130  		b.gardenerClient,
   131  		b.brokerClient,
   132  		b.provisionerClient,
   133  		b.db.Instances(),
   134  		b.logger,
   135  		b.cfg.MaxAgeHours,
   136  		b.cfg.LabelSelector,
   137  	)
   138  }