Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature: add plugin point of endpoint creating which enables users to
Browse files Browse the repository at this point in the history
setup priority of endpoint and decide whether enable libnetwork resolver
 to this endpoint and setup generic params of this endpoint.

Signed-off-by: Frank Yang <yyb196@gmail.com>
yyb196 committed Apr 13, 2018
1 parent 7a3a988 commit 5e967d3
Showing 5 changed files with 50 additions and 18 deletions.
3 changes: 3 additions & 0 deletions apis/plugins/ContainerPlugin.go
Original file line number Diff line number Diff line change
@@ -11,4 +11,7 @@ type ContainerPlugin interface {
// PreStart returns an array of priority and args which will pass to runc, the every priority
// used to sort the pre start array that pass to runc, network plugin hook always has priority value 0.
PreStart(interface{}) ([]int, [][]string, error)

//NetworkGenericParams accepts the env of this container and returns the priority of this endpoint and if this endpoint should enable resolver and a map which will be used as generic params to create endpoints of this container
PreCreateEndpoint([]string) (priority int, disableResolver bool, genericParam map[string]interface{})
}
8 changes: 7 additions & 1 deletion daemon/mgr/container.go
Original file line number Diff line number Diff line change
@@ -1524,7 +1524,7 @@ func (mgr *ContainerManager) detachVolumes(ctx context.Context, c *ContainerMeta
}

