<commit_before>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

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 (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"strings"

	"github.com/ghodss/yaml"
	"github.com/gorilla/mux"

	"github.com/kubernetes/deployment-manager/common"
	"github.com/kubernetes/deployment-manager/manager/manager"
	"github.com/kubernetes/deployment-manager/manager/repository"
	"github.com/kubernetes/deployment-manager/manager/repository/persistent"
	"github.com/kubernetes/deployment-manager/manager/repository/transient"
	"github.com/kubernetes/deployment-manager/registry"
	"github.com/kubernetes/deployment-manager/util"
)

var deployments = []Route{
	{"ListDeployments", "/deployments", "GET", listDeploymentsHandlerFunc, ""},
	{"GetDeployment", "/deployments/{deployment}", "GET", getDeploymentHandlerFunc, ""},
	{"CreateDeployment", "/deployments", "POST", createDeploymentHandlerFunc, "JSON"},
	{"DeleteDeployment", "/deployments/{deployment}", "DELETE", deleteDeploymentHandlerFunc, ""},
	{"PutDeployment", "/deployments/{deployment}", "PUT", putDeploymentHandlerFunc, "JSON"},
	{"ListManifests", "/deployments/{deployment}/manifests", "GET", listManifestsHandlerFunc, ""},
	{"GetManifest", "/deployments/{deployment}/manifests/{manifest}", "GET", getManifestHandlerFunc, ""},
	{"Expand", "/expand", "POST", expandHandlerFunc, ""},
	{"ListTypes", "/types", "GET", listTypesHandlerFunc, ""},
	{"ListTypeInstances", "/types/{type}/instances", "GET", listTypeInstancesHandlerFunc, ""},
	{"GetRegistryForType", "/types/{type}/registry", "GET", getRegistryForTypeHandlerFunc, ""},
	{"GetMetadataForType", "/types/{type}/metadata", "GET", getMetadataForTypeHandlerFunc, ""},
	{"ListRegistries", "/registries", "GET", listRegistriesHandlerFunc, ""},
	{"GetRegistry", "/registries/{registry}", "GET", getRegistryHandlerFunc, ""},
	{"CreateRegistry", "/registries/{registry}", "POST", createRegistryHandlerFunc, "JSON"},
	{"ListRegistryTypes", "/registries/{registry}/types", "GET", listRegistryTypesHandlerFunc, ""},
	{"GetDownloadURLs", "/registries/{registry}/types/{type}", "GET", getDownloadURLsHandlerFunc, ""},
	{"GetFile", "/registries/{registry}/download", "GET", getFileHandlerFunc, ""},
	{"CreateCredential", "/credentials/{credential}", "POST", createCredentialHandlerFunc, "JSON"},
	{"GetCredential", "/credentials/{credential}", "GET", getCredentialHandlerFunc, ""},
}

var (
	maxLength         = flag.Int64("maxLength", 1024, "The maximum length (KB) of a template.")
	expanderName      = flag.String("expander", "expandybird-service", "The DNS name of the expander service.")
	expanderURL       = flag.String("expanderURL", "", "The URL for the expander service.")
	deployerName      = flag.String("deployer", "resourcifier-service", "The DNS name of the deployer service.")
	deployerURL       = flag.String("deployerURL", "", "The URL for the deployer service.")
	credentialFile    = flag.String("credentialFile", "", "Local file to use for credentials.")
	credentialSecrets = flag.Bool("credentialSecrets", true, "Use secrets for credentials.")
	mongoName         = flag.String("mongoName", "mongodb", "The DNS name of the mongodb service.")
	mongoPort         = flag.String("mongoPort", "27017", "The port of the mongodb service.")
	mongoAddress      = flag.String("mongoAddress", "mongodb:27017", "The address of the mongodb service.")
)

var backend manager.Manager

func init() {
	if !flag.Parsed() {
		flag.Parse()
	}

	routes = append(routes, deployments...)
	var credentialProvider common.CredentialProvider
	if *credentialFile != "" {
		if *credentialSecrets {
			panic(fmt.Errorf("Both credentialFile and credentialSecrets are set"))
		}
		var err error
		credentialProvider, err = registry.NewFilebasedCredentialProvider(*credentialFile)
		if err != nil {
			panic(fmt.Errorf("cannot create credential provider %s: %s", *credentialFile, err))
		}
	} else if *credentialSecrets {
		credentialProvider = registry.NewSecretsCredentialProvider()
	} else {
		credentialProvider = registry.NewInmemCredentialProvider()
	}
	backend = newManager(credentialProvider)
}

