Skip to content

Commit

Permalink
Add options
Browse files Browse the repository at this point in the history
  • Loading branch information
angelnu committed Jun 6, 2021
1 parent 6212f28 commit 662bee2
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 20 deletions.
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ module github.com/k8s-at-home/gateway-admision-controller
go 1.16

require (
github.com/fiskeben/resolv v0.0.0-20200701110541-c310f0881e4b
github.com/oklog/run v1.1.0
github.com/sirupsen/logrus v1.8.1
github.com/slok/kubewebhook/v2 v2.1.0
Expand Down
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,6 @@ github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi
github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses=
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fiskeben/resolv v0.0.0-20200701110541-c310f0881e4b h1:F0oOgXwG5M9trhoBAzI/p/WdyznxKYjKdUOnbthHAKs=
github.com/fiskeben/resolv v0.0.0-20200701110541-c310f0881e4b/go.mod h1:mfzp4KVyI1aKyqzrA3txM3p0I/h0dXHIpC9y8207odc=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
Expand All @@ -123,8 +121,6 @@ github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.6 h1:UHSEyLZUwX9Qoi99vVwvewiMC8mM2bf7XEM2nqvzEn8=
github.com/go-test/deep v1.0.6/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
Expand Down
2 changes: 1 addition & 1 deletion internal/http/webhook/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func (h handler) gatewayPodMutator() (http.Handler, error) {
logger := kubewebhookLogger{Logger: h.logger.WithKV(log.KV{"lib": "kubewebhook", "webhook": "gatewayPodMutator"})}

// Create our mutator
gwPodMutator, err := gatewayPodMutator.NewGatewayPodMutator(h.cmdConfig)
gwPodMutator, err := gatewayPodMutator.NewGatewayPodMutator(h.cmdConfig, logger)
if err != nil {
return nil, fmt.Errorf("error creating webhook mutator: %w", err)
}
Expand Down
35 changes: 26 additions & 9 deletions internal/mutation/gatewayPodMutator.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/fiskeben/resolv"
"github.com/k8s-at-home/gateway-admision-controller/internal/resolv"
kwhmodel "github.com/slok/kubewebhook/v2/pkg/model"
kwhmutating "github.com/slok/kubewebhook/v2/pkg/webhook/mutating"

"github.com/k8s-at-home/gateway-admision-controller/internal/config"
"github.com/k8s-at-home/gateway-admision-controller/internal/log"
)

const (
Expand All @@ -31,7 +32,9 @@ type GatewayPodMutator interface {
}

// NewLabelMarker returns a new marker that will mark with labels.
func NewGatewayPodMutator(cmdConfig config.CmdConfig) (GatewayPodMutator, error) {
func NewGatewayPodMutator(cmdConfig config.CmdConfig, logger log.Logger) (GatewayPodMutator, error) {

logger.Infof("Command config is %#v", cmdConfig)

if cmdConfig.Gateway != "" {
//Check we got a valid Gateway
Expand All @@ -53,14 +56,24 @@ func NewGatewayPodMutator(cmdConfig config.CmdConfig) (GatewayPodMutator, error)
if error != nil {
return nil, error
}
logger.Infof("Current DNS config is %#v", DNS_config)

podDNSConfigOptions := make([]corev1.PodDNSConfigOption, 0)
for i := range DNS_config.Options {
podDNSConfigOptions = append(podDNSConfigOptions, corev1.PodDNSConfigOption{
Name: DNS_config.Options[i].Name,
Value: DNS_config.Options[i].Value,
})
}

return gatewayPodMutatorCfg{
cmdConfig: cmdConfig,
staticDNS: corev1.PodDNSConfig{
Nameservers: DNS_config.Nameservers,
Searches: DNS_config.Search,
//Options: DNS_config.Options, #Libray does not support it
Options: podDNSConfigOptions,
},
logger: logger,
}, nil
}

Expand All @@ -77,6 +90,7 @@ func (cfg gatewayPodMutatorCfg) getDNSIP() (string, error) {
type gatewayPodMutatorCfg struct {
cmdConfig config.CmdConfig
staticDNS corev1.PodDNSConfig
logger log.Logger
}

func (cfg gatewayPodMutatorCfg) GatewayPodMutator(_ context.Context, _ *kwhmodel.AdmissionReview, obj metav1.Object) (*kwhmutating.MutatorResult, error) {
Expand Down Expand Up @@ -128,13 +142,13 @@ func (cfg gatewayPodMutatorCfg) GatewayPodMutator(_ context.Context, _ *kwhmodel
copied := cfg.staticDNS.DeepCopy()

//fix the first search to match the pod namespace
firstSearch := copied.Searches[0]
if strings.Contains(firstSearch, ".svc.") {
firstSearchParts := strings.Split(firstSearch, ".")
firstSearchParts[0] = pod.Namespace
firstSearch = strings.Join(firstSearchParts, ".")
for i := range copied.Searches {
searchParts := strings.Split(copied.Searches[i], ".")
if len(searchParts) > 2 && searchParts[1] == "svc" {
searchParts[0] = pod.Namespace
copied.Searches[i] = strings.Join(searchParts, ".")
}
}
copied.Searches[0] = firstSearch

pod.Spec.DNSConfig.Searches = copied.Searches
pod.Spec.DNSConfig.Options = copied.Options
Expand Down Expand Up @@ -305,6 +319,9 @@ func (cfg gatewayPodMutatorCfg) GatewayPodMutator(_ context.Context, _ *kwhmodel
}
}

cfg.logger.Infof("Mutated pod %s", pod.Name)
cfg.logger.Debugf("%s", pod.String())

return &kwhmutating.MutatorResult{
MutatedObject: pod,
}, nil
Expand Down
40 changes: 35 additions & 5 deletions internal/mutation/gatewayPodMutator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ import (
"strings"
"testing"

"github.com/fiskeben/resolv"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/k8s-at-home/gateway-admision-controller/internal/config"
"github.com/k8s-at-home/gateway-admision-controller/internal/log"
mutator "github.com/k8s-at-home/gateway-admision-controller/internal/mutation"
"github.com/k8s-at-home/gateway-admision-controller/internal/resolv"
)

const (
Expand All @@ -31,6 +33,7 @@ const (
testSidecarCmd = "sidecarCmd"
testSidecarMountPoint = "/mnt"
testConfigmapName = "settings"
testNamespace = "myNameSpace"
)

func getExpectedPodSpec_gateway(gateway string, DNS string, initImage string, sidecarImage string) corev1.PodSpec {
Expand All @@ -44,6 +47,15 @@ func getExpectedPodSpec_gateway(gateway string, DNS string, initImage string, si
k8s_DNS_config, _ := resolv.Config()
k8s_DNS_ips := strings.Join(k8s_DNS_config.Nameservers, " ")

//fix the first search to match the pod namespace
for i := range k8s_DNS_config.Search {
searchParts := strings.Split(k8s_DNS_config.Search[i], ".")
if len(searchParts) > 2 && searchParts[1] == "svc" {
searchParts[0] = testNamespace
k8s_DNS_config.Search[i] = strings.Join(searchParts, ".")
}
}

var initContainers []corev1.Container
if initImage != "" {
initContainers = append(initContainers, corev1.Container{
Expand Down Expand Up @@ -143,6 +155,15 @@ func getExpectedPodSpec_gateway(gateway string, DNS string, initImage string, si
if testDNSPolicy == "None" {
// Copy my own webhook settings
spec.DNSConfig.Searches = k8s_DNS_config.Search

podDNSConfigOptions := make([]corev1.PodDNSConfigOption, 0)
for i := range k8s_DNS_config.Options {
podDNSConfigOptions = append(podDNSConfigOptions, corev1.PodDNSConfigOption{
Name: k8s_DNS_config.Options[i].Name,
Value: k8s_DNS_config.Options[i].Value,
})
}
spec.DNSConfig.Options = podDNSConfigOptions
}
}

Expand Down Expand Up @@ -195,7 +216,6 @@ func TestGatewayPodMutator(t *testing.T) {
obj metav1.Object
expObj metav1.Object
}{

"Empty - NOP": {
cmdConfig: config.CmdConfig{
SetGatewayDefault: true,
Expand Down Expand Up @@ -401,7 +421,7 @@ func TestGatewayPodMutator(t *testing.T) {
Spec: getExpectedPodSpec_DNSPolicy(testDNSPolicy),
},
},
"DNSPolicy, Gateway IP, init image ": {
"DNSPolicy, Gateway IP, init image": {
cmdConfig: config.CmdConfig{
SetGatewayDefault: true,
Gateway: testGatewayIP,
Expand All @@ -413,19 +433,29 @@ func TestGatewayPodMutator(t *testing.T) {
ConfigmapName: testConfigmapName,
DNSPolicy: testDNSPolicy,
},
obj: &corev1.Pod{},
obj: &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Namespace: testNamespace,
},
},
expObj: &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Namespace: testNamespace,
},
Spec: getExpectedPodSpec_gateway_DNSPolicy(testGatewayIP, testDNSIP, testInitImage, "", testDNSPolicy),
},
},
}

logrusLog := logrus.New()
logrusLogEntry := logrus.NewEntry(logrusLog).WithField("app", "gatewayPodMutator Test")

for name, test := range tests {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
require := require.New(t)

m, err := mutator.NewGatewayPodMutator(test.cmdConfig)
m, err := mutator.NewGatewayPodMutator(test.cmdConfig, log.NewLogrus(logrusLogEntry).WithKV(log.KV{"test": name}))
require.NoError(err)

_, err = m.GatewayPodMutator(context.TODO(), nil, test.obj)
Expand Down
108 changes: 108 additions & 0 deletions internal/resolv/resolv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package resolv

import (
"bufio"
"io"
"os"
"strings"
)

// Resolver contains the data from resolv.conf
type Resolver struct {
Domains []string
Nameservers []string
Search []string
Sortlist []string
Options []ResolverOption
}

type ResolverOption struct {
Name string
Value *string
}

// Config reads /etc/resolv.conf and returns it as a Resolver
func Config() (Resolver, error) {
f, err := os.Open("/etc/resolv.conf")
if err != nil {
return Resolver{}, err
}
defer f.Close()
return parse(f)
}

func parse(f io.Reader) (Resolver, error) {
domains := make([]string, 0)
nameservers := make([]string, 0)
search := make([]string, 0)
options := make([]ResolverOption, 0)
sortlist := make([]string, 0)

scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "#") {
continue
}

parts := strings.Split(line, " ")
if len(parts) < 2 {
continue
}

kind := parts[0]
rest := parts[1:]

switch kind {
case "domain":
for _, d := range rest {
d := strings.TrimSpace(d)
if d != "" {
domains = append(domains, d)
}
}
case "nameserver":
n := strings.Join(rest, "")
n = strings.TrimSpace(n)
nameservers = append(nameservers, n)
case "search":
for _, s := range rest {
s := strings.TrimSpace(s)
if s != "" {
search = append(search, s)
}
}
case "options":
for _, s := range rest {
s := strings.TrimSpace(s)
s_parts := strings.SplitN(line, ":", 2)

option := ResolverOption{
Name: s_parts[0],
}
if len(s_parts) == 2 {
option.Value = &s_parts[1]
}

if s != "" {
options = append(options, option)
}
}
case "sortlist":
for _, s := range rest {
s := strings.TrimSpace(s)
if s != "" {
sortlist = append(sortlist, s)
}
}
}
}

return Resolver{
Domains: domains,
Nameservers: nameservers,
Search: search,
Options: options,
Sortlist: sortlist,
}, nil
}

0 comments on commit 662bee2

Please sign in to comment.