github.com/containers/podman/v4@v4.9.4/pkg/bindings/pods/pods.go (about)

     1  package pods
     2  
     3  import (
     4  	"context"
     5  	"net/http"
     6  	"net/url"
     7  	"strings"
     8  
     9  	"github.com/containers/podman/v4/pkg/api/handlers"
    10  	"github.com/containers/podman/v4/pkg/bindings"
    11  	"github.com/containers/podman/v4/pkg/domain/entities"
    12  	"github.com/containers/podman/v4/pkg/errorhandling"
    13  	jsoniter "github.com/json-iterator/go"
    14  )
    15  
    16  func CreatePodFromSpec(ctx context.Context, spec *entities.PodSpec) (*entities.PodCreateReport, error) {
    17  	var (
    18  		pcr entities.PodCreateReport
    19  	)
    20  	if spec == nil {
    21  		spec = new(entities.PodSpec)
    22  	}
    23  	conn, err := bindings.GetClient(ctx)
    24  	if err != nil {
    25  		return nil, err
    26  	}
    27  	specString, err := jsoniter.MarshalToString(spec.PodSpecGen)
    28  	if err != nil {
    29  		return nil, err
    30  	}
    31  	stringReader := strings.NewReader(specString)
    32  	response, err := conn.DoRequest(ctx, stringReader, http.MethodPost, "/pods/create", nil, nil)
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  	defer response.Body.Close()
    37  
    38  	return &pcr, response.Process(&pcr)
    39  }
    40  
    41  // Exists is a lightweight method to determine if a pod exists in local storage
    42  func Exists(ctx context.Context, nameOrID string, options *ExistsOptions) (bool, error) {
    43  	conn, err := bindings.GetClient(ctx)
    44  	if err != nil {
    45  		return false, err
    46  	}
    47  	response, err := conn.DoRequest(ctx, nil, http.MethodGet, "/pods/%s/exists", nil, nil, nameOrID)
    48  	if err != nil {
    49  		return false, err
    50  	}
    51  	defer response.Body.Close()
    52  
    53  	return response.IsSuccess(), nil
    54  }
    55  
    56  // Inspect returns low-level information about the given pod.
    57  func Inspect(ctx context.Context, nameOrID string, options *InspectOptions) (*entities.PodInspectReport, error) {
    58  	var (
    59  		report entities.PodInspectReport
    60  	)
    61  	if options == nil {
    62  		options = new(InspectOptions)
    63  	}
    64  	_ = options
    65  	conn, err := bindings.GetClient(ctx)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  	response, err := conn.DoRequest(ctx, nil, http.MethodGet, "/pods/%s/json", nil, nil, nameOrID)
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  	defer response.Body.Close()
    74  
    75  	return &report, response.Process(&report)
    76  }
    77  
    78  // Kill sends a SIGTERM to all the containers in a pod.  The optional signal parameter
    79  // can be used to override  SIGTERM.
    80  func Kill(ctx context.Context, nameOrID string, options *KillOptions) (*entities.PodKillReport, error) {
    81  	var (
    82  		report entities.PodKillReport
    83  	)
    84  	if options == nil {
    85  		options = new(KillOptions)
    86  	}
    87  	conn, err := bindings.GetClient(ctx)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  	params, err := options.ToParams()
    92  	if err != nil {
    93  		return nil, err
    94  	}
    95  	response, err := conn.DoRequest(ctx, nil, http.MethodPost, "/pods/%s/kill", params, nil, nameOrID)
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  	defer response.Body.Close()
   100  
   101  	return &report, response.ProcessWithError(&report, &errorhandling.PodConflictErrorModel{})
   102  }
   103  
   104  // Pause pauses all running containers in a given pod.
   105  func Pause(ctx context.Context, nameOrID string, options *PauseOptions) (*entities.PodPauseReport, error) {
   106  	var report entities.PodPauseReport
   107  	if options == nil {
   108  		options = new(PauseOptions)
   109  	}
   110  	_ = options
   111  	conn, err := bindings.GetClient(ctx)
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  	response, err := conn.DoRequest(ctx, nil, http.MethodPost, "/pods/%s/pause", nil, nil, nameOrID)
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  	defer response.Body.Close()
   120  
   121  	return &report, response.ProcessWithError(&report, &errorhandling.PodConflictErrorModel{})
   122  }
   123  
   124  // Prune by default removes all non-running pods in local storage.
   125  // And with force set true removes all pods.
   126  func Prune(ctx context.Context, options *PruneOptions) ([]*entities.PodPruneReport, error) {
   127  	var reports []*entities.PodPruneReport
   128  	if options == nil {
   129  		options = new(PruneOptions)
   130  	}
   131  	_ = options
   132  	conn, err := bindings.GetClient(ctx)
   133  	if err != nil {
   134  		return nil, err
   135  	}
   136  	response, err := conn.DoRequest(ctx, nil, http.MethodPost, "/pods/prune", nil, nil)
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  	defer response.Body.Close()
   141  
   142  	return reports, response.Process(&reports)
   143  }
   144  
   145  // List returns all pods in local storage.  The optional filters parameter can
   146  // be used to refine which pods should be listed.
   147  func List(ctx context.Context, options *ListOptions) ([]*entities.ListPodsReport, error) {
   148  	var (
   149  		podsReports []*entities.ListPodsReport
   150  	)
   151  	if options == nil {
   152  		options = new(ListOptions)
   153  	}
   154  	conn, err := bindings.GetClient(ctx)
   155  	if err != nil {
   156  		return nil, err
   157  	}
   158  	params, err := options.ToParams()
   159  	if err != nil {
   160  		return nil, err
   161  	}
   162  	response, err := conn.DoRequest(ctx, nil, http.MethodGet, "/pods/json", params, nil)
   163  	if err != nil {
   164  		return podsReports, err
   165  	}
   166  	defer response.Body.Close()
   167  
   168  	return podsReports, response.Process(&podsReports)
   169  }
   170  
   171  // Restart restarts all containers in a pod.
   172  func Restart(ctx context.Context, nameOrID string, options *RestartOptions) (*entities.PodRestartReport, error) {
   173  	var report entities.PodRestartReport
   174  	if options == nil {
   175  		options = new(RestartOptions)
   176  	}
   177  	_ = options
   178  	conn, err := bindings.GetClient(ctx)
   179  	if err != nil {
   180  		return nil, err
   181  	}
   182  	response, err := conn.DoRequest(ctx, nil, http.MethodPost, "/pods/%s/restart", nil, nil, nameOrID)
   183  	if err != nil {
   184  		return nil, err
   185  	}
   186  	defer response.Body.Close()
   187  
   188  	return &report, response.ProcessWithError(&report, &errorhandling.PodConflictErrorModel{})
   189  }
   190  
   191  // Remove deletes a Pod from local storage. The optional force parameter denotes
   192  // that the Pod can be removed even if in a running state.
   193  func Remove(ctx context.Context, nameOrID string, options *RemoveOptions) (*entities.PodRmReport, error) {
   194  	var report entities.PodRmReport
   195  	if options == nil {
   196  		options = new(RemoveOptions)
   197  	}
   198  	conn, err := bindings.GetClient(ctx)
   199  	if err != nil {
   200  		return nil, err
   201  	}
   202  	params, err := options.ToParams()
   203  	if err != nil {
   204  		return nil, err
   205  	}
   206  	response, err := conn.DoRequest(ctx, nil, http.MethodDelete, "/pods/%s", params, nil, nameOrID)
   207  	if err != nil {
   208  		return nil, err
   209  	}
   210  	defer response.Body.Close()
   211  
   212  	return &report, response.Process(&report)
   213  }
   214  
   215  // Start starts all containers in a pod.
   216  func Start(ctx context.Context, nameOrID string, options *StartOptions) (*entities.PodStartReport, error) {
   217  	var report entities.PodStartReport
   218  	if options == nil {
   219  		options = new(StartOptions)
   220  	}
   221  	_ = options
   222  	conn, err := bindings.GetClient(ctx)
   223  	if err != nil {
   224  		return nil, err
   225  	}
   226  	response, err := conn.DoRequest(ctx, nil, http.MethodPost, "/pods/%s/start", nil, nil, nameOrID)
   227  	if err != nil {
   228  		return nil, err
   229  	}
   230  	defer response.Body.Close()
   231  
   232  	if response.StatusCode == http.StatusNotModified {
   233  		report.Id = nameOrID
   234  		return &report, nil
   235  	}
   236  
   237  	return &report, response.ProcessWithError(&report, &errorhandling.PodConflictErrorModel{})
   238  }
   239  
   240  // Stop stops all containers in a Pod. The optional timeout parameter can be
   241  // used to override the timeout before the container is killed.
   242  func Stop(ctx context.Context, nameOrID string, options *StopOptions) (*entities.PodStopReport, error) {
   243  	var report entities.PodStopReport
   244  	if options == nil {
   245  		options = new(StopOptions)
   246  	}
   247  	conn, err := bindings.GetClient(ctx)
   248  	if err != nil {
   249  		return nil, err
   250  	}
   251  	params, err := options.ToParams()
   252  	if err != nil {
   253  		return nil, err
   254  	}
   255  	response, err := conn.DoRequest(ctx, nil, http.MethodPost, "/pods/%s/stop", params, nil, nameOrID)
   256  	if err != nil {
   257  		return nil, err
   258  	}
   259  	defer response.Body.Close()
   260  
   261  	if response.StatusCode == http.StatusNotModified {
   262  		report.Id = nameOrID
   263  		return &report, nil
   264  	}
   265  	return &report, response.ProcessWithError(&report, &errorhandling.PodConflictErrorModel{})
   266  }
   267  
   268  // Top gathers statistics about the running processes in a pod. The nameOrID can be a pod name
   269  // or a partial/full ID.  The descriptors allow for specifying which data to collect from each process.
   270  func Top(ctx context.Context, nameOrID string, options *TopOptions) ([]string, error) {
   271  	if options == nil {
   272  		options = new(TopOptions)
   273  	}
   274  	conn, err := bindings.GetClient(ctx)
   275  	if err != nil {
   276  		return nil, err
   277  	}
   278  	params := url.Values{}
   279  	if descriptors := options.GetDescriptors(); len(descriptors) > 0 {
   280  		params.Set("ps_args", strings.Join(descriptors, ","))
   281  	}
   282  	response, err := conn.DoRequest(ctx, nil, http.MethodGet, "/pods/%s/top", params, nil, nameOrID)
   283  	if err != nil {
   284  		return nil, err
   285  	}
   286  	defer response.Body.Close()
   287  
   288  	body := handlers.PodTopOKBody{}
   289  	if err = response.Process(&body); err != nil {
   290  		return nil, err
   291  	}
   292  
   293  	// handlers.PodTopOKBody{} returns a slice of slices where each cell in the top table is an item.
   294  	// In libpod land, we're just using a slice with cells being split by tabs, which allows for an idiomatic
   295  	// usage of the tabwriter.
   296  	topOutput := []string{strings.Join(body.Titles, "\t")}
   297  	for _, out := range body.Processes {
   298  		topOutput = append(topOutput, strings.Join(out, "\t"))
   299  	}
   300  
   301  	return topOutput, err
   302  }
   303  
   304  // Unpause unpauses all paused containers in a Pod.
   305  func Unpause(ctx context.Context, nameOrID string, options *UnpauseOptions) (*entities.PodUnpauseReport, error) {
   306  	if options == nil {
   307  		options = new(UnpauseOptions)
   308  	}
   309  	_ = options
   310  	var report entities.PodUnpauseReport
   311  	conn, err := bindings.GetClient(ctx)
   312  	if err != nil {
   313  		return nil, err
   314  	}
   315  	response, err := conn.DoRequest(ctx, nil, http.MethodPost, "/pods/%s/unpause", nil, nil, nameOrID)
   316  	if err != nil {
   317  		return nil, err
   318  	}
   319  	defer response.Body.Close()
   320  
   321  	return &report, response.ProcessWithError(&report, &errorhandling.PodConflictErrorModel{})
   322  }
   323  
   324  // Stats display resource-usage statistics of one or more pods.
   325  func Stats(ctx context.Context, namesOrIDs []string, options *StatsOptions) ([]*entities.PodStatsReport, error) {
   326  	if options == nil {
   327  		options = new(StatsOptions)
   328  	}
   329  	conn, err := bindings.GetClient(ctx)
   330  	if err != nil {
   331  		return nil, err
   332  	}
   333  	params, err := options.ToParams()
   334  	if err != nil {
   335  		return nil, err
   336  	}
   337  	for _, i := range namesOrIDs {
   338  		params.Add("namesOrIDs", i)
   339  	}
   340  
   341  	var reports []*entities.PodStatsReport
   342  	response, err := conn.DoRequest(ctx, nil, http.MethodGet, "/pods/stats", params, nil)
   343  	if err != nil {
   344  		return nil, err
   345  	}
   346  	defer response.Body.Close()
   347  
   348  	return reports, response.Process(&reports)
   349  }