Split out the Package type into a first class Kubernetes resource (#295)
Split out the Package type into a first class Kubernetes resource. Before this change, packages were implicitly tied to functions. This wasn't ideal because: * Functions will need to share packages * A package storage system may be more generally useful than just functions (for example, for storing static assets) This change does the following: * Updates the fission and tpr types to add a new Package and PackageSpec. It also creates a PackageRef type, and a FunctionPackageRef type. The PackageRef simply references a package, but the FunctionPackageRef includes the name of a function within the package. This allows us to share packages between different functions. * Updates fetcher and other components for first-class packages * Allows customization of fetcher image pull policy in the helm charts
This commit is contained in:
@@ -138,6 +138,13 @@ func configureClient(config *rest.Config) {
|
||||
&api.ListOptions{},
|
||||
&api.DeleteOptions{},
|
||||
)
|
||||
scheme.AddKnownTypes(
|
||||
groupversion,
|
||||
&Package{},
|
||||
&PackageList{},
|
||||
&api.ListOptions{},
|
||||
&api.DeleteOptions{},
|
||||
)
|
||||
return nil
|
||||
})
|
||||
schemeBuilder.AddToScheme(api.Scheme)
|
||||
@@ -193,6 +200,10 @@ func (fc *FissionClient) Timetriggers(ns string) TimetriggerInterface {
|
||||
func (fc *FissionClient) Messagequeuetriggers(ns string) MessagequeuetriggerInterface {
|
||||
return MakeMessagequeuetriggerInterface(fc.tprClient, ns)
|
||||
}
|
||||
func (fc *FissionClient) Packages(ns string) PackageInterface {
|
||||
return MakePackageInterface(fc.tprClient, ns)
|
||||
}
|
||||
|
||||
func (fc *FissionClient) WaitForTPRs() {
|
||||
waitForTPRs(fc.tprClient)
|
||||
}
|
||||
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
Copyright 2016 The Fission 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 tpr
|
||||
|
||||
import (
|
||||
"k8s.io/client-go/1.5/pkg/api"
|
||||
"k8s.io/client-go/1.5/pkg/watch"
|
||||
"k8s.io/client-go/1.5/rest"
|
||||
)
|
||||
|
||||
type (
|
||||
PackageInterface interface {
|
||||
Create(*Package) (*Package, error)
|
||||
Get(name string) (*Package, error)
|
||||
Update(*Package) (*Package, error)
|
||||
Delete(name string, options *api.DeleteOptions) error
|
||||
List(opts api.ListOptions) (*PackageList, error)
|
||||
Watch(opts api.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
packageClient struct {
|
||||
client *rest.RESTClient
|
||||
namespace string
|
||||
}
|
||||
)
|
||||
|
||||
func MakePackageInterface(tprClient *rest.RESTClient, namespace string) PackageInterface {
|
||||
return &packageClient{
|
||||
client: tprClient,
|
||||
namespace: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *packageClient) Create(f *Package) (*Package, error) {
|
||||
var result Package
|
||||
err := c.client.Post().
|
||||
Resource("packages").
|
||||
Namespace(c.namespace).
|
||||
Body(f).
|
||||
Do().Into(&result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
func (c *packageClient) Get(name string) (*Package, error) {
|
||||
var result Package
|
||||
err := c.client.Get().
|
||||
Resource("packages").
|
||||
Namespace(c.namespace).
|
||||
Name(name).
|
||||
Do().Into(&result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
func (c *packageClient) Update(f *Package) (*Package, error) {
|
||||
var result Package
|
||||
err := c.client.Put().
|
||||
Resource("packages").
|
||||
Namespace(c.namespace).
|
||||
Name(f.Metadata.Name).
|
||||
Body(f).
|
||||
Do().Into(&result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
func (c *packageClient) Delete(name string, opts *api.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Namespace(c.namespace).
|
||||
Resource("packages").
|
||||
Name(name).
|
||||
Body(opts).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
func (c *packageClient) List(opts api.ListOptions) (*PackageList, error) {
|
||||
var result PackageList
|
||||
err := c.client.Get().
|
||||
Namespace(c.namespace).
|
||||
Resource("packages").
|
||||
VersionedParams(&opts, api.ParameterCodec).
|
||||
Do().
|
||||
Into(&result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
func (c *packageClient) Watch(opts api.ListOptions) (watch.Interface, error) {
|
||||
return c.client.Get().
|
||||
Prefix("watch").
|
||||
Namespace(c.namespace).
|
||||
Resource("packages").
|
||||
VersionedParams(&opts, api.ParameterCodec).
|
||||
Watch()
|
||||
}
|
||||
@@ -95,6 +95,15 @@ func EnsureFissionTPRs(clientset *kubernetes.Clientset) error {
|
||||
},
|
||||
Description: "Message queue triggers for functions",
|
||||
},
|
||||
{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "package.fission.io",
|
||||
},
|
||||
Versions: []v1beta1.APIVersion{
|
||||
{Name: "v1"},
|
||||
},
|
||||
Description: "Packages: archives containing source or binaries for one or more functions",
|
||||
},
|
||||
}
|
||||
for _, tpr := range tprs {
|
||||
err := ensureTPR(clientset, &tpr)
|
||||
|
||||
+8
-4
@@ -46,9 +46,13 @@ func functionTests(tprClient *rest.RESTClient) {
|
||||
Name: "hello",
|
||||
},
|
||||
Spec: fission.FunctionSpec{
|
||||
Source: fission.Package{},
|
||||
Deployment: fission.Package{
|
||||
Literal: []byte("hi"),
|
||||
Source: fission.FunctionPackageRef{},
|
||||
Deployment: fission.FunctionPackageRef{
|
||||
PackageRef: fission.PackageRef{
|
||||
Name: "foo",
|
||||
Namespace: "bar",
|
||||
},
|
||||
FunctionName: "hello",
|
||||
},
|
||||
EnvironmentName: "xxx",
|
||||
},
|
||||
@@ -70,7 +74,7 @@ func functionTests(tprClient *rest.RESTClient) {
|
||||
// read
|
||||
f, err = fi.Get(function.Metadata.Name)
|
||||
panicIf(err)
|
||||
if len(f.Spec.Deployment.Literal) != len(function.Spec.Deployment.Literal) {
|
||||
if f.Spec.Deployment.FunctionName != function.Spec.Deployment.FunctionName {
|
||||
log.Panicf("Bad result from Get: %v", f)
|
||||
}
|
||||
|
||||
|
||||
+27
-5
@@ -33,9 +33,24 @@ import (
|
||||
// 5. Add the type to configureClient in client.go
|
||||
// 6. Add the type to EnsureFissionTPRs in tpr.go
|
||||
// 7. Add tests to tpr_test.go
|
||||
// 8. Add a CRUD Interface type (analogous to FunctionInterface in function.go)
|
||||
// 9. Add a getter method for your interface type to FissionClient in client.go
|
||||
//
|
||||
|
||||
type (
|
||||
// Packages. Think of these as function-level images.
|
||||
Package struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
Metadata api.ObjectMeta `json:"metadata"`
|
||||
Spec fission.PackageSpec `json:"spec"`
|
||||
}
|
||||
PackageList struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
Metadata unversioned.ListMeta `json:"metadata"`
|
||||
|
||||
Items []Package `json:"items"`
|
||||
}
|
||||
|
||||
// Functions.
|
||||
Function struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
@@ -144,6 +159,9 @@ func (w *Timetrigger) GetObjectKind() unversioned.ObjectKind {
|
||||
func (w *Messagequeuetrigger) GetObjectKind() unversioned.ObjectKind {
|
||||
return &w.TypeMeta
|
||||
}
|
||||
func (w *Package) GetObjectKind() unversioned.ObjectKind {
|
||||
return &w.TypeMeta
|
||||
}
|
||||
|
||||
func (f *Function) GetObjectMeta() meta.Object {
|
||||
return &f.Metadata
|
||||
@@ -163,6 +181,9 @@ func (w *Timetrigger) GetObjectMeta() meta.Object {
|
||||
func (w *Messagequeuetrigger) GetObjectMeta() meta.Object {
|
||||
return &w.Metadata
|
||||
}
|
||||
func (w *Package) GetObjectMeta() meta.Object {
|
||||
return &w.Metadata
|
||||
}
|
||||
|
||||
func (fl *FunctionList) GetObjectKind() unversioned.ObjectKind {
|
||||
return &fl.TypeMeta
|
||||
@@ -182,6 +203,9 @@ func (wl *TimetriggerList) GetObjectKind() unversioned.ObjectKind {
|
||||
func (wl *MessagequeuetriggerList) GetObjectKind() unversioned.ObjectKind {
|
||||
return &wl.TypeMeta
|
||||
}
|
||||
func (wl *PackageList) GetObjectKind() unversioned.ObjectKind {
|
||||
return &wl.TypeMeta
|
||||
}
|
||||
|
||||
func (fl *FunctionList) GetListMeta() unversioned.List {
|
||||
return &fl.Metadata
|
||||
@@ -201,8 +225,6 @@ func (wl *TimetriggerList) GetListMeta() unversioned.List {
|
||||
func (wl *MessagequeuetriggerList) GetListMeta() unversioned.List {
|
||||
return &wl.Metadata
|
||||
}
|
||||
|
||||
// In the client-go TPR example, UnmarshalJSON is defined here for the
|
||||
// singular and list types. That's supposed to be a workaround for
|
||||
// some ugorji bug. But we don't seem to need it, and all our tests
|
||||
// pass without it, so we don't define any UnmarshalJSON methods.
|
||||
func (wl *PackageList) GetListMeta() unversioned.List {
|
||||
return &wl.Metadata
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user