From 8abcbf397f69ff15835ba09bc6272cef473496e3 Mon Sep 17 00:00:00 2001 From: Harvey Xia Date: Tue, 8 Sep 2020 10:04:04 -0400 Subject: [PATCH 01/14] add namespace and policy rules to KubernetesCluster status --- api/multicluster/v1alpha1/cluster.proto | 36 +++ .../kubernetes-cluster-status-settings.yaml | 4 + .../test/api/things.test.io/v1/test_api.pb.go | 3 +- .../things.test.io/v1/test_api_json.gen.go | 3 +- .../v1/zz_generated.deepcopy.go | 7 + pkg/api/core.skv2.solo.io/v1/core.pb.go | 3 +- pkg/api/core.skv2.solo.io/v1/core_json.gen.go | 3 +- .../v1alpha1/cluster.pb.go | 254 +++++++++++++++--- .../v1alpha1/cluster.pb.hash.go | 78 ++++++ .../v1alpha1/cluster_json.gen.go | 14 +- pkg/multicluster/register/helpers.go | 48 +++- pkg/multicluster/register/interfaces.go | 4 +- .../register/mocks/mock_interfaces.go | 8 +- pkg/multicluster/register/registrant.go | 12 +- pkg/multicluster/register/registrant_test.go | 22 +- 15 files changed, 440 insertions(+), 59 deletions(-) create mode 100644 changelog/v0.11.2/kubernetes-cluster-status-settings.yaml diff --git a/api/multicluster/v1alpha1/cluster.proto b/api/multicluster/v1alpha1/cluster.proto index 2b5268ec9..d80eef5dd 100644 --- a/api/multicluster/v1alpha1/cluster.proto +++ b/api/multicluster/v1alpha1/cluster.proto @@ -56,4 +56,40 @@ message KubernetesClusterStatus { // List of statuses about the kubernetes cluster. // This list allows for multiple applications/pods to record their connection status. repeated core.skv2.solo.io.Status status = 1; + + // The namespace on in which cluster registration resources are created. + string namespace = 2; + + // JSON representation of the set of PolicyRules to attach to the newly created ClusterRole when registering clusters. + repeated PolicyRule policy_rules = 3; +} + +/* + Copy pasted from the official kubernetes definition: + https://github.com/kubernetes/api/blob/697df40f2d58d7d48b180b83d7b9b2b5ff812923/rbac/v1alpha1/generated.proto#L98 + PolicyRule holds information that describes a policy rule, but does not contain information + about who the rule applies to or which namespace the rule applies to. + */ +message PolicyRule { + // Verbs is a list of Verbs that apply to ALL the ResourceKinds and AttributeRestrictions contained in this rule. VerbAll represents all kinds. + repeated string verbs = 1; + + // APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of + // the enumerated resources in any API group will be allowed. + // +optional + repeated string api_groups = 2; + + // Resources is a list of resources this rule applies to. ResourceAll represents all resources. + // +optional + repeated string resources = 3; + + // ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. + // +optional + repeated string resource_names = 4; + + // NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path + // Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding. + // Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"), but not both. + // +optional + repeated string non_resource_urls = 5; } diff --git a/changelog/v0.11.2/kubernetes-cluster-status-settings.yaml b/changelog/v0.11.2/kubernetes-cluster-status-settings.yaml new file mode 100644 index 000000000..5182a285d --- /dev/null +++ b/changelog/v0.11.2/kubernetes-cluster-status-settings.yaml @@ -0,0 +1,4 @@ +changelog: + - type: NEW_FEATURE + description: Extend KubernetesCluster CRD status with namespace and policy rules it was registered with. + issueLink: https://github.com/solo-io/skv2/issues/142 diff --git a/codegen/test/api/things.test.io/v1/test_api.pb.go b/codegen/test/api/things.test.io/v1/test_api.pb.go index 6f2ac41ea..1836d93b2 100644 --- a/codegen/test/api/things.test.io/v1/test_api.pb.go +++ b/codegen/test/api/things.test.io/v1/test_api.pb.go @@ -5,9 +5,8 @@ package v1 import ( fmt "fmt" - math "math" - proto "github.com/gogo/protobuf/proto" + math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/codegen/test/api/things.test.io/v1/test_api_json.gen.go b/codegen/test/api/things.test.io/v1/test_api_json.gen.go index adce788f2..824b0ffd5 100644 --- a/codegen/test/api/things.test.io/v1/test_api_json.gen.go +++ b/codegen/test/api/things.test.io/v1/test_api_json.gen.go @@ -6,10 +6,9 @@ package v1 import ( bytes "bytes" fmt "fmt" - math "math" - github_com_gogo_protobuf_jsonpb "github.com/gogo/protobuf/jsonpb" proto "github.com/gogo/protobuf/proto" + math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/codegen/test/api/things.test.io/v1/zz_generated.deepcopy.go b/codegen/test/api/things.test.io/v1/zz_generated.deepcopy.go index 7e32d3661..21ebd18a5 100644 --- a/codegen/test/api/things.test.io/v1/zz_generated.deepcopy.go +++ b/codegen/test/api/things.test.io/v1/zz_generated.deepcopy.go @@ -14,8 +14,12 @@ func (in *Paint) DeepCopyInto(out *Paint) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + + // deepcopy spec in.Spec.DeepCopyInto(&out.Spec) + // deepcopy status in.Status.DeepCopyInto(&out.Status) + return } @@ -71,7 +75,10 @@ func (in *ClusterResource) DeepCopyInto(out *ClusterResource) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + + // deepcopy spec in.Spec.DeepCopyInto(&out.Spec) + return } diff --git a/pkg/api/core.skv2.solo.io/v1/core.pb.go b/pkg/api/core.skv2.solo.io/v1/core.pb.go index 56ed5cb56..c64fbfd8e 100644 --- a/pkg/api/core.skv2.solo.io/v1/core.pb.go +++ b/pkg/api/core.skv2.solo.io/v1/core.pb.go @@ -6,12 +6,11 @@ package v1 import ( bytes "bytes" fmt "fmt" - math "math" - _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" types "github.com/gogo/protobuf/types" _ "github.com/solo-io/protoc-gen-ext/extproto" + math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/pkg/api/core.skv2.solo.io/v1/core_json.gen.go b/pkg/api/core.skv2.solo.io/v1/core_json.gen.go index 5b0b8f1e1..0dfdd432d 100644 --- a/pkg/api/core.skv2.solo.io/v1/core_json.gen.go +++ b/pkg/api/core.skv2.solo.io/v1/core_json.gen.go @@ -6,13 +6,12 @@ package v1 import ( bytes "bytes" fmt "fmt" - math "math" - _ "github.com/gogo/protobuf/gogoproto" github_com_gogo_protobuf_jsonpb "github.com/gogo/protobuf/jsonpb" proto "github.com/gogo/protobuf/proto" _ "github.com/gogo/protobuf/types" _ "github.com/solo-io/protoc-gen-ext/extproto" + math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go b/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go index 3b0f39f32..63fe80329 100644 --- a/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go +++ b/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go @@ -6,12 +6,11 @@ package v1alpha1 import ( bytes "bytes" fmt "fmt" - math "math" - _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" _ "github.com/solo-io/protoc-gen-ext/extproto" v1 "github.com/solo-io/skv2/pkg/api/core.skv2.solo.io/v1" + math "math" ) // Reference imports to suppress errors if they are not otherwise used. @@ -225,10 +224,14 @@ func (m *KubernetesClusterSpec_Eks) GetName() string { type KubernetesClusterStatus struct { // List of statuses about the kubernetes cluster. // This list allows for multiple applications/pods to record their connection status. - Status []*v1.Status `protobuf:"bytes,1,rep,name=status,proto3" json:"status,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Status []*v1.Status `protobuf:"bytes,1,rep,name=status,proto3" json:"status,omitempty"` + // The namespace on in which cluster registration resources are created. + Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` + // JSON representation of the set of PolicyRules to attach to the newly created ClusterRole when registering clusters. + PolicyRules []*PolicyRule `protobuf:"bytes,3,rep,name=policy_rules,json=policyRules,proto3" json:"policy_rules,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *KubernetesClusterStatus) Reset() { *m = KubernetesClusterStatus{} } @@ -262,11 +265,113 @@ func (m *KubernetesClusterStatus) GetStatus() []*v1.Status { return nil } +func (m *KubernetesClusterStatus) GetNamespace() string { + if m != nil { + return m.Namespace + } + return "" +} + +func (m *KubernetesClusterStatus) GetPolicyRules() []*PolicyRule { + if m != nil { + return m.PolicyRules + } + return nil +} + +// +//Copy pasted from the official kubernetes definition: +//https://github.com/kubernetes/api/blob/697df40f2d58d7d48b180b83d7b9b2b5ff812923/rbac/v1alpha1/generated.proto#L98 +//PolicyRule holds information that describes a policy rule, but does not contain information +//about who the rule applies to or which namespace the rule applies to. +type PolicyRule struct { + // Verbs is a list of Verbs that apply to ALL the ResourceKinds and AttributeRestrictions contained in this rule. VerbAll represents all kinds. + Verbs []string `protobuf:"bytes,1,rep,name=verbs,proto3" json:"verbs,omitempty"` + // APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of + // the enumerated resources in any API group will be allowed. + // +optional + ApiGroups []string `protobuf:"bytes,2,rep,name=api_groups,json=apiGroups,proto3" json:"api_groups,omitempty"` + // Resources is a list of resources this rule applies to. ResourceAll represents all resources. + // +optional + Resources []string `protobuf:"bytes,3,rep,name=resources,proto3" json:"resources,omitempty"` + // ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. + // +optional + ResourceNames []string `protobuf:"bytes,4,rep,name=resource_names,json=resourceNames,proto3" json:"resource_names,omitempty"` + // NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path + // Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding. + // Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"), but not both. + // +optional + NonResourceUrls []string `protobuf:"bytes,5,rep,name=non_resource_urls,json=nonResourceUrls,proto3" json:"non_resource_urls,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *PolicyRule) Reset() { *m = PolicyRule{} } +func (m *PolicyRule) String() string { return proto.CompactTextString(m) } +func (*PolicyRule) ProtoMessage() {} +func (*PolicyRule) Descriptor() ([]byte, []int) { + return fileDescriptor_533baf1d8d7a56a7, []int{2} +} +func (m *PolicyRule) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_PolicyRule.Unmarshal(m, b) +} +func (m *PolicyRule) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_PolicyRule.Marshal(b, m, deterministic) +} +func (m *PolicyRule) XXX_Merge(src proto.Message) { + xxx_messageInfo_PolicyRule.Merge(m, src) +} +func (m *PolicyRule) XXX_Size() int { + return xxx_messageInfo_PolicyRule.Size(m) +} +func (m *PolicyRule) XXX_DiscardUnknown() { + xxx_messageInfo_PolicyRule.DiscardUnknown(m) +} + +var xxx_messageInfo_PolicyRule proto.InternalMessageInfo + +func (m *PolicyRule) GetVerbs() []string { + if m != nil { + return m.Verbs + } + return nil +} + +func (m *PolicyRule) GetApiGroups() []string { + if m != nil { + return m.ApiGroups + } + return nil +} + +func (m *PolicyRule) GetResources() []string { + if m != nil { + return m.Resources + } + return nil +} + +func (m *PolicyRule) GetResourceNames() []string { + if m != nil { + return m.ResourceNames + } + return nil +} + +func (m *PolicyRule) GetNonResourceUrls() []string { + if m != nil { + return m.NonResourceUrls + } + return nil +} + func init() { proto.RegisterType((*KubernetesClusterSpec)(nil), "multicluster.solo.io.KubernetesClusterSpec") proto.RegisterType((*KubernetesClusterSpec_ProviderInfo)(nil), "multicluster.solo.io.KubernetesClusterSpec.ProviderInfo") proto.RegisterType((*KubernetesClusterSpec_Eks)(nil), "multicluster.solo.io.KubernetesClusterSpec.Eks") proto.RegisterType((*KubernetesClusterStatus)(nil), "multicluster.solo.io.KubernetesClusterStatus") + proto.RegisterType((*PolicyRule)(nil), "multicluster.solo.io.PolicyRule") } func init() { @@ -274,33 +379,41 @@ func init() { } var fileDescriptor_533baf1d8d7a56a7 = []byte{ - // 410 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0x51, 0x8b, 0x13, 0x31, - 0x10, 0xc7, 0x5d, 0xb7, 0x14, 0x3a, 0xbd, 0x13, 0x09, 0x55, 0x6b, 0x45, 0x2d, 0x07, 0x42, 0x5f, - 0x4c, 0x68, 0x7d, 0xf1, 0x45, 0x84, 0x3b, 0x0f, 0x3d, 0x14, 0x91, 0xf5, 0x4d, 0x90, 0x25, 0xdd, - 0xce, 0xed, 0x85, 0xed, 0x66, 0x42, 0x92, 0x5d, 0xce, 0x0f, 0xe1, 0xf7, 0xf0, 0x23, 0xf8, 0x79, - 0xfc, 0x0e, 0xbe, 0xcb, 0x66, 0x63, 0xa9, 0xdc, 0xf9, 0x70, 0x4f, 0x3b, 0xf9, 0xe5, 0xbf, 0x33, - 0xff, 0x99, 0x0c, 0xbc, 0x2e, 0x95, 0xbf, 0x68, 0xd6, 0xbc, 0xa0, 0x5a, 0x38, 0xda, 0xd2, 0x73, - 0x45, 0xc2, 0x55, 0xed, 0x4a, 0x48, 0xa3, 0x44, 0xdd, 0x6c, 0xbd, 0x2a, 0xb6, 0x8d, 0xf3, 0x68, - 0x45, 0xbb, 0x94, 0x5b, 0x73, 0x21, 0x97, 0x22, 0x02, 0x6e, 0x2c, 0x79, 0x62, 0x93, 0x7d, 0x11, - 0xef, 0x52, 0x70, 0x45, 0xb3, 0x49, 0x49, 0x25, 0x05, 0x81, 0xe8, 0xa2, 0x5e, 0x3b, 0x63, 0x78, - 0xe9, 0x7b, 0x88, 0x97, 0x3e, 0xb2, 0x47, 0xbb, 0x6a, 0x05, 0x59, 0x14, 0xed, 0x32, 0x7c, 0xfb, - 0xcb, 0xa3, 0xef, 0x29, 0xdc, 0x7b, 0xdf, 0xac, 0xd1, 0x6a, 0xf4, 0xe8, 0x4e, 0xfa, 0x22, 0x9f, - 0x0d, 0x16, 0xec, 0x29, 0x8c, 0x1d, 0x16, 0x16, 0x7d, 0xae, 0x65, 0x8d, 0xd3, 0x64, 0x9e, 0x2c, - 0x46, 0x19, 0xf4, 0xe8, 0xa3, 0xac, 0x91, 0x3d, 0x83, 0x3b, 0xd1, 0x54, 0xbe, 0xa1, 0x5a, 0x2a, - 0x3d, 0xbd, 0x1d, 0x34, 0x87, 0x91, 0xbe, 0x09, 0x90, 0x7d, 0x85, 0x43, 0x63, 0xa9, 0x55, 0x1b, - 0xb4, 0xb9, 0xd2, 0xe7, 0x34, 0x4d, 0xe7, 0xc9, 0x62, 0xbc, 0x7a, 0xc9, 0xaf, 0x6b, 0x8b, 0x5f, - 0xeb, 0x85, 0x7f, 0x8a, 0x09, 0xce, 0xf4, 0x39, 0x65, 0x07, 0x66, 0xef, 0x34, 0x53, 0x70, 0xb0, - 0x7f, 0xcb, 0x4e, 0x20, 0xc5, 0xca, 0x05, 0xbb, 0xe3, 0x95, 0xb8, 0x49, 0x91, 0xd3, 0xca, 0xbd, - 0xbb, 0x95, 0x75, 0x7f, 0x1f, 0x4f, 0x80, 0xfd, 0xe3, 0x39, 0xf7, 0xdf, 0x0c, 0xce, 0xd6, 0x90, - 0x9e, 0x56, 0x8e, 0xdd, 0x85, 0x54, 0x5a, 0x1d, 0x07, 0xd2, 0x85, 0xec, 0x31, 0x80, 0x2c, 0x0a, - 0x6a, 0xb4, 0xcf, 0xd5, 0x26, 0x4e, 0x61, 0x14, 0xc9, 0xd9, 0x86, 0xdd, 0x87, 0xa1, 0xc5, 0x52, - 0x91, 0x0e, 0xad, 0x8f, 0xb2, 0x78, 0x62, 0x0c, 0x06, 0x61, 0xb4, 0x83, 0x40, 0x43, 0x7c, 0xf4, - 0x01, 0x1e, 0x5c, 0x75, 0xe7, 0xa5, 0x6f, 0x1c, 0x5b, 0xc2, 0xd0, 0x85, 0x68, 0x9a, 0xcc, 0xd3, - 0xc5, 0x78, 0xf5, 0x90, 0x87, 0x77, 0xec, 0x5e, 0x77, 0xd7, 0x59, 0x2f, 0xcd, 0xa2, 0xf0, 0xf8, - 0xed, 0xcf, 0xdf, 0x83, 0xe4, 0xc7, 0xaf, 0x27, 0xc9, 0x97, 0x57, 0xff, 0xdb, 0x42, 0x53, 0x95, - 0x57, 0x36, 0xf1, 0x6f, 0xba, 0xdd, 0x46, 0xae, 0x87, 0x61, 0x5b, 0x5e, 0xfc, 0x09, 0x00, 0x00, - 0xff, 0xff, 0x96, 0x18, 0x77, 0x4b, 0xcd, 0x02, 0x00, 0x00, + // 537 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x93, 0xdd, 0x6a, 0x13, 0x41, + 0x14, 0xc7, 0xdd, 0x6e, 0x5a, 0xd8, 0x93, 0xd6, 0x8f, 0x21, 0xea, 0x1a, 0xbf, 0x42, 0x40, 0x08, + 0x82, 0xbb, 0x24, 0xde, 0x78, 0x23, 0x42, 0x63, 0xa9, 0x45, 0x90, 0xb2, 0xe2, 0x8d, 0x20, 0xcb, + 0x64, 0x33, 0xdd, 0x0e, 0xd9, 0xcc, 0x19, 0xe6, 0x23, 0xb4, 0x0f, 0xe1, 0x7b, 0x78, 0x27, 0x78, + 0xe5, 0xf3, 0xf8, 0x0e, 0xde, 0xcb, 0xce, 0x4e, 0xb6, 0x91, 0xc6, 0x0b, 0xaf, 0x72, 0xce, 0xef, + 0xfc, 0x73, 0xe6, 0x3f, 0x67, 0xe7, 0xc0, 0x9b, 0x92, 0x9b, 0x73, 0x3b, 0x4b, 0x0a, 0x5c, 0xa6, + 0x1a, 0x2b, 0x7c, 0xc1, 0x31, 0xd5, 0x8b, 0xd5, 0x24, 0xa5, 0x92, 0xa7, 0x4b, 0x5b, 0x19, 0x5e, + 0x54, 0x56, 0x1b, 0xa6, 0xd2, 0xd5, 0x98, 0x56, 0xf2, 0x9c, 0x8e, 0x53, 0x0f, 0x12, 0xa9, 0xd0, + 0x20, 0xe9, 0x6d, 0x8a, 0x92, 0xba, 0x45, 0xc2, 0xb1, 0xdf, 0x2b, 0xb1, 0x44, 0x27, 0x48, 0xeb, + 0xa8, 0xd1, 0xf6, 0x09, 0xbb, 0x30, 0x0d, 0x64, 0x17, 0xc6, 0xb3, 0x87, 0xed, 0x69, 0x05, 0x2a, + 0x96, 0xae, 0xc6, 0xee, 0xb7, 0x29, 0x0e, 0xbf, 0x86, 0x70, 0xf7, 0xbd, 0x9d, 0x31, 0x25, 0x98, + 0x61, 0x7a, 0xda, 0x1c, 0xf2, 0x51, 0xb2, 0x82, 0x3c, 0x85, 0xae, 0x66, 0x85, 0x62, 0x26, 0x17, + 0x74, 0xc9, 0xe2, 0x60, 0x10, 0x8c, 0xa2, 0x0c, 0x1a, 0xf4, 0x81, 0x2e, 0x19, 0x79, 0x06, 0x37, + 0xbd, 0xa9, 0x7c, 0x8e, 0x4b, 0xca, 0x45, 0xbc, 0xe3, 0x34, 0x07, 0x9e, 0xbe, 0x75, 0x90, 0x7c, + 0x81, 0x03, 0xa9, 0x70, 0xc5, 0xe7, 0x4c, 0xe5, 0x5c, 0x9c, 0x61, 0x1c, 0x0e, 0x82, 0x51, 0x77, + 0xf2, 0x2a, 0xd9, 0x76, 0xad, 0x64, 0xab, 0x97, 0xe4, 0xd4, 0x37, 0x38, 0x11, 0x67, 0x98, 0xed, + 0xcb, 0x8d, 0xac, 0xcf, 0x61, 0x7f, 0xb3, 0x4a, 0xa6, 0x10, 0xb2, 0x85, 0x76, 0x76, 0xbb, 0x93, + 0xf4, 0x7f, 0x0e, 0x39, 0x5a, 0xe8, 0x77, 0x37, 0xb2, 0xfa, 0xdf, 0x87, 0x3d, 0x20, 0x7f, 0x79, + 0xce, 0xcd, 0xa5, 0x64, 0xfd, 0x19, 0x84, 0x47, 0x0b, 0x4d, 0x6e, 0x43, 0x48, 0x95, 0xf0, 0x03, + 0xa9, 0x43, 0xf2, 0x18, 0x80, 0x16, 0x05, 0x5a, 0x61, 0x72, 0x3e, 0xf7, 0x53, 0x88, 0x3c, 0x39, + 0x99, 0x93, 0x7b, 0xb0, 0xa7, 0x58, 0xc9, 0x51, 0xb8, 0xab, 0x47, 0x99, 0xcf, 0x08, 0x81, 0x8e, + 0x1b, 0x6d, 0xc7, 0x51, 0x17, 0x0f, 0xbf, 0x07, 0x70, 0xff, 0xba, 0x3d, 0x43, 0x8d, 0xd5, 0x64, + 0x0c, 0x7b, 0xda, 0x45, 0x71, 0x30, 0x08, 0x47, 0xdd, 0xc9, 0x83, 0xc4, 0x7d, 0xc8, 0xfa, 0xf3, + 0xb6, 0x57, 0x6b, 0xa4, 0x99, 0x17, 0x92, 0x47, 0x10, 0xd5, 0x6d, 0xb5, 0xa4, 0x05, 0x5b, 0x1b, + 0x6b, 0x01, 0x99, 0xc2, 0xbe, 0xc4, 0x8a, 0x17, 0x97, 0xb9, 0xb2, 0x15, 0xd3, 0x71, 0xe8, 0xda, + 0x0e, 0xb6, 0x0f, 0xed, 0xd4, 0x29, 0x33, 0x5b, 0xb1, 0xac, 0x2b, 0xdb, 0x58, 0x0f, 0x7f, 0x04, + 0x00, 0x57, 0x35, 0xd2, 0x83, 0xdd, 0x15, 0x53, 0xb3, 0xc6, 0x63, 0x94, 0x35, 0x89, 0x9b, 0x90, + 0xe4, 0x79, 0xa9, 0xd0, 0x4a, 0x1d, 0xef, 0xb8, 0x52, 0x44, 0x25, 0x3f, 0x76, 0xa0, 0xb6, 0xa9, + 0x98, 0x46, 0xab, 0x0a, 0xef, 0x22, 0xca, 0xae, 0x40, 0xfd, 0xd0, 0xd6, 0x89, 0x7b, 0x8b, 0x3a, + 0xee, 0x38, 0xc9, 0xc1, 0x9a, 0xd6, 0xcf, 0x51, 0x93, 0xe7, 0x70, 0x47, 0xa0, 0xc8, 0x5b, 0xa9, + 0x55, 0x95, 0x8e, 0x77, 0x9d, 0xf2, 0x96, 0x40, 0x91, 0x79, 0xfe, 0x49, 0x55, 0xfa, 0xf0, 0xf8, + 0xe7, 0xef, 0x4e, 0xf0, 0xed, 0xd7, 0x93, 0xe0, 0xf3, 0xeb, 0x7f, 0xad, 0xa7, 0x5c, 0x94, 0xd7, + 0x56, 0x74, 0x3d, 0x8c, 0x76, 0x55, 0x67, 0x7b, 0x6e, 0x8d, 0x5e, 0xfe, 0x09, 0x00, 0x00, 0xff, + 0xff, 0x68, 0xc4, 0x21, 0x30, 0xe6, 0x03, 0x00, 0x00, } func (this *KubernetesClusterSpec) Equal(that interface{}) bool { @@ -456,6 +569,81 @@ func (this *KubernetesClusterStatus) Equal(that interface{}) bool { return false } } + if this.Namespace != that1.Namespace { + return false + } + if len(this.PolicyRules) != len(that1.PolicyRules) { + return false + } + for i := range this.PolicyRules { + if !this.PolicyRules[i].Equal(that1.PolicyRules[i]) { + return false + } + } + if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { + return false + } + return true +} +func (this *PolicyRule) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PolicyRule) + if !ok { + that2, ok := that.(PolicyRule) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if len(this.Verbs) != len(that1.Verbs) { + return false + } + for i := range this.Verbs { + if this.Verbs[i] != that1.Verbs[i] { + return false + } + } + if len(this.ApiGroups) != len(that1.ApiGroups) { + return false + } + for i := range this.ApiGroups { + if this.ApiGroups[i] != that1.ApiGroups[i] { + return false + } + } + if len(this.Resources) != len(that1.Resources) { + return false + } + for i := range this.Resources { + if this.Resources[i] != that1.Resources[i] { + return false + } + } + if len(this.ResourceNames) != len(that1.ResourceNames) { + return false + } + for i := range this.ResourceNames { + if this.ResourceNames[i] != that1.ResourceNames[i] { + return false + } + } + if len(this.NonResourceUrls) != len(that1.NonResourceUrls) { + return false + } + for i := range this.NonResourceUrls { + if this.NonResourceUrls[i] != that1.NonResourceUrls[i] { + return false + } + } if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) { return false } diff --git a/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.hash.go b/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.hash.go index fb7706551..57074d269 100644 --- a/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.hash.go +++ b/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.hash.go @@ -94,6 +94,84 @@ func (m *KubernetesClusterStatus) Hash(hasher hash.Hash64) (uint64, error) { } + if _, err = hasher.Write([]byte(m.GetNamespace())); err != nil { + return 0, err + } + + for _, v := range m.GetPolicyRules() { + + if h, ok := interface{}(v).(safe_hasher.SafeHasher); ok { + if _, err = h.Hash(hasher); err != nil { + return 0, err + } + } else { + if val, err := hashstructure.Hash(v, nil); err != nil { + return 0, err + } else { + if err := binary.Write(hasher, binary.LittleEndian, val); err != nil { + return 0, err + } + } + } + + } + + return hasher.Sum64(), nil +} + +// Hash function +func (m *PolicyRule) Hash(hasher hash.Hash64) (uint64, error) { + if m == nil { + return 0, nil + } + if hasher == nil { + hasher = fnv.New64() + } + var err error + if _, err = hasher.Write([]byte("multicluster.solo.io.github.com/solo-io/skv2/pkg/api/multicluster.solo.io/v1alpha1.PolicyRule")); err != nil { + return 0, err + } + + for _, v := range m.GetVerbs() { + + if _, err = hasher.Write([]byte(v)); err != nil { + return 0, err + } + + } + + for _, v := range m.GetApiGroups() { + + if _, err = hasher.Write([]byte(v)); err != nil { + return 0, err + } + + } + + for _, v := range m.GetResources() { + + if _, err = hasher.Write([]byte(v)); err != nil { + return 0, err + } + + } + + for _, v := range m.GetResourceNames() { + + if _, err = hasher.Write([]byte(v)); err != nil { + return 0, err + } + + } + + for _, v := range m.GetNonResourceUrls() { + + if _, err = hasher.Write([]byte(v)); err != nil { + return 0, err + } + + } + return hasher.Sum64(), nil } diff --git a/pkg/api/multicluster.solo.io/v1alpha1/cluster_json.gen.go b/pkg/api/multicluster.solo.io/v1alpha1/cluster_json.gen.go index dc9455529..e73fce13c 100644 --- a/pkg/api/multicluster.solo.io/v1alpha1/cluster_json.gen.go +++ b/pkg/api/multicluster.solo.io/v1alpha1/cluster_json.gen.go @@ -6,13 +6,12 @@ package v1alpha1 import ( bytes "bytes" fmt "fmt" - math "math" - _ "github.com/gogo/protobuf/gogoproto" github_com_gogo_protobuf_jsonpb "github.com/gogo/protobuf/jsonpb" proto "github.com/gogo/protobuf/proto" _ "github.com/solo-io/protoc-gen-ext/extproto" _ "github.com/solo-io/skv2/pkg/api/core.skv2.solo.io/v1" + math "math" ) // Reference imports to suppress errors if they are not otherwise used. @@ -64,6 +63,17 @@ func (this *KubernetesClusterStatus) UnmarshalJSON(b []byte) error { return ClusterUnmarshaler.Unmarshal(bytes.NewReader(b), this) } +// MarshalJSON is a custom marshaler for PolicyRule +func (this *PolicyRule) MarshalJSON() ([]byte, error) { + str, err := ClusterMarshaler.MarshalToString(this) + return []byte(str), err +} + +// UnmarshalJSON is a custom unmarshaler for PolicyRule +func (this *PolicyRule) UnmarshalJSON(b []byte) error { + return ClusterUnmarshaler.Unmarshal(bytes.NewReader(b), this) +} + var ( ClusterMarshaler = &github_com_gogo_protobuf_jsonpb.Marshaler{} ClusterUnmarshaler = &github_com_gogo_protobuf_jsonpb.Unmarshaler{} diff --git a/pkg/multicluster/register/helpers.go b/pkg/multicluster/register/helpers.go index 3fc36bf8f..130954a4e 100644 --- a/pkg/multicluster/register/helpers.go +++ b/pkg/multicluster/register/helpers.go @@ -86,11 +86,9 @@ func (opts RegistrationOptions) RegisterCluster( } /* - RegisterCluster is meant to be a helper function to easily "register" a remote cluster. - Currently this entails: - 1. Creating a `ServiceAccount` on the remote cluster. - 2. Binding RBAC `Roles/ClusterRoles` to said `ServiceAccount` - 3. And finally creating a kubeconfig `Secret` with the BearerToken of the remote `ServiceAccount` + RegisterProviderCluster augments RegisterCluster functionality + with additional metadata to persist to the resulting KubernetesCluster object. + ProviderInfo contains cloud provider metadata. */ func (opts RegistrationOptions) RegisterProviderCluster( ctx context.Context, @@ -100,7 +98,30 @@ func (opts RegistrationOptions) RegisterProviderCluster( if err != nil { return err } - return RegisterProviderClusterFromConfig(ctx, masterRestCfg, remoteCfg, rbacOpts, registrant, providerInfo) + // Parse ClusterRole policy rules and pass into RegisterProviderClusterFromConfig in order to persist them to the resulting + // KubernetesCluster status. + var clusterRolePolicyRules []*v1alpha1.PolicyRule + for _, clusterRole := range opts.ClusterRoles { + for _, policyRules := range clusterRole.Rules { + clusterRolePolicyRules = append(clusterRolePolicyRules, &v1alpha1.PolicyRule{ + Verbs: policyRules.Verbs, + ApiGroups: policyRules.APIGroups, + Resources: policyRules.Resources, + ResourceNames: policyRules.ResourceNames, + NonResourceUrls: policyRules.NonResourceURLs, + }) + } + } + return RegisterProviderClusterFromConfig( + ctx, + masterRestCfg, + remoteCfg, + rbacOpts, + registrant, + providerInfo, + opts.RemoteNamespace, + clusterRolePolicyRules, + ) } /* @@ -158,7 +179,7 @@ func RegisterClusterFromConfig( opts RbacOptions, registrant ClusterRegistrant, ) error { - return RegisterProviderClusterFromConfig(ctx, masterClusterCfg, remoteCfg, opts, registrant, nil) + return RegisterProviderClusterFromConfig(ctx, masterClusterCfg, remoteCfg, opts, registrant, nil, "", nil) } func RegisterProviderClusterFromConfig( @@ -168,6 +189,8 @@ func RegisterProviderClusterFromConfig( opts RbacOptions, registrant ClusterRegistrant, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, + namespace string, + policyRules []*v1alpha1.PolicyRule, ) error { sa, err := registrant.EnsureRemoteServiceAccount(ctx, remoteCfg, opts.Options) if err != nil { @@ -182,7 +205,16 @@ func RegisterProviderClusterFromConfig( return err } - return registrant.RegisterProviderClusterWithToken(ctx, masterClusterCfg, remoteCfg, token, opts.Options, providerInfo) + return registrant.RegisterProviderClusterWithToken( + ctx, + masterClusterCfg, + remoteCfg, + token, + opts.Options, + providerInfo, + namespace, + policyRules, + ) } func DeregisterClusterFromConfig( diff --git a/pkg/multicluster/register/interfaces.go b/pkg/multicluster/register/interfaces.go index 7e40dec9a..83ab2b91b 100644 --- a/pkg/multicluster/register/interfaces.go +++ b/pkg/multicluster/register/interfaces.go @@ -148,7 +148,7 @@ type ClusterRegistrant interface { ) error /* - Same functionality as RegisterClusterWithToken but supply extra ProviderInfo metadata. + Same functionality as RegisterClusterWithToken but supply extra ProviderInfo metadata and registration settings (namespace and policyRules). */ RegisterProviderClusterWithToken( ctx context.Context, @@ -157,6 +157,8 @@ type ClusterRegistrant interface { token string, opts Options, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, + namespace string, + policyRules []*v1alpha1.PolicyRule, ) error /* diff --git a/pkg/multicluster/register/mocks/mock_interfaces.go b/pkg/multicluster/register/mocks/mock_interfaces.go index 4893845c8..813b9f911 100644 --- a/pkg/multicluster/register/mocks/mock_interfaces.go +++ b/pkg/multicluster/register/mocks/mock_interfaces.go @@ -113,17 +113,17 @@ func (mr *MockClusterRegistrantMockRecorder) RegisterClusterWithToken(ctx, maste } // RegisterProviderClusterWithToken mocks base method -func (m *MockClusterRegistrant) RegisterProviderClusterWithToken(ctx context.Context, masterClusterCfg *rest.Config, remoteClientCfg clientcmd.ClientConfig, token string, opts register.Options, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo) error { +func (m *MockClusterRegistrant) RegisterProviderClusterWithToken(ctx context.Context, masterClusterCfg *rest.Config, remoteClientCfg clientcmd.ClientConfig, token string, opts register.Options, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, namespace string, policyRules []*v1alpha1.PolicyRule) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RegisterProviderClusterWithToken", ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo) + ret := m.ctrl.Call(m, "RegisterProviderClusterWithToken", ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo, namespace, policyRules) ret0, _ := ret[0].(error) return ret0 } // RegisterProviderClusterWithToken indicates an expected call of RegisterProviderClusterWithToken -func (mr *MockClusterRegistrantMockRecorder) RegisterProviderClusterWithToken(ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo interface{}) *gomock.Call { +func (mr *MockClusterRegistrantMockRecorder) RegisterProviderClusterWithToken(ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo, namespace, policyRules interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterProviderClusterWithToken", reflect.TypeOf((*MockClusterRegistrant)(nil).RegisterProviderClusterWithToken), ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterProviderClusterWithToken", reflect.TypeOf((*MockClusterRegistrant)(nil).RegisterProviderClusterWithToken), ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo, namespace, policyRules) } // DeregisterCluster mocks base method diff --git a/pkg/multicluster/register/registrant.go b/pkg/multicluster/register/registrant.go index a05302666..64f594812 100644 --- a/pkg/multicluster/register/registrant.go +++ b/pkg/multicluster/register/registrant.go @@ -289,7 +289,7 @@ func (c *clusterRegistrant) RegisterClusterWithToken( token string, opts Options, ) error { - return c.RegisterProviderClusterWithToken(ctx, masterClusterCfg, remoteClientCfg, token, opts, nil) + return c.RegisterProviderClusterWithToken(ctx, masterClusterCfg, remoteClientCfg, token, opts, nil, "", nil) } func (c *clusterRegistrant) RegisterProviderClusterWithToken( @@ -299,6 +299,8 @@ func (c *clusterRegistrant) RegisterProviderClusterWithToken( token string, opts Options, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, + namespace string, + policyRules []*v1alpha1.PolicyRule, ) error { if err := (&opts).validate(); err != nil { return err @@ -343,7 +345,7 @@ func (c *clusterRegistrant) RegisterProviderClusterWithToken( return err } - kubeCluster := buildKubeClusterResource(kcSecret, opts.ClusterDomain, providerInfo) + kubeCluster := buildKubeClusterResource(kcSecret, opts.ClusterDomain, providerInfo, namespace, policyRules) kubeClusterClient, err := c.kubeClusterFactory(masterClusterCfg) if err != nil { @@ -385,6 +387,8 @@ func buildKubeClusterResource( secret *corev1.Secret, clusterDomain string, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, + namespace string, + policyRules []*v1alpha1.PolicyRule, ) *v1alpha1.KubernetesCluster { if clusterDomain == "" { clusterDomain = DefaultClusterDomain @@ -396,6 +400,10 @@ func buildKubeClusterResource( ClusterDomain: clusterDomain, ProviderInfo: providerInfo, }, + Status: v1alpha1.KubernetesClusterStatus{ + Namespace: namespace, + PolicyRules: policyRules, + }, } } diff --git a/pkg/multicluster/register/registrant_test.go b/pkg/multicluster/register/registrant_test.go index 715577f1c..f5d9da348 100644 --- a/pkg/multicluster/register/registrant_test.go +++ b/pkg/multicluster/register/registrant_test.go @@ -617,6 +617,13 @@ var _ = Describe("Registrant", func() { }, } + policyRules := []*v1alpha1.PolicyRule{ + { + Verbs: []string{"watch"}, + ApiGroups: []string{"v1alpha1"}, + Resources: []string{"foo"}, + }, + } kubeClusterClient.EXPECT(). UpsertKubernetesCluster(ctx, &v1alpha1.KubernetesCluster{ ObjectMeta: secret.ObjectMeta, @@ -625,9 +632,22 @@ var _ = Describe("Registrant", func() { ClusterDomain: "cluster.local", ProviderInfo: providerInfo, }, + Status: v1alpha1.KubernetesClusterStatus{ + Namespace: "namespace", + PolicyRules: policyRules, + }, }).Return(nil) - err = clusterRegistrant.RegisterProviderClusterWithToken(ctx, restCfg, clientConfig, token, opts, providerInfo) + err = clusterRegistrant.RegisterProviderClusterWithToken( + ctx, + restCfg, + clientConfig, + token, + opts, + providerInfo, + "namespace", + policyRules, + ) Expect(err).NotTo(HaveOccurred()) }) From 0e82a96ef128a9b96fc6942e2d9a72f36fb11b81 Mon Sep 17 00:00:00 2001 From: Harvey Xia Date: Tue, 8 Sep 2020 14:21:24 -0400 Subject: [PATCH 02/14] update KubernetesCluster status --- pkg/multicluster/register/registrant.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/multicluster/register/registrant.go b/pkg/multicluster/register/registrant.go index 64f594812..5dd534797 100644 --- a/pkg/multicluster/register/registrant.go +++ b/pkg/multicluster/register/registrant.go @@ -352,7 +352,10 @@ func (c *clusterRegistrant) RegisterProviderClusterWithToken( return err } - return kubeClusterClient.UpsertKubernetesCluster(ctx, kubeCluster) + if err = kubeClusterClient.UpsertKubernetesCluster(ctx, kubeCluster); err != nil { + return err + } + return kubeClusterClient.UpdateKubernetesClusterStatus(ctx, kubeCluster) } func (c *clusterRegistrant) DeregisterCluster( From 81932f96d70ea46debecd245a18c545d69071256 Mon Sep 17 00:00:00 2001 From: Harvey Xia Date: Tue, 8 Sep 2020 15:35:16 -0400 Subject: [PATCH 03/14] add labels to registration options --- .../test/api/things.test.io/v1/test_api.pb.go | 3 +- .../things.test.io/v1/test_api_json.gen.go | 3 +- pkg/api/core.skv2.solo.io/v1/core.pb.go | 3 +- pkg/api/core.skv2.solo.io/v1/core_json.gen.go | 3 +- .../v1alpha1/cluster.pb.go | 3 +- .../v1alpha1/cluster_json.gen.go | 3 +- pkg/multicluster/register/helpers.go | 8 ++- pkg/multicluster/register/interfaces.go | 1 + .../register/mocks/mock_interfaces.go | 8 +-- pkg/multicluster/register/registrant.go | 13 ++-- pkg/multicluster/register/registrant_test.go | 68 +++++++++++-------- 11 files changed, 72 insertions(+), 44 deletions(-) diff --git a/codegen/test/api/things.test.io/v1/test_api.pb.go b/codegen/test/api/things.test.io/v1/test_api.pb.go index 1836d93b2..6f2ac41ea 100644 --- a/codegen/test/api/things.test.io/v1/test_api.pb.go +++ b/codegen/test/api/things.test.io/v1/test_api.pb.go @@ -5,8 +5,9 @@ package v1 import ( fmt "fmt" - proto "github.com/gogo/protobuf/proto" math "math" + + proto "github.com/gogo/protobuf/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/codegen/test/api/things.test.io/v1/test_api_json.gen.go b/codegen/test/api/things.test.io/v1/test_api_json.gen.go index 824b0ffd5..adce788f2 100644 --- a/codegen/test/api/things.test.io/v1/test_api_json.gen.go +++ b/codegen/test/api/things.test.io/v1/test_api_json.gen.go @@ -6,9 +6,10 @@ package v1 import ( bytes "bytes" fmt "fmt" + math "math" + github_com_gogo_protobuf_jsonpb "github.com/gogo/protobuf/jsonpb" proto "github.com/gogo/protobuf/proto" - math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/pkg/api/core.skv2.solo.io/v1/core.pb.go b/pkg/api/core.skv2.solo.io/v1/core.pb.go index c64fbfd8e..56ed5cb56 100644 --- a/pkg/api/core.skv2.solo.io/v1/core.pb.go +++ b/pkg/api/core.skv2.solo.io/v1/core.pb.go @@ -6,11 +6,12 @@ package v1 import ( bytes "bytes" fmt "fmt" + math "math" + _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" types "github.com/gogo/protobuf/types" _ "github.com/solo-io/protoc-gen-ext/extproto" - math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/pkg/api/core.skv2.solo.io/v1/core_json.gen.go b/pkg/api/core.skv2.solo.io/v1/core_json.gen.go index 0dfdd432d..5b0b8f1e1 100644 --- a/pkg/api/core.skv2.solo.io/v1/core_json.gen.go +++ b/pkg/api/core.skv2.solo.io/v1/core_json.gen.go @@ -6,12 +6,13 @@ package v1 import ( bytes "bytes" fmt "fmt" + math "math" + _ "github.com/gogo/protobuf/gogoproto" github_com_gogo_protobuf_jsonpb "github.com/gogo/protobuf/jsonpb" proto "github.com/gogo/protobuf/proto" _ "github.com/gogo/protobuf/types" _ "github.com/solo-io/protoc-gen-ext/extproto" - math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go b/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go index 63fe80329..1c5451491 100644 --- a/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go +++ b/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go @@ -6,11 +6,12 @@ package v1alpha1 import ( bytes "bytes" fmt "fmt" + math "math" + _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" _ "github.com/solo-io/protoc-gen-ext/extproto" v1 "github.com/solo-io/skv2/pkg/api/core.skv2.solo.io/v1" - math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/pkg/api/multicluster.solo.io/v1alpha1/cluster_json.gen.go b/pkg/api/multicluster.solo.io/v1alpha1/cluster_json.gen.go index e73fce13c..95151c7f1 100644 --- a/pkg/api/multicluster.solo.io/v1alpha1/cluster_json.gen.go +++ b/pkg/api/multicluster.solo.io/v1alpha1/cluster_json.gen.go @@ -6,12 +6,13 @@ package v1alpha1 import ( bytes "bytes" fmt "fmt" + math "math" + _ "github.com/gogo/protobuf/gogoproto" github_com_gogo_protobuf_jsonpb "github.com/gogo/protobuf/jsonpb" proto "github.com/gogo/protobuf/proto" _ "github.com/solo-io/protoc-gen-ext/extproto" _ "github.com/solo-io/skv2/pkg/api/core.skv2.solo.io/v1" - math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/pkg/multicluster/register/helpers.go b/pkg/multicluster/register/helpers.go index 130954a4e..1d1ed68ad 100644 --- a/pkg/multicluster/register/helpers.go +++ b/pkg/multicluster/register/helpers.go @@ -70,6 +70,9 @@ type RegistrationOptions struct { // List of cluster roles which will be bound to by the created cluster role bindings // The ClusterRoles upserted from the above list will automatically appended to the list ClusterRoleBindings []client.ObjectKey + + // Set of labels to include on the KubernetesCluster resource. + Labels map[string]string } /* @@ -119,6 +122,7 @@ func (opts RegistrationOptions) RegisterProviderCluster( rbacOpts, registrant, providerInfo, + opts.Labels, opts.RemoteNamespace, clusterRolePolicyRules, ) @@ -179,7 +183,7 @@ func RegisterClusterFromConfig( opts RbacOptions, registrant ClusterRegistrant, ) error { - return RegisterProviderClusterFromConfig(ctx, masterClusterCfg, remoteCfg, opts, registrant, nil, "", nil) + return RegisterProviderClusterFromConfig(ctx, masterClusterCfg, remoteCfg, opts, registrant, nil, nil, "", nil) } func RegisterProviderClusterFromConfig( @@ -189,6 +193,7 @@ func RegisterProviderClusterFromConfig( opts RbacOptions, registrant ClusterRegistrant, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, + labels map[string]string, namespace string, policyRules []*v1alpha1.PolicyRule, ) error { @@ -212,6 +217,7 @@ func RegisterProviderClusterFromConfig( token, opts.Options, providerInfo, + labels, namespace, policyRules, ) diff --git a/pkg/multicluster/register/interfaces.go b/pkg/multicluster/register/interfaces.go index 83ab2b91b..c708cbbbf 100644 --- a/pkg/multicluster/register/interfaces.go +++ b/pkg/multicluster/register/interfaces.go @@ -157,6 +157,7 @@ type ClusterRegistrant interface { token string, opts Options, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, + labels map[string]string, namespace string, policyRules []*v1alpha1.PolicyRule, ) error diff --git a/pkg/multicluster/register/mocks/mock_interfaces.go b/pkg/multicluster/register/mocks/mock_interfaces.go index 813b9f911..1c5b3a188 100644 --- a/pkg/multicluster/register/mocks/mock_interfaces.go +++ b/pkg/multicluster/register/mocks/mock_interfaces.go @@ -113,17 +113,17 @@ func (mr *MockClusterRegistrantMockRecorder) RegisterClusterWithToken(ctx, maste } // RegisterProviderClusterWithToken mocks base method -func (m *MockClusterRegistrant) RegisterProviderClusterWithToken(ctx context.Context, masterClusterCfg *rest.Config, remoteClientCfg clientcmd.ClientConfig, token string, opts register.Options, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, namespace string, policyRules []*v1alpha1.PolicyRule) error { +func (m *MockClusterRegistrant) RegisterProviderClusterWithToken(ctx context.Context, masterClusterCfg *rest.Config, remoteClientCfg clientcmd.ClientConfig, token string, opts register.Options, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, labels map[string]string, namespace string, policyRules []*v1alpha1.PolicyRule) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RegisterProviderClusterWithToken", ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo, namespace, policyRules) + ret := m.ctrl.Call(m, "RegisterProviderClusterWithToken", ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo, labels, namespace, policyRules) ret0, _ := ret[0].(error) return ret0 } // RegisterProviderClusterWithToken indicates an expected call of RegisterProviderClusterWithToken -func (mr *MockClusterRegistrantMockRecorder) RegisterProviderClusterWithToken(ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo, namespace, policyRules interface{}) *gomock.Call { +func (mr *MockClusterRegistrantMockRecorder) RegisterProviderClusterWithToken(ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo, labels, namespace, policyRules interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterProviderClusterWithToken", reflect.TypeOf((*MockClusterRegistrant)(nil).RegisterProviderClusterWithToken), ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo, namespace, policyRules) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterProviderClusterWithToken", reflect.TypeOf((*MockClusterRegistrant)(nil).RegisterProviderClusterWithToken), ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo, labels, namespace, policyRules) } // DeregisterCluster mocks base method diff --git a/pkg/multicluster/register/registrant.go b/pkg/multicluster/register/registrant.go index 5dd534797..9bcb4d123 100644 --- a/pkg/multicluster/register/registrant.go +++ b/pkg/multicluster/register/registrant.go @@ -289,7 +289,7 @@ func (c *clusterRegistrant) RegisterClusterWithToken( token string, opts Options, ) error { - return c.RegisterProviderClusterWithToken(ctx, masterClusterCfg, remoteClientCfg, token, opts, nil, "", nil) + return c.RegisterProviderClusterWithToken(ctx, masterClusterCfg, remoteClientCfg, token, opts, nil, nil, "", nil) } func (c *clusterRegistrant) RegisterProviderClusterWithToken( @@ -299,6 +299,7 @@ func (c *clusterRegistrant) RegisterProviderClusterWithToken( token string, opts Options, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, + labels map[string]string, namespace string, policyRules []*v1alpha1.PolicyRule, ) error { @@ -345,7 +346,7 @@ func (c *clusterRegistrant) RegisterProviderClusterWithToken( return err } - kubeCluster := buildKubeClusterResource(kcSecret, opts.ClusterDomain, providerInfo, namespace, policyRules) + kubeCluster := buildKubeClusterResource(kcSecret, labels, opts.ClusterDomain, providerInfo, namespace, policyRules) kubeClusterClient, err := c.kubeClusterFactory(masterClusterCfg) if err != nil { @@ -368,7 +369,7 @@ func (c *clusterRegistrant) DeregisterCluster( } kcSecretObjMeta := kubeconfig.SecretObjMeta(opts.Namespace, opts.ClusterName) - kubeClusterObjMeta := kubeClusterObjMeta(kcSecretObjMeta.Name, kcSecretObjMeta.Namespace) + kubeClusterObjMeta := kubeClusterObjMeta(kcSecretObjMeta.Name, kcSecretObjMeta.Namespace, nil) kubeClusterClient, err := c.kubeClusterFactory(masterClusterCfg) if err != nil { return err @@ -388,6 +389,7 @@ func (c *clusterRegistrant) DeregisterCluster( func buildKubeClusterResource( secret *corev1.Secret, + labels map[string]string, clusterDomain string, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, namespace string, @@ -397,7 +399,7 @@ func buildKubeClusterResource( clusterDomain = DefaultClusterDomain } return &v1alpha1.KubernetesCluster{ - ObjectMeta: kubeClusterObjMeta(secret.Name, secret.Namespace), + ObjectMeta: kubeClusterObjMeta(secret.Name, secret.Namespace, labels), Spec: v1alpha1.KubernetesClusterSpec{ SecretName: secret.Name, ClusterDomain: clusterDomain, @@ -410,10 +412,11 @@ func buildKubeClusterResource( } } -func kubeClusterObjMeta(secretName, secretNamespace string) metav1.ObjectMeta { +func kubeClusterObjMeta(secretName, secretNamespace string, labels map[string]string) metav1.ObjectMeta { return metav1.ObjectMeta{ Name: secretName, Namespace: secretNamespace, + Labels: labels, } } diff --git a/pkg/multicluster/register/registrant_test.go b/pkg/multicluster/register/registrant_test.go index f5d9da348..9c7e2b37e 100644 --- a/pkg/multicluster/register/registrant_test.go +++ b/pkg/multicluster/register/registrant_test.go @@ -502,14 +502,15 @@ var _ = Describe("Registrant", func() { CreateSecret(ctx, secret). Return(nil) - kubeClusterClient.EXPECT(). - UpsertKubernetesCluster(ctx, &v1alpha1.KubernetesCluster{ - ObjectMeta: secret.ObjectMeta, - Spec: v1alpha1.KubernetesClusterSpec{ - SecretName: secret.Name, - ClusterDomain: "cluster.local", - }, - }).Return(nil) + kubeCluster := &v1alpha1.KubernetesCluster{ + ObjectMeta: secret.ObjectMeta, + Spec: v1alpha1.KubernetesClusterSpec{ + SecretName: secret.Name, + ClusterDomain: "cluster.local", + }, + } + kubeClusterClient.EXPECT().UpsertKubernetesCluster(ctx, kubeCluster).Return(nil) + kubeClusterClient.EXPECT().UpdateKubernetesClusterStatus(ctx, kubeCluster).Return(nil) err = clusterRegistrant.RegisterClusterWithToken(ctx, restCfg, clientConfig, token, opts) @@ -624,19 +625,26 @@ var _ = Describe("Registrant", func() { Resources: []string{"foo"}, }, } - kubeClusterClient.EXPECT(). - UpsertKubernetesCluster(ctx, &v1alpha1.KubernetesCluster{ - ObjectMeta: secret.ObjectMeta, - Spec: v1alpha1.KubernetesClusterSpec{ - SecretName: secret.Name, - ClusterDomain: "cluster.local", - ProviderInfo: providerInfo, - }, - Status: v1alpha1.KubernetesClusterStatus{ - Namespace: "namespace", - PolicyRules: policyRules, + kubeCluster := &v1alpha1.KubernetesCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: secret.ObjectMeta.Name, + Namespace: secret.ObjectMeta.Namespace, + Labels: map[string]string{ + "foo": "bar", }, - }).Return(nil) + }, + Spec: v1alpha1.KubernetesClusterSpec{ + SecretName: secret.Name, + ClusterDomain: "cluster.local", + ProviderInfo: providerInfo, + }, + Status: v1alpha1.KubernetesClusterStatus{ + Namespace: "namespace", + PolicyRules: policyRules, + }, + } + kubeClusterClient.EXPECT().UpsertKubernetesCluster(ctx, kubeCluster).Return(nil) + kubeClusterClient.EXPECT().UpdateKubernetesClusterStatus(ctx, kubeCluster).Return(nil) err = clusterRegistrant.RegisterProviderClusterWithToken( ctx, @@ -645,6 +653,9 @@ var _ = Describe("Registrant", func() { token, opts, providerInfo, + map[string]string{ + "foo": "bar", + }, "namespace", policyRules, ) @@ -749,14 +760,15 @@ var _ = Describe("Registrant", func() { CreateSecret(ctx, secret). Return(nil) - kubeClusterClient.EXPECT(). - UpsertKubernetesCluster(ctx, &v1alpha1.KubernetesCluster{ - ObjectMeta: secret.ObjectMeta, - Spec: v1alpha1.KubernetesClusterSpec{ - SecretName: secret.Name, - ClusterDomain: "cluster.local", - }, - }).Return(nil) + kubeCluster := &v1alpha1.KubernetesCluster{ + ObjectMeta: secret.ObjectMeta, + Spec: v1alpha1.KubernetesClusterSpec{ + SecretName: secret.Name, + ClusterDomain: "cluster.local", + }, + } + kubeClusterClient.EXPECT().UpsertKubernetesCluster(ctx, kubeCluster).Return(nil) + kubeClusterClient.EXPECT().UpdateKubernetesClusterStatus(ctx, kubeCluster).Return(nil) err = clusterRegistrant.RegisterClusterWithToken(ctx, restCfg, clientConfig, token, opts) From 3fce40370b24ab578512574013b20c33f4e17382 Mon Sep 17 00:00:00 2001 From: Harvey Xia Date: Wed, 9 Sep 2020 15:54:07 -0400 Subject: [PATCH 04/14] update proto comments --- api/multicluster/v1alpha1/cluster.proto | 4 ++-- pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/multicluster/v1alpha1/cluster.proto b/api/multicluster/v1alpha1/cluster.proto index d80eef5dd..4c42f7b02 100644 --- a/api/multicluster/v1alpha1/cluster.proto +++ b/api/multicluster/v1alpha1/cluster.proto @@ -57,10 +57,10 @@ message KubernetesClusterStatus { // This list allows for multiple applications/pods to record their connection status. repeated core.skv2.solo.io.Status status = 1; - // The namespace on in which cluster registration resources are created. + // The namespace in which cluster registration resources were created. string namespace = 2; - // JSON representation of the set of PolicyRules to attach to the newly created ClusterRole when registering clusters. + // The set of PolicyRules attached to ClusterRoles when this cluster was registered. repeated PolicyRule policy_rules = 3; } diff --git a/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go b/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go index 1c5451491..4d81bd1fc 100644 --- a/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go +++ b/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go @@ -226,9 +226,9 @@ type KubernetesClusterStatus struct { // List of statuses about the kubernetes cluster. // This list allows for multiple applications/pods to record their connection status. Status []*v1.Status `protobuf:"bytes,1,rep,name=status,proto3" json:"status,omitempty"` - // The namespace on in which cluster registration resources are created. + // The namespace in which cluster registration resources were created. Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` - // JSON representation of the set of PolicyRules to attach to the newly created ClusterRole when registering clusters. + // The set of PolicyRules attached to ClusterRoles when this cluster was registered. PolicyRules []*PolicyRule `protobuf:"bytes,3,rep,name=policy_rules,json=policyRules,proto3" json:"policy_rules,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` From 05a6e64de56a1789380d361ade50566668013f91 Mon Sep 17 00:00:00 2001 From: Harvey Xia Date: Tue, 15 Sep 2020 09:59:10 -0400 Subject: [PATCH 05/14] update changelog version --- .../{v0.11.2 => v0.12.1}/kubernetes-cluster-status-settings.yaml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelog/{v0.11.2 => v0.12.1}/kubernetes-cluster-status-settings.yaml (100%) diff --git a/changelog/v0.11.2/kubernetes-cluster-status-settings.yaml b/changelog/v0.12.1/kubernetes-cluster-status-settings.yaml similarity index 100% rename from changelog/v0.11.2/kubernetes-cluster-status-settings.yaml rename to changelog/v0.12.1/kubernetes-cluster-status-settings.yaml From c21898df2a1b5e92fd25da10c83f669d9c93bd86 Mon Sep 17 00:00:00 2001 From: Harvey Xia Date: Tue, 15 Sep 2020 14:34:35 -0400 Subject: [PATCH 06/14] simplify remote namespace passing. ensure remote namespace. --- pkg/multicluster/register/helpers.go | 18 ++++++++++-------- pkg/multicluster/register/interfaces.go | 9 ++++++++- pkg/multicluster/register/registrant.go | 21 ++++++++++++++++----- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/pkg/multicluster/register/helpers.go b/pkg/multicluster/register/helpers.go index 1d1ed68ad..3a2dedbc5 100644 --- a/pkg/multicluster/register/helpers.go +++ b/pkg/multicluster/register/helpers.go @@ -72,7 +72,7 @@ type RegistrationOptions struct { ClusterRoleBindings []client.ObjectKey // Set of labels to include on the KubernetesCluster resource. - Labels map[string]string + KubernetesClusterLabels map[string]string } /* @@ -122,8 +122,7 @@ func (opts RegistrationOptions) RegisterProviderCluster( rbacOpts, registrant, providerInfo, - opts.Labels, - opts.RemoteNamespace, + opts.KubernetesClusterLabels, clusterRolePolicyRules, ) } @@ -183,7 +182,7 @@ func RegisterClusterFromConfig( opts RbacOptions, registrant ClusterRegistrant, ) error { - return RegisterProviderClusterFromConfig(ctx, masterClusterCfg, remoteCfg, opts, registrant, nil, nil, "", nil) + return RegisterProviderClusterFromConfig(ctx, masterClusterCfg, remoteCfg, opts, registrant, nil, nil, nil) } func RegisterProviderClusterFromConfig( @@ -193,10 +192,14 @@ func RegisterProviderClusterFromConfig( opts RbacOptions, registrant ClusterRegistrant, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, - labels map[string]string, - namespace string, + kubeClusterLabels map[string]string, policyRules []*v1alpha1.PolicyRule, ) error { + err := registrant.EnsureRemoteNamespace(ctx, remoteCfg, opts.RemoteNamespace) + if err != nil { + return err + } + sa, err := registrant.EnsureRemoteServiceAccount(ctx, remoteCfg, opts.Options) if err != nil { return err @@ -217,8 +220,7 @@ func RegisterProviderClusterFromConfig( token, opts.Options, providerInfo, - labels, - namespace, + kubeClusterLabels, policyRules, ) } diff --git a/pkg/multicluster/register/interfaces.go b/pkg/multicluster/register/interfaces.go index c708cbbbf..884436d08 100644 --- a/pkg/multicluster/register/interfaces.go +++ b/pkg/multicluster/register/interfaces.go @@ -89,6 +89,14 @@ func (o *Options) validate() error { the registrant instance. */ type ClusterRegistrant interface { + /* + EnsureRemoteNamespace ensures that the specified remoteNamespace exists on the remote cluster being registered. + */ + EnsureRemoteNamespace( + ctx context.Context, + remoteClientCfg clientcmd.ClientConfig, + remoteNamespace string, + ) error /* EnsureRemoteServiceAccount takes an instance of a remote config, and ensure a ServiceAccount exists on the @@ -158,7 +166,6 @@ type ClusterRegistrant interface { opts Options, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, labels map[string]string, - namespace string, policyRules []*v1alpha1.PolicyRule, ) error diff --git a/pkg/multicluster/register/registrant.go b/pkg/multicluster/register/registrant.go index 9bcb4d123..3f759f342 100644 --- a/pkg/multicluster/register/registrant.go +++ b/pkg/multicluster/register/registrant.go @@ -94,6 +94,18 @@ type clusterRegistrant struct { localAPIServerAddress string } +func (c *clusterRegistrant) EnsureRemoteNamespace( + ctx context.Context, + remoteClientCfg clientcmd.ClientConfig, + remoteNamespace string, +) error { + remoteRestCfg, err := remoteClientCfg.ClientConfig() + if err != nil { + return err + } + return c.ensureRemoteNamespace(ctx, remoteNamespace, remoteRestCfg) +} + func (c *clusterRegistrant) EnsureRemoteServiceAccount( ctx context.Context, remoteClientCfg clientcmd.ClientConfig, @@ -289,7 +301,7 @@ func (c *clusterRegistrant) RegisterClusterWithToken( token string, opts Options, ) error { - return c.RegisterProviderClusterWithToken(ctx, masterClusterCfg, remoteClientCfg, token, opts, nil, nil, "", nil) + return c.RegisterProviderClusterWithToken(ctx, masterClusterCfg, remoteClientCfg, token, opts, nil, nil, nil) } func (c *clusterRegistrant) RegisterProviderClusterWithToken( @@ -300,7 +312,6 @@ func (c *clusterRegistrant) RegisterProviderClusterWithToken( opts Options, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, labels map[string]string, - namespace string, policyRules []*v1alpha1.PolicyRule, ) error { if err := (&opts).validate(); err != nil { @@ -346,7 +357,7 @@ func (c *clusterRegistrant) RegisterProviderClusterWithToken( return err } - kubeCluster := buildKubeClusterResource(kcSecret, labels, opts.ClusterDomain, providerInfo, namespace, policyRules) + kubeCluster := buildKubeClusterResource(kcSecret, labels, opts.ClusterDomain, providerInfo, opts.RemoteNamespace, policyRules) kubeClusterClient, err := c.kubeClusterFactory(masterClusterCfg) if err != nil { @@ -392,7 +403,7 @@ func buildKubeClusterResource( labels map[string]string, clusterDomain string, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, - namespace string, + remoteNamespace string, policyRules []*v1alpha1.PolicyRule, ) *v1alpha1.KubernetesCluster { if clusterDomain == "" { @@ -406,7 +417,7 @@ func buildKubeClusterResource( ProviderInfo: providerInfo, }, Status: v1alpha1.KubernetesClusterStatus{ - Namespace: namespace, + Namespace: remoteNamespace, PolicyRules: policyRules, }, } From 1d625f509f0ab8a6f31d0205e050b09616bbbc45 Mon Sep 17 00:00:00 2001 From: Harvey Xia Date: Tue, 15 Sep 2020 16:02:00 -0400 Subject: [PATCH 07/14] gen code --- .../register/mocks/mock_interfaces.go | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/pkg/multicluster/register/mocks/mock_interfaces.go b/pkg/multicluster/register/mocks/mock_interfaces.go index 1c5b3a188..b3351b108 100644 --- a/pkg/multicluster/register/mocks/mock_interfaces.go +++ b/pkg/multicluster/register/mocks/mock_interfaces.go @@ -40,6 +40,20 @@ func (m *MockClusterRegistrant) EXPECT() *MockClusterRegistrantMockRecorder { return m.recorder } +// EnsureRemoteNamespace mocks base method +func (m *MockClusterRegistrant) EnsureRemoteNamespace(ctx context.Context, remoteClientCfg clientcmd.ClientConfig, remoteNamespace string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "EnsureRemoteNamespace", ctx, remoteClientCfg, remoteNamespace) + ret0, _ := ret[0].(error) + return ret0 +} + +// EnsureRemoteNamespace indicates an expected call of EnsureRemoteNamespace +func (mr *MockClusterRegistrantMockRecorder) EnsureRemoteNamespace(ctx, remoteClientCfg, remoteNamespace interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnsureRemoteNamespace", reflect.TypeOf((*MockClusterRegistrant)(nil).EnsureRemoteNamespace), ctx, remoteClientCfg, remoteNamespace) +} + // EnsureRemoteServiceAccount mocks base method func (m *MockClusterRegistrant) EnsureRemoteServiceAccount(ctx context.Context, remoteClientCfg clientcmd.ClientConfig, opts register.Options) (*v1.ServiceAccount, error) { m.ctrl.T.Helper() @@ -113,17 +127,17 @@ func (mr *MockClusterRegistrantMockRecorder) RegisterClusterWithToken(ctx, maste } // RegisterProviderClusterWithToken mocks base method -func (m *MockClusterRegistrant) RegisterProviderClusterWithToken(ctx context.Context, masterClusterCfg *rest.Config, remoteClientCfg clientcmd.ClientConfig, token string, opts register.Options, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, labels map[string]string, namespace string, policyRules []*v1alpha1.PolicyRule) error { +func (m *MockClusterRegistrant) RegisterProviderClusterWithToken(ctx context.Context, masterClusterCfg *rest.Config, remoteClientCfg clientcmd.ClientConfig, token string, opts register.Options, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, labels map[string]string, policyRules []*v1alpha1.PolicyRule) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RegisterProviderClusterWithToken", ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo, labels, namespace, policyRules) + ret := m.ctrl.Call(m, "RegisterProviderClusterWithToken", ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo, labels, policyRules) ret0, _ := ret[0].(error) return ret0 } // RegisterProviderClusterWithToken indicates an expected call of RegisterProviderClusterWithToken -func (mr *MockClusterRegistrantMockRecorder) RegisterProviderClusterWithToken(ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo, labels, namespace, policyRules interface{}) *gomock.Call { +func (mr *MockClusterRegistrantMockRecorder) RegisterProviderClusterWithToken(ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo, labels, policyRules interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterProviderClusterWithToken", reflect.TypeOf((*MockClusterRegistrant)(nil).RegisterProviderClusterWithToken), ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo, labels, namespace, policyRules) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterProviderClusterWithToken", reflect.TypeOf((*MockClusterRegistrant)(nil).RegisterProviderClusterWithToken), ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo, labels, policyRules) } // DeregisterCluster mocks base method From b6f62f6ba51ecb581a082c61229fee4cabe589ad Mon Sep 17 00:00:00 2001 From: Harvey Xia Date: Tue, 15 Sep 2020 16:50:36 -0400 Subject: [PATCH 08/14] pr comments --- .../kubeconfig/kubeconfig_secret.go | 7 +- .../kubeconfig/kubeconfig_secret_test.go | 6 +- pkg/multicluster/kubeconfig/loader.go | 93 +++++++------------ pkg/multicluster/register/helpers.go | 10 +- pkg/multicluster/register/interfaces.go | 2 +- pkg/multicluster/register/registrant.go | 7 +- pkg/multicluster/register/registrant_test.go | 13 ++- 7 files changed, 60 insertions(+), 78 deletions(-) diff --git a/pkg/multicluster/kubeconfig/kubeconfig_secret.go b/pkg/multicluster/kubeconfig/kubeconfig_secret.go index 82da22f19..305362dcd 100644 --- a/pkg/multicluster/kubeconfig/kubeconfig_secret.go +++ b/pkg/multicluster/kubeconfig/kubeconfig_secret.go @@ -27,7 +27,7 @@ var ( // TODO settle on how to canonicalize cluster names: https://github.com/solo-io/skv2/issues/15 // ToSecret converts a kubernetes api.Config to a secret with the provided name and namespace. -func ToSecret(namespace string, cluster string, kc api.Config) (*kubev1.Secret, error) { +func ToSecret(namespace string, cluster string, resourceLabels map[string]string, kc api.Config) (*kubev1.Secret, error) { err := convertCertFilesToInline(kc) if err != nil { return nil, err @@ -39,16 +39,17 @@ func ToSecret(namespace string, cluster string, kc api.Config) (*kubev1.Secret, } return &kubev1.Secret{ - ObjectMeta: SecretObjMeta(namespace, cluster), + ObjectMeta: SecretObjMeta(namespace, cluster, resourceLabels), Type: SecretType, Data: map[string][]byte{Key: rawKubeConfig}, }, nil } -func SecretObjMeta(namespace string, cluster string) metav1.ObjectMeta { +func SecretObjMeta(namespace string, cluster string, resourceLabels map[string]string) metav1.ObjectMeta { return metav1.ObjectMeta{ Name: cluster, Namespace: namespace, + Labels: resourceLabels, } } diff --git a/pkg/multicluster/kubeconfig/kubeconfig_secret_test.go b/pkg/multicluster/kubeconfig/kubeconfig_secret_test.go index 7c9d5687d..428dcae6b 100644 --- a/pkg/multicluster/kubeconfig/kubeconfig_secret_test.go +++ b/pkg/multicluster/kubeconfig/kubeconfig_secret_test.go @@ -48,17 +48,21 @@ users: Describe("ToSecret", func() { It("should convert a single KubeConfig to a single secret", func() { + expectedLabels := map[string]string{ + "foo": "bar", + } expectedSecret := &v1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: clusterName, Namespace: namespace, + Labels: expectedLabels, }, Data: map[string][]byte{ Key: []byte(kubeConfigRaw), }, Type: SecretType, } - secret, err := ToSecret(namespace, clusterName, *config) + secret, err := ToSecret(namespace, clusterName, expectedLabels, *config) Expect(err).NotTo(HaveOccurred()) Expect(secret).To(Equal(expectedSecret)) }) diff --git a/pkg/multicluster/kubeconfig/loader.go b/pkg/multicluster/kubeconfig/loader.go index 5f1e2066f..d4a43e401 100644 --- a/pkg/multicluster/kubeconfig/loader.go +++ b/pkg/multicluster/kubeconfig/loader.go @@ -1,80 +1,51 @@ package kubeconfig import ( + "fmt" "os" - "time" + "os/user" + "path" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" ) -// default KubeLoader -func NewKubeLoader(timeout time.Duration) KubeLoader { - return &kubeLoader{ - timeout: timeout.String(), - } -} - -type kubeLoader struct { - timeout string -} - -func (k *kubeLoader) GetClientConfigForContext(path, context string) (clientcmd.ClientConfig, error) { - return k.getConfigWithContext("", path, context) -} - -func (k *kubeLoader) GetRestConfigForContext(path string, context string) (*rest.Config, error) { - cfg, err := k.getConfigWithContext("", path, context) +// Fetch ClientConfig for environment in which this is invoked, override the API Server URL and current context. +// Lifted from https://github.com/kubernetes-sigs/controller-runtime/blob/cb7f85860a8cde7259b35bb84af1fdcb02c098f2/pkg/client/config/config.go#L135 +func GetClientConfigWithContext(apiServerUrl, kubeContext string) (clientcmd.ClientConfig, error) { + loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() + if _, ok := os.LookupEnv("HOME"); !ok { + u, err := user.Current() + if err != nil { + return nil, fmt.Errorf("could not get current user: %v", err) + } + loadingRules.Precedence = append(loadingRules.Precedence, path.Join(u.HomeDir, clientcmd.RecommendedHomeDir, clientcmd.RecommendedFileName)) + } + return clientcmd.NewNonInteractiveDeferredLoadingClientConfig( + loadingRules, + &clientcmd.ConfigOverrides{ + ClusterInfo: clientcmdapi.Cluster{ + Server: apiServerUrl, + }, + CurrentContext: kubeContext, + }), nil +} + +// Fetch rest.Config for environment in which this is invoked, override the API Server URL and current context. +func GetRestConfigWithContext(apiServerUrl, kubeContext string) (*rest.Config, error) { + clientConfig, err := GetClientConfigWithContext(apiServerUrl, kubeContext) if err != nil { return nil, err } - - return cfg.ClientConfig() + return clientConfig.ClientConfig() } -func (k *kubeLoader) GetRestConfigFromBytes(config []byte) (*rest.Config, error) { - clientCfg, err := clientcmd.NewClientConfigFromBytes(config) - if err != nil { - return nil, err - } - return clientCfg.ClientConfig() -} - -func (k *kubeLoader) getConfigWithContext(masterURL, kubeconfigPath, context string) (clientcmd.ClientConfig, error) { - verifiedKubeConfigPath := clientcmd.RecommendedHomeFile - if kubeconfigPath != "" { - verifiedKubeConfigPath = kubeconfigPath - } - - if err := assertKubeConfigExists(verifiedKubeConfigPath); err != nil { - return nil, err - } - - loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() - loadingRules.ExplicitPath = verifiedKubeConfigPath - configOverrides := &clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: masterURL}} - - if context != "" { - configOverrides.CurrentContext = context - } - return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides), nil -} - -// expects `path` to be nonempty -func assertKubeConfigExists(path string) error { - if _, err := os.Stat(path); err != nil { - return err - } - - return nil -} - -func (k *kubeLoader) GetRawConfigForContext(path, context string) (clientcmdapi.Config, error) { - cfg, err := k.getConfigWithContext("", path, context) +// Fetch raw Config for environment in which this is invoked, override the API Server URL and current context. +func GetRawConfigWithContext(apiServerUrl, kubeContext string) (clientcmdapi.Config, error) { + clientConfig, err := GetClientConfigWithContext(apiServerUrl, kubeContext) if err != nil { return clientcmdapi.Config{}, err } - - return cfg.RawConfig() + return clientConfig.RawConfig() } diff --git a/pkg/multicluster/register/helpers.go b/pkg/multicluster/register/helpers.go index 3a2dedbc5..ed0004ab6 100644 --- a/pkg/multicluster/register/helpers.go +++ b/pkg/multicluster/register/helpers.go @@ -71,8 +71,8 @@ type RegistrationOptions struct { // The ClusterRoles upserted from the above list will automatically appended to the list ClusterRoleBindings []client.ObjectKey - // Set of labels to include on the KubernetesCluster resource. - KubernetesClusterLabels map[string]string + // Set of labels to include on the registration output resources, currently consisting of KubernetesCluster and Secret. + ResourceLabels map[string]string } /* @@ -122,7 +122,7 @@ func (opts RegistrationOptions) RegisterProviderCluster( rbacOpts, registrant, providerInfo, - opts.KubernetesClusterLabels, + opts.ResourceLabels, clusterRolePolicyRules, ) } @@ -192,7 +192,7 @@ func RegisterProviderClusterFromConfig( opts RbacOptions, registrant ClusterRegistrant, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, - kubeClusterLabels map[string]string, + resourceLabels map[string]string, policyRules []*v1alpha1.PolicyRule, ) error { err := registrant.EnsureRemoteNamespace(ctx, remoteCfg, opts.RemoteNamespace) @@ -220,7 +220,7 @@ func RegisterProviderClusterFromConfig( token, opts.Options, providerInfo, - kubeClusterLabels, + resourceLabels, policyRules, ) } diff --git a/pkg/multicluster/register/interfaces.go b/pkg/multicluster/register/interfaces.go index 884436d08..282032f70 100644 --- a/pkg/multicluster/register/interfaces.go +++ b/pkg/multicluster/register/interfaces.go @@ -165,7 +165,7 @@ type ClusterRegistrant interface { token string, opts Options, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, - labels map[string]string, + resourceLabels map[string]string, policyRules []*v1alpha1.PolicyRule, ) error diff --git a/pkg/multicluster/register/registrant.go b/pkg/multicluster/register/registrant.go index 3f759f342..a60a41a29 100644 --- a/pkg/multicluster/register/registrant.go +++ b/pkg/multicluster/register/registrant.go @@ -311,7 +311,7 @@ func (c *clusterRegistrant) RegisterProviderClusterWithToken( token string, opts Options, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, - labels map[string]string, + resourceLabels map[string]string, policyRules []*v1alpha1.PolicyRule, ) error { if err := (&opts).validate(); err != nil { @@ -347,6 +347,7 @@ func (c *clusterRegistrant) RegisterProviderClusterWithToken( kcSecret, err := kubeconfig.ToSecret( opts.Namespace, opts.ClusterName, + resourceLabels, c.buildRemoteCfg(remoteCluster, remoteContext, opts.ClusterName, token), ) if err != nil { @@ -357,7 +358,7 @@ func (c *clusterRegistrant) RegisterProviderClusterWithToken( return err } - kubeCluster := buildKubeClusterResource(kcSecret, labels, opts.ClusterDomain, providerInfo, opts.RemoteNamespace, policyRules) + kubeCluster := buildKubeClusterResource(kcSecret, resourceLabels, opts.ClusterDomain, providerInfo, opts.RemoteNamespace, policyRules) kubeClusterClient, err := c.kubeClusterFactory(masterClusterCfg) if err != nil { @@ -379,7 +380,7 @@ func (c *clusterRegistrant) DeregisterCluster( return err } - kcSecretObjMeta := kubeconfig.SecretObjMeta(opts.Namespace, opts.ClusterName) + kcSecretObjMeta := kubeconfig.SecretObjMeta(opts.Namespace, opts.ClusterName, nil) kubeClusterObjMeta := kubeClusterObjMeta(kcSecretObjMeta.Name, kcSecretObjMeta.Namespace, nil) kubeClusterClient, err := c.kubeClusterFactory(masterClusterCfg) if err != nil { diff --git a/pkg/multicluster/register/registrant_test.go b/pkg/multicluster/register/registrant_test.go index 9c7e2b37e..9c216d0d6 100644 --- a/pkg/multicluster/register/registrant_test.go +++ b/pkg/multicluster/register/registrant_test.go @@ -476,7 +476,7 @@ var _ = Describe("Registrant", func() { }). Return(nil, errors.NewNotFound(schema.GroupResource{}, "")) - secret, err := kubeconfig.ToSecret(namespace, clusterName, api.Config{ + secret, err := kubeconfig.ToSecret(namespace, clusterName, nil, api.Config{ Kind: "Secret", APIVersion: "kubernetes_core", Preferences: api.Preferences{}, @@ -508,6 +508,9 @@ var _ = Describe("Registrant", func() { SecretName: secret.Name, ClusterDomain: "cluster.local", }, + Status: v1alpha1.KubernetesClusterStatus{ + Namespace: namespace, + }, } kubeClusterClient.EXPECT().UpsertKubernetesCluster(ctx, kubeCluster).Return(nil) kubeClusterClient.EXPECT().UpdateKubernetesClusterStatus(ctx, kubeCluster).Return(nil) @@ -581,7 +584,7 @@ var _ = Describe("Registrant", func() { }). Return(nil, errors.NewNotFound(schema.GroupResource{}, "")) - secret, err := kubeconfig.ToSecret(namespace, clusterName, api.Config{ + secret, err := kubeconfig.ToSecret(namespace, clusterName, map[string]string{"foo": "bar"}, api.Config{ Kind: "Secret", APIVersion: "kubernetes_core", Preferences: api.Preferences{}, @@ -656,7 +659,6 @@ var _ = Describe("Registrant", func() { map[string]string{ "foo": "bar", }, - "namespace", policyRules, ) @@ -734,7 +736,7 @@ var _ = Describe("Registrant", func() { overwrittenApiConfig.Clusters[clusterName].CertificateAuthority = "" overwrittenApiConfig.Clusters[clusterName].CertificateAuthorityData = []byte("") - secret, err := kubeconfig.ToSecret(namespace, clusterName, api.Config{ + secret, err := kubeconfig.ToSecret(namespace, clusterName, nil, api.Config{ Kind: "Secret", APIVersion: "kubernetes_core", Preferences: api.Preferences{}, @@ -766,6 +768,9 @@ var _ = Describe("Registrant", func() { SecretName: secret.Name, ClusterDomain: "cluster.local", }, + Status: v1alpha1.KubernetesClusterStatus{ + Namespace: namespace, + }, } kubeClusterClient.EXPECT().UpsertKubernetesCluster(ctx, kubeCluster).Return(nil) kubeClusterClient.EXPECT().UpdateKubernetesClusterStatus(ctx, kubeCluster).Return(nil) From 76d6de49680fc65e41c8ccbb85a6ce14de37e70a Mon Sep 17 00:00:00 2001 From: Harvey Xia Date: Wed, 16 Sep 2020 09:08:40 -0400 Subject: [PATCH 09/14] wrap optional metadata in struct --- pkg/multicluster/register/helpers.go | 18 +++++------- pkg/multicluster/register/interfaces.go | 5 +--- .../register/mocks/mock_interfaces.go | 9 +++--- pkg/multicluster/register/registrant.go | 29 +++++++++++++++---- pkg/multicluster/register/registrant_test.go | 10 ++++--- 5 files changed, 42 insertions(+), 29 deletions(-) diff --git a/pkg/multicluster/register/helpers.go b/pkg/multicluster/register/helpers.go index ed0004ab6..3d1055b3b 100644 --- a/pkg/multicluster/register/helpers.go +++ b/pkg/multicluster/register/helpers.go @@ -121,9 +121,11 @@ func (opts RegistrationOptions) RegisterProviderCluster( remoteCfg, rbacOpts, registrant, - providerInfo, - opts.ResourceLabels, - clusterRolePolicyRules, + RegistrationMetadata{ + ProviderInfo: providerInfo, + ResourceLabels: opts.ResourceLabels, + ClusterRolePolicyRules: clusterRolePolicyRules, + }, ) } @@ -182,7 +184,7 @@ func RegisterClusterFromConfig( opts RbacOptions, registrant ClusterRegistrant, ) error { - return RegisterProviderClusterFromConfig(ctx, masterClusterCfg, remoteCfg, opts, registrant, nil, nil, nil) + return RegisterProviderClusterFromConfig(ctx, masterClusterCfg, remoteCfg, opts, registrant, RegistrationMetadata{}) } func RegisterProviderClusterFromConfig( @@ -191,9 +193,7 @@ func RegisterProviderClusterFromConfig( remoteCfg clientcmd.ClientConfig, opts RbacOptions, registrant ClusterRegistrant, - providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, - resourceLabels map[string]string, - policyRules []*v1alpha1.PolicyRule, + metadata RegistrationMetadata, ) error { err := registrant.EnsureRemoteNamespace(ctx, remoteCfg, opts.RemoteNamespace) if err != nil { @@ -219,9 +219,7 @@ func RegisterProviderClusterFromConfig( remoteCfg, token, opts.Options, - providerInfo, - resourceLabels, - policyRules, + metadata, ) } diff --git a/pkg/multicluster/register/interfaces.go b/pkg/multicluster/register/interfaces.go index 282032f70..42ca0ea30 100644 --- a/pkg/multicluster/register/interfaces.go +++ b/pkg/multicluster/register/interfaces.go @@ -3,7 +3,6 @@ package register import ( "context" - "github.com/solo-io/skv2/pkg/api/multicluster.solo.io/v1alpha1" "k8s.io/client-go/rest" "github.com/rotisserie/eris" @@ -164,9 +163,7 @@ type ClusterRegistrant interface { remoteClientCfg clientcmd.ClientConfig, token string, opts Options, - providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, - resourceLabels map[string]string, - policyRules []*v1alpha1.PolicyRule, + metadata RegistrationMetadata, ) error /* diff --git a/pkg/multicluster/register/mocks/mock_interfaces.go b/pkg/multicluster/register/mocks/mock_interfaces.go index b3351b108..9c1ee325c 100644 --- a/pkg/multicluster/register/mocks/mock_interfaces.go +++ b/pkg/multicluster/register/mocks/mock_interfaces.go @@ -9,7 +9,6 @@ import ( reflect "reflect" gomock "github.com/golang/mock/gomock" - v1alpha1 "github.com/solo-io/skv2/pkg/api/multicluster.solo.io/v1alpha1" register "github.com/solo-io/skv2/pkg/multicluster/register" v1 "k8s.io/api/core/v1" rest "k8s.io/client-go/rest" @@ -127,17 +126,17 @@ func (mr *MockClusterRegistrantMockRecorder) RegisterClusterWithToken(ctx, maste } // RegisterProviderClusterWithToken mocks base method -func (m *MockClusterRegistrant) RegisterProviderClusterWithToken(ctx context.Context, masterClusterCfg *rest.Config, remoteClientCfg clientcmd.ClientConfig, token string, opts register.Options, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, labels map[string]string, policyRules []*v1alpha1.PolicyRule) error { +func (m *MockClusterRegistrant) RegisterProviderClusterWithToken(ctx context.Context, masterClusterCfg *rest.Config, remoteClientCfg clientcmd.ClientConfig, token string, opts register.Options, metadata register.RegistrationMetadata) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RegisterProviderClusterWithToken", ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo, labels, policyRules) + ret := m.ctrl.Call(m, "RegisterProviderClusterWithToken", ctx, masterClusterCfg, remoteClientCfg, token, opts, metadata) ret0, _ := ret[0].(error) return ret0 } // RegisterProviderClusterWithToken indicates an expected call of RegisterProviderClusterWithToken -func (mr *MockClusterRegistrantMockRecorder) RegisterProviderClusterWithToken(ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo, labels, policyRules interface{}) *gomock.Call { +func (mr *MockClusterRegistrantMockRecorder) RegisterProviderClusterWithToken(ctx, masterClusterCfg, remoteClientCfg, token, opts, metadata interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterProviderClusterWithToken", reflect.TypeOf((*MockClusterRegistrant)(nil).RegisterProviderClusterWithToken), ctx, masterClusterCfg, remoteClientCfg, token, opts, providerInfo, labels, policyRules) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterProviderClusterWithToken", reflect.TypeOf((*MockClusterRegistrant)(nil).RegisterProviderClusterWithToken), ctx, masterClusterCfg, remoteClientCfg, token, opts, metadata) } // DeregisterCluster mocks base method diff --git a/pkg/multicluster/register/registrant.go b/pkg/multicluster/register/registrant.go index a60a41a29..9c40485b9 100644 --- a/pkg/multicluster/register/registrant.go +++ b/pkg/multicluster/register/registrant.go @@ -49,6 +49,18 @@ var ( } ) +// Optional additional metadata to persist to registration output resources. +type RegistrationMetadata struct { + // Metadata about the provider for cloud hosted k8s clusters. + ProviderInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo + + // Labels to add to registration output resources (KubernetesCluster and Secret). + ResourceLabels map[string]string + + // The set of PolicyRules for the cluster roles created on the remote cluster upon registration. + ClusterRolePolicyRules []*v1alpha1.PolicyRule +} + /* NewClusterRegistrant returns an implementation of ClusterRegistrant. @@ -301,7 +313,7 @@ func (c *clusterRegistrant) RegisterClusterWithToken( token string, opts Options, ) error { - return c.RegisterProviderClusterWithToken(ctx, masterClusterCfg, remoteClientCfg, token, opts, nil, nil, nil) + return c.RegisterProviderClusterWithToken(ctx, masterClusterCfg, remoteClientCfg, token, opts, RegistrationMetadata{}) } func (c *clusterRegistrant) RegisterProviderClusterWithToken( @@ -310,9 +322,7 @@ func (c *clusterRegistrant) RegisterProviderClusterWithToken( remoteClientCfg clientcmd.ClientConfig, token string, opts Options, - providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, - resourceLabels map[string]string, - policyRules []*v1alpha1.PolicyRule, + metadata RegistrationMetadata, ) error { if err := (&opts).validate(); err != nil { return err @@ -347,7 +357,7 @@ func (c *clusterRegistrant) RegisterProviderClusterWithToken( kcSecret, err := kubeconfig.ToSecret( opts.Namespace, opts.ClusterName, - resourceLabels, + metadata.ResourceLabels, c.buildRemoteCfg(remoteCluster, remoteContext, opts.ClusterName, token), ) if err != nil { @@ -358,7 +368,14 @@ func (c *clusterRegistrant) RegisterProviderClusterWithToken( return err } - kubeCluster := buildKubeClusterResource(kcSecret, resourceLabels, opts.ClusterDomain, providerInfo, opts.RemoteNamespace, policyRules) + kubeCluster := buildKubeClusterResource( + kcSecret, + metadata.ResourceLabels, + opts.ClusterDomain, + metadata.ProviderInfo, + opts.RemoteNamespace, + metadata.ClusterRolePolicyRules, + ) kubeClusterClient, err := c.kubeClusterFactory(masterClusterCfg) if err != nil { diff --git a/pkg/multicluster/register/registrant_test.go b/pkg/multicluster/register/registrant_test.go index 9c216d0d6..d169a7888 100644 --- a/pkg/multicluster/register/registrant_test.go +++ b/pkg/multicluster/register/registrant_test.go @@ -655,11 +655,13 @@ var _ = Describe("Registrant", func() { clientConfig, token, opts, - providerInfo, - map[string]string{ - "foo": "bar", + register.RegistrationMetadata{ + ProviderInfo: providerInfo, + ResourceLabels: map[string]string{ + "foo": "bar", + }, + ClusterRolePolicyRules: policyRules, }, - policyRules, ) Expect(err).NotTo(HaveOccurred()) From f32afe68aa42857c152b75d7aed48e43cee95b97 Mon Sep 17 00:00:00 2001 From: Harvey Xia Date: Wed, 16 Sep 2020 09:46:11 -0400 Subject: [PATCH 10/14] fix e2e --- codegen/render/kube_multicluster_test.go | 12 +++++++----- pkg/multicluster/register/interfaces.go | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/codegen/render/kube_multicluster_test.go b/codegen/render/kube_multicluster_test.go index d7ea107c4..d2f6e779d 100644 --- a/codegen/render/kube_multicluster_test.go +++ b/codegen/render/kube_multicluster_test.go @@ -85,9 +85,10 @@ var _ = WithRemoteClusterContextDescribe("Multicluster", func() { Expect(err).NotTo(HaveOccurred()) err = register.RegisterClusterFromConfig(ctx, masterConfig, remoteCfg, register.RbacOptions{ Options: register.Options{ - ClusterName: cluster2, - Namespace: ns, - RemoteCtx: remoteContext, + ClusterName: cluster2, + Namespace: ns, + RemoteNamespace: ns, + RemoteCtx: remoteContext, }, ClusterRoleBindings: test.ServiceAccountClusterAdminRoles, }, registrant) @@ -95,8 +96,9 @@ var _ = WithRemoteClusterContextDescribe("Multicluster", func() { cfg := test.ClientConfigWithContext("") err = register.RegisterClusterFromConfig(ctx, masterConfig, cfg, register.RbacOptions{ Options: register.Options{ - ClusterName: cluster1, - Namespace: ns, + ClusterName: cluster1, + Namespace: ns, + RemoteNamespace: ns, }, ClusterRoleBindings: test.ServiceAccountClusterAdminRoles, }, registrant) diff --git a/pkg/multicluster/register/interfaces.go b/pkg/multicluster/register/interfaces.go index 42ca0ea30..c3ca88ed7 100644 --- a/pkg/multicluster/register/interfaces.go +++ b/pkg/multicluster/register/interfaces.go @@ -29,7 +29,7 @@ type Options struct { // If left empty will return error ClusterName string - // Namespace to write namespaced resources to in the "master" and "remote" clusters + // Namespace to write namespaced resources to in the management cluster. // If left empty will return error Namespace string @@ -37,7 +37,7 @@ type Options struct { // We need to explicitly pass this because of this open issue: https://github.com/kubernetes/client-go/issues/735 RemoteCtx string - // Namespace to write namespaced resources to in the "master" and "remote" clusters + // Namespace to write namespaced resources to in the remote cluster. // If left empty will return error RemoteNamespace string From 3f033a2e2fd06627134a14f2fa913236d275056c Mon Sep 17 00:00:00 2001 From: Harvey Xia Date: Wed, 16 Sep 2020 15:56:23 -0400 Subject: [PATCH 11/14] consolidate registration opts into Options struct --- codegen/render/kube_multicluster_test.go | 26 +-- pkg/multicluster/register/helpers.go | 119 ++++++----- pkg/multicluster/register/interfaces.go | 35 ++-- .../register/mocks/mock_interfaces.go | 18 +- pkg/multicluster/register/registrant.go | 78 +++---- pkg/multicluster/register/registrant_test.go | 191 +++++++++--------- 6 files changed, 218 insertions(+), 249 deletions(-) diff --git a/codegen/render/kube_multicluster_test.go b/codegen/render/kube_multicluster_test.go index d2f6e779d..a3964a25a 100644 --- a/codegen/render/kube_multicluster_test.go +++ b/codegen/render/kube_multicluster_test.go @@ -83,24 +83,24 @@ var _ = WithRemoteClusterContextDescribe("Multicluster", func() { remoteCfg := test.ClientConfigWithContext(remoteContext) registrant, err := register.DefaultRegistrant("", "") Expect(err).NotTo(HaveOccurred()) - err = register.RegisterClusterFromConfig(ctx, masterConfig, remoteCfg, register.RbacOptions{ - Options: register.Options{ - ClusterName: cluster2, - Namespace: ns, - RemoteNamespace: ns, - RemoteCtx: remoteContext, + err = register.RegisterClusterFromConfig(ctx, masterConfig, remoteCfg, register.Options{ + ClusterName: cluster2, + Namespace: ns, + RemoteNamespace: ns, + RemoteCtx: remoteContext, + RbacOptions: register.RbacOptions{ + ClusterRoleBindings: test.ServiceAccountClusterAdminRoles, }, - ClusterRoleBindings: test.ServiceAccountClusterAdminRoles, }, registrant) Expect(err).NotTo(HaveOccurred()) cfg := test.ClientConfigWithContext("") - err = register.RegisterClusterFromConfig(ctx, masterConfig, cfg, register.RbacOptions{ - Options: register.Options{ - ClusterName: cluster1, - Namespace: ns, - RemoteNamespace: ns, + err = register.RegisterClusterFromConfig(ctx, masterConfig, cfg, register.Options{ + ClusterName: cluster1, + Namespace: ns, + RemoteNamespace: ns, + RbacOptions: register.RbacOptions{ + ClusterRoleBindings: test.ServiceAccountClusterAdminRoles, }, - ClusterRoleBindings: test.ServiceAccountClusterAdminRoles, }, registrant) Expect(err).NotTo(HaveOccurred()) }) diff --git a/pkg/multicluster/register/helpers.go b/pkg/multicluster/register/helpers.go index 3d1055b3b..b1aee6f6f 100644 --- a/pkg/multicluster/register/helpers.go +++ b/pkg/multicluster/register/helpers.go @@ -97,35 +97,17 @@ func (opts RegistrationOptions) RegisterProviderCluster( ctx context.Context, providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, ) error { - masterRestCfg, remoteCfg, rbacOpts, registrant, err := opts.initialize() + masterRestCfg, remoteCfg, registrationOpts, registrant, err := opts.initialize(providerInfo) if err != nil { return err } - // Parse ClusterRole policy rules and pass into RegisterProviderClusterFromConfig in order to persist them to the resulting - // KubernetesCluster status. - var clusterRolePolicyRules []*v1alpha1.PolicyRule - for _, clusterRole := range opts.ClusterRoles { - for _, policyRules := range clusterRole.Rules { - clusterRolePolicyRules = append(clusterRolePolicyRules, &v1alpha1.PolicyRule{ - Verbs: policyRules.Verbs, - ApiGroups: policyRules.APIGroups, - Resources: policyRules.Resources, - ResourceNames: policyRules.ResourceNames, - NonResourceUrls: policyRules.NonResourceURLs, - }) - } - } - return RegisterProviderClusterFromConfig( + + return RegisterClusterFromConfig( ctx, masterRestCfg, remoteCfg, - rbacOpts, + registrationOpts, registrant, - RegistrationMetadata{ - ProviderInfo: providerInfo, - ResourceLabels: opts.ResourceLabels, - ClusterRolePolicyRules: clusterRolePolicyRules, - }, ) } @@ -139,87 +121,100 @@ func (opts RegistrationOptions) RegisterProviderCluster( func (opts RegistrationOptions) DeregisterCluster( ctx context.Context, ) error { - masterRestCfg, remoteCfg, rbacOpts, registrant, err := opts.initialize() + masterRestCfg, remoteCfg, registrationOpts, registrant, err := opts.initialize(nil) if err != nil { return err } - return DeregisterClusterFromConfig(ctx, masterRestCfg, remoteCfg, rbacOpts, registrant) + return DeregisterClusterFromConfig(ctx, masterRestCfg, remoteCfg, registrationOpts, registrant) } // Initialize registration dependencies -func (opts RegistrationOptions) initialize() (masterRestCfg *rest.Config, remoteCfg clientcmd.ClientConfig, rbacOpts RbacOptions, registrant ClusterRegistrant, err error) { +func (opts RegistrationOptions) initialize( + providerInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo, +) (masterRestCfg *rest.Config, remoteCfg clientcmd.ClientConfig, registrationOpts Options, registrant ClusterRegistrant, err error) { masterRestCfg, err = opts.KubeCfg.ClientConfig() if err != nil { - return masterRestCfg, remoteCfg, rbacOpts, registrant, err + return masterRestCfg, remoteCfg, registrationOpts, registrant, err } remoteCfg = opts.RemoteKubeCfg registrant, err = defaultRegistrant(masterRestCfg, opts.APIServerAddress) if err != nil { - return masterRestCfg, remoteCfg, rbacOpts, registrant, err + return masterRestCfg, remoteCfg, registrationOpts, registrant, err } - rbacOpts = RbacOptions{ - Options: Options{ - ClusterName: opts.ClusterName, - Namespace: opts.Namespace, - RemoteCtx: opts.RemoteCtx, - RemoteNamespace: opts.RemoteNamespace, - ClusterDomain: opts.ClusterDomain, + // Parse ClusterRole policy rules by iterating all cluster roles + var clusterRolePolicyRules []*v1alpha1.PolicyRule + for _, clusterRole := range opts.ClusterRoles { + for _, policyRules := range clusterRole.Rules { + clusterRolePolicyRules = append(clusterRolePolicyRules, &v1alpha1.PolicyRule{ + Verbs: policyRules.Verbs, + ApiGroups: policyRules.APIGroups, + Resources: policyRules.Resources, + ResourceNames: policyRules.ResourceNames, + NonResourceUrls: policyRules.NonResourceURLs, + }) + } + } + + registrationOpts = Options{ + ClusterName: opts.ClusterName, + Namespace: opts.Namespace, + RemoteCtx: opts.RemoteCtx, + RemoteNamespace: opts.RemoteNamespace, + ClusterDomain: opts.ClusterDomain, + RbacOptions: RbacOptions{ + Roles: opts.Roles, + ClusterRoles: opts.ClusterRoles, + RoleBindings: opts.RoleBindings, + ClusterRoleBindings: opts.ClusterRoleBindings, + }, + RegistrationMetadata: RegistrationMetadata{ + ProviderInfo: providerInfo, + ResourceLabels: opts.ResourceLabels, + ClusterRolePolicyRules: clusterRolePolicyRules, }, - Roles: opts.Roles, - ClusterRoles: opts.ClusterRoles, - RoleBindings: opts.RoleBindings, - ClusterRoleBindings: opts.ClusterRoleBindings, } - return masterRestCfg, remoteCfg, rbacOpts, registrant, nil + return masterRestCfg, remoteCfg, registrationOpts, registrant, nil } func RegisterClusterFromConfig( ctx context.Context, masterClusterCfg *rest.Config, remoteCfg clientcmd.ClientConfig, - opts RbacOptions, + opts Options, registrant ClusterRegistrant, -) error { - return RegisterProviderClusterFromConfig(ctx, masterClusterCfg, remoteCfg, opts, registrant, RegistrationMetadata{}) -} - -func RegisterProviderClusterFromConfig( - ctx context.Context, - masterClusterCfg *rest.Config, - remoteCfg clientcmd.ClientConfig, - opts RbacOptions, - registrant ClusterRegistrant, - metadata RegistrationMetadata, ) error { err := registrant.EnsureRemoteNamespace(ctx, remoteCfg, opts.RemoteNamespace) if err != nil { return err } - sa, err := registrant.EnsureRemoteServiceAccount(ctx, remoteCfg, opts.Options) + sa, err := registrant.EnsureRemoteServiceAccount(ctx, remoteCfg, opts) if err != nil { return err } - token, err := registrant.CreateRemoteAccessToken(ctx, remoteCfg, client.ObjectKey{ - Namespace: sa.GetNamespace(), - Name: sa.GetName(), - }, opts) + token, err := registrant.CreateRemoteAccessToken( + ctx, + remoteCfg, + client.ObjectKey{ + Namespace: sa.GetNamespace(), + Name: sa.GetName(), + }, + opts) if err != nil { return err } - return registrant.RegisterProviderClusterWithToken( + return registrant.RegisterClusterWithToken( ctx, masterClusterCfg, remoteCfg, token, - opts.Options, - metadata, + opts, ) } @@ -227,16 +222,16 @@ func DeregisterClusterFromConfig( ctx context.Context, masterClusterCfg *rest.Config, remoteCfg clientcmd.ClientConfig, - opts RbacOptions, + opts Options, registrant ClusterRegistrant, ) error { var multierr *multierror.Error - if err := registrant.DeregisterCluster(ctx, masterClusterCfg, opts.Options); err != nil { + if err := registrant.DeregisterCluster(ctx, masterClusterCfg, opts); err != nil { multierr = multierror.Append(multierr, err) } - if err := registrant.DeleteRemoteServiceAccount(ctx, remoteCfg, opts.Options); err != nil { + if err := registrant.DeleteRemoteServiceAccount(ctx, remoteCfg, opts); err != nil { multierr = multierror.Append(multierr, err) } diff --git a/pkg/multicluster/register/interfaces.go b/pkg/multicluster/register/interfaces.go index c3ca88ed7..434a21408 100644 --- a/pkg/multicluster/register/interfaces.go +++ b/pkg/multicluster/register/interfaces.go @@ -3,6 +3,7 @@ package register import ( "context" + "github.com/solo-io/skv2/pkg/api/multicluster.solo.io/v1alpha1" "k8s.io/client-go/rest" "github.com/rotisserie/eris" @@ -45,11 +46,25 @@ type Options struct { // Defaults to 'cluster.local' // Read more: https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/ ClusterDomain string + + RegistrationMetadata RegistrationMetadata + + RbacOptions RbacOptions } -type RbacOptions struct { - Options +// Optional additional metadata to persist to registration output resources. +type RegistrationMetadata struct { + // Metadata about the provider for cloud hosted k8s clusters. + ProviderInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo + // Labels to add to registration output resources (KubernetesCluster and Secret). + ResourceLabels map[string]string + + // The set of PolicyRules for the cluster roles created on the remote cluster upon registration. + ClusterRolePolicyRules []*v1alpha1.PolicyRule +} + +type RbacOptions struct { // A list of roles to bind the New kubeconfig token to // Any Roles in this list will be Upserted by the registrant, prior to binding Roles []*k8s_rbac_types.Role @@ -129,7 +144,7 @@ type ClusterRegistrant interface { ctx context.Context, remoteClientCfg clientcmd.ClientConfig, sa client.ObjectKey, - opts RbacOptions, + opts Options, ) (token string, err error) /* @@ -139,7 +154,7 @@ type ClusterRegistrant interface { DeleteRemoteAccessResources( ctx context.Context, remoteClientCfg clientcmd.ClientConfig, - opts RbacOptions, + opts Options, ) error /* @@ -154,18 +169,6 @@ type ClusterRegistrant interface { opts Options, ) error - /* - Same functionality as RegisterClusterWithToken but supply extra ProviderInfo metadata and registration settings (namespace and policyRules). - */ - RegisterProviderClusterWithToken( - ctx context.Context, - masterClusterCfg *rest.Config, - remoteClientCfg clientcmd.ClientConfig, - token string, - opts Options, - metadata RegistrationMetadata, - ) error - /* DeregisterClusterWithToken deletes all resources created by RegisterClusterWithToken. */ diff --git a/pkg/multicluster/register/mocks/mock_interfaces.go b/pkg/multicluster/register/mocks/mock_interfaces.go index 9c1ee325c..3aba550e7 100644 --- a/pkg/multicluster/register/mocks/mock_interfaces.go +++ b/pkg/multicluster/register/mocks/mock_interfaces.go @@ -83,7 +83,7 @@ func (mr *MockClusterRegistrantMockRecorder) DeleteRemoteServiceAccount(ctx, rem } // CreateRemoteAccessToken mocks base method -func (m *MockClusterRegistrant) CreateRemoteAccessToken(ctx context.Context, remoteClientCfg clientcmd.ClientConfig, sa client.ObjectKey, opts register.RbacOptions) (string, error) { +func (m *MockClusterRegistrant) CreateRemoteAccessToken(ctx context.Context, remoteClientCfg clientcmd.ClientConfig, sa client.ObjectKey, opts register.Options) (string, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreateRemoteAccessToken", ctx, remoteClientCfg, sa, opts) ret0, _ := ret[0].(string) @@ -98,7 +98,7 @@ func (mr *MockClusterRegistrantMockRecorder) CreateRemoteAccessToken(ctx, remote } // DeleteRemoteAccessResources mocks base method -func (m *MockClusterRegistrant) DeleteRemoteAccessResources(ctx context.Context, remoteClientCfg clientcmd.ClientConfig, opts register.RbacOptions) error { +func (m *MockClusterRegistrant) DeleteRemoteAccessResources(ctx context.Context, remoteClientCfg clientcmd.ClientConfig, opts register.Options) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DeleteRemoteAccessResources", ctx, remoteClientCfg, opts) ret0, _ := ret[0].(error) @@ -125,20 +125,6 @@ func (mr *MockClusterRegistrantMockRecorder) RegisterClusterWithToken(ctx, maste return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterClusterWithToken", reflect.TypeOf((*MockClusterRegistrant)(nil).RegisterClusterWithToken), ctx, masterClusterCfg, remoteClientCfg, token, opts) } -// RegisterProviderClusterWithToken mocks base method -func (m *MockClusterRegistrant) RegisterProviderClusterWithToken(ctx context.Context, masterClusterCfg *rest.Config, remoteClientCfg clientcmd.ClientConfig, token string, opts register.Options, metadata register.RegistrationMetadata) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RegisterProviderClusterWithToken", ctx, masterClusterCfg, remoteClientCfg, token, opts, metadata) - ret0, _ := ret[0].(error) - return ret0 -} - -// RegisterProviderClusterWithToken indicates an expected call of RegisterProviderClusterWithToken -func (mr *MockClusterRegistrantMockRecorder) RegisterProviderClusterWithToken(ctx, masterClusterCfg, remoteClientCfg, token, opts, metadata interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterProviderClusterWithToken", reflect.TypeOf((*MockClusterRegistrant)(nil).RegisterProviderClusterWithToken), ctx, masterClusterCfg, remoteClientCfg, token, opts, metadata) -} - // DeregisterCluster mocks base method func (m *MockClusterRegistrant) DeregisterCluster(ctx context.Context, masterClusterCfg *rest.Config, opts register.Options) error { m.ctrl.T.Helper() diff --git a/pkg/multicluster/register/registrant.go b/pkg/multicluster/register/registrant.go index 9c40485b9..270cb49b8 100644 --- a/pkg/multicluster/register/registrant.go +++ b/pkg/multicluster/register/registrant.go @@ -49,18 +49,6 @@ var ( } ) -// Optional additional metadata to persist to registration output resources. -type RegistrationMetadata struct { - // Metadata about the provider for cloud hosted k8s clusters. - ProviderInfo *v1alpha1.KubernetesClusterSpec_ProviderInfo - - // Labels to add to registration output resources (KubernetesCluster and Secret). - ResourceLabels map[string]string - - // The set of PolicyRules for the cluster roles created on the remote cluster upon registration. - ClusterRolePolicyRules []*v1alpha1.PolicyRule -} - /* NewClusterRegistrant returns an implementation of ClusterRegistrant. @@ -195,7 +183,7 @@ func (c *clusterRegistrant) CreateRemoteAccessToken( ctx context.Context, remoteClientCfg clientcmd.ClientConfig, sa client.ObjectKey, - opts RbacOptions, + opts Options, ) (token string, err error) { if err = (&opts).validate(); err != nil { @@ -212,13 +200,15 @@ func (c *clusterRegistrant) CreateRemoteAccessToken( return "", err } - roleBindings := make([]client.ObjectKey, 0, len(opts.Roles)+len(opts.RoleBindings)) - roleBindings = append(roleBindings, opts.RoleBindings...) - if len(opts.Roles) != 0 { - if err = c.upsertRoles(ctx, remoteCfg, opts.Roles); err != nil { + rbacOpts := opts.RbacOptions + + roleBindings := make([]client.ObjectKey, 0, len(rbacOpts.Roles)+len(rbacOpts.RoleBindings)) + roleBindings = append(roleBindings, rbacOpts.RoleBindings...) + if len(rbacOpts.Roles) != 0 { + if err = c.upsertRoles(ctx, remoteCfg, rbacOpts.Roles); err != nil { return "", err } - for _, v := range opts.Roles { + for _, v := range rbacOpts.Roles { roleBindings = append(roleBindings, client.ObjectKey{ Namespace: v.GetNamespace(), Name: v.GetName(), @@ -231,13 +221,13 @@ func (c *clusterRegistrant) CreateRemoteAccessToken( } } - clusterRoleBindings := make([]client.ObjectKey, 0, len(opts.ClusterRoles)+len(opts.ClusterRoleBindings)) - clusterRoleBindings = append(clusterRoleBindings, opts.ClusterRoleBindings...) - if len(opts.ClusterRoles) != 0 { - if err = c.upsertClusterRoles(ctx, remoteCfg, opts.ClusterRoles); err != nil { + clusterRoleBindings := make([]client.ObjectKey, 0, len(rbacOpts.ClusterRoles)+len(rbacOpts.ClusterRoleBindings)) + clusterRoleBindings = append(clusterRoleBindings, rbacOpts.ClusterRoleBindings...) + if len(rbacOpts.ClusterRoles) != 0 { + if err = c.upsertClusterRoles(ctx, remoteCfg, rbacOpts.ClusterRoles); err != nil { return "", err } - for _, v := range opts.ClusterRoles { + for _, v := range rbacOpts.ClusterRoles { clusterRoleBindings = append(clusterRoleBindings, client.ObjectKey{ Name: v.GetName(), }) @@ -254,22 +244,25 @@ func (c *clusterRegistrant) CreateRemoteAccessToken( func (c *clusterRegistrant) DeleteRemoteAccessResources(ctx context.Context, remoteClientCfg clientcmd.ClientConfig, - opts RbacOptions, + opts Options, ) error { - saObjMeta := serviceAccountObjMeta(opts.Options) + saObjMeta := serviceAccountObjMeta(opts) sa := client.ObjectKey{Name: saObjMeta.Name, Namespace: saObjMeta.Namespace} remoteCfg, err := remoteClientCfg.ClientConfig() if err != nil { return err } + + rbacOpts := opts.RbacOptions + var multierr *multierror.Error // Delete Roles - if err := c.deleteRoles(ctx, remoteCfg, opts.Roles); err != nil { + if err := c.deleteRoles(ctx, remoteCfg, rbacOpts.Roles); err != nil { multierr = multierror.Append(multierr, err) } // Delete ClusterRoles - if err := c.deleteClusterRoles(ctx, remoteCfg, opts.ClusterRoles); err != nil { + if err := c.deleteClusterRoles(ctx, remoteCfg, rbacOpts.ClusterRoles); err != nil { multierr = multierror.Append(multierr, err) } @@ -279,9 +272,9 @@ func (c *clusterRegistrant) DeleteRemoteAccessResources(ctx context.Context, } // Delete RoleBindings - roleBindings := make([]client.ObjectKey, 0, len(opts.Roles)+len(opts.RoleBindings)) - roleBindings = append(roleBindings, opts.RoleBindings...) - for _, v := range opts.Roles { + roleBindings := make([]client.ObjectKey, 0, len(rbacOpts.Roles)+len(rbacOpts.RoleBindings)) + roleBindings = append(roleBindings, rbacOpts.RoleBindings...) + for _, v := range rbacOpts.Roles { roleBindings = append(roleBindings, client.ObjectKey{ Name: v.GetName(), Namespace: v.GetNamespace(), @@ -292,9 +285,9 @@ func (c *clusterRegistrant) DeleteRemoteAccessResources(ctx context.Context, } // Delete ClusterRoleBindings - clusterRoleBindings := make([]client.ObjectKey, 0, len(opts.ClusterRoles)+len(opts.ClusterRoleBindings)) - clusterRoleBindings = append(clusterRoleBindings, opts.ClusterRoleBindings...) - for _, v := range opts.ClusterRoles { + clusterRoleBindings := make([]client.ObjectKey, 0, len(rbacOpts.ClusterRoles)+len(rbacOpts.ClusterRoleBindings)) + clusterRoleBindings = append(clusterRoleBindings, rbacOpts.ClusterRoleBindings...) + for _, v := range rbacOpts.ClusterRoles { clusterRoleBindings = append(clusterRoleBindings, client.ObjectKey{ Name: v.GetName(), }) @@ -312,17 +305,6 @@ func (c *clusterRegistrant) RegisterClusterWithToken( remoteClientCfg clientcmd.ClientConfig, token string, opts Options, -) error { - return c.RegisterProviderClusterWithToken(ctx, masterClusterCfg, remoteClientCfg, token, opts, RegistrationMetadata{}) -} - -func (c *clusterRegistrant) RegisterProviderClusterWithToken( - ctx context.Context, - masterClusterCfg *rest.Config, - remoteClientCfg clientcmd.ClientConfig, - token string, - opts Options, - metadata RegistrationMetadata, ) error { if err := (&opts).validate(); err != nil { return err @@ -357,7 +339,7 @@ func (c *clusterRegistrant) RegisterProviderClusterWithToken( kcSecret, err := kubeconfig.ToSecret( opts.Namespace, opts.ClusterName, - metadata.ResourceLabels, + opts.RegistrationMetadata.ResourceLabels, c.buildRemoteCfg(remoteCluster, remoteContext, opts.ClusterName, token), ) if err != nil { @@ -370,11 +352,11 @@ func (c *clusterRegistrant) RegisterProviderClusterWithToken( kubeCluster := buildKubeClusterResource( kcSecret, - metadata.ResourceLabels, + opts.RegistrationMetadata.ResourceLabels, opts.ClusterDomain, - metadata.ProviderInfo, + opts.RegistrationMetadata.ProviderInfo, opts.RemoteNamespace, - metadata.ClusterRolePolicyRules, + opts.RegistrationMetadata.ClusterRolePolicyRules, ) kubeClusterClient, err := c.kubeClusterFactory(masterClusterCfg) diff --git a/pkg/multicluster/register/registrant_test.go b/pkg/multicluster/register/registrant_test.go index d169a7888..51d3ce4ca 100644 --- a/pkg/multicluster/register/registrant_test.go +++ b/pkg/multicluster/register/registrant_test.go @@ -225,59 +225,59 @@ var _ = Describe("Registrant", func() { ClientConfig(). Return(nil, nil) - opts := register.RbacOptions{ - Options: register.Options{ - ClusterName: clusterName, - Namespace: namespace, - RemoteCtx: remoteCtx, - }, - Roles: []*rbacv1.Role{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "r-1", - Namespace: namespace, + opts := register.Options{ + ClusterName: clusterName, + Namespace: namespace, + RemoteCtx: remoteCtx, + RbacOptions: register.RbacOptions{ + Roles: []*rbacv1.Role{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "r-1", + Namespace: namespace, + }, }, }, - }, - ClusterRoles: []*rbacv1.ClusterRole{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "cr-1", + ClusterRoles: []*rbacv1.ClusterRole{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "cr-1", + }, }, }, - }, - RoleBindings: []client.ObjectKey{ - { - Namespace: "namespace", - Name: "rb-1", + RoleBindings: []client.ObjectKey{ + { + Namespace: "namespace", + Name: "rb-1", + }, }, - }, - ClusterRoleBindings: []client.ObjectKey{ - { - Namespace: "", - Name: "crb-1", + ClusterRoleBindings: []client.ObjectKey{ + { + Namespace: "", + Name: "crb-1", + }, }, }, } - + rbacOpts := opts.RbacOptions roleClient.EXPECT(). - UpsertRole(ctx, opts.Roles[0]). + UpsertRole(ctx, rbacOpts.Roles[0]). Return(nil) clusterRBACBinder.EXPECT(). - BindRoles(ctx, sa, append(opts.RoleBindings, client.ObjectKey{ - Name: opts.Roles[0].GetName(), - Namespace: opts.Roles[0].GetNamespace(), + BindRoles(ctx, sa, append(rbacOpts.RoleBindings, client.ObjectKey{ + Name: rbacOpts.Roles[0].GetName(), + Namespace: rbacOpts.Roles[0].GetNamespace(), })). Return(nil) clusterRoleClient.EXPECT(). - UpsertClusterRole(ctx, opts.ClusterRoles[0]). + UpsertClusterRole(ctx, rbacOpts.ClusterRoles[0]). Return(nil) clusterRBACBinder.EXPECT(). - BindClusterRoles(ctx, sa, append(opts.ClusterRoleBindings, client.ObjectKey{ - Name: opts.ClusterRoles[0].GetName(), + BindClusterRoles(ctx, sa, append(rbacOpts.ClusterRoleBindings, client.ObjectKey{ + Name: rbacOpts.ClusterRoles[0].GetName(), })).Return(nil) token := "hello" @@ -345,60 +345,62 @@ var _ = Describe("Registrant", func() { ClientConfig(). Return(nil, nil) - opts := register.RbacOptions{ - Options: register.Options{ - ClusterName: clusterName, - Namespace: namespace, - RemoteCtx: remoteCtx, - RemoteNamespace: "remote-namespace", - }, - Roles: []*rbacv1.Role{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "r-1", - Namespace: namespace, + opts := register.Options{ + ClusterName: clusterName, + Namespace: namespace, + RemoteCtx: remoteCtx, + RemoteNamespace: "remote-namespace", + RbacOptions: register.RbacOptions{ + Roles: []*rbacv1.Role{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "r-1", + Namespace: namespace, + }, }, }, - }, - ClusterRoles: []*rbacv1.ClusterRole{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "cr-1", + ClusterRoles: []*rbacv1.ClusterRole{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "cr-1", + }, }, }, - }, - RoleBindings: []client.ObjectKey{ - { - Namespace: "namespace", - Name: "rb-1", + RoleBindings: []client.ObjectKey{ + { + Namespace: "namespace", + Name: "rb-1", + }, }, - }, - ClusterRoleBindings: []client.ObjectKey{ - { - Namespace: "", - Name: "crb-1", + ClusterRoleBindings: []client.ObjectKey{ + { + Namespace: "", + Name: "crb-1", + }, }, }, } + rbacOpts := opts.RbacOptions + roleClient.EXPECT(). - DeleteRole(ctx, client.ObjectKey{Name: opts.Roles[0].Name, Namespace: opts.Roles[0].Namespace}). + DeleteRole(ctx, client.ObjectKey{Name: rbacOpts.Roles[0].Name, Namespace: rbacOpts.Roles[0].Namespace}). Return(nil) clusterRBACBinder.EXPECT(). - DeleteRoleBindings(ctx, sa, append(opts.RoleBindings, client.ObjectKey{ - Name: opts.Roles[0].GetName(), - Namespace: opts.Roles[0].GetNamespace(), + DeleteRoleBindings(ctx, sa, append(rbacOpts.RoleBindings, client.ObjectKey{ + Name: rbacOpts.Roles[0].GetName(), + Namespace: rbacOpts.Roles[0].GetNamespace(), })). Return(nil) clusterRoleClient.EXPECT(). - DeleteClusterRole(ctx, opts.ClusterRoles[0].Name). + DeleteClusterRole(ctx, rbacOpts.ClusterRoles[0].Name). Return(nil) clusterRBACBinder.EXPECT(). - DeleteClusterRoleBindings(ctx, sa, append(opts.ClusterRoleBindings, client.ObjectKey{ - Name: opts.ClusterRoles[0].GetName(), + DeleteClusterRoleBindings(ctx, sa, append(rbacOpts.ClusterRoleBindings, client.ObjectKey{ + Name: rbacOpts.ClusterRoles[0].GetName(), })).Return(nil) err := clusterRegistrant.DeleteRemoteAccessResources(ctx, clientConfig, opts) @@ -534,10 +536,36 @@ var _ = Describe("Registrant", func() { kubeClusterClientFactory, ) + providerInfo := &v1alpha1.KubernetesClusterSpec_ProviderInfo{ + ProviderInfoType: &v1alpha1.KubernetesClusterSpec_ProviderInfo_Eks{ + Eks: &v1alpha1.KubernetesClusterSpec_Eks{ + Arn: "arn", + AccountId: "accountId", + Region: "region", + Name: "name", + }, + }, + } + + policyRules := []*v1alpha1.PolicyRule{ + { + Verbs: []string{"watch"}, + ApiGroups: []string{"v1alpha1"}, + Resources: []string{"foo"}, + }, + } + opts := register.Options{ ClusterName: clusterName, Namespace: namespace, RemoteCtx: remoteCtx, + RegistrationMetadata: register.RegistrationMetadata{ + ProviderInfo: providerInfo, + ResourceLabels: map[string]string{ + "foo": "bar", + }, + ClusterRolePolicyRules: policyRules, + }, } restCfg := &rest.Config{ @@ -610,24 +638,6 @@ var _ = Describe("Registrant", func() { CreateSecret(ctx, secret). Return(nil) - providerInfo := &v1alpha1.KubernetesClusterSpec_ProviderInfo{ - ProviderInfoType: &v1alpha1.KubernetesClusterSpec_ProviderInfo_Eks{ - Eks: &v1alpha1.KubernetesClusterSpec_Eks{ - Arn: "arn", - AccountId: "accountId", - Region: "region", - Name: "name", - }, - }, - } - - policyRules := []*v1alpha1.PolicyRule{ - { - Verbs: []string{"watch"}, - ApiGroups: []string{"v1alpha1"}, - Resources: []string{"foo"}, - }, - } kubeCluster := &v1alpha1.KubernetesCluster{ ObjectMeta: metav1.ObjectMeta{ Name: secret.ObjectMeta.Name, @@ -649,19 +659,12 @@ var _ = Describe("Registrant", func() { kubeClusterClient.EXPECT().UpsertKubernetesCluster(ctx, kubeCluster).Return(nil) kubeClusterClient.EXPECT().UpdateKubernetesClusterStatus(ctx, kubeCluster).Return(nil) - err = clusterRegistrant.RegisterProviderClusterWithToken( + err = clusterRegistrant.RegisterClusterWithToken( ctx, restCfg, clientConfig, token, opts, - register.RegistrationMetadata{ - ProviderInfo: providerInfo, - ResourceLabels: map[string]string{ - "foo": "bar", - }, - ClusterRolePolicyRules: policyRules, - }, ) Expect(err).NotTo(HaveOccurred()) From 086149906533886620fc4b6d5a6be7877687becc Mon Sep 17 00:00:00 2001 From: Harvey Xia Date: Fri, 18 Sep 2020 09:24:36 -0400 Subject: [PATCH 12/14] populate Role PolicyRules --- pkg/multicluster/register/helpers.go | 45 ++++++++++++++++++------- pkg/multicluster/register/interfaces.go | 3 ++ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/pkg/multicluster/register/helpers.go b/pkg/multicluster/register/helpers.go index b1aee6f6f..6e6a06486 100644 --- a/pkg/multicluster/register/helpers.go +++ b/pkg/multicluster/register/helpers.go @@ -144,19 +144,7 @@ func (opts RegistrationOptions) initialize( return masterRestCfg, remoteCfg, registrationOpts, registrant, err } - // Parse ClusterRole policy rules by iterating all cluster roles - var clusterRolePolicyRules []*v1alpha1.PolicyRule - for _, clusterRole := range opts.ClusterRoles { - for _, policyRules := range clusterRole.Rules { - clusterRolePolicyRules = append(clusterRolePolicyRules, &v1alpha1.PolicyRule{ - Verbs: policyRules.Verbs, - ApiGroups: policyRules.APIGroups, - Resources: policyRules.Resources, - ResourceNames: policyRules.ResourceNames, - NonResourceUrls: policyRules.NonResourceURLs, - }) - } - } + rolePolicyRules, clusterRolePolicyRules := collectPolicyRules(opts.Roles, opts.ClusterRoles) registrationOpts = Options{ ClusterName: opts.ClusterName, @@ -173,6 +161,7 @@ func (opts RegistrationOptions) initialize( RegistrationMetadata: RegistrationMetadata{ ProviderInfo: providerInfo, ResourceLabels: opts.ResourceLabels, + RolePolicyRules: rolePolicyRules, ClusterRolePolicyRules: clusterRolePolicyRules, }, } @@ -180,6 +169,36 @@ func (opts RegistrationOptions) initialize( return masterRestCfg, remoteCfg, registrationOpts, registrant, nil } +// Iterate Roles and ClusterRoles to collect set of PolicyRules for each. +func collectPolicyRules( + roles []*k8s_rbac_types.Role, + clusterRoles []*k8s_rbac_types.ClusterRole, +) (rolePolicyRules []*v1alpha1.PolicyRule, clusterRolePolicyRules []*v1alpha1.PolicyRule) { + for _, role := range roles { + for _, policyRules := range role.Rules { + rolePolicyRules = append(rolePolicyRules, &v1alpha1.PolicyRule{ + Verbs: policyRules.Verbs, + ApiGroups: policyRules.APIGroups, + Resources: policyRules.Resources, + ResourceNames: policyRules.ResourceNames, + NonResourceUrls: policyRules.NonResourceURLs, + }) + } + } + for _, clusterRole := range clusterRoles { + for _, policyRules := range clusterRole.Rules { + clusterRolePolicyRules = append(clusterRolePolicyRules, &v1alpha1.PolicyRule{ + Verbs: policyRules.Verbs, + ApiGroups: policyRules.APIGroups, + Resources: policyRules.Resources, + ResourceNames: policyRules.ResourceNames, + NonResourceUrls: policyRules.NonResourceURLs, + }) + } + } + return rolePolicyRules, clusterRolePolicyRules +} + func RegisterClusterFromConfig( ctx context.Context, masterClusterCfg *rest.Config, diff --git a/pkg/multicluster/register/interfaces.go b/pkg/multicluster/register/interfaces.go index 434a21408..9905006af 100644 --- a/pkg/multicluster/register/interfaces.go +++ b/pkg/multicluster/register/interfaces.go @@ -60,6 +60,9 @@ type RegistrationMetadata struct { // Labels to add to registration output resources (KubernetesCluster and Secret). ResourceLabels map[string]string + // The set of PolicyRules for Roles created on the remote cluster upon registration. + RolePolicyRules []*v1alpha1.PolicyRule + // The set of PolicyRules for the cluster roles created on the remote cluster upon registration. ClusterRolePolicyRules []*v1alpha1.PolicyRule } From 944886cfb07b71d6273c73fcf4aeadb3cef862dc Mon Sep 17 00:00:00 2001 From: Harvey Xia Date: Fri, 18 Sep 2020 10:46:59 -0400 Subject: [PATCH 13/14] add option for not deleting remote cluster resources when deregistering a non-existent cluster --- .../test/api/things.test.io/v1/test_api.pb.go | 3 +-- .../things.test.io/v1/test_api_json.gen.go | 3 +-- pkg/api/core.skv2.solo.io/v1/core.pb.go | 3 +-- pkg/api/core.skv2.solo.io/v1/core_json.gen.go | 3 +-- .../v1alpha1/cluster.pb.go | 3 +-- .../v1alpha1/cluster_json.gen.go | 3 +-- pkg/multicluster/register/helpers.go | 22 ++++++++++++++----- pkg/multicluster/register/interfaces.go | 4 ++++ 8 files changed, 26 insertions(+), 18 deletions(-) diff --git a/codegen/test/api/things.test.io/v1/test_api.pb.go b/codegen/test/api/things.test.io/v1/test_api.pb.go index 6f2ac41ea..1836d93b2 100644 --- a/codegen/test/api/things.test.io/v1/test_api.pb.go +++ b/codegen/test/api/things.test.io/v1/test_api.pb.go @@ -5,9 +5,8 @@ package v1 import ( fmt "fmt" - math "math" - proto "github.com/gogo/protobuf/proto" + math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/codegen/test/api/things.test.io/v1/test_api_json.gen.go b/codegen/test/api/things.test.io/v1/test_api_json.gen.go index adce788f2..824b0ffd5 100644 --- a/codegen/test/api/things.test.io/v1/test_api_json.gen.go +++ b/codegen/test/api/things.test.io/v1/test_api_json.gen.go @@ -6,10 +6,9 @@ package v1 import ( bytes "bytes" fmt "fmt" - math "math" - github_com_gogo_protobuf_jsonpb "github.com/gogo/protobuf/jsonpb" proto "github.com/gogo/protobuf/proto" + math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/pkg/api/core.skv2.solo.io/v1/core.pb.go b/pkg/api/core.skv2.solo.io/v1/core.pb.go index 56ed5cb56..c64fbfd8e 100644 --- a/pkg/api/core.skv2.solo.io/v1/core.pb.go +++ b/pkg/api/core.skv2.solo.io/v1/core.pb.go @@ -6,12 +6,11 @@ package v1 import ( bytes "bytes" fmt "fmt" - math "math" - _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" types "github.com/gogo/protobuf/types" _ "github.com/solo-io/protoc-gen-ext/extproto" + math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/pkg/api/core.skv2.solo.io/v1/core_json.gen.go b/pkg/api/core.skv2.solo.io/v1/core_json.gen.go index 5b0b8f1e1..0dfdd432d 100644 --- a/pkg/api/core.skv2.solo.io/v1/core_json.gen.go +++ b/pkg/api/core.skv2.solo.io/v1/core_json.gen.go @@ -6,13 +6,12 @@ package v1 import ( bytes "bytes" fmt "fmt" - math "math" - _ "github.com/gogo/protobuf/gogoproto" github_com_gogo_protobuf_jsonpb "github.com/gogo/protobuf/jsonpb" proto "github.com/gogo/protobuf/proto" _ "github.com/gogo/protobuf/types" _ "github.com/solo-io/protoc-gen-ext/extproto" + math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go b/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go index 4d81bd1fc..38b8e830b 100644 --- a/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go +++ b/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go @@ -6,12 +6,11 @@ package v1alpha1 import ( bytes "bytes" fmt "fmt" - math "math" - _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" _ "github.com/solo-io/protoc-gen-ext/extproto" v1 "github.com/solo-io/skv2/pkg/api/core.skv2.solo.io/v1" + math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/pkg/api/multicluster.solo.io/v1alpha1/cluster_json.gen.go b/pkg/api/multicluster.solo.io/v1alpha1/cluster_json.gen.go index 95151c7f1..e73fce13c 100644 --- a/pkg/api/multicluster.solo.io/v1alpha1/cluster_json.gen.go +++ b/pkg/api/multicluster.solo.io/v1alpha1/cluster_json.gen.go @@ -6,13 +6,12 @@ package v1alpha1 import ( bytes "bytes" fmt "fmt" - math "math" - _ "github.com/gogo/protobuf/gogoproto" github_com_gogo_protobuf_jsonpb "github.com/gogo/protobuf/jsonpb" proto "github.com/gogo/protobuf/proto" _ "github.com/solo-io/protoc-gen-ext/extproto" _ "github.com/solo-io/skv2/pkg/api/core.skv2.solo.io/v1" + math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/pkg/multicluster/register/helpers.go b/pkg/multicluster/register/helpers.go index 6e6a06486..f0aeeace0 100644 --- a/pkg/multicluster/register/helpers.go +++ b/pkg/multicluster/register/helpers.go @@ -20,7 +20,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/config" ) -// Options for registering a cluster +// Options for registering and deregistering a cluster type RegistrationOptions struct { // Management kubeconfig KubeCfg clientcmd.ClientConfig @@ -73,6 +73,10 @@ type RegistrationOptions struct { // Set of labels to include on the registration output resources, currently consisting of KubernetesCluster and Secret. ResourceLabels map[string]string + + // Set to true if the remote cluster no longer exists (e.g. was deleted). + // If true, deregistration will not attempt to delete registration resources on the remote cluster. + RemoteClusterDeleted bool } /* @@ -147,11 +151,12 @@ func (opts RegistrationOptions) initialize( rolePolicyRules, clusterRolePolicyRules := collectPolicyRules(opts.Roles, opts.ClusterRoles) registrationOpts = Options{ - ClusterName: opts.ClusterName, - Namespace: opts.Namespace, - RemoteCtx: opts.RemoteCtx, - RemoteNamespace: opts.RemoteNamespace, - ClusterDomain: opts.ClusterDomain, + ClusterName: opts.ClusterName, + Namespace: opts.Namespace, + RemoteCtx: opts.RemoteCtx, + RemoteNamespace: opts.RemoteNamespace, + ClusterDomain: opts.ClusterDomain, + RemoteClusterDeleted: opts.RemoteClusterDeleted, RbacOptions: RbacOptions{ Roles: opts.Roles, ClusterRoles: opts.ClusterRoles, @@ -250,6 +255,11 @@ func DeregisterClusterFromConfig( multierr = multierror.Append(multierr, err) } + // Do not attempt to delete remote registration resources if remote cluster no longer exists. + if opts.RemoteClusterDeleted { + return multierr.ErrorOrNil() + } + if err := registrant.DeleteRemoteServiceAccount(ctx, remoteCfg, opts); err != nil { multierr = multierror.Append(multierr, err) } diff --git a/pkg/multicluster/register/interfaces.go b/pkg/multicluster/register/interfaces.go index 9905006af..d559eb10f 100644 --- a/pkg/multicluster/register/interfaces.go +++ b/pkg/multicluster/register/interfaces.go @@ -50,6 +50,10 @@ type Options struct { RegistrationMetadata RegistrationMetadata RbacOptions RbacOptions + + // Set to true if the remote cluster no longer exists (e.g. was deleted). + // If true, deregistration will not attempt to delete registration resources on the remote cluster. + RemoteClusterDeleted bool } // Optional additional metadata to persist to registration output resources. From 0c3bcf41d428ad1c8251d6121cab459c4404a709 Mon Sep 17 00:00:00 2001 From: Harvey Xia Date: Fri, 18 Sep 2020 12:54:40 -0400 Subject: [PATCH 14/14] gen code --- codegen/test/api/things.test.io/v1/test_api.pb.go | 3 ++- codegen/test/api/things.test.io/v1/test_api_json.gen.go | 3 ++- pkg/api/core.skv2.solo.io/v1/core.pb.go | 3 ++- pkg/api/core.skv2.solo.io/v1/core_json.gen.go | 3 ++- pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go | 3 ++- pkg/api/multicluster.solo.io/v1alpha1/cluster_json.gen.go | 3 ++- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/codegen/test/api/things.test.io/v1/test_api.pb.go b/codegen/test/api/things.test.io/v1/test_api.pb.go index 1836d93b2..6f2ac41ea 100644 --- a/codegen/test/api/things.test.io/v1/test_api.pb.go +++ b/codegen/test/api/things.test.io/v1/test_api.pb.go @@ -5,8 +5,9 @@ package v1 import ( fmt "fmt" - proto "github.com/gogo/protobuf/proto" math "math" + + proto "github.com/gogo/protobuf/proto" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/codegen/test/api/things.test.io/v1/test_api_json.gen.go b/codegen/test/api/things.test.io/v1/test_api_json.gen.go index 824b0ffd5..adce788f2 100644 --- a/codegen/test/api/things.test.io/v1/test_api_json.gen.go +++ b/codegen/test/api/things.test.io/v1/test_api_json.gen.go @@ -6,9 +6,10 @@ package v1 import ( bytes "bytes" fmt "fmt" + math "math" + github_com_gogo_protobuf_jsonpb "github.com/gogo/protobuf/jsonpb" proto "github.com/gogo/protobuf/proto" - math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/pkg/api/core.skv2.solo.io/v1/core.pb.go b/pkg/api/core.skv2.solo.io/v1/core.pb.go index c64fbfd8e..56ed5cb56 100644 --- a/pkg/api/core.skv2.solo.io/v1/core.pb.go +++ b/pkg/api/core.skv2.solo.io/v1/core.pb.go @@ -6,11 +6,12 @@ package v1 import ( bytes "bytes" fmt "fmt" + math "math" + _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" types "github.com/gogo/protobuf/types" _ "github.com/solo-io/protoc-gen-ext/extproto" - math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/pkg/api/core.skv2.solo.io/v1/core_json.gen.go b/pkg/api/core.skv2.solo.io/v1/core_json.gen.go index 0dfdd432d..5b0b8f1e1 100644 --- a/pkg/api/core.skv2.solo.io/v1/core_json.gen.go +++ b/pkg/api/core.skv2.solo.io/v1/core_json.gen.go @@ -6,12 +6,13 @@ package v1 import ( bytes "bytes" fmt "fmt" + math "math" + _ "github.com/gogo/protobuf/gogoproto" github_com_gogo_protobuf_jsonpb "github.com/gogo/protobuf/jsonpb" proto "github.com/gogo/protobuf/proto" _ "github.com/gogo/protobuf/types" _ "github.com/solo-io/protoc-gen-ext/extproto" - math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go b/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go index 38b8e830b..4d81bd1fc 100644 --- a/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go +++ b/pkg/api/multicluster.solo.io/v1alpha1/cluster.pb.go @@ -6,11 +6,12 @@ package v1alpha1 import ( bytes "bytes" fmt "fmt" + math "math" + _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" _ "github.com/solo-io/protoc-gen-ext/extproto" v1 "github.com/solo-io/skv2/pkg/api/core.skv2.solo.io/v1" - math "math" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/pkg/api/multicluster.solo.io/v1alpha1/cluster_json.gen.go b/pkg/api/multicluster.solo.io/v1alpha1/cluster_json.gen.go index e73fce13c..95151c7f1 100644 --- a/pkg/api/multicluster.solo.io/v1alpha1/cluster_json.gen.go +++ b/pkg/api/multicluster.solo.io/v1alpha1/cluster_json.gen.go @@ -6,12 +6,13 @@ package v1alpha1 import ( bytes "bytes" fmt "fmt" + math "math" + _ "github.com/gogo/protobuf/gogoproto" github_com_gogo_protobuf_jsonpb "github.com/gogo/protobuf/jsonpb" proto "github.com/gogo/protobuf/proto" _ "github.com/solo-io/protoc-gen-ext/extproto" _ "github.com/solo-io/skv2/pkg/api/core.skv2.solo.io/v1" - math "math" ) // Reference imports to suppress errors if they are not otherwise used.