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
1d666d95
Commit
1d666d95
authored
Feb 04, 2019
by
Darren Shepherd
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add helm controller
parent
e8325886
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
374 additions
and
10 deletions
+374
-10
nginx-ingress.yaml
manifests/nginx-ingress.yaml
+7
-0
controller.go
pkg/helm/controller.go
+309
-0
server.go
pkg/server/server.go
+7
-0
schema.go
types/apis/k3s.cattle.io/v1/schema.go
+3
-2
types.go
types/apis/k3s.cattle.io/v1/types.go
+24
-0
main.go
types/codegen/main.go
+24
-8
No files found.
manifests/nginx-ingress.yaml
0 → 100644
View file @
1d666d95
apiVersion
:
k3s.cattle.io/v1
kind
:
HelmChart
metadata
:
name
:
nginx-ingress
namespace
:
kube-system
spec
:
chart
:
stable/nginx-ingress
pkg/helm/controller.go
0 → 100644
View file @
1d666d95
package
helm
import
(
"context"
"fmt"
"sort"
batchclient
"github.com/rancher/k3s/types/apis/batch/v1"
coreclient
"github.com/rancher/k3s/types/apis/core/v1"
k3s
"github.com/rancher/k3s/types/apis/k3s.cattle.io/v1"
rbacclients
"github.com/rancher/k3s/types/apis/rbac.authorization.k8s.io/v1"
"github.com/rancher/norman/pkg/changeset"
"github.com/rancher/norman/pkg/objectset"
batch
"k8s.io/api/batch/v1"
core
"k8s.io/api/core/v1"
rbac
"k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/errors"
meta
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/intstr"
)
const
(
namespace
=
"kube-system"
image
=
"rancher/klipper-helm:v0.1.0"
label
=
"helm.k3s.cattle.io/chart"
)
var
(
trueVal
=
true
)
func
Register
(
ctx
context
.
Context
)
error
{
k3sClients
:=
k3s
.
ClientsFrom
(
ctx
)
coreClients
:=
coreclient
.
ClientsFrom
(
ctx
)
jobClients
:=
batchclient
.
ClientsFrom
(
ctx
)
rbacClients
:=
rbacclients
.
ClientsFrom
(
ctx
)
h
:=
&
handler
{
jobs
:
jobClients
.
Job
,
jobCache
:
jobClients
.
Job
.
Cache
(),
processor
:
objectset
.
NewProcessor
(
"k3s.helm"
)
.
Client
(
coreClients
.
ConfigMap
)
.
Client
(
coreClients
.
ServiceAccount
)
.
Client
(
jobClients
.
Job
)
.
Client
(
rbacClients
.
ClusterRoleBinding
)
.
Patcher
(
batch
.
SchemeGroupVersion
.
WithKind
(
"Job"
),
objectset
.
ReplaceOnChange
),
}
k3sClients
.
HelmChart
.
OnChange
(
ctx
,
"helm"
,
h
.
onChange
)
k3sClients
.
HelmChart
.
OnRemove
(
ctx
,
"helm"
,
h
.
onRemove
)
changeset
.
Watch
(
ctx
,
"helm-pod-watch"
,
func
(
namespace
,
name
string
,
obj
runtime
.
Object
)
([]
changeset
.
Key
,
error
)
{
if
job
,
ok
:=
obj
.
(
*
batch
.
Job
);
ok
{
name
:=
job
.
Labels
[
label
]
if
name
!=
""
{
return
[]
changeset
.
Key
{
{
Name
:
name
,
Namespace
:
namespace
,
},
},
nil
}
}
return
nil
,
nil
},
k3sClients
.
HelmChart
,
jobClients
.
Job
)
return
nil
}
type
handler
struct
{
jobCache
batchclient
.
JobClientCache
jobs
batchclient
.
JobClient
processor
*
objectset
.
Processor
}
func
(
h
*
handler
)
onChange
(
chart
*
k3s
.
HelmChart
)
(
runtime
.
Object
,
error
)
{
if
chart
.
Namespace
!=
namespace
||
chart
.
Spec
.
Chart
==
""
{
return
chart
,
nil
}
objs
:=
objectset
.
NewObjectSet
()
job
,
configMap
:=
job
(
chart
)
objs
.
Add
(
serviceAccount
(
chart
))
objs
.
Add
(
roleBinding
(
chart
))
objs
.
Add
(
job
)
if
configMap
!=
nil
{
objs
.
Add
(
configMap
)
}
if
err
:=
h
.
processor
.
NewDesiredSet
(
chart
,
objs
)
.
Apply
();
err
!=
nil
{
return
chart
,
err
}
chart
.
Status
.
JobName
=
job
.
Name
return
chart
,
nil
}
func
(
h
*
handler
)
onRemove
(
chart
*
k3s
.
HelmChart
)
(
runtime
.
Object
,
error
)
{
if
chart
.
Namespace
!=
namespace
||
chart
.
Spec
.
Chart
==
""
{
return
chart
,
nil
}
job
,
_
:=
job
(
chart
)
job
,
err
:=
h
.
jobCache
.
Get
(
chart
.
Namespace
,
job
.
Name
)
if
errors
.
IsNotFound
(
err
)
{
_
,
err
:=
h
.
onChange
(
chart
)
if
err
!=
nil
{
return
chart
,
err
}
}
else
if
err
!=
nil
{
return
nil
,
err
}
if
job
.
Status
.
Succeeded
<=
0
{
return
nil
,
fmt
.
Errorf
(
"waiting for delete of helm chart %s"
,
chart
.
Name
)
}
return
chart
,
h
.
processor
.
NewDesiredSet
(
chart
,
objectset
.
NewObjectSet
())
.
Apply
()
}
func
job
(
chart
*
k3s
.
HelmChart
)
(
*
batch
.
Job
,
*
core
.
ConfigMap
)
{
action
:=
"install"
if
chart
.
DeletionTimestamp
!=
nil
{
action
=
"delete"
}
job
:=
&
batch
.
Job
{
TypeMeta
:
meta
.
TypeMeta
{
APIVersion
:
"batch/v1"
,
Kind
:
"Job"
,
},
ObjectMeta
:
meta
.
ObjectMeta
{
Name
:
fmt
.
Sprintf
(
"helm-%s-%s"
,
action
,
chart
.
Name
),
Namespace
:
chart
.
Namespace
,
Labels
:
map
[
string
]
string
{
label
:
chart
.
Name
,
},
},
Spec
:
batch
.
JobSpec
{
Template
:
core
.
PodTemplateSpec
{
ObjectMeta
:
meta
.
ObjectMeta
{
Labels
:
map
[
string
]
string
{
label
:
chart
.
Name
,
},
},
Spec
:
core
.
PodSpec
{
RestartPolicy
:
core
.
RestartPolicyOnFailure
,
Containers
:
[]
core
.
Container
{
{
Name
:
"helm"
,
Image
:
image
,
ImagePullPolicy
:
core
.
PullAlways
,
Args
:
args
(
chart
),
Env
:
[]
core
.
EnvVar
{
{
Name
:
"NAME"
,
Value
:
chart
.
Name
,
},
{
Name
:
"VERSION"
,
Value
:
chart
.
Spec
.
Version
,
},
{
Name
:
"REPO"
,
Value
:
chart
.
Spec
.
Repo
,
},
},
},
},
ServiceAccountName
:
fmt
.
Sprintf
(
"helm-%s"
,
chart
.
Name
),
},
},
},
}
configMap
:=
configMap
(
chart
)
if
configMap
==
nil
{
return
job
,
nil
}
job
.
Spec
.
Template
.
Spec
.
Volumes
=
[]
core
.
Volume
{
{
Name
:
"values"
,
VolumeSource
:
core
.
VolumeSource
{
ConfigMap
:
&
core
.
ConfigMapVolumeSource
{
LocalObjectReference
:
core
.
LocalObjectReference
{
Name
:
configMap
.
Name
,
},
},
},
},
}
job
.
Spec
.
Template
.
Spec
.
Containers
[
0
]
.
VolumeMounts
=
[]
core
.
VolumeMount
{
{
MountPath
:
"/config"
,
Name
:
"values"
,
},
}
return
job
,
configMap
}
func
configMap
(
chart
*
k3s
.
HelmChart
)
*
core
.
ConfigMap
{
if
chart
.
Spec
.
ValuesContent
==
""
{
return
nil
}
return
&
core
.
ConfigMap
{
TypeMeta
:
meta
.
TypeMeta
{
APIVersion
:
"v1"
,
Kind
:
"ConfigMap"
,
},
ObjectMeta
:
meta
.
ObjectMeta
{
Name
:
fmt
.
Sprintf
(
"chart-values-%s"
,
chart
.
Name
),
Namespace
:
chart
.
Namespace
,
},
Data
:
map
[
string
]
string
{
"values.yaml"
:
chart
.
Spec
.
ValuesContent
,
},
}
}
func
roleBinding
(
chart
*
k3s
.
HelmChart
)
*
rbac
.
ClusterRoleBinding
{
return
&
rbac
.
ClusterRoleBinding
{
TypeMeta
:
meta
.
TypeMeta
{
APIVersion
:
"rbac.authorization.k8s.io/v1"
,
Kind
:
"ClusterRoleBinding"
,
},
ObjectMeta
:
meta
.
ObjectMeta
{
Name
:
fmt
.
Sprintf
(
"helm-%s-%s"
,
chart
.
Namespace
,
chart
.
Name
),
},
RoleRef
:
rbac
.
RoleRef
{
Kind
:
"ClusterRole"
,
APIGroup
:
"rbac.authorization.k8s.io"
,
Name
:
"cluster-admin"
,
},
Subjects
:
[]
rbac
.
Subject
{
{
Name
:
fmt
.
Sprintf
(
"helm-%s"
,
chart
.
Name
),
Kind
:
"ServiceAccount"
,
Namespace
:
chart
.
Namespace
,
},
},
}
}
func
serviceAccount
(
chart
*
k3s
.
HelmChart
)
*
core
.
ServiceAccount
{
return
&
core
.
ServiceAccount
{
TypeMeta
:
meta
.
TypeMeta
{
APIVersion
:
"v1"
,
Kind
:
"ServiceAccount"
,
},
ObjectMeta
:
meta
.
ObjectMeta
{
Name
:
fmt
.
Sprintf
(
"helm-%s"
,
chart
.
Name
),
Namespace
:
chart
.
Namespace
,
},
AutomountServiceAccountToken
:
&
trueVal
,
}
}
func
args
(
chart
*
k3s
.
HelmChart
)
[]
string
{
if
chart
.
DeletionTimestamp
!=
nil
{
return
[]
string
{
"delete"
,
"--purge"
,
chart
.
Name
,
}
}
spec
:=
chart
.
Spec
args
:=
[]
string
{
"install"
,
"--name"
,
chart
.
Name
,
spec
.
Chart
,
}
if
spec
.
TargetNamespace
!=
""
{
args
=
append
(
args
,
"--namespace"
,
spec
.
TargetNamespace
)
}
if
spec
.
Repo
!=
""
{
args
=
append
(
args
,
"--repo"
,
spec
.
Repo
)
}
if
spec
.
Version
!=
""
{
args
=
append
(
args
,
"--version"
,
spec
.
Version
)
}
for
_
,
k
:=
range
keys
(
spec
.
Set
)
{
val
:=
spec
.
Set
[
k
]
if
val
.
StrVal
!=
""
{
args
=
append
(
args
,
"--set-string"
,
fmt
.
Sprintf
(
"%s=%s"
,
k
,
val
.
StrVal
))
}
else
{
args
=
append
(
args
,
"--set"
,
fmt
.
Sprintf
(
"%s=%d"
,
k
,
val
.
IntVal
))
}
}
return
args
}
func
keys
(
val
map
[
string
]
intstr
.
IntOrString
)
[]
string
{
var
keys
[]
string
for
k
:=
range
val
{
keys
=
append
(
keys
,
k
)
}
sort
.
Strings
(
keys
)
return
keys
}
pkg/server/server.go
View file @
1d666d95
...
@@ -17,11 +17,14 @@ import (
...
@@ -17,11 +17,14 @@ import (
"github.com/rancher/k3s/pkg/daemons/config"
"github.com/rancher/k3s/pkg/daemons/config"
"github.com/rancher/k3s/pkg/daemons/control"
"github.com/rancher/k3s/pkg/daemons/control"
"github.com/rancher/k3s/pkg/deploy"
"github.com/rancher/k3s/pkg/deploy"
"github.com/rancher/k3s/pkg/helm"
"github.com/rancher/k3s/pkg/servicelb"
"github.com/rancher/k3s/pkg/servicelb"
"github.com/rancher/k3s/pkg/tls"
"github.com/rancher/k3s/pkg/tls"
appsv1
"github.com/rancher/k3s/types/apis/apps/v1"
appsv1
"github.com/rancher/k3s/types/apis/apps/v1"
batchv1
"github.com/rancher/k3s/types/apis/batch/v1"
corev1
"github.com/rancher/k3s/types/apis/core/v1"
corev1
"github.com/rancher/k3s/types/apis/core/v1"
v1
"github.com/rancher/k3s/types/apis/k3s.cattle.io/v1"
v1
"github.com/rancher/k3s/types/apis/k3s.cattle.io/v1"
rbacv1
"github.com/rancher/k3s/types/apis/rbac.authorization.k8s.io/v1"
"github.com/rancher/norman"
"github.com/rancher/norman"
"github.com/rancher/norman/pkg/clientaccess"
"github.com/rancher/norman/pkg/clientaccess"
"github.com/rancher/norman/pkg/dynamiclistener"
"github.com/rancher/norman/pkg/dynamiclistener"
...
@@ -91,6 +94,8 @@ func startNorman(ctx context.Context, config *Config) (string, error) {
...
@@ -91,6 +94,8 @@ func startNorman(ctx context.Context, config *Config) (string, error) {
v1
.
Factory
,
v1
.
Factory
,
appsv1
.
Factory
,
appsv1
.
Factory
,
corev1
.
Factory
,
corev1
.
Factory
,
batchv1
.
Factory
,
rbacv1
.
Factory
,
},
},
Schemas
:
[]
*
types
.
Schemas
{
Schemas
:
[]
*
types
.
Schemas
{
v1
.
Schemas
,
v1
.
Schemas
,
...
@@ -99,6 +104,7 @@ func startNorman(ctx context.Context, config *Config) (string, error) {
...
@@ -99,6 +104,7 @@ func startNorman(ctx context.Context, config *Config) (string, error) {
&
v1
.
APIVersion
:
{
&
v1
.
APIVersion
:
{
v1
.
ListenerConfigGroupVersionKind
.
Kind
,
v1
.
ListenerConfigGroupVersionKind
.
Kind
,
v1
.
AddonGroupVersionKind
.
Kind
,
v1
.
AddonGroupVersionKind
.
Kind
,
v1
.
HelmChartGroupVersionKind
.
Kind
,
},
},
},
},
IgnoredKubeConfigEnv
:
true
,
IgnoredKubeConfigEnv
:
true
,
...
@@ -108,6 +114,7 @@ func startNorman(ctx context.Context, config *Config) (string, error) {
...
@@ -108,6 +114,7 @@ func startNorman(ctx context.Context, config *Config) (string, error) {
},
},
DisableLeaderElection
:
true
,
DisableLeaderElection
:
true
,
MasterControllers
:
[]
norman
.
ControllerRegister
{
MasterControllers
:
[]
norman
.
ControllerRegister
{
helm
.
Register
,
func
(
ctx
context
.
Context
)
error
{
func
(
ctx
context
.
Context
)
error
{
return
servicelb
.
Register
(
ctx
,
norman
.
GetServer
(
ctx
)
.
K8sClient
,
!
config
.
DisableServiceLB
)
return
servicelb
.
Register
(
ctx
,
norman
.
GetServer
(
ctx
)
.
K8sClient
,
!
config
.
DisableServiceLB
)
},
},
...
...
types/apis/k3s.cattle.io/v1/schema.go
View file @
1d666d95
...
@@ -13,6 +13,7 @@ var (
...
@@ -13,6 +13,7 @@ var (
}
}
Schemas
=
factory
.
Schemas
(
&
APIVersion
)
.
Schemas
=
factory
.
Schemas
(
&
APIVersion
)
.
MustImport
(
&
APIVersion
,
ListenerConfig
{})
.
MustImport
(
&
APIVersion
,
Addon
{})
.
MustImport
(
&
APIVersion
,
Addon
{})
MustImport
(
&
APIVersion
,
HelmChart
{})
.
MustImport
(
&
APIVersion
,
ListenerConfig
{})
)
)
types/apis/k3s.cattle.io/v1/types.go
View file @
1d666d95
...
@@ -5,6 +5,7 @@ import (
...
@@ -5,6 +5,7 @@ import (
"github.com/rancher/norman/types"
"github.com/rancher/norman/types"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/intstr"
)
)
type
ListenerConfig
struct
{
type
ListenerConfig
struct
{
...
@@ -34,3 +35,26 @@ type AddonSpec struct {
...
@@ -34,3 +35,26 @@ type AddonSpec struct {
type
AddonStatus
struct
{
type
AddonStatus
struct
{
GVKs
[]
schema
.
GroupVersionKind
`json:"gvks,omitempty"`
GVKs
[]
schema
.
GroupVersionKind
`json:"gvks,omitempty"`
}
}
type
HelmChart
struct
{
types
.
Namespaced
metav1
.
TypeMeta
`json:",inline"`
metav1
.
ObjectMeta
`json:"metadata,omitempty"`
Spec
HelmChartSpec
`json:"spec,omitempty"`
Status
HelmChartStatus
`json:"status,omitempty"`
}
type
HelmChartSpec
struct
{
TargetNamespace
string
`json:"targetNamespace,omitempty"`
Chart
string
`json:"chart,omitempty"`
Version
string
`json:"version,omitempty"`
Repo
string
`json:"repo,omitempty"`
Set
map
[
string
]
intstr
.
IntOrString
`json:"set,omitempty"`
ValuesContent
string
`json:"valuesContent,omitempty"`
}
type
HelmChartStatus
struct
{
JobName
string
`json:"jobName,omitempty"`
}
types/codegen/main.go
View file @
1d666d95
...
@@ -5,8 +5,10 @@ import (
...
@@ -5,8 +5,10 @@ import (
v1
"github.com/rancher/k3s/types/apis/k3s.cattle.io/v1"
v1
"github.com/rancher/k3s/types/apis/k3s.cattle.io/v1"
"github.com/rancher/norman/generator"
"github.com/rancher/norman/generator"
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus"
v13
"k8s.io/api/apps/v1"
appsv1
"k8s.io/api/apps/v1"
v12
"k8s.io/api/core/v1"
batchv1
"k8s.io/api/batch/v1"
corev1
"k8s.io/api/core/v1"
rbacv1
"k8s.io/api/rbac/v1"
)
)
var
(
var
(
...
@@ -68,18 +70,32 @@ func main() {
...
@@ -68,18 +70,32 @@ func main() {
logrus
.
Fatal
(
err
)
logrus
.
Fatal
(
err
)
}
}
if
err
:=
generator
.
ControllersForForeignTypes
(
basePackage
,
v12
.
SchemeGroupVersion
,
[]
interface
{}{
if
err
:=
generator
.
ControllersForForeignTypes
(
basePackage
,
corev1
.
SchemeGroupVersion
,
[]
interface
{}{
v12
.
Service
{},
corev1
.
ServiceAccount
{},
v12
.
Pod
{},
corev1
.
Service
{},
corev1
.
Pod
{},
corev1
.
ConfigMap
{},
},
[]
interface
{}{
},
[]
interface
{}{
v12
.
Node
{},
corev1
.
Node
{},
});
err
!=
nil
{
});
err
!=
nil
{
logrus
.
Fatal
(
err
)
logrus
.
Fatal
(
err
)
}
}
if
err
:=
generator
.
ControllersForForeignTypes
(
basePackage
,
v13
.
SchemeGroupVersion
,
[]
interface
{}{
if
err
:=
generator
.
ControllersForForeignTypes
(
basePackage
,
appsv1
.
SchemeGroupVersion
,
[]
interface
{}{
v13
.
Deployment
{},
appsv1
.
Deployment
{},
},
nil
);
err
!=
nil
{
},
nil
);
err
!=
nil
{
logrus
.
Fatal
(
err
)
logrus
.
Fatal
(
err
)
}
}
if
err
:=
generator
.
ControllersForForeignTypes
(
basePackage
,
batchv1
.
SchemeGroupVersion
,
[]
interface
{}{
batchv1
.
Job
{},
},
nil
);
err
!=
nil
{
logrus
.
Fatal
(
err
)
}
if
err
:=
generator
.
ControllersForForeignTypes
(
basePackage
,
rbacv1
.
SchemeGroupVersion
,
nil
,
[]
interface
{}{
rbacv1
.
ClusterRoleBinding
{},
});
err
!=
nil
{
logrus
.
Fatal
(
err
)
}
}
}
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