github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/pkg/bindings/containers/exec.go (about)

     1  package containers
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"net/http"
     7  	"strings"
     8  
     9  	"github.com/hanks177/podman/v4/libpod/define"
    10  	"github.com/hanks177/podman/v4/pkg/api/handlers"
    11  	"github.com/hanks177/podman/v4/pkg/bindings"
    12  	"github.com/hanks177/podman/v4/pkg/domain/entities"
    13  	jsoniter "github.com/json-iterator/go"
    14  	"github.com/pkg/errors"
    15  	"github.com/sirupsen/logrus"
    16  )
    17  
    18  var json = jsoniter.ConfigCompatibleWithStandardLibrary
    19  
    20  // ExecCreate creates a new exec session in an existing container.
    21  // The exec session will not be started; that is done with ExecStart.
    22  // Returns ID of new exec session, or an error if one occurred.
    23  func ExecCreate(ctx context.Context, nameOrID string, config *handlers.ExecCreateConfig) (string, error) {
    24  	conn, err := bindings.GetClient(ctx)
    25  	if err != nil {
    26  		return "", err
    27  	}
    28  
    29  	if config == nil {
    30  		return "", errors.Errorf("must provide a configuration for exec session")
    31  	}
    32  
    33  	requestJSON, err := json.Marshal(config)
    34  	if err != nil {
    35  		return "", errors.Wrapf(err, "error marshalling exec config to JSON")
    36  	}
    37  	jsonReader := strings.NewReader(string(requestJSON))
    38  
    39  	resp, err := conn.DoRequest(ctx, jsonReader, http.MethodPost, "/containers/%s/exec", nil, nil, nameOrID)
    40  	if err != nil {
    41  		return "", err
    42  	}
    43  	defer resp.Body.Close()
    44  
    45  	respStruct := new(entities.IDResponse)
    46  	if err := resp.Process(respStruct); err != nil {
    47  		return "", err
    48  	}
    49  
    50  	return respStruct.ID, nil
    51  }
    52  
    53  // ExecInspect inspects an existing exec session, returning detailed information
    54  // about it.
    55  func ExecInspect(ctx context.Context, sessionID string, options *ExecInspectOptions) (*define.InspectExecSession, error) {
    56  	if options == nil {
    57  		options = new(ExecInspectOptions)
    58  	}
    59  	_ = options
    60  	conn, err := bindings.GetClient(ctx)
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  
    65  	logrus.Debugf("Inspecting session ID %q", sessionID)
    66  
    67  	resp, err := conn.DoRequest(ctx, nil, http.MethodGet, "/exec/%s/json", nil, nil, sessionID)
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  	defer resp.Body.Close()
    72  
    73  	respStruct := new(define.InspectExecSession)
    74  	if err := resp.Process(respStruct); err != nil {
    75  		return nil, err
    76  	}
    77  
    78  	return respStruct, nil
    79  }
    80  
    81  // ExecStart starts (but does not attach to) a given exec session.
    82  func ExecStart(ctx context.Context, sessionID string, options *ExecStartOptions) error {
    83  	if options == nil {
    84  		options = new(ExecStartOptions)
    85  	}
    86  	_ = options
    87  	conn, err := bindings.GetClient(ctx)
    88  	if err != nil {
    89  		return err
    90  	}
    91  
    92  	logrus.Debugf("Starting exec session ID %q", sessionID)
    93  
    94  	// We force Detach to true
    95  	body := struct {
    96  		Detach bool `json:"Detach"`
    97  	}{
    98  		Detach: true,
    99  	}
   100  	bodyJSON, err := json.Marshal(body)
   101  	if err != nil {
   102  		return err
   103  	}
   104  
   105  	resp, err := conn.DoRequest(ctx, bytes.NewReader(bodyJSON), http.MethodPost, "/exec/%s/start", nil, nil, sessionID)
   106  	if err != nil {
   107  		return err
   108  	}
   109  	defer resp.Body.Close()
   110  
   111  	return resp.Process(nil)
   112  }