Skip to content

Commit

Permalink
Add RegistryIngress to apps
Browse files Browse the repository at this point in the history
We can now build registry-ingress using cert-manager using the
docker-registry-ingress command and passing the flags.

This was tested with the help of @alexellis where i setup the registry on my
laptop using inlets-operator and alex connected using https to push & pull
images

Signed-off-by: Alistair Hey <[email protected]>
  • Loading branch information
Waterdrips authored and alexellis committed Feb 12, 2020
1 parent 39a6664 commit 72de7fa
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 14 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ k3sup app install nginx-ingress

# docker-registry - host your own registry
k3sup app install docker-registry

# docker-registry-ingress - add TLS to your registry and ingress on port 443 and 80
k3sup app install docker-registry-ingress --email [email protected] --domain reg.example.com
```

Find out more with:
Expand Down
3 changes: 3 additions & 0 deletions cmd/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ command.`,
install.AddCommand(apps.MakeInstallCrossplane())
install.AddCommand(apps.MakeInstallMongoDB())
install.AddCommand(apps.MakeInstallRegistry())
install.AddCommand(apps.MakeInstallRegistryIngress())

command.AddCommand(MakeInfo())

Expand All @@ -88,5 +89,7 @@ func getApps() []string {
"istio",
"crosspane",
"mongodb",
"docker-registry",
"docker-registry-ingress",
}
}
6 changes: 3 additions & 3 deletions cmd/apps/openfaas_ingress_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func MakeInstallOpenFaaSIngress() *cobra.Command {
return templateErr
}

