github.com/hyperledger-labs/bdls@v2.1.1+incompatible/integration/nwo/buildserver.go (about)

     1  /*
     2  Copyright IBM Corp All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package nwo
     8  
     9  import (
    10  	"context"
    11  	"fmt"
    12  	"net"
    13  	"net/http"
    14  	"strings"
    15  	"sync"
    16  	"time"
    17  
    18  	"github.com/hyperledger/fabric/integration/helpers"
    19  
    20  	. "github.com/onsi/gomega"
    21  	"github.com/onsi/gomega/gexec"
    22  )
    23  
    24  type BuildServer struct {
    25  	server *http.Server
    26  	lis    net.Listener
    27  }
    28  
    29  func NewBuildServer(args ...string) *BuildServer {
    30  	return &BuildServer{
    31  		server: &http.Server{
    32  			Handler: &buildHandler{args: args},
    33  		},
    34  	}
    35  }
    36  
    37  func (s *BuildServer) Serve() {
    38  	lis, err := net.Listen("tcp", "127.0.0.1:0")
    39  	Expect(err).NotTo(HaveOccurred())
    40  
    41  	s.lis = lis
    42  	go s.server.Serve(lis)
    43  }
    44  
    45  func (s *BuildServer) Shutdown() {
    46  	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
    47  	defer cancel()
    48  	defer gexec.CleanupBuildArtifacts()
    49  
    50  	s.server.Shutdown(ctx)
    51  }
    52  
    53  func (s *BuildServer) Components() *Components {
    54  	Expect(s.lis).NotTo(BeNil())
    55  
    56  	helpers.AssertImagesExist(RequiredImages...)
    57  
    58  	return &Components{
    59  		ServerAddress: s.lis.Addr().String(),
    60  	}
    61  }
    62  
    63  type artifact struct {
    64  	mutex  sync.Mutex
    65  	input  string
    66  	output string
    67  }
    68  
    69  func (a *artifact) build(args ...string) error {
    70  	a.mutex.Lock()
    71  	defer a.mutex.Unlock()
    72  
    73  	if a.output != "" {
    74  		return nil
    75  	}
    76  
    77  	output, err := gexec.Build(a.input, args...)
    78  	if err != nil {
    79  		return err
    80  	}
    81  
    82  	a.output = output
    83  	return nil
    84  }
    85  
    86  type buildHandler struct {
    87  	mutex     sync.Mutex
    88  	artifacts map[string]*artifact
    89  	args      []string
    90  }
    91  
    92  func (b *buildHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    93  	if req.Method != http.MethodGet {
    94  		w.WriteHeader(http.StatusBadRequest)
    95  		return
    96  	}
    97  
    98  	input := strings.TrimPrefix(req.URL.Path, "/")
    99  	a := b.artifact(input)
   100  
   101  	if err := a.build(b.args...); err != nil {
   102  		w.WriteHeader(http.StatusInternalServerError)
   103  		fmt.Fprintf(w, "%s", err)
   104  		return
   105  	}
   106  
   107  	w.WriteHeader(http.StatusOK)
   108  	fmt.Fprintf(w, "%s", a.output)
   109  }
   110  
   111  func (b *buildHandler) artifact(input string) *artifact {
   112  	b.mutex.Lock()
   113  	defer b.mutex.Unlock()
   114  
   115  	if b.artifacts == nil {
   116  		b.artifacts = map[string]*artifact{}
   117  	}
   118  
   119  	a, ok := b.artifacts[input]
   120  	if !ok {
   121  		a = &artifact{input: input}
   122  		b.artifacts[input] = a
   123  	}
   124  
   125  	return a
   126  }