| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- package assets
- import (
- "context"
- "fmt"
- "os"
- "os/exec"
- "path/filepath"
- "strings"
- )
- type OSSUtilPublisher struct {
- ossutilPath string
- configFile string
- bucketRoot string
- publicBaseURL string
- }
- func NewOSSUtilPublisher(ossutilPath, configFile, bucketRoot, publicBaseURL string) *OSSUtilPublisher {
- return &OSSUtilPublisher{
- ossutilPath: strings.TrimSpace(ossutilPath),
- configFile: strings.TrimSpace(configFile),
- bucketRoot: strings.TrimRight(strings.TrimSpace(bucketRoot), "/"),
- publicBaseURL: strings.TrimRight(strings.TrimSpace(publicBaseURL), "/"),
- }
- }
- func (p *OSSUtilPublisher) Enabled() bool {
- return p != nil &&
- p.ossutilPath != "" &&
- p.configFile != "" &&
- p.bucketRoot != "" &&
- p.publicBaseURL != ""
- }
- func (p *OSSUtilPublisher) UploadJSON(ctx context.Context, publicURL string, payload []byte) error {
- if !p.Enabled() {
- return fmt.Errorf("asset publisher is not configured")
- }
- if len(payload) == 0 {
- return fmt.Errorf("payload is empty")
- }
- objectKey, err := p.objectKeyFromPublicURL(publicURL)
- if err != nil {
- return err
- }
- if _, err := os.Stat(p.ossutilPath); err != nil {
- return fmt.Errorf("ossutil not found: %w", err)
- }
- if _, err := os.Stat(p.configFile); err != nil {
- return fmt.Errorf("ossutil config not found: %w", err)
- }
- tmpFile, err := os.CreateTemp("", "cmr-manifest-*.json")
- if err != nil {
- return fmt.Errorf("create temp file: %w", err)
- }
- tmpPath := tmpFile.Name()
- defer os.Remove(tmpPath)
- if _, err := tmpFile.Write(payload); err != nil {
- tmpFile.Close()
- return fmt.Errorf("write temp file: %w", err)
- }
- if err := tmpFile.Close(); err != nil {
- return fmt.Errorf("close temp file: %w", err)
- }
- target := p.bucketRoot + "/" + objectKey
- cmd := exec.CommandContext(ctx, p.ossutilPath, "cp", "-f", tmpPath, target, "--config-file", p.configFile)
- output, err := cmd.CombinedOutput()
- if err != nil {
- return fmt.Errorf("upload object %s failed: %w: %s", objectKey, err, strings.TrimSpace(string(output)))
- }
- return nil
- }
- func (p *OSSUtilPublisher) objectKeyFromPublicURL(publicURL string) (string, error) {
- publicURL = strings.TrimSpace(publicURL)
- if publicURL == "" {
- return "", fmt.Errorf("public url is required")
- }
- if !strings.HasPrefix(publicURL, p.publicBaseURL+"/") {
- return "", fmt.Errorf("public url %s does not match public base %s", publicURL, p.publicBaseURL)
- }
- relative := strings.TrimPrefix(publicURL, p.publicBaseURL+"/")
- relative = strings.ReplaceAll(relative, "\\", "/")
- relative = strings.TrimLeft(relative, "/")
- if relative == "" {
- return "", fmt.Errorf("public url %s resolved to empty object key", publicURL)
- }
- return filepath.ToSlash(relative), nil
- }
|