const expanderPort = "8080"
const deployerPort = "8080"

func newManager(cp common.CredentialProvider) manager.Manager {
	service := registry.NewInmemRegistryService()
	registryProvider := registry.NewDefaultRegistryProvider(cp, service)
	resolver := manager.NewTypeResolver(registryProvider, util.DefaultHTTPClient())
	expander := manager.NewExpander(getServiceURL(*expanderURL, *expanderName, expanderPort), resolver)
	deployer := manager.NewDeployer(getServiceURL(*deployerURL, *deployerName, deployerPort))
	address := strings.TrimPrefix(getServiceURL(*mongoAddress, *mongoName, *mongoPort), "https://")
	repository := createRepository(address)
	return manager.NewManager(expander, deployer, repository, registryProvider, service, cp)
}

func createRepository(address string) repository.Repository {
	r, err := persistent.NewRepository(address)
	if err != nil {
		r = transient.NewRepository()
	}

	return r
}

func getServiceURL(serviceURL, serviceName, servicePort string) string {
	if serviceURL == "" {
		serviceURL = makeEnvVariableURL(serviceName)
		if serviceURL == "" {
			addrs, err := net.LookupHost(serviceName)
			if err != nil || len(addrs) < 1 {
				log.Fatalf("cannot resolve service:%v. environment:%v\n", serviceName, os.Environ())
			}

			serviceURL = fmt.Sprintf("https://%s:%s", addrs[0], servicePort)
		}
	}

	return serviceURL
}

// makeEnvVariableURL takes a service name and returns the value of the
// environment variable that identifies its URL, if it exists, or the empty
// string, if it doesn't.
func makeEnvVariableURL(str string) string {
	prefix := makeEnvVariableName(str)
	url := os.Getenv(prefix + "_PORT")
	return strings.Replace(url, "tcp", "https", 1)
}

// makeEnvVariableName is copied from the Kubernetes source,
// which is referenced by the documentation for service environment variables.<commit_msg>Fix TLS mismatch issue.<commit_after>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

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 (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"strings"

	"github.com/ghodss/yaml"
	"github.com/gorilla/mux"

	"github.com/kubernetes/deployment-manager/common"
	"github.com/kubernetes/deployment-manager/manager/manager"
	"github.com/kubernetes/deployment-manager/manager/repository"
	"github.com/kubernetes/deployment-manager/manager/repository/persistent"
	"github.com/kubernetes/deployment-manager/manager/repository/transient"
	"github.com/kubernetes/deployment-manager/registry"
	"github.com/kubernetes/deployment-manager/util"
)

var deployments = []Route{
	{"ListDeployments", "/deployments", "GET", listDeploymentsHandlerFunc, ""},
	{"GetDeployment", "/deployments/{deployment}", "GET", getDeploymentHandlerFunc, ""},
	{"CreateDeployment", "/deployments", "POST", createDeploymentHandlerFunc, "JSON"},
	{"DeleteDeployment", "/deployments/{deployment}", "DELETE", deleteDeploymentHandlerFunc, ""},
	{"PutDeployment", "/deployments/{deployment}", "PUT", putDeploymentHandlerFunc, "JSON"},
	{"ListManifests", "/deployments/{deployment}/manifests", "GET", listManifestsHandlerFunc, ""},
	{"GetManifest", "/deployments/{deployment}/manifests/{manifest}", "GET", getManifestHandlerFunc, ""},
	{"Expand", "/expand", "POST", expandHandlerFunc, ""},
	{"ListTypes", "/types", "GET", listTypesHandlerFunc, ""},
	{"ListTypeInstances", "/types/{type}/instances", "GET", listTypeInstancesHandlerFunc, ""},
	{"GetRegistryForType", "/types/{type}/registry", "GET", getRegistryForTypeHandlerFunc, ""},
	{"GetMetadataForType", "/types/{type}/metadata", "GET", getMetadataForTypeHandlerFunc, ""},
	{"ListRegistries", "/registries", "GET", listRegistriesHandlerFunc, ""},
	{"GetRegistry", "/registries/{registry}", "GET", getRegistryHandlerFunc, ""},
	{"CreateRegistry", "/registries/{registry}", "POST", createRegistryHandlerFunc, "JSON"},
	{"ListRegistryTypes", "/registries/{registry}/types", "GET", listRegistryTypesHandlerFunc, ""},
	{"GetDownloadURLs", "/registries/{registry}/types/{type}", "GET", getDownloadURLsHandlerFunc, ""},
	{"GetFile", "/registries/{registry}/download", "GET", getFileHandlerFunc, ""},
	{"CreateCredential", "/credentials/{credential}", "POST", createCredentialHandlerFunc, "JSON"},
	{"GetCredential", "/credentials/{credential}", "GET", getCredentialHandlerFunc, ""},
}

