--- /dev/null
+// Copyright 2019 Nokia
+//
+// 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.
+
+package main
+
+import (
+ "crypto/tls"
+ "log"
+ "net/http"
+ "pkg/api"
+ "pkg/config"
+ "pkg/repo"
+ "github.com/kelseyhightower/envconfig"
+ "github.com/ncw/swift"
+ "os"
+ "os/signal"
+ "syscall"
+ "strconv"
+ "time"
+ "errors"
+ "crypto/x509"
+ "io/ioutil"
+)
+
+var (
+ chartRepo *http.Server
+)
+
+const (
+ regenRetryCounter = 10
+)
+
+func main() {
+ var envConfig config.EnvConfig
+ err := envconfig.Process("chartrepohandler", &envConfig)
+ if err != nil {
+ log.Fatal(err.Error())
+ }
+
+ swiftCon := connectSwift(envConfig)
+ log.Println("Chart repo handler v0.9 started up.")
+ log.Printf("Config: %s\n", envConfig.ToString())
+ log.Println("Regenerating index for:", envConfig.IndexPath)
+ if err := regenerateIndexYaml(envConfig, &swiftCon); err != nil {
+ log.Println(err.Error())
+ os.Exit(-1)
+ }
+ startHttpServer(envConfig, &swiftCon)
+ signalChan := make(chan os.Signal, 1)
+ signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
+ for {
+ select {
+ case <-signalChan:
+ log.Println("Shutdown signal received, exiting...")
+ if (chartRepo != nil) {
+ chartRepo.Close()
+ }
+ os.Exit(0)
+ }
+ }
+}
+
+func connectSwift(envConfig config.EnvConfig) swift.Connection {
+ swiftCon := swift.Connection{
+ UserName: envConfig.AuthUser,
+ ApiKey: envConfig.AuthKey,
+ AuthUrl: envConfig.AuthUrl,
+ }
+ if envConfig.TlsCaPath != "" {
+ log.Printf("INFO: TlsCaPath is presented: Trying to enforce TLS Authentication on swift backend using the server certs")
+ file, err := ioutil.ReadFile(envConfig.TlsCaPath)
+ if err != nil {
+ log.Fatal(err)
+ log.Printf("Wrong or missing value in paramteter: TlsCaPath")
+ os.Exit(-1)
+ }
+ certPool := x509.NewCertPool()
+ ok := certPool.AppendCertsFromPEM([]byte(file))
+ if !ok {
+ log.Fatal("Corrupt CACert file")
+ os.Exit(-1)
+ }
+ cert, err := tls.LoadX509KeyPair(envConfig.TlsCertPath, envConfig.TlsKeyPath)
+ if err != nil {
+ log.Fatal(err)
+ log.Printf("Wrong or missing value in paramteter: TlsCertPath or TlsKeyPath")
+ os.Exit(-1)
+ }
+ swiftCon.Transport = &http.Transport{
+ TLSClientConfig: &tls.Config{
+ RootCAs: certPool,
+ Certificates: []tls.Certificate{cert},
+ },
+ }
+ }
+ return swiftCon
+}
+
+func regenerateIndexYaml(envConfig config.EnvConfig, swiftConn *swift.Connection) error {
+ var err error
+ for i := 0; i <= regenRetryCounter; i++ {
+ err = repo.Index(swiftConn, envConfig.Container, envConfig.RepoUrl+":"+envConfig.ListenOnPort, envConfig.IndexPath, "/index.yaml")
+ if err != nil {
+ log.Println("INFO: Regenerating index.yaml in Swift try no.: " + strconv.Itoa(i) + " was unsuccessful at: " + swiftConn.AuthUrl +
+ " with error:" + err.Error())
+ time.Sleep(10 * time.Second)
+ continue
+ } else {
+ return nil
+ }
+ }
+ return errors.New("ERROR: Swift is not responsive, giving-up regeneration!")
+}
+
+func startHttpServer(envConfig config.EnvConfig, swiftConn *swift.Connection) {
+ router := api.NewRouter(swiftConn, envConfig)
+ var tlsCfg *tls.Config
+ if envConfig.TlsCertPath != "" && envConfig.TlsKeyPath != "" {
+ log.Println("TLS used")
+ tlsCfg = &tls.Config{
+ MinVersion: tls.VersionTLS12,
+ CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
+ PreferServerCipherSuites: true,
+ CipherSuites: []uint16{
+ tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
+ tls.TLS_RSA_WITH_AES_256_CBC_SHA,
+ },
+ }
+ } else {
+ tlsCfg = &tls.Config{}
+ }
+ chartRepo = &http.Server{
+ Addr: envConfig.ListenOnIP + ":" + envConfig.ListenOnPort,
+ Handler: router,
+ TLSConfig: tlsCfg,
+ TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler), 0),
+ }
+ go func() {
+ if chartRepo.TLSConfig != nil {
+ log.Fatal(chartRepo.ListenAndServeTLS(envConfig.TlsCertPath, envConfig.TlsKeyPath))
+ } else {
+ log.Fatal(chartRepo.ListenAndServe())
+ }
+ }()
+}
+