// Crappy workaround. RSC doesn't return the body of the http request which contains // the script source, so do the same lower level calls it does to get it. func getSource(loc *cm15.RightScriptLocator) (respBody []byte, err error) { var params rsapi.APIParams var p rsapi.APIParams APIVersion := "1.5" client, _ := Config.Account.Client15() uri, err := loc.ActionPath("RightScript", "show_source") if err != nil { return respBody, err } req, err := client.BuildHTTPRequest(uri.HTTPMethod, uri.Path, APIVersion, params, p) if err != nil { return respBody, err } resp, err := client.PerformRequest(req) if err != nil { return respBody, err } defer resp.Body.Close() respBody, _ = ioutil.ReadAll(resp.Body) if resp.StatusCode < 200 || resp.StatusCode > 299 { return respBody, fmt.Errorf("invalid response %s: %s", resp.Status, string(respBody)) } return respBody, nil }
func (r *RightScript) PushLocal(prefix string) error { client, _ := Config.Account.Client15() createLocator := client.RightScriptLocator("/api/right_scripts") scriptName := r.Metadata.Name if prefix != "" { scriptName = fmt.Sprintf("%s_%s", prefix, r.Metadata.Name) } foundId, err := rightScriptIdByName(scriptName) if err != nil { return err } fileSrc, err := ioutil.ReadFile(r.Path) if err != nil { return err } var rightscriptLocator *cm15.RightScriptLocator if foundId == "" { fmt.Printf(" Creating a new RightScript named '%s' from %s\n", scriptName, r.Path) // New one, perform create call params := cm15.RightScriptParam2{ Name: scriptName, Description: r.Metadata.Description, Packages: r.Metadata.Packages, Source: string(fileSrc), } rightscriptLocator, err = createLocator.Create(¶ms) if err != nil { return err } fmt.Printf(" RightScript created with HREF %s\n", rightscriptLocator.Href) r.Href = string(rightscriptLocator.Href) } else { // Found existing, do an update href := fmt.Sprintf("/api/right_scripts/%s", foundId) fmt.Printf(" Updating existing RightScript named '%s' with HREF %s from %s\n", scriptName, href, r.Path) params := cm15.RightScriptParam3{ Name: scriptName, Description: r.Metadata.Description, Packages: r.Metadata.Packages, Source: string(fileSrc), } rightscriptLocator = client.RightScriptLocator(href) err = rightscriptLocator.Update(¶ms) if err != nil { return err } r.Href = href } attachmentsHref := fmt.Sprintf("%s/attachments", rightscriptLocator.Href) attachmentsLocator := client.RightScriptAttachmentLocator(attachmentsHref) attachments, err := attachmentsLocator.Index(rsapi.APIParams{}) if err != nil { return err } toUpload := make(map[string]string) // scripts we want to upload onRightscript := make(map[string]*cm15.RightScriptAttachment) // scripts attached to the rightsript for _, a := range r.Metadata.Attachments { fullPath := filepath.Join(filepath.Dir(r.Path), "attachments", a) md5, err := fmd5sum(fullPath) if err != nil { return err } // We use a compound key with the name+md5 here to work around a couple corner cases // - if the file is renamed, it'll be deleted and reuploaded // - if two files have the same md5 for whatever reason they won't clash toUpload[path.Base(a)+"_"+md5] = a } for _, a := range attachments { onRightscript[path.Base(a.Filename)+"_"+a.Digest] = a } // Two passes. First pass we delete RightScripts. This comes up when a file was // removed from the RightScript, or when the contents of a file on disk changed. // In the second case, the second pass will reupload the correct attachment. for digestKey, a := range onRightscript { if _, ok := toUpload[digestKey]; !ok { loc := a.Locator(client) fmt.Printf(" Deleting attachment '%s' with HREF '%s'\n", a.Filename, loc.Href) err := loc.Destroy() if err != nil { return err } } } // Second pass, now upload any missing attachment and any attachments that were // deleted because we changed file contents. for digestKey, name := range toUpload { digestKeyParts := strings.Split(digestKey, "_") md5 := digestKeyParts[len(digestKeyParts)-1] if _, ok := onRightscript[digestKey]; ok { fmt.Printf(" Attachment '%s' already uploaded with md5 %s\n", name, md5) // TBD -- update if a.Name != name? } else { fullPath := filepath.Join(filepath.Dir(r.Path), "attachments", name) fmt.Printf(" Uploading attachment '%s' with md5 %s\n", name, md5) f, err := os.Open(fullPath) if err != nil { return err } // FileUpload represents payload fields that correspond to multipart file uploads. file := rsapi.FileUpload{Name: "right_script_attachment[content]", Reader: f, Filename: name} //params := cm15.RightScriptAttachmentParam{Content: &file, Name: a} err = uploadAttachment(attachmentsLocator, &file, path.Base(name)) if err != nil { return err } } } return err }