Skip to content

Commit

Permalink
implement for #401
Browse files Browse the repository at this point in the history
  • Loading branch information
ShotaKitazawa committed Jan 20, 2024
1 parent a1a073f commit 5a2a866
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 55 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ go 1.21

require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/elliotchance/orderedmap/v2 v2.2.0
github.com/form3tech-oss/jwt-go v3.2.5+incompatible
github.com/google/go-cmp v0.6.0
github.com/google/go-github v17.0.0+incompatible
github.com/labstack/echo/v4 v4.11.4
github.com/markbates/goth v1.78.0
github.com/mattn/go-jsonpointer v0.0.1
github.com/sirupsen/logrus v1.9.3
github.com/thanhpk/randstr v1.0.6
k8s.io/api v0.29.1
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/elliotchance/orderedmap/v2 v2.2.0 h1:7/2iwO98kYT4XkOjA9mBEIwvi4KpGB4cyHeOFOnj4Vk=
github.com/elliotchance/orderedmap/v2 v2.2.0/go.mod h1:85lZyVbpGaGvHvnKa7Qhx7zncAdBIBq6u56Hb1PRU5Q=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
Expand Down Expand Up @@ -207,6 +209,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-jsonpointer v0.0.1 h1:j5m5P9BdP4B/zn6J7oH3KIQSOa2OHmcNAKEozUW7wuE=
github.com/mattn/go-jsonpointer v0.0.1/go.mod h1:1s8vx7JSjlgVRF+LW16MPpWSRZAxyrc1/FYzOonxeao=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand Down
136 changes: 84 additions & 52 deletions server/infrastructure/kubernetes/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@ package kubernetes

