api: types: keep info.SecurityOptions a string slice
Signed-off-by: Antonio Murdaca <runcom@redhat.com>
(cherry picked from commit 514ca09426
)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
This commit is contained in:
parent
2737519f9a
commit
0a5732d1cf
8 changed files with 84 additions and 57 deletions
|
@ -16,7 +16,6 @@ import (
|
|||
"github.com/docker/docker/api/types/registry"
|
||||
timetypes "github.com/docker/docker/api/types/time"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/docker/docker/api/types/versions/v1p24"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
@ -42,16 +41,24 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht
|
|||
|
||||
if versions.LessThan(httputils.VersionFromContext(ctx), "1.25") {
|
||||
// TODO: handle this conversion in engine-api
|
||||
oldInfo := &v1p24.Info{
|
||||
InfoBase: info.InfoBase,
|
||||
type oldInfo struct {
|
||||
*types.Info
|
||||
ExecutionDriver string
|
||||
}
|
||||
old := &oldInfo{
|
||||
Info: info,
|
||||
ExecutionDriver: "<not supported>",
|
||||
}
|
||||
for _, s := range info.SecurityOptions {
|
||||
if s.Key == "Name" {
|
||||
oldInfo.SecurityOptions = append(oldInfo.SecurityOptions, s.Value)
|
||||
}
|
||||
nameOnlySecurityOptions := []string{}
|
||||
kvSecOpts, err := types.DecodeSecurityOptions(old.SecurityOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return httputils.WriteJSON(w, http.StatusOK, oldInfo)
|
||||
for _, s := range kvSecOpts {
|
||||
nameOnlySecurityOptions = append(nameOnlySecurityOptions, s.Name)
|
||||
}
|
||||
old.SecurityOptions = nameOnlySecurityOptions
|
||||
return httputils.WriteJSON(w, http.StatusOK, old)
|
||||
}
|
||||
return httputils.WriteJSON(w, http.StatusOK, info)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
|
@ -158,9 +161,9 @@ type Commit struct {
|
|||
Expected string
|
||||
}
|
||||
|
||||
// InfoBase contains the base response of Remote API:
|
||||
// Info contains response of Remote API:
|
||||
// GET "/info"
|
||||
type InfoBase struct {
|
||||
type Info struct {
|
||||
ID string
|
||||
Containers int
|
||||
ContainersRunning int
|
||||
|
@ -219,18 +222,49 @@ type InfoBase struct {
|
|||
ContainerdCommit Commit
|
||||
RuncCommit Commit
|
||||
InitCommit Commit
|
||||
SecurityOptions []string
|
||||
}
|
||||
|
||||
// SecurityOpt holds key/value pair about a security option
|
||||
type SecurityOpt struct {
|
||||
// KeyValue holds a key/value pair
|
||||
type KeyValue struct {
|
||||
Key, Value string
|
||||
}
|
||||
|
||||
// Info contains response of Remote API:
|
||||
// GET "/info"
|
||||
type Info struct {
|
||||
*InfoBase
|
||||
SecurityOptions []SecurityOpt
|
||||
// SecurityOpt contains the name and options of a security option
|
||||
type SecurityOpt struct {
|
||||
Name string
|
||||
Options []KeyValue
|
||||
}
|
||||
|
||||
// DecodeSecurityOptions decodes a security options string slice to a type safe
|
||||
// SecurityOpt
|
||||
func DecodeSecurityOptions(opts []string) ([]SecurityOpt, error) {
|
||||
so := []SecurityOpt{}
|
||||
for _, opt := range opts {
|
||||
// support output from a < 1.13 docker daemon
|
||||
if !strings.Contains(opt, "=") {
|
||||
so = append(so, SecurityOpt{Name: opt})
|
||||
continue
|
||||
}
|
||||
secopt := SecurityOpt{}
|
||||
split := strings.Split(opt, ",")
|
||||
for _, s := range split {
|
||||
kv := strings.SplitN(s, "=", 2)
|
||||
if len(kv) != 2 {
|
||||
return nil, fmt.Errorf("invalid security option %q", s)
|
||||
}
|
||||
if kv[0] == "" || kv[1] == "" {
|
||||
return nil, errors.New("invalid empty security option")
|
||||
}
|
||||
if kv[0] == "name" {
|
||||
secopt.Name = kv[1]
|
||||
continue
|
||||
}
|
||||
secopt.Options = append(secopt.Options, KeyValue{Key: kv[0], Value: kv[1]})
|
||||
}
|
||||
so = append(so, secopt)
|
||||
}
|
||||
return so, nil
|
||||
}
|
||||
|
||||
// PluginsInfo is a temp struct holding Plugins name
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
// Package v1p24 provides specific API types for the API version 1, patch 24.
|
||||
package v1p24
|
||||
|
||||
import "github.com/docker/docker/api/types"
|
||||
|
||||
// Info is a backcompatibility struct for the API 1.24
|
||||
type Info struct {
|
||||
*types.InfoBase
|
||||
ExecutionDriver string
|
||||
SecurityOptions []string
|
||||
}
|
|
@ -172,16 +172,21 @@ func prettyPrintInfo(dockerCli *command.DockerCli, info types.Info) error {
|
|||
fmt.Fprintf(dockerCli.Out(), "\n")
|
||||
}
|
||||
if len(info.SecurityOptions) != 0 {
|
||||
kvs, err := types.DecodeSecurityOptions(info.SecurityOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(dockerCli.Out(), "Security Options:\n")
|
||||
for _, o := range info.SecurityOptions {
|
||||
switch o.Key {
|
||||
case "Name":
|
||||
fmt.Fprintf(dockerCli.Out(), " %s\n", o.Value)
|
||||
case "Profile":
|
||||
if o.Value != "default" {
|
||||
fmt.Fprintf(dockerCli.Err(), " WARNING: You're not using the default seccomp profile\n")
|
||||
for _, so := range kvs {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s\n", so.Name)
|
||||
for _, o := range so.Options {
|
||||
switch o.Key {
|
||||
case "profile":
|
||||
if o.Value != "default" {
|
||||
fmt.Fprintf(dockerCli.Err(), " WARNING: You're not using the default seccomp profile\n")
|
||||
}
|
||||
fmt.Fprintf(dockerCli.Out(), " Profile: %s\n", o.Value)
|
||||
}
|
||||
fmt.Fprintf(dockerCli.Out(), " %s: %s\n", o.Key, o.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,10 +46,8 @@ func TestInfo(t *testing.T) {
|
|||
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
|
||||
}
|
||||
info := &types.Info{
|
||||
InfoBase: &types.InfoBase{
|
||||
ID: "daemonID",
|
||||
Containers: 3,
|
||||
},
|
||||
ID: "daemonID",
|
||||
Containers: 3,
|
||||
}
|
||||
b, err := json.Marshal(info)
|
||||
if err != nil {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"sync/atomic"
|
||||
|
@ -69,29 +70,26 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
|
|||
}
|
||||
})
|
||||
|
||||
securityOptions := []types.SecurityOpt{}
|
||||
securityOptions := []string{}
|
||||
if sysInfo.AppArmor {
|
||||
securityOptions = append(securityOptions, types.SecurityOpt{Key: "Name", Value: "apparmor"})
|
||||
securityOptions = append(securityOptions, "name=apparmor")
|
||||
}
|
||||
if sysInfo.Seccomp && supportsSeccomp {
|
||||
profile := daemon.seccompProfilePath
|
||||
if profile == "" {
|
||||
profile = "default"
|
||||
}
|
||||
securityOptions = append(securityOptions,
|
||||
types.SecurityOpt{Key: "Name", Value: "seccomp"},
|
||||
types.SecurityOpt{Key: "Profile", Value: profile},
|
||||
)
|
||||
securityOptions = append(securityOptions, fmt.Sprintf("name=seccomp,profile=%s", profile))
|
||||
}
|
||||
if selinuxEnabled() {
|
||||
securityOptions = append(securityOptions, types.SecurityOpt{Key: "Name", Value: "selinux"})
|
||||
securityOptions = append(securityOptions, "name=selinux")
|
||||
}
|
||||
uid, gid := daemon.GetRemappedUIDGID()
|
||||
if uid != 0 || gid != 0 {
|
||||
securityOptions = append(securityOptions, types.SecurityOpt{Key: "Name", Value: "userns"})
|
||||
securityOptions = append(securityOptions, "name=userns")
|
||||
}
|
||||
|
||||
v := &types.InfoBase{
|
||||
v := &types.Info{
|
||||
ID: daemon.ID,
|
||||
Containers: int(cRunning + cPaused + cStopped),
|
||||
ContainersRunning: int(cRunning),
|
||||
|
@ -129,6 +127,7 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
|
|||
HTTPSProxy: sockets.GetProxyEnv("https_proxy"),
|
||||
NoProxy: sockets.GetProxyEnv("no_proxy"),
|
||||
LiveRestoreEnabled: daemon.configStore.LiveRestoreEnabled,
|
||||
SecurityOptions: securityOptions,
|
||||
Isolation: daemon.defaultIsolation,
|
||||
}
|
||||
|
||||
|
@ -143,12 +142,7 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
|
|||
}
|
||||
v.Name = hostname
|
||||
|
||||
i := &types.Info{
|
||||
InfoBase: v,
|
||||
SecurityOptions: securityOptions,
|
||||
}
|
||||
|
||||
return i, nil
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// SystemVersion returns version information about the daemon.
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
)
|
||||
|
||||
// FillPlatformInfo fills the platform related info.
|
||||
func (daemon *Daemon) FillPlatformInfo(v *types.InfoBase, sysInfo *sysinfo.SysInfo) {
|
||||
func (daemon *Daemon) FillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo) {
|
||||
v.MemoryLimit = sysInfo.MemoryLimit
|
||||
v.SwapLimit = sysInfo.SwapLimit
|
||||
v.KernelMemory = sysInfo.KernelMemory
|
||||
|
|
|
@ -6,5 +6,5 @@ import (
|
|||
)
|
||||
|
||||
// FillPlatformInfo fills the platform related info.
|
||||
func (daemon *Daemon) FillPlatformInfo(v *types.InfoBase, sysInfo *sysinfo.SysInfo) {
|
||||
func (daemon *Daemon) FillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo) {
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue