podman
156 строк · 3.8 Кб
1package containers2
3import (4"bytes"5"context"6"errors"7"fmt"8"net/http"9"strings"10
11"github.com/containers/podman/v5/libpod/define"12"github.com/containers/podman/v5/pkg/api/handlers"13"github.com/containers/podman/v5/pkg/bindings"14dockerAPI "github.com/docker/docker/api/types"15jsoniter "github.com/json-iterator/go"16"github.com/sirupsen/logrus"17)
18
19var json = jsoniter.ConfigCompatibleWithStandardLibrary20
21// ExecCreate creates a new exec session in an existing container.
22// The exec session will not be started; that is done with ExecStart.
23// Returns ID of new exec session, or an error if one occurred.
24func ExecCreate(ctx context.Context, nameOrID string, config *handlers.ExecCreateConfig) (string, error) {25conn, err := bindings.GetClient(ctx)26if err != nil {27return "", err28}29
30if config == nil {31return "", errors.New("must provide a configuration for exec session")32}33
34requestJSON, err := json.Marshal(config)35if err != nil {36return "", fmt.Errorf("marshalling exec config to JSON: %w", err)37}38jsonReader := strings.NewReader(string(requestJSON))39
40resp, err := conn.DoRequest(ctx, jsonReader, http.MethodPost, "/containers/%s/exec", nil, nil, nameOrID)41if err != nil {42return "", err43}44defer resp.Body.Close()45
46respStruct := new(dockerAPI.IDResponse)47if err := resp.Process(respStruct); err != nil {48return "", err49}50
51return respStruct.ID, nil52}
53
54// ExecInspect inspects an existing exec session, returning detailed information
55// about it.
56func ExecInspect(ctx context.Context, sessionID string, options *ExecInspectOptions) (*define.InspectExecSession, error) {57if options == nil {58options = new(ExecInspectOptions)59}60_ = options61conn, err := bindings.GetClient(ctx)62if err != nil {63return nil, err64}65
66logrus.Debugf("Inspecting session ID %q", sessionID)67
68resp, err := conn.DoRequest(ctx, nil, http.MethodGet, "/exec/%s/json", nil, nil, sessionID)69if err != nil {70return nil, err71}72defer resp.Body.Close()73
74respStruct := new(define.InspectExecSession)75if err := resp.Process(respStruct); err != nil {76return nil, err77}78
79return respStruct, nil80}
81
82// ExecStart starts (but does not attach to) a given exec session.
83func ExecStart(ctx context.Context, sessionID string, options *ExecStartOptions) error {84if options == nil {85options = new(ExecStartOptions)86}87_ = options88conn, err := bindings.GetClient(ctx)89if err != nil {90return err91}92
93logrus.Debugf("Starting exec session ID %q", sessionID)94
95// We force Detach to true96body := struct {97Detach bool `json:"Detach"`98}{99Detach: true,100}101bodyJSON, err := json.Marshal(body)102if err != nil {103return err104}105
106resp, err := conn.DoRequest(ctx, bytes.NewReader(bodyJSON), http.MethodPost, "/exec/%s/start", nil, nil, sessionID)107if err != nil {108return err109}110defer resp.Body.Close()111
112return resp.Process(nil)113}
114
115// ExecRemove removes a given exec session.
116func ExecRemove(ctx context.Context, sessionID string, options *ExecRemoveOptions) error {117v := bindings.ServiceVersion(ctx)118// The exec remove endpoint was added in 4.8.119if v.Major < 4 || (v.Major == 4 && v.Minor < 8) {120// Do no call this endpoint as it will not be supported on the server and throw an "NOT FOUND" error.121return bindings.NewAPIVersionError("/exec/{id}/remove", v, "4.8.0")122}123if options == nil {124options = new(ExecRemoveOptions)125}126conn, err := bindings.GetClient(ctx)127if err != nil {128return err129}130
131logrus.Debugf("Removing exec session ID %q", sessionID)132
133// We force Detach to true134body := struct {135Force bool `json:"Force"`136}{137Force: false,138}139
140if options.Force != nil {141body.Force = *options.Force142}143
144bodyJSON, err := json.Marshal(body)145if err != nil {146return err147}148
149resp, err := conn.DoRequest(ctx, bytes.NewReader(bodyJSON), http.MethodPost, "/exec/%s/remove", nil, nil, sessionID)150if err != nil {151return err152}153defer resp.Body.Close()154
155return resp.Process(nil)156}
157