Example #1
0
func (suite *TestSuiteSource) TestSourceUsage(c *C) {
	ctx := ContextPutTimeout(context.Background(), 1*time.Minute)
	url := "zk://" + strings.Join(Hosts(), ",")
	zk, err := namespace.Dial(ctx, url)
	c.Assert(err, IsNil)
	c.Log(zk)
	defer zk.Close()

	root := namespace.NewPathf("/unit-test/zk/%d/source", time.Now().Unix())
	value := []byte("test-value-12345")
	_, err = zk.Put(root, value, false)
	c.Assert(err, IsNil)
	read, _, err := zk.Get(root)
	c.Assert(read, DeepEquals, value)

	sourced, err := resource.Fetch(ctx, url+root.String())
	c.Assert(err, IsNil)
	c.Assert(sourced, DeepEquals, value)

	// Test default to what's in the environment variable -- no hosts specified.
	sourced, err = resource.Fetch(ctx, "zk://"+root.String())
	c.Assert(err, IsNil)
	c.Assert(sourced, DeepEquals, value)

	// Test default to what's in the environment variable -- no hosts specified.
	sourced, err = resource.Fetch(ctx, "zk://bogus/node")
	c.Assert(err, Not(IsNil))
}
Example #2
0
// Fetch the url and write content inline
// ex) {{ inline "http://file/here" }}
func ContentInline(ctx context.Context) interface{} {
	return func(uri string) (string, error) {
		data := ContextGetTemplateData(ctx)
		applied, err := Apply([]byte(uri), data)
		if err != nil {
			return NullTemplate, err
		}
		url := string(applied)
		content, err := resource.Fetch(ctx, url)
		if err != nil {
			return NullTemplate, err
		}
		return string(content), nil
	}
}
Example #3
0
// This test here shows how to implement two stages of configuring an object.
// First a field in the struct gets the source of the config url from the command line flags.
// Second, the config is fetched and unmarshalled to the object.
// Finally, we parse again so that additional flag values are overlaid onto the struct.
func (suite *TestSuiteCommand) TestCommandReparseFlag(c *C) {
	Register("person", func() (Module, ErrorHandling) {
		return new(person), PanicOnError
	})

	// 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)

	suite.template = `
name: joe
age: 21
employee: false
not-a-field: hello
`

	p := &person{
		Age:      18,
		Employee: true,
	}

	RunModule("person", p, strings.Split("--config_url=http://localhost:7986/secure --age=35", " "), nil)

	c.Assert(p.ConfigUrl, Equals, "http://localhost:7986/secure")
	c.Assert(p.Employee, Equals, true)

	data, err := resource.Fetch(ctx, p.ConfigUrl)
	c.Assert(err, IsNil)
	c.Log(string(data))
	err = encoding.Unmarshal(encoding.ContentTypeYAML, bytes.NewBuffer(data), p)
	c.Assert(err, IsNil)
	c.Assert(p.Age, Equals, 21)
	c.Assert(p.Name, Equals, "joe")
	c.Assert(p.Employee, Equals, true) // we don't expect the yaml to change the field.

	ReparseFlags(p)
	c.Assert(p.Age, Equals, 35) // This is overwritten by the flag value
	c.Assert(p.Name, Equals, "joe")
	c.Assert(p.Employee, Equals, true)
}
Example #4
0
// Execute a template at the given uri/url.  The data to be applied to the template should
// be placed in the context via the ContextPutTemplateData() function.
func Execute(ctx context.Context, uri string, funcs ...template.FuncMap) ([]byte, error) {
	data := ContextGetTemplateData(ctx)
	fm := DefaultFuncMap(ctx)
	for _, opt := range funcs {
		fm = MergeFuncMaps(fm, opt)
	}

	// THe url itself can be a template that uses the state of the context object as vars.
	url := uri
	if applied, err := Apply([]byte(uri), data, fm); err != nil {
		return nil, err
	} else {
		url = string(applied)
	}

	body, err := resource.Fetch(ctx, url)
	if err != nil {
		return nil, err
	}
	return Apply2(body, data, fm)
}
Example #5
0
func ContentToFile(ctx context.Context) interface{} {
	return func(uri string, opts ...interface{}) (string, error) {
		data := ContextGetTemplateData(ctx)
		applied, err := Apply([]byte(uri), data)
		if err != nil {
			return NullTemplate, err
		}
		url := string(applied)
		content, err := resource.Fetch(ctx, url)
		if err != nil {
			return NullTemplate, err
		}

		destination := os.TempDir()
		fileMode := os.FileMode(0644)

		// The optional param ordering not important. We check by type.
		// String -> destination path
		// Int -> file mode
		for _, opt := range opts {
			switch opt.(type) {
			case int:
				fileMode = os.FileMode(opt.(int))
			case string:
				if applied, err = Apply([]byte(opt.(string)), data); err != nil {
					return NullContent, err
				} else {
					destination = string(applied)
				}
				// Also expands shell path variables
				switch {
				case strings.Index(destination, "~") > -1:
					// expand tilda
					destination = strings.Replace(destination, "~", os.Getenv("HOME"), 1)
				case strings.Index(destination, "./") > -1:
					// expand tilda
					destination = strings.Replace(destination, "./", os.Getenv("PWD")+"/", 1)
				}
			}
		}

		parent := filepath.Dir(destination)
		fi, err := os.Stat(parent)
		if err != nil {
			switch {
			case os.IsNotExist(err):
				err = os.MkdirAll(parent, fileMode)
				if err != nil {
					return NullContent, err
				}
			default:
				return NullContent, err
			}
		}
		// read again after we created the directories
		fi, err = os.Stat(destination)
		if err == nil && fi.IsDir() {
			// build the name because we provided only a directory path
			destination = filepath.Join(destination, filepath.Base(string(url)))
		}

		err = ioutil.WriteFile(destination, []byte(content), fileMode)
		if err != nil {
			return NullTemplate, err
		}
		return destination, nil
	}
}