wip lxc-config
This commit is contained in:
parent
ae9c197be0
commit
b76a500f2e
8
lxc-config/BUILD
Normal file
8
lxc-config/BUILD
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = ["lxcconfig.go"],
|
||||||
|
importpath = "github.com/motiejus/code/undocker/lxc-config",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
92
lxc-config/lxcconfig.go
Normal file
92
lxc-config/lxcconfig.go
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
package lxcconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const _manifestJSON = "manifest.json"
|
||||||
|
|
||||||
|
// dockerManifest is manifest.json
|
||||||
|
type dockerManifest []struct {
|
||||||
|
Config string `json:"Config"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// dockerConfig returns interesting configs for the container. user/group are
|
||||||
|
// skipped, since Docker allows specifying them by name, which would require
|
||||||
|
// peeking into the container image's /etc/passwd to resolve the names to ints.
|
||||||
|
type dockerConfig struct {
|
||||||
|
Architecture string `json:"architecture"`
|
||||||
|
Config struct {
|
||||||
|
Entrypoint []string `json:"Entrypoint"`
|
||||||
|
Cmd []string `json:"Cmd"`
|
||||||
|
Env []string `json:"Env"`
|
||||||
|
WorkingDir string `json:"WorkingDir"`
|
||||||
|
} `json:"config"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
errBadManifest = errors.New("bad or missing manifest.json")
|
||||||
|
)
|
||||||
|
|
||||||
|
func getDockerConfig(in io.ReadSeeker) (dockerConfig, error) {
|
||||||
|
tr := tar.NewReader(in)
|
||||||
|
// get offsets to all json files in the archive
|
||||||
|
jsonOffsets := map[string]int64{}
|
||||||
|
for {
|
||||||
|
hdr, err := tr.Next()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if hdr.Typeflag != tar.TypeReg {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !strings.HasSuffix(".json", hdr.Name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
here, err := in.Seek(0, io.SeekCurrent)
|
||||||
|
if err != nil {
|
||||||
|
return dockerConfig{}, err
|
||||||
|
}
|
||||||
|
jsonOffsets[hdr.Name] = here
|
||||||
|
}
|
||||||
|
|
||||||
|
// manifest is the docker manifest in the image
|
||||||
|
var manifest dockerManifest
|
||||||
|
if err := parseJSON(in, jsonOffsets, _manifestJSON, &manifest); err != nil {
|
||||||
|
return dockerConfig{}, err
|
||||||
|
}
|
||||||
|
if len(manifest) == 0 {
|
||||||
|
return dockerConfig{}, errBadManifest
|
||||||
|
}
|
||||||
|
|
||||||
|
var config dockerConfig
|
||||||
|
if err := parseJSON(in, jsonOffsets, manifest[0].Config, &config); err != nil {
|
||||||
|
return dockerConfig{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseJSON(in io.ReadSeeker, offsets map[string]int64, fname string, c interface{}) error {
|
||||||
|
configOffset, ok := offsets[fname]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("file %s not found", fname)
|
||||||
|
}
|
||||||
|
if _, err := in.Seek(configOffset, io.SeekStart); err != nil {
|
||||||
|
return fmt.Errorf("seek to %s: %w", fname, err)
|
||||||
|
}
|
||||||
|
tr := tar.NewReader(in)
|
||||||
|
if _, err := tr.Next(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dec := json.NewDecoder(tr)
|
||||||
|
if err := dec.Decode(c); err != nil {
|
||||||
|
return fmt.Errorf("decode %s: %w", fname, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -61,7 +61,7 @@ func RootFS(in io.ReadSeeker, out io.Writer) (err error) {
|
|||||||
case filepath.Clean(hdr.Name) == _manifestJSON:
|
case filepath.Clean(hdr.Name) == _manifestJSON:
|
||||||
dec := json.NewDecoder(tr)
|
dec := json.NewDecoder(tr)
|
||||||
if err := dec.Decode(&manifest); err != nil {
|
if err := dec.Decode(&manifest); err != nil {
|
||||||
return fmt.Errorf("parse %s: %w", _manifestJSON, err)
|
return fmt.Errorf("decode %s: %w", _manifestJSON, err)
|
||||||
}
|
}
|
||||||
case strings.HasSuffix(hdr.Name, _layerSuffix):
|
case strings.HasSuffix(hdr.Name, _layerSuffix):
|
||||||
here, err := in.Seek(0, io.SeekCurrent)
|
here, err := in.Seek(0, io.SeekCurrent)
|
||||||
|
Loading…
Reference in New Issue
Block a user