github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/model/cloudery/service.go (about) 1 package cloudery 2 3 import ( 4 "errors" 5 "fmt" 6 "net/url" 7 8 "github.com/cozy/cozy-stack/model/instance" 9 "github.com/cozy/cozy-stack/pkg/config/config" 10 "github.com/cozy/cozy-stack/pkg/manager" 11 ) 12 13 var ( 14 ErrInvalidContext = errors.New("missing or invalid context") 15 ) 16 17 // ClouderyService handle all the Cloudery actions. 18 type ClouderyService struct { 19 contexts map[string]config.ClouderyConfig 20 } 21 22 // NewService instantiate a new [ClouderyService]. 23 // 24 // If contexts arg is nil, nil will be returned. 25 func NewService(contexts map[string]config.ClouderyConfig) *ClouderyService { 26 if contexts == nil { 27 return nil 28 } 29 30 return &ClouderyService{contexts} 31 } 32 33 type SaveCmd struct { 34 Locale string 35 Email string 36 PublicName string 37 } 38 39 // SaveInstance data into the cloudery matching the instance context. 40 func (s *ClouderyService) SaveInstance(inst *instance.Instance, cmd *SaveCmd) error { 41 client, err := s.getClient(inst) 42 if err != nil { 43 return err 44 } 45 46 url := fmt.Sprintf("/api/v1/instances/%s?source=stack", url.PathEscape(inst.UUID)) 47 if err := client.Put(url, map[string]interface{}{ 48 "locale": cmd.Locale, 49 "email": cmd.Email, 50 "public_name": cmd.PublicName, 51 }); err != nil { 52 return fmt.Errorf("request failed: %w", err) 53 } 54 55 return nil 56 } 57 58 type BlockingSubscription struct { 59 Vendor string `json:"vendor,omitempty"` 60 } 61 62 func (s *ClouderyService) BlockingSubscription(inst *instance.Instance) (*BlockingSubscription, error) { 63 client, err := s.getClient(inst) 64 if err != nil { 65 return nil, err 66 } 67 68 url := fmt.Sprintf("/api/v1/instances/%s", url.PathEscape(inst.UUID)) 69 res, err := client.Get(url) 70 if err != nil { 71 return nil, fmt.Errorf("request failed: %w", err) 72 } 73 74 if hasBlockingSubscription(res) { 75 vendor, err := blockingSubscriptionVendor(res) 76 if err != nil { 77 return nil, err 78 } 79 80 return &BlockingSubscription{ 81 Vendor: vendor, 82 }, nil 83 } 84 85 return nil, nil 86 } 87 88 func hasBlockingSubscription(clouderyInstance map[string]interface{}) bool { 89 return clouderyInstance["has_blocking_subscription"] == true 90 } 91 92 func blockingSubscriptionVendor(clouderyInstance map[string]interface{}) (string, error) { 93 if vendor, ok := clouderyInstance["blocking_subscription_vendor"].(string); ok { 94 return vendor, nil 95 } 96 97 return "", fmt.Errorf("invalid blocking subscription vendor") 98 } 99 100 func (s *ClouderyService) getClient(inst *instance.Instance) (*manager.APIClient, error) { 101 cfg, ok := s.contexts[inst.ContextName] 102 if !ok { 103 cfg, ok = s.contexts[config.DefaultInstanceContext] 104 } 105 106 if !ok { 107 return nil, fmt.Errorf("%w: tried %q and %q", ErrInvalidContext, inst.ContextName, config.DefaultInstanceContext) 108 } 109 110 client := manager.NewAPIClient(cfg.API.URL, cfg.API.Token) 111 112 return client, nil 113 }