From 74ee579375654c79fa710f13b7c2ee3810366f82 Mon Sep 17 00:00:00 2001
From: umohnani8 <umohnani@redhat.com>
Date: Wed, 29 Nov 2017 16:56:18 -0500
Subject: [PATCH] Update kpod inspect to use the new container state

kpod inspect now uses the new libpod container state
and closely matches the output of docker inspect
some aspects of it are still WIP as the libpod container state
is still being worked on

Signed-off-by: umohnani8 <umohnani@redhat.com>
---
 cmd/kpod/create.go          | 357 +++++++++++++++++++-----------------
 cmd/kpod/create_cli.go      | 106 +++++------
 cmd/kpod/images.go          |  33 ++--
 cmd/kpod/inspect.go         | 308 +++++++++++++++++++++++++++----
 cmd/kpod/run.go             |  12 +-
 cmd/kpod/spec.go            | 162 ++++++++--------
 cmd/kpod/spec_test.go       |   4 +-
 docs/kpod-inspect.1.md      | 163 ++++------------
 libkpod/container_data.go   | 210 ---------------------
 libpod/container.go         |  90 ++++++++-
 libpod/container_inspect.go |  70 +++++++
 libpod/driver/driver.go     |  20 +-
 libpod/image_inspect.go     |  81 ++++++++
 libpod/images/image_data.go | 202 --------------------
 libpod/inspect_data.go      | 103 +++++++++++
 libpod/runtime_img.go       |  69 +++----
 test/kpod_inspect.bats      |  10 +
 17 files changed, 1047 insertions(+), 953 deletions(-)
 delete mode 100644 libkpod/container_data.go
 create mode 100644 libpod/container_inspect.go
 create mode 100644 libpod/image_inspect.go
 delete mode 100644 libpod/images/image_data.go
 create mode 100644 libpod/inspect_data.go

diff --git a/cmd/kpod/create.go b/cmd/kpod/create.go
index fc6e519fac..3548ad7dfc 100644
--- a/cmd/kpod/create.go
+++ b/cmd/kpod/create.go
@@ -1,6 +1,7 @@
 package main
 
 import (
+	"encoding/json"
 	"fmt"
 	"os"
 	"strconv"
@@ -36,91 +37,92 @@ var (
 )
 
 type createResourceConfig struct {
-	blkioWeight       uint16   // blkio-weight
-	blkioWeightDevice []string // blkio-weight-device
-	cpuPeriod         uint64   // cpu-period
-	cpuQuota          int64    // cpu-quota
-	cpuRtPeriod       uint64   // cpu-rt-period
-	cpuRtRuntime      int64    // cpu-rt-runtime
-	cpuShares         uint64   // cpu-shares
-	cpus              string   // cpus
-	cpusetCpus        string
-	cpusetMems        string   // cpuset-mems
-	deviceReadBps     []string // device-read-bps
-	deviceReadIOps    []string // device-read-iops
-	deviceWriteBps    []string // device-write-bps
-	deviceWriteIOps   []string // device-write-iops
-	disableOomKiller  bool     // oom-kill-disable
-	kernelMemory      int64    // kernel-memory
-	memory            int64    //memory
-	memoryReservation int64    // memory-reservation
-	memorySwap        int64    //memory-swap
-	memorySwappiness  int      // memory-swappiness
-	oomScoreAdj       int      //oom-score-adj
-	pidsLimit         int64    // pids-limit
-	shmSize           string
-	ulimit            []string //ulimit
+	BlkioWeight       uint16   // blkio-weight
+	BlkioWeightDevice []string // blkio-weight-device
+	CpuPeriod         uint64   // cpu-period
+	CpuQuota          int64    // cpu-quota
+	CpuRtPeriod       uint64   // cpu-rt-period
+	CpuRtRuntime      int64    // cpu-rt-runtime
+	CpuShares         uint64   // cpu-shares
+	Cpus              string   // cpus
+	CpusetCpus        string
+	CpusetMems        string   // cpuset-mems
+	DeviceReadBps     []string // device-read-bps
+	DeviceReadIOps    []string // device-read-iops
+	DeviceWriteBps    []string // device-write-bps
+	DeviceWriteIOps   []string // device-write-iops
+	DisableOomKiller  bool     // oom-kill-disable
+	KernelMemory      int64    // kernel-memory
+	Memory            int64    //memory
+	MemoryReservation int64    // memory-reservation
+	MemorySwap        int64    //memory-swap
+	MemorySwappiness  int      // memory-swappiness
+	OomScoreAdj       int      //oom-score-adj
+	PidsLimit         int64    // pids-limit
+	ShmSize           string
+	Ulimit            []string //ulimit
 }
 
 type createConfig struct {
-	runtime            *libpod.Runtime
-	args               []string
-	capAdd             []string // cap-add
-	capDrop            []string // cap-drop
-	cidFile            string
-	cgroupParent       string // cgroup-parent
-	command            []string
-	detach             bool              // detach
-	devices            []*pb.Device      // device
-	dnsOpt             []string          //dns-opt
-	dnsSearch          []string          //dns-search
-	dnsServers         []string          //dns
-	entrypoint         string            //entrypoint
-	env                map[string]string //env
-	expose             []string          //expose
-	groupAdd           []uint32          // group-add
-	hostname           string            //hostname
-	image              string
-	interactive        bool                  //interactive
-	ipcMode            container.IpcMode     //ipc
-	ip6Address         string                //ipv6
-	ipAddress          string                //ip
-	labels             map[string]string     //label
-	linkLocalIP        []string              // link-local-ip
-	logDriver          string                // log-driver
-	logDriverOpt       []string              // log-opt
-	macAddress         string                //mac-address
-	name               string                //name
-	netMode            container.NetworkMode //net
-	network            string                //network
-	networkAlias       []string              //network-alias
-	pidMode            container.PidMode     //pid
-	nsUser             string
-	pod                string   //pod
-	privileged         bool     //privileged
-	publish            []string //publish
-	publishAll         bool     //publish-all
-	readOnlyRootfs     bool     //read-only
-	resources          createResourceConfig
-	rm                 bool //rm
-	shmDir             string
-	sigProxy           bool              //sig-proxy
-	stopSignal         string            // stop-signal
-	stopTimeout        int64             // stop-timeout
-	storageOpts        []string          //storage-opt
-	sysctl             map[string]string //sysctl
-	tmpfs              []string          // tmpfs
-	tty                bool              //tty
-	user               uint32            //user
-	group              uint32            // group
-	utsMode            container.UTSMode //uts
-	volumes            []string          //volume
-	workDir            string            //workdir
-	mountLabel         string            //SecurityOpts
-	processLabel       string            //SecurityOpts
-	noNewPrivileges    bool              //SecurityOpts
-	apparmorProfile    string            //SecurityOpts
-	seccompProfilePath string            //SecurityOpts
+	Runtime            *libpod.Runtime
+	Args               []string
+	CapAdd             []string // cap-add
+	CapDrop            []string // cap-drop
+	CidFile            string
+	CgroupParent       string // cgroup-parent
+	Command            []string
+	Detach             bool              // detach
+	Devices            []*pb.Device      // device
+	DnsOpt             []string          //dns-opt
+	DnsSearch          []string          //dns-search
+	DnsServers         []string          //dns
+	Entrypoint         string            //entrypoint
+	Env                map[string]string //env
+	Expose             []string          //expose
+	GroupAdd           []uint32          // group-add
+	Hostname           string            //hostname
+	Image              string
+	Interactive        bool                  //interactive
+	IpcMode            container.IpcMode     //ipc
+	Ip6Address         string                //ipv6
+	IpAddress          string                //ip
+	Labels             map[string]string     //label
+	LinkLocalIP        []string              // link-local-ip
+	LogDriver          string                // log-driver
+	LogDriverOpt       []string              // log-opt
+	MacAddress         string                //mac-address
+	Name               string                //name
+	NetMode            container.NetworkMode //net
+	Network            string                //network
+	NetworkAlias       []string              //network-alias
+	PidMode            container.PidMode     //pid
+	NsUser             string
+	Pod                string   //pod
+	Privileged         bool     //privileged
+	Publish            []string //publish
+	PublishAll         bool     //publish-all
+	ReadOnlyRootfs     bool     //read-only
+	Resources          createResourceConfig
+	Rm                 bool //rm
+	ShmDir             string
+	SigProxy           bool              //sig-proxy
+	StopSignal         string            // stop-signal
+	StopTimeout        int64             // stop-timeout
+	StorageOpts        []string          //storage-opt
+	Sysctl             map[string]string //sysctl
+	Tmpfs              []string          // tmpfs
+	Tty                bool              //tty
+	User               uint32            //user
+	Group              uint32            // group
+	UtsMode            container.UTSMode //uts
+	Volumes            []string          //volume
+	WorkDir            string            //workdir
+	MountLabel         string            //SecurityOpts
+	ProcessLabel       string            //SecurityOpts
+	NoNewPrivileges    bool              //SecurityOpts
+	ApparmorProfile    string            //SecurityOpts
+	SeccompProfilePath string            //SecurityOpts
+	SecurityOpts       []string
 }
 
 var createDescription = "Creates a new container from the given image or" +
@@ -160,7 +162,7 @@ func createCmd(c *cli.Context) error {
 	}
 
 	// Deal with the image after all the args have been checked
-	createImage := runtime.NewImage(createConfig.image)
+	createImage := runtime.NewImage(createConfig.Image)
 	createImage.LocalName, _ = createImage.GetLocalImageName()
 	if createImage.LocalName == "" {
 		// The image wasnt found by the user input'd name or its fqname
@@ -203,13 +205,21 @@ func createCmd(c *cli.Context) error {
 	}
 	// Gather up the options for NewContainer which consist of With... funcs
 	options = append(options, libpod.WithRootFSFromImage(imageID, imageName, false))
-	options = append(options, libpod.WithSELinuxLabels(createConfig.processLabel, createConfig.mountLabel))
-	options = append(options, libpod.WithShmDir(createConfig.shmDir))
+	options = append(options, libpod.WithSELinuxLabels(createConfig.ProcessLabel, createConfig.MountLabel))
+	options = append(options, libpod.WithShmDir(createConfig.ShmDir))
 	ctr, err := runtime.NewContainer(runtimeSpec, options...)
 	if err != nil {
 		return err
 	}
 
+	createConfigJSON, err := json.Marshal(createConfig)
+	if err != nil {
+		return err
+	}
+	if err := ctr.AddArtifact("create-config", createConfigJSON); err != nil {
+		return err
+	}
+
 	logrus.Debug("new container created ", ctr.ID())
 
 	if c.String("cidfile") != "" {
@@ -229,29 +239,29 @@ func parseSecurityOpt(config *createConfig, securityOpts []string) error {
 		err       error
 	)
 
-	if config.pidMode.IsHost() {
+	if config.PidMode.IsHost() {
 		labelOpts = append(labelOpts, label.DisableSecOpt()...)
-	} else if config.pidMode.IsContainer() {
-		ctr, err := config.runtime.LookupContainer(config.pidMode.Container())
+	} else if config.PidMode.IsContainer() {
+		ctr, err := config.Runtime.LookupContainer(config.PidMode.Container())
 		if err != nil {
-			return errors.Wrapf(err, "container %q not found", config.pidMode.Container())
+			return errors.Wrapf(err, "container %q not found", config.PidMode.Container())
 		}
 		labelOpts = append(labelOpts, label.DupSecOpt(ctr.ProcessLabel())...)
 	}
 
-	if config.ipcMode.IsHost() {
+	if config.IpcMode.IsHost() {
 		labelOpts = append(labelOpts, label.DisableSecOpt()...)
-	} else if config.ipcMode.IsContainer() {
-		ctr, err := config.runtime.LookupContainer(config.ipcMode.Container())
+	} else if config.IpcMode.IsContainer() {
+		ctr, err := config.Runtime.LookupContainer(config.IpcMode.Container())
 		if err != nil {
-			return errors.Wrapf(err, "container %q not found", config.ipcMode.Container())
+			return errors.Wrapf(err, "container %q not found", config.IpcMode.Container())
 		}
 		labelOpts = append(labelOpts, label.DupSecOpt(ctr.ProcessLabel())...)
 	}
 
 	for _, opt := range securityOpts {
 		if opt == "no-new-privileges" {
-			config.noNewPrivileges = true
+			config.NoNewPrivileges = true
 		} else {
 			con := strings.SplitN(opt, "=", 2)
 			if len(con) != 2 {
@@ -262,25 +272,25 @@ func parseSecurityOpt(config *createConfig, securityOpts []string) error {
 			case "label":
 				labelOpts = append(labelOpts, con[1])
 			case "apparmor":
-				config.apparmorProfile = con[1]
+				config.ApparmorProfile = con[1]
 			case "seccomp":
-				config.seccompProfilePath = con[1]
+				config.SeccompProfilePath = con[1]
 			default:
 				return fmt.Errorf("Invalid --security-opt 2: %q", opt)
 			}
 		}
 	}
 
-	if config.seccompProfilePath == "" {
+	if config.SeccompProfilePath == "" {
 		if _, err := os.Stat(seccompDefaultPath); err != nil {
 			if !os.IsNotExist(err) {
 				return errors.Wrapf(err, "can't check if %q exists", seccompDefaultPath)
 			}
 		} else {
-			config.seccompProfilePath = seccompDefaultPath
+			config.SeccompProfilePath = seccompDefaultPath
 		}
 	}
-	config.processLabel, config.mountLabel, err = label.InitLabels(labelOpts)
+	config.ProcessLabel, config.MountLabel, err = label.InitLabels(labelOpts)
 	return err
 }
 
@@ -403,88 +413,89 @@ func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime) (*createConfig, er
 	}
 
 	config := &createConfig{
-		runtime:        runtime,
-		capAdd:         c.StringSlice("cap-add"),
-		capDrop:        c.StringSlice("cap-drop"),
-		cgroupParent:   c.String("cgroup-parent"),
-		command:        command,
-		detach:         c.Bool("detach"),
-		dnsOpt:         c.StringSlice("dns-opt"),
-		dnsSearch:      c.StringSlice("dns-search"),
-		dnsServers:     c.StringSlice("dns"),
-		entrypoint:     c.String("entrypoint"),
-		env:            env,
-		expose:         c.StringSlice("expose"),
-		groupAdd:       groupAdd,
-		hostname:       c.String("hostname"),
-		image:          image,
-		interactive:    c.Bool("interactive"),
-		ip6Address:     c.String("ipv6"),
-		ipAddress:      c.String("ip"),
-		labels:         labels,
-		linkLocalIP:    c.StringSlice("link-local-ip"),
-		logDriver:      c.String("log-driver"),
-		logDriverOpt:   c.StringSlice("log-opt"),
-		macAddress:     c.String("mac-address"),
-		name:           c.String("name"),
-		network:        c.String("network"),
-		networkAlias:   c.StringSlice("network-alias"),
-		ipcMode:        ipcMode,
-		netMode:        container.NetworkMode(c.String("network")),
-		utsMode:        utsMode,
-		pidMode:        pidMode,
-		pod:            c.String("pod"),
-		privileged:     c.Bool("privileged"),
-		publish:        c.StringSlice("publish"),
-		publishAll:     c.Bool("publish-all"),
-		readOnlyRootfs: c.Bool("read-only"),
-		resources: createResourceConfig{
-			blkioWeight:       blkioWeight,
-			blkioWeightDevice: c.StringSlice("blkio-weight-device"),
-			cpuShares:         c.Uint64("cpu-shares"),
-			cpuPeriod:         c.Uint64("cpu-period"),
-			cpusetCpus:        c.String("cpu-period"),
-			cpusetMems:        c.String("cpuset-mems"),
-			cpuQuota:          c.Int64("cpu-quota"),
-			cpuRtPeriod:       c.Uint64("cpu-rt-period"),
-			cpuRtRuntime:      c.Int64("cpu-rt-runtime"),
-			cpus:              c.String("cpus"),
-			deviceReadBps:     c.StringSlice("device-read-bps"),
-			deviceReadIOps:    c.StringSlice("device-read-iops"),
-			deviceWriteBps:    c.StringSlice("device-write-bps"),
-			deviceWriteIOps:   c.StringSlice("device-write-iops"),
-			disableOomKiller:  c.Bool("oom-kill-disable"),
-			shmSize:           c.String("shm-size"),
-			memory:            memoryLimit,
-			memoryReservation: memoryReservation,
-			memorySwap:        memorySwap,
-			memorySwappiness:  c.Int("memory-swappiness"),
-			kernelMemory:      memoryKernel,
-			oomScoreAdj:       c.Int("oom-score-adj"),
+		Runtime:        runtime,
+		CapAdd:         c.StringSlice("cap-add"),
+		CapDrop:        c.StringSlice("cap-drop"),
+		CgroupParent:   c.String("cgroup-parent"),
+		Command:        command,
+		Detach:         c.Bool("detach"),
+		DnsOpt:         c.StringSlice("dns-opt"),
+		DnsSearch:      c.StringSlice("dns-search"),
+		DnsServers:     c.StringSlice("dns"),
+		Entrypoint:     c.String("entrypoint"),
+		Env:            env,
+		Expose:         c.StringSlice("expose"),
+		GroupAdd:       groupAdd,
+		Hostname:       c.String("hostname"),
+		Image:          image,
+		Interactive:    c.Bool("interactive"),
+		Ip6Address:     c.String("ipv6"),
+		IpAddress:      c.String("ip"),
+		Labels:         labels,
+		LinkLocalIP:    c.StringSlice("link-local-ip"),
+		LogDriver:      c.String("log-driver"),
+		LogDriverOpt:   c.StringSlice("log-opt"),
+		MacAddress:     c.String("mac-address"),
+		Name:           c.String("name"),
+		Network:        c.String("network"),
+		NetworkAlias:   c.StringSlice("network-alias"),
+		IpcMode:        ipcMode,
+		NetMode:        container.NetworkMode(c.String("network")),
+		UtsMode:        utsMode,
+		PidMode:        pidMode,
+		Pod:            c.String("pod"),
+		Privileged:     c.Bool("privileged"),
+		Publish:        c.StringSlice("publish"),
+		PublishAll:     c.Bool("publish-all"),
+		ReadOnlyRootfs: c.Bool("read-only"),
+		Resources: createResourceConfig{
+			BlkioWeight:       blkioWeight,
+			BlkioWeightDevice: c.StringSlice("blkio-weight-device"),
+			CpuShares:         c.Uint64("cpu-shares"),
+			CpuPeriod:         c.Uint64("cpu-period"),
+			CpusetCpus:        c.String("cpu-period"),
+			CpusetMems:        c.String("cpuset-mems"),
+			CpuQuota:          c.Int64("cpu-quota"),
+			CpuRtPeriod:       c.Uint64("cpu-rt-period"),
+			CpuRtRuntime:      c.Int64("cpu-rt-runtime"),
+			Cpus:              c.String("cpus"),
+			DeviceReadBps:     c.StringSlice("device-read-bps"),
+			DeviceReadIOps:    c.StringSlice("device-read-iops"),
+			DeviceWriteBps:    c.StringSlice("device-write-bps"),
+			DeviceWriteIOps:   c.StringSlice("device-write-iops"),
+			DisableOomKiller:  c.Bool("oom-kill-disable"),
+			ShmSize:           c.String("shm-size"),
+			Memory:            memoryLimit,
+			MemoryReservation: memoryReservation,
+			MemorySwap:        memorySwap,
+			MemorySwappiness:  c.Int("memory-swappiness"),
+			KernelMemory:      memoryKernel,
+			OomScoreAdj:       c.Int("oom-score-adj"),
 
-			pidsLimit: c.Int64("pids-limit"),
-			ulimit:    c.StringSlice("ulimit"),
+			PidsLimit: c.Int64("pids-limit"),
+			Ulimit:    c.StringSlice("ulimit"),
 		},
-		rm:          c.Bool("rm"),
-		shmDir:      shmDir,
-		sigProxy:    c.Bool("sig-proxy"),
-		stopSignal:  c.String("stop-signal"),
-		stopTimeout: c.Int64("stop-timeout"),
-		storageOpts: c.StringSlice("storage-opt"),
-		sysctl:      sysctl,
-		tmpfs:       c.StringSlice("tmpfs"),
-		tty:         tty,
-		user:        uid,
-		group:       gid,
-		volumes:     c.StringSlice("volume"),
-		workDir:     c.String("workdir"),
+		Rm:          c.Bool("rm"),
+		ShmDir:      shmDir,
+		SigProxy:    c.Bool("sig-proxy"),
+		StopSignal:  c.String("stop-signal"),
+		StopTimeout: c.Int64("stop-timeout"),
+		StorageOpts: c.StringSlice("storage-opt"),
+		Sysctl:      sysctl,
+		Tmpfs:       c.StringSlice("tmpfs"),
+		Tty:         tty,
+		User:        uid,
+		Group:       gid,
+		Volumes:     c.StringSlice("volume"),
+		WorkDir:     c.String("workdir"),
 	}
 
-	if !config.privileged {
+	if !config.Privileged {
 		if err := parseSecurityOpt(config, c.StringSlice("security-opt")); err != nil {
 			return nil, err
 		}
 	}
+	config.SecurityOpts = c.StringSlice("security-opt")
 	warnings, err := verifyContainerResources(config, false)
 	if err != nil {
 		return nil, err
diff --git a/cmd/kpod/create_cli.go b/cmd/kpod/create_cli.go
index 9686b89a79..a162cb319f 100644
--- a/cmd/kpod/create_cli.go
+++ b/cmd/kpod/create_cli.go
@@ -111,131 +111,131 @@ func verifyContainerResources(config *createConfig, update bool) ([]string, erro
 	sysInfo := sysinfo.New(true)
 
 	// memory subsystem checks and adjustments
-	if config.resources.memory != 0 && config.resources.memory < linuxMinMemory {
+	if config.Resources.Memory != 0 && config.Resources.Memory < linuxMinMemory {
 		return warnings, fmt.Errorf("minimum memory limit allowed is 4MB")
 	}
-	if config.resources.memory > 0 && !sysInfo.MemoryLimit {
+	if config.Resources.Memory > 0 && !sysInfo.MemoryLimit {
 		warnings = addWarning(warnings, "Your kernel does not support memory limit capabilities or the cgroup is not mounted. Limitation discarded.")
-		config.resources.memory = 0
-		config.resources.memorySwap = -1
+		config.Resources.Memory = 0
+		config.Resources.MemorySwap = -1
 	}
-	if config.resources.memory > 0 && config.resources.memorySwap != -1 && !sysInfo.SwapLimit {
+	if config.Resources.Memory > 0 && config.Resources.MemorySwap != -1 && !sysInfo.SwapLimit {
 		warnings = addWarning(warnings, "Your kernel does not support swap limit capabilities,or the cgroup is not mounted. Memory limited without swap.")
-		config.resources.memorySwap = -1
+		config.Resources.MemorySwap = -1
 	}
-	if config.resources.memory > 0 && config.resources.memorySwap > 0 && config.resources.memorySwap < config.resources.memory {
+	if config.Resources.Memory > 0 && config.Resources.MemorySwap > 0 && config.Resources.MemorySwap < config.Resources.Memory {
 		return warnings, fmt.Errorf("minimum memoryswap limit should be larger than memory limit, see usage")
 	}
-	if config.resources.memory == 0 && config.resources.memorySwap > 0 && !update {
-		return warnings, fmt.Errorf("you should always set the Memory limit when using Memoryswap limit, see usage")
+	if config.Resources.Memory == 0 && config.Resources.MemorySwap > 0 && !update {
+		return warnings, fmt.Errorf("you should always set the memory limit when using memoryswap limit, see usage")
 	}
-	if config.resources.memorySwappiness != -1 {
+	if config.Resources.MemorySwappiness != -1 {
 		if !sysInfo.MemorySwappiness {
 			msg := "Your kernel does not support memory swappiness capabilities, or the cgroup is not mounted. Memory swappiness discarded."
 			warnings = addWarning(warnings, msg)
-			config.resources.memorySwappiness = -1
+			config.Resources.MemorySwappiness = -1
 		} else {
-			swappiness := config.resources.memorySwappiness
+			swappiness := config.Resources.MemorySwappiness
 			if swappiness < -1 || swappiness > 100 {
 				return warnings, fmt.Errorf("invalid value: %v, valid memory swappiness range is 0-100", swappiness)
 			}
 		}
 	}
-	if config.resources.memoryReservation > 0 && !sysInfo.MemoryReservation {
+	if config.Resources.MemoryReservation > 0 && !sysInfo.MemoryReservation {
 		warnings = addWarning(warnings, "Your kernel does not support memory soft limit capabilities or the cgroup is not mounted. Limitation discarded.")
-		config.resources.memoryReservation = 0
+		config.Resources.MemoryReservation = 0
 	}
-	if config.resources.memoryReservation > 0 && config.resources.memoryReservation < linuxMinMemory {
+	if config.Resources.MemoryReservation > 0 && config.Resources.MemoryReservation < linuxMinMemory {
 		return warnings, fmt.Errorf("minimum memory reservation allowed is 4MB")
 	}
-	if config.resources.memory > 0 && config.resources.memoryReservation > 0 && config.resources.memory < config.resources.memoryReservation {
+	if config.Resources.Memory > 0 && config.Resources.MemoryReservation > 0 && config.Resources.Memory < config.Resources.MemoryReservation {
 		return warnings, fmt.Errorf("minimum memory limit can not be less than memory reservation limit, see usage")
 	}
-	if config.resources.kernelMemory > 0 && !sysInfo.KernelMemory {
+	if config.Resources.KernelMemory > 0 && !sysInfo.KernelMemory {
 		warnings = addWarning(warnings, "Your kernel does not support kernel memory limit capabilities or the cgroup is not mounted. Limitation discarded.")
-		config.resources.kernelMemory = 0
+		config.Resources.KernelMemory = 0
 	}
-	if config.resources.kernelMemory > 0 && config.resources.kernelMemory < linuxMinMemory {
+	if config.Resources.KernelMemory > 0 && config.Resources.KernelMemory < linuxMinMemory {
 		return warnings, fmt.Errorf("minimum kernel memory limit allowed is 4MB")
 	}
-	if config.resources.disableOomKiller == true && !sysInfo.OomKillDisable {
+	if config.Resources.DisableOomKiller == true && !sysInfo.OomKillDisable {
 		// only produce warnings if the setting wasn't to *disable* the OOM Kill; no point
 		// warning the caller if they already wanted the feature to be off
 		warnings = addWarning(warnings, "Your kernel does not support OomKillDisable. OomKillDisable discarded.")
-		config.resources.disableOomKiller = false
+		config.Resources.DisableOomKiller = false
 	}
 
-	if config.resources.pidsLimit != 0 && !sysInfo.PidsLimit {
+	if config.Resources.PidsLimit != 0 && !sysInfo.PidsLimit {
 		warnings = addWarning(warnings, "Your kernel does not support pids limit capabilities or the cgroup is not mounted. PIDs limit discarded.")
-		config.resources.pidsLimit = 0
+		config.Resources.PidsLimit = 0
 	}
 
-	if config.resources.cpuShares > 0 && !sysInfo.CPUShares {
+	if config.Resources.CpuShares > 0 && !sysInfo.CPUShares {
 		warnings = addWarning(warnings, "Your kernel does not support CPU shares or the cgroup is not mounted. Shares discarded.")
-		config.resources.cpuShares = 0
+		config.Resources.CpuShares = 0
 	}
-	if config.resources.cpuPeriod > 0 && !sysInfo.CPUCfsPeriod {
+	if config.Resources.CpuPeriod > 0 && !sysInfo.CPUCfsPeriod {
 		warnings = addWarning(warnings, "Your kernel does not support CPU cfs period or the cgroup is not mounted. Period discarded.")
-		config.resources.cpuPeriod = 0
+		config.Resources.CpuPeriod = 0
 	}
-	if config.resources.cpuPeriod != 0 && (config.resources.cpuPeriod < 1000 || config.resources.cpuPeriod > 1000000) {
+	if config.Resources.CpuPeriod != 0 && (config.Resources.CpuPeriod < 1000 || config.Resources.CpuPeriod > 1000000) {
 		return warnings, fmt.Errorf("CPU cfs period can not be less than 1ms (i.e. 1000) or larger than 1s (i.e. 1000000)")
 	}
-	if config.resources.cpuQuota > 0 && !sysInfo.CPUCfsQuota {
+	if config.Resources.CpuQuota > 0 && !sysInfo.CPUCfsQuota {
 		warnings = addWarning(warnings, "Your kernel does not support CPU cfs quota or the cgroup is not mounted. Quota discarded.")
-		config.resources.cpuQuota = 0
+		config.Resources.CpuQuota = 0
 	}
-	if config.resources.cpuQuota > 0 && config.resources.cpuQuota < 1000 {
+	if config.Resources.CpuQuota > 0 && config.Resources.CpuQuota < 1000 {
 		return warnings, fmt.Errorf("CPU cfs quota can not be less than 1ms (i.e. 1000)")
 	}
 	// cpuset subsystem checks and adjustments
-	if (config.resources.cpusetCpus != "" || config.resources.cpusetMems != "") && !sysInfo.Cpuset {
+	if (config.Resources.CpusetCpus != "" || config.Resources.CpusetMems != "") && !sysInfo.Cpuset {
 		warnings = addWarning(warnings, "Your kernel does not support cpuset or the cgroup is not mounted. Cpuset discarded.")
-		config.resources.cpusetCpus = ""
-		config.resources.cpusetMems = ""
+		config.Resources.CpusetCpus = ""
+		config.Resources.CpusetMems = ""
 	}
-	cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(config.resources.cpusetCpus)
+	cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(config.Resources.CpusetCpus)
 	if err != nil {
-		return warnings, fmt.Errorf("invalid value %s for cpuset cpus", config.resources.cpusetCpus)
+		return warnings, fmt.Errorf("invalid value %s for cpuset cpus", config.Resources.CpusetCpus)
 	}
 	if !cpusAvailable {
-		return warnings, fmt.Errorf("requested CPUs are not available - requested %s, available: %s", config.resources.cpusetCpus, sysInfo.Cpus)
+		return warnings, fmt.Errorf("requested CPUs are not available - requested %s, available: %s", config.Resources.CpusetCpus, sysInfo.Cpus)
 	}
-	memsAvailable, err := sysInfo.IsCpusetMemsAvailable(config.resources.cpusetMems)
+	memsAvailable, err := sysInfo.IsCpusetMemsAvailable(config.Resources.CpusetMems)
 	if err != nil {
-		return warnings, fmt.Errorf("invalid value %s for cpuset mems", config.resources.cpusetMems)
+		return warnings, fmt.Errorf("invalid value %s for cpuset mems", config.Resources.CpusetMems)
 	}
 	if !memsAvailable {
-		return warnings, fmt.Errorf("requested memory nodes are not available - requested %s, available: %s", config.resources.cpusetMems, sysInfo.Mems)
+		return warnings, fmt.Errorf("requested memory nodes are not available - requested %s, available: %s", config.Resources.CpusetMems, sysInfo.Mems)
 	}
 
 	// blkio subsystem checks and adjustments
-	if config.resources.blkioWeight > 0 && !sysInfo.BlkioWeight {
+	if config.Resources.BlkioWeight > 0 && !sysInfo.BlkioWeight {
 		warnings = addWarning(warnings, "Your kernel does not support Block I/O weight or the cgroup is not mounted. Weight discarded.")
-		config.resources.blkioWeight = 0
+		config.Resources.BlkioWeight = 0
 	}
-	if config.resources.blkioWeight > 0 && (config.resources.blkioWeight < 10 || config.resources.blkioWeight > 1000) {
+	if config.Resources.BlkioWeight > 0 && (config.Resources.BlkioWeight < 10 || config.Resources.BlkioWeight > 1000) {
 		return warnings, fmt.Errorf("range of blkio weight is from 10 to 1000")
 	}
-	if len(config.resources.blkioWeightDevice) > 0 && !sysInfo.BlkioWeightDevice {
+	if len(config.Resources.BlkioWeightDevice) > 0 && !sysInfo.BlkioWeightDevice {
 		warnings = addWarning(warnings, "Your kernel does not support Block I/O weight_device or the cgroup is not mounted. Weight-device discarded.")
-		config.resources.blkioWeightDevice = []string{}
+		config.Resources.BlkioWeightDevice = []string{}
 	}
-	if len(config.resources.deviceReadBps) > 0 && !sysInfo.BlkioReadBpsDevice {
+	if len(config.Resources.DeviceReadBps) > 0 && !sysInfo.BlkioReadBpsDevice {
 		warnings = addWarning(warnings, "Your kernel does not support BPS Block I/O read limit or the cgroup is not mounted. Block I/O BPS read limit discarded")
-		config.resources.deviceReadBps = []string{}
+		config.Resources.DeviceReadBps = []string{}
 	}
-	if len(config.resources.deviceWriteBps) > 0 && !sysInfo.BlkioWriteBpsDevice {
+	if len(config.Resources.DeviceWriteBps) > 0 && !sysInfo.BlkioWriteBpsDevice {
 		warnings = addWarning(warnings, "Your kernel does not support BPS Block I/O write limit or the cgroup is not mounted. Block I/O BPS write limit discarded.")
-		config.resources.deviceWriteBps = []string{}
+		config.Resources.DeviceWriteBps = []string{}
 	}
-	if len(config.resources.deviceReadIOps) > 0 && !sysInfo.BlkioReadIOpsDevice {
+	if len(config.Resources.DeviceReadIOps) > 0 && !sysInfo.BlkioReadIOpsDevice {
 		warnings = addWarning(warnings, "Your kernel does not support IOPS Block read limit or the cgroup is not mounted. Block I/O IOPS read limit discarded.")
-		config.resources.deviceReadIOps = []string{}
+		config.Resources.DeviceReadIOps = []string{}
 	}
-	if len(config.resources.deviceWriteIOps) > 0 && !sysInfo.BlkioWriteIOpsDevice {
+	if len(config.Resources.DeviceWriteIOps) > 0 && !sysInfo.BlkioWriteIOpsDevice {
 		warnings = addWarning(warnings, "Your kernel does not support IOPS Block I/O write limit or the cgroup is not mounted. Block I/O IOPS write limit discarded.")
-		config.resources.deviceWriteIOps = []string{}
+		config.Resources.DeviceWriteIOps = []string{}
 	}
 
 	return warnings, nil
diff --git a/cmd/kpod/images.go b/cmd/kpod/images.go
index 7b020c984d..1cf69c96df 100644
--- a/cmd/kpod/images.go
+++ b/cmd/kpod/images.go
@@ -6,7 +6,6 @@ import (
 	"strings"
 	"time"
 
-	"github.com/containers/image/types"
 	"github.com/containers/storage"
 	"github.com/docker/go-units"
 	digest "github.com/opencontainers/go-digest"
@@ -208,18 +207,18 @@ func getImagesTemplateOutput(runtime *libpod.Runtime, images []*storage.Image, o
 			}
 		}
 
-		info, imageDigest, size, _ := runtime.InfoAndDigestAndSize(*img)
-		if info != nil {
-			createdTime = info.Created
+		imgData, _ := runtime.GetImageInspectInfo(*img)
+		if imgData != nil {
+			createdTime = *imgData.Created
 		}
 
 		params := imagesTemplateParams{
 			Repository: repository,
 			Tag:        tag,
 			ID:         imageID,
-			Digest:     imageDigest,
+			Digest:     imgData.Digest,
 			Created:    units.HumanDuration(time.Since((createdTime))) + " ago",
-			Size:       units.HumanSizeWithPrecision(float64(size), 3),
+			Size:       units.HumanSizeWithPrecision(float64(imgData.Size), 3),
 		}
 		imagesOutput = append(imagesOutput, params)
 	}
@@ -231,17 +230,17 @@ func getImagesJSONOutput(runtime *libpod.Runtime, images []*storage.Image) (imag
 	for _, img := range images {
 		createdTime := img.Created
 
-		info, imageDigest, size, _ := runtime.InfoAndDigestAndSize(*img)
-		if info != nil {
-			createdTime = info.Created
+		imgData, _ := runtime.GetImageInspectInfo(*img)
+		if imgData != nil {
+			createdTime = *imgData.Created
 		}
 
 		params := imagesJSONParams{
 			ID:      img.ID,
 			Name:    img.Names,
-			Digest:  imageDigest,
+			Digest:  imgData.Digest,
 			Created: createdTime,
-			Size:    size,
+			Size:    imgData.Size,
 		}
 		imagesOutput = append(imagesOutput, params)
 	}
@@ -274,7 +273,7 @@ func generateImagesOutput(runtime *libpod.Runtime, images []*storage.Image, opts
 func generateImagesFilter(params *libpod.ImageFilterParams, filterType string) libpod.ImageFilter {
 	switch filterType {
 	case "label":
-		return func(image *storage.Image, info *types.ImageInspectInfo) bool {
+		return func(image *storage.Image, info *libpod.ImageData) bool {
 			if params == nil || params.Label == "" {
 				return true
 			}
@@ -291,21 +290,21 @@ func generateImagesFilter(params *libpod.ImageFilterParams, filterType string) l
 			return false
 		}
 	case "before-image":
-		return func(image *storage.Image, info *types.ImageInspectInfo) bool {
+		return func(image *storage.Image, info *libpod.ImageData) bool {
 			if params == nil || params.BeforeImage.IsZero() {
 				return true
 			}
 			return info.Created.Before(params.BeforeImage)
 		}
 	case "since-image":
-		return func(image *storage.Image, info *types.ImageInspectInfo) bool {
+		return func(image *storage.Image, info *libpod.ImageData) bool {
 			if params == nil || params.SinceImage.IsZero() {
 				return true
 			}
 			return info.Created.After(params.SinceImage)
 		}
 	case "dangling":
-		return func(image *storage.Image, info *types.ImageInspectInfo) bool {
+		return func(image *storage.Image, info *libpod.ImageData) bool {
 			if params == nil || params.Dangling == "" {
 				return true
 			}
@@ -318,14 +317,14 @@ func generateImagesFilter(params *libpod.ImageFilterParams, filterType string) l
 			return false
 		}
 	case "reference":
-		return func(image *storage.Image, info *types.ImageInspectInfo) bool {
+		return func(image *storage.Image, info *libpod.ImageData) bool {
 			if params == nil || params.ReferencePattern == "" {
 				return true
 			}
 			return libpod.MatchesReference(params.ImageName, params.ReferencePattern)
 		}
 	case "image-input":
-		return func(image *storage.Image, info *types.ImageInspectInfo) bool {
+		return func(image *storage.Image, info *libpod.ImageData) bool {
 			if params == nil || params.ImageInput == "" {
 				return true
 			}
diff --git a/cmd/kpod/inspect.go b/cmd/kpod/inspect.go
index a70e285ac3..e2f9ec97ec 100644
--- a/cmd/kpod/inspect.go
+++ b/cmd/kpod/inspect.go
@@ -1,10 +1,12 @@
 package main
 
 import (
+	"encoding/json"
+
+	specs "github.com/opencontainers/runtime-spec/specs-go"
 	"github.com/pkg/errors"
 	"github.com/projectatomic/libpod/cmd/kpod/formats"
-	"github.com/projectatomic/libpod/libkpod"
-	"github.com/projectatomic/libpod/libpod/images"
+	"github.com/projectatomic/libpod/libpod"
 	"github.com/urfave/cli"
 )
 
@@ -53,56 +55,63 @@ func inspectCmd(c *cli.Context) error {
 		return err
 	}
 
-	itemType := c.String("type")
-	size := c.Bool("size")
+	runtime, err := getRuntime(c)
+	if err != nil {
+		return errors.Wrapf(err, "error creating libpod runtime")
+	}
+	defer runtime.Shutdown(false)
 
-	switch itemType {
-	case inspectTypeContainer:
-	case inspectTypeImage:
-	case inspectAll:
-	default:
+	if c.String("type") != inspectTypeContainer && c.String("type") != inspectTypeImage && c.String("type") != inspectAll {
 		return errors.Errorf("the only recognized types are %q, %q, and %q", inspectTypeContainer, inspectTypeImage, inspectAll)
 	}
 
 	name := args[0]
 
-	config, err := getConfig(c)
-	if err != nil {
-		return errors.Wrapf(err, "Could not get config")
-	}
-	server, err := libkpod.New(config)
-	if err != nil {
-		return errors.Wrapf(err, "could not get container server")
-	}
-	defer server.Shutdown()
-	if err = server.Update(); err != nil {
-		return errors.Wrapf(err, "could not update list of containers")
-	}
-
 	outputFormat := c.String("format")
 	var data interface{}
-	switch itemType {
+	switch c.String("type") {
 	case inspectTypeContainer:
-		data, err = server.GetContainerData(name, size)
+		ctr, err := runtime.LookupContainer(name)
 		if err != nil {
-			return errors.Wrapf(err, "error parsing container data")
+			return errors.Wrapf(err, "error looking up container %q", name)
+		}
+		libpodInspectData, err := ctr.Inspect(c.Bool("size"))
+		if err != nil {
+			return errors.Wrapf(err, "error getting libpod container inspect data %q", ctr.ID)
+		}
+		data, err = getCtrInspectInfo(ctr, libpodInspectData)
+		if err != nil {
+			return errors.Wrapf(err, "error parsing container data %q", ctr.ID())
 		}
 	case inspectTypeImage:
-		data, err = images.GetData(server.Store(), name)
+		image, err := runtime.GetImage(name)
 		if err != nil {
-			return errors.Wrapf(err, "error parsing image data")
+			return errors.Wrapf(err, "error getting image %q", name)
+		}
+		data, err = runtime.GetImageInspectInfo(*image)
+		if err != nil {
+			return errors.Wrapf(err, "error parsing image data %q", image.ID)
 		}
 	case inspectAll:
-		ctrData, err := server.GetContainerData(name, size)
+		ctr, err := runtime.LookupContainer(name)
 		if err != nil {
-			imgData, err := images.GetData(server.Store(), name)
+			image, err := runtime.GetImage(name)
 			if err != nil {
-				return errors.Wrapf(err, "error parsing container or image data")
+				return errors.Wrapf(err, "error getting image %q", name)
+			}
+			data, err = runtime.GetImageInspectInfo(*image)
+			if err != nil {
+				return errors.Wrapf(err, "error parsing image data %q", image.ID)
 			}
-			data = imgData
-
 		} else {
-			data = ctrData
+			libpodInspectData, err := ctr.Inspect(c.Bool("size"))
+			if err != nil {
+				return errors.Wrapf(err, "error getting libpod container inspect data %q", ctr.ID)
+			}
+			data, err = getCtrInspectInfo(ctr, libpodInspectData)
+			if err != nil {
+				return errors.Wrapf(err, "error parsing container data %q", ctr.ID)
+			}
 		}
 	}
 
@@ -118,3 +127,236 @@ func inspectCmd(c *cli.Context) error {
 	formats.Writer(out).Out()
 	return nil
 }
+
+func getCtrInspectInfo(ctr *libpod.Container, ctrInspectData *libpod.ContainerInspectData) (*ContainerData, error) {
+	config := ctr.Config()
+	spec := config.Spec
+
+	cpus, mems, period, quota, realtimePeriod, realtimeRuntime, shares := getCPUInfo(spec)
+	blkioWeight, blkioWeightDevice, blkioReadBps, blkioWriteBps, blkioReadIOPS, blkioeWriteIOPS := getBLKIOInfo(spec)
+	memKernel, memReservation, memSwap, memSwappiness, memDisableOOMKiller := getMemoryInfo(spec)
+	pidsLimit := getPidsInfo(spec)
+	cgroup := getCgroup(spec)
+
+	artifact, err := ctr.GetArtifact("create-config")
+	if err != nil {
+		return nil, errors.Wrapf(err, "error getting artifact %q", ctr.ID())
+	}
+	var createArtifact createConfig
+	if err := json.Unmarshal(artifact, &createArtifact); err != nil {
+		return nil, err
+	}
+
+	data := &ContainerData{
+		CtrInspectData: ctrInspectData,
+		HostConfig: &HostConfig{
+			ConsoleSize:          spec.Process.ConsoleSize,
+			OomScoreAdj:          spec.Process.OOMScoreAdj,
+			CPUShares:            shares,
+			BlkioWeight:          blkioWeight,
+			BlkioWeightDevice:    blkioWeightDevice,
+			BlkioDeviceReadBps:   blkioReadBps,
+			BlkioDeviceWriteBps:  blkioWriteBps,
+			BlkioDeviceReadIOps:  blkioReadIOPS,
+			BlkioDeviceWriteIOps: blkioeWriteIOPS,
+			CPUPeriod:            period,
+			CPUQuota:             quota,
+			CPURealtimePeriod:    realtimePeriod,
+			CPURealtimeRuntime:   realtimeRuntime,
+			CPUSetCpus:           cpus,
+			CPUSetMems:           mems,
+			Devices:              spec.Linux.Devices,
+			KernelMemory:         memKernel,
+			MemoryReservation:    memReservation,
+			MemorySwap:           memSwap,
+			MemorySwappiness:     memSwappiness,
+			OomKillDisable:       memDisableOOMKiller,
+			PidsLimit:            pidsLimit,
+			Privileged:           spec.Process.NoNewPrivileges,
+			ReadonlyRootfs:       spec.Root.Readonly,
+			Runtime:              ctr.RuntimeName(),
+			NetworkMode:          string(createArtifact.NetMode),
+			IpcMode:              string(createArtifact.IpcMode),
+			Cgroup:               cgroup,
+			UTSMode:              string(createArtifact.UtsMode),
+			UsernsMode:           createArtifact.NsUser,
+			GroupAdd:             spec.Process.User.AdditionalGids,
+			ContainerIDFile:      createArtifact.CidFile,
+			AutoRemove:           createArtifact.Rm,
+			CapAdd:               createArtifact.CapAdd,
+			CapDrop:              createArtifact.CapDrop,
+			DNS:                  createArtifact.DnsServers,
+			DNSOptions:           createArtifact.DnsOpt,
+			DNSSearch:            createArtifact.DnsSearch,
+			PidMode:              string(createArtifact.PidMode),
+			CgroupParent:         createArtifact.CgroupParent,
+			ShmSize:              createArtifact.Resources.ShmSize,
+			Memory:               createArtifact.Resources.Memory,
+			Ulimits:              createArtifact.Resources.Ulimit,
+			SecurityOpt:          createArtifact.SecurityOpts,
+		},
+		Config: &CtrConfig{
+			Hostname:    spec.Hostname,
+			User:        spec.Process.User,
+			Env:         spec.Process.Env,
+			Image:       config.RootfsImageName,
+			WorkingDir:  spec.Process.Cwd,
+			Labels:      config.Labels,
+			Annotations: spec.Annotations,
+			Tty:         spec.Process.Terminal,
+			OpenStdin:   config.Stdin,
+			StopSignal:  config.StopSignal,
+			Cmd:         config.Spec.Process.Args,
+			Entrypoint:  createArtifact.Entrypoint,
+		},
+	}
+	return data, nil
+}
+
+func getCPUInfo(spec *specs.Spec) (string, string, *uint64, *int64, *uint64, *int64, *uint64) {
+	if spec.Linux.Resources == nil {
+		return "", "", nil, nil, nil, nil, nil
+	}
+	cpu := spec.Linux.Resources.CPU
+	if cpu == nil {
+		return "", "", nil, nil, nil, nil, nil
+	}
+	return cpu.Cpus, cpu.Mems, cpu.Period, cpu.Quota, cpu.RealtimePeriod, cpu.RealtimeRuntime, cpu.Shares
+}
+
+func getBLKIOInfo(spec *specs.Spec) (*uint16, []specs.LinuxWeightDevice, []specs.LinuxThrottleDevice, []specs.LinuxThrottleDevice, []specs.LinuxThrottleDevice, []specs.LinuxThrottleDevice) {
+	if spec.Linux.Resources == nil {
+		return nil, nil, nil, nil, nil, nil
+	}
+	blkio := spec.Linux.Resources.BlockIO
+	if blkio == nil {
+		return nil, nil, nil, nil, nil, nil
+	}
+	return blkio.Weight, blkio.WeightDevice, blkio.ThrottleReadBpsDevice, blkio.ThrottleWriteBpsDevice, blkio.ThrottleReadIOPSDevice, blkio.ThrottleWriteIOPSDevice
+}
+
+func getMemoryInfo(spec *specs.Spec) (*int64, *int64, *int64, *uint64, *bool) {
+	if spec.Linux.Resources == nil {
+		return nil, nil, nil, nil, nil
+	}
+	memory := spec.Linux.Resources.Memory
+	if memory == nil {
+		return nil, nil, nil, nil, nil
+	}
+	return memory.Kernel, memory.Reservation, memory.Swap, memory.Swappiness, memory.DisableOOMKiller
+}
+
+func getPidsInfo(spec *specs.Spec) *int64 {
+	if spec.Linux.Resources == nil {
+		return nil
+	}
+	pids := spec.Linux.Resources.Pids
+	if pids == nil {
+		return nil
+	}
+	return &pids.Limit
+}
+
+func getCgroup(spec *specs.Spec) string {
+	cgroup := "host"
+	for _, ns := range spec.Linux.Namespaces {
+		if ns.Type == specs.CgroupNamespace && ns.Path != "" {
+			cgroup = "container"
+		}
+	}
+	return cgroup
+}
+
+// ContainerData holds the kpod inspect data for a container
+type ContainerData struct {
+	CtrInspectData *libpod.ContainerInspectData `json:"CtrInspectData"`
+	HostConfig     *HostConfig                  `json:"HostConfig"`
+	Config         *CtrConfig                   `json:"Config"`
+}
+
+// LogConfig holds the log information for a container
+type LogConfig struct {
+	Type   string            `json:"Type"`   // TODO
+	Config map[string]string `json:"Config"` //idk type, TODO
+}
+
+// HostConfig represents the host configuration for the container
+type HostConfig struct {
+	ContainerIDFile      string                      `json:"ContainerIDFile"`
+	LogConfig            *LogConfig                  `json:"LogConfig"` //TODO
+	NetworkMode          string                      `json:"NetworkMode"`
+	PortBindings         map[string]struct{}         `json:"PortBindings"` //TODO
+	AutoRemove           bool                        `json:"AutoRemove"`
+	CapAdd               []string                    `json:"CapAdd"`
+	CapDrop              []string                    `json:"CapDrop"`
+	DNS                  []string                    `json:"DNS"`
+	DNSOptions           []string                    `json:"DNSOptions"`
+	DNSSearch            []string                    `json:"DNSSearch"`
+	ExtraHosts           []string                    `json:"ExtraHosts"`
+	GroupAdd             []uint32                    `json:"GroupAdd"`
+	IpcMode              string                      `json:"IpcMode"`
+	Cgroup               string                      `json:"Cgroup"`
+	OomScoreAdj          *int                        `json:"OomScoreAdj"`
+	PidMode              string                      `json:"PidMode"`
+	Privileged           bool                        `json:"Privileged"`
+	PublishAllPorts      bool                        `json:"PublishAllPorts"` //TODO
+	ReadonlyRootfs       bool                        `json:"ReadonlyRootfs"`
+	SecurityOpt          []string                    `json:"SecurityOpt"`
+	UTSMode              string                      `json:"UTSMode"`
+	UsernsMode           string                      `json:"UsernsMode"`
+	ShmSize              string                      `json:"ShmSize"`
+	Runtime              string                      `json:"Runtime"`
+	ConsoleSize          *specs.Box                  `json:"ConsoleSize"`
+	Isolation            string                      `json:"Isolation"` //TODO
+	CPUShares            *uint64                     `json:"CPUSShares"`
+	Memory               int64                       `json:"Memory"`
+	NanoCpus             int                         `json:"NanoCpus"` //check type, TODO
+	CgroupParent         string                      `json:"CgroupParent"`
+	BlkioWeight          *uint16                     `json:"BlkioWeight"`
+	BlkioWeightDevice    []specs.LinuxWeightDevice   `json:"BlkioWeightDevice"`
+	BlkioDeviceReadBps   []specs.LinuxThrottleDevice `json:"BlkioDeviceReadBps"`
+	BlkioDeviceWriteBps  []specs.LinuxThrottleDevice `json:"BlkioDeviceWriteBps"`
+	BlkioDeviceReadIOps  []specs.LinuxThrottleDevice `json:"BlkioDeviceReadIOps"`
+	BlkioDeviceWriteIOps []specs.LinuxThrottleDevice `json:"BlkioDeviceWriteIOps"`
+	CPUPeriod            *uint64                     `json:"CPUPeriod"`
+	CPUQuota             *int64                      `json:"CPUQuota"`
+	CPURealtimePeriod    *uint64                     `json:"CPURealtimePeriod"`
+	CPURealtimeRuntime   *int64                      `json:"CPURealtimeRuntime"`
+	CPUSetCpus           string                      `json:"CPUSetCpus"`
+	CPUSetMems           string                      `json:"CPUSetMems"`
+	Devices              []specs.LinuxDevice         `json:"Devices"`
+	DiskQuota            int                         `json:"DiskQuota"` //check type, TODO
+	KernelMemory         *int64                      `json:"KernelMemory"`
+	MemoryReservation    *int64                      `json:"MemoryReservation"`
+	MemorySwap           *int64                      `json:"MemorySwap"`
+	MemorySwappiness     *uint64                     `json:"MemorySwappiness"`
+	OomKillDisable       *bool                       `json:"OomKillDisable"`
+	PidsLimit            *int64                      `json:"PidsLimit"`
+	Ulimits              []string                    `json:"Ulimits"`
+	CPUCount             int                         `json:"CPUCount"`           //check type, TODO
+	CPUPercent           int                         `json:"CPUPercent"`         //check type, TODO
+	IOMaximumIOps        int                         `json:"IOMaximumIOps"`      //check type, TODO
+	IOMaximumBandwidth   int                         `json:"IOMaximumBandwidth"` //check type, TODO
+}
+
+// CtrConfig holds information about the container configuration
+type CtrConfig struct {
+	Hostname     string              `json:"Hostname"`
+	DomainName   string              `json:"Domainname"` //TODO
+	User         specs.User          `json:"User"`
+	AttachStdin  bool                `json:"AttachStdin"`  //TODO
+	AttachStdout bool                `json:"AttachStdout"` //TODO
+	AttachStderr bool                `json:"AttachStderr"` //TODO
+	Tty          bool                `json:"Tty"`
+	OpenStdin    bool                `json:"OpenStdin"`
+	StdinOnce    bool                `json:"StdinOnce"` //TODO
+	Env          []string            `json:"Env"`
+	Cmd          []string            `json:"Cmd"`
+	Image        string              `json:"Image"`
+	Volumes      map[string]struct{} `json:"Volumes"`
+	WorkingDir   string              `json:"WorkingDir"`
+	Entrypoint   string              `json:"Entrypoint"`
+	Labels       map[string]string   `json:"Labels"`
+	Annotations  map[string]string   `json:"Annotations"`
+	StopSignal   uint                `json:"StopSignal"`
+}
diff --git a/cmd/kpod/run.go b/cmd/kpod/run.go
index 7e078f66aa..6142983ad1 100644
--- a/cmd/kpod/run.go
+++ b/cmd/kpod/run.go
@@ -39,7 +39,7 @@ func runCmd(c *cli.Context) error {
 		return err
 	}
 
-	createImage := runtime.NewImage(createConfig.image)
+	createImage := runtime.NewImage(createConfig.Image)
 	createImage.LocalName, _ = createImage.GetLocalImageName()
 	if createImage.LocalName == "" {
 		// The image wasnt found by the user input'd name or its fqname
@@ -89,8 +89,8 @@ func runCmd(c *cli.Context) error {
 
 	// Gather up the options for NewContainer which consist of With... funcs
 	options = append(options, libpod.WithRootFSFromImage(imageID, imageName, false))
-	options = append(options, libpod.WithSELinuxLabels(createConfig.processLabel, createConfig.mountLabel))
-	options = append(options, libpod.WithShmDir(createConfig.shmDir))
+	options = append(options, libpod.WithSELinuxLabels(createConfig.ProcessLabel, createConfig.MountLabel))
+	options = append(options, libpod.WithShmDir(createConfig.ShmDir))
 	ctr, err := runtime.NewContainer(runtimeSpec, options...)
 	if err != nil {
 		return err
@@ -114,7 +114,7 @@ func runCmd(c *cli.Context) error {
 	// to finish before exiting main
 	var wg sync.WaitGroup
 
-	if !createConfig.detach {
+	if !createConfig.Detach {
 		// We increment the wg counter because we need to do the attach
 		wg.Add(1)
 		// Attach to the running container
@@ -133,13 +133,13 @@ func runCmd(c *cli.Context) error {
 	if err := ctr.Start(); err != nil {
 		return errors.Wrapf(err, "unable to start container %q", ctr.ID())
 	}
-	if createConfig.detach {
+	if createConfig.Detach {
 		fmt.Printf("%s\n", ctr.ID())
 		return nil
 	}
 	wg.Wait()
 
-	if createConfig.rm {
+	if createConfig.Rm {
 		return runtime.RemoveContainer(ctr, true)
 	}
 	return ctr.CleanupStorage()
diff --git a/cmd/kpod/spec.go b/cmd/kpod/spec.go
index b200ed77a5..4e00f04ff3 100644
--- a/cmd/kpod/spec.go
+++ b/cmd/kpod/spec.go
@@ -20,7 +20,7 @@ import (
 )
 
 func blockAccessToKernelFilesystems(config *createConfig, g *generate.Generator) {
-	if !config.privileged {
+	if !config.Privileged {
 		for _, mp := range []string{
 			"/proc/kcore",
 			"/proc/latency_stats",
@@ -47,12 +47,12 @@ func blockAccessToKernelFilesystems(config *createConfig, g *generate.Generator)
 }
 
 func addPidNS(config *createConfig, g *generate.Generator) error {
-	pidMode := config.pidMode
+	pidMode := config.PidMode
 	if pidMode.IsHost() {
 		return g.RemoveLinuxNamespace(libpod.PIDNamespace)
 	}
 	if pidMode.IsContainer() {
-		ctr, err := config.runtime.LookupContainer(pidMode.Container())
+		ctr, err := config.Runtime.LookupContainer(pidMode.Container())
 		if err != nil {
 			return errors.Wrapf(err, "container %q not found", pidMode.Container())
 		}
@@ -69,7 +69,7 @@ func addPidNS(config *createConfig, g *generate.Generator) error {
 }
 
 func addNetNS(config *createConfig, g *generate.Generator) error {
-	netMode := config.netMode
+	netMode := config.NetMode
 	if netMode.IsHost() {
 		return g.RemoveLinuxNamespace(libpod.NetNamespace)
 	}
@@ -80,7 +80,7 @@ func addNetNS(config *createConfig, g *generate.Generator) error {
 		return libpod.ErrNotImplemented
 	}
 	if netMode.IsContainer() {
-		ctr, err := config.runtime.LookupContainer(netMode.ConnectedContainer())
+		ctr, err := config.Runtime.LookupContainer(netMode.ConnectedContainer())
 		if err != nil {
 			return errors.Wrapf(err, "container %q not found", netMode.ConnectedContainer())
 		}
@@ -97,7 +97,7 @@ func addNetNS(config *createConfig, g *generate.Generator) error {
 }
 
 func addUTSNS(config *createConfig, g *generate.Generator) error {
-	utsMode := config.utsMode
+	utsMode := config.UtsMode
 	if utsMode.IsHost() {
 		return g.RemoveLinuxNamespace(libpod.UTSNamespace)
 	}
@@ -105,12 +105,12 @@ func addUTSNS(config *createConfig, g *generate.Generator) error {
 }
 
 func addIpcNS(config *createConfig, g *generate.Generator) error {
-	ipcMode := config.ipcMode
+	ipcMode := config.IpcMode
 	if ipcMode.IsHost() {
 		return g.RemoveLinuxNamespace(libpod.IPCNamespace)
 	}
 	if ipcMode.IsContainer() {
-		ctr, err := config.runtime.LookupContainer(ipcMode.Container())
+		ctr, err := config.Runtime.LookupContainer(ipcMode.Container())
 		if err != nil {
 			return errors.Wrapf(err, "container %q not found", ipcMode.Container())
 		}
@@ -133,7 +133,7 @@ func addRlimits(config *createConfig, g *generate.Generator) error {
 		err error
 	)
 
-	for _, u := range config.resources.ulimit {
+	for _, u := range config.Resources.Ulimit {
 		if ul, err = units.ParseUlimit(u); err != nil {
 			return errors.Wrapf(err, "ulimit option %q requires name=SOFT:HARD, failed to be parsed", u)
 		}
@@ -146,10 +146,10 @@ func addRlimits(config *createConfig, g *generate.Generator) error {
 func setupCapabilities(config *createConfig, configSpec *spec.Spec) error {
 	var err error
 	var caplist []string
-	if config.privileged {
+	if config.Privileged {
 		caplist = caps.GetAllCapabilities()
 	} else {
-		caplist, err = caps.TweakCapabilities(configSpec.Process.Capabilities.Bounding, config.capAdd, config.capDrop)
+		caplist, err = caps.TweakCapabilities(configSpec.Process.Capabilities.Bounding, config.CapAdd, config.CapDrop)
 		if err != nil {
 			return err
 		}
@@ -166,85 +166,85 @@ func setupCapabilities(config *createConfig, configSpec *spec.Spec) error {
 func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
 	g := generate.New()
 	g.AddCgroupsMount("ro")
-	g.SetProcessCwd(config.workDir)
-	g.SetProcessArgs(config.command)
-	g.SetProcessTerminal(config.tty)
+	g.SetProcessCwd(config.WorkDir)
+	g.SetProcessArgs(config.Command)
+	g.SetProcessTerminal(config.Tty)
 	// User and Group must go together
-	g.SetProcessUID(config.user)
-	g.SetProcessGID(config.group)
-	for _, gid := range config.groupAdd {
+	g.SetProcessUID(config.User)
+	g.SetProcessGID(config.Group)
+	for _, gid := range config.GroupAdd {
 		g.AddProcessAdditionalGid(gid)
 	}
 	for key, val := range config.GetAnnotations() {
 		g.AddAnnotation(key, val)
 	}
-	g.SetRootReadonly(config.readOnlyRootfs)
-	g.SetHostname(config.hostname)
-	if config.hostname != "" {
-		g.AddProcessEnv("HOSTNAME", config.hostname)
+	g.SetRootReadonly(config.ReadOnlyRootfs)
+	g.SetHostname(config.Hostname)
+	if config.Hostname != "" {
+		g.AddProcessEnv("HOSTNAME", config.Hostname)
 	}
 
-	for _, sysctl := range config.sysctl {
+	for _, sysctl := range config.Sysctl {
 		s := strings.SplitN(sysctl, "=", 2)
 		g.AddLinuxSysctl(s[0], s[1])
 	}
 
 	// RESOURCES - MEMORY
-	if config.resources.memory != 0 {
-		g.SetLinuxResourcesMemoryLimit(config.resources.memory)
+	if config.Resources.Memory != 0 {
+		g.SetLinuxResourcesMemoryLimit(config.Resources.Memory)
 	}
-	if config.resources.memoryReservation != 0 {
-		g.SetLinuxResourcesMemoryReservation(config.resources.memoryReservation)
+	if config.Resources.MemoryReservation != 0 {
+		g.SetLinuxResourcesMemoryReservation(config.Resources.MemoryReservation)
 	}
-	if config.resources.memorySwap != 0 {
-		g.SetLinuxResourcesMemorySwap(config.resources.memorySwap)
+	if config.Resources.MemorySwap != 0 {
+		g.SetLinuxResourcesMemorySwap(config.Resources.MemorySwap)
 	}
-	if config.resources.kernelMemory != 0 {
-		g.SetLinuxResourcesMemoryKernel(config.resources.kernelMemory)
+	if config.Resources.KernelMemory != 0 {
+		g.SetLinuxResourcesMemoryKernel(config.Resources.KernelMemory)
 	}
-	if config.resources.memorySwappiness != -1 {
-		g.SetLinuxResourcesMemorySwappiness(uint64(config.resources.memorySwappiness))
+	if config.Resources.MemorySwappiness != -1 {
+		g.SetLinuxResourcesMemorySwappiness(uint64(config.Resources.MemorySwappiness))
 	}
-	g.SetLinuxResourcesMemoryDisableOOMKiller(config.resources.disableOomKiller)
-	g.SetProcessOOMScoreAdj(config.resources.oomScoreAdj)
+	g.SetLinuxResourcesMemoryDisableOOMKiller(config.Resources.DisableOomKiller)
+	g.SetProcessOOMScoreAdj(config.Resources.OomScoreAdj)
 
 	// RESOURCES - CPU
 
-	if config.resources.cpuShares != 0 {
-		g.SetLinuxResourcesCPUShares(config.resources.cpuShares)
+	if config.Resources.CpuShares != 0 {
+		g.SetLinuxResourcesCPUShares(config.Resources.CpuShares)
 	}
-	if config.resources.cpuQuota != 0 {
-		g.SetLinuxResourcesCPUQuota(config.resources.cpuQuota)
+	if config.Resources.CpuQuota != 0 {
+		g.SetLinuxResourcesCPUQuota(config.Resources.CpuQuota)
 	}
-	if config.resources.cpuPeriod != 0 {
-		g.SetLinuxResourcesCPUPeriod(config.resources.cpuPeriod)
+	if config.Resources.CpuPeriod != 0 {
+		g.SetLinuxResourcesCPUPeriod(config.Resources.CpuPeriod)
 	}
-	if config.resources.cpuRtRuntime != 0 {
-		g.SetLinuxResourcesCPURealtimeRuntime(config.resources.cpuRtRuntime)
+	if config.Resources.CpuRtRuntime != 0 {
+		g.SetLinuxResourcesCPURealtimeRuntime(config.Resources.CpuRtRuntime)
 	}
-	if config.resources.cpuRtPeriod != 0 {
-		g.SetLinuxResourcesCPURealtimePeriod(config.resources.cpuRtPeriod)
+	if config.Resources.CpuRtPeriod != 0 {
+		g.SetLinuxResourcesCPURealtimePeriod(config.Resources.CpuRtPeriod)
 	}
-	if config.resources.cpus != "" {
-		g.SetLinuxResourcesCPUCpus(config.resources.cpus)
+	if config.Resources.Cpus != "" {
+		g.SetLinuxResourcesCPUCpus(config.Resources.Cpus)
 	}
-	if config.resources.cpusetMems != "" {
-		g.SetLinuxResourcesCPUMems(config.resources.cpusetMems)
+	if config.Resources.CpusetMems != "" {
+		g.SetLinuxResourcesCPUMems(config.Resources.CpusetMems)
 	}
 
 	// SECURITY OPTS
-	g.SetProcessNoNewPrivileges(config.noNewPrivileges)
-	g.SetProcessApparmorProfile(config.apparmorProfile)
-	g.SetProcessSelinuxLabel(config.processLabel)
-	g.SetLinuxMountLabel(config.mountLabel)
+	g.SetProcessNoNewPrivileges(config.NoNewPrivileges)
+	g.SetProcessApparmorProfile(config.ApparmorProfile)
+	g.SetProcessSelinuxLabel(config.ProcessLabel)
+	g.SetLinuxMountLabel(config.MountLabel)
 	blockAccessToKernelFilesystems(config, &g)
 
 	// RESOURCES - PIDS
-	if config.resources.pidsLimit != 0 {
-		g.SetLinuxResourcesPidsLimit(config.resources.pidsLimit)
+	if config.Resources.PidsLimit != 0 {
+		g.SetLinuxResourcesPidsLimit(config.Resources.PidsLimit)
 	}
 
-	for _, i := range config.tmpfs {
+	for _, i := range config.Tmpfs {
 		options := []string{"rw", "noexec", "nosuid", "nodev", "size=65536k"}
 		spliti := strings.SplitN(i, ":", 2)
 		if len(spliti) > 1 {
@@ -257,7 +257,7 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
 		g.AddTmpfsMount(spliti[0], options)
 	}
 
-	for name, val := range config.env {
+	for name, val := range config.Env {
 		g.AddProcessEnv(name, val)
 	}
 
@@ -282,14 +282,14 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
 	}
 	configSpec := g.Spec()
 
-	if config.seccompProfilePath != "" && config.seccompProfilePath != "unconfined" {
-		seccompProfile, err := ioutil.ReadFile(config.seccompProfilePath)
+	if config.SeccompProfilePath != "" && config.SeccompProfilePath != "unconfined" {
+		seccompProfile, err := ioutil.ReadFile(config.SeccompProfilePath)
 		if err != nil {
-			return nil, errors.Wrapf(err, "opening seccomp profile (%s) failed", config.seccompProfilePath)
+			return nil, errors.Wrapf(err, "opening seccomp profile (%s) failed", config.SeccompProfilePath)
 		}
 		var seccompConfig spec.LinuxSeccomp
 		if err := json.Unmarshal(seccompProfile, &seccompConfig); err != nil {
-			return nil, errors.Wrapf(err, "decoding seccomp profile (%s) failed", config.seccompProfilePath)
+			return nil, errors.Wrapf(err, "decoding seccomp profile (%s) failed", config.SeccompProfilePath)
 		}
 		configSpec.Linux.Seccomp = &seccompConfig
 	}
@@ -347,10 +347,10 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
 
 func (c *createConfig) CreateBlockIO() (spec.LinuxBlockIO, error) {
 	bio := spec.LinuxBlockIO{}
-	bio.Weight = &c.resources.blkioWeight
-	if len(c.resources.blkioWeightDevice) > 0 {
+	bio.Weight = &c.Resources.BlkioWeight
+	if len(c.Resources.BlkioWeightDevice) > 0 {
 		var lwds []spec.LinuxWeightDevice
-		for _, i := range c.resources.blkioWeightDevice {
+		for _, i := range c.Resources.BlkioWeightDevice {
 			wd, err := validateweightDevice(i)
 			if err != nil {
 				return bio, errors.Wrapf(err, "invalid values for blkio-weight-device")
@@ -364,29 +364,29 @@ func (c *createConfig) CreateBlockIO() (spec.LinuxBlockIO, error) {
 			lwds = append(lwds, lwd)
 		}
 	}
-	if len(c.resources.deviceReadBps) > 0 {
-		readBps, err := makeThrottleArray(c.resources.deviceReadBps)
+	if len(c.Resources.DeviceReadBps) > 0 {
+		readBps, err := makeThrottleArray(c.Resources.DeviceReadBps)
 		if err != nil {
 			return bio, err
 		}
 		bio.ThrottleReadBpsDevice = readBps
 	}
-	if len(c.resources.deviceWriteBps) > 0 {
-		writeBpds, err := makeThrottleArray(c.resources.deviceWriteBps)
+	if len(c.Resources.DeviceWriteBps) > 0 {
+		writeBpds, err := makeThrottleArray(c.Resources.DeviceWriteBps)
 		if err != nil {
 			return bio, err
 		}
 		bio.ThrottleWriteBpsDevice = writeBpds
 	}
-	if len(c.resources.deviceReadIOps) > 0 {
-		readIOps, err := makeThrottleArray(c.resources.deviceReadIOps)
+	if len(c.Resources.DeviceReadIOps) > 0 {
+		readIOps, err := makeThrottleArray(c.Resources.DeviceReadIOps)
 		if err != nil {
 			return bio, err
 		}
 		bio.ThrottleReadIOPSDevice = readIOps
 	}
-	if len(c.resources.deviceWriteIOps) > 0 {
-		writeIOps, err := makeThrottleArray(c.resources.deviceWriteIOps)
+	if len(c.Resources.DeviceWriteIOps) > 0 {
+		writeIOps, err := makeThrottleArray(c.Resources.DeviceWriteIOps)
 		if err != nil {
 			return bio, err
 		}
@@ -401,7 +401,7 @@ func (c *createConfig) GetAnnotations() map[string]string {
 	a := getDefaultAnnotations()
 	// TODO - Which annotations do we want added by default
 	// TODO - This should be added to the DB long term
-	if c.tty {
+	if c.Tty {
 		a["io.kubernetes.cri-o.TTY"] = "true"
 	}
 	return a
@@ -445,7 +445,7 @@ func getDefaultAnnotations() map[string]string {
 func (c *createConfig) GetVolumeMounts() ([]spec.Mount, error) {
 	var m []spec.Mount
 	var options []string
-	for _, i := range c.volumes {
+	for _, i := range c.Volumes {
 		// We need to handle SELinux options better here, specifically :Z
 		spliti := strings.Split(i, ":")
 		if len(spliti) > 2 {
@@ -472,12 +472,12 @@ func (c *createConfig) GetVolumeMounts() ([]spec.Mount, error) {
 			options = append(options, "rw")
 		}
 		if foundz {
-			if err := label.Relabel(spliti[0], c.mountLabel, true); err != nil {
+			if err := label.Relabel(spliti[0], c.MountLabel, true); err != nil {
 				return nil, errors.Wrapf(err, "relabel failed %q", spliti[0])
 			}
 		}
 		if foundZ {
-			if err := label.Relabel(spliti[0], c.mountLabel, false); err != nil {
+			if err := label.Relabel(spliti[0], c.MountLabel, false); err != nil {
 				return nil, errors.Wrapf(err, "relabel failed %q", spliti[0])
 			}
 		}
@@ -495,10 +495,10 @@ func (c *createConfig) GetVolumeMounts() ([]spec.Mount, error) {
 	return m, nil
 }
 
-//GetTmpfsMounts takes user provided input for tmpfs mounts and creates Mount structs
+//GetTmpfsMounts takes user provided input for Tmpfs mounts and creates Mount structs
 func (c *createConfig) GetTmpfsMounts() []spec.Mount {
 	var m []spec.Mount
-	for _, i := range c.tmpfs {
+	for _, i := range c.Tmpfs {
 		// Default options if nothing passed
 		options := []string{"rw", "noexec", "nosuid", "nodev", "size=65536k"}
 		spliti := strings.Split(i, ":")
@@ -522,12 +522,12 @@ func (c *createConfig) GetContainerCreateOptions() ([]libpod.CtrCreateOption, er
 	// Uncomment after talking to mheon about unimplemented funcs
 	// options = append(options, libpod.WithLabels(c.labels))
 
-	if c.interactive {
+	if c.Interactive {
 		options = append(options, libpod.WithStdin())
 	}
-	if c.name != "" {
-		logrus.Debugf("appending name %s", c.name)
-		options = append(options, libpod.WithName(c.name))
+	if c.Name != "" {
+		logrus.Debugf("appending name %s", c.Name)
+		options = append(options, libpod.WithName(c.Name))
 	}
 
 	return options, nil
diff --git a/cmd/kpod/spec_test.go b/cmd/kpod/spec_test.go
index 799d6b2358..01e1a4ad37 100644
--- a/cmd/kpod/spec_test.go
+++ b/cmd/kpod/spec_test.go
@@ -16,7 +16,7 @@ func TestCreateConfig_GetVolumeMounts(t *testing.T) {
 		Options:     []string{"ro", "rbind", "rprivate"},
 	}
 	config := createConfig{
-		volumes: []string{"foobar:/foobar:ro"},
+		Volumes: []string{"foobar:/foobar:ro"},
 	}
 	specMount, err := config.GetVolumeMounts()
 	assert.NoError(t, err)
@@ -31,7 +31,7 @@ func TestCreateConfig_GetTmpfsMounts(t *testing.T) {
 		Options:     []string{"rw", "size=787448k", "mode=1777"},
 	}
 	config := createConfig{
-		tmpfs: []string{"/homer:rw,size=787448k,mode=1777"},
+		Tmpfs: []string{"/homer:rw,size=787448k,mode=1777"},
 	}
 	tmpfsMount := config.GetTmpfsMounts()
 	assert.True(t, reflect.DeepEqual(data, tmpfsMount[0]))
diff --git a/docs/kpod-inspect.1.md b/docs/kpod-inspect.1.md
index 1baa46f138..d3927cd371 100644
--- a/docs/kpod-inspect.1.md
+++ b/docs/kpod-inspect.1.md
@@ -28,144 +28,55 @@ Display the total file size if the type is a container
 
 ## EXAMPLE
 
-kpod inspect redis:alpine
-
+```
+# kpod inspect fedora
 {
-    "ArgsEscaped": true,
-    "AttachStderr": false,
-    "AttachStdin": false,
-    "AttachStdout": false,
-    "Cmd": [
-	"/bin/sh",
-	"-c",
-	"#(nop) ",
-	"CMD [\"redis-server\"]"
+    "Id": "422dc563ca3260ad9ef5c47a1c246f5065d7f177ce51f4dd208efd82967ff182",
+    "Digest": "sha256:1b9bfb4e634dc1e5c19d0fa1eb2e5a28a5c2b498e3d3e4ac742bd7f5dae08611",
+    "RepoTags": [
+        "docker.io/library/fedora:latest"
     ],
-    "Domainname": "",
-    "Entrypoint": [
-	"entrypoint.sh"
-    ],
-    "Env": [
-	"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
-	"REDIS_VERSION=3.2.9",
-	"REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-3.2.9.tar.gz",
-	"REDIS_DOWNLOAD_SHA=6eaacfa983b287e440d0839ead20c2231749d5d6b78bbe0e0ffa3a890c59ff26"
-    ],
-    "ExposedPorts": {
-	"6379/tcp": {}
-    },
-    "Hostname": "e1ede117fb1e",
-    "Image": "sha256:75e877aa15b534396de82d385386cc4dda7819d5cbb018b9f97b77aeb8f4b55a",
-    "Labels": {},
-    "OnBuild": [],
-    "OpenStdin": false,
-    "StdinOnce": false,
-    "Tty": false,
-    "User": "",
-    "Volumes": {
-	"/data": {}
-    },
-    "WorkingDir": "/data"
-}
-{
-    "ID": "b3f2436bdb978c1d33b1387afb5d7ba7e3243ed2ce908db431ac0069da86cb45",
-    "Names": [
-	"docker.io/library/redis:alpine"
-    ],
-    "Digests": [
-	"sha256:88286f41530e93dffd4b964e1db22ce4939fffa4a4c665dab8591fbab03d4926",
-	"sha256:07b1ac6c7a5068201d8b63a09bb15358ec1616b813ef3942eb8cc12ae191227f",
-	"sha256:91e2e140ea27b3e89f359cd9fab4ec45647dda2a8e5fb0c78633217d9dca87b5",
-	"sha256:08957ceaa2b3be874cde8d7fa15c274300f47185acd62bca812a2ffb6228482d",
-	"sha256:acd3d12a6a79f772961a771f678c1a39e1f370e7baeb9e606ad8f1b92572f4ab",
-	"sha256:4ad88df090801e8faa8cf0be1f403b77613d13e11dad73f561461d482f79256c",
-	"sha256:159ac12c79e1a8d85dfe61afff8c64b96881719139730012a9697f432d6b739a"
+    "RepoDigests": [
+        "docker.io/library/fedora@sha256:1b9bfb4e634dc1e5c19d0fa1eb2e5a28a5c2b498e3d3e4ac742bd7f5dae08611"
     ],
     "Parent": "",
     "Comment": "",
-    "Created": "2017-06-28T22:14:36.35280993Z",
-    "Container": "ba8d6c6b0d7fdd201fce404236136b44f3bfdda883466531a3d1a1f87906770b",
-    "ContainerConfig": {
-	"Hostname": "e1ede117fb1e",
-	"Domainname": "",
-	"User": "",
-	"AttachStdin": false,
-	"AttachStdout": false,
-	"AttachStderr": false,
-	"Tty": false,
-	"OpenStdin": false,
-	"StdinOnce": false,
-	"Env": [
-	    "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
-	    "REDIS_VERSION=3.2.9",
-	    "REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-3.2.9.tar.gz",
-	    "REDIS_DOWNLOAD_SHA=6eaacfa983b287e440d0839ead20c2231749d5d6b78bbe0e0ffa3a890c59ff26"
-	],
-	"Cmd": [
-	    "/bin/sh",
-	    "-c",
-	    "#(nop) ",
-	    "CMD [\"redis-server\"]"
-	],
-	"ArgsEscaped": true,
-	"Image": "sha256:75e877aa15b534396de82d385386cc4dda7819d5cbb018b9f97b77aeb8f4b55a",
-	"Volumes": {
-	    "/data": {}
-	},
-	"WorkingDir": "/data",
-	"Entrypoint": [
-	    "entrypoint.sh"
-	],
-	"Labels": {},
-	"OnBuild": []
-    },
-    "Author": "",
+    "Created": "2017-11-14T21:07:08.475840838Z",
     "Config": {
-	"ExposedPorts": {
-	    "6379/tcp": {}
-	},
-	"Env": [
-	    "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
-	    "REDIS_VERSION=3.2.9",
-	    "REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-3.2.9.tar.gz",
-	    "REDIS_DOWNLOAD_SHA=6eaacfa983b287e440d0839ead20c2231749d5d6b78bbe0e0ffa3a890c59ff26"
-	],
-	"Entrypoint": [
-	    "entrypoint.sh"
-	],
-	"Cmd": [
-	    "redis-server"
-	],
-	"Volumes": {
-	    "/data": {}
-	},
-	"WorkingDir": "/data"
+        "Env": [
+            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+            "DISTTAG=f27container",
+            "FGC=f27",
+            "FBR=f27"
+        ]
     },
+    "Version": "17.06.2-ce",
+    "Author": "[Adam Miller \u003cmaxamillion@fedoraproject.org\u003e] [Patrick Uiterwijk \u003cpatrick@puiterwijk.org\u003e]",
     "Architecture": "amd64",
-    "OS": "linux",
-    "Size": 3965955,
-    "VirtualSize": 19808086,
+    "Os": "linux",
+    "Size": 251722732,
+    "VirtualSize": 514895140,
     "GraphDriver": {
-	"Name": "overlay",
-	"Data": {
-	    "MergedDir": "/var/lib/containers/storage/overlay/2059d805c90e034cb773d9722232ef018a72143dd31113b470fb876baeccd700/merged",
-	    "UpperDir": "/var/lib/containers/storage/overlay/2059d805c90e034cb773d9722232ef018a72143dd31113b470fb876baeccd700/diff",
-	    "WorkDir": "/var/lib/containers/storage/overlay/2059d805c90e034cb773d9722232ef018a72143dd31113b470fb876baeccd700/work"
-	}
+        "Name": "overlay",
+        "Data": {
+            "MergedDir": "/var/lib/containers/storage/overlay/d32459d9ce237564fb93573b85cbc707600d43fbe5e46e8eeef22cad914bb516/merged",
+            "UpperDir": "/var/lib/containers/storage/overlay/d32459d9ce237564fb93573b85cbc707600d43fbe5e46e8eeef22cad914bb516/diff",
+            "WorkDir": "/var/lib/containers/storage/overlay/d32459d9ce237564fb93573b85cbc707600d43fbe5e46e8eeef22cad914bb516/work"
+        }
     },
     "RootFS": {
-	"type": "layers",
-	"diff_ids": [
-	    "sha256:5bef08742407efd622d243692b79ba0055383bbce12900324f75e56f589aedb0",
-	    "sha256:c92a8fc997217611d0bfc9ff14d7ec00350ca564aef0ecbf726624561d7872d7",
-	    "sha256:d4c406dea37a107b0cccb845611266a146725598be3e82ba31c55c08d1583b5a",
-	    "sha256:8b4fa064e2b6c03a6c37089b0203f167375a8b49259c0ad7cb47c8c1e58b3fa0",
-	    "sha256:c393e3d0b00ddf6b4166f1e2ad68245e08e9e3be0a0567a36d0a43854f03bfd6",
-	    "sha256:38047b4117cb8bb3bba82991daf9a4e14ba01f9f66c1434d4895a7e96f67d8ba"
-	]
-    }
+        "Type": "layers",
+        "Layers": [
+            "sha256:d32459d9ce237564fb93573b85cbc707600d43fbe5e46e8eeef22cad914bb516"
+        ]
+    },
+    "Labels": null,
+    "Annotations": {}
 }
-
+```
 
 ## SEE ALSO
 kpod(1)
+
+## HISTORY
+July 2017, Originally compiled by Dan Walsh <dwalsh@redhat.com>
diff --git a/libkpod/container_data.go b/libkpod/container_data.go
deleted file mode 100644
index eb84aa42d3..0000000000
--- a/libkpod/container_data.go
+++ /dev/null
@@ -1,210 +0,0 @@
-package libkpod
-
-import (
-	"encoding/json"
-	"os"
-	"time"
-
-	"k8s.io/apimachinery/pkg/fields"
-	pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
-
-	"github.com/opencontainers/image-spec/specs-go/v1"
-	specs "github.com/opencontainers/runtime-spec/specs-go"
-	"github.com/pkg/errors"
-	"github.com/projectatomic/libpod/libpod/driver"
-	"github.com/projectatomic/libpod/libpod/images"
-	"github.com/projectatomic/libpod/oci"
-)
-
-// ContainerData handles the data used when inspecting a container
-type ContainerData struct {
-	ID               string
-	Name             string
-	LogPath          string
-	Labels           fields.Set
-	Annotations      fields.Set
-	State            *ContainerState
-	Metadata         *pb.ContainerMetadata
-	BundlePath       string
-	StopSignal       string
-	FromImage        string `json:"Image,omitempty"`
-	FromImageID      string `json:"ImageID"`
-	MountPoint       string `json:"Mountpoint,omitempty"`
-	MountLabel       string
-	Mounts           []specs.Mount
-	AppArmorProfile  string
-	ImageAnnotations map[string]string `json:"Annotations,omitempty"`
-	ImageCreatedBy   string            `json:"CreatedBy,omitempty"`
-	Config           v1.ImageConfig    `json:"Config,omitempty"`
-	SizeRw           uint              `json:"SizeRw,omitempty"`
-	SizeRootFs       uint              `json:"SizeRootFs,omitempty"`
-	Args             []string
-	ResolvConfPath   string
-	HostnamePath     string
-	HostsPath        string
-	GraphDriver      driverData
-}
-
-type driverData struct {
-	Name string
-	Data map[string]string
-}
-
-// ContainerState represents the status of a container.
-type ContainerState struct {
-	specs.State
-	Created   time.Time `json:"created"`
-	Started   time.Time `json:"started,omitempty"`
-	Finished  time.Time `json:"finished,omitempty"`
-	ExitCode  int32     `json:"exitCode"`
-	OOMKilled bool      `json:"oomKilled,omitempty"`
-	Error     string    `json:"error,omitempty"`
-}
-
-// GetContainerData gets the ContainerData for a container with the given name in the given store.
-// If size is set to true, it will also determine the size of the container
-func (c *ContainerServer) GetContainerData(name string, size bool) (*ContainerData, error) {
-	ctr, err := c.inspectContainer(name)
-	if err != nil {
-		return nil, errors.Wrapf(err, "error reading build container %q", name)
-	}
-	container, err := c.store.Container(name)
-	if err != nil {
-		return nil, errors.Wrapf(err, "error reading container data")
-	}
-
-	// The runtime configuration won't exist if the container has never been started by cri-o or kpod,
-	// so treat a not-exist error as non-fatal.
-	m := getBlankSpec()
-	config, err := c.store.FromContainerDirectory(ctr.ID(), "config.json")
-	if err != nil && !os.IsNotExist(errors.Cause(err)) {
-		return nil, err
-	}
-	if len(config) > 0 {
-		if err = json.Unmarshal(config, &m); err != nil {
-			return nil, err
-		}
-	}
-
-	if container.ImageID == "" {
-		return nil, errors.Errorf("error reading container image data: container is not based on an image")
-	}
-	imageData, err := images.GetData(c.store, container.ImageID)
-	if err != nil {
-		return nil, errors.Wrapf(err, "error reading container image data")
-	}
-
-	driverName, err := driver.GetDriverName(c.store)
-	if err != nil {
-		return nil, err
-	}
-	topLayer, err := c.GetContainerTopLayerID(ctr.ID())
-	if err != nil {
-		return nil, err
-	}
-	layer, err := c.store.Layer(topLayer)
-	if err != nil {
-		return nil, err
-	}
-	driverMetadata, err := driver.GetDriverMetadata(c.store, topLayer)
-	if err != nil {
-		return nil, err
-	}
-	imageName := ""
-	if len(imageData.Tags) > 0 {
-		imageName = imageData.Tags[0]
-	} else if len(imageData.Digests) > 0 {
-		imageName = imageData.Digests[0]
-	}
-	data := &ContainerData{
-		ID:               ctr.ID(),
-		Name:             ctr.Name(),
-		LogPath:          ctr.LogPath(),
-		Labels:           ctr.Labels(),
-		Annotations:      ctr.Annotations(),
-		State:            c.State(ctr),
-		Metadata:         ctr.Metadata(),
-		BundlePath:       ctr.BundlePath(),
-		StopSignal:       ctr.GetStopSignal(),
-		Args:             m.Process.Args,
-		FromImage:        imageName,
-		FromImageID:      container.ImageID,
-		MountPoint:       layer.MountPoint,
-		ImageAnnotations: imageData.Annotations,
-		ImageCreatedBy:   imageData.CreatedBy,
-		Config:           imageData.Config,
-		GraphDriver: driverData{
-			Name: driverName,
-			Data: driverMetadata,
-		},
-		MountLabel:      m.Linux.MountLabel,
-		Mounts:          m.Mounts,
-		AppArmorProfile: m.Process.ApparmorProfile,
-		ResolvConfPath:  "",
-		HostnamePath:    "",
-		HostsPath:       "",
-	}
-
-	if size {
-		sizeRootFs, err := c.GetContainerRootFsSize(data.ID)
-		if err != nil {
-
-			return nil, errors.Wrapf(err, "error reading size for container %q", name)
-		}
-		data.SizeRootFs = uint(sizeRootFs)
-		sizeRw, err := c.GetContainerRwSize(data.ID)
-		if err != nil {
-			return nil, errors.Wrapf(err, "error reading RWSize for container %q", name)
-		}
-		data.SizeRw = uint(sizeRw)
-	}
-
-	return data, nil
-}
-
-// Get an oci.Container and update its status
-func (c *ContainerServer) inspectContainer(container string) (*oci.Container, error) {
-	ociCtr, err := c.LookupContainer(container)
-	if err != nil {
-		return nil, err
-	}
-	// call runtime.UpdateStatus()
-	err = c.Runtime().UpdateStatus(ociCtr)
-	if err != nil {
-		return nil, err
-	}
-	return ociCtr, nil
-}
-
-func getBlankSpec() specs.Spec {
-	return specs.Spec{
-		Process:     &specs.Process{},
-		Root:        &specs.Root{},
-		Mounts:      []specs.Mount{},
-		Hooks:       &specs.Hooks{},
-		Annotations: make(map[string]string),
-		Linux:       &specs.Linux{},
-		Solaris:     &specs.Solaris{},
-		Windows:     &specs.Windows{},
-	}
-}
-
-// State copies the crio container state to ContainerState type for kpod
-func (c *ContainerServer) State(ctr *oci.Container) *ContainerState {
-	crioState := ctr.State()
-	specState := specs.State{
-		Version:     crioState.Version,
-		ID:          crioState.ID,
-		Status:      crioState.Status,
-		Pid:         crioState.Pid,
-		Bundle:      crioState.Bundle,
-		Annotations: crioState.Annotations,
-	}
-	cState := &ContainerState{
-		Started:  crioState.Started,
-		Created:  crioState.Created,
-		Finished: crioState.Finished,
-	}
-	cState.State = specState
-	return cState
-}
diff --git a/libpod/container.go b/libpod/container.go
index fce64b0dd6..d53a863c03 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -22,6 +22,7 @@ import (
 	"github.com/opencontainers/runtime-tools/generate"
 	"github.com/opencontainers/selinux/go-selinux/label"
 	"github.com/pkg/errors"
+	"github.com/projectatomic/libpod/libpod/driver"
 	crioAnnotations "github.com/projectatomic/libpod/pkg/annotations"
 	"github.com/sirupsen/logrus"
 	"github.com/ulule/deepcopier"
@@ -132,6 +133,7 @@ type ContainerConfig struct {
 	SharedNamespaceMap map[string]string `json:"sharedNamespaces"`
 	// Time container was created
 	CreatedTime time.Time `json:"createdTime"`
+
 	// TODO save log location here and pass into OCI code
 	// TODO allow overriding of log path
 }
@@ -192,7 +194,6 @@ func (c *Container) Labels() map[string]string {
 	for key, value := range c.config.Labels {
 		labels[key] = value
 	}
-
 	return labels
 }
 
@@ -204,6 +205,68 @@ func (c *Container) Config() *ContainerConfig {
 	return returnConfig
 }
 
+// RuntimeName returns the name of the runtime
+func (c *Container) RuntimeName() string {
+	return c.runtime.ociRuntime.name
+}
+
+// rootFsSize gets the size of the container's root filesystem
+// A container FS is split into two parts.  The first is the top layer, a
+// mutable layer, and the rest is the RootFS: the set of immutable layers
+// that make up the image on which the container is based.
+func (c *Container) rootFsSize() (int64, error) {
+	container, err := c.runtime.store.Container(c.ID())
+	if err != nil {
+		return 0, err
+	}
+
+	// Ignore the size of the top layer.   The top layer is a mutable RW layer
+	// and is not considered a part of the rootfs
+	rwLayer, err := c.runtime.store.Layer(container.LayerID)
+	if err != nil {
+		return 0, err
+	}
+	layer, err := c.runtime.store.Layer(rwLayer.Parent)
+	if err != nil {
+		return 0, err
+	}
+
+	size := int64(0)
+	for layer.Parent != "" {
+		layerSize, err := c.runtime.store.DiffSize(layer.Parent, layer.ID)
+		if err != nil {
+			return size, errors.Wrapf(err, "getting diffsize of layer %q and its parent %q", layer.ID, layer.Parent)
+		}
+		size += layerSize
+		layer, err = c.runtime.store.Layer(layer.Parent)
+		if err != nil {
+			return 0, err
+		}
+	}
+	// Get the size of the last layer.  Has to be outside of the loop
+	// because the parent of the last layer is "", andlstore.Get("")
+	// will return an error.
+	layerSize, err := c.runtime.store.DiffSize(layer.Parent, layer.ID)
+	return size + layerSize, err
+}
+
+// rwSize Gets the size of the mutable top layer of the container.
+func (c *Container) rwSize() (int64, error) {
+	container, err := c.runtime.store.Container(c.ID())
+	if err != nil {
+		return 0, err
+	}
+
+	// Get the size of the top layer by calculating the size of the diff
+	// between the layer and its parent.  The top layer of a container is
+	// the only RW layer, all others are immutable
+	layer, err := c.runtime.store.Layer(container.LayerID)
+	if err != nil {
+		return 0, err
+	}
+	return c.runtime.store.DiffSize(layer.Parent, layer.ID)
+}
+
 // LogPath returns the path to the container's log file
 // This file will only be present after Init() is called to create the container
 // in runc
@@ -829,6 +892,31 @@ func (c *Container) getArtifactPath(name string) string {
 	return filepath.Join(c.config.StaticDir, artifactsDir, name)
 }
 
+// Inspect a container for low-level information
+func (c *Container) Inspect(size bool) (*ContainerInspectData, error) {
+	c.lock.Lock()
+	defer c.lock.Unlock()
+
+	if err := c.syncContainer(); err != nil {
+		return nil, err
+	}
+
+	storeCtr, err := c.runtime.store.Container(c.ID())
+	if err != nil {
+		return nil, errors.Wrapf(err, "error getting container from store %q", c.ID())
+	}
+	layer, err := c.runtime.store.Layer(storeCtr.LayerID)
+	if err != nil {
+		return nil, errors.Wrapf(err, "error reading information about layer %q", storeCtr.LayerID)
+	}
+	driverData, err := driver.GetDriverData(c.runtime.store, layer.ID)
+	if err != nil {
+		return nil, errors.Wrapf(err, "error getting graph driver info %q", c.ID())
+	}
+
+	return c.getContainerInspectData(size, driverData)
+}
+
 // Commit commits the changes between a container and its image, creating a new
 // image
 func (c *Container) Commit() (*storage.Image, error) {
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
new file mode 100644
index 0000000000..5f29a231e2
--- /dev/null
+++ b/libpod/container_inspect.go
@@ -0,0 +1,70 @@
+package libpod
+
+import (
+	"github.com/projectatomic/libpod/libpod/driver"
+	"github.com/sirupsen/logrus"
+)
+
+func (c *Container) getContainerInspectData(size bool, driverData *driver.Data) (*ContainerInspectData, error) {
+	config := c.config
+	runtimeInfo := c.state
+	spec := c.config.Spec
+
+	args := config.Spec.Process.Args
+	var path string
+	if len(args) > 0 {
+		path = args[0]
+	}
+	if len(args) > 1 {
+		args = args[1:]
+	}
+
+	data := &ContainerInspectData{
+		ID:      config.ID,
+		Created: config.CreatedTime,
+		Path:    path,
+		Args:    args,
+		State: &ContainerInspectState{
+			OciVersion: spec.Version,
+			Status:     runtimeInfo.State.String(),
+			Running:    runtimeInfo.State == ContainerStateRunning,
+			Paused:     runtimeInfo.State == ContainerStatePaused,
+			OOMKilled:  runtimeInfo.OOMKilled,
+			Dead:       runtimeInfo.State.String() == "bad state",
+			Pid:        runtimeInfo.PID,
+			ExitCode:   runtimeInfo.ExitCode,
+			Error:      "", // can't get yet
+			StartedAt:  runtimeInfo.StartedTime,
+			FinishedAt: runtimeInfo.FinishedTime,
+		},
+		ImageID:         config.RootfsImageID,
+		ImageName:       config.RootfsImageName,
+		ResolvConfPath:  "",                                                   // TODO get from networking path
+		HostnamePath:    spec.Annotations["io.kubernetes.cri-o.HostnamePath"], // not sure
+		HostsPath:       "",                                                   // can't get yet
+		StaticDir:       config.StaticDir,
+		LogPath:         c.LogPath(),
+		Name:            config.Name,
+		Driver:          driverData.Name,
+		MountLabel:      config.MountLabel,
+		ProcessLabel:    spec.Process.SelinuxLabel,
+		AppArmorProfile: spec.Process.ApparmorProfile,
+		ExecIDs:         []string{}, //TODO
+		GraphDriver:     driverData,
+		Mounts:          spec.Mounts,
+		NetworkSettings: &NetworkSettings{}, // TODO from networking patch
+	}
+	if size {
+		rootFsSize, err := c.rootFsSize()
+		if err != nil {
+			logrus.Errorf("error getting rootfs size %q: %v", config.ID, err)
+		}
+		rwSize, err := c.rwSize()
+		if err != nil {
+			logrus.Errorf("error getting rw size %q: %v", config.ID, err)
+		}
+		data.SizeRootFs = rootFsSize
+		data.SizeRw = rwSize
+	}
+	return data, nil
+}
diff --git a/libpod/driver/driver.go b/libpod/driver/driver.go
index 4db55852c1..8475810a82 100644
--- a/libpod/driver/driver.go
+++ b/libpod/driver/driver.go
@@ -4,8 +4,8 @@ import cstorage "github.com/containers/storage"
 
 // Data handles the data for a storage driver
 type Data struct {
-	Name string
-	Data map[string]string
+	Name string            `json:"Name"`
+	Data map[string]string `json:"Data"`
 }
 
 // GetDriverName returns the name of the driver for the given store
@@ -25,3 +25,19 @@ func GetDriverMetadata(store cstorage.Store, layerID string) (map[string]string,
 	}
 	return driver.Metadata(layerID)
 }
+
+// GetDriverData returns the Data struct with information of the driver used by the store
+func GetDriverData(store cstorage.Store, layerID string) (*Data, error) {
+	name, err := GetDriverName(store)
+	if err != nil {
+		return nil, err
+	}
+	metaData, err := GetDriverMetadata(store, layerID)
+	if err != nil {
+		return nil, err
+	}
+	return &Data{
+		Name: name,
+		Data: metaData,
+	}, nil
+}
diff --git a/libpod/image_inspect.go b/libpod/image_inspect.go
new file mode 100644
index 0000000000..a086654349
--- /dev/null
+++ b/libpod/image_inspect.go
@@ -0,0 +1,81 @@
+package libpod
+
+import (
+	"encoding/json"
+	"strings"
+
+	"github.com/containers/image/types"
+	"github.com/containers/storage"
+	digest "github.com/opencontainers/go-digest"
+	ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
+	"github.com/pkg/errors"
+	"github.com/projectatomic/libpod/libpod/driver"
+)
+
+func getImageData(img storage.Image, imgRef types.Image, size int64, driver *driver.Data) (*ImageData, error) {
+	imgSize, err := imgRef.Size()
+	if err != nil {
+		return nil, errors.Wrapf(err, "error reading size of image %q", img.ID)
+	}
+	manifest, manifestType, err := imgRef.Manifest()
+	if err != nil {
+		return nil, errors.Wrapf(err, "error reading manifest for image %q", img.ID)
+	}
+	imgDigest := digest.Digest("")
+	if len(manifest) > 0 {
+		imgDigest = digest.Canonical.FromBytes(manifest)
+	}
+	annotations := annotations(manifest, manifestType)
+
+	ociv1Img, err := imgRef.OCIConfig()
+	if err != nil {
+		return nil, errors.Wrapf(err, "error getting oci image info %q", img.ID)
+	}
+	info, err := imgRef.Inspect()
+	if err != nil {
+		return nil, errors.Wrapf(err, "error getting image info %q", img.ID)
+	}
+
+	var repoDigests []string
+	for _, name := range img.Names {
+		repoDigests = append(repoDigests, strings.SplitN(name, ":", 2)[0]+"@"+imgDigest.String())
+	}
+
+	data := &ImageData{
+		ID:           img.ID,
+		RepoTags:     img.Names,
+		RepoDigests:  repoDigests,
+		Comment:      ociv1Img.History[0].Comment,
+		Created:      ociv1Img.Created,
+		Author:       ociv1Img.History[0].Author,
+		Architecture: ociv1Img.Architecture,
+		Os:           ociv1Img.OS,
+		Config:       &ociv1Img.Config,
+		Version:      info.DockerVersion,
+		Size:         size,
+		VirtualSize:  size + imgSize,
+		Annotations:  annotations,
+		Digest:       imgDigest,
+		Labels:       info.Labels,
+		RootFS: &RootFS{
+			Type:   ociv1Img.RootFS.Type,
+			Layers: ociv1Img.RootFS.DiffIDs,
+		},
+		GraphDriver: driver,
+	}
+	return data, nil
+}
+
+func annotations(manifest []byte, manifestType string) map[string]string {
+	annotations := make(map[string]string)
+	switch manifestType {
+	case ociv1.MediaTypeImageManifest:
+		var m ociv1.Manifest
+		if err := json.Unmarshal(manifest, &m); err == nil {
+			for k, v := range m.Annotations {
+				annotations[k] = v
+			}
+		}
+	}
+	return annotations
+}
diff --git a/libpod/images/image_data.go b/libpod/images/image_data.go
deleted file mode 100644
index 1fa63f6cb8..0000000000
--- a/libpod/images/image_data.go
+++ /dev/null
@@ -1,202 +0,0 @@
-package images
-
-import (
-	"encoding/json"
-	"time"
-
-	"github.com/containers/image/docker/reference"
-	is "github.com/containers/image/storage"
-	"github.com/containers/image/transports"
-	"github.com/containers/image/types"
-	"github.com/containers/storage"
-	digest "github.com/opencontainers/go-digest"
-	ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
-	"github.com/pkg/errors"
-	"github.com/projectatomic/libpod/libpod/driver"
-)
-
-// Data handles the data used when inspecting a container
-// nolint
-type Data struct {
-	ID           string
-	Tags         []string
-	Digests      []string
-	Digest       digest.Digest
-	Comment      string
-	Created      *time.Time
-	Container    string
-	Author       string
-	Config       ociv1.ImageConfig
-	Architecture string
-	OS           string
-	Annotations  map[string]string
-	CreatedBy    string
-	Size         uint
-	VirtualSize  uint
-	GraphDriver  driver.Data
-	RootFS       ociv1.RootFS
-}
-
-// ParseImageNames parses the names we've stored with an image into a list of
-// tagged references and a list of references which contain digests.
-func ParseImageNames(names []string) (tags, digests []string, err error) {
-	for _, name := range names {
-		if named, err := reference.ParseNamed(name); err == nil {
-			if digested, ok := named.(reference.Digested); ok {
-				canonical, err := reference.WithDigest(named, digested.Digest())
-				if err == nil {
-					digests = append(digests, canonical.String())
-				}
-			} else {
-				if reference.IsNameOnly(named) {
-					named = reference.TagNameOnly(named)
-				}
-				if tagged, ok := named.(reference.Tagged); ok {
-					namedTagged, err := reference.WithTag(named, tagged.Tag())
-					if err == nil {
-						tags = append(tags, namedTagged.String())
-					}
-				}
-			}
-		}
-	}
-	return tags, digests, nil
-}
-
-func annotations(manifest []byte, manifestType string) map[string]string {
-	annotations := make(map[string]string)
-	switch manifestType {
-	case ociv1.MediaTypeImageManifest:
-		var m ociv1.Manifest
-		if err := json.Unmarshal(manifest, &m); err == nil {
-			for k, v := range m.Annotations {
-				annotations[k] = v
-			}
-		}
-	}
-	return annotations
-}
-
-// GetData gets the Data for a container with the given name in the given store.
-func GetData(store storage.Store, name string) (*Data, error) {
-	img, err := FindImage(store, name)
-	if err != nil {
-		return nil, errors.Wrapf(err, "error reading image %q", name)
-	}
-
-	imgRef, err := FindImageRef(store, "@"+img.ID)
-	if err != nil {
-		return nil, errors.Wrapf(err, "error reading image %q", img.ID)
-	}
-
-	tags, digests, err := ParseImageNames(img.Names)
-	if err != nil {
-		return nil, errors.Wrapf(err, "error parsing image names for %q", name)
-	}
-
-	driverName, err := driver.GetDriverName(store)
-	if err != nil {
-		return nil, errors.Wrapf(err, "error reading name of storage driver")
-	}
-
-	topLayerID := img.TopLayer
-
-	driverMetadata, err := driver.GetDriverMetadata(store, topLayerID)
-	if err != nil {
-		return nil, errors.Wrapf(err, "error asking storage driver %q for metadata", driverName)
-	}
-
-	layer, err := store.Layer(topLayerID)
-	if err != nil {
-		return nil, errors.Wrapf(err, "error reading information about layer %q", topLayerID)
-	}
-	size, err := store.DiffSize(layer.Parent, layer.ID)
-	if err != nil {
-		return nil, errors.Wrapf(err, "error determining size of layer %q", layer.ID)
-	}
-
-	imgSize, err := imgRef.Size()
-	if err != nil {
-		return nil, errors.Wrapf(err, "error determining size of image %q", transports.ImageName(imgRef.Reference()))
-	}
-
-	manifest, manifestType, err := imgRef.Manifest()
-	if err != nil {
-		return nil, errors.Wrapf(err, "error reading manifest for image %q", img.ID)
-	}
-	manifestDigest := digest.Digest("")
-	if len(manifest) > 0 {
-		manifestDigest = digest.Canonical.FromBytes(manifest)
-	}
-	annotations := annotations(manifest, manifestType)
-
-	config, err := imgRef.OCIConfig()
-	if err != nil {
-		return nil, errors.Wrapf(err, "error reading image configuration for %q", img.ID)
-	}
-	historyComment := ""
-	historyCreatedBy := ""
-	if len(config.History) > 0 {
-		historyComment = config.History[len(config.History)-1].Comment
-		historyCreatedBy = config.History[len(config.History)-1].CreatedBy
-	}
-
-	return &Data{
-		ID:           img.ID,
-		Tags:         tags,
-		Digests:      digests,
-		Digest:       manifestDigest,
-		Comment:      historyComment,
-		Created:      config.Created,
-		Author:       config.Author,
-		Config:       config.Config,
-		Architecture: config.Architecture,
-		OS:           config.OS,
-		Annotations:  annotations,
-		CreatedBy:    historyCreatedBy,
-		Size:         uint(size),
-		VirtualSize:  uint(size + imgSize),
-		GraphDriver: driver.Data{
-			Name: driverName,
-			Data: driverMetadata,
-		},
-		RootFS: config.RootFS,
-	}, nil
-}
-
-// FindImage searches for a *storage.Image with a matching the given name or ID in the given store.
-func FindImage(store storage.Store, image string) (*storage.Image, error) {
-	var img *storage.Image
-	ref, err := is.Transport.ParseStoreReference(store, image)
-	if err == nil {
-		img, err = is.Transport.GetStoreImage(store, ref)
-	}
-	if err != nil {
-		img2, err2 := store.Image(image)
-		if err2 != nil {
-			if ref == nil {
-				return nil, errors.Wrapf(err, "error parsing reference to image %q", image)
-			}
-			return nil, errors.Wrapf(err, "unable to locate image %q", image)
-		}
-		img = img2
-	}
-	return img, nil
-}
-
-// FindImageRef searches for and returns a new types.Image matching the given name or ID in the given store.
-func FindImageRef(store storage.Store, image string) (types.Image, error) {
-	img, err := FindImage(store, image)
-	if err != nil {
-		return nil, errors.Wrapf(err, "unable to locate image %q", image)
-	}
-	ref, err := is.Transport.ParseStoreReference(store, "@"+img.ID)
-	if err != nil {
-		return nil, errors.Wrapf(err, "error parsing reference to image %q", img.ID)
-	}
-	imgRef, err := ref.NewImage(nil)
-	if err != nil {
-		return nil, errors.Wrapf(err, "error reading image %q", img.ID)
-	}
-	return imgRef, nil
-}
diff --git a/libpod/inspect_data.go b/libpod/inspect_data.go
new file mode 100644
index 0000000000..072b94ab2b
--- /dev/null
+++ b/libpod/inspect_data.go
@@ -0,0 +1,103 @@
+package libpod
+
+import (
+	"time"
+
+	digest "github.com/opencontainers/go-digest"
+	"github.com/opencontainers/image-spec/specs-go/v1"
+	specs "github.com/opencontainers/runtime-spec/specs-go"
+	"github.com/projectatomic/libpod/libpod/driver"
+)
+
+// ContainerInspectData handles the data used when inspecting a container
+type ContainerInspectData struct {
+	ID              string                 `json:"ID"`
+	Created         time.Time              `json:"Created"`
+	Path            string                 `json:"Path"`
+	Args            []string               `json:"Args"`
+	State           *ContainerInspectState `json:"State"`
+	ImageID         string                 `json:"Image"`
+	ImageName       string                 `json:"ImageName"`
+	ResolvConfPath  string                 `json:"ResolvConfPath"`
+	HostnamePath    string                 `json:"HostnamePath"` //TODO
+	HostsPath       string                 `json:"HostsPath"`    //TODO
+	StaticDir       string                 `json:"StaticDir"`
+	LogPath         string                 `json:"LogPath"`
+	Name            string                 `json:"Name"`
+	RestartCount    int32                  `json:"RestartCount"` //TODO
+	Driver          string                 `json:"Driver"`
+	MountLabel      string                 `json:"MountLabel"`
+	ProcessLabel    string                 `json:"ProcessLabel"`
+	AppArmorProfile string                 `json:"AppArmorProfile"`
+	ExecIDs         []string               `json:"ExecIDs"` //TODO
+	GraphDriver     *driver.Data           `json:"GraphDriver"`
+	SizeRw          int64                  `json:"SizeRw,omitempty"`
+	SizeRootFs      int64                  `json:"SizeRootFs,omitempty"`
+	Mounts          []specs.Mount          `json:"Mounts"`
+	NetworkSettings *NetworkSettings       `json:"NetworkSettings"` //TODO
+}
+
+// ContainerInspectState represents the state of a container.
+type ContainerInspectState struct {
+	OciVersion string    `json:"OciVersion"`
+	Status     string    `json:"Status"`
+	Running    bool      `json:"Running"`
+	Paused     bool      `json:"Paused"`
+	Restarting bool      `json:"Restarting"` // TODO
+	OOMKilled  bool      `json:"OOMKilled"`
+	Dead       bool      `json:"Dead"`
+	Pid        int       `json:"Pid"`
+	ExitCode   int32     `json:"ExitCode"`
+	Error      string    `json:"Error"` // TODO
+	StartedAt  time.Time `json:"StartedAt"`
+	FinishedAt time.Time `json:"FinishedAt"`
+}
+
+// NetworkSettings holds information about the newtwork settings of the container
+type NetworkSettings struct {
+	Bridge                 string              `json:"Bridge"`
+	SandboxID              string              `json:"SandboxID"`
+	HairpinMode            bool                `json:"HairpinMode"`
+	LinkLocalIPv6Address   string              `json:"LinkLocalIPv6Address"`
+	LinkLocalIPv6PrefixLen int                 `json:"LinkLocalIPv6PrefixLen"`
+	Ports                  map[string]struct{} `json:"Ports"`
+	SandboxKey             string              `json:"SandboxKey"`
+	SecondaryIPAddresses   string              `json:"SecondaryIPAddresses"`   //idk type
+	SecondaryIPv6Addresses string              `json:"SecondaryIPv6Addresses"` //idk type
+	EndpointID             string              `json:"EndpointID"`
+	Gateway                string              `json:"Gateway"`
+	GlobalIPv6Addresses    string              `json:"GlobalIPv6Addresses"`
+	GlobalIPv6PrefixLen    int                 `json:"GlobalIPv6PrefixLen"`
+	IPAddress              string              `json:"IPAddress"`
+	IPPrefixLen            int                 `json:"IPPrefixLen"`
+	IPv6Gateway            string              `json:"IPv6Gateway"`
+	MacAddress             string              `json:"MacAddress"`
+}
+
+// ImageData holds the inspect information of an image
+type ImageData struct {
+	ID           string            `json:"ID"`
+	Digest       digest.Digest     `json:"Digest"`
+	RepoTags     []string          `json:"RepoTags"`
+	RepoDigests  []string          `json:"RepoDigests"`
+	Parent       string            `json:"Parent"`
+	Comment      string            `json:"Comment"`
+	Created      *time.Time        `json:"Created"`
+	Config       *v1.ImageConfig   `json:"Config"`
+	Version      string            `json:"Version"`
+	Author       string            `json:"Author"`
+	Architecture string            `json:"Architecture"`
+	Os           string            `json:"Os"`
+	Size         int64             `json:"Size"`
+	VirtualSize  int64             `json:"VirtualSize"`
+	GraphDriver  *driver.Data      `json:"GraphDriver"`
+	RootFS       *RootFS           `json:"RootFS"`
+	Labels       map[string]string `json:"Labels"`
+	Annotations  map[string]string `json:"Annotations"`
+}
+
+// RootFS holds the root fs information of an image
+type RootFS struct {
+	Type   string          `json:"Type"`
+	Layers []digest.Digest `json:"Layers"`
+}
diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go
index 26f85b0370..d5da35c420 100644
--- a/libpod/runtime_img.go
+++ b/libpod/runtime_img.go
@@ -20,15 +20,14 @@ import (
 	"github.com/containers/image/signature"
 	is "github.com/containers/image/storage"
 	"github.com/containers/image/tarball"
-	"github.com/containers/image/transports"
 	"github.com/containers/image/transports/alltransports"
 	"github.com/containers/image/types"
 	"github.com/containers/storage"
 	"github.com/containers/storage/pkg/archive"
-	digest "github.com/opencontainers/go-digest"
 	ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/pkg/errors"
 	"github.com/projectatomic/libpod/libpod/common"
+	"github.com/projectatomic/libpod/libpod/driver"
 )
 
 // Runtime API
@@ -452,7 +451,7 @@ func getRegistries() ([]string, error) {
 // ImageFilter is a function to determine whether an image is included in
 // command output. Images to be outputted are tested using the function. A true
 // return will include the image, a false return will exclude it.
-type ImageFilter func(*storage.Image, *types.ImageInspectInfo) bool
+type ImageFilter func(*storage.Image, *ImageData) bool
 
 func (ips imageDecomposeStruct) returnFQName() string {
 	return fmt.Sprintf("%s%s/%s:%s", ips.transport, ips.registry, ips.imageName, ips.tag)
@@ -1032,7 +1031,7 @@ func (r *Runtime) ImportImage(path string, options CopyOptions) error {
 }
 
 // GetImageInspectInfo returns the inspect information of an image
-func (r *Runtime) GetImageInspectInfo(image storage.Image) (*types.ImageInspectInfo, error) {
+func (r *Runtime) GetImageInspectInfo(image storage.Image) (*ImageData, error) {
 	r.lock.RLock()
 	defer r.lock.RUnlock()
 
@@ -1042,12 +1041,25 @@ func (r *Runtime) GetImageInspectInfo(image storage.Image) (*types.ImageInspectI
 	return r.getImageInspectInfo(image)
 }
 
-func (r *Runtime) getImageInspectInfo(image storage.Image) (*types.ImageInspectInfo, error) {
-	img, err := r.getImageRef(image.ID)
+func (r *Runtime) getImageInspectInfo(image storage.Image) (*ImageData, error) {
+	imgRef, err := r.getImageRef("@" + image.ID)
 	if err != nil {
-		return nil, err
+		return nil, errors.Wrapf(err, "error reading image %q", image.ID)
 	}
-	return img.Inspect()
+
+	layer, err := r.store.Layer(image.TopLayer)
+	if err != nil {
+		return nil, errors.Wrapf(err, "error reading information about layer %q", image.TopLayer)
+	}
+	size, err := r.store.DiffSize(layer.Parent, layer.ID)
+	if err != nil {
+		return nil, errors.Wrapf(err, "error determining size of layer %q", layer.ID)
+	}
+	driverData, err := driver.GetDriverData(r.store, layer.ID)
+	if err != nil {
+		return nil, errors.Wrapf(err, "error getting graph driver info %q", image.ID)
+	}
+	return getImageData(image, imgRef, size, driverData)
 }
 
 // ParseImageFilter takes a set of images and a filter string as input, and returns the libpod.ImageFilterParams struct
@@ -1093,7 +1105,7 @@ func (r *Runtime) ParseImageFilter(imageInput, filter string) (*ImageFilterParam
 				if err != nil {
 					return nil, err
 				}
-				params.BeforeImage = info.Created
+				params.BeforeImage = *info.Created
 			} else {
 				return nil, fmt.Errorf("no such id: %s", pair[0])
 			}
@@ -1103,7 +1115,7 @@ func (r *Runtime) ParseImageFilter(imageInput, filter string) (*ImageFilterParam
 				if err != nil {
 					return nil, err
 				}
-				params.SinceImage = info.Created
+				params.SinceImage = *info.Created
 			} else {
 				return nil, fmt.Errorf("no such id: %s``", pair[0])
 			}
@@ -1116,43 +1128,6 @@ func (r *Runtime) ParseImageFilter(imageInput, filter string) (*ImageFilterParam
 	return &params, nil
 }
 
-// InfoAndDigestAndSize returns the inspection info and size of the image in the given
-// store and the digest of its manifest, if it has one, or "" if it doesn't.
-func (r *Runtime) InfoAndDigestAndSize(img storage.Image) (*types.ImageInspectInfo, digest.Digest, int64, error) {
-	r.lock.RLock()
-	defer r.lock.RUnlock()
-
-	if !r.valid {
-		return nil, "", -1, ErrRuntimeStopped
-	}
-
-	imgRef, err := r.getImageRef("@" + img.ID)
-	if err != nil {
-		return nil, "", -1, errors.Wrapf(err, "error reading image %q", img.ID)
-	}
-	return infoAndDigestAndSize(imgRef)
-}
-
-func infoAndDigestAndSize(imgRef types.Image) (*types.ImageInspectInfo, digest.Digest, int64, error) {
-	imgSize, err := imgRef.Size()
-	if err != nil {
-		return nil, "", -1, errors.Wrapf(err, "error reading size of image %q", transports.ImageName(imgRef.Reference()))
-	}
-	manifest, _, err := imgRef.Manifest()
-	if err != nil {
-		return nil, "", -1, errors.Wrapf(err, "error reading manifest for image %q", transports.ImageName(imgRef.Reference()))
-	}
-	manifestDigest := digest.Digest("")
-	if len(manifest) > 0 {
-		manifestDigest = digest.Canonical.FromBytes(manifest)
-	}
-	info, err := imgRef.Inspect()
-	if err != nil {
-		return nil, "", -1, errors.Wrapf(err, "error inspecting image %q", transports.ImageName(imgRef.Reference()))
-	}
-	return info, manifestDigest, imgSize, nil
-}
-
 // MatchesID returns true if argID is a full or partial match for id
 func MatchesID(id, argID string) bool {
 	return strings.HasPrefix(argID, id)
diff --git a/test/kpod_inspect.bats b/test/kpod_inspect.bats
index ca7e16aad3..86a4e7698f 100644
--- a/test/kpod_inspect.bats
+++ b/test/kpod_inspect.bats
@@ -40,3 +40,13 @@ function setup() {
     echo "$output"
     [ "$status" -eq 0 ]
 }
+
+@test "kpod inspect container with size" {
+    run bash -c "${KPOD_BINARY} ${KPOD_OPTIONS} create ${BB} ls"
+    echo "$output"
+    [ "$status" -eq 0 ]
+    ctr_id="$output"
+    run bash -c "${KPOD_BINARY} $KPOD_OPTIONS inspect --size $ctr_id | python -m json.tool | grep SizeRootFs"
+    echo "$output"
+    [ "$status" -eq 0 ]
+}