github.com/IBM-Cloud/bluemix-go@v0.0.0-20240423071914-9e96525baef4/crn/crn.go (about) 1 package crn 2 3 import ( 4 "encoding/json" 5 "errors" 6 "strings" 7 ) 8 9 const ( 10 crn = "crn" 11 version = "v1" 12 13 crnSeparator = ":" 14 scopeSeparator = "/" 15 ) 16 17 var ( 18 ErrMalformedCRN = errors.New("malformed CRN") 19 ErrMalformedScope = errors.New("malformed scope in CRN") 20 ) 21 22 const ( 23 ServiceBluemix = "bluemix" 24 ServiceIAM = "iam" 25 // ServiceCF is the service name for public Cloudfoundry 26 ServiceCF = "cf" 27 // ServiceCFEE is the service name for CFEE Cloudfoundry 28 ServiceCFEE = "cfaas" 29 // more services ... 30 31 ScopeAccount = "a" 32 ScopeOrganization = "o" 33 ScopeSpace = "s" 34 ScopeProject = "p" 35 36 ResourceTypeCFSpace = "cf-space" 37 ResourceTypeCFApp = "cf-application" 38 ResourceTypeCFService = "cf-service-instance" 39 ResourceTypeRole = "role" 40 ResourceTypeDeployment = "deployment" 41 // more resources ... 42 ) 43 44 type CRN struct { 45 Scheme string 46 Version string 47 CName string 48 CType string 49 ServiceName string 50 Region string 51 ScopeType string 52 Scope string 53 ServiceInstance string 54 ResourceType string 55 Resource string 56 } 57 58 func New(cloudName string, cloudType string) CRN { 59 return CRN{ 60 Scheme: crn, 61 Version: version, 62 CName: cloudName, 63 CType: cloudType, 64 } 65 } 66 67 func (c *CRN) UnmarshalJSON(b []byte) error { 68 var s string 69 err := json.Unmarshal(b, &s) 70 if err != nil { 71 return err 72 } 73 74 *c, err = Parse(s) 75 return err 76 } 77 78 func (c CRN) MarshalJSON() ([]byte, error) { 79 return json.Marshal(c.String()) 80 } 81 82 func Parse(s string) (CRN, error) { 83 if s == "" { 84 return CRN{}, nil 85 } 86 87 segments := strings.Split(s, crnSeparator) 88 if len(segments) != 10 || segments[0] != crn { 89 return CRN{}, ErrMalformedCRN 90 } 91 92 crn := CRN{ 93 Scheme: segments[0], 94 Version: segments[1], 95 CName: segments[2], 96 CType: segments[3], 97 ServiceName: segments[4], 98 Region: segments[5], 99 ServiceInstance: segments[7], 100 ResourceType: segments[8], 101 Resource: segments[9], 102 } 103 104 scopeSegments := segments[6] 105 if scopeSegments != "" { 106 if scopeSegments == "global" { 107 crn.Scope = "global" 108 } else { 109 scopeParts := strings.Split(scopeSegments, scopeSeparator) 110 if len(scopeParts) == 2 { 111 crn.ScopeType, crn.Scope = scopeParts[0], scopeParts[1] 112 } else { 113 return CRN{}, ErrMalformedScope 114 } 115 } 116 } 117 118 return crn, nil 119 } 120 121 func (c CRN) String() string { 122 return strings.Join([]string{ 123 c.Scheme, 124 c.Version, 125 c.CName, 126 c.CType, 127 c.ServiceName, 128 c.Region, 129 c.ScopeSegment(), 130 c.ServiceInstance, 131 c.ResourceType, 132 c.Resource, 133 }, crnSeparator) 134 } 135 136 func (c CRN) ScopeSegment() string { 137 if c.ScopeType == "" { 138 return c.Scope 139 } 140 return c.ScopeType + scopeSeparator + c.Scope 141 }