tempFile, tempFileErr := writeTempFile(yamlBytes)
tempFile, tempFileErr := writeTempFile(yamlBytes, "temp_openfaas_ingress.yaml")
if tempFileErr != nil {
log.Print("Unable to save generated yaml file into the temporary directory")
return tempFileErr
Expand Down Expand Up @@ -104,13 +104,13 @@ func createTempDirectory(directory string) (string, error) {
return tempDirectory, nil
}

func writeTempFile(input []byte) (string, error) {
func writeTempFile(input []byte, fileLocation string) (string, error) {
var tempDirectory, dirErr = createTempDirectory(".k3sup/")
if dirErr != nil {
return "", dirErr
}

filename := filepath.Join(tempDirectory, "temp_openfaas_ingress.yaml")
filename := filepath.Join(tempDirectory, fileLocation)

err := ioutil.WriteFile(filename, input, 0744)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion cmd/apps/openfaas_ingress_app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ spec:

func Test_writeTempFile_writes_to_tmp(t *testing.T) {
var want = "some input string"
tmpLocation, _ := writeTempFile([]byte(want))
tmpLocation, _ := writeTempFile([]byte(want), "tmp_file_name.yaml")

got, _ := ioutil.ReadFile(tmpLocation)
if string(got) != want {
Expand Down
16 changes: 6 additions & 10 deletions cmd/apps/registry_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,6 @@ func MakeInstallRegistry() *cobra.Command {
registry.Flags().StringP("username", "u", "admin", "Username for the registry")
registry.Flags().StringP("password", "p", "", "Password for the registry, leave blank to generate")

// Flags for generating an Ingress record like openfaas-ingress
// registry.Flags().String("issuer", "", "Cert-manager issuer")
// registry.Flags().String("cluster-issuer", "", "Cert-manager cluster-issuer")
// registry.Flags().String("domain", "", "Domain for an Ingress record")
// registry.Flags().String("ingress-class", "nginx", "Ingress class (required for --domain)")

registry.RunE = func(command *cobra.Command, args []string) error {
kubeConfigPath := getDefaultKubeconfig()

Expand All @@ -51,6 +45,7 @@ func MakeInstallRegistry() *cobra.Command {

if helm3 {
fmt.Println("Using helm3")
os.Setenv("HELM_VERSION", helm3Version)
}

userPath, err := config.InitUserDir()
Expand All @@ -69,6 +64,7 @@ func MakeInstallRegistry() *cobra.Command {

os.Setenv("HELM_HOME", path.Join(userPath, ".helm"))


_, err = helm.TryDownloadHelm(userPath, clientArch, clientOS, helm3)
if err != nil {
return err
Expand Down Expand Up @@ -157,7 +153,7 @@ func MakeInstallRegistry() *cobra.Command {
}
}

fmt.Println(registryIngressInstallMsg)
fmt.Println(registryInstallMsg)
fmt.Printf("Registry credentials: %s %s\nexport PASSWORD=%s\n", username, pass, pass)

return nil
Expand All @@ -166,7 +162,7 @@ func MakeInstallRegistry() *cobra.Command {
return registry
}

const registryIngressInfoMsg = `# Your docker-registry has been configured
const registryInfoMsg = `# Your docker-registry has been configured
kubectl logs deploy/docker-registry
Expand All @@ -181,7 +177,7 @@ docker push $IP:5000/alpine:3.11
# Find out more at:
# https://github.com/helm/charts/tree/master/stable/registry`

const registryIngressInstallMsg = `=======================================================================
const registryInstallMsg = `=======================================================================
= docker-registry has been installed. =
=======================================================================` +
"\n\n" + registryIngressInfoMsg + "\n\n" + pkg.ThanksForUsing
"\n\n" + registryInfoMsg + "\n\n" + pkg.ThanksForUsing
188 changes: 188 additions & 0 deletions cmd/apps/registry_ingress_app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
package apps

import (
"bytes"
"errors"
"fmt"
"log"

"text/template"

"github.com/alexellis/k3sup/pkg"

"github.com/spf13/cobra"
)

type RegInputData struct {
IngressDomain string
CertmanagerEmail string
IngressClass string
Namespace string
MaxSize string
}

func MakeInstallRegistryIngress() *cobra.Command {
var registryIngress = &cobra.Command{
Use: "docker-registry-ingress",
Short: "Install registry ingress with TLS",
Long: `Install registry ingress. Requires cert-manager 0.11.0 or higher installation in the cluster. Please set --domain to your custom domain and set --email to your email - this email is used by letsencrypt for domain expiry etc.`,
Example: ` k3sup app install registry-ingress --domain registry.example.com --email [email protected]`,
SilenceUsage: true,
}

registryIngress.Flags().StringP("domain", "d", "", "Custom Ingress Domain")
registryIngress.Flags().StringP("email", "e", "", "Letsencrypt Email")
registryIngress.Flags().String("ingress-class", "nginx", "Ingress class to be used such as nginx or traefik")
registryIngress.Flags().String("max-size", "200m", "the max size for the ingress proxy, default to 200m")
registryIngress.Flags().StringP("namespace", "n", "default", "The namespace where the registry is installed")

registryIngress.RunE = func(command *cobra.Command, args []string) error {

email, _ := command.Flags().GetString("email")
domain, _ := command.Flags().GetString("domain")
ingressClass, _ := command.Flags().GetString("ingress-class")
namespace, _ := command.Flags().GetString("namespace")
maxSize, _ := command.Flags().GetString("max-size")

if email == "" || domain == "" {
return errors.New("both --email and --domain flags should be set and not empty, please set these values")
}

if ingressClass == "" {
return errors.New("--ingress-class must be set")
}

kubeConfigPath := getDefaultKubeconfig()

if command.Flags().Changed("kubeconfig") {
kubeConfigPath, _ = command.Flags().GetString("kubeconfig")
}

fmt.Printf("Using kubeconfig: %s\n", kubeConfigPath)

yamlBytes, templateErr := buildRegistryYAML(domain, email, ingressClass, namespace, maxSize)
if templateErr != nil {
log.Print("Unable to install the application. Could not build the templated yaml file for the resources")
return templateErr
}

tempFile, tempFileErr := writeTempFile(yamlBytes, "temp_registry_ingress.yaml")
if tempFileErr != nil {
log.Print("Unable to save generated yaml file into the temporary directory")
return tempFileErr
}

res, err := kubectlTask("apply", "-f", tempFile)

if err != nil {
log.Print(err)
return err
}

if res.ExitCode != 0 {
return fmt.Errorf(`Unable to apply YAML files.
Have you got the Registry running and cert-manager 0.11.0 or higher installed? %s`,
res.Stderr)
}

fmt.Println(RegistryIngressInstallMsg)

return nil
}

return registryIngress
}

func buildRegistryYAML(domain, email, ingressClass, namespace, maxSize string) ([]byte, error) {
tmpl, err := template.New("yaml").Parse(registryIngressYamlTemplate)

if err != nil {
return nil, err
}

inputData := RegInputData{
IngressDomain: domain,
CertmanagerEmail: email,
IngressClass: ingressClass,
Namespace: namespace,
MaxSize: maxSize,
}

var tpl bytes.Buffer

err = tmpl.Execute(&tpl, inputData)

if err != nil {
return nil, err
}

return tpl.Bytes(), nil
}

const RegistryIngressInfoMsg = `# You will need to ensure that your domain points to your cluster and is
# accessible through ports 80 and 443.
#
# This is used to validate your ownership of this domain by LetsEncrypt
# and then you can use https with your installation.
# Ingress to your domain has been installed for the Registry
# to see the ingress record run
kubectl get -n <installed-namespace> ingress docker-registry
# Check the cert-manager logs with:
kubectl logs -n cert-manager deploy/cert-manager
# A cert-manager ClusterIssuer has been installed into the provided
# namespace - to see the resource run
kubectl describe -n <installed-namespace> ClusterIssuer letsencrypt-prod-registry
# To check the status of your certificate you can run
kubectl describe -n <installed-namespace> Certificate docker-registry
# It may take a while to be issued by LetsEncrypt, in the meantime a
# self-signed cert will be installed`

const RegistryIngressInstallMsg = `=======================================================================
= Docker Registry Ingress and cert-manager ClusterIssuer have been installed =
=======================================================================` +
"\n\n" + RegistryIngressInfoMsg + "\n\n" + pkg.ThanksForUsing

var registryIngressYamlTemplate = `
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: docker-registry
namespace: {{.Namespace}}
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod-registry
kubernetes.io/ingress.class: {{.IngressClass}}
nginx.ingress.kubernetes.io/proxy-body-size: {{.MaxSize}}
spec:
rules:
- host: {{.IngressDomain}}
http:
paths:
- backend:
serviceName: docker-registry
servicePort: 5000
path: /
tls:
- hosts:
- {{.IngressDomain}}
secretName: docker-registry
---
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
name: letsencrypt-prod-registry
namespace: {{.Namespace}}
spec:
acme:
email: {{.CertmanagerEmail}}
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-prod-registry
solvers:
- http01:
ingress:
class: {{.IngressClass}}`
3 changes: 3 additions & 0 deletions cmd/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ k3sup app info --help`,
case "crossplane":
fmt.Printf("Info for app: %s\n", appName)
fmt.Println(apps.CrossplanInfoMsg)
case "docker-registry-ingress":
fmt.Printf("Info for app: %s\n", appName)
fmt.Println(apps.RegistryIngressInfoMsg)
default:
return fmt.Errorf("no info available for app: %s", appName)
}
Expand Down

0 comments on commit 72de7fa

Please sign in to comment.