mirror of
https://github.com/containers/podman
synced 2024-10-20 01:03:51 +00:00
commit
796ae87b1a
|
@ -102,6 +102,8 @@ gating_task:
|
|||
networking_script: '${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/networking.sh'
|
||||
|
||||
gate_script:
|
||||
# TODO: remove once the image doesn't ship with pre-installed tools
|
||||
- rm /go/bin/*
|
||||
# N/B: entrypoint.sh resets $GOSRC (same as make clean)
|
||||
- '/usr/local/bin/entrypoint.sh install.tools |& ${TIMESTAMP}'
|
||||
- '/usr/local/bin/entrypoint.sh validate |& ${TIMESTAMP}'
|
||||
|
|
|
@ -6,8 +6,9 @@ run:
|
|||
- selinux
|
||||
concurrency: 6
|
||||
deadline: 5m
|
||||
skip-dirs-use-default: true
|
||||
skip-dirs:
|
||||
- dependencies/*
|
||||
- dependencies
|
||||
- contrib
|
||||
- test/e2e
|
||||
- docs
|
||||
|
@ -16,39 +17,19 @@ run:
|
|||
skip-files:
|
||||
- iopodman.go
|
||||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
- bodyclose
|
||||
- deadcode
|
||||
- depguard
|
||||
# dupl really overdid it; disabling
|
||||
# - dupl
|
||||
- errcheck
|
||||
- gofmt
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- nakedret
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- typecheck
|
||||
- unused
|
||||
- varcheck
|
||||
# - gochecknoglobals
|
||||
# - gochecknoinits
|
||||
# - goconst
|
||||
# - gocritic
|
||||
# - gocyclo
|
||||
# - goimports
|
||||
# - golint
|
||||
# - gosec
|
||||
- interfacer
|
||||
# - lll
|
||||
# - maligned
|
||||
# - misspell
|
||||
# - prealloc
|
||||
- scopelint
|
||||
- stylecheck
|
||||
- unconvert
|
||||
# I think we should uncomment this one and used it
|
||||
# - unparam
|
||||
enable-all: true
|
||||
disable:
|
||||
- dupl
|
||||
- funlen
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
- goconst
|
||||
- gocyclo
|
||||
- golint
|
||||
- goimports
|
||||
- gosec
|
||||
- lll
|
||||
- maligned
|
||||
- misspell
|
||||
- prealloc
|
||||
- unparam
|
||||
|
|
46
.tool/lint
46
.tool/lint
|
@ -1,46 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
# Create the linter path for use later
|
||||
LINTER=${GOPATH}/bin/gometalinter
|
||||
|
||||
# Make sure gometalinter is installed
|
||||
if [ ! -f ${LINTER} ]; then
|
||||
echo >&2 "gometalinter must be installed. Please run 'make install.tools' and try again"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PKGS=$(find . -type d -not -path . -a -not -iwholename '*.git*' -a -not -iname '.tool' -a -not -iwholename '*vendor*' -a -not -iname 'hack' -a -not -iwholename '*.artifacts*' -a -not -iwholename '*contrib*' -a -not -iwholename '*test*' -a -not -iwholename '*logo*' -a -not -iwholename '*conmon*' -a -not -iwholename '*completions*' -a -not -iwholename '*docs*' -a -not -iwholename '*pause*' -a -not -iwholename './_output*' -a -not -iwholename '*ioprojectatomicpodman.go')
|
||||
|
||||
echo $PKGS
|
||||
|
||||
# Execute the linter
|
||||
${LINTER} \
|
||||
--concurrency=4\
|
||||
--enable-gc\
|
||||
--vendored-linters\
|
||||
--deadline=600s --disable-all\
|
||||
--enable=deadcode\
|
||||
--enable=errcheck\
|
||||
--enable=gofmt\
|
||||
--enable=golint\
|
||||
--enable=ineffassign\
|
||||
--enable=megacheck\
|
||||
--enable=misspell\
|
||||
--enable=structcheck\
|
||||
--enable=varcheck\
|
||||
--enable=vet\
|
||||
--enable=vetshadow\
|
||||
--exclude='error return value not checked.*\(errcheck\)$'\
|
||||
--exclude='declaration of.*err.*shadows declaration.*\(vetshadow\)$'\
|
||||
--exclude='.*_test\.go:.*error return value not checked.*\(errcheck\)$'\
|
||||
--exclude='duplicate of.*_test.go.*\(dupl\)$'\
|
||||
--exclude='cmd\/client\/.*\.go.*\(dupl\)$'\
|
||||
--exclude='vendor\/.*'\
|
||||
--exclude='podman\/.*'\
|
||||
--exclude='server\/seccomp\/.*\.go.*$'\
|
||||
--exclude='dependencies\/.*'\
|
||||
${PKGS[@]}
|
12
Makefile
12
Makefile
|
@ -148,9 +148,7 @@ ifeq ("$(wildcard $(GOPKGDIR))","")
|
|||
endif
|
||||
touch $@
|
||||
|
||||
lint: .gopathok varlink_generate ## Execute the source code linter
|
||||
@echo "checking lint"
|
||||
@./.tool/lint
|
||||
lint: golangci-lint
|
||||
|
||||
golangci-lint: .gopathok varlink_generate .install.golangci-lint
|
||||
$(GOBIN)/golangci-lint run --tests=false --skip-files swagger.go
|
||||
|
@ -314,12 +312,6 @@ remotesystem:
|
|||
system.test-binary: .install.ginkgo
|
||||
$(GO) test -c ./test/system
|
||||
|
||||
perftest: ## Build perf tests
|
||||
$ cd contrib/perftest;go build
|
||||
|
||||
run-perftest: perftest ## Build and run perf tests
|
||||
$ contrib/perftest/perftest
|
||||
|
||||
vagrant-check:
|
||||
BOX=$(BOX) sh ./vagrant.sh
|
||||
|
||||
|
@ -517,7 +509,7 @@ endef
|
|||
|
||||
.install.golangci-lint: .gopathok
|
||||
if [ ! -x "$(GOBIN)/golangci-lint" ]; then \
|
||||
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOBIN)/ v1.17.1; \
|
||||
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOBIN)/ v1.18.0; \
|
||||
fi
|
||||
|
||||
.install.md2man: .gopathok
|
||||
|
|
|
@ -116,21 +116,22 @@ func getContainerfiles(files []string) []string {
|
|||
func getNsValues(c *cliconfig.BuildValues) ([]buildah.NamespaceOption, error) {
|
||||
var ret []buildah.NamespaceOption
|
||||
if c.Network != "" {
|
||||
if c.Network == "host" {
|
||||
switch {
|
||||
case c.Network == "host":
|
||||
ret = append(ret, buildah.NamespaceOption{
|
||||
Name: string(specs.NetworkNamespace),
|
||||
Host: true,
|
||||
})
|
||||
} else if c.Network == "container" {
|
||||
case c.Network == "container":
|
||||
ret = append(ret, buildah.NamespaceOption{
|
||||
Name: string(specs.NetworkNamespace),
|
||||
})
|
||||
} else if c.Network[0] == '/' {
|
||||
case c.Network[0] == '/':
|
||||
ret = append(ret, buildah.NamespaceOption{
|
||||
Name: string(specs.NetworkNamespace),
|
||||
Path: c.Network,
|
||||
})
|
||||
} else {
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported configuration network=%s", c.Network)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,8 @@ func getAllOrLatestContainers(c *cliconfig.PodmanCommand, runtime *libpod.Runtim
|
|||
var containers []*libpod.Container
|
||||
var lastError error
|
||||
var err error
|
||||
if c.Bool("all") {
|
||||
switch {
|
||||
case c.Bool("all"):
|
||||
if filterState != -1 {
|
||||
var filterFuncs []libpod.ContainerFilter
|
||||
filterFuncs = append(filterFuncs, func(c *libpod.Container) bool {
|
||||
|
@ -38,13 +39,13 @@ func getAllOrLatestContainers(c *cliconfig.PodmanCommand, runtime *libpod.Runtim
|
|||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "unable to get %s containers", verb)
|
||||
}
|
||||
} else if c.Bool("latest") {
|
||||
case c.Bool("latest"):
|
||||
lastCtr, err := runtime.GetLatestContainer()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "unable to get latest container")
|
||||
}
|
||||
containers = append(containers, lastCtr)
|
||||
} else {
|
||||
default:
|
||||
args := c.InputArgs
|
||||
for _, i := range args {
|
||||
container, err := runtime.LookupContainer(i)
|
||||
|
|
|
@ -138,25 +138,25 @@ func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest strin
|
|||
hostOwner := idtools.IDPair{UID: int(hostUID), GID: int(hostGID)}
|
||||
|
||||
if isFromHostToCtr {
|
||||
if isVol, volDestName, volName := isVolumeDestName(destPath, ctr); isVol {
|
||||
if isVol, volDestName, volName := isVolumeDestName(destPath, ctr); isVol { //nolint(gocritic)
|
||||
path, err := pathWithVolumeMount(ctr, runtime, volDestName, volName, destPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error getting destination path from volume %s", volDestName)
|
||||
}
|
||||
destPath = path
|
||||
} else if isBindMount, mount := isBindMountDestName(destPath, ctr); isBindMount {
|
||||
} else if isBindMount, mount := isBindMountDestName(destPath, ctr); isBindMount { //nolint(gocritic)
|
||||
path, err := pathWithBindMountSource(mount, destPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error getting destination path from bind mount %s", mount.Destination)
|
||||
}
|
||||
destPath = path
|
||||
} else if filepath.IsAbs(destPath) {
|
||||
} else if filepath.IsAbs(destPath) { //nolint(gocritic)
|
||||
cleanedPath, err := securejoin.SecureJoin(mountPoint, destPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
destPath = cleanedPath
|
||||
} else {
|
||||
} else { //nolint(gocritic)
|
||||
ctrWorkDir, err := securejoin.SecureJoin(mountPoint, ctr.WorkingDir())
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -172,25 +172,25 @@ func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest strin
|
|||
}
|
||||
} else {
|
||||
destOwner = idtools.IDPair{UID: os.Getuid(), GID: os.Getgid()}
|
||||
if isVol, volDestName, volName := isVolumeDestName(srcPath, ctr); isVol {
|
||||
if isVol, volDestName, volName := isVolumeDestName(srcPath, ctr); isVol { //nolint(gocritic)
|
||||
path, err := pathWithVolumeMount(ctr, runtime, volDestName, volName, srcPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error getting source path from volume %s", volDestName)
|
||||
}
|
||||
srcPath = path
|
||||
} else if isBindMount, mount := isBindMountDestName(srcPath, ctr); isBindMount {
|
||||
} else if isBindMount, mount := isBindMountDestName(srcPath, ctr); isBindMount { //nolint(gocritic)
|
||||
path, err := pathWithBindMountSource(mount, srcPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error getting source path from bind mount %s", mount.Destination)
|
||||
}
|
||||
srcPath = path
|
||||
} else if filepath.IsAbs(srcPath) {
|
||||
} else if filepath.IsAbs(srcPath) { //nolint(gocritic)
|
||||
cleanedPath, err := securejoin.SecureJoin(mountPoint, srcPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srcPath = cleanedPath
|
||||
} else {
|
||||
} else { //nolint(gocritic)
|
||||
cleanedPath, err := securejoin.SecureJoin(mountPoint, filepath.Join(ctr.WorkingDir(), srcPath))
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -115,14 +115,14 @@ func genHistoryFormat(format string, quiet bool) string {
|
|||
}
|
||||
|
||||
// historyToGeneric makes an empty array of interfaces for output
|
||||
func historyToGeneric(templParams []historyTemplateParams, JSONParams []*image.History) (genericParams []interface{}) {
|
||||
func historyToGeneric(templParams []historyTemplateParams, jsonParams []*image.History) (genericParams []interface{}) {
|
||||
if len(templParams) > 0 {
|
||||
for _, v := range templParams {
|
||||
genericParams = append(genericParams, interface{}(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
for _, v := range JSONParams {
|
||||
for _, v := range jsonParams {
|
||||
genericParams = append(genericParams, interface{}(v))
|
||||
}
|
||||
return
|
||||
|
|
|
@ -209,7 +209,7 @@ func (i imagesOptions) setOutputFormat() string {
|
|||
}
|
||||
|
||||
// imagesToGeneric creates an empty array of interfaces for output
|
||||
func imagesToGeneric(templParams []imagesTemplateParams, JSONParams []imagesJSONParams) []interface{} {
|
||||
func imagesToGeneric(templParams []imagesTemplateParams, jsonParams []imagesJSONParams) []interface{} {
|
||||
genericParams := []interface{}{}
|
||||
if len(templParams) > 0 {
|
||||
for _, v := range templParams {
|
||||
|
@ -217,7 +217,7 @@ func imagesToGeneric(templParams []imagesTemplateParams, JSONParams []imagesJSON
|
|||
}
|
||||
return genericParams
|
||||
}
|
||||
for _, v := range JSONParams {
|
||||
for _, v := range jsonParams {
|
||||
genericParams = append(genericParams, interface{}(v))
|
||||
}
|
||||
return genericParams
|
||||
|
@ -282,10 +282,8 @@ func getImagesTemplateOutput(ctx context.Context, images []*adapter.ContainerIma
|
|||
if len(tag) == 71 && strings.HasPrefix(tag, "sha256:") {
|
||||
imageDigest = digest.Digest(tag)
|
||||
tag = ""
|
||||
} else {
|
||||
if img.Digest() != "" {
|
||||
imageDigest = img.Digest()
|
||||
}
|
||||
} else if img.Digest() != "" {
|
||||
imageDigest = img.Digest()
|
||||
}
|
||||
params := imagesTemplateParams{
|
||||
Repository: repo,
|
||||
|
|
|
@ -72,17 +72,13 @@ var mainCommands = []*cobra.Command{
|
|||
}
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: path.Base(os.Args[0]),
|
||||
Long: "manage pods and images",
|
||||
RunE: commandRunE(),
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return before(cmd, args)
|
||||
},
|
||||
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return after(cmd, args)
|
||||
},
|
||||
SilenceUsage: true,
|
||||
SilenceErrors: true,
|
||||
Use: path.Base(os.Args[0]),
|
||||
Long: "manage pods and images",
|
||||
RunE: commandRunE(),
|
||||
PersistentPreRunE: before,
|
||||
PersistentPostRunE: after,
|
||||
SilenceUsage: true,
|
||||
SilenceErrors: true,
|
||||
}
|
||||
|
||||
var MainGlobalOpts cliconfig.MainFlags
|
||||
|
@ -160,16 +156,13 @@ func main() {
|
|||
}
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
outputError(err)
|
||||
} else {
|
||||
} else if exitCode == define.ExecErrorCodeGeneric {
|
||||
// The exitCode modified from define.ExecErrorCodeGeneric,
|
||||
// indicates an application
|
||||
// running inside of a container failed, as opposed to the
|
||||
// podman command failed. Must exit with that exit code
|
||||
// otherwise command exited correctly.
|
||||
if exitCode == define.ExecErrorCodeGeneric {
|
||||
exitCode = 0
|
||||
}
|
||||
|
||||
exitCode = 0
|
||||
}
|
||||
|
||||
// Check if /etc/containers/registries.conf exists when running in
|
||||
|
|
|
@ -320,13 +320,14 @@ func generatePodFilterFuncs(filter, filterValue string) (func(pod *adapter.Pod)
|
|||
// generate the template based on conditions given
|
||||
func genPodPsFormat(c *cliconfig.PodPsValues) string {
|
||||
format := ""
|
||||
if c.Format != "" {
|
||||
switch {
|
||||
case c.Format != "":
|
||||
// "\t" from the command line is not being recognized as a tab
|
||||
// replacing the string "\t" to a tab character if the user passes in "\t"
|
||||
format = strings.Replace(c.Format, `\t`, "\t", -1)
|
||||
} else if c.Quiet {
|
||||
case c.Quiet:
|
||||
format = formats.IDString
|
||||
} else {
|
||||
default:
|
||||
format = "table {{.ID}}\t{{.Name}}\t{{.Status}}\t{{.Created}}"
|
||||
if c.Bool("namespace") {
|
||||
format += "\t{{.Cgroup}}\t{{.Namespaces}}"
|
||||
|
@ -341,14 +342,14 @@ func genPodPsFormat(c *cliconfig.PodPsValues) string {
|
|||
return format
|
||||
}
|
||||
|
||||
func podPsToGeneric(templParams []podPsTemplateParams, JSONParams []podPsJSONParams) (genericParams []interface{}) {
|
||||
func podPsToGeneric(templParams []podPsTemplateParams, jsonParams []podPsJSONParams) (genericParams []interface{}) {
|
||||
if len(templParams) > 0 {
|
||||
for _, v := range templParams {
|
||||
genericParams = append(genericParams, interface{}(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
for _, v := range JSONParams {
|
||||
for _, v := range jsonParams {
|
||||
genericParams = append(genericParams, interface{}(v))
|
||||
}
|
||||
return
|
||||
|
|
|
@ -124,10 +124,8 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
|
|||
for i := 0; i < t.NumField(); i++ {
|
||||
value := strings.ToUpper(splitCamelCase(t.Field(i).Name))
|
||||
switch value {
|
||||
case "CPU":
|
||||
value = value + " %"
|
||||
case "MEM":
|
||||
value = value + " %"
|
||||
case "CPU", "MEM":
|
||||
value += " %"
|
||||
case "MEM USAGE":
|
||||
value = "MEM USAGE / LIMIT"
|
||||
}
|
||||
|
@ -167,10 +165,8 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
|
|||
results := podContainerStatsToPodStatOut(newStats)
|
||||
if len(format) == 0 {
|
||||
outputToStdOut(results)
|
||||
} else {
|
||||
if err := printPSFormat(c.Format, results, headerNames); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if err := printPSFormat(c.Format, results, headerNames); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
|
|
|
@ -65,7 +65,7 @@ func rmiCmd(c *cliconfig.RmiValues) error {
|
|||
return errors.Errorf("when using the --all switch, you may not pass any images names or IDs")
|
||||
}
|
||||
|
||||
images := args[:]
|
||||
images := args
|
||||
|
||||
removeImage := func(img *adapter.ContainerImage) {
|
||||
response, err := runtime.RemoveImage(ctx, img, c.Force)
|
||||
|
|
|
@ -650,10 +650,7 @@ func getNamespaceInfo(path string) (string, error) {
|
|||
|
||||
// getStrFromSquareBrackets gets the string inside [] from a string.
|
||||
func getStrFromSquareBrackets(cmd string) string {
|
||||
reg, err := regexp.Compile(`.*\[|\].*`)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
reg := regexp.MustCompile(`.*\[|\].*`)
|
||||
arr := strings.Split(reg.ReplaceAllLiteralString(cmd, ""), ",")
|
||||
return strings.Join(arr, ",")
|
||||
}
|
||||
|
|
|
@ -444,11 +444,12 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
|
|||
// USER
|
||||
user := c.String("user")
|
||||
if user == "" {
|
||||
if usernsMode.IsKeepID() {
|
||||
switch {
|
||||
case usernsMode.IsKeepID():
|
||||
user = fmt.Sprintf("%d:%d", rootless.GetRootlessUID(), rootless.GetRootlessGID())
|
||||
} else if data == nil {
|
||||
case data == nil:
|
||||
user = "0"
|
||||
} else {
|
||||
default:
|
||||
user = data.Config.User
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,18 +59,20 @@ func CreatePodStatusResults(ctrStatuses map[string]define.ContainerStatus) (stri
|
|||
}
|
||||
}
|
||||
|
||||
if statuses[PodStateRunning] > 0 {
|
||||
switch {
|
||||
case statuses[PodStateRunning] > 0:
|
||||
return PodStateRunning, nil
|
||||
} else if statuses[PodStatePaused] == ctrNum {
|
||||
case statuses[PodStatePaused] == ctrNum:
|
||||
return PodStatePaused, nil
|
||||
} else if statuses[PodStateStopped] == ctrNum {
|
||||
case statuses[PodStateStopped] == ctrNum:
|
||||
return PodStateExited, nil
|
||||
} else if statuses[PodStateStopped] > 0 {
|
||||
case statuses[PodStateStopped] > 0:
|
||||
return PodStateStopped, nil
|
||||
} else if statuses[PodStateErrored] > 0 {
|
||||
case statuses[PodStateErrored] > 0:
|
||||
return PodStateErrored, nil
|
||||
default:
|
||||
return PodStateCreated, nil
|
||||
}
|
||||
return PodStateCreated, nil
|
||||
}
|
||||
|
||||
// GetNamespaceOptions transforms a slice of kernel namespaces
|
||||
|
|
|
@ -105,9 +105,10 @@ func statsCmd(c *cliconfig.StatsValues) error {
|
|||
var ctrs []*libpod.Container
|
||||
|
||||
containerFunc := runtime.GetRunningContainers
|
||||
if len(c.InputArgs) > 0 {
|
||||
switch {
|
||||
case len(c.InputArgs) > 0:
|
||||
containerFunc = func() ([]*libpod.Container, error) { return runtime.GetContainersByList(c.InputArgs) }
|
||||
} else if latest {
|
||||
case latest:
|
||||
containerFunc = func() ([]*libpod.Container, error) {
|
||||
lastCtr, err := runtime.GetLatestContainer()
|
||||
if err != nil {
|
||||
|
@ -115,7 +116,7 @@ func statsCmd(c *cliconfig.StatsValues) error {
|
|||
}
|
||||
return []*libpod.Container{lastCtr}, nil
|
||||
}
|
||||
} else if all {
|
||||
case all:
|
||||
containerFunc = runtime.GetAllContainers
|
||||
}
|
||||
|
||||
|
@ -219,14 +220,14 @@ func genStatsFormat(format string) string {
|
|||
}
|
||||
|
||||
// imagesToGeneric creates an empty array of interfaces for output
|
||||
func statsToGeneric(templParams []statsOutputParams, JSONParams []statsOutputParams) (genericParams []interface{}) {
|
||||
func statsToGeneric(templParams []statsOutputParams, jsonParams []statsOutputParams) (genericParams []interface{}) {
|
||||
if len(templParams) > 0 {
|
||||
for _, v := range templParams {
|
||||
genericParams = append(genericParams, interface{}(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
for _, v := range JSONParams {
|
||||
for _, v := range jsonParams {
|
||||
genericParams = append(genericParams, interface{}(v))
|
||||
}
|
||||
return
|
||||
|
|
|
@ -113,12 +113,12 @@ func printImageChildren(layerMap map[string]*image.LayerInfo, layerID string, pr
|
|||
intend := middleItem
|
||||
if !last {
|
||||
// add continueItem i.e. '|' for next iteration prefix
|
||||
prefix = prefix + continueItem
|
||||
prefix += continueItem
|
||||
} else if len(ll.ChildID) > 1 || len(ll.ChildID) == 0 {
|
||||
// The above condition ensure, alignment happens for node, which has more then 1 children.
|
||||
// If node is last in printing hierarchy, it should not be printed as middleItem i.e. ├──
|
||||
intend = lastItem
|
||||
prefix = prefix + " "
|
||||
prefix += " "
|
||||
}
|
||||
|
||||
var tags string
|
||||
|
|
|
@ -134,14 +134,14 @@ func genVolLsFormat(c *cliconfig.VolumeLsValues) string {
|
|||
}
|
||||
|
||||
// Convert output to genericParams for printing
|
||||
func volLsToGeneric(templParams []volumeLsTemplateParams, JSONParams []volumeLsJSONParams) (genericParams []interface{}) {
|
||||
func volLsToGeneric(templParams []volumeLsTemplateParams, jsonParams []volumeLsJSONParams) (genericParams []interface{}) {
|
||||
if len(templParams) > 0 {
|
||||
for _, v := range templParams {
|
||||
genericParams = append(genericParams, interface{}(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
for _, v := range JSONParams {
|
||||
for _, v := range jsonParams {
|
||||
genericParams = append(genericParams, interface{}(v))
|
||||
}
|
||||
return
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
## perftest : tool for benchmarking and profiling libpod library
|
||||
perftest uses libpod as golang library and perform stress test and profile for CPU usage.
|
||||
|
||||
Build:
|
||||
|
||||
```
|
||||
# cd $GOPATH/src/github.com/containers/libpod/contrib/perftest
|
||||
# go build
|
||||
# go install
|
||||
```
|
||||
|
||||
Usage:
|
||||
|
||||
```
|
||||
# perftest -h
|
||||
Usage of perftest:
|
||||
|
||||
-count int
|
||||
count of loop counter for test (default 50)
|
||||
-image string
|
||||
image-name to be used for test (default "docker.io/library/alpine:latest")
|
||||
|
||||
```
|
||||
|
||||
e.g.
|
||||
|
||||
```
|
||||
# perftest
|
||||
runc version spec: 1.0.1-dev
|
||||
conmon version 1.12.0-dev, commit: b6c5cafeffa9b3cde89812207b29ccedd3102712
|
||||
|
||||
preparing test environment...
|
||||
2018/11/05 16:52:14 profile: cpu profiling enabled, /tmp/profile626959338/cpu.pprof
|
||||
Test Round: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
|
||||
Profile data
|
||||
|
||||
Create Start Stop Delete
|
||||
Min 0.23s 0.34s 2.12s 0.51s
|
||||
Avg 0.25s 0.38s 2.13s 0.54s
|
||||
Max 0.27s 0.48s 2.13s 0.70s
|
||||
Total 12.33s 18.82s 106.47s 26.91s
|
||||
2018/11/05 16:54:59 profile: cpu profiling disabled, /tmp/profile626959338/cpu.pprof
|
||||
|
||||
```
|
||||
|
||||
Analyse CPU profile.
|
||||
|
||||
```
|
||||
# go tool pprof -http=":8081" $GOPATH/src/github.com/containers/libpod/contrib/perftest/perftest /tmp/profile626959338/cpu.pprof
|
||||
```
|
||||
- Open http://localhost:8081 in webbrowser
|
|
@ -1,282 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/libpod/libpod"
|
||||
image2 "github.com/containers/libpod/libpod/image"
|
||||
cc "github.com/containers/libpod/pkg/spec"
|
||||
"github.com/containers/libpod/pkg/util"
|
||||
"github.com/containers/storage/pkg/reexec"
|
||||
"github.com/cri-o/ocicni/pkg/ocicni"
|
||||
"github.com/pkg/profile"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTestImage = "docker.io/library/alpine:latest"
|
||||
defaultRunCount = 50
|
||||
)
|
||||
|
||||
var helpMessage = `
|
||||
-count int
|
||||
count of loop counter for test (default 50)
|
||||
-image string
|
||||
image-name to be used for test (default "docker.io/library/alpine:latest")
|
||||
-log string
|
||||
log level (info|debug|warn|error) (default "error")
|
||||
|
||||
`
|
||||
|
||||
func main() {
|
||||
if reexec.Init() {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
imageName := ""
|
||||
|
||||
testImageName := flag.String("image", defaultTestImage, "image-name to be used for test")
|
||||
testRunCount := flag.Int("count", defaultRunCount, "count of loop counter for test")
|
||||
logLevel := flag.String("log", "error", "log level (info|debug|warn|error)")
|
||||
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
|
||||
fmt.Fprintf(os.Stderr, "%s \n", helpMessage)
|
||||
}
|
||||
|
||||
flag.Parse()
|
||||
|
||||
switch strings.ToLower(*logLevel) {
|
||||
case "error":
|
||||
logrus.SetLevel(logrus.ErrorLevel)
|
||||
case "warn":
|
||||
logrus.SetLevel(logrus.WarnLevel)
|
||||
case "info":
|
||||
logrus.SetLevel(logrus.InfoLevel)
|
||||
case "debug":
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
default:
|
||||
logrus.Fatalf("invalid option : %s ", *logLevel)
|
||||
}
|
||||
|
||||
opts := defaultRuntimeOptions()
|
||||
client, err := libpod.NewRuntime(opts...)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
defer client.Shutdown(false)
|
||||
|
||||
// Print Runtime & System Information.
|
||||
err = printSystemInfo(client)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
imageRuntime := client.ImageRuntime()
|
||||
if imageRuntime == nil {
|
||||
logrus.Fatal("ImageRuntime is null")
|
||||
}
|
||||
|
||||
fmt.Printf("preparing test environment...\n")
|
||||
//Prepare for test.
|
||||
testImage, err := imageRuntime.NewFromLocal(*testImageName)
|
||||
if err != nil {
|
||||
// Download the image from remote registry.
|
||||
writer := os.Stderr
|
||||
registryCreds := &types.DockerAuthConfig{
|
||||
Username: "",
|
||||
Password: "",
|
||||
}
|
||||
dockerRegistryOptions := image2.DockerRegistryOptions{
|
||||
DockerRegistryCreds: registryCreds,
|
||||
DockerCertPath: "",
|
||||
DockerInsecureSkipTLSVerify: types.OptionalBoolFalse,
|
||||
}
|
||||
fmt.Printf("image %s not found locally, fetching from remote registry..\n", *testImageName)
|
||||
|
||||
testImage, err = client.ImageRuntime().New(ctx, *testImageName, "", "", writer, &dockerRegistryOptions, image2.SigningOptions{}, nil, util.PullImageMissing)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
fmt.Printf("image downloaded successfully\n\n")
|
||||
}
|
||||
|
||||
names := testImage.Names()
|
||||
if len(names) > 0 {
|
||||
imageName = names[0]
|
||||
} else {
|
||||
imageName = testImage.ID()
|
||||
}
|
||||
|
||||
idmappings, err := util.ParseIDMapping(nil, nil, "", "")
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
config := &cc.CreateConfig{
|
||||
Tty: true,
|
||||
Image: imageName,
|
||||
ImageID: testImage.ID(),
|
||||
IDMappings: idmappings,
|
||||
Command: []string{"/bin/sh"},
|
||||
WorkDir: "/",
|
||||
NetMode: "bridge",
|
||||
Network: "bridge",
|
||||
}
|
||||
|
||||
// Enable CPU Profile
|
||||
defer profile.Start().Stop()
|
||||
|
||||
data, err := runSingleThreadedStressTest(ctx, client, imageName, testImage.ID(), config, *testRunCount)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
data.printProfiledData((float64)(*testRunCount))
|
||||
}
|
||||
|
||||
func defaultRuntimeOptions() []libpod.RuntimeOption {
|
||||
options := []libpod.RuntimeOption{}
|
||||
return options
|
||||
/*
|
||||
//TODO: Shall we test in clean environment?
|
||||
sOpts := storage.StoreOptions{
|
||||
GraphDriverName: "overlay",
|
||||
RunRoot: "/var/run/containers/storage",
|
||||
GraphRoot: "/var/lib/containers/storage",
|
||||
}
|
||||
|
||||
storageOpts := libpod.WithStorageConfig(sOpts)
|
||||
options = append(options, storageOpts)
|
||||
return options
|
||||
*/
|
||||
}
|
||||
|
||||
func printSystemInfo(client *libpod.Runtime) error {
|
||||
OCIRuntimeInfo, err := client.GetOCIRuntimeVersion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
connmanInfo, err := client.GetConmonVersion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("%s\n%s\n\n", OCIRuntimeInfo, connmanInfo)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runSingleThreadedStressTest(ctx context.Context, client *libpod.Runtime, imageName string, imageID string, config *cc.CreateConfig, testCount int) (*profileData, error) {
|
||||
data := new(profileData)
|
||||
fmt.Printf("Test Round: ")
|
||||
for i := 0; i < testCount; i++ {
|
||||
fmt.Printf("%d ", i)
|
||||
|
||||
runtimeSpec, err := cc.CreateConfigToOCISpec(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//Create Container
|
||||
networks := make([]string, 0)
|
||||
netmode := "bridge"
|
||||
createStartTime := time.Now()
|
||||
ctr, err := client.NewContainer(ctx,
|
||||
runtimeSpec,
|
||||
libpod.WithRootFSFromImage(imageID, imageName, false),
|
||||
libpod.WithNetNS([]ocicni.PortMapping{}, false, netmode, networks),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
createTotalTime := time.Now().Sub(createStartTime)
|
||||
|
||||
// Start container
|
||||
startStartTime := time.Now()
|
||||
err = ctr.Start(ctx, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
startTotalTime := time.Now().Sub(startStartTime)
|
||||
|
||||
//Stop Container
|
||||
stopStartTime := time.Now()
|
||||
err = ctr.StopWithTimeout(2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stopTotalTime := time.Now().Sub(stopStartTime)
|
||||
|
||||
//Delete Container
|
||||
deleteStartTime := time.Now()
|
||||
|
||||
err = client.RemoveContainer(ctx, ctr, true, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
deleteTotalTime := time.Now().Sub(deleteStartTime)
|
||||
|
||||
data.updateProfileData(createTotalTime, startTotalTime, stopTotalTime, deleteTotalTime)
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
type profileData struct {
|
||||
minCreate, minStart, minStop, minDel time.Duration
|
||||
avgCreate, avgStart, avgStop, avgDel time.Duration
|
||||
maxCreate, maxStart, maxStop, maxDel time.Duration
|
||||
}
|
||||
|
||||
func (data *profileData) updateProfileData(create, start, stop, delete time.Duration) {
|
||||
if create < data.minCreate || data.minCreate == 0 {
|
||||
data.minCreate = create
|
||||
}
|
||||
if create > data.maxCreate || data.maxCreate == 0 {
|
||||
data.maxCreate = create
|
||||
}
|
||||
if start < data.minStart || data.minStart == 0 {
|
||||
data.minStart = start
|
||||
}
|
||||
if start > data.maxStart || data.maxStart == 0 {
|
||||
data.maxStart = start
|
||||
}
|
||||
if stop < data.minStop || data.minStop == 0 {
|
||||
data.minStop = stop
|
||||
}
|
||||
if stop > data.maxStop || data.maxStop == 0 {
|
||||
data.maxStop = stop
|
||||
}
|
||||
if delete < data.minDel || data.minDel == 0 {
|
||||
data.minDel = delete
|
||||
}
|
||||
if delete > data.maxDel || data.maxDel == 0 {
|
||||
data.maxDel = delete
|
||||
}
|
||||
|
||||
data.avgCreate = data.avgCreate + create
|
||||
data.avgStart = data.avgStart + start
|
||||
data.avgStop = data.avgStop + stop
|
||||
data.avgDel = data.avgDel + delete
|
||||
}
|
||||
|
||||
func (data *profileData) printProfiledData(testCount float64) {
|
||||
|
||||
fmt.Printf("\nProfile data\n\n")
|
||||
w := new(tabwriter.Writer)
|
||||
w.Init(os.Stdout, 0, 8, 0, '\t', 0)
|
||||
fmt.Fprintln(w, "\tCreate\tStart\tStop\tDelete")
|
||||
fmt.Fprintf(w, "Min\t%.2fs\t%.2fs\t%.2fs\t%.2fs\n", data.minCreate.Seconds(), data.minStart.Seconds(), data.minStop.Seconds(), data.minDel.Seconds())
|
||||
fmt.Fprintf(w, "Avg\t%.2fs\t%.2fs\t%.2fs\t%.2fs\n", data.avgCreate.Seconds()/testCount, data.avgStart.Seconds()/testCount, data.avgStop.Seconds()/testCount, data.avgDel.Seconds()/testCount)
|
||||
fmt.Fprintf(w, "Max\t%.2fs\t%.2fs\t%.2fs\t%.2fs\n", data.maxCreate.Seconds(), data.maxStart.Seconds(), data.maxStop.Seconds(), data.maxDel.Seconds())
|
||||
fmt.Fprintf(w, "Total\t%.2fs\t%.2fs\t%.2fs\t%.2fs\n", data.avgCreate.Seconds(), data.avgStart.Seconds(), data.avgStop.Seconds(), data.avgDel.Seconds())
|
||||
fmt.Fprintln(w)
|
||||
w.Flush()
|
||||
}
|
2
go.mod
2
go.mod
|
@ -51,7 +51,7 @@ require (
|
|||
github.com/opencontainers/selinux v1.3.0
|
||||
github.com/opentracing/opentracing-go v1.1.0
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/pkg/profile v1.4.0
|
||||
github.com/pkg/profile v1.4.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0
|
||||
github.com/rootless-containers/rootlesskit v0.7.1
|
||||
github.com/seccomp/containers-golang v0.0.0-20190312124753-8ca8945ccf5f
|
||||
|
|
|
@ -652,11 +652,9 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error {
|
|||
if string(depCtrPod) != pod.ID() {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "container %s depends on container %s which is in a different pod (%s)", ctr.ID(), dependsCtr, string(depCtrPod))
|
||||
}
|
||||
} else {
|
||||
} else if depCtrPod != nil {
|
||||
// If we're not part of a pod, we cannot depend on containers in a pod
|
||||
if depCtrPod != nil {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "container %s depends on container %s which is in a pod - containers not in pods cannot depend on containers in pods", ctr.ID(), dependsCtr)
|
||||
}
|
||||
return errors.Wrapf(define.ErrInvalidArg, "container %s depends on container %s which is in a pod - containers not in pods cannot depend on containers in pods", ctr.ID(), dependsCtr)
|
||||
}
|
||||
|
||||
depNamespace := depCtrBkt.Get(namespaceKey)
|
||||
|
|
|
@ -472,11 +472,9 @@ func (c *Container) specFromState() (*spec.Spec, error) {
|
|||
if err := json.Unmarshal(content, &returnSpec); err != nil {
|
||||
return nil, errors.Wrapf(err, "error unmarshalling container config")
|
||||
}
|
||||
} else {
|
||||
} else if !os.IsNotExist(err) {
|
||||
// ignore when the file does not exist
|
||||
if !os.IsNotExist(err) {
|
||||
return nil, errors.Wrapf(err, "error opening container config")
|
||||
}
|
||||
return nil, errors.Wrapf(err, "error opening container config")
|
||||
}
|
||||
|
||||
return returnSpec, nil
|
||||
|
|
|
@ -56,7 +56,7 @@ func (c *Container) readFromLogFile(options *logs.LogOptions, logChannel chan *l
|
|||
continue
|
||||
}
|
||||
if nll.Partial() {
|
||||
partial = partial + nll.Msg
|
||||
partial += nll.Msg
|
||||
continue
|
||||
} else if !nll.Partial() && len(partial) > 1 {
|
||||
nll.Msg = partial
|
||||
|
|
|
@ -113,7 +113,7 @@ func detectCycles(graph *ContainerGraph) (bool, error) {
|
|||
info := new(nodeInfo)
|
||||
info.index = index
|
||||
info.lowLink = index
|
||||
index = index + 1
|
||||
index++
|
||||
|
||||
nodes[node.id] = info
|
||||
|
||||
|
|
|
@ -1214,11 +1214,12 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named
|
|||
|
||||
// Network mode parsing.
|
||||
networkMode := ""
|
||||
if c.config.CreateNetNS {
|
||||
switch {
|
||||
case c.config.CreateNetNS:
|
||||
networkMode = "default"
|
||||
} else if c.config.NetNsCtr != "" {
|
||||
case c.config.NetNsCtr != "":
|
||||
networkMode = fmt.Sprintf("container:%s", c.config.NetNsCtr)
|
||||
} else {
|
||||
default:
|
||||
// Find the spec's network namespace.
|
||||
// If there is none, it's host networking.
|
||||
// If there is one and it has a path, it's "ns:".
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
"github.com/containers/storage"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/containers/storage/pkg/mount"
|
||||
"github.com/cyphar/filepath-securejoin"
|
||||
securejoin "github.com/cyphar/filepath-securejoin"
|
||||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/opencontainers/runtime-tools/generate"
|
||||
"github.com/opencontainers/selinux/go-selinux/label"
|
||||
|
@ -339,7 +339,7 @@ func (c *Container) handleRestartPolicy(ctx context.Context) (restarted bool, er
|
|||
c.newContainerEvent(events.Restart)
|
||||
|
||||
// Increment restart count
|
||||
c.state.RestartCount = c.state.RestartCount + 1
|
||||
c.state.RestartCount += 1
|
||||
logrus.Debugf("Container %s now on retry %d", c.ID(), c.state.RestartCount)
|
||||
if err := c.save(); err != nil {
|
||||
return false, err
|
||||
|
@ -1286,7 +1286,7 @@ func (c *Container) restartWithTimeout(ctx context.Context, timeout uint) (err e
|
|||
// TODO: Add ability to override mount label so we can use this for Mount() too
|
||||
// TODO: Can we use this for export? Copying SHM into the export might not be
|
||||
// good
|
||||
func (c *Container) mountStorage() (_ string, Err error) {
|
||||
func (c *Container) mountStorage() (_ string, deferredErr error) {
|
||||
var err error
|
||||
// Container already mounted, nothing to do
|
||||
if c.state.Mounted {
|
||||
|
@ -1307,7 +1307,7 @@ func (c *Container) mountStorage() (_ string, Err error) {
|
|||
return "", errors.Wrapf(err, "failed to chown %s", c.config.ShmDir)
|
||||
}
|
||||
defer func() {
|
||||
if Err != nil {
|
||||
if deferredErr != nil {
|
||||
if err := c.unmountSHM(c.config.ShmDir); err != nil {
|
||||
logrus.Errorf("Error unmounting SHM for container %s after mount error: %v", c.ID(), err)
|
||||
}
|
||||
|
@ -1324,7 +1324,7 @@ func (c *Container) mountStorage() (_ string, Err error) {
|
|||
return "", err
|
||||
}
|
||||
defer func() {
|
||||
if Err != nil {
|
||||
if deferredErr != nil {
|
||||
if err := c.unmount(false); err != nil {
|
||||
logrus.Errorf("Error unmounting container %s after mount error: %v", c.ID(), err)
|
||||
}
|
||||
|
@ -1339,7 +1339,7 @@ func (c *Container) mountStorage() (_ string, Err error) {
|
|||
return "", err
|
||||
}
|
||||
defer func() {
|
||||
if Err == nil {
|
||||
if deferredErr == nil {
|
||||
return
|
||||
}
|
||||
vol.lock.Lock()
|
||||
|
|
|
@ -62,7 +62,7 @@ func (c *Container) unmountSHM(mount string) error {
|
|||
|
||||
// prepare mounts the container and sets up other required resources like net
|
||||
// namespaces
|
||||
func (c *Container) prepare() (Err error) {
|
||||
func (c *Container) prepare() error {
|
||||
var (
|
||||
wg sync.WaitGroup
|
||||
netNS ns.NetNS
|
||||
|
@ -1277,21 +1277,21 @@ func (c *Container) generateResolvConf() (string, error) {
|
|||
}
|
||||
|
||||
// If the user provided dns, it trumps all; then dns masq; then resolv.conf
|
||||
if len(c.config.DNSServer) > 0 {
|
||||
switch {
|
||||
case len(c.config.DNSServer) > 0:
|
||||
// We store DNS servers as net.IP, so need to convert to string
|
||||
for _, server := range c.config.DNSServer {
|
||||
nameservers = append(nameservers, server.String())
|
||||
}
|
||||
} else if len(cniNameServers) > 0 {
|
||||
case len(cniNameServers) > 0:
|
||||
nameservers = append(nameservers, cniNameServers...)
|
||||
} else {
|
||||
default:
|
||||
// Make a new resolv.conf
|
||||
nameservers = resolvconf.GetNameservers(resolv.Content)
|
||||
// slirp4netns has a built in DNS server.
|
||||
if c.config.NetMode.IsSlirp4netns() {
|
||||
nameservers = append([]string{"10.0.2.3"}, nameservers...)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
search := resolvconf.GetSearchDomains(resolv.Content)
|
||||
|
@ -1451,23 +1451,24 @@ func (c *Container) getOCICgroupPath() (string, error) {
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if (rootless.IsRootless() && !unified) || c.config.NoCgroups {
|
||||
switch {
|
||||
case (rootless.IsRootless() && !unified) || c.config.NoCgroups:
|
||||
return "", nil
|
||||
} else if c.runtime.config.CgroupManager == define.SystemdCgroupsManager {
|
||||
case c.runtime.config.CgroupManager == define.SystemdCgroupsManager:
|
||||
// When runc is set to use Systemd as a cgroup manager, it
|
||||
// expects cgroups to be passed as follows:
|
||||
// slice:prefix:name
|
||||
systemdCgroups := fmt.Sprintf("%s:libpod:%s", path.Base(c.config.CgroupParent), c.ID())
|
||||
logrus.Debugf("Setting CGroups for container %s to %s", c.ID(), systemdCgroups)
|
||||
return systemdCgroups, nil
|
||||
} else if c.runtime.config.CgroupManager == define.CgroupfsCgroupsManager {
|
||||
case c.runtime.config.CgroupManager == define.CgroupfsCgroupsManager:
|
||||
cgroupPath, err := c.CGroupPath()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
logrus.Debugf("Setting CGroup path for container %s to %s", c.ID(), cgroupPath)
|
||||
return cgroupPath, nil
|
||||
} else {
|
||||
default:
|
||||
return "", errors.Wrapf(define.ErrInvalidArg, "invalid cgroup manager %s requested", c.runtime.config.CgroupManager)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,8 +129,6 @@ func StringToStatus(name string) (Status, error) {
|
|||
return Attach, nil
|
||||
case Checkpoint.String():
|
||||
return Checkpoint, nil
|
||||
case Restore.String():
|
||||
return Restore, nil
|
||||
case Cleanup.String():
|
||||
return Cleanup, nil
|
||||
case Commit.String():
|
||||
|
|
|
@ -238,7 +238,7 @@ func (c *Container) updateHealthCheckLog(hcl HealthCheckLog, inStartPeriod bool)
|
|||
}
|
||||
if !inStartPeriod {
|
||||
// increment failing streak
|
||||
healthCheck.FailingStreak = healthCheck.FailingStreak + 1
|
||||
healthCheck.FailingStreak += 1
|
||||
// if failing streak > retries, then status to unhealthy
|
||||
if healthCheck.FailingStreak >= c.HealthCheckConfig().Retries {
|
||||
healthCheck.Status = HealthCheckUnhealthy
|
||||
|
|
|
@ -902,8 +902,7 @@ func (i *Image) Annotations(ctx context.Context) (map[string]string, error) {
|
|||
}
|
||||
}
|
||||
annotations := make(map[string]string)
|
||||
switch manifestType {
|
||||
case ociv1.MediaTypeImageManifest:
|
||||
if manifestType == ociv1.MediaTypeImageManifest {
|
||||
var m ociv1.Manifest
|
||||
if err := json.Unmarshal(imageManifest, &m); err == nil {
|
||||
for k, v := range m.Annotations {
|
||||
|
|
|
@ -15,7 +15,7 @@ import (
|
|||
"github.com/opencontainers/runtime-tools/generate"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"k8s.io/api/core/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
|
@ -365,11 +365,12 @@ func generateKubeVolumeMount(m specs.Mount) (v1.VolumeMount, v1.Volume, error) {
|
|||
// neither a directory or a file lives here, default to creating a directory
|
||||
// TODO should this be an error instead?
|
||||
var hostPathType v1.HostPathType
|
||||
if err != nil {
|
||||
switch {
|
||||
case err != nil:
|
||||
hostPathType = v1.HostPathDirectoryOrCreate
|
||||
} else if isDir {
|
||||
case isDir:
|
||||
hostPathType = v1.HostPathDirectory
|
||||
} else {
|
||||
default:
|
||||
hostPathType = v1.HostPathFile
|
||||
}
|
||||
vo.HostPath.Type = &hostPathType
|
||||
|
|
|
@ -96,7 +96,7 @@ func getTailLog(path string, tail int) ([]*LogLine, error) {
|
|||
}
|
||||
nlls = append(nlls, nll)
|
||||
if !nll.Partial() {
|
||||
tailCounter = tailCounter + 1
|
||||
tailCounter++
|
||||
}
|
||||
if tailCounter == tail {
|
||||
break
|
||||
|
@ -105,9 +105,9 @@ func getTailLog(path string, tail int) ([]*LogLine, error) {
|
|||
// Now we iterate the results and assemble partial messages to become full messages
|
||||
for _, nll := range nlls {
|
||||
if nll.Partial() {
|
||||
partial = partial + nll.Msg
|
||||
partial += nll.Msg
|
||||
} else {
|
||||
nll.Msg = nll.Msg + partial
|
||||
nll.Msg += partial
|
||||
tailLog = append(tailLog, nll)
|
||||
partial = ""
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ func (l *LogLine) String(options *LogOptions) string {
|
|||
out = fmt.Sprintf("%s ", cid)
|
||||
}
|
||||
if options.Timestamps {
|
||||
out = out + fmt.Sprintf("%s ", l.Time.Format(LogTimeFormat))
|
||||
out += fmt.Sprintf("%s ", l.Time.Format(LogTimeFormat))
|
||||
}
|
||||
return out + l.Msg
|
||||
}
|
||||
|
|
|
@ -586,7 +586,8 @@ func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options
|
|||
|
||||
// we don't want to step on users fds they asked to preserve
|
||||
// Since 0-2 are used for stdio, start the fds we pass in at preserveFDs+3
|
||||
execCmd.Env = append(r.conmonEnv, fmt.Sprintf("_OCI_SYNCPIPE=%d", options.PreserveFDs+3), fmt.Sprintf("_OCI_STARTPIPE=%d", options.PreserveFDs+4), fmt.Sprintf("_OCI_ATTACHPIPE=%d", options.PreserveFDs+5))
|
||||
execCmd.Env = r.conmonEnv
|
||||
execCmd.Env = append(execCmd.Env, fmt.Sprintf("_OCI_SYNCPIPE=%d", options.PreserveFDs+3), fmt.Sprintf("_OCI_STARTPIPE=%d", options.PreserveFDs+4), fmt.Sprintf("_OCI_ATTACHPIPE=%d", options.PreserveFDs+5))
|
||||
execCmd.Env = append(execCmd.Env, conmonEnv...)
|
||||
|
||||
execCmd.ExtraFiles = append(execCmd.ExtraFiles, childSyncPipe, childStartPipe, childAttachPipe)
|
||||
|
@ -998,7 +999,8 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
|
|||
return err
|
||||
}
|
||||
|
||||
cmd.Env = append(r.conmonEnv, fmt.Sprintf("_OCI_SYNCPIPE=%d", 3), fmt.Sprintf("_OCI_STARTPIPE=%d", 4))
|
||||
cmd.Env = r.conmonEnv
|
||||
cmd.Env = append(cmd.Env, fmt.Sprintf("_OCI_SYNCPIPE=%d", 3), fmt.Sprintf("_OCI_STARTPIPE=%d", 4))
|
||||
cmd.Env = append(cmd.Env, conmonEnv...)
|
||||
cmd.ExtraFiles = append(cmd.ExtraFiles, childSyncPipe, childStartPipe)
|
||||
cmd.ExtraFiles = append(cmd.ExtraFiles, envFiles...)
|
||||
|
@ -1306,12 +1308,10 @@ func (r *ConmonOCIRuntime) moveConmonToCgroupAndSignal(ctr *Container, cmd *exec
|
|||
control, err := cgroups.New(cgroupPath, &spec.LinuxResources{})
|
||||
if err != nil {
|
||||
logrus.Warnf("Failed to add conmon to cgroupfs sandbox cgroup: %v", err)
|
||||
} else {
|
||||
} else if err := control.AddPid(cmd.Process.Pid); err != nil {
|
||||
// we need to remove this defer and delete the cgroup once conmon exits
|
||||
// maybe need a conmon monitor?
|
||||
if err := control.AddPid(cmd.Process.Pid); err != nil {
|
||||
logrus.Warnf("Failed to add conmon to cgroupfs sandbox cgroup: %v", err)
|
||||
}
|
||||
logrus.Warnf("Failed to add conmon to cgroupfs sandbox cgroup: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -733,7 +733,9 @@ func WithExitCommand(exitCommand []string) CtrCreateOption {
|
|||
return define.ErrCtrFinalized
|
||||
}
|
||||
|
||||
ctr.config.ExitCommand = append(exitCommand, ctr.ID())
|
||||
ctr.config.ExitCommand = exitCommand
|
||||
ctr.config.ExitCommand = append(ctr.config.ExitCommand, ctr.ID())
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,12 +180,13 @@ func getLockManager(runtime *Runtime) (lock.Manager, error) {
|
|||
// Set up the lock manager
|
||||
manager, err = lock.OpenSHMLockManager(lockPath, runtime.config.NumLocks)
|
||||
if err != nil {
|
||||
if os.IsNotExist(errors.Cause(err)) {
|
||||
switch {
|
||||
case os.IsNotExist(errors.Cause(err)):
|
||||
manager, err = lock.NewSHMLockManager(lockPath, runtime.config.NumLocks)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get new shm lock manager")
|
||||
}
|
||||
} else if errors.Cause(err) == syscall.ERANGE && runtime.doRenumber {
|
||||
case errors.Cause(err) == syscall.ERANGE && runtime.doRenumber:
|
||||
logrus.Debugf("Number of locks does not match - removing old locks")
|
||||
|
||||
// ERANGE indicates a lock numbering mismatch.
|
||||
|
@ -199,7 +200,7 @@ func getLockManager(runtime *Runtime) (lock.Manager, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
@ -289,10 +290,8 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) {
|
|||
logrus.Debug("Not configuring container store")
|
||||
} else if runtime.noStore {
|
||||
logrus.Debug("No store required. Not opening container store.")
|
||||
} else {
|
||||
if err := runtime.configureStore(); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if err := runtime.configureStore(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil && store != nil {
|
||||
|
@ -718,18 +717,14 @@ func (r *Runtime) generateName() (string, error) {
|
|||
// Make sure container with this name does not exist
|
||||
if _, err := r.state.LookupContainer(name); err == nil {
|
||||
continue
|
||||
} else {
|
||||
if errors.Cause(err) != define.ErrNoSuchCtr {
|
||||
return "", err
|
||||
}
|
||||
} else if errors.Cause(err) != define.ErrNoSuchCtr {
|
||||
return "", err
|
||||
}
|
||||
// Make sure pod with this name does not exist
|
||||
if _, err := r.state.LookupPod(name); err == nil {
|
||||
continue
|
||||
} else {
|
||||
if errors.Cause(err) != define.ErrNoSuchPod {
|
||||
return "", err
|
||||
}
|
||||
} else if errors.Cause(err) != define.ErrNoSuchPod {
|
||||
return "", err
|
||||
}
|
||||
return name, nil
|
||||
}
|
||||
|
|
|
@ -107,15 +107,13 @@ func (r *Runtime) removeStorageContainer(idOrName string, force bool) error {
|
|||
if timesMounted > 0 {
|
||||
return errors.Wrapf(define.ErrCtrStateInvalid, "container %q is mounted and cannot be removed without using force", idOrName)
|
||||
}
|
||||
} else {
|
||||
if _, err := r.store.Unmount(ctr.ID, true); err != nil {
|
||||
if errors.Cause(err) == storage.ErrContainerUnknown {
|
||||
// Container again gone, no error
|
||||
logrus.Warnf("Storage for container %s already removed", ctr.ID)
|
||||
return nil
|
||||
}
|
||||
return errors.Wrapf(err, "error unmounting container %q", idOrName)
|
||||
} else if _, err := r.store.Unmount(ctr.ID, true); err != nil {
|
||||
if errors.Cause(err) == storage.ErrContainerUnknown {
|
||||
// Container again gone, no error
|
||||
logrus.Warnf("Storage for container %s already removed", ctr.ID)
|
||||
return nil
|
||||
}
|
||||
return errors.Wrapf(err, "error unmounting container %q", idOrName)
|
||||
}
|
||||
|
||||
if err := r.store.DeleteContainer(ctr.ID); err != nil {
|
||||
|
|
|
@ -234,15 +234,16 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (c *Contai
|
|||
}
|
||||
case define.SystemdCgroupsManager:
|
||||
if ctr.config.CgroupParent == "" {
|
||||
if pod != nil && pod.config.UsePodCgroup {
|
||||
switch {
|
||||
case pod != nil && pod.config.UsePodCgroup:
|
||||
podCgroup, err := pod.CgroupPath()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error retrieving pod %s cgroup", pod.ID())
|
||||
}
|
||||
ctr.config.CgroupParent = podCgroup
|
||||
} else if rootless.IsRootless() {
|
||||
case rootless.IsRootless():
|
||||
ctr.config.CgroupParent = SystemdDefaultRootlessCgroupParent
|
||||
} else {
|
||||
default:
|
||||
ctr.config.CgroupParent = SystemdDefaultCgroupParent
|
||||
}
|
||||
} else if len(ctr.config.CgroupParent) < 6 || !strings.HasSuffix(path.Base(ctr.config.CgroupParent), ".slice") {
|
||||
|
@ -361,10 +362,8 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (c *Contai
|
|||
if err := r.state.AddContainerToPod(pod, ctr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if err := r.state.AddContainer(ctr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if err := r.state.AddContainer(ctr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctr.newContainerEvent(events.Create)
|
||||
return ctr, nil
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
)
|
||||
|
||||
// NewPod makes a new, empty pod
|
||||
func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Pod, Err error) {
|
||||
func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Pod, deferredErr error) {
|
||||
r.lock.Lock()
|
||||
defer r.lock.Unlock()
|
||||
|
||||
|
@ -65,7 +65,7 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Po
|
|||
pod.config.LockID = pod.lock.ID()
|
||||
|
||||
defer func() {
|
||||
if Err != nil {
|
||||
if deferredErr != nil {
|
||||
if err := pod.lock.Free(); err != nil {
|
||||
logrus.Errorf("Error freeing pod lock after failed creation: %v", err)
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Po
|
|||
return nil, errors.Wrapf(err, "error adding pod to state")
|
||||
}
|
||||
defer func() {
|
||||
if Err != nil {
|
||||
if deferredErr != nil {
|
||||
if err := r.removePod(ctx, pod, true, true); err != nil {
|
||||
logrus.Errorf("Error removing pod after pause container creation failure: %v", err)
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ func (r *Runtime) NewVolume(ctx context.Context, options ...VolumeCreateOption)
|
|||
}
|
||||
|
||||
// newVolume creates a new empty volume
|
||||
func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption) (_ *Volume, Err error) {
|
||||
func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption) (_ *Volume, deferredErr error) {
|
||||
volume, err := newVolume(r)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error creating volume")
|
||||
|
@ -98,7 +98,7 @@ func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption)
|
|||
volume.config.LockID = volume.lock.ID()
|
||||
|
||||
defer func() {
|
||||
if Err != nil {
|
||||
if deferredErr != nil {
|
||||
if err := volume.lock.Free(); err != nil {
|
||||
logrus.Errorf("Error freeing volume lock after failed creation: %v", err)
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ func (v *Volume) mount() error {
|
|||
// If the count is non-zero, the volume is already mounted.
|
||||
// Nothing to do.
|
||||
if v.state.MountCount > 0 {
|
||||
v.state.MountCount = v.state.MountCount + 1
|
||||
v.state.MountCount += 1
|
||||
logrus.Debugf("Volume %s mount count now at %d", v.Name(), v.state.MountCount)
|
||||
return v.save()
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ func (v *Volume) mount() error {
|
|||
logrus.Debugf("Mounted volume %s", v.Name())
|
||||
|
||||
// Increment the mount counter
|
||||
v.state.MountCount = v.state.MountCount + 1
|
||||
v.state.MountCount += 1
|
||||
logrus.Debugf("Volume %s mount count now at %d", v.Name(), v.state.MountCount)
|
||||
return v.save()
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ func (v *Volume) unmount(force bool) error {
|
|||
}
|
||||
|
||||
if !force {
|
||||
v.state.MountCount = v.state.MountCount - 1
|
||||
v.state.MountCount -= 1
|
||||
} else {
|
||||
v.state.MountCount = 0
|
||||
}
|
||||
|
|
|
@ -609,11 +609,12 @@ func (r *LocalRuntime) Restore(ctx context.Context, c *cliconfig.RestoreValues)
|
|||
return state == define.ContainerStateExited
|
||||
})
|
||||
|
||||
if c.Import != "" {
|
||||
switch {
|
||||
case c.Import != "":
|
||||
containers, err = crImportCheckpoint(ctx, r.Runtime, c.Import, c.Name)
|
||||
} else if c.All {
|
||||
case c.All:
|
||||
containers, err = r.GetContainers(filterFuncs...)
|
||||
} else {
|
||||
default:
|
||||
containers, err = shortcuts.GetContainersByContext(false, c.Latest, c.InputArgs, r.Runtime)
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -835,25 +836,26 @@ func (r *LocalRuntime) Restart(ctx context.Context, c *cliconfig.RestartValues)
|
|||
inputTimeout := c.Timeout
|
||||
|
||||
// Handle --latest
|
||||
if c.Latest {
|
||||
switch {
|
||||
case c.Latest:
|
||||
lastCtr, err := r.Runtime.GetLatestContainer()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "unable to get latest container")
|
||||
}
|
||||
restartContainers = append(restartContainers, lastCtr)
|
||||
} else if c.Running {
|
||||
case c.Running:
|
||||
containers, err = r.GetRunningContainers()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
restartContainers = append(restartContainers, containers...)
|
||||
} else if c.All {
|
||||
case c.All:
|
||||
containers, err = r.Runtime.GetAllContainers()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
restartContainers = append(restartContainers, containers...)
|
||||
} else {
|
||||
default:
|
||||
for _, id := range c.InputArgs {
|
||||
ctr, err := r.Runtime.LookupContainer(id)
|
||||
if err != nil {
|
||||
|
|
|
@ -407,7 +407,8 @@ func (r *LocalRuntime) Events(c *cliconfig.EventValues) error {
|
|||
}
|
||||
w := bufio.NewWriter(os.Stdout)
|
||||
for event := range eventChannel {
|
||||
if c.Format == formats.JSONString {
|
||||
switch {
|
||||
case c.Format == formats.JSONString:
|
||||
jsonStr, err := event.ToJSONString()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to format json")
|
||||
|
@ -415,11 +416,11 @@ func (r *LocalRuntime) Events(c *cliconfig.EventValues) error {
|
|||
if _, err := w.Write([]byte(jsonStr)); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if len(c.Format) > 0 {
|
||||
case len(c.Format) > 0:
|
||||
if err := tmpl.Execute(w, event); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
if _, err := w.Write([]byte(event.ToHumanReadable())); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -42,12 +42,13 @@ func GetContainersByContext(all, latest bool, names []string, runtime *libpod.Ru
|
|||
var ctr *libpod.Container
|
||||
ctrs = []*libpod.Container{}
|
||||
|
||||
if all {
|
||||
switch {
|
||||
case all:
|
||||
ctrs, err = runtime.GetAllContainers()
|
||||
} else if latest {
|
||||
case latest:
|
||||
ctr, err = runtime.GetLatestContainer()
|
||||
ctrs = append(ctrs, ctr)
|
||||
} else {
|
||||
default:
|
||||
for _, n := range names {
|
||||
ctr, e := runtime.LookupContainer(n)
|
||||
if e != nil {
|
||||
|
|
|
@ -12,19 +12,19 @@ import (
|
|||
|
||||
// WriteResponse encodes the given value as JSON or string and renders it for http client
|
||||
func WriteResponse(w http.ResponseWriter, code int, value interface{}) {
|
||||
switch value.(type) {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
w.Header().Set("Content-Type", "text/plain; charset=us-ascii")
|
||||
w.WriteHeader(code)
|
||||
|
||||
if _, err := fmt.Fprintln(w, value); err != nil {
|
||||
if _, err := fmt.Fprintln(w, v); err != nil {
|
||||
log.Errorf("unable to send string response: %q", err)
|
||||
}
|
||||
case *os.File:
|
||||
w.Header().Set("Content-Type", "application/octet; charset=us-ascii")
|
||||
w.WriteHeader(code)
|
||||
|
||||
if _, err := io.Copy(w, value.(*os.File)); err != nil {
|
||||
if _, err := io.Copy(w, v); err != nil {
|
||||
log.Errorf("unable to copy to response: %q", err)
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -155,7 +155,7 @@ func (c *CgroupControl) getCgroupv1Path(name string) string {
|
|||
}
|
||||
|
||||
// createCgroupv2Path creates the cgroupv2 path and enables all the available controllers
|
||||
func createCgroupv2Path(path string) (Err error) {
|
||||
func createCgroupv2Path(path string) (deferredError error) {
|
||||
content, err := ioutil.ReadFile("/sys/fs/cgroup/cgroup.controllers")
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "read /sys/fs/cgroup/cgroup.controllers")
|
||||
|
@ -169,7 +169,7 @@ func createCgroupv2Path(path string) (Err error) {
|
|||
if i == 0 {
|
||||
res = fmt.Sprintf("+%s", c)
|
||||
} else {
|
||||
res = res + fmt.Sprintf(" +%s", c)
|
||||
res += fmt.Sprintf(" +%s", c)
|
||||
}
|
||||
}
|
||||
resByte := []byte(res)
|
||||
|
@ -186,7 +186,7 @@ func createCgroupv2Path(path string) (Err error) {
|
|||
} else {
|
||||
// If the directory was created, be sure it is not left around on errors.
|
||||
defer func() {
|
||||
if Err != nil {
|
||||
if deferredError != nil {
|
||||
os.Remove(current)
|
||||
}
|
||||
}()
|
||||
|
|
|
@ -44,7 +44,8 @@ func (c *NetworkConfig) ToCreateOptions(runtime *libpod.Runtime, userns *UserCon
|
|||
}
|
||||
}
|
||||
|
||||
if c.NetMode.IsNS() {
|
||||
switch {
|
||||
case c.NetMode.IsNS():
|
||||
ns := c.NetMode.NS()
|
||||
if ns == "" {
|
||||
return nil, errors.Errorf("invalid empty user-defined network namespace")
|
||||
|
@ -53,13 +54,13 @@ func (c *NetworkConfig) ToCreateOptions(runtime *libpod.Runtime, userns *UserCon
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if c.NetMode.IsContainer() {
|
||||
case c.NetMode.IsContainer():
|
||||
connectedCtr, err := runtime.LookupContainer(c.NetMode.Container())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "container %q not found", c.NetMode.Container())
|
||||
}
|
||||
options = append(options, libpod.WithNetNSFrom(connectedCtr))
|
||||
} else if !c.NetMode.IsHost() && !c.NetMode.IsNone() {
|
||||
case !c.NetMode.IsHost() && !c.NetMode.IsNone():
|
||||
postConfigureNetNS := userns.getPostConfigureNetNS()
|
||||
options = append(options, libpod.WithNetNS(portBindings, postConfigureNetNS, string(c.NetMode), networks))
|
||||
}
|
||||
|
@ -102,29 +103,31 @@ func (c *NetworkConfig) ToCreateOptions(runtime *libpod.Runtime, userns *UserCon
|
|||
// state of the NetworkConfig.
|
||||
func (c *NetworkConfig) ConfigureGenerator(g *generate.Generator) error {
|
||||
netMode := c.NetMode
|
||||
if netMode.IsHost() {
|
||||
netCtr := netMode.Container()
|
||||
switch {
|
||||
case netMode.IsHost():
|
||||
logrus.Debug("Using host netmode")
|
||||
if err := g.RemoveLinuxNamespace(string(spec.NetworkNamespace)); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if netMode.IsNone() {
|
||||
case netMode.IsNone():
|
||||
logrus.Debug("Using none netmode")
|
||||
} else if netMode.IsBridge() {
|
||||
case netMode.IsBridge():
|
||||
logrus.Debug("Using bridge netmode")
|
||||
} else if netCtr := netMode.Container(); netCtr != "" {
|
||||
case netCtr != "":
|
||||
logrus.Debugf("using container %s netmode", netCtr)
|
||||
} else if IsNS(string(netMode)) {
|
||||
case IsNS(string(netMode)):
|
||||
logrus.Debug("Using ns netmode")
|
||||
if err := g.AddOrReplaceLinuxNamespace(string(spec.NetworkNamespace), NS(string(netMode))); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if IsPod(string(netMode)) {
|
||||
case IsPod(string(netMode)):
|
||||
logrus.Debug("Using pod netmode, unless pod is not sharing")
|
||||
} else if netMode.IsSlirp4netns() {
|
||||
case netMode.IsSlirp4netns():
|
||||
logrus.Debug("Using slirp4netns netmode")
|
||||
} else if netMode.IsUserDefined() {
|
||||
case netMode.IsUserDefined():
|
||||
logrus.Debug("Using user defined netmode")
|
||||
} else {
|
||||
default:
|
||||
return errors.Errorf("unknown network mode")
|
||||
}
|
||||
|
||||
|
@ -220,7 +223,8 @@ func (c *CgroupConfig) ToCreateOptions(runtime *libpod.Runtime) ([]libpod.CtrCre
|
|||
// ToCreateOptions converts the input to container create options.
|
||||
func (c *UserConfig) ToCreateOptions(runtime *libpod.Runtime) ([]libpod.CtrCreateOption, error) {
|
||||
options := make([]libpod.CtrCreateOption, 0)
|
||||
if c.UsernsMode.IsNS() {
|
||||
switch {
|
||||
case c.UsernsMode.IsNS():
|
||||
ns := c.UsernsMode.NS()
|
||||
if ns == "" {
|
||||
return nil, errors.Errorf("invalid empty user-defined user namespace")
|
||||
|
@ -230,13 +234,13 @@ func (c *UserConfig) ToCreateOptions(runtime *libpod.Runtime) ([]libpod.CtrCreat
|
|||
return nil, err
|
||||
}
|
||||
options = append(options, libpod.WithIDMappings(*c.IDMappings))
|
||||
} else if c.UsernsMode.IsContainer() {
|
||||
case c.UsernsMode.IsContainer():
|
||||
connectedCtr, err := runtime.LookupContainer(c.UsernsMode.Container())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "container %q not found", c.UsernsMode.Container())
|
||||
}
|
||||
options = append(options, libpod.WithUserNSFrom(connectedCtr))
|
||||
} else {
|
||||
default:
|
||||
options = append(options, libpod.WithIDMappings(*c.IDMappings))
|
||||
}
|
||||
|
||||
|
@ -413,20 +417,22 @@ func (c *UtsConfig) ToCreateOptions(runtime *libpod.Runtime, pod *libpod.Pod) ([
|
|||
// of the UtsConfig.
|
||||
func (c *UtsConfig) ConfigureGenerator(g *generate.Generator, net *NetworkConfig, runtime *libpod.Runtime) error {
|
||||
hostname := c.Hostname
|
||||
utsCtrID := c.UtsMode.Container()
|
||||
var err error
|
||||
if hostname == "" {
|
||||
if utsCtrID := c.UtsMode.Container(); utsCtrID != "" {
|
||||
switch {
|
||||
case utsCtrID != "":
|
||||
utsCtr, err := runtime.GetContainer(utsCtrID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to retrieve hostname from dependency container %s", utsCtrID)
|
||||
}
|
||||
hostname = utsCtr.Hostname()
|
||||
} else if net.NetMode.IsHost() || c.UtsMode.IsHost() {
|
||||
case net.NetMode.IsHost() || c.UtsMode.IsHost():
|
||||
hostname, err = os.Hostname()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to retrieve hostname of the host")
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
logrus.Debug("No hostname set; container's hostname will default to runtime default")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -409,9 +409,10 @@ func getBindMount(args []string) (spec.Mount, error) {
|
|||
// ro=[true|false]
|
||||
// rw
|
||||
// rw=[true|false]
|
||||
if len(kv) == 1 {
|
||||
switch len(kv) {
|
||||
case 1:
|
||||
newMount.Options = append(newMount.Options, kv[0])
|
||||
} else if len(kv) == 2 {
|
||||
case 2:
|
||||
switch strings.ToLower(kv[1]) {
|
||||
case "true":
|
||||
newMount.Options = append(newMount.Options, kv[0])
|
||||
|
@ -424,7 +425,7 @@ func getBindMount(args []string) (spec.Mount, error) {
|
|||
default:
|
||||
return newMount, errors.Wrapf(optionArgError, "%s must be set to true or false, instead received %q", kv[0], kv[1])
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
return newMount, errors.Wrapf(optionArgError, "badly formatted option %q", val)
|
||||
}
|
||||
case "nosuid", "suid":
|
||||
|
|
|
@ -34,7 +34,7 @@ func GetTimestamp(value string, reference time.Time) (string, error) {
|
|||
// if the string has a Z or a + or three dashes use parse otherwise use parseinlocation
|
||||
parseInLocation := !(strings.ContainsAny(value, "zZ+") || strings.Count(value, "-") == 3)
|
||||
|
||||
if strings.Contains(value, ".") {
|
||||
if strings.Contains(value, ".") { // nolint(gocritic)
|
||||
if parseInLocation {
|
||||
format = rFC3339NanoLocal
|
||||
} else {
|
||||
|
|
|
@ -321,14 +321,14 @@ func ParseSignal(rawSignal string) (syscall.Signal, error) {
|
|||
}
|
||||
|
||||
// ParseIDMapping takes idmappings and subuid and subgid maps and returns a storage mapping
|
||||
func ParseIDMapping(mode namespaces.UsernsMode, UIDMapSlice, GIDMapSlice []string, subUIDMap, subGIDMap string) (*storage.IDMappingOptions, error) {
|
||||
func ParseIDMapping(mode namespaces.UsernsMode, uidMapSlice, gidMapSlice []string, subUIDMap, subGIDMap string) (*storage.IDMappingOptions, error) {
|
||||
options := storage.IDMappingOptions{
|
||||
HostUIDMapping: true,
|
||||
HostGIDMapping: true,
|
||||
}
|
||||
|
||||
if mode.IsKeepID() {
|
||||
if len(UIDMapSlice) > 0 || len(GIDMapSlice) > 0 {
|
||||
if len(uidMapSlice) > 0 || len(gidMapSlice) > 0 {
|
||||
return nil, errors.New("cannot specify custom mappings with --userns=keep-id")
|
||||
}
|
||||
if len(subUIDMap) > 0 || len(subGIDMap) > 0 {
|
||||
|
@ -384,17 +384,17 @@ func ParseIDMapping(mode namespaces.UsernsMode, UIDMapSlice, GIDMapSlice []strin
|
|||
if subUIDMap == "" && subGIDMap != "" {
|
||||
subUIDMap = subGIDMap
|
||||
}
|
||||
if len(GIDMapSlice) == 0 && len(UIDMapSlice) != 0 {
|
||||
GIDMapSlice = UIDMapSlice
|
||||
if len(gidMapSlice) == 0 && len(uidMapSlice) != 0 {
|
||||
gidMapSlice = uidMapSlice
|
||||
}
|
||||
if len(UIDMapSlice) == 0 && len(GIDMapSlice) != 0 {
|
||||
UIDMapSlice = GIDMapSlice
|
||||
if len(uidMapSlice) == 0 && len(gidMapSlice) != 0 {
|
||||
uidMapSlice = gidMapSlice
|
||||
}
|
||||
if len(UIDMapSlice) == 0 && subUIDMap == "" && os.Getuid() != 0 {
|
||||
UIDMapSlice = []string{fmt.Sprintf("0:%d:1", os.Getuid())}
|
||||
if len(uidMapSlice) == 0 && subUIDMap == "" && os.Getuid() != 0 {
|
||||
uidMapSlice = []string{fmt.Sprintf("0:%d:1", os.Getuid())}
|
||||
}
|
||||
if len(GIDMapSlice) == 0 && subGIDMap == "" && os.Getuid() != 0 {
|
||||
GIDMapSlice = []string{fmt.Sprintf("0:%d:1", os.Getgid())}
|
||||
if len(gidMapSlice) == 0 && subGIDMap == "" && os.Getuid() != 0 {
|
||||
gidMapSlice = []string{fmt.Sprintf("0:%d:1", os.Getgid())}
|
||||
}
|
||||
|
||||
if subUIDMap != "" && subGIDMap != "" {
|
||||
|
@ -405,11 +405,11 @@ func ParseIDMapping(mode namespaces.UsernsMode, UIDMapSlice, GIDMapSlice []strin
|
|||
options.UIDMap = mappings.UIDs()
|
||||
options.GIDMap = mappings.GIDs()
|
||||
}
|
||||
parsedUIDMap, err := idtools.ParseIDMap(UIDMapSlice, "UID")
|
||||
parsedUIDMap, err := idtools.ParseIDMap(uidMapSlice, "UID")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parsedGIDMap, err := idtools.ParseIDMap(GIDMapSlice, "GID")
|
||||
parsedGIDMap, err := idtools.ParseIDMap(gidMapSlice, "GID")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
10
vendor/github.com/pkg/profile/.travis.yml
generated
vendored
10
vendor/github.com/pkg/profile/.travis.yml
generated
vendored
|
@ -1,10 +0,0 @@
|
|||
language: go
|
||||
go_import_path: github.com/pkg/profile
|
||||
go:
|
||||
- 1.12.x
|
||||
- 1.13.x
|
||||
- tip
|
||||
|
||||
script:
|
||||
- go test github.com/pkg/profile
|
||||
- go test -race github.com/pkg/profile
|
1
vendor/github.com/pkg/profile/AUTHORS
generated
vendored
1
vendor/github.com/pkg/profile/AUTHORS
generated
vendored
|
@ -1 +0,0 @@
|
|||
Dave Cheney <dave@cheney.net>
|
24
vendor/github.com/pkg/profile/LICENSE
generated
vendored
24
vendor/github.com/pkg/profile/LICENSE
generated
vendored
|
@ -1,24 +0,0 @@
|
|||
Copyright (c) 2013 Dave Cheney. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
54
vendor/github.com/pkg/profile/README.md
generated
vendored
54
vendor/github.com/pkg/profile/README.md
generated
vendored
|
@ -1,54 +0,0 @@
|
|||
profile
|
||||
=======
|
||||
|
||||
Simple profiling support package for Go
|
||||
|
||||
[![Build Status](https://travis-ci.org/pkg/profile.svg?branch=master)](https://travis-ci.org/pkg/profile) [![GoDoc](http://godoc.org/github.com/pkg/profile?status.svg)](http://godoc.org/github.com/pkg/profile)
|
||||
|
||||
|
||||
installation
|
||||
------------
|
||||
|
||||
go get github.com/pkg/profile
|
||||
|
||||
usage
|
||||
-----
|
||||
|
||||
Enabling profiling in your application is as simple as one line at the top of your main function
|
||||
|
||||
```go
|
||||
import "github.com/pkg/profile"
|
||||
|
||||
func main() {
|
||||
defer profile.Start().Stop()
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
options
|
||||
-------
|
||||
|
||||
What to profile is controlled by config value passed to profile.Start.
|
||||
By default CPU profiling is enabled.
|
||||
|
||||
```go
|
||||
import "github.com/pkg/profile"
|
||||
|
||||
func main() {
|
||||
// p.Stop() must be called before the program exits to
|
||||
// ensure profiling information is written to disk.
|
||||
p := profile.Start(profile.MemProfile, profile.ProfilePath("."), profile.NoShutdownHook)
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Several convenience package level values are provided for cpu, memory, and block (contention) profiling.
|
||||
|
||||
For more complex options, consult the [documentation](http://godoc.org/github.com/pkg/profile).
|
||||
|
||||
contributing
|
||||
------------
|
||||
|
||||
We welcome pull requests, bug fixes and issue reports.
|
||||
|
||||
Before proposing a change, please discuss it first by raising an issue.
|
3
vendor/github.com/pkg/profile/go.mod
generated
vendored
3
vendor/github.com/pkg/profile/go.mod
generated
vendored
|
@ -1,3 +0,0 @@
|
|||
module github.com/pkg/profile
|
||||
|
||||
go 1.12
|
284
vendor/github.com/pkg/profile/profile.go
generated
vendored
284
vendor/github.com/pkg/profile/profile.go
generated
vendored
|
@ -1,284 +0,0 @@
|
|||
// Package profile provides a simple way to manage runtime/pprof
|
||||
// profiling of your Go application.
|
||||
package profile
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
"runtime/trace"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
const (
|
||||
cpuMode = iota
|
||||
memMode
|
||||
mutexMode
|
||||
blockMode
|
||||
traceMode
|
||||
threadCreateMode
|
||||
goroutineMode
|
||||
)
|
||||
|
||||
// Profile represents an active profiling session.
|
||||
type Profile struct {
|
||||
// quiet suppresses informational messages during profiling.
|
||||
quiet bool
|
||||
|
||||
// noShutdownHook controls whether the profiling package should
|
||||
// hook SIGINT to write profiles cleanly.
|
||||
noShutdownHook bool
|
||||
|
||||
// mode holds the type of profiling that will be made
|
||||
mode int
|
||||
|
||||
// path holds the base path where various profiling files are written.
|
||||
// If blank, the base path will be generated by ioutil.TempDir.
|
||||
path string
|
||||
|
||||
// memProfileRate holds the rate for the memory profile.
|
||||
memProfileRate int
|
||||
|
||||
// closer holds a cleanup function that run after each profile
|
||||
closer func()
|
||||
|
||||
// stopped records if a call to profile.Stop has been made
|
||||
stopped uint32
|
||||
}
|
||||
|
||||
// NoShutdownHook controls whether the profiling package should
|
||||
// hook SIGINT to write profiles cleanly.
|
||||
// Programs with more sophisticated signal handling should set
|
||||
// this to true and ensure the Stop() function returned from Start()
|
||||
// is called during shutdown.
|
||||
func NoShutdownHook(p *Profile) { p.noShutdownHook = true }
|
||||
|
||||
// Quiet suppresses informational messages during profiling.
|
||||
func Quiet(p *Profile) { p.quiet = true }
|
||||
|
||||
// CPUProfile enables cpu profiling.
|
||||
// It disables any previous profiling settings.
|
||||
func CPUProfile(p *Profile) { p.mode = cpuMode }
|
||||
|
||||
// DefaultMemProfileRate is the default memory profiling rate.
|
||||
// See also http://golang.org/pkg/runtime/#pkg-variables
|
||||
const DefaultMemProfileRate = 4096
|
||||
|
||||
// MemProfile enables memory profiling.
|
||||
// It disables any previous profiling settings.
|
||||
func MemProfile(p *Profile) {
|
||||
p.memProfileRate = DefaultMemProfileRate
|
||||
p.mode = memMode
|
||||
}
|
||||
|
||||
// MemProfileRate enables memory profiling at the preferred rate.
|
||||
// It disables any previous profiling settings.
|
||||
func MemProfileRate(rate int) func(*Profile) {
|
||||
return func(p *Profile) {
|
||||
p.memProfileRate = rate
|
||||
p.mode = memMode
|
||||
}
|
||||
}
|
||||
|
||||
// MutexProfile enables mutex profiling.
|
||||
// It disables any previous profiling settings.
|
||||
func MutexProfile(p *Profile) { p.mode = mutexMode }
|
||||
|
||||
// BlockProfile enables block (contention) profiling.
|
||||
// It disables any previous profiling settings.
|
||||
func BlockProfile(p *Profile) { p.mode = blockMode }
|
||||
|
||||
// Trace profile enables execution tracing.
|
||||
// It disables any previous profiling settings.
|
||||
func TraceProfile(p *Profile) { p.mode = traceMode }
|
||||
|
||||
// ThreadcreationProfile enables thread creation profiling..
|
||||
// It disables any previous profiling settings.
|
||||
func ThreadcreationProfile(p *Profile) { p.mode = threadCreateMode }
|
||||
|
||||
// GoroutineProfile enables goroutine profiling.
|
||||
// It disables any previous profiling settings.
|
||||
func GoroutineProfile(p *Profile) { p.mode = goroutineMode }
|
||||
|
||||
// ProfilePath controls the base path where various profiling
|
||||
// files are written. If blank, the base path will be generated
|
||||
// by ioutil.TempDir.
|
||||
func ProfilePath(path string) func(*Profile) {
|
||||
return func(p *Profile) {
|
||||
p.path = path
|
||||
}
|
||||
}
|
||||
|
||||
// Stop stops the profile and flushes any unwritten data.
|
||||
func (p *Profile) Stop() {
|
||||
if !atomic.CompareAndSwapUint32(&p.stopped, 0, 1) {
|
||||
// someone has already called close
|
||||
return
|
||||
}
|
||||
p.closer()
|
||||
atomic.StoreUint32(&started, 0)
|
||||
}
|
||||
|
||||
// started is non zero if a profile is running.
|
||||
var started uint32
|
||||
|
||||
// Start starts a new profiling session.
|
||||
// The caller should call the Stop method on the value returned
|
||||
// to cleanly stop profiling.
|
||||
func Start(options ...func(*Profile)) interface {
|
||||
Stop()
|
||||
} {
|
||||
if !atomic.CompareAndSwapUint32(&started, 0, 1) {
|
||||
log.Fatal("profile: Start() already called")
|
||||
}
|
||||
|
||||
var prof Profile
|
||||
for _, option := range options {
|
||||
option(&prof)
|
||||
}
|
||||
|
||||
path, err := func() (string, error) {
|
||||
if p := prof.path; p != "" {
|
||||
return p, os.MkdirAll(p, 0777)
|
||||
}
|
||||
return ioutil.TempDir("", "profile")
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("profile: could not create initial output directory: %v", err)
|
||||
}
|
||||
|
||||
logf := func(format string, args ...interface{}) {
|
||||
if !prof.quiet {
|
||||
log.Printf(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
switch prof.mode {
|
||||
case cpuMode:
|
||||
fn := filepath.Join(path, "cpu.pprof")
|
||||
f, err := os.Create(fn)
|
||||
if err != nil {
|
||||
log.Fatalf("profile: could not create cpu profile %q: %v", fn, err)
|
||||
}
|
||||
logf("profile: cpu profiling enabled, %s", fn)
|
||||
pprof.StartCPUProfile(f)
|
||||
prof.closer = func() {
|
||||
pprof.StopCPUProfile()
|
||||
f.Close()
|
||||
logf("profile: cpu profiling disabled, %s", fn)
|
||||
}
|
||||
|
||||
case memMode:
|
||||
fn := filepath.Join(path, "mem.pprof")
|
||||
f, err := os.Create(fn)
|
||||
if err != nil {
|
||||
log.Fatalf("profile: could not create memory profile %q: %v", fn, err)
|
||||
}
|
||||
old := runtime.MemProfileRate
|
||||
runtime.MemProfileRate = prof.memProfileRate
|
||||
logf("profile: memory profiling enabled (rate %d), %s", runtime.MemProfileRate, fn)
|
||||
prof.closer = func() {
|
||||
pprof.Lookup("heap").WriteTo(f, 0)
|
||||
f.Close()
|
||||
runtime.MemProfileRate = old
|
||||
logf("profile: memory profiling disabled, %s", fn)
|
||||
}
|
||||
|
||||
case mutexMode:
|
||||
fn := filepath.Join(path, "mutex.pprof")
|
||||
f, err := os.Create(fn)
|
||||
if err != nil {
|
||||
log.Fatalf("profile: could not create mutex profile %q: %v", fn, err)
|
||||
}
|
||||
runtime.SetMutexProfileFraction(1)
|
||||
logf("profile: mutex profiling enabled, %s", fn)
|
||||
prof.closer = func() {
|
||||
if mp := pprof.Lookup("mutex"); mp != nil {
|
||||
mp.WriteTo(f, 0)
|
||||
}
|
||||
f.Close()
|
||||
runtime.SetMutexProfileFraction(0)
|
||||
logf("profile: mutex profiling disabled, %s", fn)
|
||||
}
|
||||
|
||||
case blockMode:
|
||||
fn := filepath.Join(path, "block.pprof")
|
||||
f, err := os.Create(fn)
|
||||
if err != nil {
|
||||
log.Fatalf("profile: could not create block profile %q: %v", fn, err)
|
||||
}
|
||||
runtime.SetBlockProfileRate(1)
|
||||
logf("profile: block profiling enabled, %s", fn)
|
||||
prof.closer = func() {
|
||||
pprof.Lookup("block").WriteTo(f, 0)
|
||||
f.Close()
|
||||
runtime.SetBlockProfileRate(0)
|
||||
logf("profile: block profiling disabled, %s", fn)
|
||||
}
|
||||
|
||||
case threadCreateMode:
|
||||
fn := filepath.Join(path, "threadcreation.pprof")
|
||||
f, err := os.Create(fn)
|
||||
if err != nil {
|
||||
log.Fatalf("profile: could not create thread creation profile %q: %v", fn, err)
|
||||
}
|
||||
logf("profile: thread creation profiling enabled, %s", fn)
|
||||
prof.closer = func() {
|
||||
if mp := pprof.Lookup("threadcreate"); mp != nil {
|
||||
mp.WriteTo(f, 0)
|
||||
}
|
||||
f.Close()
|
||||
logf("profile: thread creation profiling disabled, %s", fn)
|
||||
}
|
||||
|
||||
case traceMode:
|
||||
fn := filepath.Join(path, "trace.out")
|
||||
f, err := os.Create(fn)
|
||||
if err != nil {
|
||||
log.Fatalf("profile: could not create trace output file %q: %v", fn, err)
|
||||
}
|
||||
if err := trace.Start(f); err != nil {
|
||||
log.Fatalf("profile: could not start trace: %v", err)
|
||||
}
|
||||
logf("profile: trace enabled, %s", fn)
|
||||
prof.closer = func() {
|
||||
trace.Stop()
|
||||
logf("profile: trace disabled, %s", fn)
|
||||
}
|
||||
|
||||
case goroutineMode:
|
||||
fn := filepath.Join(path, "goroutine.pprof")
|
||||
f, err := os.Create(fn)
|
||||
if err != nil {
|
||||
log.Fatalf("profile: could not create goroutine profile %q: %v", fn, err)
|
||||
}
|
||||
logf("profile: goroutine profiling enabled, %s", fn)
|
||||
prof.closer = func() {
|
||||
if mp := pprof.Lookup("goroutine"); mp != nil {
|
||||
mp.WriteTo(f, 0)
|
||||
}
|
||||
f.Close()
|
||||
logf("profile: goroutine profiling disabled, %s", fn)
|
||||
}
|
||||
}
|
||||
|
||||
if !prof.noShutdownHook {
|
||||
go func() {
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt)
|
||||
<-c
|
||||
|
||||
log.Println("profile: caught interrupt, stopping profiles")
|
||||
prof.Stop()
|
||||
|
||||
os.Exit(0)
|
||||
}()
|
||||
}
|
||||
|
||||
return &prof
|
||||
}
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
|
@ -423,8 +423,6 @@ github.com/ostreedev/ostree-go/pkg/glibobject
|
|||
github.com/ostreedev/ostree-go/pkg/otbuiltin
|
||||
# github.com/pkg/errors v0.8.1
|
||||
github.com/pkg/errors
|
||||
# github.com/pkg/profile v1.4.0
|
||||
github.com/pkg/profile
|
||||
# github.com/pmezard/go-difflib v1.0.0
|
||||
github.com/pmezard/go-difflib/difflib
|
||||
# github.com/pquerna/ffjson v0.0.0-20190813045741-dac163c6c0a9
|
||||
|
|
Loading…
Reference in a new issue