Skip to content

Commit

Permalink
Cache registry clients and expose modules as map
Browse files Browse the repository at this point in the history
  • Loading branch information
cezarsa committed Dec 8, 2020
1 parent 7f750e8 commit 508860e
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 29 deletions.
16 changes: 11 additions & 5 deletions controllers/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -819,11 +819,17 @@ func (r *RpaasInstanceReconciler) renderTemplate(ctx context.Context, instance *
return "", err
}

return cr.Render(nginx.ConfigurationData{
Instance: instance,
Config: &plan.Spec.Config,
LoadedModules: modules,
})
config := nginx.ConfigurationData{
Instance: instance,
Config: &plan.Spec.Config,
Modules: make(map[string]interface{}),
}

for _, mod := range modules {
config.Modules[mod] = nil
}

return cr.Render(config)
}

func (r *RpaasInstanceReconciler) getConfigurationBlocks(ctx context.Context, instance *v1alpha1.RpaasInstance, plan *v1alpha1.RpaasPlan) (nginx.ConfigurationBlocks, error) {
Expand Down
7 changes: 7 additions & 0 deletions controllers/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1961,12 +1961,19 @@ func Test_nameForCronJob(t *testing.T) {
}
}

type fakeImageMetadata struct{}

func (i *fakeImageMetadata) Modules(img string) ([]string, error) {
return []string{"mod1"}, nil
}

func newRpaasInstanceReconciler(objs ...runtime.Object) *RpaasInstanceReconciler {
scheme := extensionsruntime.NewScheme()
return &RpaasInstanceReconciler{
Client: fake.NewFakeClientWithScheme(scheme, objs...),
Log: ctrl.Log,
Scheme: scheme,
RolloutNginxEnabled: true,
ImageMetadata: &fakeImageMetadata{},
}
}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@ go 1.13

