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
ea2cd6d7
Commit
ea2cd6d7
authored
Nov 06, 2020
by
Brad Davidson
Committed by
Brad Davidson
Jun 11, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add comments, clean up imports and function names
Signed-off-by:
Brad Davidson
<
brad.davidson@rancher.com
>
parent
6e48ca9b
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
51 additions
and
21 deletions
+51
-21
controller.go
pkg/deploy/controller.go
+51
-21
No files found.
pkg/deploy/controller.go
View file @
ea2cd6d7
...
@@ -16,8 +16,8 @@ import (
...
@@ -16,8 +16,8 @@ import (
errors2
"github.com/pkg/errors"
errors2
"github.com/pkg/errors"
"github.com/rancher/k3s/pkg/agent/util"
"github.com/rancher/k3s/pkg/agent/util"
v12
"github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1"
apisv1
"github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1"
v1
"github.com/rancher/k3s/pkg/generated/controllers/k3s.cattle.io/v1"
controllers
v1
"github.com/rancher/k3s/pkg/generated/controllers/k3s.cattle.io/v1"
"github.com/rancher/wrangler/pkg/apply"
"github.com/rancher/wrangler/pkg/apply"
"github.com/rancher/wrangler/pkg/merr"
"github.com/rancher/wrangler/pkg/merr"
"github.com/rancher/wrangler/pkg/objectset"
"github.com/rancher/wrangler/pkg/objectset"
...
@@ -32,11 +32,11 @@ import (
...
@@ -32,11 +32,11 @@ import (
const
(
const
(
ControllerName
=
"deploy"
ControllerName
=
"deploy"
ns
=
"kube-system"
startKey
=
"_start_"
startKey
=
"_start_"
)
)
func
WatchFiles
(
ctx
context
.
Context
,
apply
apply
.
Apply
,
addons
v1
.
AddonController
,
disables
map
[
string
]
bool
,
bases
...
string
)
error
{
// WatchFiles sets up an OnChange callback to start a periodic goroutine to watch files for changes once the controller has started up.
func
WatchFiles
(
ctx
context
.
Context
,
apply
apply
.
Apply
,
addons
controllersv1
.
AddonController
,
disables
map
[
string
]
bool
,
bases
...
string
)
error
{
w
:=
&
watcher
{
w
:=
&
watcher
{
apply
:
apply
,
apply
:
apply
,
addonCache
:
addons
.
Cache
(),
addonCache
:
addons
.
Cache
(),
...
@@ -46,8 +46,8 @@ func WatchFiles(ctx context.Context, apply apply.Apply, addons v1.AddonControlle
...
@@ -46,8 +46,8 @@ func WatchFiles(ctx context.Context, apply apply.Apply, addons v1.AddonControlle
modTime
:
map
[
string
]
time
.
Time
{},
modTime
:
map
[
string
]
time
.
Time
{},
}
}
addons
.
Enqueue
(
""
,
startKey
)
addons
.
Enqueue
(
metav1
.
NamespaceNone
,
startKey
)
addons
.
OnChange
(
ctx
,
"addon-start"
,
func
(
key
string
,
_
*
v12
.
Addon
)
(
*
v12
.
Addon
,
error
)
{
addons
.
OnChange
(
ctx
,
"addon-start"
,
func
(
key
string
,
_
*
apisv1
.
Addon
)
(
*
apisv1
.
Addon
,
error
)
{
if
key
==
startKey
{
if
key
==
startKey
{
go
w
.
start
(
ctx
)
go
w
.
start
(
ctx
)
}
}
...
@@ -59,13 +59,14 @@ func WatchFiles(ctx context.Context, apply apply.Apply, addons v1.AddonControlle
...
@@ -59,13 +59,14 @@ func WatchFiles(ctx context.Context, apply apply.Apply, addons v1.AddonControlle
type
watcher
struct
{
type
watcher
struct
{
apply
apply
.
Apply
apply
apply
.
Apply
addonCache
v1
.
AddonCache
addonCache
controllers
v1
.
AddonCache
addons
v1
.
AddonClient
addons
controllers
v1
.
AddonClient
bases
[]
string
bases
[]
string
disables
map
[
string
]
bool
disables
map
[
string
]
bool
modTime
map
[
string
]
time
.
Time
modTime
map
[
string
]
time
.
Time
}
}
// start calls listFiles at regular intervals to trigger application of manifests that have changed on disk.
func
(
w
*
watcher
)
start
(
ctx
context
.
Context
)
{
func
(
w
*
watcher
)
start
(
ctx
context
.
Context
)
{
force
:=
true
force
:=
true
for
{
for
{
...
@@ -82,6 +83,7 @@ func (w *watcher) start(ctx context.Context) {
...
@@ -82,6 +83,7 @@ func (w *watcher) start(ctx context.Context) {
}
}
}
}
// listFiles calls listFilesIn on a list of paths.
func
(
w
*
watcher
)
listFiles
(
force
bool
)
error
{
func
(
w
*
watcher
)
listFiles
(
force
bool
)
error
{
var
errs
[]
error
var
errs
[]
error
for
_
,
base
:=
range
w
.
bases
{
for
_
,
base
:=
range
w
.
bases
{
...
@@ -92,6 +94,8 @@ func (w *watcher) listFiles(force bool) error {
...
@@ -92,6 +94,8 @@ func (w *watcher) listFiles(force bool) error {
return
merr
.
NewErrors
(
errs
...
)
return
merr
.
NewErrors
(
errs
...
)
}
}
// listFilesIn recursively processes all files within a path, and checks them against the disable and skip lists. Files found that
// are not on either list are loaded as Addons and applied to the cluster.
func
(
w
*
watcher
)
listFilesIn
(
base
string
,
force
bool
)
error
{
func
(
w
*
watcher
)
listFilesIn
(
base
string
,
force
bool
)
error
{
files
:=
map
[
string
]
os
.
FileInfo
{}
files
:=
map
[
string
]
os
.
FileInfo
{}
if
err
:=
filepath
.
Walk
(
base
,
func
(
path
string
,
info
os
.
FileInfo
,
err
error
)
error
{
if
err
:=
filepath
.
Walk
(
base
,
func
(
path
string
,
info
os
.
FileInfo
,
err
error
)
error
{
...
@@ -104,6 +108,9 @@ func (w *watcher) listFilesIn(base string, force bool) error {
...
@@ -104,6 +108,9 @@ func (w *watcher) listFilesIn(base string, force bool) error {
return
err
return
err
}
}
// Make a map of .skip files - these are used later to indicate that a given file should be ignored
// For example, 'addon.yaml.skip' will cause 'addon.yaml' to be ignored completely - unless it is also
// disabled, since disable processing happens first.
skips
:=
map
[
string
]
bool
{}
skips
:=
map
[
string
]
bool
{}
keys
:=
make
([]
string
,
len
(
files
))
keys
:=
make
([]
string
,
len
(
files
))
keyIndex
:=
0
keyIndex
:=
0
...
@@ -118,13 +125,15 @@ func (w *watcher) listFilesIn(base string, force bool) error {
...
@@ -118,13 +125,15 @@ func (w *watcher) listFilesIn(base string, force bool) error {
var
errs
[]
error
var
errs
[]
error
for
_
,
path
:=
range
keys
{
for
_
,
path
:=
range
keys
{
if
shouldDisableService
(
base
,
path
,
w
.
disables
)
{
// Disabled files are not just skipped, but actively deleted from the filesystem
if
shouldDisableFile
(
base
,
path
,
w
.
disables
)
{
if
err
:=
w
.
delete
(
path
);
err
!=
nil
{
if
err
:=
w
.
delete
(
path
);
err
!=
nil
{
errs
=
append
(
errs
,
errors2
.
Wrapf
(
err
,
"failed to delete %s"
,
path
))
errs
=
append
(
errs
,
errors2
.
Wrapf
(
err
,
"failed to delete %s"
,
path
))
}
}
continue
continue
}
}
if
skipFile
(
files
[
path
]
.
Name
(),
skips
)
{
// Skipped files are just ignored
if
shouldSkipFile
(
files
[
path
]
.
Name
(),
skips
)
{
continue
continue
}
}
modTime
:=
files
[
path
]
.
ModTime
()
modTime
:=
files
[
path
]
.
ModTime
()
...
@@ -141,14 +150,16 @@ func (w *watcher) listFilesIn(base string, force bool) error {
...
@@ -141,14 +150,16 @@ func (w *watcher) listFilesIn(base string, force bool) error {
return
merr
.
NewErrors
(
errs
...
)
return
merr
.
NewErrors
(
errs
...
)
}
}
// deploy loads yaml from a manifest on disk, creates an AddOn resource to track its application, and then applies
// all resources contained within to the cluster.
func
(
w
*
watcher
)
deploy
(
path
string
,
compareChecksum
bool
)
error
{
func
(
w
*
watcher
)
deploy
(
path
string
,
compareChecksum
bool
)
error
{
content
,
err
:=
ioutil
.
ReadFile
(
path
)
content
,
err
:=
ioutil
.
ReadFile
(
path
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
name
:=
name
(
path
)
name
:=
base
name
(
path
)
addon
,
err
:=
w
.
a
ddon
(
name
)
addon
,
err
:=
w
.
getOrCreateA
ddon
(
name
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -172,6 +183,8 @@ func (w *watcher) deploy(path string, compareChecksum bool) error {
...
@@ -172,6 +183,8 @@ func (w *watcher) deploy(path string, compareChecksum bool) error {
addon
.
Spec
.
Checksum
=
checksum
addon
.
Spec
.
Checksum
=
checksum
addon
.
Status
.
GVKs
=
nil
addon
.
Status
.
GVKs
=
nil
// Create the new Addon now so that we can use it to report Events when parsing/applying the manifest
// Events need the UID and ObjectRevision set to function properly
if
addon
.
UID
==
""
{
if
addon
.
UID
==
""
{
_
,
err
:=
w
.
addons
.
Create
(
&
addon
)
_
,
err
:=
w
.
addons
.
Create
(
&
addon
)
return
err
return
err
...
@@ -181,9 +194,11 @@ func (w *watcher) deploy(path string, compareChecksum bool) error {
...
@@ -181,9 +194,11 @@ func (w *watcher) deploy(path string, compareChecksum bool) error {
return
err
return
err
}
}
// delete completely removes both a manifest, and any resources that it did or would have created. The manifest is
// parsed, and any resources it specified are deleted. Finally, the file itself is removed from disk.
func
(
w
*
watcher
)
delete
(
path
string
)
error
{
func
(
w
*
watcher
)
delete
(
path
string
)
error
{
name
:=
name
(
path
)
name
:=
base
name
(
path
)
addon
,
err
:=
w
.
a
ddon
(
name
)
addon
,
err
:=
w
.
getOrCreateA
ddon
(
name
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -214,16 +229,19 @@ func (w *watcher) delete(path string) error {
...
@@ -214,16 +229,19 @@ func (w *watcher) delete(path string) error {
return
os
.
Remove
(
path
)
return
os
.
Remove
(
path
)
}
}
func
(
w
*
watcher
)
addon
(
name
string
)
(
v12
.
Addon
,
error
)
{
// getOrCreateAddon attempts to get an Addon by name from the addon namespace, and creates a new one
addon
,
err
:=
w
.
addonCache
.
Get
(
ns
,
name
)
// if it cannot be found.
func
(
w
*
watcher
)
getOrCreateAddon
(
name
string
)
(
apisv1
.
Addon
,
error
)
{
addon
,
err
:=
w
.
addonCache
.
Get
(
metav1
.
NamespaceSystem
,
name
)
if
errors
.
IsNotFound
(
err
)
{
if
errors
.
IsNotFound
(
err
)
{
addon
=
v12
.
NewAddon
(
ns
,
name
,
v12
.
Addon
{})
addon
=
apisv1
.
NewAddon
(
metav1
.
NamespaceSystem
,
name
,
apisv1
.
Addon
{})
}
else
if
err
!=
nil
{
}
else
if
err
!=
nil
{
return
v12
.
Addon
{},
err
return
apisv1
.
Addon
{},
err
}
}
return
*
addon
,
nil
return
*
addon
,
nil
}
}
// objectSet returns a new ObjectSet containing all resources from a given yaml chunk
func
objectSet
(
content
[]
byte
)
(
*
objectset
.
ObjectSet
,
error
)
{
func
objectSet
(
content
[]
byte
)
(
*
objectset
.
ObjectSet
,
error
)
{
objs
,
err
:=
yamlToObjects
(
bytes
.
NewBuffer
(
content
))
objs
,
err
:=
yamlToObjects
(
bytes
.
NewBuffer
(
content
))
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -235,16 +253,19 @@ func objectSet(content []byte) (*objectset.ObjectSet, error) {
...
@@ -235,16 +253,19 @@ func objectSet(content []byte) (*objectset.ObjectSet, error) {
return
os
,
nil
return
os
,
nil
}
}
func
name
(
path
string
)
string
{
// basename returns a file's basename by returning everything before the first period
func
basename
(
path
string
)
string
{
name
:=
filepath
.
Base
(
path
)
name
:=
filepath
.
Base
(
path
)
return
strings
.
SplitN
(
name
,
"."
,
2
)[
0
]
return
strings
.
SplitN
(
name
,
"."
,
2
)[
0
]
}
}
// checksum returns the hex-encoded SHA256 sum of a byte slice
func
checksum
(
bytes
[]
byte
)
string
{
func
checksum
(
bytes
[]
byte
)
string
{
d
:=
sha256
.
Sum256
(
bytes
)
d
:=
sha256
.
Sum256
(
bytes
)
return
hex
.
EncodeToString
(
d
[
:
])
return
hex
.
EncodeToString
(
d
[
:
])
}
}
// isEmptyYaml returns true if a chunk of YAML contains nothing but whitespace, comments, or document separators
func
isEmptyYaml
(
yaml
[]
byte
)
bool
{
func
isEmptyYaml
(
yaml
[]
byte
)
bool
{
isEmpty
:=
true
isEmpty
:=
true
lines
:=
bytes
.
Split
(
yaml
,
[]
byte
(
"
\n
"
))
lines
:=
bytes
.
Split
(
yaml
,
[]
byte
(
"
\n
"
))
...
@@ -257,6 +278,7 @@ func isEmptyYaml(yaml []byte) bool {
...
@@ -257,6 +278,7 @@ func isEmptyYaml(yaml []byte) bool {
return
isEmpty
return
isEmpty
}
}
// yamlToObjects returns an object slice yielded from documents in a chunk of YAML
func
yamlToObjects
(
in
io
.
Reader
)
([]
runtime
.
Object
,
error
)
{
func
yamlToObjects
(
in
io
.
Reader
)
([]
runtime
.
Object
,
error
)
{
var
result
[]
runtime
.
Object
var
result
[]
runtime
.
Object
reader
:=
yamlDecoder
.
NewYAMLReader
(
bufio
.
NewReaderSize
(
in
,
4096
))
reader
:=
yamlDecoder
.
NewYAMLReader
(
bufio
.
NewReaderSize
(
in
,
4096
))
...
@@ -282,6 +304,7 @@ func yamlToObjects(in io.Reader) ([]runtime.Object, error) {
...
@@ -282,6 +304,7 @@ func yamlToObjects(in io.Reader) ([]runtime.Object, error) {
return
result
,
nil
return
result
,
nil
}
}
// Returns one or more objects from a single YAML document
func
toObjects
(
bytes
[]
byte
)
([]
runtime
.
Object
,
error
)
{
func
toObjects
(
bytes
[]
byte
)
([]
runtime
.
Object
,
error
)
{
bytes
,
err
:=
yamlDecoder
.
ToJSON
(
bytes
)
bytes
,
err
:=
yamlDecoder
.
ToJSON
(
bytes
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -305,7 +328,9 @@ func toObjects(bytes []byte) ([]runtime.Object, error) {
...
@@ -305,7 +328,9 @@ func toObjects(bytes []byte) ([]runtime.Object, error) {
return
[]
runtime
.
Object
{
obj
},
nil
return
[]
runtime
.
Object
{
obj
},
nil
}
}
func
skipFile
(
fileName
string
,
skips
map
[
string
]
bool
)
bool
{
// Returns true if a file should be skipped. Skips anything from the provided skip map,
// anything that is a dotfile, and anything that does not have a json/yaml/yml extension.
func
shouldSkipFile
(
fileName
string
,
skips
map
[
string
]
bool
)
bool
{
switch
{
switch
{
case
strings
.
HasPrefix
(
fileName
,
"."
)
:
case
strings
.
HasPrefix
(
fileName
,
"."
)
:
return
true
return
true
...
@@ -318,7 +343,11 @@ func skipFile(fileName string, skips map[string]bool) bool {
...
@@ -318,7 +343,11 @@ func skipFile(fileName string, skips map[string]bool) bool {
}
}
}
}
func
shouldDisableService
(
base
,
fileName
string
,
disables
map
[
string
]
bool
)
bool
{
// Returns true if a file should be disabled, by checking the file basename against a disables map.
// only json/yaml files are checked.
func
shouldDisableFile
(
base
,
fileName
string
,
disables
map
[
string
]
bool
)
bool
{
// Check to see if the file is in a subdirectory that is in the disables map.
// If a file is nested several levels deep, checks 'parent1', 'parent1/parent2', 'parent1/parent2/parent3', etc.
relFile
:=
strings
.
TrimPrefix
(
fileName
,
base
)
relFile
:=
strings
.
TrimPrefix
(
fileName
,
base
)
namePath
:=
strings
.
Split
(
relFile
,
string
(
os
.
PathSeparator
))
namePath
:=
strings
.
Split
(
relFile
,
string
(
os
.
PathSeparator
))
for
i
:=
1
;
i
<
len
(
namePath
);
i
++
{
for
i
:=
1
;
i
<
len
(
namePath
);
i
++
{
...
@@ -330,6 +359,7 @@ func shouldDisableService(base, fileName string, disables map[string]bool) bool
...
@@ -330,6 +359,7 @@ func shouldDisableService(base, fileName string, disables map[string]bool) bool
if
!
util
.
HasSuffixI
(
fileName
,
".yaml"
,
".yml"
,
".json"
)
{
if
!
util
.
HasSuffixI
(
fileName
,
".yaml"
,
".yml"
,
".json"
)
{
return
false
return
false
}
}
// Check the basename against the disables map
baseFile
:=
filepath
.
Base
(
fileName
)
baseFile
:=
filepath
.
Base
(
fileName
)
suffix
:=
filepath
.
Ext
(
baseFile
)
suffix
:=
filepath
.
Ext
(
baseFile
)
baseName
:=
strings
.
TrimSuffix
(
baseFile
,
suffix
)
baseName
:=
strings
.
TrimSuffix
(
baseFile
,
suffix
)
...
...
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