Beispiel #1
0
func runCatManifest(args []string) (exit int) {
	if len(args) != 1 {
		stderr("cat-manifest: Must provide one file")
		return 1
	}

	inputFile = args[0]

	input, err := os.Open(inputFile)
	if err != nil {
		stderr("cat-manifest: Cannot open %s: %v", inputFile, err)
		return 1
	}
	defer input.Close()

	tr, err := aci.NewCompressedTarReader(input)
	if err != nil {
		stderr("cat-manifest: Cannot extract %s: %v", inputFile, err)
		return 1
	}
	defer tr.Close()

	err = extractManifest(tr.Reader, nil, true, nil)
	if err != nil {
		stderr("cat-manifest: Unable to read %s: %v", inputFile, err)
		return 1
	}

	return
}
Beispiel #2
0
func runPatchManifest(args []string) (exit int) {
	var fh *os.File
	var err error

	if patchReplace && patchOverwrite {
		stderr("patch-manifest: Cannot use both --replace and --overwrite")
		return 1
	}
	if !patchReplace && len(args) != 2 {
		stderr("patch-manifest: Must provide input and output files (or use --replace)")
		return 1
	}
	if patchReplace && len(args) != 1 {
		stderr("patch-manifest: Must provide one file")
		return 1
	}
	if patchManifestFile != "" && (patchName != "" || patchExec != "" || patchUser != "" || patchGroup != "" || patchCaps != "" || patchMounts != "") {
		stderr("patch-manifest: --manifest is incompatible with other manifest editing options")
		return 1
	}

	inputFile = args[0]

	// Prepare output writer

	if patchReplace {
		fh, err = ioutil.TempFile(path.Dir(inputFile), ".actool-tmp."+path.Base(inputFile)+"-")
		if err != nil {
			stderr("patch-manifest: Cannot create temporary file: %v", err)
			return 1
		}
	} else {
		outputFile = args[1]

		ext := filepath.Ext(outputFile)
		if ext != schema.ACIExtension {
			stderr("patch-manifest: Extension must be %s (given %s)", schema.ACIExtension, ext)
			return 1
		}

		mode := os.O_CREATE | os.O_WRONLY
		if patchOverwrite {
			mode |= os.O_TRUNC
		} else {
			mode |= os.O_EXCL
		}

		fh, err = os.OpenFile(outputFile, mode, 0644)
		if err != nil {
			if os.IsExist(err) {
				stderr("patch-manifest: Output file exists (try --overwrite)")
			} else {
				stderr("patch-manifest: Unable to open output %s: %v", outputFile, err)
			}
			return 1
		}
	}

	var gw *gzip.Writer
	var w io.WriteCloser = fh
	if !patchNocompress {
		gw = gzip.NewWriter(fh)
		w = gw
	}
	tw := tar.NewWriter(w)

	defer func() {
		tw.Close()
		if !patchNocompress {
			gw.Close()
		}
		fh.Close()
		if exit != 0 && !patchOverwrite {
			os.Remove(fh.Name())
		}
	}()

	// Prepare input reader

	input, err := os.Open(inputFile)
	if err != nil {
		stderr("patch-manifest: Cannot open %s: %v", inputFile, err)
		return 1
	}
	defer input.Close()

	tr, err := aci.NewCompressedTarReader(input)
	if err != nil {
		stderr("patch-manifest: Cannot extract %s: %v", inputFile, err)
		return 1
	}
	defer tr.Close()

	var newManifest []byte

	if patchManifestFile != "" {
		mr, err := os.Open(patchManifestFile)
		if err != nil {
			stderr("patch-manifest: Cannot open %s: %v", patchManifestFile, err)
			return 1
		}
		defer input.Close()

		newManifest, err = ioutil.ReadAll(mr)
		if err != nil {
			stderr("patch-manifest: Cannot read %s: %v", patchManifestFile, err)
			return 1
		}
	}

	err = extractManifest(tr.Reader, tw, false, newManifest)
	if err != nil {
		stderr("patch-manifest: Unable to read %s: %v", inputFile, err)
		return 1
	}

	if patchReplace {
		err = os.Rename(fh.Name(), inputFile)
		if err != nil {
			stderr("patch-manifest: Cannot rename %q to %q: %v", fh.Name, inputFile, err)
			return 1
		}
	}

	return
}
Beispiel #3
0
func runValidate(args []string) (exit int) {
	if len(args) < 1 {
		stderr("must pass one or more files")
		return 1
	}

	for _, path := range args {
		vt := valType
		fi, err := os.Stat(path)
		if err != nil {
			stderr("unable to access %s: %v", path, err)
			return 1
		}
		var fh *os.File
		if fi.IsDir() {
			switch vt {
			case typeImageLayout:
			case "":
				vt = typeImageLayout
			case typeManifest, typeAppImage:
				stderr("%s is a directory (wrong --type?)", path)
				return 1
			default:
				// should never happen
				panic(fmt.Sprintf("unexpected type: %v", vt))
			}
		} else {
			fh, err = os.Open(path)
			if err != nil {
				stderr("%s: unable to open: %v", path, err)
				return 1
			}
		}

		if vt == "" {
			vt, err = detectValType(fh)
			if err != nil {
				stderr("%s: error detecting file type: %v", path, err)
				return 1
			}
		}
		switch vt {
		case typeImageLayout:
			err = aci.ValidateLayout(path)
			if err != nil {
				stderr("%s: invalid image layout: %v", path, err)
				exit = 1
			} else if globalFlags.Debug {
				stderr("%s: valid image layout", path)
			}
		case typeAppImage:
			tr, err := aci.NewCompressedTarReader(fh)
			if err != nil {
				stderr("%s: error decompressing file: %v", path, err)
				return 1
			}
			err = aci.ValidateArchive(tr.Reader)
			tr.Close()
			fh.Close()
			if err != nil {
				if e, ok := err.(aci.ErrOldVersion); ok {
					stderr("%s: warning: %v", path, e)
				} else {
					stderr("%s: error validating: %v", path, err)
					exit = 1
				}
			} else if globalFlags.Debug {
				stderr("%s: valid app container image", path)
			}
		case typeManifest:
			b, err := ioutil.ReadAll(fh)
			fh.Close()
			if err != nil {
				stderr("%s: unable to read file %s", path, err)
				return 1
			}
			k := schema.Kind{}
			if err := k.UnmarshalJSON(b); err != nil {
				stderr("%s: error unmarshaling manifest: %v", path, err)
				return 1
			}
			switch k.ACKind {
			case "ImageManifest":
				m := schema.ImageManifest{}
				err = m.UnmarshalJSON(b)
			case "PodManifest":
				m := schema.PodManifest{}
				err = m.UnmarshalJSON(b)
			default:
				// Should not get here; schema.Kind unmarshal should fail
				panic("bad ACKind")
			}
			if err != nil {
				stderr("%s: invalid %s: %v", path, k.ACKind, err)
				exit = 1
			} else if globalFlags.Debug {
				stderr("%s: valid %s", path, k.ACKind)
			}
		default:
			stderr("%s: unable to detect filetype (try --type)", path)
			return 1
		}
	}

	return
}