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  }