require (
github.com/HdrHistogram/hdrhistogram-go v1.0.0 // indirect
github.com/Masterminds/sprig/v3 v3.1.0
github.com/ajg/form v1.5.1
github.com/davecgh/go-spew v1.1.1
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7
github.com/fsnotify/fsnotify v1.4.9
github.com/globocom/echo-prometheus v0.1.2
github.com/go-logr/logr v0.2.1
github.com/go-logr/zapr v0.2.0 // indirect
github.com/google/gops v0.3.12
github.com/gorilla/websocket v1.4.2
github.com/heroku/docker-registry-client v0.0.0-20190909225348-afc9e1acc3d5
github.com/huandu/xstrings v1.3.2 // indirect
github.com/imdario/mergo v0.3.11
github.com/labstack/echo/v4 v4.1.17
github.com/mitchellh/mapstructure v1.1.2
Expand Down
17 changes: 17 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,14 @@ github.com/Djarvur/go-err113 v0.0.0-20200511133814-5174e21577d5/go.mod h1:4UJr5H
github.com/HdrHistogram/hdrhistogram-go v1.0.0 h1:jivTvI9tBw5B8wW9Qd0uoQ2qaajb29y4TPhYTgh8Lb0=
github.com/HdrHistogram/hdrhistogram-go v1.0.0/go.mod h1:YzE1EgsuAz8q9lfGdlxBZo2Ma655+PfKp2mlzcAqIFw=
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg=
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/semver/v3 v3.1.0 h1:Y2lUDsFKVRSYGojLJ1yLxSXdMmMYTYls0rCvoqmMUQk=
github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/Masterminds/sprig/v3 v3.1.0 h1:j7GpgZ7PdFqNsmncycTHsLmVPf5/3wJtlgW9TNDYD9Y=
github.com/Masterminds/sprig/v3 v3.1.0/go.mod h1:ONGMf7UfYGAbMXCZmQLy8x3lCDIPrEZE/rU8pmrbihA=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OpenPeeDeeP/depguard v1.0.0/go.mod h1:7/4sitnI9YlQgTLLk734QlzXT8DuHVnAyztLplQjk+o=
Expand Down Expand Up @@ -419,9 +425,13 @@ github.com/howeyc/fsnotify v0.9.0 h1:0gtV5JmOKH4A8SsFxG2BczSeXWWPvcMT0euZt5gDAxY
github.com/howeyc/fsnotify v0.9.0/go.mod h1:41HzSPxBGeFRQKEEwgh49TRw/nKBsYZ2cF1OzPjSJsA=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
Expand Down Expand Up @@ -526,6 +536,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182aff
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
Expand All @@ -540,6 +552,8 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F
github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd h1:aY7OQNf2XqY/JQ6qREWamhI/81os/agb2BAGpcx5yWI=
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand Down Expand Up @@ -697,6 +711,8 @@ github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTd
github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.2/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
Expand Down Expand Up @@ -828,6 +844,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
Expand Down
25 changes: 21 additions & 4 deletions internal/pkg/rpaas/nginx/configuration_render.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"strings"
"text/template"

sprig "github.com/Masterminds/sprig/v3"
"github.com/tsuru/rpaas-operator/api/v1alpha1"
"github.com/tsuru/rpaas-operator/pkg/util"
"k8s.io/apimachinery/pkg/api/resource"
Expand All @@ -33,9 +34,11 @@ type ConfigurationBlocks struct {
}

type ConfigurationData struct {
Config *v1alpha1.NginxConfig
Instance *v1alpha1.RpaasInstance
LoadedModules []string
Config *v1alpha1.NginxConfig
Instance *v1alpha1.RpaasInstance
// Modules is a map of installed modules, using a map instead of a slice
// allow us to use `hasKey` inside templates.
Modules map[string]interface{}
}

type rpaasConfigurationRenderer struct {
Expand Down Expand Up @@ -190,7 +193,7 @@ func tlsSessionTicketTimeout(instance *v1alpha1.RpaasInstance) int {
return nkeys * int(keyRotationInterval)
}

var templateFuncs = template.FuncMap(map[string]interface{}{
var internalTemplateFuncs = template.FuncMap(map[string]interface{}{
"boolValue": v1alpha1.BoolValue,
"buildLocationKey": buildLocationKey,
"hasRootPath": hasRootPath,
Expand All @@ -217,6 +220,14 @@ var templateFuncs = template.FuncMap(map[string]interface{}{
},
})

var templateFuncs = func() template.FuncMap {
funcs := sprig.GenericFuncMap()
for k, v := range internalTemplateFuncs {
funcs[k] = v
}
return template.FuncMap(funcs)
}()

var defaultMainTemplate = template.Must(template.New("main").
Funcs(templateFuncs).
Parse(rawNginxConfiguration))
Expand All @@ -230,6 +241,7 @@ var rawNginxConfiguration = `
{{- $all := . -}}
{{- $config := .Config -}}
{{- $instance := .Instance -}}
{{- $modules := .Modules -}}
# This file was generated by RPaaS (https://github.com/tsuru/rpaas-operator.git)
# Do not modify this file, any change will be lost.
Expand All @@ -242,7 +254,12 @@ user {{ . }};
worker_processes {{ . }};
{{- end }}
{{- range $mod, $_ := $modules }}
load_module "modules/{{ $mod }}.so";
{{- else }}
include modules/*.conf;
{{- end }}
{{ template "root" . }}
Expand Down
14 changes: 14 additions & 0 deletions internal/pkg/rpaas/nginx/configuration_render_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func TestRpaasConfigurationRenderer_Render(t *testing.T) {
assert.NotRegexp(t, `user(.+);`, result)
assert.NotRegexp(t, `worker_processes(.+);`, result)
assert.NotRegexp(t, `worker_connections(.+);`, result)
assert.Regexp(t, `include modules/\*\.conf;`, result)
assert.Regexp(t, `access_log /dev/stdout combined;`, result)
assert.Regexp(t, `error_log /dev/stderr;`, result)
assert.Regexp(t, `server {\n\s+listen 8800;\n\s+}\n+`, result)
Expand Down Expand Up @@ -514,6 +515,19 @@ func TestRpaasConfigurationRenderer_Render(t *testing.T) {
\s+\}`, result)
},
},
{
name: "with custom modules",
data: ConfigurationData{
Config: &v1alpha1.NginxConfig{},
Instance: &v1alpha1.RpaasInstance{},
Modules: map[string]interface{}{"mod1": nil, "mod2": nil},
},
assertion: func(t *testing.T, result string) {
assert.NotRegexp(t, `include modules/\*\.conf;`, result)
assert.Regexp(t, `load_module "modules/mod1.so";`, result)
assert.Regexp(t, `load_module "modules/mod2.so";`, result)
},
},
}

for _, tt := range tests {
Expand Down
57 changes: 37 additions & 20 deletions internal/registry/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package registry

import (
"crypto/tls"
"encoding/json"
"net/http"
"strings"
Expand All @@ -22,18 +23,21 @@ type ImageMetadata interface {
}

type imageMetadataRetriever struct {
mu sync.Mutex
labelsCache map[string]map[string]string
mu sync.Mutex
labelsCache map[string]map[string]string
registryCache map[string]*registry.Registry
insecure bool
}

func NewImageMetadata() *imageMetadataRetriever {
return &imageMetadataRetriever{
labelsCache: map[string]map[string]string{},
labelsCache: map[string]map[string]string{},
registryCache: map[string]*registry.Registry{},
}
}

func (r *imageMetadataRetriever) Modules(image string) ([]string, error) {
labels, err := r.getLabels(image)
labels, err := r.cachedLabels(image)
if err != nil {
return nil, err
}
Expand All @@ -47,15 +51,15 @@ func (r *imageMetadataRetriever) Modules(image string) ([]string, error) {
return strings.Split(labels[modulesLabel], ","), nil
}

func (r *imageMetadataRetriever) getLabels(image string) (map[string]string, error) {
func (r *imageMetadataRetriever) cachedLabels(image string) (map[string]string, error) {
r.mu.Lock()
defer r.mu.Unlock()

if _, ok := r.labelsCache[image]; ok {
return r.labelsCache[image], nil
}

labels, err := getImageLabels(image)
labels, err := r.imageLabels(image)
if err != nil {
return nil, err
}
Expand All @@ -64,15 +68,15 @@ func (r *imageMetadataRetriever) getLabels(image string) (map[string]string, err
return labels, nil
}

func getImageLabels(image string) (map[string]string, error) {
func (r *imageMetadataRetriever) imageLabels(image string) (map[string]string, error) {
type historyEntry struct {
Config struct {
Labels map[string]string
}
}

parts := parseImage(image)
hub := newRegistry(parts.registry)
hub := r.registry(parts.registry)
manifest, err := hub.Manifest(parts.image, parts.tag)
if err != nil {
return nil, err
Expand All @@ -91,6 +95,31 @@ func getImageLabels(image string) (map[string]string, error) {
return entry.Config.Labels, nil
}

func (r *imageMetadataRetriever) registry(registryHost string) *registry.Registry {
if reg := r.registryCache[registryHost]; reg != nil {
return reg
}
url := "https://" + registryHost
transport := http.DefaultTransport
if r.insecure {
newTransport := http.DefaultTransport.(*http.Transport).Clone()
newTransport.TLSClientConfig = &tls.Config{
InsecureSkipVerify: true,
}
transport = newTransport
}
reg := &registry.Registry{
URL: url,
Client: &http.Client{
Transport: registry.WrapTransport(transport, url, "", ""),
Timeout: 30 * time.Second,
},
Logf: registry.Quiet,
}
r.registryCache[registryHost] = reg
return reg
}

type dockerImage struct {
registry string
image string
Expand Down Expand Up @@ -124,15 +153,3 @@ func parseImage(imageName string) dockerImage {
}
return img
}

func newRegistry(registryHost string) *registry.Registry {
url := "https://" + registryHost
return &registry.Registry{
URL: url,
Client: &http.Client{
Transport: registry.WrapTransport(http.DefaultTransport, url, "", ""),
Timeout: 30 * time.Second,
},
Logf: registry.Quiet,
}
}
41 changes: 41 additions & 0 deletions internal/registry/image_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,52 @@
package registry

import (
"net/http"
"net/http/httptest"
"net/url"
"testing"

"github.com/docker/libtrust"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestImageMetadataRetriever_Modules(t *testing.T) {
r := NewImageMetadata()
r.insecure = true
srv := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "/v2/my/img/manifests/v1", r.URL.Path)
assert.Equal(t, "GET", r.Method)
w.Header().Add("Content-Type", "application/vnd.docker.distribution.manifest.v1+json")
sig, err := libtrust.NewJSONSignatureFromMap(map[string]interface{}{
"schemaVersion": 1,
"name": "my/img",
"tag": "v1",
"history": []map[string]interface{}{{
"v1Compatibility": `{
"config":{
"Labels":{"io.tsuru.nginx-modules":"mod1,mod2"}
}
}`,
}},
})
require.NoError(t, err)
pk, err := libtrust.GenerateECP256PrivateKey()
require.NoError(t, err)
err = sig.Sign(pk)
require.NoError(t, err)
data, err := sig.PrettySignature("signatures")
require.NoError(t, err)
w.Write(data)
}))
defer srv.Close()
u, err := url.Parse(srv.URL)
require.NoError(t, err)
mod, err := r.Modules(u.Host + "/my/img:v1")
require.NoError(t, err)
assert.Equal(t, []string{"mod1", "mod2"}, mod)
}

func TestParseImage(t *testing.T) {
tests := []struct {
imageURI string
Expand Down

0 comments on commit 508860e

Please sign in to comment.