github.com/nvkalinin/business-calendar@v1.0.2-0.20220515154925-e7df8a3d0c34/cmd/sync.go (about)

     1  package cmd
     2  
     3  import (
     4  	"encoding/json"
     5  	"io"
     6  	"net/http"
     7  	"net/url"
     8  	"strconv"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/nvkalinin/business-calendar/log"
    13  )
    14  
    15  type Sync struct {
    16  	ServerUrl   string        `long:"server-url" short:"s" env:"SERVER_URL" value-name:"str" default:"http://localhost" description:"URL сервера с REST API календаря."`
    17  	AdminPasswd string        `long:"passwd" short:"p" env:"WEB_ADMIN_PASSWD" value-name:"str" description:"Пароль пользователя admin."`
    18  	Timeout     time.Duration `long:"timeout" short:"t" env:"TIMEOUT" value-name:"duration" default:"60s" description:"Макс. время выполнения запроса."`
    19  	Years       []int         `long:"year" short:"y" env:"YEAR" value-name:"int" required:"true" description:"Год, за который нужно синхронизировать календарь. Можно указывать несколько раз."`
    20  }
    21  
    22  func (s *Sync) Execute(args []string) error {
    23  	ystr := make([]string, len(s.Years))
    24  	for i, y := range s.Years {
    25  		ystr[i] = strconv.Itoa(y)
    26  	}
    27  
    28  	params := url.Values{"y": ystr}
    29  	body := strings.NewReader(params.Encode())
    30  
    31  	url := makeUrl(s.ServerUrl, "/api/admin/sync")
    32  	req, err := http.NewRequest(http.MethodPost, url, body)
    33  	if err != nil {
    34  		log.Fatalf("[ERROR] cannot make request: %v", err)
    35  	}
    36  	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
    37  	req.SetBasicAuth("admin", s.AdminPasswd)
    38  	log.Printf("[DEBUG] sync request: URL=%s, %#v", url, req)
    39  
    40  	client := &http.Client{
    41  		Timeout: s.Timeout,
    42  	}
    43  	resp, err := client.Do(req)
    44  	if err != nil {
    45  		log.Fatalf("[ERROR] cannot make request: %v", err)
    46  	}
    47  	defer func() {
    48  		if err := resp.Body.Close(); err != nil {
    49  			log.Printf("[WARN] cannot close response: %v", err)
    50  		}
    51  	}()
    52  	log.Printf("[DEBUG] sync response: %#v", resp)
    53  
    54  	respBody, err := io.ReadAll(resp.Body)
    55  	if err != nil {
    56  		log.Fatalf("[ERROR] cannot read response: %v", err)
    57  	}
    58  	log.Printf("[DEBUG] sync resp body: %v", respBody)
    59  
    60  	if resp.StatusCode != 200 {
    61  		err := readJsonError(respBody)
    62  		log.Fatalf("[ERROR] sync error (status %d): %v", resp.StatusCode, err)
    63  	}
    64  
    65  	res := map[int]string{}
    66  	if err := json.Unmarshal(respBody, &res); err != nil {
    67  		log.Fatalf("[ERROR] cannot parse response (status %d): %v", resp.StatusCode, err)
    68  	}
    69  
    70  	for y, syncRes := range res {
    71  		if syncRes == "ok" {
    72  			log.Printf("[INFO] year %d: ok", y)
    73  		} else {
    74  			log.Printf("[ERROR] year %d: %s", y, syncRes)
    75  		}
    76  	}
    77  	return nil
    78  }