import (
"context"
"encoding/json"
"fmt"
"net/url"
"regexp"
"strconv"
"strings"

"github.com/elliotchance/orderedmap/v2"
"github.com/mattn/go-jsonpointer"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
Expand All @@ -19,6 +24,16 @@ import (
"github.com/ShotaKitazawa/kube-portal/server/models/ports"
)

const ingressAnnotationPrefix = "kube-portal.kanatakita.com/"

var ingressAnnotationMatcher *regexp.Regexp

func init() {
ingressAnnotationMatcher = regexp.MustCompile(
fmt.Sprintf(`^%srules\[(\d+)\]\.paths\[(\d+)\]\.(.+)$`,
ingressAnnotationPrefix))
}

type Client struct {
clientset kubernetes.Interface
dynamic dynamic.Interface
Expand Down Expand Up @@ -63,63 +78,80 @@ func (c *Client) ListIngress(ctx context.Context) (models.IngressInfoList, error
return nil, err
}

var result []models.IngressInfo
var result models.IngressInfoList
for _, ing := range ings.Items {
m := orderedmap.NewOrderedMap[string, models.IngressInfo]()
for key, val := range ing.Annotations {
// Skip if it's not related annotation
if !strings.HasPrefix(key, ingressAnnotationPrefix) {
continue
}

/* check ignore flag */
ignoreStr := ing.Annotations["kube-portal.kanatakita.com/ignore"]
if strings.ToLower(ignoreStr) == "true" {
continue
}
// Extract value from annotations
if !ingressAnnotationMatcher.MatchString(key) {
continue
}
l := ingressAnnotationMatcher.FindStringSubmatch(key)
if len(l) != 4 {
continue
}
ruleIdx, _ := strconv.Atoi(l[1])
pathIdx, _ := strconv.Atoi(l[2])
action := l[3]

/* get & validate values */
// name
// - using metadata.name if annotation is empty
name, ok := ing.Annotations["kube-portal.kanatakita.com/name"]
if !ok {
name = ing.Name
}
// fqdn
// - TODO: ref ing.Spec.Rules[1:].Host
fqdn := ing.Spec.Rules[0].Host
// path
// - TODO: ref ing.Spec.Rules[1:].http.Paths[1:].path
path := ing.Spec.Rules[0].HTTP.Paths[0].Path
if path == "" {
path = "/"
// Fill models.IngressInfo
tmp, _ := m.Get(fmt.Sprintf("%d-%d", ruleIdx, pathIdx))
if tmp.Hostname == "" || tmp.Path == "" { // Fill Fqdn & Path first
b, err := json.Marshal(&ing.Spec)
if err != nil {
return nil, err
}
// Hostname
rvRule, err := jsonpointer.Get(b,
fmt.Sprintf("/rules/%d/host", ruleIdx))
if err != nil {
return nil, err
}
r, ok := rvRule.(string)
if !ok {
// TODO: warnding log
continue
}
tmp.Hostname = r
// Path
rvPath, err := jsonpointer.Get(b,
fmt.Sprintf("/rules/%d/http/paths/%d/path", ruleIdx, pathIdx))
if err != nil {
return nil, err
}
p, ok := rvPath.(string)
if !ok {
p = "/"
}
tmp.Path = p
}
switch action { // Fill from annotations
case "name":
tmp.Name = val
case "proto":
tmp.Proto = val
case "icon-url":
tmp.IconUrl = val
case "tags":
tmp.Tags = strings.Split(val, ",")
case "is-private":
if strings.ToLower(val) == "true" {
tmp.IsPrivate = true
}
}
m.Set(fmt.Sprintf("%d-%d", ruleIdx, pathIdx), tmp)
}

// proto
// - allow only "http" or "https"
proto, ok := ing.Annotations["kube-portal.kanatakita.com/proto"]
if !ok || !(strings.ToLower(proto) == "http" || strings.ToLower(proto) == "https") {
proto = "https"
}
// icon_url
iconUrl := ing.Annotations["kube-portal.kanatakita.com/icon-url"]
// tags
tags := []string{}
tagsStr, ok := ing.Annotations["kube-portal.kanatakita.com/tags"]
if ok {
tags = strings.Split(tagsStr, ",")
// append result from orderedMap
for _, key := range m.Keys() {
val, _ := m.Get(key)
result = append(result, val)
}
// is_private
var isPrivate bool
isPrivateStr, ok := ing.Annotations["kube-portal.kanatakita.com/is-private"]
if ok && strings.ToLower(isPrivateStr) == "true" {
isPrivate = true
}

/* set values to result */
result = append(result, models.IngressInfo{
Name: name,
Fqdn: fqdn,
Path: path,
Proto: proto,
IconUrl: iconUrl,
Tags: tags,
IsPrivate: isPrivate,
})
}

return result, nil
Expand Down Expand Up @@ -149,7 +181,7 @@ func (c *Client) ListExternalLink(ctx context.Context) (models.IngressInfoList,
/* set values to result */
result = append(result, models.IngressInfo{
Name: exLink.Spec.Title,
Fqdn: u.Host,
Hostname: u.Host,
Path: u.Path,
Proto: u.Scheme,
IconUrl: exLink.Spec.IconURL,
Expand Down
2 changes: 1 addition & 1 deletion server/infrastructure/kubernetes/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func TestClient_ListIngressInfo(t *testing.T) {
want: models.IngressInfoList{
{
Name: "test01",
Fqdn: "01.example.com",
Hostname: "01.example.com",
Path: "/",
Proto: "https",
IconUrl: "",
Expand Down
2 changes: 1 addition & 1 deletion server/models/ingress_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package models

type IngressInfo struct {
Name string
Fqdn string
Hostname string
Path string
Proto string
IconUrl string
Expand Down
2 changes: 1 addition & 1 deletion server/view/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func (v JSON) ListIngressInfo(ctx echo.Context, list []models.IngressInfo) error

var res []IngressInfo
for _, val := range list {
u, err := url.Parse(val.Proto + "://" + val.Fqdn + "/" + val.Path)
u, err := url.Parse(val.Proto + "://" + val.Hostname + "/" + val.Path)
if err != nil {
return err
}
Expand Down

0 comments on commit 5a2a866

Please sign in to comment.