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 }