github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/pkg/domain/infra/abi/pods.go (about) 1 package abi 2 3 import ( 4 "context" 5 6 "github.com/hanks177/podman/v4/libpod" 7 "github.com/hanks177/podman/v4/libpod/define" 8 "github.com/hanks177/podman/v4/pkg/domain/entities" 9 dfilters "github.com/hanks177/podman/v4/pkg/domain/filters" 10 "github.com/hanks177/podman/v4/pkg/signal" 11 "github.com/hanks177/podman/v4/pkg/specgen/generate" 12 "github.com/pkg/errors" 13 "github.com/sirupsen/logrus" 14 ) 15 16 // getPodsByContext returns a slice of pods. Note that all, latest and pods are 17 // mutually exclusive arguments. 18 func getPodsByContext(all, latest bool, pods []string, runtime *libpod.Runtime) ([]*libpod.Pod, error) { 19 var outpods []*libpod.Pod 20 if all { 21 return runtime.GetAllPods() 22 } 23 if latest { 24 p, err := runtime.GetLatestPod() 25 if err != nil { 26 return nil, err 27 } 28 outpods = append(outpods, p) 29 return outpods, nil 30 } 31 var err error 32 for _, p := range pods { 33 pod, e := runtime.LookupPod(p) 34 if e != nil { 35 // Log all errors here, so callers don't need to. 36 logrus.Debugf("Error looking up pod %q: %v", p, e) 37 if err == nil { 38 err = e 39 } 40 } else { 41 outpods = append(outpods, pod) 42 } 43 } 44 return outpods, err 45 } 46 47 func (ic *ContainerEngine) PodExists(ctx context.Context, nameOrID string) (*entities.BoolReport, error) { 48 _, err := ic.Libpod.LookupPod(nameOrID) 49 if err != nil && errors.Cause(err) != define.ErrNoSuchPod { 50 return nil, err 51 } 52 return &entities.BoolReport{Value: err == nil}, nil 53 } 54 55 func (ic *ContainerEngine) PodKill(ctx context.Context, namesOrIds []string, options entities.PodKillOptions) ([]*entities.PodKillReport, error) { 56 reports := []*entities.PodKillReport{} 57 sig, err := signal.ParseSignalNameOrNumber(options.Signal) 58 if err != nil { 59 return nil, err 60 } 61 pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod) 62 if err != nil { 63 return nil, err 64 } 65 66 for _, p := range pods { 67 report := entities.PodKillReport{Id: p.ID()} 68 conErrs, err := p.Kill(ctx, uint(sig)) 69 if err != nil && errors.Cause(err) != define.ErrPodPartialFail { 70 report.Errs = []error{err} 71 reports = append(reports, &report) 72 continue 73 } 74 if len(conErrs) > 0 { 75 for id, err := range conErrs { 76 report.Errs = append(report.Errs, errors.Wrapf(err, "error killing container %s", id)) 77 } 78 reports = append(reports, &report) 79 continue 80 } 81 reports = append(reports, &report) 82 } 83 return reports, nil 84 } 85 86 func (ic *ContainerEngine) PodLogs(ctx context.Context, nameOrID string, options entities.PodLogsOptions) error { 87 // Implementation accepts slice 88 podName := []string{nameOrID} 89 pod, err := getPodsByContext(false, options.Latest, podName, ic.Libpod) 90 if err != nil { 91 return err 92 } 93 // Get pod containers 94 podCtrs, err := pod[0].AllContainers() 95 if err != nil { 96 return err 97 } 98 99 ctrNames := []string{} 100 // Check if `kubectl pod logs -c ctrname <podname>` alike command is used 101 if options.ContainerName != "" { 102 ctrFound := false 103 for _, ctr := range podCtrs { 104 if ctr.ID() == options.ContainerName || ctr.Name() == options.ContainerName { 105 ctrNames = append(ctrNames, options.ContainerName) 106 ctrFound = true 107 } 108 } 109 if !ctrFound { 110 return errors.Wrapf(define.ErrNoSuchCtr, "container %s is not in pod %s", options.ContainerName, nameOrID) 111 } 112 } else { 113 // No container name specified select all containers 114 for _, ctr := range podCtrs { 115 ctrNames = append(ctrNames, ctr.Name()) 116 } 117 } 118 119 // PodLogsOptions are similar but contains few extra fields like ctrName 120 // So cast other values as is so we can re-use the code 121 containerLogsOpts := entities.PodLogsOptionsToContainerLogsOptions(options) 122 123 return ic.ContainerLogs(ctx, ctrNames, containerLogsOpts) 124 } 125 126 func (ic *ContainerEngine) PodPause(ctx context.Context, namesOrIds []string, options entities.PodPauseOptions) ([]*entities.PodPauseReport, error) { 127 reports := []*entities.PodPauseReport{} 128 pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod) 129 if err != nil { 130 return nil, err 131 } 132 for _, p := range pods { 133 report := entities.PodPauseReport{Id: p.ID()} 134 errs, err := p.Pause(ctx) 135 if err != nil && errors.Cause(err) != define.ErrPodPartialFail { 136 report.Errs = []error{err} 137 continue 138 } 139 if len(errs) > 0 { 140 for id, v := range errs { 141 report.Errs = append(report.Errs, errors.Wrapf(v, "error pausing container %s", id)) 142 } 143 reports = append(reports, &report) 144 continue 145 } 146 reports = append(reports, &report) 147 } 148 return reports, nil 149 } 150 151 func (ic *ContainerEngine) PodUnpause(ctx context.Context, namesOrIds []string, options entities.PodunpauseOptions) ([]*entities.PodUnpauseReport, error) { 152 reports := []*entities.PodUnpauseReport{} 153 pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod) 154 if err != nil { 155 return nil, err 156 } 157 for _, p := range pods { 158 report := entities.PodUnpauseReport{Id: p.ID()} 159 errs, err := p.Unpause(ctx) 160 if err != nil && errors.Cause(err) != define.ErrPodPartialFail { 161 report.Errs = []error{err} 162 continue 163 } 164 if len(errs) > 0 { 165 for id, v := range errs { 166 report.Errs = append(report.Errs, errors.Wrapf(v, "error unpausing container %s", id)) 167 } 168 reports = append(reports, &report) 169 continue 170 } 171 reports = append(reports, &report) 172 } 173 return reports, nil 174 } 175 176 func (ic *ContainerEngine) PodStop(ctx context.Context, namesOrIds []string, options entities.PodStopOptions) ([]*entities.PodStopReport, error) { 177 reports := []*entities.PodStopReport{} 178 pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod) 179 if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchPod) { 180 return nil, err 181 } 182 for _, p := range pods { 183 report := entities.PodStopReport{Id: p.ID()} 184 errs, err := p.StopWithTimeout(ctx, false, options.Timeout) 185 if err != nil && errors.Cause(err) != define.ErrPodPartialFail { 186 report.Errs = []error{err} 187 continue 188 } 189 if len(errs) > 0 { 190 for id, v := range errs { 191 report.Errs = append(report.Errs, errors.Wrapf(v, "error stopping container %s", id)) 192 } 193 reports = append(reports, &report) 194 continue 195 } 196 reports = append(reports, &report) 197 } 198 return reports, nil 199 } 200 201 func (ic *ContainerEngine) PodRestart(ctx context.Context, namesOrIds []string, options entities.PodRestartOptions) ([]*entities.PodRestartReport, error) { 202 reports := []*entities.PodRestartReport{} 203 pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod) 204 if err != nil { 205 return nil, err 206 } 207 for _, p := range pods { 208 report := entities.PodRestartReport{Id: p.ID()} 209 errs, err := p.Restart(ctx) 210 if err != nil && errors.Cause(err) != define.ErrPodPartialFail { 211 report.Errs = []error{err} 212 reports = append(reports, &report) 213 continue 214 } 215 if len(errs) > 0 { 216 for id, v := range errs { 217 report.Errs = append(report.Errs, errors.Wrapf(v, "error restarting container %s", id)) 218 } 219 reports = append(reports, &report) 220 continue 221 } 222 reports = append(reports, &report) 223 } 224 return reports, nil 225 } 226 227 func (ic *ContainerEngine) PodStart(ctx context.Context, namesOrIds []string, options entities.PodStartOptions) ([]*entities.PodStartReport, error) { 228 reports := []*entities.PodStartReport{} 229 pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod) 230 if err != nil { 231 return nil, err 232 } 233 234 for _, p := range pods { 235 report := entities.PodStartReport{Id: p.ID()} 236 errs, err := p.Start(ctx) 237 if err != nil && errors.Cause(err) != define.ErrPodPartialFail { 238 report.Errs = []error{err} 239 reports = append(reports, &report) 240 continue 241 } 242 if len(errs) > 0 { 243 for id, v := range errs { 244 report.Errs = append(report.Errs, errors.Wrapf(v, "error starting container %s", id)) 245 } 246 reports = append(reports, &report) 247 continue 248 } 249 reports = append(reports, &report) 250 } 251 return reports, nil 252 } 253 254 func (ic *ContainerEngine) PodRm(ctx context.Context, namesOrIds []string, options entities.PodRmOptions) ([]*entities.PodRmReport, error) { 255 pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod) 256 if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchPod) { 257 return nil, err 258 } 259 reports := make([]*entities.PodRmReport, 0, len(pods)) 260 for _, p := range pods { 261 report := entities.PodRmReport{Id: p.ID()} 262 err := ic.Libpod.RemovePod(ctx, p, true, options.Force, options.Timeout) 263 if err != nil { 264 report.Err = err 265 } 266 reports = append(reports, &report) 267 } 268 return reports, nil 269 } 270 271 func (ic *ContainerEngine) PodPrune(ctx context.Context, options entities.PodPruneOptions) ([]*entities.PodPruneReport, error) { 272 return ic.prunePodHelper(ctx) 273 } 274 275 func (ic *ContainerEngine) prunePodHelper(ctx context.Context) ([]*entities.PodPruneReport, error) { 276 response, err := ic.Libpod.PrunePods(ctx) 277 if err != nil { 278 return nil, err 279 } 280 reports := make([]*entities.PodPruneReport, 0, len(response)) 281 for k, v := range response { 282 reports = append(reports, &entities.PodPruneReport{ 283 Err: v, 284 Id: k, 285 }) 286 } 287 return reports, nil 288 } 289 290 func (ic *ContainerEngine) PodCreate(ctx context.Context, specg entities.PodSpec) (*entities.PodCreateReport, error) { 291 pod, err := generate.MakePod(&specg, ic.Libpod) 292 if err != nil { 293 return nil, err 294 } 295 return &entities.PodCreateReport{Id: pod.ID()}, nil 296 } 297 298 func (ic *ContainerEngine) PodTop(ctx context.Context, options entities.PodTopOptions) (*entities.StringSliceReport, error) { 299 var ( 300 pod *libpod.Pod 301 err error 302 ) 303 304 // Look up the pod. 305 if options.Latest { 306 pod, err = ic.Libpod.GetLatestPod() 307 } else { 308 pod, err = ic.Libpod.LookupPod(options.NameOrID) 309 } 310 if err != nil { 311 return nil, errors.Wrap(err, "unable to lookup requested container") 312 } 313 314 // Run Top. 315 report := &entities.StringSliceReport{} 316 report.Value, err = pod.GetPodPidInformation(options.Descriptors) 317 return report, err 318 } 319 320 func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOptions) ([]*entities.ListPodsReport, error) { 321 var ( 322 err error 323 pds = []*libpod.Pod{} 324 ) 325 326 filters := make([]libpod.PodFilter, 0, len(options.Filters)) 327 for k, v := range options.Filters { 328 f, err := dfilters.GeneratePodFilterFunc(k, v, ic.Libpod) 329 if err != nil { 330 return nil, err 331 } 332 filters = append(filters, f) 333 } 334 if options.Latest { 335 pod, err := ic.Libpod.GetLatestPod() 336 if err != nil { 337 return nil, err 338 } 339 pds = append(pds, pod) 340 } else { 341 pds, err = ic.Libpod.Pods(filters...) 342 if err != nil { 343 return nil, err 344 } 345 } 346 347 reports := make([]*entities.ListPodsReport, 0, len(pds)) 348 for _, p := range pds { 349 var lpcs []*entities.ListPodContainer 350 status, err := p.GetPodStatus() 351 if err != nil { 352 return nil, err 353 } 354 cons, err := p.AllContainers() 355 if err != nil { 356 return nil, err 357 } 358 for _, c := range cons { 359 state, err := c.State() 360 if err != nil { 361 return nil, err 362 } 363 lpcs = append(lpcs, &entities.ListPodContainer{ 364 Id: c.ID(), 365 Names: c.Name(), 366 Status: state.String(), 367 }) 368 } 369 infraID, err := p.InfraContainerID() 370 if err != nil { 371 return nil, err 372 } 373 networks := []string{} 374 if len(infraID) > 0 { 375 infra, err := p.InfraContainer() 376 if err != nil { 377 return nil, err 378 } 379 networks, err = infra.Networks() 380 if err != nil { 381 return nil, err 382 } 383 } 384 reports = append(reports, &entities.ListPodsReport{ 385 Cgroup: p.CgroupParent(), 386 Containers: lpcs, 387 Created: p.CreatedTime(), 388 Id: p.ID(), 389 InfraId: infraID, 390 Name: p.Name(), 391 Namespace: p.Namespace(), 392 Networks: networks, 393 Status: status, 394 Labels: p.Labels(), 395 }) 396 } 397 return reports, nil 398 } 399 400 func (ic *ContainerEngine) PodInspect(ctx context.Context, options entities.PodInspectOptions) (*entities.PodInspectReport, error) { 401 var ( 402 pod *libpod.Pod 403 err error 404 ) 405 // Look up the pod. 406 if options.Latest { 407 pod, err = ic.Libpod.GetLatestPod() 408 } else { 409 pod, err = ic.Libpod.LookupPod(options.NameOrID) 410 } 411 if err != nil { 412 return nil, errors.Wrap(err, "unable to lookup requested container") 413 } 414 inspect, err := pod.Inspect() 415 if err != nil { 416 return nil, err 417 } 418 return &entities.PodInspectReport{InspectPodData: inspect}, nil 419 }