Пример #1
0
func (suite *TestSuiteTemplate) TestGet(c *C) {
	// Write something
	url := "zk://" + strings.Join(Hosts(), ",")
	zk, err := namespace.Dial(context.Background(), url)
	c.Assert(err, IsNil)
	c.Log(zk)
	defer zk.Close()

	k := fmt.Sprintf("/unit-test/registry/template/%d/test", time.Now().Unix())
	p := namespace.NewPath(k)
	v := []byte("test")
	_, err = zk.Put(p, v, false)
	c.Assert(err, IsNil)

	suite.template = "The value is {{get \"zk://" + k + "\"}}!"

	// Generate the auth token required by the server.
	token := auth.NewToken(1*time.Hour).Add("secure", 1)
	header := http.Header{}
	token.SetHeader(header, testutil.PrivateKeyFunc)

	ctx := resource.ContextPutHttpHeader(context.Background(), header)
	applied, err := template.Execute(ctx, fmt.Sprintf("http://localhost:%d/secure", suite.port))
	c.Assert(err, IsNil)
	c.Log(string(applied))
	c.Assert(string(applied), Equals, "The value is test!")
}
Пример #2
0
func (suite *TestSuiteTemplate) TestList(c *C) {
	// Write something
	url := "zk://" + strings.Join(Hosts(), ",")
	zk, err := namespace.Dial(context.Background(), url)
	c.Assert(err, IsNil)
	c.Log(zk)
	defer zk.Close()

	k := "/unit-test/registry/template/test"
	p := namespace.NewPath(k)

	err = zk.Delete(p)

	// Write new data
	v := []byte("test")
	_, err = zk.Put(p, v, false)
	c.Assert(err, IsNil)

	// write children
	for i := 0; i < 5; i++ {
		cp := p.Sub(fmt.Sprintf("child-%d", i))
		cv := []byte(fmt.Sprintf("value-%d", i))
		_, err = zk.Put(cp, cv, false)
		c.Assert(err, IsNil)
	}

	suite.template = "{{range list \"zk://" + k + "\"}}\n{{.}}{{end}}"

	// Generate the auth token required by the server.
	token := auth.NewToken(1*time.Hour).Add("secure", 1)
	header := http.Header{}
	token.SetHeader(header, testutil.PrivateKeyFunc)

	ctx := resource.ContextPutHttpHeader(context.Background(), header)
	applied, err := template.Execute(ctx, fmt.Sprintf("http://localhost:%d/secure", suite.port))
	c.Assert(err, IsNil)
	c.Log(string(applied))

	l := strings.Split(string(applied), "\n")[1:]
	c.Assert(l, DeepEquals, []string{
		url + "/unit-test/registry/template/test/child-4",
		url + "/unit-test/registry/template/test/child-3",
		url + "/unit-test/registry/template/test/child-2",
		url + "/unit-test/registry/template/test/child-1",
		url + "/unit-test/registry/template/test/child-0",
	})
}
Пример #3
0
// Run the configuration specified in conf against the target.  This will run a series
// of template fetching, applying templates, unmarshaling of the final applied template
// onto the given target object.  After unmarshaling is done, the target's fields are
// examined one by one, by tag, and fields that have template as values are then applied.
func Configure(ctx context.Context, conf Conf, target interface{}, optionalFuncs ...template.FuncMap) error {
	conf.lock.Lock()
	defer conf.lock.Unlock()

	initialData := ContextGetInitialData(ctx)
	if initialData != nil {
		gtemplate.ContextPutTemplateData(ctx, initialData)
	}

	contentType := ContextGetConfigDataType(ctx)

	// Generate a list of functions that will escape the template strings
	// Ex.  "secret" : "{{var "zk://host/path/to/secret"}}"
	// This string will be escaped so that the evaluation happens after the unmarshal step by field tag
	funcs := template.FuncMap{}
	for _, fns := range optionalFuncs {
		funcs = gtemplate.MergeFuncMaps(funcs, fns)
	}

	// Note here we generate escaped versions of function to override what's provided.
	// The actual funcs are used in the struct field-by-field step, for those that are marked by tags.
	stubs := gtemplate.MergeFuncMaps(funcs, generateEscapeFuncsFromFieldTag(target))

	conf.model = map[string]interface{}{}
	for _, url := range conf.Urls {

		// Fetch the config data and execute as if it were template
		applied, err := gtemplate.Execute(ctx, url, stubs)

		if conf.OnDoneExecuteLayer != nil {
			conf.OnDoneExecuteLayer(&conf, url, applied, err)
		}

		if err != nil {
			return err
		}

		// Unmarshal to an intermediate representation
		buff := bytes.NewBuffer(applied)
		err = encoding.Unmarshal(contentType, buff, conf.model)

		if conf.OnDoneUnmarshalLayer != nil {
			conf.OnDoneUnmarshalLayer(&conf, url, err)
		}

		if err != nil {
			return err
		}
	}

	if conf.OnDoneFetching != nil {
		conf.OnDoneFetching(&conf)
	}

	// Now marshal the aggregated model to a buffer and then unmarshal it back to the typed struct
	serialized := new(bytes.Buffer)
	err := encoding.Marshal(contentType, serialized, conf.model)
	if err != nil {
		return err
	}
	conf.serialized = serialized.Bytes()
	err = encoding.Unmarshal(contentType, bytes.NewBuffer(conf.serialized), target)

	if conf.OnDoneSerialize != nil {
		conf.OnDoneSerialize(&conf, err)
	}

	if err != nil {
		return err
	}

	if conf.OnDoneUnmarshal != nil {
		conf.OnDoneUnmarshal(&conf, target)
	}

	// Now look for fields with struct tags and apply the actual templates
	return evalStructFieldTemplates(target, funcs)
}
Пример #4
0
func (suite *TestSuiteTemplate) TestTemplateExecuteWithVarBlock(c *C) {
	// Write something
	url := "zk://" + strings.Join(Hosts(), ",")
	zk, err := namespace.Dial(context.Background(), url)
	c.Assert(err, IsNil)
	c.Log(zk)

	k := "/unit-test/registry/template/test-template-execute-vars/PG_PASS"
	p := namespace.NewPath(k)

	err = zk.Delete(p)

	// Write new data
	v := []byte("password")
	_, err = zk.Put(p, v, false)
	c.Assert(err, IsNil)

	zk.Close()

	// Now use the value in zk in the template

	// Generate the auth token required by the server.
	token := auth.NewToken(1*time.Hour).Add("secure", 1)
	header := http.Header{}
	token.SetHeader(header, testutil.PrivateKeyFunc)

	// This is the content to be served by the test server.
	// Using the Execute will add additional functions that can be included in the var blocks.
	suite.template = `
{{define "comments"}}
# The variable define blocks allow the definition of variables that are reused throughout the
# main body of the template.  The variables are referenced as '<blockname>.<fieldname>'.
{{end}}

{{define "app"}} # blockname is 'app'
version: 1.2
image: repo
build: 1234
user: "******"USER"}}"  # Getting the environment variable and use that as value.
password: "******"zk:///unit-test/registry/template/test-template-execute-vars/PG_PASS" }}"
{{end}}

{{define "host"}}
label: appserver
name: myhost
port: {{.port}}  # Here we allow the application to pass in a context that's refereceable.
{{end}}

{
   "image" : "repo/myapp:` + "{{my `app.version`}}-{{my `app.build`}}" + `",
   "host" : "` + "{{my `host.name`}}" + `",{{/* use this for comment in JSON :) */}}
   "user" : "` + "{{my `app.user`}}" + `",
   "password" : "` + "{{my `app.password`}}" + `",
   "port" : "` + "{{my `host.port`}}" + `"
}`

	// The url is a template too.
	url = "http://localhost:{{.port}}/secure"

	data := map[string]interface{}{
		"Name": "test",
		"Age":  20,
		"port": suite.port,
	}
	ctx := template.ContextPutTemplateData(resource.ContextPutHttpHeader(context.Background(), header), data)

	text, err := template.Execute(ctx, url)
	c.Assert(err, IsNil)
	c.Log(string(text))
	obj := make(map[string]string)
	err = json.Unmarshal(text, &obj)
	c.Assert(err, IsNil)
	c.Assert(obj["image"], Equals, "repo/myapp:1.2-1234")
	c.Assert(obj["user"], Equals, os.Getenv("USER"))
	c.Assert(obj["host"], Equals, "myhost")
	c.Assert(obj["port"], Equals, fmt.Sprintf("%d", suite.port))
	c.Assert(obj["password"], Equals, string(v))
}