Skip to content

Commit cda282e

Browse files
authored
Merge pull request cri-o#1517 from wking/upstream-hook-schema
lib: Use libpod's hooks package
2 parents 3961eb3 + 99fe854 commit cda282e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+85125
-381
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ Note that kpod and its container management and debugging commands have moved to
6969

7070
## OCI Hooks Support
7171

72-
[CRI-O configures OCI Hooks to run when launching a container](./hooks.md)
72+
[You can configure CRI-O][libpod-hooks] to inject [OCI Hooks][spec-hooks] when creating containers.
7373

7474
## CRI-O Usage Transfer
7575

@@ -224,3 +224,6 @@ To run a full cluster, see [the instructions](kubernetes.md).
224224
1. Support for exec/attach (done)
225225
1. Target fully automated kubernetes testing without failures [e2e status](https://github.com/kubernetes-incubator/cri-o/issues/533)
226226
1. Track upstream k8s releases
227+
228+
[libpod-hooks]: https://github.com/projectatomic/libpod/blob/v0.6.2/pkg/hooks/README.md
229+
[spec-hooks]: https://github.com/opencontainers/runtime-spec/blob/v1.0.1/config.md#posix-platform-hooks

cmd/crio/main.go

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import (
2020
"github.com/kubernetes-incubator/cri-o/pkg/signals"
2121
"github.com/kubernetes-incubator/cri-o/server"
2222
"github.com/kubernetes-incubator/cri-o/version"
23+
"github.com/projectatomic/libpod/pkg/hooks"
24+
_ "github.com/projectatomic/libpod/pkg/hooks/0.1.0"
2325
"github.com/sirupsen/logrus"
2426
"github.com/soheilhy/cmux"
2527
"github.com/urfave/cli"
@@ -172,7 +174,7 @@ func mergeConfig(config *server.Config, ctx *cli.Context) error {
172174
return nil
173175
}
174176

175-
func catchShutdown(gserver *grpc.Server, sserver *server.Server, hserver *http.Server, signalled *bool) {
177+
func catchShutdown(ctx context.Context, cancel context.CancelFunc, gserver *grpc.Server, sserver *server.Server, hserver *http.Server, signalled *bool) {
176178
sig := make(chan os.Signal, 10)
177179
signal.Notify(sig, signals.Interrupt, signals.Term)
178180
go func() {
@@ -186,11 +188,11 @@ func catchShutdown(gserver *grpc.Server, sserver *server.Server, hserver *http.S
186188
continue
187189
}
188190
*signalled = true
189-
ctx := context.Background()
190191
gserver.GracefulStop()
191192
hserver.Shutdown(ctx)
192193
sserver.StopStreamServer()
193194
sserver.StopMonitors()
195+
cancel()
194196
if err := sserver.Shutdown(ctx); err != nil {
195197
logrus.Warnf("error shutting down main service %v", err)
196198
}
@@ -347,7 +349,7 @@ func main() {
347349
cli.StringFlag{
348350
Name: "hooks-dir-path",
349351
Usage: "set the OCI hooks directory path",
350-
Value: lib.DefaultHooksDirPath,
352+
Value: hooks.DefaultDir,
351353
Hidden: true,
352354
},
353355
cli.StringSliceFlag{
@@ -456,7 +458,8 @@ func main() {
456458
}
457459

458460
app.Action = func(c *cli.Context) error {
459-
ctx := context.Background()
461+
ctx, cancel := context.WithCancel(context.Background())
462+
460463
if c.GlobalBool("profile") {
461464
profilePort := c.GlobalInt("profile-port")
462465
profileEndpoint := fmt.Sprintf("localhost:%v", profilePort)
@@ -534,9 +537,17 @@ func main() {
534537
go func() {
535538
service.StartExitMonitor()
536539
}()
537-
go func() {
538-
service.StartHooksMonitor()
539-
}()
540+
hookSync := make(chan error, 2)
541+
if service.ContainerServer.Hooks == nil {
542+
hookSync <- err // so we don't block during cleanup
543+
} else {
544+
go service.ContainerServer.Hooks.Monitor(ctx, hookSync)
545+
err = <-hookSync
546+
if err != nil {
547+
cancel()
548+
logrus.Fatal(err)
549+
}
550+
}
540551

541552
m := cmux.New(lis)
542553
grpcL := m.Match(cmux.HTTP2HeaderField("content-type", "application/grpc"))
@@ -549,7 +560,7 @@ func main() {
549560
}
550561

551562
graceful := false
552-
catchShutdown(s, service, srv, &graceful)
563+
catchShutdown(ctx, cancel, s, service, srv, &graceful)
553564

554565
go s.Serve(grpcL)
555566
go srv.Serve(httpL)
@@ -575,11 +586,18 @@ func main() {
575586
}
576587

577588
service.Shutdown(ctx)
589+
cancel()
578590

579591
<-streamServerCloseCh
580592
logrus.Debug("closed stream server")
581593
<-serverMonitorsCh
582594
logrus.Debug("closed monitors")
595+
err = <-hookSync
596+
if err == nil || err == context.Canceled {
597+
logrus.Debug("closed hook monitor")
598+
} else {
599+
logrus.Errorf("hook monitor failed: %v", err)
600+
}
583601
<-serverCloseCh
584602
logrus.Debug("closed main server")
585603

docs/crio.8.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,16 @@ it later with **--config**. Global options will modify the output.
148148
**crio.conf** (`/etc/crio/crio.conf`)
149149
`cri-o` configuration file for all of the available command-line options for the crio(8) program, but in a TOML format that can be more easily modified and versioned.
150150

151+
**hook JSON** (`/etc/containers/oci/hooks.d/*.json`, `/usr/share/containers/oci/hooks.d/*.json`)
152+
153+
Each `*.json` file in `/etc/containers/oci/hooks.d` and `/usr/share/containers/oci/hooks.d` configures a hook for CRI-O containers, with `/etc/containers/oci/hooks.d` having higher precedence. `crio(8)` monitors the hook directories for changes, so there is no need to restart the server after adjusting the hook configuration. For more details on the syntax of the JSON files and the semantics of hook injection, see `oci-hooks(5)`.
154+
155+
CRI-O currently supports both the 1.0.0 and 0.1.0 hook schemas, although the 0.1.0 schema is deprecated.
156+
157+
For the annotation conditions, CRI-O uses the Kubernetes annotations, which are a subset of the annotations passed to the OCI runtime. For example, io.kubernetes.cri-o.Volumes is part of the OCI runtime configuration annotations, but it is not part of the Kubernetes annotations being matched for hooks.
158+
159+
For the bind-mount conditions, only mounts explicitly requested by Kubernetes configuration are considered. Bind mounts that CRI-O inserts by default (e.g. `/dev/shm`) are not considered.
160+
151161
**policy.json** (`/etc/containers/policy.json`)
152162
Signature verification policy files are used to specify policy, e.g. trusted keys, applicable when deciding whether to accept an image, or individual signatures of that image, as valid.
153163

@@ -158,7 +168,7 @@ it later with **--config**. Global options will modify the output.
158168
Storage configuration file specifies all of the available container storage options for tools using shared container storage.
159169

160170
# SEE ALSO
161-
crio.conf(5),policy.json(5),registries.conf(5),storage.conf(5)
171+
`crio.conf(5)`, `oci-hooks(5)`, `policy.json(5)`, `registries.conf(5)`, `storage.conf(5)`
162172

163173
# HISTORY
164174
Sept 2016, Originally compiled by Dan Walsh <[email protected]> and Aleksa Sarai <[email protected]>

hooks.md

Lines changed: 0 additions & 71 deletions
This file was deleted.

lib/config.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/containers/image/types"
1010
"github.com/containers/storage"
1111
"github.com/kubernetes-incubator/cri-o/oci"
12+
"github.com/projectatomic/libpod/pkg/hooks"
1213
)
1314

1415
// Defaults if none are specified
@@ -162,9 +163,6 @@ type RuntimeConfig struct {
162163
// Note, for testing purposes mainly
163164
DefaultMountsFile string `toml:"default_mounts_file"`
164165

165-
// Hooks List of hooks to run with container
166-
Hooks map[string]HookParams
167-
168166
// PidsLimit is the number of processes each container is restricted to
169167
// by the cgroup process number controller.
170168
PidsLimit int64 `toml:"pids_limit"`
@@ -333,7 +331,7 @@ func DefaultConfig() *Config {
333331
CgroupManager: cgroupManager,
334332
PidsLimit: DefaultPidsLimit,
335333
ContainerExitsDir: containerExitsDir,
336-
HooksDirPath: DefaultHooksDirPath,
334+
HooksDirPath: hooks.DefaultDir,
337335
LogSizeMax: DefaultLogSizeMax,
338336
DefaultMountsFile: "",
339337
DefaultCapabilities: DefaultCapabilities,

lib/container_server.go

Lines changed: 58 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"os"
88
"path/filepath"
9+
"strings"
910
"sync"
1011
"time"
1112

@@ -21,11 +22,22 @@ import (
2122
rspec "github.com/opencontainers/runtime-spec/specs-go"
2223
"github.com/opencontainers/selinux/go-selinux/label"
2324
"github.com/pkg/errors"
25+
"github.com/projectatomic/libpod/pkg/hooks"
2426
"github.com/sirupsen/logrus"
27+
"golang.org/x/text/language"
2528
pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
2629
"k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport"
2730
)
2831

32+
var (
33+
// localeToLanguage maps from locale values to language tags.
34+
localeToLanguage = map[string]string{
35+
"": "und-u-va-posix",
36+
"c": "und-u-va-posix",
37+
"posix": "und-u-va-posix",
38+
}
39+
)
40+
2941
// ContainerServer implements the ImageServer
3042
type ContainerServer struct {
3143
runtime *oci.Runtime
@@ -37,8 +49,7 @@ type ContainerServer struct {
3749
ctrIDIndex *truncindex.TruncIndex
3850
podNameIndex *registrar.Registrar
3951
podIDIndex *truncindex.TruncIndex
40-
hooks map[string]HookParams
41-
hooksLock sync.Mutex
52+
Hooks *hooks.Manager
4253

4354
imageContext *types.SystemContext
4455
stateLock sync.Locker
@@ -51,40 +62,6 @@ func (c *ContainerServer) Runtime() *oci.Runtime {
5162
return c.runtime
5263
}
5364

54-
// Hooks returns the oci hooks for the ContainerServer
55-
func (c *ContainerServer) Hooks() map[string]HookParams {
56-
hooks := map[string]HookParams{}
57-
c.hooksLock.Lock()
58-
defer c.hooksLock.Unlock()
59-
for key, h := range c.hooks {
60-
hooks[key] = h
61-
}
62-
return hooks
63-
}
64-
65-
// RemoveHook removes an hook by name
66-
func (c *ContainerServer) RemoveHook(hook string) (ok bool) {
67-
c.hooksLock.Lock()
68-
defer c.hooksLock.Unlock()
69-
_, ok = c.hooks[hook]
70-
if ok {
71-
delete(c.hooks, hook)
72-
}
73-
return ok
74-
}
75-
76-
// AddHook adds an hook by hook's path
77-
func (c *ContainerServer) AddHook(hookPath string) (err error) {
78-
c.hooksLock.Lock()
79-
defer c.hooksLock.Unlock()
80-
hook, err := readHook(hookPath)
81-
if err != nil {
82-
return err
83-
}
84-
c.hooks[filepath.Base(hookPath)] = hook
85-
return nil
86-
}
87-
8865
// Store returns the Store for the ContainerServer
8966
func (c *ContainerServer) Store() cstorage.Store {
9067
return c.store
@@ -168,21 +145,56 @@ func New(ctx context.Context, config *Config) (*ContainerServer, error) {
168145
lock = new(sync.Mutex)
169146
}
170147

171-
hooks := make(map[string]HookParams)
148+
hookDirectories := []string{}
149+
missingHookDirectoryFatal := false
150+
172151
// If hooks directory is set in config use it
173152
if config.HooksDirPath != "" {
174-
if err := readHooks(config.HooksDirPath, hooks); err != nil {
175-
return nil, err
176-
}
153+
hookDirectories = append(hookDirectories, config.HooksDirPath)
154+
177155
// If user overrode default hooks, this means it is in a test, so don't
178156
// use OverrideHooksDirPath
179-
if config.HooksDirPath == DefaultHooksDirPath {
180-
if err := readHooks(OverrideHooksDirPath, hooks); err != nil {
181-
return nil, err
182-
}
157+
if config.HooksDirPath == hooks.DefaultDir {
158+
hookDirectories = append(hookDirectories, hooks.OverrideDir)
159+
} else {
160+
missingHookDirectoryFatal = true
161+
}
162+
}
163+
164+
var locale string
165+
var ok bool
166+
for _, envVar := range []string{
167+
"LC_ALL",
168+
"LC_COLLATE",
169+
"LANG",
170+
} {
171+
locale, ok = os.LookupEnv(envVar)
172+
if ok {
173+
break
174+
}
175+
}
176+
177+
langString, ok := localeToLanguage[strings.ToLower(locale)]
178+
if !ok {
179+
langString = locale
180+
}
181+
182+
lang, err := language.Parse(langString)
183+
if err != nil {
184+
logrus.Warnf("failed to parse language %q: %s", langString, err)
185+
lang, err = language.Parse("und-u-va-posix")
186+
if err != nil {
187+
return nil, err
188+
}
189+
}
190+
191+
hooks, err := hooks.New(ctx, hookDirectories, []string{}, lang)
192+
if err != nil {
193+
if missingHookDirectoryFatal || !os.IsNotExist(err) {
194+
return nil, err
183195
}
196+
logrus.Warnf("failed to load hooks: {}", err)
184197
}
185-
logrus.Debugf("hooks %+v", hooks)
186198

187199
return &ContainerServer{
188200
runtime: runtime,
@@ -194,7 +206,7 @@ func New(ctx context.Context, config *Config) (*ContainerServer, error) {
194206
podNameIndex: registrar.NewRegistrar(),
195207
podIDIndex: truncindex.NewTruncIndex([]string{}),
196208
imageContext: &types.SystemContext{SignaturePolicyPath: config.SignaturePolicyPath},
197-
hooks: hooks,
209+
Hooks: hooks,
198210
stateLock: lock,
199211
state: &containerServerState{
200212
containers: oci.NewMemoryStore(),

0 commit comments

Comments
 (0)