func (c *Client) ExecuteWorkflow(ctx context.Context, input requests.CreateWorkflow) (responses.ExecuteWorkflow, error) {
	url := fmt.Sprintf("%s/workflows", c.endpoint)
	reqBody, err := json.Marshal(input)
	if err != nil {
		return responses.ExecuteWorkflow{}, fmt.Errorf("unable to create api request body, error: %w", err)
	}
	req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewBuffer(reqBody))
	if err != nil {
		return responses.ExecuteWorkflow{}, fmt.Errorf("unable to create api request: %w", err)
	}
	req.Header.Add("Authorization", c.authToken)
	resp, err := c.httpClient.Do(req)
	if err != nil {
		return responses.ExecuteWorkflow{}, fmt.Errorf("unable to make api call: %w", err)
	}
	defer resp.Body.Close()
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return responses.ExecuteWorkflow{}, fmt.Errorf("error reading response body. status code: %d, error: %w", resp.StatusCode, err)
	}
	if resp.StatusCode >= 300 || resp.StatusCode < 200 {
		return responses.ExecuteWorkflow{}, fmt.Errorf("received unexpected status code: %d, body: %s", resp.StatusCode, string(body))
	}
	var output responses.ExecuteWorkflow
	if err := json.Unmarshal(body, &output); err != nil {
		return responses.ExecuteWorkflow{}, fmt.Errorf("unable to parse response: %w", err)
	}
	return output, nil
}
ExecuteWorkflow submits a workflow execution request.
package api
import (
	"bytes"
	"context"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"strings"
	"time"
	"github.com/argoproj-labs/argo-cloudops/internal/requests"
	"github.com/argoproj-labs/argo-cloudops/internal/responses"
)
const (
	diff                  = "diff"
	defaultLocalSecureURI = "https://localhost:8443"
	sync                  = "sync"
)
type httpClient interface {
	Do(req *http.Request) (*http.Response, error)
}
type Client struct {
	authToken  string
	httpClient httpClient
	endpoint   string
}
func NewClient(endpoint, authToken string) Client {
	tr := &http.Transport{}
	if endpoint == defaultLocalSecureURI {
		tr.TLSClientConfig = &tls.Config{
			InsecureSkipVerify: true,
		}
	}
	return Client{
		authToken:  authToken,
		endpoint:   endpoint,
		httpClient: &http.Client{Transport: tr},
	}
}
type TargetOperationInput struct {
	Path        string
	ProjectName string
	SHA         string
	TargetName  string
}
func (c *Client) GetLogs(ctx context.Context, workflowName string) (responses.GetLogs, error) {
	url := fmt.Sprintf("%s/workflows/%s/logs", c.endpoint, workflowName)
	body, err := c.getRequest(ctx, url)
	if err != nil {
		return responses.GetLogs{}, err
	}
	var output responses.GetLogs
	if err := json.Unmarshal(body, &output); err != nil {
		return responses.GetLogs{}, fmt.Errorf("unable to parse response: %w", err)
	}
	return output, nil
}
func (c *Client) StreamLogs(ctx context.Context, w io.Writer, workflowName string) error {
	var loggingCursorByte int64
	for i := 0; i < 10; i++ {
		err := c.streamLogsToWriterAtCursor(ctx, w, workflowName, &loggingCursorByte)
		if err != nil {
			if strings.Contains(err.Error(), "stream error: stream ID 1; INTERNAL_ERROR") || strings.Contains(err.Error(), "stream error: stream ID 3; INTERNAL_ERROR") {
				time.Sleep(time.Second * 10)
				continue
			}
			return err
		}
		break
	}
	return nil
}
func (c *Client) streamLogsToWriterAtCursor(ctx context.Context, w io.Writer, workflowName string, loggingCursorByte *int64) error {
	url := fmt.Sprintf("%s/workflows/%s/logstream", c.endpoint, workflowName)
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
	if err != nil {
		return fmt.Errorf("unable to create api request: %w", err)
	}
	resp, err := c.httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("unable to make api call: %w", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("received unexpected status code: %d", resp.StatusCode)
	}
	if _, err := io.CopyN(ioutil.Discard, resp.Body, *loggingCursorByte); err != nil {
		return err
	}
	writtenBytes, err := io.Copy(w, resp.Body)
	if err != nil {
		*loggingCursorByte += writtenBytes
		return fmt.Errorf("error reading response body. status code: %d, error: %w", resp.StatusCode, err)
	}
	return nil
}
func (c *Client) GetWorkflowStatus(ctx context.Context, workflowName string) (responses.GetWorkflowStatus, error) {
	url := fmt.Sprintf("%s/workflows/%s", c.endpoint, workflowName)
	body, err := c.getRequest(ctx, url)
	if err != nil {
		return responses.GetWorkflowStatus{}, err
	}
	var output responses.GetWorkflowStatus
	if err := json.Unmarshal(body, &output); err != nil {
		return responses.GetWorkflowStatus{}, fmt.Errorf("unable to parse response: %w", err)
	}
	return output, nil
}
func (c *Client) GetWorkflows(ctx context.Context, project, target string) (responses.GetWorkflows, error) {
	url := fmt.Sprintf("%s/projects/%s/targets/%s/workflows", c.endpoint, project, target)
	body, err := c.getRequest(ctx, url)
	if err != nil {
		return responses.GetWorkflows{}, err
	}
	var output responses.GetWorkflows
	if err := json.Unmarshal(body, &output); err != nil {
		return responses.GetWorkflows{}, fmt.Errorf("unable to parse response: %w", err)
	}
	return output, nil
}
func (c *Client) Diff(ctx context.Context, input TargetOperationInput) (responses.Diff, error) {
	output, err := c.targetOperation(ctx, input, diff)
	if err != nil {
		return responses.Diff{}, err
	}
	return responses.Diff(output), nil
}