Skip to content

Commit

Permalink
chore: continued on filtering out unneeded fields when doing an apply
Browse files Browse the repository at this point in the history
  • Loading branch information
rhuss committed Sep 9, 2020
1 parent 9f320fc commit 22ffd28
Showing 1 changed file with 107 additions and 12 deletions.
119 changes: 107 additions & 12 deletions pkg/kn/commands/service/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,17 +154,109 @@ func encodeService(service *servingv1.Service) ([]byte, error) {
return nil, err
}

// Remove/adapt service so that it can be used in the apply-annotation
cleanupServiceUnstructured(serviceUnstructured)

// Try to cleanup
// delete(serviceUnstructured.Object["spec"].(map[string]interface{})["template"].(map[string]interface{})["spec"].(map[string]interface{})["containers"].([]interface{})[0].(map[string]interface{}),"name")
return runtime.Encode(encoder, serviceUnstructured)
}

func cleanupServiceUnstructured(uService *unstructured.Unstructured) {
// Set container name if not set
setUserContainerIfNotSet(uService.Object)
clearCreationTimestamps(uService.Object)
removeStatus(uService.Object)
removeResourcesIfNotSet(uService.Object)

}

func removeResourcesIfNotSet(uService map[string]interface{}) {
uContainer := extractUserContainer(uService)
if uContainer == nil {
return
}
resources := uContainer["resources"]
if resources == nil {
return
}
resourcesMap := resources.(map[string]interface{})
if len(resourcesMap) == 0 {
delete(uContainer, "resources")
}
}

func extractUserContainer(uService map[string]interface{}) map[string]interface{} {
tSpec := extractTemplateSpec(uService)
if tSpec == nil {
return nil
}
containers := tSpec["containers"]
if len(containers.([]interface{})) == 0 {
return nil
}
return containers.([]interface{})[0].(map[string]interface{})
}

func removeStatus(uService map[string]interface{}) {
delete(uService, "status")
}

func clearCreationTimestamps(uService map[string]interface{}) {
meta := uService["metadata"]
if meta != nil {
delete(meta.(map[string]interface{}), "creationTimestamp")
}
template := extractTemplate(uService)
if template != nil {
meta = template["metadata"]
if meta != nil {
delete(meta.(map[string]interface{}), "creationTimestamp")
}
}
}

func setUserContainerIfNotSet(uService map[string]interface{}) {
container := extractUserContainer(uService)
if container == nil {
return
}
if container["name"] == nil || container["name"].(string) == "" {
container["name"] = "user-container"
}
}

func extractTemplateSpec(uService map[string]interface{}) map[string]interface{} {
templ := extractTemplate(uService)
if templ == nil {
return nil
}
templSpec := templ["spec"]
if templSpec == nil {
return nil
}

return templSpec.(map[string]interface{})
}

func extractTemplate(uService map[string]interface{}) map[string]interface{} {
spec := uService["spec"]
if spec == nil {
return nil
}
templ := spec.(map[string]interface{})["template"]
if templ == nil {
return nil
}
return templ.(map[string]interface{})
}

func patch(client clientservingv1.KnServingClient, service *servingv1.Service, current *servingv1.Service) (bool, error) {
modified, err := getModifiedConfiguration(service, true)
uModified, err := getModifiedConfiguration(service, true)
if err != nil {
return false, err
}
patchBytes, err := patchSimple(client, current, modified)
patchBytes, err := patchSimple(client, current, uModified)
for i := 1; i <= 5 && apierrors.IsConflict(err); i++ {
if i > 1 {
time.Sleep(1 * time.Second)
Expand All @@ -173,7 +265,7 @@ func patch(client clientservingv1.KnServingClient, service *servingv1.Service, c
if err != nil {
return false, err
}
patchBytes, err = patchSimple(client, current, modified)
patchBytes, err = patchSimple(client, current, uModified)
}

// TODO: Introduce a "force" parameter that would do the same as `kn service create --force`
Expand All @@ -185,15 +277,15 @@ func patch(client clientservingv1.KnServingClient, service *servingv1.Service, c
return string(patchBytes) != "{}", err
}

func patchSimple(client clientservingv1.KnServingClient, service *servingv1.Service, modified []byte) ([]byte, error) {
func patchSimple(client clientservingv1.KnServingClient, service *servingv1.Service, uModified []byte) ([]byte, error) {
// Serialize the current configuration of the object from the server.
current, err := encodeService(service)
uCurrent, err := encodeService(service)
if err != nil {
return nil, err
}

// Retrieve the original configuration of the object from the annotation.
original := getOriginalConfiguration(service)
uOriginal := getOriginalConfiguration(service)

var patch []byte

Expand All @@ -203,7 +295,7 @@ func patchSimple(client clientservingv1.KnServingClient, service *servingv1.Serv
return nil, err
}
// TODO: Allow "overwrite" to be configured
patch, err = strategicpatch.CreateThreeWayMergePatch(original, modified, current, lookupPatchMeta, false)
patch, err = strategicpatch.CreateThreeWayMergePatch(uOriginal, uModified, uCurrent, lookupPatchMeta, false)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -239,9 +331,10 @@ func getOriginalConfiguration(service *servingv1.Service) []byte {
}

func getModifiedConfiguration(service *servingv1.Service, annotate bool) ([]byte, error) {

// First serialize the object without the annotation to prevent recursion,
// then add that serialization to it as the annotation and serialize it again.
var modified []byte
var uModifiedService []byte

// Otherwise, use the server side version of the object.
// Get the current annotations from the object.
Expand All @@ -254,15 +347,17 @@ func getModifiedConfiguration(service *servingv1.Service, annotate bool) ([]byte
delete(annots, v1.LastAppliedConfigAnnotation)
service.Annotations = annots

modified, err := encodeService(service)
service.Spec.Template.Spec.Containers[0].Name = "user-container"

uModifiedService, err := encodeService(service)
if err != nil {
return nil, err
}

if annotate {
annots[v1.LastAppliedConfigAnnotation] = string(modified)
annots[v1.LastAppliedConfigAnnotation] = string(uModifiedService)
service.Annotations = annots
modified, err = encodeService(service)
uModifiedService, err = encodeService(service)
if err != nil {
return nil, err
}
Expand All @@ -271,7 +366,7 @@ func getModifiedConfiguration(service *servingv1.Service, annotate bool) ([]byte
// Restore the object to its original condition.
annots[v1.LastAppliedConfigAnnotation] = original
service.Annotations = annots
return modified, nil
return uModifiedService, nil
}

// SetOriginalConfiguration sets the original configuration of the object
Expand Down

0 comments on commit 22ffd28

Please sign in to comment.