github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/pkg/bindings/pods/pods.go (about)

     1  package pods
     2  
     3  import (
     4  	"context"
     5  	"net/http"
     6  	"net/url"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"github.com/containers/libpod/pkg/api/handlers"
    11  	"github.com/containers/libpod/pkg/bindings"
    12  	"github.com/containers/libpod/pkg/domain/entities"
    13  	"github.com/containers/libpod/pkg/specgen"
    14  	jsoniter "github.com/json-iterator/go"
    15  )
    16  
    17  func CreatePodFromSpec(ctx context.Context, s *specgen.PodSpecGenerator) (*entities.PodCreateReport, error) {
    18  	var (
    19  		pcr entities.PodCreateReport
    20  	)
    21  	conn, err := bindings.GetClient(ctx)
    22  	if err != nil {
    23  		return nil, err
    24  	}
    25  	specgenString, err := jsoniter.MarshalToString(s)
    26  	if err != nil {
    27  		return nil, err
    28  	}
    29  	stringReader := strings.NewReader(specgenString)
    30  	response, err := conn.DoRequest(stringReader, http.MethodPost, "/pods/create", nil)
    31  	if err != nil {
    32  		return nil, err
    33  	}
    34  	return &pcr, response.Process(&pcr)
    35  }
    36  
    37  // Exists is a lightweight method to determine if a pod exists in local storage
    38  func Exists(ctx context.Context, nameOrID string) (bool, error) {
    39  	conn, err := bindings.GetClient(ctx)
    40  	if err != nil {
    41  		return false, err
    42  	}
    43  	response, err := conn.DoRequest(nil, http.MethodGet, "/pods/%s/exists", nil, nameOrID)
    44  	if err != nil {
    45  		return false, err
    46  	}
    47  	return response.IsSuccess(), nil
    48  }
    49  
    50  // Inspect returns low-level information about the given pod.
    51  func Inspect(ctx context.Context, nameOrID string) (*entities.PodInspectReport, error) {
    52  	var (
    53  		report entities.PodInspectReport
    54  	)
    55  	conn, err := bindings.GetClient(ctx)
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  	response, err := conn.DoRequest(nil, http.MethodGet, "/pods/%s/json", nil, nameOrID)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  	return &report, response.Process(&report)
    64  }
    65  
    66  // Kill sends a SIGTERM to all the containers in a pod.  The optional signal parameter
    67  // can be used to override  SIGTERM.
    68  func Kill(ctx context.Context, nameOrID string, signal *string) (*entities.PodKillReport, error) {
    69  	var (
    70  		report entities.PodKillReport
    71  	)
    72  	conn, err := bindings.GetClient(ctx)
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	params := url.Values{}
    77  	if signal != nil {
    78  		params.Set("signal", *signal)
    79  	}
    80  	response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/kill", params, nameOrID)
    81  	if err != nil {
    82  		return nil, err
    83  	}
    84  	return &report, response.Process(&report)
    85  }
    86  
    87  // Pause pauses all running containers in a given pod.
    88  func Pause(ctx context.Context, nameOrID string) (*entities.PodPauseReport, error) {
    89  	var report entities.PodPauseReport
    90  	conn, err := bindings.GetClient(ctx)
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  	response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/pause", nil, nameOrID)
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  	return &report, response.Process(&report)
    99  }
   100  
   101  // Prune removes all non-running pods in local storage.
   102  func Prune(ctx context.Context) error {
   103  	conn, err := bindings.GetClient(ctx)
   104  	if err != nil {
   105  		return err
   106  	}
   107  	response, err := conn.DoRequest(nil, http.MethodPost, "/pods/prune", nil)
   108  	if err != nil {
   109  		return err
   110  	}
   111  	return response.Process(nil)
   112  }
   113  
   114  // List returns all pods in local storage.  The optional filters parameter can
   115  // be used to refine which pods should be listed.
   116  func List(ctx context.Context, filters map[string][]string) ([]*entities.ListPodsReport, error) {
   117  	var (
   118  		podsReports []*entities.ListPodsReport
   119  	)
   120  	conn, err := bindings.GetClient(ctx)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  	params := url.Values{}
   125  	if filters != nil {
   126  		stringFilter, err := bindings.FiltersToString(filters)
   127  		if err != nil {
   128  			return nil, err
   129  		}
   130  		params.Set("filters", stringFilter)
   131  	}
   132  	response, err := conn.DoRequest(nil, http.MethodGet, "/pods/json", params)
   133  	if err != nil {
   134  		return podsReports, err
   135  	}
   136  	return podsReports, response.Process(&podsReports)
   137  }
   138  
   139  // Restart restarts all containers in a pod.
   140  func Restart(ctx context.Context, nameOrID string) (*entities.PodRestartReport, error) {
   141  	var report entities.PodRestartReport
   142  	conn, err := bindings.GetClient(ctx)
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  	response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/restart", nil, nameOrID)
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  	return &report, response.Process(&report)
   151  }
   152  
   153  // Remove deletes a Pod from from local storage. The optional force parameter denotes
   154  // that the Pod can be removed even if in a running state.
   155  func Remove(ctx context.Context, nameOrID string, force *bool) (*entities.PodRmReport, error) {
   156  	var report entities.PodRmReport
   157  	conn, err := bindings.GetClient(ctx)
   158  	if err != nil {
   159  		return nil, err
   160  	}
   161  	params := url.Values{}
   162  	if force != nil {
   163  		params.Set("force", strconv.FormatBool(*force))
   164  	}
   165  	response, err := conn.DoRequest(nil, http.MethodDelete, "/pods/%s", params, nameOrID)
   166  	if err != nil {
   167  		return nil, err
   168  	}
   169  	return &report, response.Process(&report)
   170  }
   171  
   172  // Start starts all containers in a pod.
   173  func Start(ctx context.Context, nameOrID string) (*entities.PodStartReport, error) {
   174  	var report entities.PodStartReport
   175  	conn, err := bindings.GetClient(ctx)
   176  	if err != nil {
   177  		return nil, err
   178  	}
   179  	response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/start", nil, nameOrID)
   180  	if err != nil {
   181  		return nil, err
   182  	}
   183  	if response.StatusCode == http.StatusNotModified {
   184  		report.Id = nameOrID
   185  		return &report, nil
   186  	}
   187  	return &report, response.Process(&report)
   188  }
   189  
   190  func Stats() error {
   191  	// TODO
   192  	return bindings.ErrNotImplemented
   193  }
   194  
   195  // Stop stops all containers in a Pod. The optional timeout parameter can be
   196  // used to override the timeout before the container is killed.
   197  func Stop(ctx context.Context, nameOrID string, timeout *int) (*entities.PodStopReport, error) {
   198  	var report entities.PodStopReport
   199  	conn, err := bindings.GetClient(ctx)
   200  	if err != nil {
   201  		return nil, err
   202  	}
   203  	params := url.Values{}
   204  	if timeout != nil {
   205  		params.Set("t", strconv.Itoa(*timeout))
   206  	}
   207  	response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/stop", params, nameOrID)
   208  	if err != nil {
   209  		return nil, err
   210  	}
   211  	if response.StatusCode == http.StatusNotModified {
   212  		report.Id = nameOrID
   213  		return &report, nil
   214  	}
   215  	return &report, response.Process(&report)
   216  }
   217  
   218  // Top gathers statistics about the running processes in a pod. The nameOrID can be a pod name
   219  // or a partial/full ID.  The descriptors allow for specifying which data to collect from each process.
   220  func Top(ctx context.Context, nameOrID string, descriptors []string) ([]string, error) {
   221  	conn, err := bindings.GetClient(ctx)
   222  	if err != nil {
   223  		return nil, err
   224  	}
   225  	params := url.Values{}
   226  
   227  	if len(descriptors) > 0 {
   228  		// flatten the slice into one string
   229  		params.Set("ps_args", strings.Join(descriptors, ","))
   230  	}
   231  	response, err := conn.DoRequest(nil, http.MethodGet, "/pods/%s/top", params, nameOrID)
   232  	if err != nil {
   233  		return nil, err
   234  	}
   235  
   236  	body := handlers.PodTopOKBody{}
   237  	if err = response.Process(&body); err != nil {
   238  		return nil, err
   239  	}
   240  
   241  	// handlers.PodTopOKBody{} returns a slice of slices where each cell in the top table is an item.
   242  	// In libpod land, we're just using a slice with cells being split by tabs, which allows for an idiomatic
   243  	// usage of the tabwriter.
   244  	topOutput := []string{strings.Join(body.Titles, "\t")}
   245  	for _, out := range body.Processes {
   246  		topOutput = append(topOutput, strings.Join(out, "\t"))
   247  	}
   248  
   249  	return topOutput, err
   250  }
   251  
   252  // Unpause unpauses all paused containers in a Pod.
   253  func Unpause(ctx context.Context, nameOrID string) (*entities.PodUnpauseReport, error) {
   254  	var report entities.PodUnpauseReport
   255  	conn, err := bindings.GetClient(ctx)
   256  	if err != nil {
   257  		return nil, err
   258  	}
   259  	response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/unpause", nil, nameOrID)
   260  	if err != nil {
   261  		return nil, err
   262  	}
   263  	return &report, response.Process(&report)
   264  }