var (
	maxLength         = flag.Int64("maxLength", 1024, "The maximum length (KB) of a template.")
	expanderName      = flag.String("expander", "expandybird-service", "The DNS name of the expander service.")
	expanderURL       = flag.String("expanderURL", "", "The URL for the expander service.")
	deployerName      = flag.String("deployer", "resourcifier-service", "The DNS name of the deployer service.")
	deployerURL       = flag.String("deployerURL", "", "The URL for the deployer service.")
	credentialFile    = flag.String("credentialFile", "", "Local file to use for credentials.")
	credentialSecrets = flag.Bool("credentialSecrets", true, "Use secrets for credentials.")
	mongoName         = flag.String("mongoName", "mongodb", "The DNS name of the mongodb service.")
	mongoPort         = flag.String("mongoPort", "27017", "The port of the mongodb service.")
	mongoAddress      = flag.String("mongoAddress", "mongodb:27017", "The address of the mongodb service.")
)

var backend manager.Manager

func init() {
	if !flag.Parsed() {
		flag.Parse()
	}

	routes = append(routes, deployments...)
	var credentialProvider common.CredentialProvider
	if *credentialFile != "" {
		if *credentialSecrets {
			panic(fmt.Errorf("Both credentialFile and credentialSecrets are set"))
		}
		var err error
		credentialProvider, err = registry.NewFilebasedCredentialProvider(*credentialFile)
		if err != nil {
			panic(fmt.Errorf("cannot create credential provider %s: %s", *credentialFile, err))
		}
	} else if *credentialSecrets {
		credentialProvider = registry.NewSecretsCredentialProvider()
	} else {
		credentialProvider = registry.NewInmemCredentialProvider()
	}
	backend = newManager(credentialProvider)
}

const expanderPort = "8080"
const deployerPort = "8080"

func newManager(cp common.CredentialProvider) manager.Manager {
	service := registry.NewInmemRegistryService()
	registryProvider := registry.NewDefaultRegistryProvider(cp, service)
	resolver := manager.NewTypeResolver(registryProvider, util.DefaultHTTPClient())
	expander := manager.NewExpander(getServiceURL(*expanderURL, *expanderName, expanderPort), resolver)
	deployer := manager.NewDeployer(getServiceURL(*deployerURL, *deployerName, deployerPort))
	address := strings.TrimPrefix(getServiceURL(*mongoAddress, *mongoName, *mongoPort), "http://")
	repository := createRepository(address)
	return manager.NewManager(expander, deployer, repository, registryProvider, service, cp)
}

func createRepository(address string) repository.Repository {
	r, err := persistent.NewRepository(address)
	if err != nil {
		r = transient.NewRepository()
	}

	return r
}

func getServiceURL(serviceURL, serviceName, servicePort string) string {
	if serviceURL == "" {
		serviceURL = makeEnvVariableURL(serviceName)
		if serviceURL == "" {
			addrs, err := net.LookupHost(serviceName)
			if err != nil || len(addrs) < 1 {
				log.Fatalf("cannot resolve service:%v. environment:%v\n", serviceName, os.Environ())
			}

			serviceURL = fmt.Sprintf("http://%s:%s", addrs[0], servicePort)
		}
	}

	return serviceURL
}

// makeEnvVariableURL takes a service name and returns the value of the
// environment variable that identifies its URL, if it exists, or the empty
// string, if it doesn't.
func makeEnvVariableURL(str string) string {
	prefix := makeEnvVariableName(str)
	url := os.Getenv(prefix + "_PORT")
	return strings.Replace(url, "tcp", "http", 1)
}

// makeEnvVariableName is copied from the Kubernetes source,
// which is referenced by the documentation for service environment variables.
{'fraction_non_alphanumeric': 0.14338150952053222, 'fraction_numerical': 0.005352909688766536, 'mean_word_length': 5.696364567332309, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2094153', 'n_tokens_mistral': 4061, 'n_tokens_neox': 3854, 'n_words': 970}