Add check support for: bridge, ipvlan, macvlan, p2p, vlan and host-device main plugins
host-local and static ipam plugins tuning, bandwidth and portmap meta plugins Utility functions created for common PrevResult checking Fix windows build
This commit is contained in:
@ -138,3 +138,44 @@ func chainExists(ipt *iptables.IPTables, tableName, chainName string) (bool, err
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// check the chain.
|
||||
func (c *chain) check(ipt *iptables.IPTables) error {
|
||||
|
||||
exists, err := chainExists(ipt, c.table, c.name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
return fmt.Errorf("chain %s not found in iptables table %s", c.name, c.table)
|
||||
}
|
||||
|
||||
for i := len(c.rules) - 1; i >= 0; i-- {
|
||||
match := checkRule(ipt, c.table, c.name, c.rules[i])
|
||||
if !match {
|
||||
return fmt.Errorf("rule %s in chain %s not found in table %s", c.rules, c.name, c.table)
|
||||
}
|
||||
}
|
||||
|
||||
for _, entryChain := range c.entryChains {
|
||||
for i := len(c.entryRules) - 1; i >= 0; i-- {
|
||||
r := []string{}
|
||||
r = append(r, c.entryRules[i]...)
|
||||
r = append(r, "-j", c.name)
|
||||
matchEntryChain := checkRule(ipt, c.table, entryChain, r)
|
||||
if !matchEntryChain {
|
||||
return fmt.Errorf("rule %s in chain %s not found in table %s", c.entryRules, entryChain, c.table)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkRule(ipt *iptables.IPTables, table, chain string, rule []string) bool {
|
||||
exists, err := ipt.Exists(table, chain, rule...)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return exists
|
||||
}
|
||||
|
@ -55,8 +55,6 @@ type PortMapConf struct {
|
||||
RuntimeConfig struct {
|
||||
PortMaps []PortMapEntry `json:"portMappings,omitempty"`
|
||||
} `json:"runtimeConfig,omitempty"`
|
||||
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
|
||||
PrevResult *current.Result `json:"-"`
|
||||
|
||||
// These are fields parsed out of the config or the environment;
|
||||
// included here for convenience
|
||||
@ -70,7 +68,7 @@ type PortMapConf struct {
|
||||
const DefaultMarkBit = 13
|
||||
|
||||
func cmdAdd(args *skel.CmdArgs) error {
|
||||
netConf, err := parseConfig(args.StdinData, args.IfName)
|
||||
netConf, _, err := parseConfig(args.StdinData, args.IfName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse config: %v", err)
|
||||
}
|
||||
@ -102,7 +100,7 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
}
|
||||
|
||||
func cmdDel(args *skel.CmdArgs) error {
|
||||
netConf, err := parseConfig(args.StdinData, args.IfName)
|
||||
netConf, _, err := parseConfig(args.StdinData, args.IfName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse config: %v", err)
|
||||
}
|
||||
@ -119,36 +117,60 @@ func cmdDel(args *skel.CmdArgs) error {
|
||||
|
||||
func main() {
|
||||
// TODO: implement plugin version
|
||||
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||
skel.PluginMain(cmdAdd, cmdCheck, cmdDel, version.All, "TODO")
|
||||
}
|
||||
|
||||
func cmdGet(args *skel.CmdArgs) error {
|
||||
// TODO: implement
|
||||
return fmt.Errorf("not implemented")
|
||||
func cmdCheck(args *skel.CmdArgs) error {
|
||||
conf, result, err := parseConfig(args.StdinData, args.IfName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ensure we have previous result.
|
||||
if result == nil {
|
||||
return fmt.Errorf("Required prevResult missing")
|
||||
}
|
||||
|
||||
if len(conf.RuntimeConfig.PortMaps) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
conf.ContainerID = args.ContainerID
|
||||
|
||||
if conf.ContIPv4 != nil {
|
||||
if err := checkPorts(conf, conf.ContIPv4); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if conf.ContIPv6 != nil {
|
||||
if err := checkPorts(conf, conf.ContIPv6); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseConfig parses the supplied configuration (and prevResult) from stdin.
|
||||
func parseConfig(stdin []byte, ifName string) (*PortMapConf, error) {
|
||||
func parseConfig(stdin []byte, ifName string) (*PortMapConf, *current.Result, error) {
|
||||
conf := PortMapConf{}
|
||||
|
||||
if err := json.Unmarshal(stdin, &conf); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse network configuration: %v", err)
|
||||
return nil, nil, fmt.Errorf("failed to parse network configuration: %v", err)
|
||||
}
|
||||
|
||||
// Parse previous result.
|
||||
var result *current.Result
|
||||
if conf.RawPrevResult != nil {
|
||||
resultBytes, err := json.Marshal(conf.RawPrevResult)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not serialize prevResult: %v", err)
|
||||
var err error
|
||||
if err = version.ParsePrevResult(&conf.NetConf); err != nil {
|
||||
return nil, nil, fmt.Errorf("could not parse prevResult: %v", err)
|
||||
}
|
||||
res, err := version.NewResult(conf.CNIVersion, resultBytes)
|
||||
|
||||
result, err = current.NewResultFromResult(conf.PrevResult)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse prevResult: %v", err)
|
||||
}
|
||||
conf.RawPrevResult = nil
|
||||
conf.PrevResult, err = current.NewResultFromResult(res)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not convert result to current version: %v", err)
|
||||
return nil, nil, fmt.Errorf("could not convert result to current version: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,7 +180,7 @@ func parseConfig(stdin []byte, ifName string) (*PortMapConf, error) {
|
||||
}
|
||||
|
||||
if conf.MarkMasqBit != nil && conf.ExternalSetMarkChain != nil {
|
||||
return nil, fmt.Errorf("Cannot specify externalSetMarkChain and markMasqBit")
|
||||
return nil, nil, fmt.Errorf("Cannot specify externalSetMarkChain and markMasqBit")
|
||||
}
|
||||
|
||||
if conf.MarkMasqBit == nil {
|
||||
@ -167,21 +189,21 @@ func parseConfig(stdin []byte, ifName string) (*PortMapConf, error) {
|
||||
}
|
||||
|
||||
if *conf.MarkMasqBit < 0 || *conf.MarkMasqBit > 31 {
|
||||
return nil, fmt.Errorf("MasqMarkBit must be between 0 and 31")
|
||||
return nil, nil, fmt.Errorf("MasqMarkBit must be between 0 and 31")
|
||||
}
|
||||
|
||||
// Reject invalid port numbers
|
||||
for _, pm := range conf.RuntimeConfig.PortMaps {
|
||||
if pm.ContainerPort <= 0 {
|
||||
return nil, fmt.Errorf("Invalid container port number: %d", pm.ContainerPort)
|
||||
return nil, nil, fmt.Errorf("Invalid container port number: %d", pm.ContainerPort)
|
||||
}
|
||||
if pm.HostPort <= 0 {
|
||||
return nil, fmt.Errorf("Invalid host port number: %d", pm.HostPort)
|
||||
return nil, nil, fmt.Errorf("Invalid host port number: %d", pm.HostPort)
|
||||
}
|
||||
}
|
||||
|
||||
if conf.PrevResult != nil {
|
||||
for _, ip := range conf.PrevResult.IPs {
|
||||
for _, ip := range result.IPs {
|
||||
if ip.Version == "6" && conf.ContIPv6 != nil {
|
||||
continue
|
||||
} else if ip.Version == "4" && conf.ContIPv4 != nil {
|
||||
@ -192,9 +214,9 @@ func parseConfig(stdin []byte, ifName string) (*PortMapConf, error) {
|
||||
if ip.Interface != nil {
|
||||
intIdx := *ip.Interface
|
||||
if intIdx >= 0 &&
|
||||
intIdx < len(conf.PrevResult.Interfaces) &&
|
||||
(conf.PrevResult.Interfaces[intIdx].Name != ifName ||
|
||||
conf.PrevResult.Interfaces[intIdx].Sandbox == "") {
|
||||
intIdx < len(result.Interfaces) &&
|
||||
(result.Interfaces[intIdx].Name != ifName ||
|
||||
result.Interfaces[intIdx].Sandbox == "") {
|
||||
continue
|
||||
}
|
||||
}
|
||||
@ -207,5 +229,5 @@ func parseConfig(stdin []byte, ifName string) (*PortMapConf, error) {
|
||||
}
|
||||
}
|
||||
|
||||
return &conf, nil
|
||||
return &conf, result, nil
|
||||
}
|
||||
|
@ -111,6 +111,46 @@ func forwardPorts(config *PortMapConf, containerIP net.IP) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkPorts(config *PortMapConf, containerIP net.IP) error {
|
||||
|
||||
dnatChain := genDnatChain(config.Name, config.ContainerID)
|
||||
fillDnatRules(&dnatChain, config, containerIP)
|
||||
|
||||
ip4t := maybeGetIptables(false)
|
||||
ip6t := maybeGetIptables(true)
|
||||
if ip4t == nil && ip6t == nil {
|
||||
return fmt.Errorf("neither iptables nor ip6tables usable")
|
||||
}
|
||||
|
||||
if ip4t != nil {
|
||||
exists, err := chainExists(ip4t, dnatChain.table, dnatChain.name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
return err
|
||||
}
|
||||
if err := dnatChain.check(ip4t); err != nil {
|
||||
return fmt.Errorf("could not check ipv4 dnat: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if ip6t != nil {
|
||||
exists, err := chainExists(ip6t, dnatChain.table, dnatChain.name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
return err
|
||||
}
|
||||
if err := dnatChain.check(ip6t); err != nil {
|
||||
return fmt.Errorf("could not check ipv6 dnat: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// genToplevelDnatChain creates the top-level summary chain that we'll
|
||||
// add our chain to. This is easy, because creating chains is idempotent.
|
||||
// IMPORTANT: do not change this, or else upgrading plugins will require
|
||||
|
@ -68,7 +68,7 @@ var _ = Describe("portmapping configuration", func() {
|
||||
]
|
||||
}
|
||||
}`)
|
||||
c, err := parseConfig(configBytes, "container")
|
||||
c, _, err := parseConfig(configBytes, "container")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(c.CNIVersion).To(Equal("0.3.1"))
|
||||
Expect(c.ConditionsV4).To(Equal(&[]string{"a", "b"}))
|
||||
@ -91,7 +91,7 @@ var _ = Describe("portmapping configuration", func() {
|
||||
"conditionsV4": ["a", "b"],
|
||||
"conditionsV6": ["c", "d"]
|
||||
}`)
|
||||
c, err := parseConfig(configBytes, "container")
|
||||
c, _, err := parseConfig(configBytes, "container")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(c.CNIVersion).To(Equal("0.3.1"))
|
||||
Expect(c.ConditionsV4).To(Equal(&[]string{"a", "b"}))
|
||||
@ -115,7 +115,7 @@ var _ = Describe("portmapping configuration", func() {
|
||||
]
|
||||
}
|
||||
}`)
|
||||
_, err := parseConfig(configBytes, "container")
|
||||
_, _, err := parseConfig(configBytes, "container")
|
||||
Expect(err).To(MatchError("Invalid host port number: 0"))
|
||||
})
|
||||
|
||||
@ -143,7 +143,7 @@ var _ = Describe("portmapping configuration", func() {
|
||||
]
|
||||
}
|
||||
}`)
|
||||
_, err := parseConfig(configBytes, "container")
|
||||
_, _, err := parseConfig(configBytes, "container")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
})
|
||||
@ -175,7 +175,7 @@ var _ = Describe("portmapping configuration", func() {
|
||||
"conditionsV6": ["c", "d"]
|
||||
}`)
|
||||
|
||||
conf, err := parseConfig(configBytes, "foo")
|
||||
conf, _, err := parseConfig(configBytes, "foo")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
conf.ContainerID = containerID
|
||||
|
||||
@ -271,7 +271,7 @@ var _ = Describe("portmapping configuration", func() {
|
||||
"conditionsV6": ["c", "d"]
|
||||
}`)
|
||||
|
||||
conf, err := parseConfig(configBytes, "foo")
|
||||
conf, _, err := parseConfig(configBytes, "foo")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
conf.ContainerID = containerID
|
||||
|
||||
|
Reference in New Issue
Block a user