Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
87ab70d6
Commit
87ab70d6
authored
Aug 22, 2016
by
Minhan Xia
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add ebtables util
parent
4f4c5022
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
313 additions
and
0 deletions
+313
-0
ebtables.go
pkg/util/ebtables/ebtables.go
+189
-0
ebtables_test.go
pkg/util/ebtables/ebtables_test.go
+124
-0
No files found.
pkg/util/ebtables/ebtables.go
0 → 100644
View file @
87ab70d6
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
ebtables
import
(
"fmt"
utilexec
"k8s.io/kubernetes/pkg/util/exec"
"regexp"
"strings"
"sync"
)
const
(
cmdebtables
=
"ebtables"
// Flag to show full mac in output. The default representation omits leading zeroes.
fullMac
=
"--Lmac2"
)
type
RulePosition
string
const
(
Prepend
RulePosition
=
"-I"
Append
RulePosition
=
"-A"
)
type
Table
string
const
(
TableNAT
Table
=
"nat"
TableFilter
Table
=
"filter"
)
type
Chain
string
const
(
ChainPostrouting
Chain
=
"POSTROUTING"
ChainPrerouting
Chain
=
"PREROUTING"
ChainOutput
Chain
=
"OUTPUT"
ChainInput
Chain
=
"INPUT"
)
type
operation
string
const
(
opCreateChain
operation
=
"-N"
opFlushChain
operation
=
"-F"
opDeleteChain
operation
=
"-X"
opListChain
operation
=
"-L"
opAppendRule
operation
=
"-A"
opPrependRule
operation
=
"-I"
opDeleteRule
operation
=
"-D"
)
// An injectable interface for running ebtables commands. Implementations must be goroutine-safe.
type
Interface
interface
{
// GetVersion returns the "X.Y.Z" semver string for ebtables.
GetVersion
()
(
string
,
error
)
// EnsureRule checks if the specified rule is present and, if not, creates it. If the rule existed, return true.
// WARNING: ebtables does not provide check operation like iptables do. Hence we have to do a string match of args.
// Input args must follow the format and sequence of ebtables list output. Otherwise, EnsureRule will always create
// new rules and causing duplicates.
EnsureRule
(
position
RulePosition
,
table
Table
,
chain
Chain
,
args
...
string
)
(
bool
,
error
)
// EnsureChain checks if the specified chain is present and, if not, creates it. If the rule existed, return true.
EnsureChain
(
table
Table
,
chain
Chain
)
(
bool
,
error
)
// DeleteChain deletes the specified chain. If the chain did not exist, return error.
DeleteChain
(
table
Table
,
chain
Chain
)
error
// FlushChain flush the specified chain. If the chain did not exist, return error.
FlushChain
(
table
Table
,
chain
Chain
)
error
}
// runner implements Interface in terms of exec("ebtables").
type
runner
struct
{
mu
sync
.
Mutex
exec
utilexec
.
Interface
}
// New returns a new Interface which will exec ebtables.
func
New
(
exec
utilexec
.
Interface
)
Interface
{
runner
:=
&
runner
{
exec
:
exec
,
}
return
runner
}
func
makeFullArgs
(
table
Table
,
op
operation
,
chain
Chain
,
args
...
string
)
[]
string
{
return
append
([]
string
{
"-t"
,
string
(
table
),
string
(
op
),
string
(
chain
)},
args
...
)
}
// getEbtablesVersionString runs "ebtables --version" to get the version string
// in the form "X.X.X"
func
getEbtablesVersionString
(
exec
utilexec
.
Interface
)
(
string
,
error
)
{
// this doesn't access mutable state so we don't need to use the interface / runner
bytes
,
err
:=
exec
.
Command
(
cmdebtables
,
"--version"
)
.
CombinedOutput
()
if
err
!=
nil
{
return
""
,
err
}
versionMatcher
:=
regexp
.
MustCompile
(
"v([0-9]+
\\
.[0-9]+
\\
.[0-9]+)"
)
match
:=
versionMatcher
.
FindStringSubmatch
(
string
(
bytes
))
if
match
==
nil
{
return
""
,
fmt
.
Errorf
(
"no ebtables version found in string: %s"
,
bytes
)
}
return
match
[
1
],
nil
}
func
(
runner
*
runner
)
GetVersion
()
(
string
,
error
)
{
return
getEbtablesVersionString
(
runner
.
exec
)
}
func
(
runner
*
runner
)
EnsureRule
(
position
RulePosition
,
table
Table
,
chain
Chain
,
args
...
string
)
(
bool
,
error
)
{
exist
:=
true
fullArgs
:=
makeFullArgs
(
table
,
opListChain
,
chain
,
fullMac
)
out
,
err
:=
runner
.
exec
.
Command
(
cmdebtables
,
fullArgs
...
)
.
CombinedOutput
()
if
err
!=
nil
{
exist
=
false
}
else
{
exist
=
checkIfRuleExists
(
string
(
out
),
args
...
)
}
if
!
exist
{
fullArgs
=
makeFullArgs
(
table
,
operation
(
position
),
chain
,
args
...
)
out
,
err
:=
runner
.
exec
.
Command
(
cmdebtables
,
fullArgs
...
)
.
CombinedOutput
()
if
err
!=
nil
{
return
exist
,
fmt
.
Errorf
(
"Failed to ensure rule: %v, output: %v"
,
err
,
string
(
out
))
}
}
return
exist
,
nil
}
func
(
runner
*
runner
)
EnsureChain
(
table
Table
,
chain
Chain
)
(
bool
,
error
)
{
exist
:=
true
args
:=
makeFullArgs
(
table
,
opListChain
,
chain
)
_
,
err
:=
runner
.
exec
.
Command
(
cmdebtables
,
args
...
)
.
CombinedOutput
()
if
err
!=
nil
{
exist
=
false
}
if
!
exist
{
args
=
makeFullArgs
(
table
,
opCreateChain
,
chain
)
out
,
err
:=
runner
.
exec
.
Command
(
cmdebtables
,
args
...
)
.
CombinedOutput
()
if
err
!=
nil
{
return
exist
,
fmt
.
Errorf
(
"Failed to ensure %v chain: %v, output: %v"
,
chain
,
err
,
string
(
out
))
}
}
return
exist
,
nil
}
// checkIfRuleExists takes the output of ebtables list chain and checks if the input rules exists
// WARNING: checkIfRuleExists expects the input args matches the format and sequence of ebtables list output
func
checkIfRuleExists
(
listChainOutput
string
,
args
...
string
)
bool
{
rule
:=
strings
.
Join
(
args
,
" "
)
for
_
,
line
:=
range
strings
.
Split
(
listChainOutput
,
"
\n
"
)
{
if
strings
.
TrimSpace
(
line
)
==
rule
{
return
true
}
}
return
false
}
func
(
runner
*
runner
)
DeleteChain
(
table
Table
,
chain
Chain
)
error
{
fullArgs
:=
makeFullArgs
(
table
,
opDeleteChain
,
chain
)
out
,
err
:=
runner
.
exec
.
Command
(
cmdebtables
,
fullArgs
...
)
.
CombinedOutput
()
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Failed to delete %v chain %v: %v, output: %v"
,
string
(
table
),
string
(
chain
),
err
,
string
(
out
))
}
return
nil
}
func
(
runner
*
runner
)
FlushChain
(
table
Table
,
chain
Chain
)
error
{
fullArgs
:=
makeFullArgs
(
table
,
opFlushChain
,
chain
)
out
,
err
:=
runner
.
exec
.
Command
(
cmdebtables
,
fullArgs
...
)
.
CombinedOutput
()
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Failed to flush %v chain %v: %v, output: %v"
,
string
(
table
),
string
(
chain
),
err
,
string
(
out
))
}
return
nil
}
pkg/util/ebtables/ebtables_test.go
0 → 100644
View file @
87ab70d6
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
ebtables
import
(
"k8s.io/kubernetes/pkg/util/exec"
"strings"
"testing"
)
func
testEnsureChain
(
t
*
testing
.
T
)
{
fcmd
:=
exec
.
FakeCmd
{
CombinedOutputScript
:
[]
exec
.
FakeCombinedOutputAction
{
// Does not Exists
func
()
([]
byte
,
error
)
{
return
nil
,
&
exec
.
FakeExitError
{
Status
:
1
}
},
// Success
func
()
([]
byte
,
error
)
{
return
[]
byte
{},
nil
},
// Exists
func
()
([]
byte
,
error
)
{
return
nil
,
nil
},
// Does not Exists
func
()
([]
byte
,
error
)
{
return
nil
,
&
exec
.
FakeExitError
{
Status
:
1
}
},
// Fail to create chain
func
()
([]
byte
,
error
)
{
return
nil
,
&
exec
.
FakeExitError
{
Status
:
2
}
},
},
}
fexec
:=
exec
.
FakeExec
{
CommandScript
:
[]
exec
.
FakeCommandAction
{
func
(
cmd
string
,
args
...
string
)
exec
.
Cmd
{
return
exec
.
InitFakeCmd
(
&
fcmd
,
cmd
,
args
...
)
},
func
(
cmd
string
,
args
...
string
)
exec
.
Cmd
{
return
exec
.
InitFakeCmd
(
&
fcmd
,
cmd
,
args
...
)
},
func
(
cmd
string
,
args
...
string
)
exec
.
Cmd
{
return
exec
.
InitFakeCmd
(
&
fcmd
,
cmd
,
args
...
)
},
func
(
cmd
string
,
args
...
string
)
exec
.
Cmd
{
return
exec
.
InitFakeCmd
(
&
fcmd
,
cmd
,
args
...
)
},
func
(
cmd
string
,
args
...
string
)
exec
.
Cmd
{
return
exec
.
InitFakeCmd
(
&
fcmd
,
cmd
,
args
...
)
},
},
}
runner
:=
New
(
&
fexec
)
exists
,
err
:=
runner
.
EnsureChain
(
TableFilter
,
"TEST-CHAIN"
)
if
exists
{
t
.
Errorf
(
"expected exists = false"
)
}
if
err
!=
nil
{
t
.
Errorf
(
"expected err = nil"
)
}
exists
,
err
=
runner
.
EnsureChain
(
TableFilter
,
"TEST-CHAIN"
)
if
!
exists
{
t
.
Errorf
(
"expected exists = true"
)
}
if
err
!=
nil
{
t
.
Errorf
(
"expected err = nil"
)
}
exists
,
err
=
runner
.
EnsureChain
(
TableFilter
,
"TEST-CHAIN"
)
if
exists
{
t
.
Errorf
(
"expected exists = false"
)
}
errStr
:=
"Failed to ensure TEST-CHAIN chain: exit 2, output:"
if
err
==
nil
||
!
strings
.
Contains
(
err
.
Error
(),
errStr
)
{
t
.
Errorf
(
"expected error: %q"
,
errStr
)
}
}
func
testEnsureRule
(
t
*
testing
.
T
)
{
fcmd
:=
exec
.
FakeCmd
{
CombinedOutputScript
:
[]
exec
.
FakeCombinedOutputAction
{
// Exists
func
()
([]
byte
,
error
)
{
return
[]
byte
(
`Bridge table: filter
Bridge chain: OUTPUT, entries: 4, policy: ACCEPT
-j TEST
`
),
nil
},
// Does not Exists.
func
()
([]
byte
,
error
)
{
return
[]
byte
(
`Bridge table: filter
Bridge chain: TEST, entries: 0, policy: ACCEPT`
),
nil
},
// Fail to create
func
()
([]
byte
,
error
)
{
return
nil
,
&
exec
.
FakeExitError
{
Status
:
2
}
},
},
}
fexec
:=
exec
.
FakeExec
{
CommandScript
:
[]
exec
.
FakeCommandAction
{
func
(
cmd
string
,
args
...
string
)
exec
.
Cmd
{
return
exec
.
InitFakeCmd
(
&
fcmd
,
cmd
,
args
...
)
},
func
(
cmd
string
,
args
...
string
)
exec
.
Cmd
{
return
exec
.
InitFakeCmd
(
&
fcmd
,
cmd
,
args
...
)
},
func
(
cmd
string
,
args
...
string
)
exec
.
Cmd
{
return
exec
.
InitFakeCmd
(
&
fcmd
,
cmd
,
args
...
)
},
},
}
runner
:=
New
(
&
fexec
)
exists
,
err
:=
runner
.
EnsureRule
(
Append
,
TableFilter
,
ChainOutput
,
"-j"
,
"TEST"
)
if
!
exists
{
t
.
Errorf
(
"expected exists = true"
)
}
if
err
!=
nil
{
t
.
Errorf
(
"expected err = nil"
)
}
exists
,
err
=
runner
.
EnsureRule
(
Append
,
TableFilter
,
ChainOutput
,
"-j"
,
"NEXT-TEST"
)
if
exists
{
t
.
Errorf
(
"expected exists = false"
)
}
errStr
:=
"Failed to ensure rule: exist 2, output: "
if
err
==
nil
||
err
.
Error
()
!=
errStr
{
t
.
Errorf
(
"expected error: %q"
,
errStr
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment