{"action":"created","comment":{"url":"https://api.github.com/repos/hashicorp/terraform/pulls/comments/29959903","id":29959903,"diff_hunk":"@@ -0,0 +1,402 @@\n+package chefclient\n+\n+import (\n+\t\"bytes\"\n+\t\"encoding/json\"\n+\t\"errors\"\n+\t\"fmt\"\n+\t\"io\"\n+\t\"log\"\n+\t\"os\"\n+\t\"path\"\n+\t\"regexp\"\n+\t\"strings\"\n+\t\"text/template\"\n+\t\"time\"\n+\n+\t\"github.com/hashicorp/terraform/communicator\"\n+\t\"github.com/hashicorp/terraform/communicator/remote\"\n+\t\"github.com/hashicorp/terraform/terraform\"\n+\t\"github.com/mitchellh/go-linereader\"\n+\t\"github.com/mitchellh/mapstructure\"\n+)\n+\n+const (\n+\tfirstBoot      = \"first-boot.json\"\n+\tlogfileDir     = \"logfiles\"\n+\tlinuxConfDir   = \"/etc/chef\"\n+\twindowsConfDir = \"C:/chef\"\n+)\n+\n+const clientConf = `\n+log_location            STDOUT\n+chef_server_url         \"{{ .ServerURL }}\"\n+validation_client_name  \"{{ .ValidationClientName }}\"\n+node_name               \"{{ .NodeName }}\"\n+\n+{{ if .HTTPProxy }}\n+http_proxy          \"{{ .HTTPProxy }}\"\n+ENV['http_proxy'] = \"{{ .HTTPProxy }}\"\n+ENV['HTTP_PROXY'] = \"{{ .HTTPProxy }}\"\n+{{ end }}\n+\n+{{ if .HTTPSProxy }}\n+https_proxy          \"{{ .HTTPSProxy }}\"\n+ENV['https_proxy'] = \"{{ .HTTPSProxy }}\"\n+ENV['HTTPS_PROXY'] = \"{{ .HTTPSProxy }}\"\n+{{ end }}\n+\n+{{ if .NOProxy }}no_proxy \"{{ join .NOProxy \",\" }}\"{{ end }}\n+{{ if .SSLVerifyMode }}ssl_verify_mode {{ .SSLVerifyMode }}{{ end }}\n+`\n+\n+// Provisioner represents a specificly configured chef provisioner\n+type Provisioner struct {\n+\tAttributes           interface{} `mapstructure:\"-\"`\n+\tEnvironment          string      `mapstructure:\"environment\"`\n+\tLogToFile            bool        `mapstructure:\"log_to_file\"`\n+\tHTTPProxy            string      `mapstructure:\"http_proxy\"`\n+\tHTTPSProxy           string      `mapstructure:\"https_proxy\"`\n+\tNOProxy              []string    `mapstructure:\"no_proxy\"`\n+\tNodeName             string      `mapstructure:\"node_name\"`\n+\tPreventSudo          bool        `mapstructure:\"prevent_sudo\"`\n+\tRunList              []string    `mapstructure:\"run_list\"`\n+\tServerURL            string      `mapstructure:\"server_url\"`\n+\tSkipInstall          bool        `mapstructure:\"skip_install\"`\n+\tSSLVerifyMode        string      `mapstructure:\"ssl_verify_mode\"`\n+\tValidationClientName string      `mapstructure:\"validation_client_name\"`\n+\tValidationKeyPath    string      `mapstructure:\"validation_key_path\"`\n+\tVersion              string      `mapstructure:\"version\"`\n+\n+\tinstallChefClient func(terraform.UIOutput, communicator.Communicator) error\n+\tcreateConfigFiles func(terraform.UIOutput, communicator.Communicator) error\n+\trunChefClient     func(terraform.UIOutput, communicator.Communicator) error\n+}\n+\n+// ResourceProvisioner represents a generic chef provisioner\n+type ResourceProvisioner struct{}\n+\n+// Apply executes the file provisioner\n+func (r *ResourceProvisioner) Apply(\n+\to terraform.UIOutput,\n+\ts *terraform.InstanceState,\n+\tc *terraform.ResourceConfig) error {\n+\t// Decode the raw config for this provisioner\n+\tp, err := r.decodeConfig(c)\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\n+\t// Set some values based on the targeted OS\n+\tswitch s.Ephemeral.ConnInfo[\"type\"] {\n+\tcase \"ssh\", \"\": // The default connection type is ssh, so if the type is empty use ssh\n+\t\tp.PreventSudo = p.PreventSudo || s.Ephemeral.ConnInfo[\"user\"] == \"root\"\n+\t\tp.installChefClient = p.sshInstallChefClient\n+\t\tp.createConfigFiles = p.sshCreateConfigFiles\n+\t\tp.runChefClient = p.runChefClientFunc(linuxConfDir)\n+\tcase \"winrm\":\n+\t\tp.PreventSudo = true\n+\t\tp.installChefClient = p.winrmInstallChefClient\n+\t\tp.createConfigFiles = p.winrmCreateConfigFiles\n+\t\tp.runChefClient = p.runChefClientFunc(windowsConfDir)\n+\tdefault:\n+\t\treturn fmt.Errorf(\"Unsupported connection type: %s\", s.Ephemeral.ConnInfo[\"type\"])\n+\t}\n+\n+\t// Get a new communicator\n+\tcomm, err := communicator.New(s)\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\n+\t// Wait and retry until we establish the connection\n+\terr = retryFunc(comm.Timeout(), func() error {\n+\t\terr := comm.Connect(o)\n+\t\treturn err\n+\t})\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\tdefer comm.Disconnect()\n+\n+\tif !p.SkipInstall {\n+\t\tif err := p.installChefClient(o, comm); err != nil {\n+\t\t\treturn err\n+\t\t}\n+\t}\n+\n+\to.Output(\"Creating configuration files...\")\n+\tif err := p.createConfigFiles(o, comm); err != nil {\n+\t\treturn err\n+\t}\n+\n+\to.Output(\"Starting initial Chef-Client run...\")\n+\tif err := p.runChefClient(o, comm); err != nil {\n+\t\treturn err\n+\t}\n+\n+\treturn nil\n+}\n+\n+// Validate checks if the required arguments are configured\n+func (r *ResourceProvisioner) Validate(c *terraform.ResourceConfig) (ws []string, es []error) {\n+\tp, err := r.decodeConfig(c)\n+\tif err != nil {\n+\t\tes = append(es, err)\n+\t\treturn ws, es\n+\t}\n+\n+\tif p.NodeName == \"\" {\n+\t\tes = append(es, fmt.Errorf(\"Key not found: node_name\"))\n+\t}\n+\tif p.RunList == nil {\n+\t\tes = append(es, fmt.Errorf(\"Key not found: run_list\"))\n+\t}\n+\tif p.ServerURL == \"\" {\n+\t\tes = append(es, fmt.Errorf(\"Key not found: server_url\"))\n+\t}\n+\tif p.ValidationClientName == \"\" {\n+\t\tes = append(es, fmt.Errorf(\"Key not found: validation_client_name\"))\n+\t}\n+\tif p.ValidationKeyPath == \"\" {\n+\t\tes = append(es, fmt.Errorf(\"Key not found: validation_key_path\"))\n+\t}\n+\n+\treturn ws, es\n+}\n+\n+func (r *ResourceProvisioner) decodeConfig(c *terraform.ResourceConfig) (*Provisioner, error) {\n+\tp := new(Provisioner)\n+\n+\tdecConf := &mapstructure.DecoderConfig{\n+\t\tWeaklyTypedInput: true,\n+\t\tResult:           p,\n+\t}\n+\tdec, err := mapstructure.NewDecoder(decConf)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\tif err := dec.Decode(c.Raw); err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\tif p.Environment == \"\" {\n+\t\tp.Environment = \"_default\"\n+\t}\n+\n+\tif attrs, ok := c.Raw[\"attributes\"]; ok {\n+\t\tp.Attributes, err = rawToJSON(attrs)\n+\t\tif err != nil {\n+\t\t\treturn nil, fmt.Errorf(\"Error parsing the attributes: %v\", err)\n+\t\t}\n+\t}\n+\n+\treturn p, nil\n+}\n+\n+func rawToJSON(raw interface{}) (interface{}, error) {\n+\tswitch s := raw.(type) {\n+\tcase []map[string]interface{}:\n+\t\tif len(s) != 1 {\n+\t\t\treturn nil, errors.New(\"unexpected input while parsing raw config to JSON\")\n+\t\t}\n+\n+\t\tvar err error\n+\t\tfor k, v := range s[0] {\n+\t\t\ts[0][k], err = rawToJSON(v)\n+\t\t\tif err != nil {\n+\t\t\t\treturn nil, err\n+\t\t\t}\n+\t\t}\n+\n+\t\treturn s[0], nil\n+\tdefault:\n+\t\treturn raw, nil\n+\t}\n+}\n+\n+// retryFunc is used to retry a function for a given duration\n+func retryFunc(timeout time.Duration, f func() error) error {\n+\tfinish := time.After(timeout)\n+\tfor {\n+\t\terr := f()\n+\t\tif err == nil {\n+\t\t\treturn nil\n+\t\t}\n+\t\tlog.Printf(\"Retryable error: %v\", err)\n+\n+\t\tselect {\n+\t\tcase <-finish:\n+\t\t\treturn err\n+\t\tcase <-time.After(3 * time.Second):\n+\t\t}\n+\t}\n+}\n+\n+func (p *Provisioner) runChefClientFunc(\n+\tconfDir string) func(terraform.UIOutput, communicator.Communicator) error {\n+\treturn func(o terraform.UIOutput, comm communicator.Communicator) error {\n+\t\tfb := path.Join(confDir, firstBoot)\n+\t\tcmd := fmt.Sprintf(\"chef-client -j %q -E %q\", fb, p.Environment)\n+\n+\t\tif p.LogToFile {\n+\t\t\tif err := os.MkdirAll(logfileDir, 0777); err != nil {\n+\t\t\t\treturn fmt.Errorf(\"Error creating logfile directory %s: %v\", logfileDir, err)\n+\t\t\t}\n+\n+\t\t\tlogFile := path.Join(logfileDir, p.NodeName)\n+\t\t\tf, err := os.Create(path.Join(logFile))\n+\t\t\tif err != nil {\n+\t\t\t\treturn fmt.Errorf(\"Error creating logfile %s: %v\", logFile, err)\n+\t\t\t}\n+\t\t\tf.Close()\n+\n+\t\t\to.Output(\"Writing Chef Client output to \" + logFile)\n+\t\t\to = p\n+\t\t}\n+\n+\t\treturn p.runCommand(o, comm, cmd)\n+\t}\n+}\n+\n+// Output implementation of terraform.UIOutput interface\n+func (p *Provisioner) Output(output string) {\n+\tlogFile := path.Join(logfileDir, p.NodeName)\n+\tf, err := os.OpenFile(logFile, os.O_APPEND|os.O_WRONLY, 0666)\n+\tif err != nil {\n+\t\tlog.Printf(\"Error creating logfile %s: %v\", logFile, err)\n+\t\treturn\n+\t}\n+\tdefer f.Close()\n+\n+\t// These steps are needed to remove any ANSI escape codes used to colorize\n+\t// the output and to make sure we have proper line endings before writing\n+\t// the string to the logfile.\n+\tre := regexp.MustCompile(`\\x1b\\[[0-9;]+m`)\n+\toutput = re.ReplaceAllString(output, \"\")\n+\toutput = strings.Replace(output, \"\\r\", \"\\n\", -1)\n+\n+\tif _, err := f.WriteString(output); err != nil {\n+\t\tlog.Printf(\"Error writing output to logfile %s: %v\", logFile, err)\n+\t}\n+\n+\tif err := f.Sync(); err != nil {\n+\t\tlog.Printf(\"Error saving logfile %s to disk: %v\", logFile, err)\n+\t}\n+}\n+\n+func (p *Provisioner) deployConfigFiles(\n+\to terraform.UIOutput,\n+\tcomm communicator.Communicator,\n+\tconfDir string) error {\n+\t// Open the validation .pem file\n+\tf, err := os.Open(p.ValidationKeyPath)\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\tdefer f.Close()\n+\n+\t// Copy the validation .pem to the new instance\n+\tif err := comm.Upload(path.Join(confDir, \"validation.pem\"), f); err != nil {\n+\t\treturn fmt.Errorf(\"Uploading validation.pem failed: %v\", err)\n+\t}\n+\n+\t// Make strings.Join available for use within the template\n+\tfuncMap := template.FuncMap{\n+\t\t\"join\": strings.Join,\n+\t}\n+\n+\t// Create a new template and parse the client.rb into it\n+\tt := template.Must(template.New(\"client.rb\").Funcs(funcMap).Parse(clientConf))\n+\n+\tvar buf bytes.Buffer\n+\terr = t.Execute(&buf, p)\n+\tif err != nil {\n+\t\treturn fmt.Errorf(\"Error executing client.rb template: %s\", err)\n+\t}\n+\n+\t// Copy the client.rb to the new instance\n+\tif err := comm.Upload(path.Join(confDir, \"client.rb\"), &buf); err != nil {\n+\t\treturn fmt.Errorf(\"Uploading client.rb failed: %v\", err)\n+\t}\n+\n+\t// Create a map with first boot settings\n+\tfb := make(map[string]interface{})\n+\tif p.Attributes != nil {\n+\t\tfb = p.Attributes.(map[string]interface{})\n+\t}\n+\n+\t// Add the initial runlist to the first boot settings\n+\tfb[\"run_list\"] = p.RunList\n+\n+\t// Marshal the first boot settings to JSON\n+\td, err := json.Marshal(fb)\n+\tif err != nil {\n+\t\treturn fmt.Errorf(\"Failed to create %s data: %s\", firstBoot, err)\n+\t}\n+\n+\t// Copy the first-boot.json to the new instance\n+\tif err := comm.Upload(path.Join(confDir, firstBoot), bytes.NewReader(d)); err != nil {\n+\t\treturn fmt.Errorf(\"Uploading first-boot.json failed: %v\", err)\n+\t}\n+\n+\treturn nil\n+}\n+\n+// runCommand is used to run already prepared commands\n+func (p *Provisioner) runCommand(\n+\to terraform.UIOutput,\n+\tcomm communicator.Communicator,\n+\tcommand string) error {\n+\tvar err error\n+\n+\t// Unless prevented, prefix the command with sudo\n+\tif !p.PreventSudo {\n+\t\tcommand = \"sudo \" + command","path":"builtin/provisioners/chef-client/resource_provisioner.go","position":356,"original_position":356,"commit_id":"d4150d5b1a7869b5b511dd4becf3b470e98d3fd7","original_commit_id":"d4150d5b1a7869b5b511dd4becf3b470e98d3fd7","user":{"login":"sethvargo","id":408570,"avatar_url":"https://avatars.githubusercontent.com/u/408570?v=3","gravatar_id":"","url":"https://api.github.com/users/sethvargo","html_url":"https://github.com/sethvargo","followers_url":"https://api.github.com/users/sethvargo/followers","following_url":"https://api.github.com/users/sethvargo/following{/other_user}","gists_url":"https://api.github.com/users/sethvargo/gists{/gist_id}","starred_url":"https://api.github.com/users/sethvargo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sethvargo/subscriptions","organizations_url":"https://api.github.com/users/sethvargo/orgs","repos_url":"https://api.github.com/users/sethvargo/repos","events_url":"https://api.github.com/users/sethvargo/events{/privacy}","received_events_url":"https://api.github.com/users/sethvargo/received_events","type":"User","site_admin":false},"body":"Won't this break Windows too?","created_at":"2015-05-08T17:40:27Z","updated_at":"2015-05-08T17:40:27Z","html_url":"https://github.com/hashicorp/terraform/pull/1868#discussion_r29959903","pull_request_url":"https://api.github.com/repos/hashicorp/terraform/pulls/1868","_links":{"self":{"href":"https://api.github.com/repos/hashicorp/terraform/pulls/comments/29959903"},"html":{"href":"https://github.com/hashicorp/terraform/pull/1868#discussion_r29959903"},"pull_request":{"href":"https://api.github.com/repos/hashicorp/terraform/pulls/1868"}}},"pull_request":{"url":"https://api.github.com/repos/hashicorp/terraform/pulls/1868","id":35024100,"html_url":"https://github.com/hashicorp/terraform/pull/1868","diff_url":"https://github.com/hashicorp/terraform/pull/1868.diff","patch_url":"https://github.com/hashicorp/terraform/pull/1868.patch","issue_url":"https://api.github.com/repos/hashicorp/terraform/issues/1868","number":1868,"state":"open","locked":false,"title":"New provisioner for Chef-Client","user":{"login":"svanharmelen","id":4171547,"avatar_url":"https://avatars.githubusercontent.com/u/4171547?v=3","gravatar_id":"","url":"https://api.github.com/users/svanharmelen","html_url":"https://github.com/svanharmelen","followers_url":"https://api.github.com/users/svanharmelen/followers","following_url":"https://api.github.com/users/svanharmelen/following{/other_user}","gists_url":"https://api.github.com/users/svanharmelen/gists{/gist_id}","starred_url":"https://api.github.com/users/svanharmelen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/svanharmelen/subscriptions","organizations_url":"https://api.github.com/users/svanharmelen/orgs","repos_url":"https://api.github.com/users/svanharmelen/repos","events_url":"https://api.github.com/users/svanharmelen/events{/privacy}","received_events_url":"https://api.github.com/users/svanharmelen/received_events","type":"User","site_admin":false},"body":"The PR is pretty complete and has a tested provisioner that works for both SSH and WinRM. There is a pretty decent test coverage and docs are included in this PR as well.","created_at":"2015-05-08T16:24:40Z","updated_at":"2015-05-08T17:40:27Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e5e26a0e6575f1ebe40280c8ad3eb5af3c4bbdd2","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/hashicorp/terraform/pulls/1868/commits","review_comments_url":"https://api.github.com/repos/hashicorp/terraform/pulls/1868/comments","review_comment_url":"https://api.github.com/repos/hashicorp/terraform/pulls/comments{/number}","comments_url":"https://api.github.com/repos/hashicorp/terraform/issues/1868/comments","statuses_url":"https://api.github.com/repos/hashicorp/terraform/statuses/d4150d5b1a7869b5b511dd4becf3b470e98d3fd7","head":{"label":"svanharmelen:f-chef-client-provisioner","ref":"f-chef-client-provisioner","sha":"d4150d5b1a7869b5b511dd4becf3b470e98d3fd7","user":{"login":"svanharmelen","id":4171547,"avatar_url":"https://avatars.githubusercontent.com/u/4171547?v=3","gravatar_id":"","url":"https://api.github.com/users/svanharmelen","html_url":"https://github.com/svanharmelen","followers_url":"https://api.github.com/users/svanharmelen/followers","following_url":"https://api.github.com/users/svanharmelen/following{/other_user}","gists_url":"https://api.github.com/users/svanharmelen/gists{/gist_id}","starred_url":"https://api.github.com/users/svanharmelen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/svanharmelen/subscriptions","organizations_url":"https://api.github.com/users/svanharmelen/orgs","repos_url":"https://api.github.com/users/svanharmelen/repos","events_url":"https://api.github.com/users/svanharmelen/events{/privacy}","received_events_url":"https://api.github.com/users/svanharmelen/received_events","type":"User","site_admin":false},"repo":{"id":27924829,"name":"terraform","full_name":"svanharmelen/terraform","owner":{"login":"svanharmelen","id":4171547,"avatar_url":"https://avatars.githubusercontent.com/u/4171547?v=3","gravatar_id":"","url":"https://api.github.com/users/svanharmelen","html_url":"https://github.com/svanharmelen","followers_url":"https://api.github.com/users/svanharmelen/followers","following_url":"https://api.github.com/users/svanharmelen/following{/other_user}","gists_url":"https://api.github.com/users/svanharmelen/gists{/gist_id}","starred_url":"https://api.github.com/users/svanharmelen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/svanharmelen/subscriptions","organizations_url":"https://api.github.com/users/svanharmelen/orgs","repos_url":"https://api.github.com/users/svanharmelen/repos","events_url":"https://api.github.com/users/svanharmelen/events{/privacy}","received_events_url":"https://api.github.com/users/svanharmelen/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/svanharmelen/terraform","description":"Terraform is a tool for building, changing, and combining infrastructure safely and efficiently.","fork":true,"url":"https://api.github.com/repos/svanharmelen/terraform","forks_url":"https://api.github.com/repos/svanharmelen/terraform/forks","keys_url":"https://api.github.com/repos/svanharmelen/terraform/keys{/key_id}","collaborators_url":"https://api.github.com/repos/svanharmelen/terraform/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/svanharmelen/terraform/teams","hooks_url":"https://api.github.com/repos/svanharmelen/terraform/hooks","issue_events_url":"https://api.github.com/repos/svanharmelen/terraform/issues/events{/number}","events_url":"https://api.github.com/repos/svanharmelen/terraform/events","assignees_url":"https://api.github.com/repos/svanharmelen/terraform/assignees{/user}","branches_url":"https://api.github.com/repos/svanharmelen/terraform/branches{/branch}","tags_url":"https://api.github.com/repos/svanharmelen/terraform/tags","blobs_url":"https://api.github.com/repos/svanharmelen/terraform/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/svanharmelen/terraform/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/svanharmelen/terraform/git/refs{/sha}","trees_url":"https://api.github.com/repos/svanharmelen/terraform/git/trees{/sha}","statuses_url":"https://api.github.com/repos/svanharmelen/terraform/statuses/{sha}","languages_url":"https://api.github.com/repos/svanharmelen/terraform/languages","stargazers_url":"https://api.github.com/repos/svanharmelen/terraform/stargazers","contributors_url":"https://api.github.com/repos/svanharmelen/terraform/contributors","subscribers_url":"https://api.github.com/repos/svanharmelen/terraform/subscribers","subscription_url":"https://api.github.com/repos/svanharmelen/terraform/subscription","commits_url":"https://api.github.com/repos/svanharmelen/terraform/commits{/sha}","git_commits_url":"https://api.github.com/repos/svanharmelen/terraform/git/commits{/sha}","comments_url":"https://api.github.com/repos/svanharmelen/terraform/comments{/number}","issue_comment_url":"https://api.github.com/repos/svanharmelen/terraform/issues/comments{/number}","contents_url":"https://api.github.com/repos/svanharmelen/terraform/contents/{+path}","compare_url":"https://api.github.com/repos/svanharmelen/terraform/compare/{base}...{head}","merges_url":"https://api.github.com/repos/svanharmelen/terraform/merges","archive_url":"https://api.github.com/repos/svanharmelen/terraform/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/svanharmelen/terraform/downloads","issues_url":"https://api.github.com/repos/svanharmelen/terraform/issues{/number}","pulls_url":"https://api.github.com/repos/svanharmelen/terraform/pulls{/number}","milestones_url":"https://api.github.com/repos/svanharmelen/terraform/milestones{/number}","notifications_url":"https://api.github.com/repos/svanharmelen/terraform/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/svanharmelen/terraform/labels{/name}","releases_url":"https://api.github.com/repos/svanharmelen/terraform/releases{/id}","created_at":"2014-12-12T15:01:08Z","updated_at":"2015-05-08T12:54:30Z","pushed_at":"2015-05-08T16:18:02Z","git_url":"git://github.com/svanharmelen/terraform.git","ssh_url":"git@github.com:svanharmelen/terraform.git","clone_url":"https://github.com/svanharmelen/terraform.git","svn_url":"https://github.com/svanharmelen/terraform","homepage":"http://www.terraform.io","size":23054,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2,"mirror_url":null,"open_issues_count":3,"forks":2,"open_issues":3,"watchers":0,"default_branch":"master"}},"base":{"label":"hashicorp:master","ref":"master","sha":"8dd1f939e233f67c77c64837a422c784b4732e2c","user":{"login":"hashicorp","id":761456,"avatar_url":"https://avatars.githubusercontent.com/u/761456?v=3","gravatar_id":"","url":"https://api.github.com/users/hashicorp","html_url":"https://github.com/hashicorp","followers_url":"https://api.github.com/users/hashicorp/followers","following_url":"https://api.github.com/users/hashicorp/following{/other_user}","gists_url":"https://api.github.com/users/hashicorp/gists{/gist_id}","starred_url":"https://api.github.com/users/hashicorp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hashicorp/subscriptions","organizations_url":"https://api.github.com/users/hashicorp/orgs","repos_url":"https://api.github.com/users/hashicorp/repos","events_url":"https://api.github.com/users/hashicorp/events{/privacy}","received_events_url":"https://api.github.com/users/hashicorp/received_events","type":"Organization","site_admin":false},"repo":{"id":17728164,"name":"terraform","full_name":"hashicorp/terraform","owner":{"login":"hashicorp","id":761456,"avatar_url":"https://avatars.githubusercontent.com/u/761456?v=3","gravatar_id":"","url":"https://api.github.com/users/hashicorp","html_url":"https://github.com/hashicorp","followers_url":"https://api.github.com/users/hashicorp/followers","following_url":"https://api.github.com/users/hashicorp/following{/other_user}","gists_url":"https://api.github.com/users/hashicorp/gists{/gist_id}","starred_url":"https://api.github.com/users/hashicorp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hashicorp/subscriptions","organizations_url":"https://api.github.com/users/hashicorp/orgs","repos_url":"https://api.github.com/users/hashicorp/repos","events_url":"https://api.github.com/users/hashicorp/events{/privacy}","received_events_url":"https://api.github.com/users/hashicorp/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/hashicorp/terraform","description":"Terraform is a tool for building, changing, and combining infrastructure safely and efficiently.","fork":false,"url":"https://api.github.com/repos/hashicorp/terraform","forks_url":"https://api.github.com/repos/hashicorp/terraform/forks","keys_url":"https://api.github.com/repos/hashicorp/terraform/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hashicorp/terraform/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hashicorp/terraform/teams","hooks_url":"https://api.github.com/repos/hashicorp/terraform/hooks","issue_events_url":"https://api.github.com/repos/hashicorp/terraform/issues/events{/number}","events_url":"https://api.github.com/repos/hashicorp/terraform/events","assignees_url":"https://api.github.com/repos/hashicorp/terraform/assignees{/user}","branches_url":"https://api.github.com/repos/hashicorp/terraform/branches{/branch}","tags_url":"https://api.github.com/repos/hashicorp/terraform/tags","blobs_url":"https://api.github.com/repos/hashicorp/terraform/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hashicorp/terraform/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hashicorp/terraform/git/refs{/sha}","trees_url":"https://api.github.com/repos/hashicorp/terraform/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hashicorp/terraform/statuses/{sha}","languages_url":"https://api.github.com/repos/hashicorp/terraform/languages","stargazers_url":"https://api.github.com/repos/hashicorp/terraform/stargazers","contributors_url":"https://api.github.com/repos/hashicorp/terraform/contributors","subscribers_url":"https://api.github.com/repos/hashicorp/terraform/subscribers","subscription_url":"https://api.github.com/repos/hashicorp/terraform/subscription","commits_url":"https://api.github.com/repos/hashicorp/terraform/commits{/sha}","git_commits_url":"https://api.github.com/repos/hashicorp/terraform/git/commits{/sha}","comments_url":"https://api.github.com/repos/hashicorp/terraform/comments{/number}","issue_comment_url":"https://api.github.com/repos/hashicorp/terraform/issues/comments{/number}","contents_url":"https://api.github.com/repos/hashicorp/terraform/contents/{+path}","compare_url":"https://api.github.com/repos/hashicorp/terraform/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hashicorp/terraform/merges","archive_url":"https://api.github.com/repos/hashicorp/terraform/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hashicorp/terraform/downloads","issues_url":"https://api.github.com/repos/hashicorp/terraform/issues{/number}","pulls_url":"https://api.github.com/repos/hashicorp/terraform/pulls{/number}","milestones_url":"https://api.github.com/repos/hashicorp/terraform/milestones{/number}","notifications_url":"https://api.github.com/repos/hashicorp/terraform/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hashicorp/terraform/labels{/name}","releases_url":"https://api.github.com/repos/hashicorp/terraform/releases{/id}","created_at":"2014-03-13T22:25:48Z","updated_at":"2015-05-08T17:27:44Z","pushed_at":"2015-05-08T17:27:44Z","git_url":"git://github.com/hashicorp/terraform.git","ssh_url":"git@github.com:hashicorp/terraform.git","clone_url":"https://github.com/hashicorp/terraform.git","svn_url":"https://github.com/hashicorp/terraform","homepage":"http://www.terraform.io","size":47445,"stargazers_count":2362,"watchers_count":2362,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":417,"mirror_url":null,"open_issues_count":249,"forks":417,"open_issues":249,"watchers":2362,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/hashicorp/terraform/pulls/1868"},"html":{"href":"https://github.com/hashicorp/terraform/pull/1868"},"issue":{"href":"https://api.github.com/repos/hashicorp/terraform/issues/1868"},"comments":{"href":"https://api.github.com/repos/hashicorp/terraform/issues/1868/comments"},"review_comments":{"href":"https://api.github.com/repos/hashicorp/terraform/pulls/1868/comments"},"review_comment":{"href":"https://api.github.com/repos/hashicorp/terraform/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/hashicorp/terraform/pulls/1868/commits"},"statuses":{"href":"https://api.github.com/repos/hashicorp/terraform/statuses/d4150d5b1a7869b5b511dd4becf3b470e98d3fd7"}}}}