From f6cec238ac6370a3450e3616b1e40d42cd2a5f31 Mon Sep 17 00:00:00 2001
From: Daishan <daishan@rancher.com>
Date: Thu, 18 Feb 2021 20:21:14 -0700
Subject: [PATCH] Add self link mapper

---
 types/mapper/object.go   |  1 +
 types/mapper/selflink.go | 52 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+)
 create mode 100644 types/mapper/selflink.go

diff --git a/types/mapper/object.go b/types/mapper/object.go
index 07503a116..33339908e 100644
--- a/types/mapper/object.go
+++ b/types/mapper/object.go
@@ -13,6 +13,7 @@ func NewObject(mappers ...types.Mapper) Object {
 		Mappers: append([]types.Mapper{
 			&APIGroup{},
 			&Embed{Field: "metadata"},
+			&SelfLink{},
 			&Embed{Field: "spec", Optional: true},
 			&ReadOnly{Field: "status", Optional: true, SubFields: true},
 			Drop{Field: "kind"},
diff --git a/types/mapper/selflink.go b/types/mapper/selflink.go
new file mode 100644
index 000000000..123fe0577
--- /dev/null
+++ b/types/mapper/selflink.go
@@ -0,0 +1,52 @@
+package mapper
+
+import (
+	"github.com/rancher/wrangler/pkg/name"
+	"strings"
+
+	"github.com/rancher/norman/types"
+)
+
+type SelfLink struct {
+	resource   string
+}
+
+func (s *SelfLink) FromInternal(data map[string]interface{}) {
+	sl, ok := data["selfLink"].(string)
+	if !ok || sl == "" {
+		data["selfLink"] = s.selflink(data)
+	}
+}
+
+func (s *SelfLink) ToInternal(data map[string]interface{}) error {
+	return nil
+}
+
+func (s *SelfLink) ModifySchema(schema *types.Schema, schemas *types.Schemas) error {
+	s.resource = name.GuessPluralName(schema.ID)
+	return nil
+}
+
+func (s *SelfLink) selflink(data map[string]interface{}) string {
+	buf := &strings.Builder{}
+	name := data["name"].(string)
+	apiVersion, ok := data["apiVersion"].(string)
+	if !ok || apiVersion == "v1" {
+		buf.WriteString("/api/v1/")
+	} else {
+		buf.WriteString("/apis/")
+		buf.WriteString(apiVersion)
+		buf.WriteString("/")
+	}
+	namespace, ok := data["namespace"].(string)
+	if !ok || namespace != "" {
+		buf.WriteString("namespaces/")
+		buf.WriteString(namespace)
+		buf.WriteString("/")
+	}
+	buf.WriteString(s.resource)
+	buf.WriteString("/")
+	buf.WriteString(name)
+	return buf.String()
+}
+