github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/cmd/puppeth/module_nginx.go (about) 1 // Copyright 2017 The Spectrum Authors 2 // This file is part of Spectrum. 3 // 4 // Spectrum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Spectrum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Spectrum. If not, see <http://www.gnu.org/licenses/>. 16 17 package main 18 19 import ( 20 "bytes" 21 "fmt" 22 "html/template" 23 "math/rand" 24 "path/filepath" 25 "strconv" 26 27 "github.com/SmartMeshFoundation/Spectrum/log" 28 ) 29 30 // nginxDockerfile is theis the Dockerfile required to build an nginx reverse- 31 // proxy. 32 var nginxDockerfile = `FROM jwilder/nginx-proxy` 33 34 // nginxComposefile is the docker-compose.yml file required to deploy and maintain 35 // an nginx reverse-proxy. The proxy is responsible for exposing one or more HTTP 36 // services running on a single host. 37 var nginxComposefile = ` 38 version: '2' 39 services: 40 nginx: 41 build: . 42 image: {{.Network}}/nginx 43 ports: 44 - "{{.Port}}:80" 45 volumes: 46 - /var/run/docker.sock:/tmp/docker.sock:ro 47 logging: 48 driver: "json-file" 49 options: 50 max-size: "1m" 51 max-file: "10" 52 restart: always 53 ` 54 55 // deployNginx deploys a new nginx reverse-proxy container to expose one or more 56 // HTTP services running on a single host. If an instance with the specified 57 // network name already exists there, it will be overwritten! 58 func deployNginx(client *sshClient, network string, port int, nocache bool) ([]byte, error) { 59 log.Info("Deploying nginx reverse-proxy", "server", client.server, "port", port) 60 61 // Generate the content to upload to the server 62 workdir := fmt.Sprintf("%d", rand.Int63()) 63 files := make(map[string][]byte) 64 65 dockerfile := new(bytes.Buffer) 66 template.Must(template.New("").Parse(nginxDockerfile)).Execute(dockerfile, nil) 67 files[filepath.Join(workdir, "Dockerfile")] = dockerfile.Bytes() 68 69 composefile := new(bytes.Buffer) 70 template.Must(template.New("").Parse(nginxComposefile)).Execute(composefile, map[string]interface{}{ 71 "Network": network, 72 "Port": port, 73 }) 74 files[filepath.Join(workdir, "docker-compose.yaml")] = composefile.Bytes() 75 76 // Upload the deployment files to the remote server (and clean up afterwards) 77 if out, err := client.Upload(files); err != nil { 78 return out, err 79 } 80 defer client.Run("rm -rf " + workdir) 81 82 // Build and deploy the reverse-proxy service 83 if nocache { 84 return nil, client.Stream(fmt.Sprintf("cd %s && docker-compose -p %s build --pull --no-cache && docker-compose -p %s up -d --force-recreate", workdir, network, network)) 85 } 86 return nil, client.Stream(fmt.Sprintf("cd %s && docker-compose -p %s up -d --build --force-recreate", workdir, network)) 87 } 88 89 // nginxInfos is returned from an nginx reverse-proxy status check to allow 90 // reporting various configuration parameters. 91 type nginxInfos struct { 92 port int 93 } 94 95 // Report converts the typed struct into a plain string->string map, containing 96 // most - but not all - fields for reporting to the user. 97 func (info *nginxInfos) Report() map[string]string { 98 return map[string]string{ 99 "Shared listener port": strconv.Itoa(info.port), 100 } 101 } 102 103 // checkNginx does a health-check against an nginx reverse-proxy to verify whether 104 // it's running, and if yes, gathering a collection of useful infos about it. 105 func checkNginx(client *sshClient, network string) (*nginxInfos, error) { 106 // Inspect a possible nginx container on the host 107 infos, err := inspectContainer(client, fmt.Sprintf("%s_nginx_1", network)) 108 if err != nil { 109 return nil, err 110 } 111 if !infos.running { 112 return nil, ErrServiceOffline 113 } 114 // Container available, assemble and return the useful infos 115 return &nginxInfos{ 116 port: infos.portmap["80/tcp"], 117 }, nil 118 }