diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 12a4daf..91bf1e5 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -4,7 +4,7 @@ You will need admin access to a Kubernetes cluster, some CLI tooling and a GitHu ## Pre-reqs -This tool automates the installation of OpenFaaS Cloud on Kubernetes. Before starting you will need to install some tools and then create either a local or remote cluster. +This tool automates the installation of OpenFaaS Cloud on Kubernetes. Before starting, you will need to install some tools and then create either a local or remote cluster. For your cluster the following specifications are recommended: @@ -513,28 +513,8 @@ At this point you can also view your UI dashboard at: http://127.0.0.1:31112 ## Re-deploy the OpenFaaS Cloud functions (advanced) -If you run the step above `Access your OpenFaaS UI or API`, then you can edit settings for OpenFaaS Cloud and redeploy your functions. This is an advanced step. - -``` -cd tmp/openfaas-cloud/ - -# Edit stack.yml -# Edit github.yml or gitlab.yml -# Edit gateway_config.yml -# Edit buildshiprun_limits.yml - -# Edit aws.yml if you want to change AWS ECR settings such as the region - -# Update all functions -faas-cli deploy -f stack.yml - - -# Update AWS ECR functions if needed -faas-cli deploy -f aws.yml - -# Update a single function, such as "buildshiprun" -faas-cli deploy -f stack.yml --filter=buildshiprun -``` +Run `ofc-bootstrap` passing `--update-cloud` as a flag. +This will re-deploy the ofc helm chart using the new settings in init.yaml ## Invite your team @@ -549,29 +529,9 @@ alexellis When you want to switch to the Production issuer from staging do the following: -Flush out the staging certificates and orders +Update the staging setting in init.yaml to "prod" and re-run `ofc-bootstrap` passing `--update-cloud` as a flag. +This will re-deploy the ofc helm chart using the new settings. -```sh -kubectl delete certificates --all -n openfaas -kubectl delete secret -n openfaas -l="cert-manager.io/certificate-name" -kubectl delete order -n openfaas --all +```sh +ofc-bootstrap apply -f init.yaml --update-cloud ``` - -Now update the staging references to "prod": - -```sh -sed -i '' s/letsencrypt-staging/letsencrypt-prod/g ./tmp/generated-ingress-ingress-wildcard.yaml -sed -i '' s/letsencrypt-staging/letsencrypt-prod/g ./tmp/generated-ingress-ingress-auth.yaml -sed -i '' s/letsencrypt-staging/letsencrypt-prod/g ./tmp/generated-tls-auth-domain-cert.yml -sed -i '' s/letsencrypt-staging/letsencrypt-prod/g ./tmp/generated-tls-wildcard-domain-cert.yml -``` - -Now create the new ingress and certificates: - -```sh -kubectl apply -f ./tmp/generated-ingress-ingress-wildcard.yaml -kubectl apply -f ./tmp/generated-ingress-ingress-auth.yaml -kubectl apply -f ./tmp/generated-tls-auth-domain-cert.yml -kubectl apply -f ./tmp/generated-tls-wildcard-domain-cert.yml -``` - diff --git a/cmd/apply.go b/cmd/apply.go index 4e99347..50a3437 100644 --- a/cmd/apply.go +++ b/cmd/apply.go @@ -4,6 +4,7 @@ package cmd import ( + "errors" "fmt" "io/ioutil" "log" @@ -18,13 +19,11 @@ import ( execute "github.com/alexellis/go-execute/pkg/v1" "github.com/alexellis/k3sup/pkg/config" "github.com/alexellis/k3sup/pkg/env" - "github.com/openfaas/ofc-bootstrap/pkg/ingress" "github.com/openfaas/ofc-bootstrap/pkg/stack" - "github.com/openfaas/ofc-bootstrap/pkg/tls" "github.com/openfaas/ofc-bootstrap/pkg/validators" "github.com/openfaas/ofc-bootstrap/pkg/types" - yaml "gopkg.in/yaml.v2" + "gopkg.in/yaml.v2" ) func init() { @@ -35,6 +34,7 @@ func init() { applyCmd.Flags().Bool("skip-minio", false, "Skip Minio installation") applyCmd.Flags().Bool("skip-create-secrets", false, "Skip creating secrets") applyCmd.Flags().Bool("print-plan", false, "Print merged plan and exit") + applyCmd.Flags().Bool("update-cloud", false, "set to true to only upgrade OFC components") } var applyCmd = &cobra.Command{ @@ -141,7 +141,7 @@ func runApplyCommandE(command *cobra.Command, _ []string) error { "faas-cli version", } - validateToolsErr := validateTools(tools, additionalPaths) + validateToolsErr := validateTools(tools) if validateToolsErr != nil { panic(validateToolsErr) @@ -159,15 +159,28 @@ func runApplyCommandE(command *cobra.Command, _ []string) error { os.MkdirAll("tmp", 0700) ioutil.WriteFile("tmp/go.mod", []byte("\n"), 0700) - fmt.Fprint(os.Stdout, "Validating registry credentials file") + fmt.Fprint(os.Stdout, "Validating registry credentials file\n") registryAuthErr := validateRegistryAuth(plan.Registry, plan.Secrets, plan.EnableECR) if registryAuthErr != nil { fmt.Fprint(os.Stderr, "error with registry credentials file. Please ensure it has been created correctly") } + cloudOnly, err := command.Flags().GetBool("update-cloud") + if err != nil { + return err + } + + if cloudOnly { + err := cloudComponentsInstall(plan) + if err != nil { + return err + } + return nil + } + start := time.Now() - err = process(plan, prefs, additionalPaths) + err = process(plan, prefs) done := time.Since(start) if err != nil { @@ -184,7 +197,7 @@ type Vars struct { YamlFile string } -func taskGivesStdout(tool string, additionalPaths []string) error { +func taskGivesStdout(tool string) error { parts := strings.Split(tool, " ") @@ -210,10 +223,10 @@ func taskGivesStdout(tool string, additionalPaths []string) error { return nil } -func validateTools(tools []string, additionalPaths []string) error { +func validateTools(tools []string) error { for _, tool := range tools { - err := taskGivesStdout(tool, additionalPaths) + err := taskGivesStdout(tool) if err != nil { return err } @@ -265,7 +278,7 @@ func filesExists(files []types.FileSecret) error { return nil } -func process(plan types.Plan, prefs InstallPreferences, additionalPaths []string) error { +func process(plan types.Plan, prefs InstallPreferences) error { if plan.OpenFaaSCloudVersion == "" { plan.OpenFaaSCloudVersion = "master" @@ -298,7 +311,7 @@ func process(plan types.Plan, prefs InstallPreferences, additionalPaths []string return err } - installIngressErr := installIngressController(plan.Ingress, additionalPaths) + installIngressErr := installIngressController(plan.Ingress) if installIngressErr != nil { log.Println(installIngressErr.Error()) return installIngressErr @@ -333,7 +346,7 @@ func process(plan types.Plan, prefs InstallPreferences, additionalPaths []string log.Println(functionAuthErr.Error()) } - ofErr := installOpenfaas(plan.ScaleToZero, plan.IngressOperator, additionalPaths) + ofErr := installOpenfaas(plan.ScaleToZero, plan.IngressOperator) if ofErr != nil { log.Println(ofErr) } @@ -350,23 +363,12 @@ func process(plan types.Plan, prefs InstallPreferences, additionalPaths []string } } - ingressErr := ingress.Apply(plan) - if ingressErr != nil { - log.Println(ingressErr) - } - - if plan.TLS { - tlsErr := tls.Apply(plan) - if tlsErr != nil { - log.Println(tlsErr) - } - } - fmt.Println("Creating stack.yml") planErr := stack.Apply(plan) if planErr != nil { log.Println(planErr) + return planErr } if !prefs.SkipSealedSecrets { @@ -384,46 +386,103 @@ func process(plan types.Plan, prefs InstallPreferences, additionalPaths []string } } - cloneErr := cloneCloudComponents(plan.OpenFaaSCloudVersion, additionalPaths) + err := cloudComponentsInstall(plan) + if err != nil { + return err + } + + return nil +} + +func cloudComponentsInstall(plan types.Plan) error { + cloneErr := cloneCloudComponents(plan.OpenFaaSCloudVersion) if cloneErr != nil { return cloneErr } - deployErr := deployCloudComponents(plan, additionalPaths) + ofcValuesErr := writeOFCValuesYaml(plan) + if ofcValuesErr != nil { + return ofcValuesErr + } + + deployErr := deployCloudComponents(plan) if deployErr != nil { return deployErr } - return nil } -func helmRepoAdd(name, repo string) error { - log.Printf("Adding %s helm repo\n", name) +func writeOFCValuesYaml(plan types.Plan) error { + ofcOptions := &types.OFCValues{} - task := execute.ExecTask{ - Command: "helm", - Args: []string{"repo", "add", name, repo}, - StreamStdio: true, + ofcOptions.NetworkPolicies.Enabled = plan.NetworkPolicies + + if plan.EnableOAuth { + ofcOptions.EdgeAuth.EnableOauth2 = true + ofcOptions.EdgeAuth.OauthProvider = plan.SCM + ofcOptions.EdgeAuth.ClientID = plan.OAuth.ClientId + ofcOptions.EdgeAuth.OauthProviderBaseURL = plan.OAuth.OAuthProviderBaseURL + } else { + ofcOptions.EdgeAuth.EnableOauth2 = false } - taskRes, taskErr := task.Execute() + ofcOptions.NetworkPolicies.Enabled = plan.NetworkPolicies + ofcOptions.Global.EnableECR = plan.EnableECR - if taskErr != nil { - return taskErr + if plan.TLS { + ofcOptions.TLS.IssuerType = plan.TLSConfig.IssuerType + ofcOptions.TLS.Enabled = true + ofcOptions.TLS.Email = plan.TLSConfig.Email + ofcOptions.TLS.DNSService = plan.TLSConfig.DNSService + switch ofcOptions.TLS.DNSService { + case types.CloudDNS: + ofcOptions.TLS.CloudDNS.ProjectID = plan.TLSConfig.ProjectID + case types.Cloudflare: + ofcOptions.TLS.Cloudflare.Email = plan.TLSConfig.Email + ofcOptions.TLS.Cloudflare.ProjectID = plan.TLSConfig.ProjectID + case types.Route53: + ofcOptions.TLS.Route53.AccessKeyID = plan.TLSConfig.AccessKeyID + ofcOptions.TLS.Route53.Region = plan.TLSConfig.Region + case types.DigitalOcean: + // No special config for DO DNS + default: + log.Fatalf("dns service not recognised: %s", ofcOptions.TLS.DNSService) + } + + } else { + ofcOptions.TLS.Enabled = false } - if len(taskRes.Stderr) > 0 { - log.Println(taskRes.Stderr) + ofcOptions.Customers.CustomersSecret = plan.CustomersSecret + ofcOptions.Customers.URL = plan.CustomersURL + if len(plan.CustomersURL) == 0 && !plan.CustomersSecret { + return errors.New("unable to continue without a customers secret or url") + } + + ofcOptions.Global.EnableECR = plan.EnableECR + ofcOptions.Global.RootDomain = plan.RootDomain + + ofcOptions.Ingress.MaxConnections = plan.IngressConfig.MaxConnections + ofcOptions.Ingress.RequestsPerMinute = plan.IngressConfig.RequestsPerMinute + yamlBytes, err := yaml.Marshal(&ofcOptions) + if err != nil { + log.Fatalf("error: %v", err) + } + filePath := "./tmp/ofc-values.yaml" + fileErr := ioutil.WriteFile(filePath, yamlBytes, 0644) + if fileErr != nil { + return fileErr } return nil } -func helmRepoAddStable() error { - log.Println("Adding stable helm repo") +func helmRepoAdd(name, repo string) error { + log.Printf("Adding %s helm repo\n", name) task := execute.ExecTask{ Command: "helm", + Args: []string{"repo", "add", name, repo}, StreamStdio: true, } @@ -484,7 +543,7 @@ func createFunctionsAuth() error { return nil } -func installIngressController(ingress string, additionalPaths []string) error { +func installIngressController(ingress string) error { log.Println("Creating Ingress Controller") var env []string @@ -532,7 +591,7 @@ func installSealedSecrets() error { return nil } -func installOpenfaas(scaleToZero, ingressOperator bool, additionalPaths []string) error { +func installOpenfaas(scaleToZero, ingressOperator bool) error { log.Println("Creating OpenFaaS") task := execute.ExecTask{ @@ -660,19 +719,6 @@ func createSecrets(plan types.Plan) error { return nil } -func sealedSecretsReady() bool { - - task := execute.ExecTask{ - Command: "./scripts/get-sealedsecretscontroller.sh", - Shell: true, - StreamStdio: true, - } - - res, err := task.Execute() - fmt.Println("sealedsecretscontroller", res.ExitCode, res.Stdout, res.Stderr, err) - return res.Stdout == "1" -} - func exportSealedSecretPubCert() string { task := execute.ExecTask{ @@ -698,7 +744,7 @@ func certManagerReady() bool { return res.Stdout == "True" } -func cloneCloudComponents(tag string, additionalPaths []string) error { +func cloneCloudComponents(tag string) error { task := execute.ExecTask{ Command: "./scripts/clone-cloud-components.sh", Shell: true, @@ -708,17 +754,15 @@ func cloneCloudComponents(tag string, additionalPaths []string) error { StreamStdio: true, } - res, err := task.Execute() + _, err := task.Execute() if err != nil { return err } - fmt.Println(res) - return nil } -func deployCloudComponents(plan types.Plan, additionalPaths []string) error { +func deployCloudComponents(plan types.Plan) error { authEnv := "" if plan.EnableOAuth { diff --git a/example.init.yaml b/example.init.yaml index ceb7ff6..6fef2ba 100644 --- a/example.init.yaml +++ b/example.init.yaml @@ -104,7 +104,7 @@ secrets: value_from: "~/Downloads/do-access-token" filters: - "do_dns01" - namespace: "cert-manager" + namespace: "openfaas" ## Use Google Cloud DNS ### Create a service account for DNS management and export it @@ -114,7 +114,7 @@ secrets: value_from: "~/Downloads/service-account.json" filters: - "gcp_dns01" - namespace: "cert-manager" + namespace: "openfaas" ## Use Route 53 ### Create role and download its secret access key @@ -124,7 +124,7 @@ secrets: value_from: "~/Downloads/route53-secret-access-key" filters: - "route53_dns01" - namespace: "cert-manager" + namespace: "openfaas" ## Use Cloudflare ### Create role and download its secret access key @@ -134,7 +134,7 @@ secrets: value_from: "~/Downloads/cloudflare-secret-access-key" filters: - "cloudflare_dns01" - namespace: "cert-manager" + namespace: "openfaas" # Used by Buildkit to push images to your registry - name: "registry-secret" @@ -333,3 +333,7 @@ enable_ingress_operator: false ### Usage: release tag, a SHA or branch name openfaas_cloud_version: 0.14.2 +## Settings for the ingress records +ingress_config: + max_connections: 20 + requests_per_minute: 600 diff --git a/pkg/ingress/ingress.go b/pkg/ingress/ingress.go deleted file mode 100644 index 2f405ea..0000000 --- a/pkg/ingress/ingress.go +++ /dev/null @@ -1,98 +0,0 @@ -package ingress - -import ( - "bytes" - "fmt" - "html/template" - "io/ioutil" - "log" - "os" - - execute "github.com/alexellis/go-execute/pkg/v1" - "github.com/openfaas/ofc-bootstrap/pkg/types" -) - -type IngressTemplate struct { - RootDomain string - TLS bool - IssuerType string -} - -// Apply templates and applies any ingress records required -// for the OpenFaaS Cloud ingress configuration -func Apply(plan types.Plan) error { - - err := apply("ingress-wildcard.yml", "ingress-wildcard", IngressTemplate{ - RootDomain: plan.RootDomain, - TLS: plan.TLS, - IssuerType: plan.TLSConfig.IssuerType, - }) - - if err != nil { - return err - } - - err1 := apply("ingress-auth.yml", "ingress-auth", IngressTemplate{ - RootDomain: plan.RootDomain, - TLS: plan.TLS, - IssuerType: plan.TLSConfig.IssuerType, - }) - - if err1 != nil { - return err1 - } - - return nil -} - -func apply(source string, name string, ingress IngressTemplate) error { - - generatedData, err := applyTemplate("templates/k8s/"+source, ingress) - if err != nil { - return fmt.Errorf("unable to read template %s (%s), error: %q", name, "templates/k8s/"+source, err) - } - - tempFilePath := "tmp/generated-ingress-" + name + ".yaml" - file, fileErr := os.Create(tempFilePath) - if fileErr != nil { - return fileErr - } - defer file.Close() - - _, writeErr := file.Write(generatedData) - file.Close() - - if writeErr != nil { - return writeErr - } - - execTask := execute.ExecTask{ - Command: "kubectl", - Args: []string{"apply", "-f", tempFilePath}, - Shell: false, - StreamStdio: true, - } - - execRes, execErr := execTask.Execute() - if execErr != nil { - return execErr - } - - log.Println(execRes.ExitCode, execRes.Stdout, execRes.Stderr) - - return nil -} - -func applyTemplate(templateFileName string, templateValues IngressTemplate) ([]byte, error) { - data, err := ioutil.ReadFile(templateFileName) - if err != nil { - return nil, err - } - t := template.Must(template.New(templateFileName).Parse(string(data))) - - buffer := new(bytes.Buffer) - - executeErr := t.Execute(buffer, templateValues) - - return buffer.Bytes(), executeErr -} diff --git a/pkg/ingress/ingress_test.go b/pkg/ingress/ingress_test.go deleted file mode 100644 index 44689f8..0000000 --- a/pkg/ingress/ingress_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package ingress - -import ( - "strings" - "testing" -) - -func Test_applyTemplateWithTLS(t *testing.T) { - templateValues := IngressTemplate{ - RootDomain: "test.com", - TLS: true, - } - - templateFileName := "../../templates/k8s/ingress-auth.yml" - - generatedValue, err := applyTemplate(templateFileName, templateValues) - want := "tls" - - if err != nil { - t.Errorf("expected no error generating template, but got %s", err.Error()) - t.Fail() - return - } - - if strings.Contains(string(generatedValue), want) == false { - t.Errorf("want generated value to contain: %q, generated was: %q", want, string(generatedValue)) - t.Fail() - } -} diff --git a/pkg/stack/stack.go b/pkg/stack/stack.go index 898ec36..bb5355f 100644 --- a/pkg/stack/stack.go +++ b/pkg/stack/stack.go @@ -50,7 +50,6 @@ type awsConfig struct { ECRRegion string } -// Apply creates `templates/gateway_config.yml` to be referenced by stack.yml func Apply(plan types.Plan) error { scheme := "http" if plan.TLS { @@ -67,7 +66,6 @@ func Apply(plan types.Plan) error { Registry: plan.Registry, RootDomain: plan.RootDomain, CustomersURL: plan.CustomersURL, - Scheme: scheme, S3: plan.S3, CustomTemplates: plan.Deployment.FormatCustomTemplates(), EnableDockerfileLang: plan.EnableDockerfileLang, @@ -105,26 +103,6 @@ func Apply(plan types.Plan) error { return dashboardConfigErr } - if plan.EnableOAuth { - ofCustomersSecretPath := "" - if plan.CustomersSecret { - ofCustomersSecretPath = "/var/secrets/of-customers/of-customers" - } - - if ofAuthDepErr := generateTemplate("edge-auth-dep", plan, authConfig{ - RootDomain: plan.RootDomain, - ClientId: plan.OAuth.ClientId, - CustomersURL: plan.CustomersURL, - Scheme: scheme, - OAuthProvider: plan.SCM, - OAuthProviderBaseURL: plan.OAuth.OAuthProviderBaseURL, - OFCustomersSecretPath: ofCustomersSecretPath, - TLSEnabled: plan.TLS, - }); ofAuthDepErr != nil { - return ofAuthDepErr - } - } - isGitHub := plan.SCM == "github" if stackErr := generateTemplate("stack", plan, stackConfig{ GitHub: isGitHub, @@ -133,12 +111,6 @@ func Apply(plan types.Plan) error { return stackErr } - if builderErr := generateTemplate("of-builder-dep", plan, builderConfig{ - ECR: plan.EnableECR, - }); builderErr != nil { - return builderErr - } - if ecrErr := generateTemplate("aws", plan, awsConfig{ ECRRegion: plan.ECRConfig.ECRRegion, }); ecrErr != nil { diff --git a/pkg/stack/stack_test.go b/pkg/stack/stack_test.go index 3a1b92f..a4e4304 100644 --- a/pkg/stack/stack_test.go +++ b/pkg/stack/stack_test.go @@ -5,36 +5,6 @@ import ( "testing" ) -func Test_applyTemplateWithAuth(t *testing.T) { - - clientID := "test_oauth_app_client_id" - customersURL := "https://raw.githubusercontent.com/test/path/CUSTOMERS" - - templateValues := authConfig{ - ClientId: clientID, - CustomersURL: customersURL, - Scheme: "http", - } - - templateFileName := "../../templates/edge-auth-dep.yml" - - generatedValue, err := applyTemplate(templateFileName, templateValues) - - if err != nil { - t.Errorf("expected no error generating template, but got %s", err.Error()) - t.Fail() - return - } - - values := []string{clientID, customersURL} - for _, want := range values { - if strings.Contains(string(generatedValue), want) == false { - t.Errorf("want generated value to contain: %q, generated was: %q", want, string(generatedValue)) - t.Fail() - } - } -} - func Test_gitlabTemplates(t *testing.T) { gitLabInstance := "https://gitlab.test.o6s.io/" diff --git a/pkg/tls/.gitignore b/pkg/tls/.gitignore deleted file mode 100644 index 1e82fc7..0000000 --- a/pkg/tls/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.yaml diff --git a/pkg/tls/issuer_test.go b/pkg/tls/issuer_test.go deleted file mode 100644 index 710ca57..0000000 --- a/pkg/tls/issuer_test.go +++ /dev/null @@ -1,236 +0,0 @@ -package tls - -import ( - "bytes" - "html/template" - "io/ioutil" - "testing" -) - -func Test_DigitalOcean_Issuer(t *testing.T) { - tlsTemplate := TLSTemplate{ - Email: "sales@openfaas.com", - IssuerType: "ClusterIssuer", - DNSService: "digitalocean", - } - - templatePath := "../../templates/k8s/tls/issuer-prod.yml" - templateData, err := ioutil.ReadFile(templatePath) - if err != nil { - t.Error(err) - return - } - - templateRes := template.Must(template.New("prod-issuer").Parse(string(templateData))) - buf := bytes.Buffer{} - - templateRes.Execute(&buf, &tlsTemplate) - - wantTemplate := `apiVersion: cert-manager.io/v1alpha2 -kind: ClusterIssuer -metadata: - name: letsencrypt-prod - namespace: openfaas -spec: - acme: - email: "sales@openfaas.com" - server: https://acme-v02.api.letsencrypt.org/directory - privateKeySecretRef: - name: letsencrypt-prod - solvers: - - dns01: - digitalocean: - - tokenSecretRef: - name: digitalocean-dns - key: access-token - ` - - got := string(buf.Bytes()) - if len(got) == 0 { - t.Errorf("No bytes generated from template") - t.Fail() - } - - if debugYAML { - ioutil.WriteFile("want-"+tlsTemplate.DNSService+".yaml", []byte(wantTemplate), 0700) - ioutil.WriteFile("got-"+tlsTemplate.DNSService+".yaml", []byte(got), 0700) - } - - if got != wantTemplate { - t.Errorf("Want\n`%q`\n, but got\n`%q`", wantTemplate, got) - } - -} - -func Test_Route53_Issuer(t *testing.T) { - tlsTemplate := TLSTemplate{ - Email: "sales@openfaas.com", - IssuerType: "ClusterIssuer", - DNSService: "route53", - Region: "us-east-1", - AccessKeyID: "key-id", - } - - templatePath := "../../templates/k8s/tls/issuer-prod.yml" - templateData, err := ioutil.ReadFile(templatePath) - if err != nil { - t.Error(err) - return - } - - templateRes := template.Must(template.New("prod-issuer").Parse(string(templateData))) - buf := bytes.Buffer{} - templateRes.Execute(&buf, &tlsTemplate) - - wantTemplate := `apiVersion: cert-manager.io/v1alpha2 -kind: ClusterIssuer -metadata: - name: letsencrypt-prod - namespace: openfaas -spec: - acme: - email: "sales@openfaas.com" - server: https://acme-v02.api.letsencrypt.org/directory - privateKeySecretRef: - name: letsencrypt-prod - solvers: - - dns01: - route53: - - region: us-east-1 - # optional if ambient credentials are available; see ambient credentials documentation - accessKeyID: key-id - secretAccessKeySecretRef: - name: "route53-credentials-secret" - key: secret-access-key - ` - - got := string(buf.Bytes()) - if len(got) == 0 { - t.Errorf("No bytes generated from template") - t.Fail() - } - - if debugYAML { - ioutil.WriteFile("want-"+tlsTemplate.DNSService+".yaml", []byte(wantTemplate), 0700) - ioutil.WriteFile("got-"+tlsTemplate.DNSService+".yaml", []byte(got), 0700) - } - - if got != wantTemplate { - t.Errorf("Want\n`%q`\n, but got\n`%q`", wantTemplate, got) - } -} - -func Test_GoogleCloudDNS_Issuer(t *testing.T) { - tlsTemplate := TLSTemplate{ - Email: "sales@openfaas.com", - IssuerType: "ClusterIssuer", - DNSService: "clouddns", - ProjectID: "project-1", - } - - templatePath := "../../templates/k8s/tls/issuer-prod.yml" - templateData, err := ioutil.ReadFile(templatePath) - if err != nil { - t.Error(err) - return - } - - templateRes := template.Must(template.New("prod-issuer").Parse(string(templateData))) - buf := bytes.Buffer{} - templateRes.Execute(&buf, &tlsTemplate) - - wantTemplate := `apiVersion: cert-manager.io/v1alpha2 -kind: ClusterIssuer -metadata: - name: letsencrypt-prod - namespace: openfaas -spec: - acme: - email: "sales@openfaas.com" - server: https://acme-v02.api.letsencrypt.org/directory - privateKeySecretRef: - name: letsencrypt-prod - solvers: - - dns01: - clouddns: - - project: "project-1" - serviceAccountSecretRef: - name: "clouddns-service-account" - key: service-account.json - ` - - got := string(buf.Bytes()) - if len(got) == 0 { - t.Errorf("No bytes generated from template") - t.Fail() - } - - if debugYAML { - ioutil.WriteFile("want-"+tlsTemplate.DNSService+".yaml", []byte(wantTemplate), 0700) - ioutil.WriteFile("got-"+tlsTemplate.DNSService+".yaml", []byte(got), 0700) - } - - if got != wantTemplate { - t.Errorf("Want\n`%q`\n, but got\n`%q`", wantTemplate, got) - } -} - -func Test_CloudFlare_Issuer(t *testing.T) { - tlsTemplate := TLSTemplate{ - Email: "sales@openfaas.com", - IssuerType: "ClusterIssuer", - DNSService: "cloudflare", - } - - templatePath := "../../templates/k8s/tls/issuer-prod.yml" - templateData, err := ioutil.ReadFile(templatePath) - if err != nil { - t.Error(err) - return - } - - templateRes := template.Must(template.New("prod-issuer").Parse(string(templateData))) - buf := bytes.Buffer{} - templateRes.Execute(&buf, &tlsTemplate) - - wantTemplate := `apiVersion: cert-manager.io/v1alpha2 -kind: ClusterIssuer -metadata: - name: letsencrypt-prod - namespace: openfaas -spec: - acme: - email: "sales@openfaas.com" - server: https://acme-v02.api.letsencrypt.org/directory - privateKeySecretRef: - name: letsencrypt-prod - solvers: - - dns01: - cloudflare: - - email: sales@openfaas.com - apiKeySecretRef: - name: cloudflare-api-key-secret - key: api-key - ` - - got := string(buf.Bytes()) - if len(got) == 0 { - t.Errorf("No bytes generated from template") - t.Fail() - } - - if debugYAML { - ioutil.WriteFile("want-"+tlsTemplate.DNSService+".yaml", []byte(wantTemplate), 0700) - ioutil.WriteFile("got-"+tlsTemplate.DNSService+".yaml", []byte(got), 0700) - } - - if got != wantTemplate { - t.Errorf("Want\n`%q`\n, but got\n`%q`", wantTemplate, got) - } -} - -var debugYAML bool diff --git a/pkg/tls/tls.go b/pkg/tls/tls.go deleted file mode 100644 index 42012b0..0000000 --- a/pkg/tls/tls.go +++ /dev/null @@ -1,104 +0,0 @@ -package tls - -import ( - "html/template" - "io/ioutil" - "log" - "os" - - execute "github.com/alexellis/go-execute/pkg/v1" - "github.com/openfaas/ofc-bootstrap/pkg/types" -) - -// TLSTemplate TLS configuration -type TLSTemplate struct { - RootDomain string - Email string - DNSService string - ProjectID string - IssuerType string - Region string - AccessKeyID string -} - -// Apply executes the plan -func Apply(plan types.Plan) error { - - tlsTemplatesList, _ := listTLSTemplates() - tlsTemplate := TLSTemplate{ - RootDomain: plan.RootDomain, - Email: plan.TLSConfig.Email, - DNSService: plan.TLSConfig.DNSService, - ProjectID: plan.TLSConfig.ProjectID, - IssuerType: plan.TLSConfig.IssuerType, - Region: plan.TLSConfig.Region, - AccessKeyID: plan.TLSConfig.AccessKeyID, - } - - for _, template := range tlsTemplatesList { - tempFilePath, tlsTemplateErr := generateTemplate(template, tlsTemplate) - if tlsTemplateErr != nil { - return tlsTemplateErr - } - - applyErr := applyTemplate(tempFilePath) - if applyErr != nil { - return applyErr - } - } - - return nil -} - -func listTLSTemplates() ([]string, error) { - - return []string{ - "issuer-prod.yml", - "issuer-staging.yml", - "wildcard-domain-cert.yml", - "auth-domain-cert.yml", - }, nil -} - -func generateTemplate(fileName string, tlsTemplate TLSTemplate) (string, error) { - tlsTemplatesPath := "templates/k8s/tls/" - - data, err := ioutil.ReadFile(tlsTemplatesPath + fileName) - if err != nil { - return "", err - } - - t := template.Must(template.New(fileName).Parse(string(data))) - tempFilePath := "tmp/generated-tls-" + fileName - file, fileErr := os.Create(tempFilePath) - if fileErr != nil { - return "", fileErr - } - defer file.Close() - - executeErr := t.Execute(file, tlsTemplate) - - if executeErr != nil { - return "", executeErr - } - - return tempFilePath, nil -} - -func applyTemplate(tempFilePath string) error { - - execTask := execute.ExecTask{ - Command: "kubectl apply -f " + tempFilePath, - Shell: false, - StreamStdio: true, - } - - execRes, execErr := execTask.Execute() - if execErr != nil { - return execErr - } - - log.Println(execRes.ExitCode, execRes.Stdout, execRes.Stderr) - - return nil -} diff --git a/pkg/types/types.go b/pkg/types/types.go index cd59f34..c294d1c 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -70,6 +70,13 @@ type Plan struct { ECRConfig ECRConfig `yaml:"ecr_config,omitempty"` CustomersSecret bool `yaml:"customers_secret,omitempty"` IngressOperator bool `yaml:"enable_ingress_operator,omitempty"` + IngressConfig IngressConfig `yaml:"ingress_config,omitempty"` +} + +// IngressConfig is for configuring Ingress type settings, like max connections +type IngressConfig struct { + MaxConnections string `yaml:"max_connections,omitempty"` + RequestsPerMinute string `yaml:"requests_per_minute,omitempty"` } // Deployment is the deployment section of YAML concerning @@ -156,3 +163,62 @@ type TLSConfig struct { type ECRConfig struct { ECRRegion string `yaml:"ecr_region,omitempty"` } + +type OFCValues struct { + EdgeAuth EdgeAuth `yaml:"edgeAuth,omitempty"` + TLS OFCTLS `yaml:"tls,omitempty"` + Ingress Ingress `yaml:"ingress,omitempty"` + Global Global `yaml:"global,omitempty"` + NetworkPolicies NetworkPolicies `yaml:"networkPolicies,omitempty"` + Customers Customers `yaml:"customers,omitempty"` +} + +type NetworkPolicies struct { + Enabled bool `yaml:"enabled,omitempty"` +} + +type EdgeAuth struct { + EnableOauth2 bool `yaml:"enableOauth2,omitempty"` + OauthProvider string `yaml:"oauthProvider,omitempty"` + OauthProviderBaseURL string `yaml:"oauthProviderBaseURL,omitempty"` + ClientID string `yaml:"clientId,omitempty"` +} + +type OFCTLS struct { + Enabled bool `yaml:"enabled"` + Email string `yaml:"email,omitempty"` + IssuerType string `yaml:"issuerType,omitempty"` + DNSService string `yaml:"dnsService,omitempty"` + Route53 OFCRoute53 `yaml:"route53,omitempty"` + Cloudflare OFCCloudflare `yaml:"cloudflare,omitempty"` + CloudDNS CloudDNSConfig `yaml:"clouddns,omitempty"` +} + +type CloudDNSConfig struct { + ProjectID string `yaml:"projectID,omitempty"` +} + +type OFCRoute53 struct { + Region string `yaml:"region,omitempty"` + AccessKeyID string `yaml:"accessKeyID,omitempty"` +} + +type OFCCloudflare struct { + Email string `yaml:"email,omitempty"` + ProjectID string `yaml:"projectID,omitempty"` +} + +type Ingress struct { + MaxConnections string `yaml:"maxConnections,omitempty"` + RequestsPerMinute string `yaml:"requestsPerMinute,omitempty"` +} + +type Customers struct { + URL string `yaml:"url,omitempty"` + CustomersSecret bool `yaml:"customersSecret,omitempty"` +} + +type Global struct { + RootDomain string `yaml:"rootDomain,omitempty"` + EnableECR bool `yaml:"enableECR,omitempty"` +} diff --git a/scripts/clone-cloud-components.sh b/scripts/clone-cloud-components.sh index 781ed24..bdeb8b3 100755 --- a/scripts/clone-cloud-components.sh +++ b/scripts/clone-cloud-components.sh @@ -2,7 +2,7 @@ rm -rf ./tmp/openfaas-cloud -git clone https://github.com/openfaas/openfaas-cloud ./tmp/openfaas-cloud +git clone https://github.com/openfaas/openfaas-cloud --depth 1 ./tmp/openfaas-cloud cd ./tmp/openfaas-cloud echo "Checking out openfaas/openfaas-cloud@$TAG" diff --git a/scripts/deploy-cloud-components.sh b/scripts/deploy-cloud-components.sh index a4af600..d90de0a 100755 --- a/scripts/deploy-cloud-components.sh +++ b/scripts/deploy-cloud-components.sh @@ -1,38 +1,17 @@ #!/bin/bash + + cp ./tmp/generated-gateway_config.yml ./tmp/openfaas-cloud/gateway_config.yml cp ./tmp/generated-github.yml ./tmp/openfaas-cloud/github.yml cp ./tmp/generated-slack.yml ./tmp/openfaas-cloud/slack.yml cp ./tmp/generated-dashboard_config.yml ./tmp/openfaas-cloud/dashboard/dashboard_config.yml cp ./tmp/generated-aws.yml ./tmp/openfaas-cloud/aws.yml -kubectl apply -f ./tmp/openfaas-cloud/yaml/core/of-builder-svc.yml - -# Update builder for any ECR secrets needed -cp ./tmp/generated-of-builder-dep.yml ./tmp/openfaas-cloud/yaml/core/of-builder-dep.yml -kubectl apply -f ./tmp/openfaas-cloud/yaml/core/of-builder-dep.yml - -kubectl apply -f ./tmp/openfaas-cloud/yaml/core/rbac-import-secrets.yml - -if [ "$ENABLE_OAUTH" = "true" ] ; then - cp ./tmp/generated-edge-auth-dep.yml ./tmp/openfaas-cloud/yaml/core/edge-auth-dep.yml - kubectl apply -f ./tmp/openfaas-cloud/yaml/core/edge-auth-dep.yml - kubectl apply -f ./tmp/openfaas-cloud/yaml/core/edge-auth-svc.yml - kubectl apply -f ./tmp/openfaas-cloud/yaml/core/edge-router-dep.yml -else - # Disable auth service by pointing the router at the echo function: - sed s/edge-auth.openfaas/echo.openfaas-fn/g ./tmp/openfaas-cloud/yaml/core/edge-router-dep.yml | kubectl apply -f - -fi - -kubectl apply -f ./tmp/openfaas-cloud/yaml/core/edge-router-svc.yml - -kubectl apply -f ./tmp/openfaas-cloud/yaml/core/edge-auth-svc.yml +cd ./tmp/openfaas-cloud -if [ "$ENABLE_NETWORK_POLICIES" = "true" ] ; then - kubectl apply -f ./tmp/openfaas-cloud/yaml/network-policy/ -fi -cd ./tmp/openfaas-cloud +helm upgrade --install --values ../ofc-values.yaml ofc-core ./chart/openfaas-cloud echo "Creating payload-secret in openfaas-fn" @@ -86,9 +65,5 @@ faas-cli deploy sleep 2 -# This `ServiceAccount` needs to be patched in place so that the function can perform create / get and update on the SealedSecret CRD: -#kubectl patch -n openfaas-fn deploy import-secrets -p '{"spec":{"template":{"spec":{"serviceAccountName":"sealedsecrets-importer-rw"}}}}' -# This is now applied through an annotation in stack.yml - # Close the kubectl port-forward kill %1