Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Tricks & Treats with HashiCorps OSS

Allee
February 20, 2020

Tricks & Treats with HashiCorps OSS

Allee

February 20, 2020
Tweet

More Decks by Allee

Other Decks in Programming

Transcript

  1. Open Source Software (OSS) HashiCorp writes a lot of software

    for the community What treats for today Go-Getter and Consul template
  2. How Git works Clones It clones the repository in memory

    and discard everything that isn’t needed.
  3. How Cloud Storage works Leverages 3rd Party Uses Amazon’s or

    Google’s storage API to optimize operations.
  4. Detector interface CODE EDITOR // Detector defines the interface that

    an invalid URL or a URL with a blank // scheme is passed through in order to determine if its shorthand for // something else well-known. type Detector interface { // Detect will detect whether the string matches a known pattern to // turn it into a proper URL. Detect(string, string) (string, bool, error) }
  5. Detector CODE EDITOR //define the type of detectors to use

    -- in this case only github is needed detector := []getter.Detector{new(getter.GitHubDetector)}
  6. Getter interface CODE EDITOR // Getter defines the interface that

    schemes must implement to download type Getter interface { // Get downloads the given URL into the given directory. This always // assumes that we're updating and gets the latest version that it can. // // The directory may already exist (if we're updating). If it is in a // format that isn't understood, an error should be returned. Get shouldn't // simply nuke the directory. Get(string, *url.URL) error // GetFile downloads the give URL into the given path. The URL must // reference a single file. If possible, the Getter should check if // the remote end contains the same file and no-op this operation. GetFile(string, *url.URL) error
  7. Getter interface CODE EDITOR // ClientMode returns the mode based

    on the given URL. This is used to // allow clients to let the getters decide which mode to use. ClientMode(*url.URL) (ClientMode, error) // SetClient allows a getter to know it's client // in order to access client's Get functions or // progress tracking. SetClient(*Client) }
  8. Getter use case CODE EDITOR //provide the getter needed to

    download the files getters := map[string]getter.Getter{ "git": &getter.GitGetter{}}
  9. Create a new client CODE EDITOR client := &getter.Client{ Ctx:

    context.Background(), //define the destination to where the directory will be stored. This will create the directory if it doesnt exist Dst: "/tmp/gogetter", Dir: true, //the repository with a subdirectory I would like to clone only Src: "github.com/hashicorp/terraform/examples/cross-provider", Mode: getter.ClientModeDir, }
  10. Download the files CODE EDITOR if err := client.Get(); err

    != nil { fmt.Fprintf(os.Stderr, "Error getting path %s: %v", client.Src, err) os.Exit(1) }
  11. Where you can get your values from Vault Read secret

    values, static or dynamic from Vault paths and export them into your configuration. Consul Allows you to read values from Consul key and services into a file
  12. TERMINAL [root@e63609e6e248 tmpl]# ls bar.tpl foo [root@e63609e6e248 tmpl]# consul-template -template

    "bar.tpl:bar.txt" -once [root@e63609e6e248 tmpl]# cat bar.txt testdata [root@e63609e6e248 tmpl]# cat foo testdata
  13. Template Let’s run a simple example of consul template through

    code. CODE EDITOR consulTemplateInput := &template.NewTemplateInput{Source: “/foo”} templ, err := template.NewTemplate(consulTemplateInput) if err != nil { return err } response, err := templ.Execute(&template.ExecuteInput{}) if err != nil { return err } //do something with output fmt.Fprintln(os.Stdout, response.Out)
  14. NewTemplateInput ▪ Source or Contents ▪ ErrMissingKey (bool) ▪ LeftDelim

    or RightDelim (string) ▪ FunctionBlacklist (array of strings) ▪ SandboxPath (array of strings)
  15. Configuration ▪ Consul (object of type ConsulConfig) ▪ Exec (map)

    ▪ KillSignal (type os.Signal) ▪ PidFile (string) ▪ ReloadSignal (type os.Signal) ▪ Syslog (type SyslogConfig) ▪ Vault (object of type VaultConfig)
  16. Template multiple values TERMINAL > consul-template \ -template "/tmp/nginx.ctmpl:/var/nginx/nginx.conf:nginx -s

    reload" \ -template "/tmp/redis.ctmpl:/var/redis/redis.conf:service redis restart" \ -template "/tmp/haproxy.ctmpl:/var/haproxy/haproxy.conf"
  17. Template Configuration ▪ Backup (bool) ▪ Contents (string) ▪ ErrMissingKey

    (bool) ▪ FunctionBlacklist (array of stings) ▪ Sandbox (array of strings)
  18. Initialize manager CODE EDITOR // NewRunner accepts a slice of

    TemplateConfigs and returns a pointer to the new // Runner and any error that occurred during creation. runner, err := manger.NewRunner(defaultConfig, false) if err != nil { return err } var out bytes.Buffer go runner.Start() defer runner.Stop() if err = runner.Run(); err != nil { return err } runner.SetOutStream(&out) runner.SetErrStream(&out)
  19. Wait for the runner to done or error Each as

    its own type. We want to save the result of the error so we can return that back to the client. The final case is to keep rendering the template CODE EDITOR for { select { case err := <-runner.ErrCh: return err case <-runner.DoneCh: return nil case <-runner.TemplateRenderedCh(): } }
  20. Authoring Plugins “For some use cases, it may be necessary

    to write a plugin that offloads work to another system. This is especially useful for things that may not fit in the "standard library" of Consul Template, but still need to be shared across multiple instances.”
  21. NAME NAME - the name of the plugin - this

    is also the name of the binary, either a full path or just the program name. It will be executed in a shell with the inherited PATH so e.g. the plugin cat will run the first executable cat that is found on the PATH.
  22. INPUT INPUT - input from the template. There will be

    one INPUT for every argument passed to the plugin function. If the arguments
  23. CODE EDITOR ec2-consul-template-plugin.py metadata = boto.utils.get_instance_metadata() metadata['user_data'] = boto.utils.get_instance_userdata() metadata['identity']

    = boto.utils.get_instance_identity() metadata['placement']['region'] = metadata['identity']['document']['region'] metadata = mangle_keys(metadata) if(len(sys.argv) > 1): if(len(sys.argv) > 2): output = {} for arg in sys.argv[1:]: output[arg] = xpath_get(metadata, arg) print json.dumps(output) else: if isinstance(xpath_get(metadata, sys.argv[1]), basestring): print xpath_get(metadata, sys.argv[1]) else: print json.dumps(xpath_get(metadata, sys.argv[1])) else: print json.dumps(metadata)
  24. Other 7 Open source projects 1. serf 2. consul-replicate 3.

    consul-esm 4. envconsul 5. go-discover 6. go-memdb 7. memberlist