Files
kata-containers/src/runtime/virtcontainers/pkg/compatoci/utils.go
bin 03546f75a6 runtime: change io/ioutil to io/os packages
Change io/ioutil to io/os packages because io/ioutil package
is deprecated from 1.16:

Discard => io.Discard
NopCloser => io.NopCloser
ReadAll => io.ReadAll
ReadDir => os.ReadDir
ReadFile => os.ReadFile
TempDir => os.MkdirTemp
TempFile => os.CreateTemp
WriteFile => os.WriteFile

Details: https://go.dev/doc/go1.16#ioutil

Fixes: #3265

Signed-off-by: bin <bin@hyper.sh>
2021-12-15 07:31:48 +08:00

159 lines
4.2 KiB
Go

// Copyright (c) 2017 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package compatoci
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/sirupsen/logrus"
vcAnnotations "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/annotations"
)
var ociLog = logrus.WithFields(logrus.Fields{
"source": "virtcontainers",
"subsystem": "compatoci",
})
// compatOCIProcess is a structure inheriting from specs.Process defined
// in runtime-spec/specs-go package. The goal is to be compatible with
// both v1.0.0-rc4 and v1.0.0-rc5 since the latter introduced a change
// about the type of the Capabilities field.
// Refer to: https://github.com/opencontainers/runtime-spec/commit/37391fb
type compatOCIProcess struct {
Capabilities interface{} `json:"capabilities,omitempty" platform:"linux"` //nolint:govet
specs.Process
}
// compatOCISpec is a structure inheriting from specs.Spec defined
// in runtime-spec/specs-go package. It relies on the compatOCIProcess
// structure declared above, in order to be compatible with both
// v1.0.0-rc4 and v1.0.0-rc5.
// Refer to: https://github.com/opencontainers/runtime-spec/commit/37391fb
type compatOCISpec struct {
specs.Spec
Process *compatOCIProcess `json:"process,omitempty"` //nolint:govet
}
func containerCapabilities(s compatOCISpec) (specs.LinuxCapabilities, error) {
capabilities := s.Process.Capabilities
var c specs.LinuxCapabilities
// In spec v1.0.0-rc4, capabilities was a list of strings. This was changed
// to an object with v1.0.0-rc5.
// Check for the interface type to support both the versions.
switch caps := capabilities.(type) {
case map[string]interface{}:
for key, value := range caps {
switch val := value.(type) {
case []interface{}:
var list []string
for _, str := range val {
list = append(list, str.(string))
}
switch key {
case "bounding":
c.Bounding = list
case "effective":
c.Effective = list
case "inheritable":
c.Inheritable = list
case "ambient":
c.Ambient = list
case "permitted":
c.Permitted = list
}
default:
return c, fmt.Errorf("Unexpected format for capabilities: %v", caps)
}
}
case []interface{}:
var list []string
for _, str := range caps {
list = append(list, str.(string))
}
c = specs.LinuxCapabilities{
Bounding: list,
Effective: list,
Inheritable: list,
Ambient: list,
Permitted: list,
}
case nil:
ociLog.Debug("Empty capabilities have been passed")
return c, nil
default:
return c, fmt.Errorf("Unexpected format for capabilities: %v", caps)
}
return c, nil
}
// SetLogger sets up a logger for this pkg
func SetLogger(logger *logrus.Entry) {
fields := ociLog.Data
ociLog = logger.WithFields(fields)
}
// ContainerCapabilities return a LinuxCapabilities for virtcontainer
func ContainerCapabilities(s compatOCISpec) (specs.LinuxCapabilities, error) {
if s.Process == nil {
return specs.LinuxCapabilities{}, fmt.Errorf("ContainerCapabilities, Process is nil")
}
return containerCapabilities(s)
}
// getConfigPath returns the full config path from the bundle
// path provided.
func getConfigPath(bundlePath string) string {
return filepath.Join(bundlePath, "config.json")
}
// ParseConfigJSON unmarshals the config.json file.
func ParseConfigJSON(bundlePath string) (specs.Spec, error) {
configPath := getConfigPath(bundlePath)
ociLog.Debugf("converting %s", configPath)
configByte, err := os.ReadFile(configPath)
if err != nil {
return specs.Spec{}, err
}
var compSpec compatOCISpec
if err := json.Unmarshal(configByte, &compSpec); err != nil {
return specs.Spec{}, err
}
caps, err := ContainerCapabilities(compSpec)
if err != nil {
return specs.Spec{}, err
}
compSpec.Spec.Process = &compSpec.Process.Process
compSpec.Spec.Process.Capabilities = &caps
return compSpec.Spec, nil
}
func GetContainerSpec(annotations map[string]string) (specs.Spec, error) {
if bundlePath, ok := annotations[vcAnnotations.BundlePathKey]; ok {
return ParseConfigJSON(bundlePath)
}
ociLog.Errorf("Annotations[%s] not found, cannot find container spec",
vcAnnotations.BundlePathKey)
return specs.Spec{}, fmt.Errorf("Could not find container spec")
}