summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libpod/container.go31
-rw-r--r--libpod/sql_state.go73
-rw-r--r--libpod/sql_state_internal.go101
-rw-r--r--libpod/sql_state_test.go20
4 files changed, 190 insertions, 35 deletions
diff --git a/libpod/container.go b/libpod/container.go
index 2c769b00b..7b0852c07 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -156,23 +156,28 @@ type ContainerConfig struct {
Mounts []string `json:"mounts,omitempty"`
// Security Config
+ // Whether the container is privileged
+ Privileged bool `json:"privileged"`
+ // Whether to set the No New Privileges flag
+ NoNewPrivs bool `json:"noNewPrivs"`
// SELinux process label for container
ProcessLabel string `json:"ProcessLabel,omitempty"`
// SELinux mount label for root filesystem
MountLabel string `json:"MountLabel,omitempty"`
// User and group to use in the container
// Can be specified by name or UID/GID
- User string `json:"user"`
+ User string `json:"user,omitempty"`
// Namespace Config
// IDs of container to share namespaces with
// NetNsCtr conflicts with the CreateNetNS bool
- IPCNsCtr string `json:"ipcNsCtr"`
- MountNsCtr string `json:"mountNsCtr"`
- NetNsCtr string `json:"netNsCtr"`
- PIDNsCtr string `json:"pidNsCtr"`
- UserNsCtr string `json:"userNsCtr"`
- UTSNsCtr string `json:"utsNsCtr"`
+ IPCNsCtr string `json:"ipcNsCtr,omitempty"`
+ MountNsCtr string `json:"mountNsCtr,omitempty"`
+ NetNsCtr string `json:"netNsCtr,omitempty"`
+ PIDNsCtr string `json:"pidNsCtr,omitempty"`
+ UserNsCtr string `json:"userNsCtr,omitempty"`
+ UTSNsCtr string `json:"utsNsCtr,omitempty"`
+ CgroupNsCtr string `json:"cgroupNsCtr,omitempty"`
// Network Config
// CreateNetNS indicates that libpod should create and configure a new
@@ -183,6 +188,18 @@ type ContainerConfig struct {
// namespace
// These are not used unless CreateNetNS is true
PortMappings []ocicni.PortMapping `json:"portMappings,omitempty"`
+ // DNS servers to use in container resolv.conf
+ // Will override servers in host resolv if set
+ DNSServer []net.IP `json:"dnsServer,omitempty"`
+ // DNS Search domains to use in container resolv.conf
+ // Will override search domains in host resolv if set
+ DNSSearch []string `json:"dnsSearch,omitempty"`
+ // DNS options to be set in container resolv.conf
+ // With override options in host resolv if set
+ DNSOption []string `json:"dnsOption,omitempty"`
+ // Hosts to add in container
+ // Will be appended to host's host file
+ HostAdd []string `json:"hostsAdd,omitempty"`
// Misc Options
// Whether to keep container STDIN open
diff --git a/libpod/sql_state.go b/libpod/sql_state.go
index fe3232e62..51ec25510 100644
--- a/libpod/sql_state.go
+++ b/libpod/sql_state.go
@@ -15,7 +15,7 @@ import (
// DBSchema is the current DB schema version
// Increments every time a change is made to the database's tables
-const DBSchema = 7
+const DBSchema = 8
// SQLState is a state implementation backed by a persistent SQLite3 database
type SQLState struct {
@@ -284,7 +284,8 @@ func (s *SQLState) AddContainer(ctr *Container) (err error) {
?, ?, ?, ?, ?,
?, ?, ?, ?, ?,
?, ?, ?, ?, ?,
- ?, ?, ?
+ ?, ?, ?, ?, ?,
+ ?, ?, ?, ?
);`
addCtrState = `INSERT INTO containerState VALUES (
?, ?, ?, ?, ?,
@@ -306,9 +307,24 @@ func (s *SQLState) AddContainer(ctr *Container) (err error) {
return errors.Wrapf(err, "error marshaling container %s mounts to JSON", ctr.ID())
}
- portsJSON, err := json.Marshal(ctr.config.PortMappings)
+ dnsServerJSON, err := json.Marshal(ctr.config.DNSServer)
+ if err != nil {
+ return errors.Wrapf(err, "error marshaling container %s DNS servers to JSON", ctr.ID())
+ }
+
+ dnsSearchJSON, err := json.Marshal(ctr.config.DNSSearch)
+ if err != nil {
+ return errors.Wrapf(err, "error marshaling container %s DNS search domains to JSON", ctr.ID())
+ }
+
+ dnsOptionJSON, err := json.Marshal(ctr.config.DNSOption)
if err != nil {
- return errors.Wrapf(err, "error marshaling container %s port mappings to JSON", ctr.ID())
+ return errors.Wrapf(err, "error marshaling container %s DNS options to JSON", ctr.ID())
+ }
+
+ hostAddJSON, err := json.Marshal(ctr.config.HostAdd)
+ if err != nil {
+ return errors.Wrapf(err, "error marshaling container %s hosts to JSON", ctr.ID())
}
labelsJSON, err := json.Marshal(ctr.config.Labels)
@@ -321,6 +337,19 @@ func (s *SQLState) AddContainer(ctr *Container) (err error) {
netNSPath = ctr.state.NetNS.Path()
}
+ specJSON, err := json.Marshal(ctr.config.Spec)
+ if err != nil {
+ return errors.Wrapf(err, "error marshalling container %s spec to JSON", ctr.ID())
+ }
+
+ portsJSON := []byte{}
+ if len(ctr.config.PortMappings) > 0 {
+ portsJSON, err = json.Marshal(&ctr.config.PortMappings)
+ if err != nil {
+ return errors.Wrapf(err, "error marshalling container %s port mappings to JSON", ctr.ID())
+ }
+ }
+
tx, err := s.db.Begin()
if err != nil {
return errors.Wrapf(err, "error beginning database transaction")
@@ -348,6 +377,8 @@ func (s *SQLState) AddContainer(ctr *Container) (err error) {
ctr.config.StaticDir,
string(mounts),
+ boolToSQL(ctr.config.Privileged),
+ boolToSQL(ctr.config.NoNewPrivs),
ctr.config.ProcessLabel,
ctr.config.MountLabel,
ctr.config.User,
@@ -358,9 +389,13 @@ func (s *SQLState) AddContainer(ctr *Container) (err error) {
stringToNullString(ctr.config.PIDNsCtr),
stringToNullString(ctr.config.UserNsCtr),
stringToNullString(ctr.config.UTSNsCtr),
+ stringToNullString(ctr.config.CgroupNsCtr),
boolToSQL(ctr.config.CreateNetNS),
- string(portsJSON),
+ string(dnsServerJSON),
+ string(dnsSearchJSON),
+ string(dnsOptionJSON),
+ string(hostAddJSON),
boolToSQL(ctr.config.Stdin),
string(labelsJSON),
@@ -392,10 +427,6 @@ func (s *SQLState) AddContainer(ctr *Container) (err error) {
}
// Save the container's runtime spec to disk
- specJSON, err := json.Marshal(ctr.config.Spec)
- if err != nil {
- return errors.Wrapf(err, "error marshalling container %s spec to JSON", ctr.ID())
- }
specPath := getSpecPath(s.specsDir, ctr.ID())
if err := ioutil.WriteFile(specPath, specJSON, 0750); err != nil {
return errors.Wrapf(err, "error saving container %s spec JSON to disk", ctr.ID())
@@ -408,6 +439,21 @@ func (s *SQLState) AddContainer(ctr *Container) (err error) {
}
}()
+ // If the container has port mappings, save them to disk
+ if len(ctr.config.PortMappings) > 0 {
+ portPath := getPortsPath(s.specsDir, ctr.ID())
+ if err := ioutil.WriteFile(portPath, portsJSON, 0750); err != nil {
+ return errors.Wrapf(err, "error saving container %s port JSON to disk", ctr.ID())
+ }
+ defer func() {
+ if err != nil {
+ if err2 := os.Remove(portPath); err2 != nil {
+ logrus.Errorf("Error removing container %s JSON ports from state: %v", ctr.ID(), err2)
+ }
+ }
+ }()
+ }
+
if err := tx.Commit(); err != nil {
return errors.Wrapf(err, "error committing transaction to add container %s", ctr.ID())
}
@@ -668,6 +714,15 @@ func (s *SQLState) RemoveContainer(ctr *Container) error {
return errors.Wrapf(err, "error removing JSON spec from state for container %s", ctr.ID())
}
+ // Remove containers ports JSON from disk
+ // May not exist, so ignore os.IsNotExist
+ portsPath := getPortsPath(s.specsDir, ctr.ID())
+ if err := os.Remove(portsPath); err != nil {
+ if !os.IsNotExist(err) {
+ return errors.Wrapf(err, "error removing JSON ports from state for container %s", ctr.ID())
+ }
+ }
+
ctr.valid = false
return nil
diff --git a/libpod/sql_state_internal.go b/libpod/sql_state_internal.go
index ef3b6bd4e..189fae190 100644
--- a/libpod/sql_state_internal.go
+++ b/libpod/sql_state_internal.go
@@ -4,6 +4,7 @@ import (
"database/sql"
"encoding/json"
"io/ioutil"
+ "os"
"path/filepath"
"time"
@@ -178,6 +179,8 @@ func prepareDB(db *sql.DB) (err error) {
StaticDir TEXT NOT NULL,
Mounts TEXT NOT NULL,
+ Privileged INTEGER NOT NULL,
+ NoNewPrivs INTEGER NOT NULL,
ProcessLabel TEXT NOT NULL,
MountLabel TEXT NOT NULL,
User TEXT NOT NULL,
@@ -188,9 +191,13 @@ func prepareDB(db *sql.DB) (err error) {
PIDNsCtr TEXT,
UserNsCtr TEXT,
UTSNsCtr TEXT,
+ CgroupNsCtr TEXT,
CreateNetNS INTEGER NOT NULL,
- PortMappings TEXT NOT NULL,
+ DNSServer TEXT NOT NULL,
+ DNSSearch TEXT NOT NULL,
+ DNSOption TEXT NOT NULL,
+ HostAdd TEXT NOT NULL,
Stdin INTEGER NOT NULL,
LabelsJSON TEXT NOT NULL,
@@ -202,16 +209,20 @@ func prepareDB(db *sql.DB) (err error) {
CHECK (ImageVolumes IN (0, 1)),
CHECK (ReadOnly IN (0, 1)),
CHECK (SHMSize>=0),
+ CHECK (Privileged IN (0, 1)),
+ CHECK (NoNewPrivs IN (0, 1)),
CHECK (CreateNetNS IN (0, 1)),
CHECK (Stdin IN (0, 1)),
CHECK (StopSignal>=0),
- FOREIGN KEY (Pod) REFERENCES pod(Id) DEFERRABLE INITIALLY DEFERRED,
- FOREIGN KEY (IPCNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED,
- FOREIGN KEY (MountNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED,
- FOREIGN KEY (NetNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED,
- FOREIGN KEY (PIDNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED,
- FOREIGN KEY (UserNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED,
- FOREIGN KEY (UTSNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED
+ FOREIGN KEY (Id) REFERENCES containerState(Id) DEFERRABLE INITIALLY DEFERRED
+ FOREIGN KEY (Pod) REFERENCES pod(Id) DEFERRABLE INITIALLY DEFERRED,
+ FOREIGN KEY (IPCNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED,
+ FOREIGN KEY (MountNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED,
+ FOREIGN KEY (NetNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED,
+ FOREIGN KEY (PIDNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED,
+ FOREIGN KEY (UserNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED,
+ FOREIGN KEY (UTSNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED,
+ FOREIGN KEY (CgroupNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED
);
`
@@ -283,6 +294,11 @@ func getSpecPath(specsDir, id string) string {
return filepath.Join(specsDir, id)
}
+// Get filename for container port mappings on disk
+func getPortsPath(specsDir, id string) string {
+ return filepath.Join(specsDir, id+"_ports")
+}
+
// Convert a bool into SQL-readable format
func boolToSQL(b bool) int {
if b {
@@ -347,19 +363,25 @@ func (s *SQLState) ctrFromScannable(row scannable) (*Container, error) {
staticDir string
mounts string
+ privileged int
+ noNewPrivs int
processLabel string
mountLabel string
user string
- ipcNsCtrNullStr sql.NullString
- mountNsCtrNullStr sql.NullString
- netNsCtrNullStr sql.NullString
- pidNsCtrNullStr sql.NullString
- userNsCtrNullStr sql.NullString
- utsNsCtrNullStr sql.NullString
+ ipcNsCtrNullStr sql.NullString
+ mountNsCtrNullStr sql.NullString
+ netNsCtrNullStr sql.NullString
+ pidNsCtrNullStr sql.NullString
+ userNsCtrNullStr sql.NullString
+ utsNsCtrNullStr sql.NullString
+ cgroupNsCtrNullStr sql.NullString
- createNetNS int
- portMappingsJSON string
+ createNetNS int
+ dnsServerJSON string
+ dnsSearchJSON string
+ dnsOptionJSON string
+ hostAddJSON string
stdin int
labelsJSON string
@@ -396,6 +418,8 @@ func (s *SQLState) ctrFromScannable(row scannable) (*Container, error) {
&staticDir,
&mounts,
+ &privileged,
+ &noNewPrivs,
&processLabel,
&mountLabel,
&user,
@@ -406,9 +430,13 @@ func (s *SQLState) ctrFromScannable(row scannable) (*Container, error) {
&pidNsCtrNullStr,
&userNsCtrNullStr,
&utsNsCtrNullStr,
+ &cgroupNsCtrNullStr,
&createNetNS,
- &portMappingsJSON,
+ &dnsServerJSON,
+ &dnsSearchJSON,
+ &dnsOptionJSON,
+ &hostAddJSON,
&stdin,
&labelsJSON,
@@ -453,6 +481,8 @@ func (s *SQLState) ctrFromScannable(row scannable) (*Container, error) {
ctr.config.ShmSize = shmSize
ctr.config.StaticDir = staticDir
+ ctr.config.Privileged = boolFromSQL(privileged)
+ ctr.config.NoNewPrivs = boolFromSQL(noNewPrivs)
ctr.config.ProcessLabel = processLabel
ctr.config.MountLabel = mountLabel
ctr.config.User = user
@@ -463,6 +493,7 @@ func (s *SQLState) ctrFromScannable(row scannable) (*Container, error) {
ctr.config.PIDNsCtr = stringFromNullString(pidNsCtrNullStr)
ctr.config.UserNsCtr = stringFromNullString(userNsCtrNullStr)
ctr.config.UTSNsCtr = stringFromNullString(utsNsCtrNullStr)
+ ctr.config.CgroupNsCtr = stringFromNullString(cgroupNsCtrNullStr)
ctr.config.CreateNetNS = boolFromSQL(createNetNS)
@@ -490,8 +521,20 @@ func (s *SQLState) ctrFromScannable(row scannable) (*Container, error) {
return nil, errors.Wrapf(err, "error parsing container %s mounts JSON", id)
}
- if err := json.Unmarshal([]byte(portMappingsJSON), &ctr.config.PortMappings); err != nil {
- return nil, errors.Wrapf(err, "error parsing container %s port mappings JSON", id)
+ if err := json.Unmarshal([]byte(dnsServerJSON), &ctr.config.DNSServer); err != nil {
+ return nil, errors.Wrapf(err, "error parsing container %s DNS server JSON", id)
+ }
+
+ if err := json.Unmarshal([]byte(dnsSearchJSON), &ctr.config.DNSSearch); err != nil {
+ return nil, errors.Wrapf(err, "error parsing container %s DNS search JSON", id)
+ }
+
+ if err := json.Unmarshal([]byte(dnsOptionJSON), &ctr.config.DNSOption); err != nil {
+ return nil, errors.Wrapf(err, "error parsing container %s DNS option JSON", id)
+ }
+
+ if err := json.Unmarshal([]byte(hostAddJSON), &ctr.config.HostAdd); err != nil {
+ return nil, errors.Wrapf(err, "error parsing container %s DNS server JSON", id)
}
labels := make(map[string]string)
@@ -550,5 +593,25 @@ func (s *SQLState) ctrFromScannable(row scannable) (*Container, error) {
}
ctr.config.Spec = ociSpec
+ // Retrieve the ports from disk
+ // They may not exist - if they don't, this container just doesn't have ports
+ portPath := getPortsPath(s.specsDir, id)
+ _, err = os.Stat(portPath)
+ if err != nil {
+ if !os.IsNotExist(err) {
+ return nil, errors.Wrapf(err, "error stating container %s JSON ports", id)
+ }
+ }
+ if err == nil {
+ // The file exists, read it
+ fileContents, err := ioutil.ReadFile(portPath)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error reading container %s JSON ports", id)
+ }
+ if err := json.Unmarshal(fileContents, &ctr.config.PortMappings); err != nil {
+ return nil, errors.Wrapf(err, "error parsing container %s JSON ports", id)
+ }
+ }
+
return ctr, nil
}
diff --git a/libpod/sql_state_test.go b/libpod/sql_state_test.go
index 020e2ce40..19d5da63e 100644
--- a/libpod/sql_state_test.go
+++ b/libpod/sql_state_test.go
@@ -3,6 +3,7 @@ package libpod
import (
"encoding/json"
"io/ioutil"
+ "net"
"os"
"path/filepath"
"reflect"
@@ -10,6 +11,7 @@ import (
"time"
"github.com/containers/storage"
+ "github.com/cri-o/ocicni/pkg/ocicni"
"github.com/opencontainers/runtime-tools/generate"
"github.com/stretchr/testify/assert"
)
@@ -29,6 +31,24 @@ func getTestContainer(id, name, locksDir string) (*Container, error) {
StopSignal: 0,
StopTimeout: 0,
CreatedTime: time.Now(),
+ Privileged: true,
+ Mounts: []string{"/does/not/exist"},
+ DNSServer: []net.IP{net.ParseIP("192.168.1.1"), net.ParseIP("192.168.2.2")},
+ DNSSearch: []string{"example.com", "example.example.com"},
+ PortMappings: []ocicni.PortMapping{
+ {
+ HostPort: 80,
+ ContainerPort: 90,
+ Protocol: "tcp",
+ HostIP: "192.168.3.3",
+ },
+ {
+ HostPort: 100,
+ ContainerPort: 110,
+ Protocol: "udp",
+ HostIP: "192.168.4.4",
+ },
+ },
},
state: &containerRuntimeInfo{
State: ContainerStateRunning,