func (mgr *ContainerManager) buildContainerEndpoint(c *ContainerMeta) *networktypes.Endpoint {
return &networktypes.Endpoint{
ep := &networktypes.Endpoint{
Owner: c.ID,
Hostname: c.Config.Hostname,
Domainname: c.Config.Domainname,
@@ -1543,6 +1543,12 @@ func (mgr *ContainerManager) buildContainerEndpoint(c *ContainerMeta) *networkty
PortBindings: c.HostConfig.PortBindings,
NetworkConfig: c.NetworkSettings,
}

if mgr.containerPlugin != nil {
ep.Priority, ep.DisableResolver, ep.GenericParams = mgr.containerPlugin.PreCreateEndpoint(c.Config.Env)
}

return ep
}

// setBaseFS keeps container basefs in meta
19 changes: 14 additions & 5 deletions daemon/mgr/network.go
Original file line number Diff line number Diff line change
@@ -257,7 +257,7 @@ func (nm *NetworkManager) EndpointCreate(ctx context.Context, endpoint *types.En
}

// create endpoint
epOptions, err := endpointOptions(n, networkConfig, endpointConfig)
epOptions, err := endpointOptions(n, endpoint)
if err != nil {
return "", err
}
@@ -293,7 +293,7 @@ func (nm *NetworkManager) EndpointCreate(ctx context.Context, endpoint *types.En
networkConfig.SandboxKey = sb.Key()

// endpoint joins into sandbox
joinOptions, err := joinOptions(endpointConfig)
joinOptions, err := joinOptions(endpoint)
if err != nil {
return "", err
}
@@ -493,9 +493,9 @@ func initNetworkLog(cfg *config.Config) {
netlog.SetFormatter(formatter)
}

func endpointOptions(n libnetwork.Network, nwconfig *apitypes.NetworkSettings, epConfig *apitypes.EndpointSettings) ([]libnetwork.EndpointOption, error) {
func endpointOptions(n libnetwork.Network, endpoint *types.Endpoint) ([]libnetwork.EndpointOption, error) {
var createOptions []libnetwork.EndpointOption

epConfig := endpoint.EndpointConfig
if epConfig != nil {
ipam := epConfig.IPAMConfig
if ipam != nil && (ipam.IPV4Address != "" || ipam.IPV6Address != "" || len(ipam.LinkLocalIps) > 0) {
@@ -517,6 +517,13 @@ func endpointOptions(n libnetwork.Network, nwconfig *apitypes.NetworkSettings, e
genericOption := options.Generic{}
createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(genericOption))

if len(endpoint.GenericParams) > 0 {
createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(endpoint.GenericParams))
}
if endpoint.DisableResolver {
createOptions = append(createOptions, libnetwork.CreateOptionDisableResolution())
}

return createOptions, nil
}

@@ -653,9 +660,11 @@ func (nm *NetworkManager) cleanEndpointConfig(epConfig *apitypes.EndpointSetting
epConfig.MacAddress = ""
}

func joinOptions(epConfig *apitypes.EndpointSettings) ([]libnetwork.EndpointOption, error) {
func joinOptions(endpoint *types.Endpoint) ([]libnetwork.EndpointOption, error) {
var joinOptions []libnetwork.EndpointOption
// TODO: parse endpoint's links

// set priority option
joinOptions = append(joinOptions, libnetwork.JoinOptionPriority(nil, endpoint.Priority))
return joinOptions, nil
}
34 changes: 22 additions & 12 deletions docs/features/pouch_with_plugin.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# Pouch with plugin

In order to run custom code provided by users which will be triggered at some point, we support a plugin framework which introduced from golang 1.8. At this time in this plugin framework we enable users to add custom code at four point:
In order to run custom code provided by users which will be triggered at some point, we support a plugin framework which introduced from golang 1.8. At this time in this plugin framework we enable users to add custom code at file points:

* pre-start daemon point
* pre-stop daemon point
* pre-create container point
* pre-start container point
* pre-create-endapoint container point

Above four points are organized by two Plugin interfaces, which are DaemonPlugin and ContainerPlugin, defined as follow:

@@ -21,15 +22,18 @@ type DaemonPlugin interface {
PreStopHook() error
}
// ContainerPlugin defines in which place a plugin will be triggered in container lifecycle
// ContainerPlugin defines places where a plugin will be triggered in container lifecycle
type ContainerPlugin interface {
// PreCreate defines plugin point where receives an container create request, in this plugin point user
// could change the container create body passed-in by http request body
PreCreate(io.ReadCloser) (io.ReadCloser, error)
// PreCreate defines plugin point where receives an container create request, in this plugin point user
// could change the container create body passed-in by http request body
PreCreate(io.ReadCloser) (io.ReadCloser, error)
// PreStart returns an array of priority and args which will pass to runc, the every priority
// used to sort the pre start array that pass to runc, network plugin hook always has priority value 0.
PreStart(interface{}) ([]int, [][]string, error)
// PreStart returns an array of priority and args which will pass to runc, the every priority
// used to sort the pre start array that pass to runc, network plugin hook always has priority value 0.
PreStart(interface{}) ([]int, [][]string, error)
//NetworkGenericParams accepts the env of this container and returns the priority of this endpoint and if this endpoint should enable resolver and a map which will be used as generic params to create endpoints of this container
PreCreateEndpoint([]string) (priority int, disableResolver bool, genericParam map[string]interface{})
}
```
@@ -83,6 +87,11 @@ func (c ContPlugin) PreStart(interface{}) ([]int, [][]string, error) {
return []int{-4}, [][]string{{"/usr/bin/touch", "touch", "/tmp/pre_start_hook"}}, nil
}
func (c ContPlugin) PreCreateEndpoint([]string) (priority int, disableResolver bool, genericParam map[string]interface{}) {
fmt.Println("pre create endpoint")
return
}
func main() {
fmt.Println(ContainerPlugin, DaemonPlugin)
}
@@ -130,7 +139,8 @@ and if you use the exact code above, every time you start a container the file a

## usage

at pre-start daemon point you can start assist processes like network plugins and dfget proxy which need by pouchd and whose life cycle is the same as pouchd.
at pre-stop daemon point you can stop the assist processes gracefully, but the trigger of this point is not a promise, because pouchd may be killed by SIGKILL.
at pre-create container point you can change the input stream by some rules, in some company they have some stale orchestration system who use env to pass-in some limit which is an attribute in pouch, then you can use this point to convert value in env to attribute in ContainerConfig or HostConfig of pouch create api.
at pre-start container point you can set more pre-start hooks to oci spec, where you can do some special thing before container entrypoint start, priority decide the order of executing of the hook. libnetwork hook has priority 0, so if the hook is expected to run before network in container setup you should set priority to a value big then 0, and vice versa.
* at pre-start daemon point you can start assist processes like network plugins and dfget proxy which need by pouchd and whose life cycle is the same as pouchd.
* at pre-stop daemon point you can stop the assist processes gracefully, but the trigger of this point is not a promise, because pouchd may be killed by SIGKILL.
* at pre-create container point you can change the input stream by some rules, in some company they have some stale orchestration system who use env to pass-in some limit which is an attribute in pouch, then you can use this point to convert value in env to attribute in ContainerConfig or HostConfig of pouch create api.
* at pre-start container point you can set more pre-start hooks to oci spec, where you can do some special thing before container entrypoint start, priority decide the order of executing of the hook. libnetwork hook has priority 0, so if the hook is expected to run before network in container setup you should set priority to a value big then 0, and vice versa.
* at pre-create-endpoint container point you can return the priority of this endpoint and if this endpoint need enable resolver and the generic params of this endpoint.
4 changes: 4 additions & 0 deletions network/types/endpoint.go
Original file line number Diff line number Diff line change
@@ -31,4 +31,8 @@ type Endpoint struct {

NetworkConfig *types.NetworkSettings
EndpointConfig *types.EndpointSettings

GenericParams map[string]interface{}
Priority int
DisableResolver bool
}

0 comments on commit 5e967d3

Please sign in to comment.