github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/cmd/puppeth/module_nginx.go (about)

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