github.hscsec.cn/openshift/source-to-image@v1.2.0/pkg/util/callback.go (about)

     1  package util
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"encoding/json"
     7  	"fmt"
     8  	"io"
     9  	"net/http"
    10  )
    11  
    12  // CallbackInvoker posts results to a callback URL when a STI build is done.
    13  type CallbackInvoker interface {
    14  	ExecuteCallback(callbackURL string, success bool, labels map[string]string, messages []string) []string
    15  }
    16  
    17  // NewCallbackInvoker creates an instance of the default CallbackInvoker implementation
    18  func NewCallbackInvoker() CallbackInvoker {
    19  	invoker := &callbackInvoker{}
    20  	invoker.postFunc = invoker.httpPost
    21  	return invoker
    22  }
    23  
    24  type callbackInvoker struct {
    25  	postFunc func(url, contentType string, body io.Reader) (resp *http.Response, err error)
    26  }
    27  
    28  // ExecuteCallback prepares a JSON payload and posts it to the specified callback URL
    29  func (c *callbackInvoker) ExecuteCallback(callbackURL string, success bool, labels map[string]string, messages []string) []string {
    30  	buf := new(bytes.Buffer)
    31  	writer := bufio.NewWriter(buf)
    32  
    33  	data := map[string]interface{}{
    34  		"success": success,
    35  	}
    36  
    37  	if len(labels) > 0 {
    38  		data["labels"] = labels
    39  	}
    40  
    41  	jsonBuffer := new(bytes.Buffer)
    42  	writer = bufio.NewWriter(jsonBuffer)
    43  	jsonWriter := json.NewEncoder(writer)
    44  	jsonWriter.Encode(data)
    45  	writer.Flush()
    46  
    47  	var (
    48  		resp *http.Response
    49  		err  error
    50  	)
    51  	for retries := 0; retries < 3; retries++ {
    52  		resp, err = c.postFunc(callbackURL, "application/json", jsonBuffer)
    53  		if err != nil {
    54  			errorMessage := fmt.Sprintf("Unable to invoke callback: %v", err)
    55  			messages = append(messages, errorMessage)
    56  		}
    57  		if resp != nil {
    58  			if resp.StatusCode >= 300 {
    59  				errorMessage := fmt.Sprintf("Callback returned with error code: %d", resp.StatusCode)
    60  				messages = append(messages, errorMessage)
    61  			}
    62  			break
    63  		}
    64  	}
    65  	return messages
    66  }
    67  
    68  func (*callbackInvoker) httpPost(url, contentType string, body io.Reader) (resp *http.Response, err error) {
    69  	return http.Post(url, contentType, body)
    70  }