forked from tektoncd/triggers
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor functions to not be members of Sink 🚰
Just like with reconcilers / controllers, adding functions of as members of the Sink (or controller) object itself has some downsides: it's hard to tell what the responsibilities of the functions are and how they are coupled to the Sink, and it's harder to write more focused unit tests. I am working on tektoncd#258 in another branch and in that branch I wanted to make some updates to the unit tests for this logic; it's easier to do if it's factored out a bit. There is more factoring we can do here: now that the functions are moved out of Sink we can make decisions around their interfaces and maybe make them even more focused and unit testable. (Though it was a happy surprise to see they were unit tested even though they were members of Sink!)
- Loading branch information
1 parent
e6881e2
commit 5af787c
Showing
5 changed files
with
478 additions
and
381 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
/* | ||
Copyright 2019 The Tekton 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 resources | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"strings" | ||
|
||
"k8s.io/client-go/dynamic" | ||
|
||
"go.uber.org/zap" | ||
|
||
"golang.org/x/xerrors" | ||
|
||
triggersv1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1" | ||
"github.com/tidwall/sjson" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" | ||
"k8s.io/apimachinery/pkg/runtime/schema" | ||
discoveryclient "k8s.io/client-go/discovery" | ||
) | ||
|
||
// FindAPIResource returns the APIResource definition using the discovery client c. | ||
func FindAPIResource(apiVersion, kind string, c discoveryclient.ServerResourcesInterface) (*metav1.APIResource, error) { | ||
//resourceList, err := r.DiscoveryClient.ServerResourcesForGroupVersion(apiVersion) | ||
resourceList, err := c.ServerResourcesForGroupVersion(apiVersion) | ||
if err != nil { | ||
return nil, xerrors.Errorf("Error getting kubernetes server resources for apiVersion %s: %s", apiVersion, err) | ||
} | ||
for _, apiResource := range resourceList.APIResources { | ||
if apiResource.Kind != kind { | ||
continue | ||
} | ||
r := &apiResource | ||
// Resolve GroupVersion from parent list to have consistent resource identifiers. | ||
if r.Version == "" || r.Group == "" { | ||
gv, err := schema.ParseGroupVersion(resourceList.GroupVersion) | ||
if err != nil { | ||
return nil, xerrors.Errorf("error parsing parsing GroupVersion: %v", err) | ||
} | ||
r.Group = gv.Group | ||
r.Version = gv.Version | ||
} | ||
return r, nil | ||
} | ||
return nil, xerrors.Errorf("Error could not find resource with apiVersion %s and kind %s", apiVersion, kind) | ||
} | ||
|
||
// Create uses the kubeClient to create the resource defined in the | ||
// TriggerResourceTemplate and returns any errors with this process | ||
func Create(logger *zap.SugaredLogger, rt json.RawMessage, triggerName, eventID, elName, elNamespace string, c discoveryclient.ServerResourcesInterface, dc dynamic.Interface) error { | ||
rt, err := AddLabels(rt, map[string]string{ | ||
triggersv1.EventListenerLabelKey: elName, | ||
triggersv1.EventIDLabelKey: eventID, | ||
triggersv1.TriggerLabelKey: triggerName, | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Assume the TriggerResourceTemplate is valid (it has an apiVersion and Kind) | ||
data := new(unstructured.Unstructured) | ||
if err := data.UnmarshalJSON(rt); err != nil { | ||
return err | ||
} | ||
|
||
namespace := data.GetNamespace() | ||
// Default the resource creation to the EventListenerNamespace if not found in the resource template | ||
if namespace == "" { | ||
namespace = elNamespace | ||
} | ||
|
||
// Resolve resource kind to the underlying API Resource type. | ||
apiResource, err := FindAPIResource(data.GetAPIVersion(), data.GetKind(), c) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
name := data.GetName() | ||
if name == "" { | ||
name = data.GetGenerateName() | ||
} | ||
logger.Infof("Generating resource: kind: %+v, name: %s", apiResource, name) | ||
|
||
gvr := schema.GroupVersionResource{ | ||
Group: apiResource.Group, | ||
Version: apiResource.Version, | ||
Resource: apiResource.Name, | ||
} | ||
|
||
_, err = dc.Resource(gvr).Namespace(namespace).Create(data, metav1.CreateOptions{}) | ||
return err | ||
} | ||
|
||
// AddLabels adds autogenerated Tekton labels to created resources. | ||
func AddLabels(rt json.RawMessage, labels map[string]string) (json.RawMessage, error) { | ||
var err error | ||
for k, v := range labels { | ||
l := fmt.Sprintf("metadata.labels.%s/%s", triggersv1.LabelEscape, strings.TrimLeft(k, "/")) | ||
rt, err = sjson.SetBytes(rt, l, v) | ||
if err != nil { | ||
return rt, err | ||
} | ||
} | ||
return rt, err | ||
} |
Oops, something went wrong.