func (id ID) Components() (namespace, kind, name string) {
	switch impl := id.resourceIDImpl.(type) {
	case resourceID:
		return impl.namespace, impl.kind, impl.name
	case legacyServiceID:
		return impl.namespace, "service", impl.service
	default:
		panic("wrong underlying type")
	}
}
Components returns the constituent components of a ID
package resource
import (
	"encoding/json"
	"fmt"
	"regexp"
	"sort"
	"strings"
	"github.com/pkg/errors"
)
var (
	ErrInvalidServiceID = errors.New("invalid service ID")
	LegacyServiceIDRegexp = regexp.MustCompile("^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)$")
	IDRegexp            = regexp.MustCompile("^(<cluster>|[a-zA-Z0-9_-]+):([a-zA-Z0-9_-]+)/([a-zA-Z0-9_.:-]+)$")
	UnqualifiedIDRegexp = regexp.MustCompile("^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_.:-]+)$")
)
type ID struct {
	resourceIDImpl
}
type resourceIDImpl interface {
	String() string
}
type legacyServiceID struct {
	namespace, service string
}
func (id legacyServiceID) String() string {
	return fmt.Sprintf("%s/%s", id.namespace, id.service)
}
type resourceID struct {
	namespace, kind, name string
}
func (id resourceID) String() string {
	return fmt.Sprintf("%s:%s/%s", id.namespace, id.kind, id.name)
}
func ParseID(s string) (ID, error) {
	if m := IDRegexp.FindStringSubmatch(s); m != nil {
		return ID{resourceID{m[1], strings.ToLower(m[2]), m[3]}}, nil
	}
	if m := LegacyServiceIDRegexp.FindStringSubmatch(s); m != nil {
		return ID{legacyServiceID{m[1], m[2]}}, nil
	}
	return ID{}, errors.Wrap(ErrInvalidServiceID, "parsing "+s)
}
func MustParseID(s string) ID {
	id, err := ParseID(s)
	if err != nil {
		panic(err)
	}
	return id
}
func ParseIDOptionalNamespace(namespace, s string) (ID, error) {
	if m := IDRegexp.FindStringSubmatch(s); m != nil {
		return ID{resourceID{m[1], strings.ToLower(m[2]), m[3]}}, nil
	}
	if m := UnqualifiedIDRegexp.FindStringSubmatch(s); m != nil {
		return ID{resourceID{namespace, strings.ToLower(m[1]), m[2]}}, nil
	}
	return ID{}, errors.Wrap(ErrInvalidServiceID, "parsing "+s)
}
func MakeID(namespace, kind, name string) ID {
	return ID{resourceID{namespace, strings.ToLower(kind), name}}
}