github.com/containerd/Containerd@v1.4.13/plugin/context.go (about) 1 /* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package plugin 18 19 import ( 20 "context" 21 "path/filepath" 22 23 "github.com/containerd/containerd/errdefs" 24 "github.com/containerd/containerd/events/exchange" 25 ocispec "github.com/opencontainers/image-spec/specs-go/v1" 26 "github.com/pkg/errors" 27 ) 28 29 // InitContext is used for plugin inititalization 30 type InitContext struct { 31 Context context.Context 32 Root string 33 State string 34 Config interface{} 35 Address string 36 TTRPCAddress string 37 Events *exchange.Exchange 38 39 Meta *Meta // plugins can fill in metadata at init. 40 41 plugins *Set 42 } 43 44 // NewContext returns a new plugin InitContext 45 func NewContext(ctx context.Context, r *Registration, plugins *Set, root, state string) *InitContext { 46 return &InitContext{ 47 Context: ctx, 48 Root: filepath.Join(root, r.URI()), 49 State: filepath.Join(state, r.URI()), 50 Meta: &Meta{ 51 Exports: map[string]string{}, 52 }, 53 plugins: plugins, 54 } 55 } 56 57 // Get returns the first plugin by its type 58 func (i *InitContext) Get(t Type) (interface{}, error) { 59 return i.plugins.Get(t) 60 } 61 62 // Meta contains information gathered from the registration and initialization 63 // process. 64 type Meta struct { 65 Platforms []ocispec.Platform // platforms supported by plugin 66 Exports map[string]string // values exported by plugin 67 Capabilities []string // feature switches for plugin 68 } 69 70 // Plugin represents an initialized plugin, used with an init context. 71 type Plugin struct { 72 Registration *Registration // registration, as initialized 73 Config interface{} // config, as initialized 74 Meta *Meta 75 76 instance interface{} 77 err error // will be set if there was an error initializing the plugin 78 } 79 80 // Err returns the errors during initialization. 81 // returns nil if not error was encountered 82 func (p *Plugin) Err() error { 83 return p.err 84 } 85 86 // Instance returns the instance and any initialization error of the plugin 87 func (p *Plugin) Instance() (interface{}, error) { 88 return p.instance, p.err 89 } 90 91 // Set defines a plugin collection, used with InitContext. 92 // 93 // This maintains ordering and unique indexing over the set. 94 // 95 // After iteratively instantiating plugins, this set should represent, the 96 // ordered, initialization set of plugins for a containerd instance. 97 type Set struct { 98 ordered []*Plugin // order of initialization 99 byTypeAndID map[Type]map[string]*Plugin 100 } 101 102 // NewPluginSet returns an initialized plugin set 103 func NewPluginSet() *Set { 104 return &Set{ 105 byTypeAndID: make(map[Type]map[string]*Plugin), 106 } 107 } 108 109 // Add a plugin to the set 110 func (ps *Set) Add(p *Plugin) error { 111 if byID, typeok := ps.byTypeAndID[p.Registration.Type]; !typeok { 112 ps.byTypeAndID[p.Registration.Type] = map[string]*Plugin{ 113 p.Registration.ID: p, 114 } 115 } else if _, idok := byID[p.Registration.ID]; !idok { 116 byID[p.Registration.ID] = p 117 } else { 118 return errors.Wrapf(errdefs.ErrAlreadyExists, "plugin %v already initialized", p.Registration.URI()) 119 } 120 121 ps.ordered = append(ps.ordered, p) 122 return nil 123 } 124 125 // Get returns the first plugin by its type 126 func (ps *Set) Get(t Type) (interface{}, error) { 127 for _, v := range ps.byTypeAndID[t] { 128 return v.Instance() 129 } 130 return nil, errors.Wrapf(errdefs.ErrNotFound, "no plugins registered for %s", t) 131 } 132 133 // GetAll plugins in the set 134 func (i *InitContext) GetAll() []*Plugin { 135 return i.plugins.ordered 136 } 137 138 // GetByType returns all plugins with the specific type. 139 func (i *InitContext) GetByType(t Type) (map[string]*Plugin, error) { 140 p, ok := i.plugins.byTypeAndID[t] 141 if !ok { 142 return nil, errors.Wrapf(errdefs.ErrNotFound, "no plugins registered for %s", t) 143 } 144 145 return p, nil 146 }