diff --git a/api/docs/apis-network.openshift.io/v1.HostSubnet.adoc b/api/docs/apis-network.openshift.io/v1.HostSubnet.adoc index d42ffcc1b420..eefebb847aef 100644 --- a/api/docs/apis-network.openshift.io/v1.HostSubnet.adoc +++ b/api/docs/apis-network.openshift.io/v1.HostSubnet.adoc @@ -19,7 +19,9 @@ Expand or mouse-over a field for more information about it. ++++
 
apiVersion: -
egressIPs: +
egressCIDRs: +
- [string]: +
egressIPs:
- [string]:
host:
hostIP: diff --git a/api/docs/oapi/v1.HostSubnet.adoc b/api/docs/oapi/v1.HostSubnet.adoc index 0adb9f4689cb..6e7c8874da0d 100644 --- a/api/docs/oapi/v1.HostSubnet.adoc +++ b/api/docs/oapi/v1.HostSubnet.adoc @@ -19,7 +19,9 @@ Expand or mouse-over a field for more information about it. ++++
 
apiVersion: -
egressIPs: +
egressCIDRs: +
- [string]: +
egressIPs:
- [string]:
host:
hostIP: diff --git a/api/protobuf-spec/github_com_openshift_api_network_v1.proto b/api/protobuf-spec/github_com_openshift_api_network_v1.proto index e6f2ff513740..6bbc3ffacf78 100644 --- a/api/protobuf-spec/github_com_openshift_api_network_v1.proto +++ b/api/protobuf-spec/github_com_openshift_api_network_v1.proto @@ -114,9 +114,17 @@ message HostSubnet { // Subnet is the CIDR range of the overlay network assigned to the node for its pods optional string subnet = 4; - // EgressIPs is the list of automatic egress IP addresses currently hosted by this node + // EgressIPs is the list of automatic egress IP addresses currently hosted by this node. + // If EgressCIDRs is empty, this can be set by hand; if EgressCIDRs is set then the + // master will overwrite the value here with its own allocation of egress IPs. // +optional repeated string egressIPs = 5; + + // EgressCIDRs is the list of CIDR ranges available for automatically assigning + // egress IPs to this node from. If this field is set then EgressIPs should be + // treated as read-only. + // +optional + repeated string egressCIDRs = 6; } // HostSubnetList is a collection of HostSubnets diff --git a/api/swagger-spec/oapi-v1.json b/api/swagger-spec/oapi-v1.json index 19a8ab2e97e9..c75be30e7189 100644 --- a/api/swagger-spec/oapi-v1.json +++ b/api/swagger-spec/oapi-v1.json @@ -27528,7 +27528,14 @@ "items": { "type": "string" }, - "description": "EgressIPs is the list of automatic egress IP addresses currently hosted by this node" + "description": "EgressIPs is the list of automatic egress IP addresses currently hosted by this node. If EgressCIDRs is empty, this can be set by hand; if EgressCIDRs is set then the master will overwrite the value here with its own allocation of egress IPs." + }, + "egressCIDRs": { + "type": "array", + "items": { + "type": "string" + }, + "description": "EgressCIDRs is the list of CIDR ranges available for automatically assigning egress IPs to this node from. If this field is set then EgressIPs should be treated as read-only." } } }, diff --git a/api/swagger-spec/openshift-openapi-spec.json b/api/swagger-spec/openshift-openapi-spec.json index 58b5c5564881..025d0980b8fb 100644 --- a/api/swagger-spec/openshift-openapi-spec.json +++ b/api/swagger-spec/openshift-openapi-spec.json @@ -116751,8 +116751,15 @@ "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", "type": "string" }, + "egressCIDRs": { + "description": "EgressCIDRs is the list of CIDR ranges available for automatically assigning egress IPs to this node from. If this field is set then EgressIPs should be treated as read-only.", + "type": "array", + "items": { + "type": "string" + } + }, "egressIPs": { - "description": "EgressIPs is the list of automatic egress IP addresses currently hosted by this node", + "description": "EgressIPs is the list of automatic egress IP addresses currently hosted by this node. If EgressCIDRs is empty, this can be set by hand; if EgressCIDRs is set then the master will overwrite the value here with its own allocation of egress IPs.", "type": "array", "items": { "type": "string" diff --git a/glide.lock b/glide.lock index afc4fe962bc6..e50f656098f5 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 424aaf9eb0319384574a012df2886bbf6cd77b479e7065462bc48a61e99a9b3f -updated: 2018-07-12T22:59:32.292828018-07:00 +updated: 2018-07-19T07:54:15.181641803-04:00 imports: - name: bitbucket.org/ww/goautoneg version: 75cd24fc2f2c2a2088577d12123ddee5f54e0675 @@ -819,7 +819,7 @@ imports: - go-selinux - go-selinux/label - name: github.com/openshift/api - version: 12a230f9f9225237f1a35b86171848da610900bb + version: da58561fa85ae09a2fdc0540001acf835ad239b0 subpackages: - apps/v1 - authorization @@ -930,6 +930,7 @@ imports: - security/informers/externalversions/security/v1 - security/listers/security/v1 - template/clientset/versioned + - template/clientset/versioned/fake - template/clientset/versioned/scheme - template/clientset/versioned/typed/template/v1 - template/clientset/versioned/typed/template/v1/fake @@ -956,7 +957,7 @@ imports: - signal - strslice - name: github.com/openshift/library-go - version: 4bdffb3d6ca083fad9ee9f51d3273d328d349dbc + version: d366b6f2e76695de0e702cb9d06767bd517753b0 subpackages: - pkg/config/client - pkg/config/leaderelection @@ -966,9 +967,10 @@ imports: - pkg/operator/resource/resourceapply - pkg/operator/resource/resourcecread - pkg/operator/resource/resourcemerge + - pkg/operator/v1alpha1helpers - pkg/serviceability - name: github.com/openshift/service-serving-cert-signer - version: 10d530a76d1e98ae342df2fa5a3cbefd5dc3f241 + version: 9337a18300a63e369f34d411b2080b4bd877e7a9 subpackages: - pkg/controller/servingcert - pkg/controller/servingcert/cryptoextensions @@ -1838,7 +1840,7 @@ imports: - pkg/util/proto/testing - pkg/util/proto/validation - name: k8s.io/kubernetes - version: cbf5b4279a751d7d4dc876149e8b2a4c3bb732c3 + version: 18a70828259b9ddc1c3805301e0c14c21028f46d repo: https://github.com/openshift/kubernetes.git subpackages: - cmd/controller-manager/app diff --git a/pkg/network/apis/network/types.go b/pkg/network/apis/network/types.go index 882e9f372da8..ec608fc8e3ba 100644 --- a/pkg/network/apis/network/types.go +++ b/pkg/network/apis/network/types.go @@ -51,7 +51,8 @@ type HostSubnet struct { HostIP string Subnet string - EgressIPs []string + EgressIPs []string + EgressCIDRs []string } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/network/apis/network/v1/zz_generated.conversion.go b/pkg/network/apis/network/v1/zz_generated.conversion.go index 618bef0499a5..58057a3ec515 100644 --- a/pkg/network/apis/network/v1/zz_generated.conversion.go +++ b/pkg/network/apis/network/v1/zz_generated.conversion.go @@ -264,6 +264,7 @@ func autoConvert_v1_HostSubnet_To_network_HostSubnet(in *v1.HostSubnet, out *net out.HostIP = in.HostIP out.Subnet = in.Subnet out.EgressIPs = *(*[]string)(unsafe.Pointer(&in.EgressIPs)) + out.EgressCIDRs = *(*[]string)(unsafe.Pointer(&in.EgressCIDRs)) return nil } @@ -278,6 +279,7 @@ func autoConvert_network_HostSubnet_To_v1_HostSubnet(in *network.HostSubnet, out out.HostIP = in.HostIP out.Subnet = in.Subnet out.EgressIPs = *(*[]string)(unsafe.Pointer(&in.EgressIPs)) + out.EgressCIDRs = *(*[]string)(unsafe.Pointer(&in.EgressCIDRs)) return nil } diff --git a/pkg/network/apis/network/validation/validation.go b/pkg/network/apis/network/validation/validation.go index 17715f03feb4..23175338867a 100644 --- a/pkg/network/apis/network/validation/validation.go +++ b/pkg/network/apis/network/validation/validation.go @@ -174,6 +174,12 @@ func ValidateHostSubnet(hs *networkapi.HostSubnet) field.ErrorList { } } + for i, egressCIDR := range hs.EgressCIDRs { + if _, err := validateCIDRv4(egressCIDR); err != nil { + allErrs = append(allErrs, field.Invalid(field.NewPath("egressCIDRs").Index(i), egressCIDR, err.Error())) + } + } + return allErrs } diff --git a/pkg/network/apis/network/validation/validation_test.go b/pkg/network/apis/network/validation/validation_test.go index 20e0e277420f..b5be62cb1eae 100644 --- a/pkg/network/apis/network/validation/validation_test.go +++ b/pkg/network/apis/network/validation/validation_test.go @@ -405,6 +405,39 @@ func TestValidateHostSubnet(t *testing.T) { }, expectedErrors: 2, }, + { + name: "Good one with EgressCIDRs", + hs: &networkapi.HostSubnet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "abc.def.com", + }, + Host: "abc.def.com", + HostIP: "10.20.30.40", + Subnet: "8.8.8.0/24", + EgressCIDRs: []string{ + "192.168.1.99/32", + "192.168.2.0/24", + }, + }, + expectedErrors: 0, + }, + { + name: "Malformed EgressCIDRs", + hs: &networkapi.HostSubnet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "abc.def.com", + }, + Host: "abc.def.com", + HostIP: "10.20.30.40", + Subnet: "8.8.8.0/24", + EgressCIDRs: []string{ + "192.168.1.99", + "bob/32", + "1234::5678/64", + }, + }, + expectedErrors: 3, + }, { name: "IPv6 subnet", hs: &networkapi.HostSubnet{ diff --git a/pkg/network/apis/network/zz_generated.deepcopy.go b/pkg/network/apis/network/zz_generated.deepcopy.go index a02316351b14..d3dc738bff74 100644 --- a/pkg/network/apis/network/zz_generated.deepcopy.go +++ b/pkg/network/apis/network/zz_generated.deepcopy.go @@ -212,6 +212,11 @@ func (in *HostSubnet) DeepCopyInto(out *HostSubnet) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.EgressCIDRs != nil { + in, out := &in.EgressCIDRs, &out.EgressCIDRs + *out = make([]string, len(*in)) + copy(*out, *in) + } return } diff --git a/pkg/network/common/egressip.go b/pkg/network/common/egressip.go index 05f29adcb46c..edea2db2c5fd 100644 --- a/pkg/network/common/egressip.go +++ b/pkg/network/common/egressip.go @@ -18,10 +18,15 @@ import ( ) type nodeEgress struct { - nodeIP string - sdnIP string - requestedIPs sets.String - offline bool + nodeName string + nodeIP string + sdnIP string + + requestedIPs sets.String + requestedCIDRs sets.String + parsedCIDRs map[string]*net.IPNet + + offline bool } type namespaceEgress struct { @@ -32,7 +37,8 @@ type namespaceEgress struct { } type egressIPInfo struct { - ip string + ip string + parsed net.IP nodes []*nodeEgress namespaces []*namespaceEgress @@ -48,6 +54,8 @@ type EgressIPWatcher interface { SetNamespaceEgressNormal(vnid uint32) SetNamespaceEgressDropped(vnid uint32) SetNamespaceEgressViaEgressIP(vnid uint32, egressIP, nodeIP string) + + UpdateEgressCIDRs() } type EgressIPTracker struct { @@ -58,9 +66,11 @@ type EgressIPTracker struct { nodesByNodeIP map[string]*nodeEgress namespacesByVNID map[uint32]*namespaceEgress egressIPs map[string]*egressIPInfo + nodesWithCIDRs int changedEgressIPs map[*egressIPInfo]bool changedNamespaces map[*namespaceEgress]bool + updateEgressCIDRs bool } func NewEgressIPTracker(watcher EgressIPWatcher) *EgressIPTracker { @@ -84,7 +94,7 @@ func (eit *EgressIPTracker) Start(hostSubnetInformer networkinformers.HostSubnet func (eit *EgressIPTracker) ensureEgressIPInfo(egressIP string) *egressIPInfo { eg := eit.egressIPs[egressIP] if eg == nil { - eg = &egressIPInfo{ip: egressIP} + eg = &egressIPInfo{ip: egressIP, parsed: net.ParseIP(egressIP)} eit.egressIPs[egressIP] = eg } return eg @@ -177,22 +187,40 @@ func (eit *EgressIPTracker) UpdateHostSubnetEgress(hs *networkapi.HostSubnet) { node := eit.nodesByNodeIP[hs.HostIP] if node == nil { - if len(hs.EgressIPs) == 0 { + if len(hs.EgressIPs) == 0 && len(hs.EgressCIDRs) == 0 { return } node = &nodeEgress{ + nodeName: hs.Host, nodeIP: hs.HostIP, sdnIP: sdnIP, requestedIPs: sets.NewString(), } eit.nodesByNodeIP[hs.HostIP] = node - } else if len(hs.EgressIPs) == 0 { + } else if len(hs.EgressIPs) == 0 && len(hs.EgressCIDRs) == 0 { delete(eit.nodesByNodeIP, hs.HostIP) } - oldRequestedIPs := node.requestedIPs - node.requestedIPs = sets.NewString(hs.EgressIPs...) + + // Process EgressCIDRs + newRequestedCIDRs := sets.NewString(hs.EgressCIDRs...) + if !node.requestedCIDRs.Equal(newRequestedCIDRs) { + if len(hs.EgressCIDRs) == 0 { + eit.nodesWithCIDRs-- + } else if node.requestedCIDRs.Len() == 0 { + eit.nodesWithCIDRs++ + } + node.requestedCIDRs = newRequestedCIDRs + node.parsedCIDRs = make(map[string]*net.IPNet) + for _, cidr := range hs.EgressCIDRs { + _, parsed, _ := net.ParseCIDR(cidr) + node.parsedCIDRs[cidr] = parsed + } + eit.updateEgressCIDRs = true + } // Process new and removed EgressIPs + oldRequestedIPs := node.requestedIPs + node.requestedIPs = sets.NewString(hs.EgressIPs...) for _, ip := range node.requestedIPs.Difference(oldRequestedIPs).UnsortedList() { eit.addNodeEgressIP(node, ip) } @@ -301,6 +329,13 @@ func (eit *EgressIPTracker) syncEgressIPs() { for ns := range changedNamespaces { eit.syncEgressNamespaceState(ns) } + + if eit.updateEgressCIDRs { + eit.updateEgressCIDRs = false + if eit.nodesWithCIDRs > 0 { + eit.watcher.UpdateEgressCIDRs() + } + } } func (eit *EgressIPTracker) syncEgressNodeState(eg *egressIPInfo, active bool) { @@ -313,6 +348,10 @@ func (eit *EgressIPTracker) syncEgressNodeState(eg *egressIPInfo, active bool) { eit.watcher.ReleaseEgressIP(eg.ip, eg.assignedNodeIP) eg.assignedNodeIP = "" } + + if eg.assignedNodeIP == "" { + eit.updateEgressCIDRs = true + } } func (eit *EgressIPTracker) syncEgressNamespaceState(ns *namespaceEgress) { @@ -402,3 +441,103 @@ func (eit *EgressIPTracker) Ping(ip string, timeout time.Duration) bool { return true } } + +// Finds the best node to allocate the egress IP to, given the existing allocation. The +// boolean return value indicates whether multiple nodes could host the IP. +func (eit *EgressIPTracker) findEgressIPAllocation(ip net.IP, allocation map[string][]string) (string, bool) { + bestNode := "" + otherNodes := false + + for _, node := range eit.nodesByNodeIP { + egressIPs, exists := allocation[node.nodeName] + if !exists { + continue + } + for _, parsed := range node.parsedCIDRs { + if parsed.Contains(ip) { + if bestNode != "" { + otherNodes = true + if len(allocation[bestNode]) < len(egressIPs) { + break + } + } + bestNode = node.nodeName + break + } + } + } + + return bestNode, otherNodes +} + +// ReallocateEgressIPs returns a map from Node name to array-of-Egress-IP. Unchanged nodes are not included. +func (eit *EgressIPTracker) ReallocateEgressIPs() map[string][]string { + eit.Lock() + defer eit.Unlock() + + allocation := make(map[string][]string) + changed := make(map[string]bool) + alreadyAllocated := make(map[string]bool) + for _, node := range eit.nodesByNodeIP { + if len(node.parsedCIDRs) > 0 { + allocation[node.nodeName] = make([]string, 0, node.requestedIPs.Len()) + } + } + // For each active egress IP, if it still fits within some egress CIDR on its node, + // add it to that node's allocation. (Otherwise add the node to the "changed" map, + // since we'll be removing this egress IP from it.) + for egressIP, eip := range eit.egressIPs { + if eip.assignedNodeIP == "" { + continue + } + node := eip.nodes[0] + found := false + for _, parsed := range node.parsedCIDRs { + if parsed.Contains(eip.parsed) { + found = true + break + } + } + if found { + allocation[node.nodeName] = append(allocation[node.nodeName], egressIP) + } else { + changed[node.nodeName] = true + } + // (We set alreadyAllocated even if the egressIP will be removed from + // its current node; we can't assign it to a new node until the next + // reallocation.) + alreadyAllocated[egressIP] = true + } + + // Allocate pending egress IPs that can only go to a single node + for egressIP, eip := range eit.egressIPs { + if alreadyAllocated[egressIP] { + continue + } + nodeName, otherNodes := eit.findEgressIPAllocation(eip.parsed, allocation) + if nodeName != "" && !otherNodes { + allocation[nodeName] = append(allocation[nodeName], egressIP) + changed[nodeName] = true + alreadyAllocated[egressIP] = true + } + } + // Allocate any other pending egress IPs that we can + for egressIP, eip := range eit.egressIPs { + if alreadyAllocated[egressIP] { + continue + } + nodeName, _ := eit.findEgressIPAllocation(eip.parsed, allocation) + if nodeName != "" { + allocation[nodeName] = append(allocation[nodeName], egressIP) + changed[nodeName] = true + } + } + + // Remove unchanged nodes from the return value + for _, node := range eit.nodesByNodeIP { + if !changed[node.nodeName] { + delete(allocation, node.nodeName) + } + } + return allocation +} diff --git a/pkg/network/common/egressip_test.go b/pkg/network/common/egressip_test.go index bdb9db0dbcd6..158ac201074e 100644 --- a/pkg/network/common/egressip_test.go +++ b/pkg/network/common/egressip_test.go @@ -31,6 +31,10 @@ func (w *testEIPWatcher) SetNamespaceEgressViaEgressIP(vnid uint32, egressIP, no w.changes = append(w.changes, fmt.Sprintf("namespace %d via %s on %s", int(vnid), egressIP, nodeIP)) } +func (w *testEIPWatcher) UpdateEgressCIDRs() { + w.changes = append(w.changes, "update egress CIDRs") +} + func (w *testEIPWatcher) assertChanges(expected ...string) error { changed := w.changes w.changes = []string{} @@ -742,3 +746,242 @@ func TestOfflineEgressIPs(t *testing.T) { t.Fatalf("%v", err) } } + +func updateAllocations(eit *EgressIPTracker, allocation map[string][]string) { + for nodeName, egressIPs := range allocation { + for _, node := range eit.nodesByNodeIP { + if node.nodeName == nodeName { + eit.UpdateHostSubnetEgress(&networkapi.HostSubnet{ + Host: nodeName, + HostIP: node.nodeIP, + EgressIPs: egressIPs, + EgressCIDRs: node.requestedCIDRs.List(), + }) + break + } + } + } +} + +func TestEgressCIDRAllocation(t *testing.T) { + eit, w := setupEgressIPTracker(t) + + eit.UpdateHostSubnetEgress(&networkapi.HostSubnet{ + Host: "node-3", + HostIP: "172.17.0.3", + EgressIPs: []string{}, + EgressCIDRs: []string{"172.17.0.100/32", "172.17.0.101/32", "172.17.0.102/32", "172.17.0.103/32", "172.17.1.0/24"}, + }) + eit.UpdateHostSubnetEgress(&networkapi.HostSubnet{ + Host: "node-4", + HostIP: "172.17.0.4", + EgressIPs: []string{}, + EgressCIDRs: []string{"172.17.0.0/24"}, + }) + eit.UpdateHostSubnetEgress(&networkapi.HostSubnet{ + Host: "node-5", + HostIP: "172.17.0.5", + EgressIPs: []string{}, + EgressCIDRs: []string{}, + }) + err := w.assertChanges( + "update egress CIDRs", + "update egress CIDRs", + // no "update egress CIDRs" for node-5 since it has no EgressCIDRs + ) + if err != nil { + t.Fatalf("%v", err) + } + + // Either of these could be assigned to either node, but they should be balanced + eit.UpdateNetNamespaceEgress(&networkapi.NetNamespace{ + NetName: "ns-42", + NetID: 42, + EgressIPs: []string{"172.17.0.100"}, + }) + eit.UpdateNetNamespaceEgress(&networkapi.NetNamespace{ + NetName: "ns-43", + NetID: 43, + EgressIPs: []string{"172.17.0.101"}, + }) + err = w.assertChanges( + "namespace 42 dropped", + "update egress CIDRs", + "namespace 43 dropped", + "update egress CIDRs", + ) + if err != nil { + t.Fatalf("%v", err) + } + + allocation := eit.ReallocateEgressIPs() + node3ips := allocation["node-3"] + node4ips := allocation["node-4"] + if len(node3ips) != 1 || len(node4ips) != 1 { + t.Fatalf("Bad IP allocation: %#v", allocation) + } + var n42, n43 string + if node3ips[0] == "172.17.0.100" && node4ips[0] == "172.17.0.101" { + n42 = "172.17.0.3" + n43 = "172.17.0.4" + } else if node3ips[0] == "172.17.0.101" && node4ips[0] == "172.17.0.100" { + n42 = "172.17.0.4" + n43 = "172.17.0.3" + } else { + t.Fatalf("Bad IP allocation: %#v", allocation) + } + + updateAllocations(eit, allocation) + err = w.assertChanges( + fmt.Sprintf("claim 172.17.0.100 on %s for namespace 42", n42), + fmt.Sprintf("namespace 42 via 172.17.0.100 on %s", n42), + fmt.Sprintf("claim 172.17.0.101 on %s for namespace 43", n43), + fmt.Sprintf("namespace 43 via 172.17.0.101 on %s", n43), + ) + if err != nil { + t.Fatalf("%v", err) + } + + // First can only be assigned to node3. Second *could* be assigned to either, but + // must get assigned to node4 for balance + eit.UpdateNetNamespaceEgress(&networkapi.NetNamespace{ + NetName: "ns-44", + NetID: 44, + EgressIPs: []string{"172.17.1.1"}, + }) + eit.UpdateNetNamespaceEgress(&networkapi.NetNamespace{ + NetName: "ns-45", + NetID: 45, + EgressIPs: []string{"172.17.0.102"}, + }) + err = w.assertChanges( + "namespace 44 dropped", + "update egress CIDRs", + "namespace 45 dropped", + "update egress CIDRs", + ) + if err != nil { + t.Fatalf("%v", err) + } + + allocation = eit.ReallocateEgressIPs() + updateAllocations(eit, allocation) + err = w.assertChanges( + "claim 172.17.1.1 on 172.17.0.3 for namespace 44", + "namespace 44 via 172.17.1.1 on 172.17.0.3", + "claim 172.17.0.102 on 172.17.0.4 for namespace 45", + "namespace 45 via 172.17.0.102 on 172.17.0.4", + ) + if err != nil { + t.Fatalf("%v", err) + } + + // Manually assigning egress IPs to the node with no EgressCIDRs should have no + // effect on automatic assignments (though it will result in a spurious "update + // egress CIDRs" notification). + eit.UpdateHostSubnetEgress(&networkapi.HostSubnet{ + Host: "node-5", + HostIP: "172.17.0.5", + EgressIPs: []string{"172.17.2.100"}, + }) + eit.UpdateNetNamespaceEgress(&networkapi.NetNamespace{ + NetName: "ns-50", + NetID: 50, + EgressIPs: []string{"172.17.2.100"}, + }) + err = w.assertChanges( + "claim 172.17.2.100 on 172.17.0.5 for namespace 50", + "namespace 50 via 172.17.2.100 on 172.17.0.5", + "update egress CIDRs", + ) + if err != nil { + t.Fatalf("%v", err) + } + allocation = eit.ReallocateEgressIPs() + if len(allocation) != 0 { + t.Fatalf("Unexpected allocation: %#v", allocation) + } + updateAllocations(eit, allocation) + err = w.assertNoChanges() + if err != nil { + t.Fatalf("%v", err) + } + + // First two can only be assigned to node4. Last must get assigned to node3 for balance + eit.UpdateNetNamespaceEgress(&networkapi.NetNamespace{ + NetName: "ns-46", + NetID: 46, + EgressIPs: []string{"172.17.0.200"}, + }) + eit.UpdateNetNamespaceEgress(&networkapi.NetNamespace{ + NetName: "ns-47", + NetID: 47, + EgressIPs: []string{"172.17.0.201"}, + }) + eit.UpdateNetNamespaceEgress(&networkapi.NetNamespace{ + NetName: "ns-48", + NetID: 48, + EgressIPs: []string{"172.17.0.103"}, + }) + err = w.assertChanges( + "namespace 46 dropped", + "update egress CIDRs", + "namespace 47 dropped", + "update egress CIDRs", + "namespace 48 dropped", + "update egress CIDRs", + ) + if err != nil { + t.Fatalf("%v", err) + } + + allocation = eit.ReallocateEgressIPs() + updateAllocations(eit, allocation) + err = w.assertChanges( + "claim 172.17.0.200 on 172.17.0.4 for namespace 46", + "namespace 46 via 172.17.0.200 on 172.17.0.4", + "claim 172.17.0.201 on 172.17.0.4 for namespace 47", + "namespace 47 via 172.17.0.201 on 172.17.0.4", + "claim 172.17.0.103 on 172.17.0.3 for namespace 48", + "namespace 48 via 172.17.0.103 on 172.17.0.3", + ) + if err != nil { + t.Fatalf("%v", err) + } + + // Dropping an Egress CIDR will drop the Egress IP(s) that came from that CIDR. + // If we then reallocate, the dropped Egress IP(s) might be allocated to new nodes. + eit.UpdateHostSubnetEgress(&networkapi.HostSubnet{ + Host: "node-3", + HostIP: "172.17.0.3", + EgressIPs: allocation["node-3"], + EgressCIDRs: []string{"172.17.0.100/32", "172.17.0.101/32", "172.17.0.102/32", "172.17.1.0/24"}, // removed "172.17.0.103/32" + }) + err = w.assertChanges( + "update egress CIDRs", + ) + if err != nil { + t.Fatalf("%v", err) + } + allocation = eit.ReallocateEgressIPs() + updateAllocations(eit, allocation) + err = w.assertChanges( + "release 172.17.0.103 on 172.17.0.3", + "namespace 48 dropped", + // Now that the egress IP has been unassigned, the tracker sees that it + // could be assigned to a new node. + "update egress CIDRs", + ) + if err != nil { + t.Fatalf("%v", err) + } + allocation = eit.ReallocateEgressIPs() + updateAllocations(eit, allocation) + err = w.assertChanges( + "claim 172.17.0.103 on 172.17.0.4 for namespace 48", + "namespace 48 via 172.17.0.103 on 172.17.0.4", + ) + if err != nil { + t.Fatalf("%v", err) + } +} diff --git a/pkg/network/master/egressip.go b/pkg/network/master/egressip.go new file mode 100644 index 000000000000..7f82853e1e2b --- /dev/null +++ b/pkg/network/master/egressip.go @@ -0,0 +1,110 @@ +package master + +import ( + "fmt" + "sync" + "time" + + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + utilwait "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/util/retry" + + "github.com/openshift/origin/pkg/network/common" + networkinformers "github.com/openshift/origin/pkg/network/generated/informers/internalversion/network/internalversion" + networkclient "github.com/openshift/origin/pkg/network/generated/internalclientset" +) + +type egressIPManager struct { + sync.Mutex + + tracker *common.EgressIPTracker + networkClient networkclient.Interface + hostSubnetInformer networkinformers.HostSubnetInformer + + updatePending bool + updatedAgain bool +} + +func newEgressIPManager() *egressIPManager { + eim := &egressIPManager{} + eim.tracker = common.NewEgressIPTracker(eim) + return eim +} + +func (eim *egressIPManager) Start(networkClient networkclient.Interface, hostSubnetInformer networkinformers.HostSubnetInformer, netNamespaceInformer networkinformers.NetNamespaceInformer) { + eim.networkClient = networkClient + eim.hostSubnetInformer = hostSubnetInformer + eim.tracker.Start(hostSubnetInformer, netNamespaceInformer) +} + +func (eim *egressIPManager) UpdateEgressCIDRs() { + eim.Lock() + defer eim.Unlock() + + // Coalesce multiple "UpdateEgressCIDRs" notifications into one by queueing + // the update to happen a little bit later in a goroutine, and postponing that + // update any time we get another "UpdateEgressCIDRs". + + if eim.updatePending { + eim.updatedAgain = true + } else { + eim.updatePending = true + go utilwait.PollInfinite(time.Second, eim.maybeDoUpdateEgressCIDRs) + } +} + +func (eim *egressIPManager) maybeDoUpdateEgressCIDRs() (bool, error) { + eim.Lock() + defer eim.Unlock() + + if eim.updatedAgain { + eim.updatedAgain = false + return false, nil + } + eim.updatePending = false + + // At this point it has been at least 1 second since the last "UpdateEgressCIDRs" + // notification, so things are stable. + // + // ReallocateEgressIPs() will figure out what HostSubnets either can have new + // egress IPs added to them, or need to have egress IPs removed from them, and + // returns a map from node name to the new EgressIPs value, for each changed + // HostSubnet. + // + // If a HostSubnet's EgressCIDRs changes while we are processing the reallocation, + // we won't process that until this reallocation is complete. + + allocation := eim.tracker.ReallocateEgressIPs() + for nodeName, egressIPs := range allocation { + resultErr := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + hs, err := eim.hostSubnetInformer.Lister().Get(nodeName) + if err != nil { + return err + } + + hs.EgressIPs = egressIPs + _, err = eim.networkClient.Network().HostSubnets().Update(hs) + return err + }) + if resultErr != nil { + utilruntime.HandleError(fmt.Errorf("Could not update HostSubnet EgressIPs: %v", resultErr)) + } + } + + return true, nil +} + +func (eim *egressIPManager) ClaimEgressIP(vnid uint32, egressIP, nodeIP string) { +} + +func (eim *egressIPManager) ReleaseEgressIP(egressIP, nodeIP string) { +} + +func (eim *egressIPManager) SetNamespaceEgressNormal(vnid uint32) { +} + +func (eim *egressIPManager) SetNamespaceEgressDropped(vnid uint32) { +} + +func (eim *egressIPManager) SetNamespaceEgressViaEgressIP(vnid uint32, egressIP, nodeIP string) { +} diff --git a/pkg/network/master/master.go b/pkg/network/master/master.go index 6002edc92081..a5e723aa6d44 100644 --- a/pkg/network/master/master.go +++ b/pkg/network/master/master.go @@ -193,6 +193,9 @@ func (master *OsdnMaster) startSubSystems(pluginName string) { glog.Fatalf("failed to start VNID master: %v", err) } } + + eim := newEgressIPManager() + eim.Start(master.networkClient, master.hostSubnetInformer, master.netNamespaceInformer) } func (master *OsdnMaster) checkClusterNetworkAgainstLocalNetworks() error { diff --git a/pkg/network/node/egressip.go b/pkg/network/node/egressip.go index 48916751d02b..b09d0ededf73 100644 --- a/pkg/network/node/egressip.go +++ b/pkg/network/node/egressip.go @@ -105,6 +105,9 @@ func (eip *egressIPWatcher) ReleaseEgressIP(egressIP, nodeIP string) { } } +func (eip *egressIPWatcher) UpdateEgressCIDRs() { +} + func (eip *egressIPWatcher) SetNamespaceEgressNormal(vnid uint32) { if err := eip.oc.SetNamespaceEgressNormal(vnid); err != nil { utilruntime.HandleError(fmt.Errorf("Error updating Namespace egress rules for VNID %d: %v", vnid, err)) diff --git a/pkg/openapi/zz_generated.openapi.go b/pkg/openapi/zz_generated.openapi.go index f56dfc230c0f..1dcef1c2c90d 100644 --- a/pkg/openapi/zz_generated.openapi.go +++ b/pkg/openapi/zz_generated.openapi.go @@ -8641,7 +8641,21 @@ func schema_openshift_api_network_v1_HostSubnet(ref common.ReferenceCallback) co }, "egressIPs": { SchemaProps: spec.SchemaProps{ - Description: "EgressIPs is the list of automatic egress IP addresses currently hosted by this node", + Description: "EgressIPs is the list of automatic egress IP addresses currently hosted by this node. If EgressCIDRs is empty, this can be set by hand; if EgressCIDRs is set then the master will overwrite the value here with its own allocation of egress IPs.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "egressCIDRs": { + SchemaProps: spec.SchemaProps{ + Description: "EgressCIDRs is the list of CIDR ranges available for automatically assigning egress IPs to this node from. If this field is set then EgressIPs should be treated as read-only.", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ diff --git a/vendor/github.com/openshift/api/network/v1/generated.pb.go b/vendor/github.com/openshift/api/network/v1/generated.pb.go index 536264a62dce..339639303808 100644 --- a/vendor/github.com/openshift/api/network/v1/generated.pb.go +++ b/vendor/github.com/openshift/api/network/v1/generated.pb.go @@ -430,6 +430,21 @@ func (m *HostSubnet) MarshalTo(dAtA []byte) (int, error) { i += copy(dAtA[i:], s) } } + if len(m.EgressCIDRs) > 0 { + for _, s := range m.EgressCIDRs { + dAtA[i] = 0x32 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } return i, nil } @@ -701,6 +716,12 @@ func (m *HostSubnet) Size() (n int) { n += 1 + l + sovGenerated(uint64(l)) } } + if len(m.EgressCIDRs) > 0 { + for _, s := range m.EgressCIDRs { + l = len(s) + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -863,6 +884,7 @@ func (this *HostSubnet) String() string { `HostIP:` + fmt.Sprintf("%v", this.HostIP) + `,`, `Subnet:` + fmt.Sprintf("%v", this.Subnet) + `,`, `EgressIPs:` + fmt.Sprintf("%v", this.EgressIPs) + `,`, + `EgressCIDRs:` + fmt.Sprintf("%v", this.EgressCIDRs) + `,`, `}`, }, "") return s @@ -2030,6 +2052,35 @@ func (m *HostSubnet) Unmarshal(dAtA []byte) error { } m.EgressIPs = append(m.EgressIPs, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EgressCIDRs", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.EgressCIDRs = append(m.EgressCIDRs, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -2540,63 +2591,64 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 915 bytes of a gzipped FileDescriptorProto + // 935 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x4f, 0x6f, 0xe3, 0x44, - 0x14, 0x8f, 0xd3, 0xa4, 0xbb, 0x99, 0xb6, 0x69, 0x35, 0x8b, 0x58, 0xab, 0x48, 0x6e, 0xe4, 0x95, + 0x14, 0x8f, 0xd3, 0xa4, 0xbb, 0x99, 0xb4, 0x69, 0x35, 0x8b, 0x58, 0xab, 0x48, 0x4e, 0xe4, 0x95, 0x50, 0xd0, 0x0a, 0x9b, 0xb4, 0x08, 0xf5, 0x80, 0x40, 0xf2, 0xb6, 0xd2, 0x46, 0x5a, 0x42, 0x34, - 0xa9, 0xd0, 0x0a, 0x01, 0xc2, 0x75, 0xde, 0x3a, 0xa6, 0x89, 0x6d, 0x79, 0xc6, 0x41, 0x11, 0xe2, - 0xcf, 0x17, 0x40, 0xe2, 0xc3, 0xf0, 0x11, 0x38, 0xf4, 0xc0, 0x61, 0x0f, 0x08, 0xf6, 0x54, 0xd1, - 0x70, 0xe6, 0x0b, 0x70, 0x42, 0x33, 0x1e, 0x27, 0x76, 0xea, 0xa8, 0x51, 0x11, 0x39, 0x25, 0x9e, - 0xdf, 0x7b, 0xbf, 0xf7, 0xe7, 0xf7, 0xde, 0xd8, 0xe8, 0xc8, 0xf5, 0xd8, 0x20, 0x3e, 0x37, 0x9c, - 0x60, 0x64, 0x06, 0x21, 0xf8, 0x74, 0xe0, 0xbd, 0x60, 0xa6, 0x1d, 0x7a, 0xa6, 0x0f, 0xec, 0xeb, - 0x20, 0xba, 0x30, 0xc7, 0x2d, 0xd3, 0x05, 0x1f, 0x22, 0x9b, 0x41, 0xdf, 0x08, 0xa3, 0x80, 0x05, - 0xf8, 0xd1, 0xdc, 0xc9, 0x98, 0x39, 0x19, 0x76, 0xe8, 0x19, 0xd2, 0xc9, 0x18, 0xb7, 0xf6, 0xdf, - 0xce, 0x30, 0xbb, 0x81, 0x1b, 0x98, 0xc2, 0xf7, 0x3c, 0x7e, 0x21, 0x9e, 0xc4, 0x83, 0xf8, 0x97, - 0x70, 0xee, 0xbf, 0x7b, 0x71, 0x4c, 0x0d, 0x2f, 0xe0, 0xa1, 0x47, 0xb6, 0x33, 0xf0, 0x7c, 0x88, - 0x26, 0x66, 0x78, 0xe1, 0xf2, 0x03, 0x6a, 0x8e, 0x80, 0xd9, 0x05, 0x99, 0xec, 0xbf, 0xb7, 0xcc, - 0x2b, 0x8a, 0x7d, 0xe6, 0x8d, 0xc0, 0xa4, 0xce, 0x00, 0x46, 0xf6, 0x0d, 0xbf, 0xa3, 0x65, 0x7e, - 0x31, 0xf3, 0x86, 0xa6, 0xe7, 0x33, 0xca, 0xa2, 0x45, 0x27, 0xfd, 0xb7, 0x0d, 0x54, 0x7f, 0x32, - 0x8c, 0x29, 0x83, 0xa8, 0x93, 0xd4, 0x89, 0xbf, 0x44, 0xf7, 0x79, 0x6a, 0x7d, 0x9b, 0xd9, 0xaa, - 0xd2, 0x50, 0x9a, 0x5b, 0x87, 0xef, 0x18, 0x09, 0xb5, 0x91, 0xa5, 0x36, 0xc2, 0x0b, 0x97, 0x1f, - 0x50, 0x83, 0x5b, 0x1b, 0xe3, 0x96, 0xf1, 0xf1, 0xf9, 0x57, 0xe0, 0xb0, 0x8f, 0x80, 0xd9, 0x16, - 0xbe, 0xbc, 0x3a, 0x28, 0x4d, 0xaf, 0x0e, 0xd0, 0xfc, 0x8c, 0xcc, 0x58, 0xf1, 0x5b, 0xe8, 0x9e, - 0x6c, 0xaa, 0x5a, 0x6e, 0x28, 0xcd, 0x9a, 0xb5, 0x2b, 0xcd, 0xef, 0xc9, 0x1c, 0x48, 0x8a, 0xe3, - 0x13, 0xb4, 0x37, 0x08, 0x28, 0xa3, 0xf1, 0xb9, 0x0f, 0x6c, 0x08, 0xbe, 0xcb, 0x06, 0xea, 0x46, - 0x43, 0x69, 0xee, 0x58, 0xaa, 0xf4, 0xd9, 0x7b, 0x1a, 0x50, 0xd6, 0x13, 0xf8, 0x33, 0x81, 0x93, - 0x1b, 0x1e, 0xf8, 0x03, 0x54, 0xa7, 0x10, 0x8d, 0x3d, 0x07, 0x64, 0x00, 0xb5, 0x22, 0xe2, 0xbe, - 0x2e, 0x39, 0xea, 0xbd, 0x1c, 0x4a, 0x16, 0xac, 0xf1, 0x21, 0x42, 0xe1, 0x30, 0x76, 0x3d, 0xbf, - 0x63, 0x8f, 0x40, 0xad, 0x0a, 0xdf, 0x59, 0x89, 0xdd, 0x19, 0x42, 0x32, 0x56, 0xf8, 0x1b, 0xb4, - 0xeb, 0xe4, 0x1a, 0x4b, 0xd5, 0xcd, 0xc6, 0x46, 0x73, 0xeb, 0xf0, 0xd8, 0x58, 0x61, 0xd4, 0x8c, - 0xbc, 0x28, 0xa7, 0x3e, 0x8b, 0x26, 0xd6, 0x43, 0x19, 0x72, 0x37, 0x0f, 0x52, 0xb2, 0x18, 0x49, - 0xff, 0x16, 0x3d, 0x28, 0x20, 0xc0, 0x0d, 0x54, 0x71, 0xbc, 0x7e, 0x24, 0x64, 0xad, 0x59, 0xdb, - 0x92, 0xae, 0xf2, 0xa4, 0x7d, 0x42, 0x88, 0x40, 0xd2, 0x7e, 0x67, 0xfb, 0x29, 0x34, 0xba, 0xb5, - 0xdf, 0xd9, 0x13, 0xfd, 0x57, 0x05, 0xe1, 0x7c, 0xfc, 0x67, 0x1e, 0x65, 0xf8, 0xb3, 0x1b, 0x93, - 0x65, 0xac, 0x36, 0x59, 0xdc, 0x5b, 0xcc, 0xd5, 0x9e, 0x4c, 0xe2, 0x7e, 0x7a, 0x92, 0x99, 0xaa, - 0xe7, 0xa8, 0xea, 0x31, 0x18, 0x51, 0xb5, 0x2c, 0xda, 0x7c, 0x74, 0x87, 0x36, 0x5b, 0x3b, 0x92, - 0xbf, 0xda, 0xe6, 0x4c, 0x24, 0x21, 0xd4, 0xff, 0x50, 0xd0, 0x83, 0x53, 0x37, 0x02, 0x4a, 0xa5, - 0x5d, 0x37, 0x18, 0x7a, 0xce, 0x64, 0x0d, 0x9b, 0xf2, 0x05, 0xaa, 0xd0, 0x10, 0x1c, 0x21, 0xc1, - 0xd6, 0xe1, 0xfb, 0x2b, 0x95, 0x54, 0x90, 0x69, 0x2f, 0x04, 0x67, 0x2e, 0x37, 0x7f, 0x22, 0x82, - 0x57, 0xff, 0x5d, 0x41, 0x0f, 0x0b, 0xec, 0xd7, 0xa0, 0xd6, 0xe7, 0x79, 0xb5, 0x8e, 0xef, 0x5a, - 0xda, 0x12, 0xc9, 0xbe, 0x2b, 0xac, 0xab, 0x0b, 0x10, 0xe1, 0x63, 0xb4, 0xcd, 0x47, 0xbd, 0x07, - 0x43, 0x70, 0x58, 0x90, 0x2e, 0xc3, 0x6b, 0x92, 0x66, 0x9b, 0x2f, 0x43, 0x8a, 0x91, 0x9c, 0x25, - 0xbf, 0xb7, 0xfa, 0x3e, 0x15, 0x77, 0xc0, 0xc2, 0xbd, 0x75, 0xd2, 0xe9, 0x89, 0x0b, 0x20, 0xc5, - 0xf5, 0x9f, 0x8b, 0x1b, 0x4b, 0xe2, 0x21, 0xe0, 0x0f, 0x51, 0x85, 0x4d, 0x42, 0x90, 0x81, 0x1f, - 0xa7, 0xb2, 0x9c, 0x4d, 0x42, 0xf8, 0xe7, 0xea, 0xe0, 0x8d, 0x25, 0x6e, 0x1c, 0x26, 0xc2, 0x11, - 0x3f, 0x47, 0x65, 0x16, 0xfc, 0xd7, 0x99, 0xe0, 0xbd, 0xb0, 0x90, 0x0c, 0x5e, 0x3e, 0x0b, 0x48, - 0x99, 0x05, 0xfa, 0xf7, 0x85, 0x59, 0xf3, 0x81, 0xc1, 0x7d, 0xb4, 0x09, 0x02, 0x52, 0x15, 0xa1, - 0xd8, 0x9d, 0x03, 0xf3, 0x62, 0xac, 0xba, 0x0c, 0xbc, 0x99, 0x18, 0x10, 0xc9, 0xad, 0xff, 0x58, - 0x46, 0x68, 0x7e, 0xc1, 0xac, 0x61, 0xc3, 0x1a, 0xa8, 0xc2, 0xaf, 0x2f, 0x29, 0xe8, 0x6c, 0x47, - 0x78, 0x0e, 0x44, 0x20, 0xf8, 0x4d, 0xb4, 0xc9, 0x7f, 0xdb, 0x5d, 0xf1, 0xe2, 0xa9, 0xcd, 0x53, - 0x7f, 0x2a, 0x4e, 0x89, 0x44, 0xb9, 0x5d, 0xf2, 0xd2, 0x91, 0x2f, 0x97, 0x99, 0x5d, 0x52, 0x0b, - 0x91, 0x28, 0x7e, 0x8c, 0x6a, 0x49, 0xb1, 0xed, 0x2e, 0x55, 0xab, 0x8d, 0x8d, 0x66, 0xcd, 0xda, - 0x99, 0x5e, 0x1d, 0xd4, 0x4e, 0xd3, 0x43, 0x32, 0xc7, 0xf5, 0x5f, 0x14, 0x54, 0xcf, 0x5c, 0xb8, - 0xff, 0xff, 0x5e, 0x9e, 0xe5, 0xf7, 0xd2, 0x5c, 0x49, 0xe5, 0x79, 0x86, 0x4b, 0xd6, 0xf1, 0x6f, - 0x05, 0x6d, 0x77, 0x80, 0xf1, 0xd5, 0xa0, 0xa1, 0xed, 0xc0, 0xda, 0x3e, 0x32, 0xfc, 0x82, 0x65, - 0x95, 0x89, 0x90, 0x14, 0xc7, 0x8f, 0x50, 0xd5, 0x07, 0xe6, 0xf5, 0xe5, 0x97, 0xc5, 0xac, 0x84, - 0x0e, 0xb0, 0xf6, 0x09, 0x49, 0xb0, 0xbc, 0x6c, 0x95, 0x5b, 0x64, 0xbb, 0x54, 0xd0, 0x5e, 0xb6, - 0xde, 0x35, 0x08, 0xf7, 0x49, 0x5e, 0xb8, 0xd6, 0x4a, 0xc2, 0x65, 0x73, 0x2c, 0x96, 0xce, 0x6a, - 0x5e, 0x5e, 0x6b, 0xa5, 0x97, 0xd7, 0x5a, 0xe9, 0xd5, 0xb5, 0x56, 0xfa, 0x61, 0xaa, 0x29, 0x97, - 0x53, 0x4d, 0x79, 0x39, 0xd5, 0x94, 0x57, 0x53, 0x4d, 0xf9, 0x73, 0xaa, 0x29, 0x3f, 0xfd, 0xa5, - 0x95, 0x3e, 0x2d, 0x8f, 0x5b, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x65, 0xc8, 0xb6, 0x0f, 0x78, - 0x0b, 0x00, 0x00, + 0xa9, 0xd0, 0x0a, 0x01, 0xc2, 0x75, 0xde, 0x3a, 0xa6, 0x89, 0x6d, 0x79, 0x26, 0x41, 0x11, 0xe2, + 0xcf, 0x47, 0xe0, 0xc3, 0xf0, 0x01, 0x38, 0x70, 0xe8, 0x81, 0xc3, 0x1e, 0x10, 0xf4, 0x14, 0xd1, + 0x70, 0xe6, 0x0b, 0x70, 0x42, 0x33, 0x1e, 0x27, 0x76, 0xeb, 0x40, 0x54, 0x44, 0x4e, 0xc9, 0xbc, + 0xdf, 0xfb, 0xff, 0x7b, 0x6f, 0xc6, 0xe8, 0xc8, 0xf5, 0xd8, 0x60, 0x7c, 0x6e, 0x38, 0xc1, 0xc8, + 0x0c, 0x42, 0xf0, 0xe9, 0xc0, 0x7b, 0xc1, 0x4c, 0x3b, 0xf4, 0x4c, 0x1f, 0xd8, 0x97, 0x41, 0x74, + 0x61, 0x4e, 0x5a, 0xa6, 0x0b, 0x3e, 0x44, 0x36, 0x83, 0xbe, 0x11, 0x46, 0x01, 0x0b, 0xf0, 0xa3, + 0xa5, 0x91, 0xb1, 0x30, 0x32, 0xec, 0xd0, 0x33, 0xa4, 0x91, 0x31, 0x69, 0x1d, 0xbc, 0x99, 0xf2, + 0xec, 0x06, 0x6e, 0x60, 0x0a, 0xdb, 0xf3, 0xf1, 0x0b, 0x71, 0x12, 0x07, 0xf1, 0x2f, 0xf6, 0x79, + 0xf0, 0xf6, 0xc5, 0x31, 0x35, 0xbc, 0x80, 0x87, 0x1e, 0xd9, 0xce, 0xc0, 0xf3, 0x21, 0x9a, 0x9a, + 0xe1, 0x85, 0xcb, 0x05, 0xd4, 0x1c, 0x01, 0xb3, 0x73, 0x32, 0x39, 0x78, 0x67, 0x95, 0x55, 0x34, + 0xf6, 0x99, 0x37, 0x02, 0x93, 0x3a, 0x03, 0x18, 0xd9, 0xb7, 0xec, 0x8e, 0x56, 0xd9, 0x8d, 0x99, + 0x37, 0x34, 0x3d, 0x9f, 0x51, 0x16, 0xdd, 0x34, 0xd2, 0x7f, 0xd9, 0x42, 0xb5, 0x27, 0xc3, 0x31, + 0x65, 0x10, 0x75, 0xe2, 0x3a, 0xf1, 0xe7, 0xe8, 0x3e, 0x4f, 0xad, 0x6f, 0x33, 0x5b, 0x55, 0x1a, + 0x4a, 0xb3, 0x7a, 0xf8, 0x96, 0x11, 0xbb, 0x36, 0xd2, 0xae, 0x8d, 0xf0, 0xc2, 0xe5, 0x02, 0x6a, + 0x70, 0x6d, 0x63, 0xd2, 0x32, 0x3e, 0x3c, 0xff, 0x02, 0x1c, 0xf6, 0x01, 0x30, 0xdb, 0xc2, 0x97, + 0xb3, 0x7a, 0x61, 0x3e, 0xab, 0xa3, 0xa5, 0x8c, 0x2c, 0xbc, 0xe2, 0x37, 0xd0, 0x3d, 0xd9, 0x54, + 0xb5, 0xd8, 0x50, 0x9a, 0x15, 0x6b, 0x4f, 0xaa, 0xdf, 0x93, 0x39, 0x90, 0x04, 0xc7, 0x27, 0x68, + 0x7f, 0x10, 0x50, 0x46, 0xc7, 0xe7, 0x3e, 0xb0, 0x21, 0xf8, 0x2e, 0x1b, 0xa8, 0x5b, 0x0d, 0xa5, + 0xb9, 0x6b, 0xa9, 0xd2, 0x66, 0xff, 0x69, 0x40, 0x59, 0x4f, 0xe0, 0xcf, 0x04, 0x4e, 0x6e, 0x59, + 0xe0, 0xf7, 0x50, 0x8d, 0x42, 0x34, 0xf1, 0x1c, 0x90, 0x01, 0xd4, 0x92, 0x88, 0xfb, 0xaa, 0xf4, + 0x51, 0xeb, 0x65, 0x50, 0x72, 0x43, 0x1b, 0x1f, 0x22, 0x14, 0x0e, 0xc7, 0xae, 0xe7, 0x77, 0xec, + 0x11, 0xa8, 0x65, 0x61, 0xbb, 0x28, 0xb1, 0xbb, 0x40, 0x48, 0x4a, 0x0b, 0x7f, 0x85, 0xf6, 0x9c, + 0x4c, 0x63, 0xa9, 0xba, 0xdd, 0xd8, 0x6a, 0x56, 0x0f, 0x8f, 0x8d, 0x35, 0x46, 0xcd, 0xc8, 0x92, + 0x72, 0xea, 0xb3, 0x68, 0x6a, 0x3d, 0x94, 0x21, 0xf7, 0xb2, 0x20, 0x25, 0x37, 0x23, 0xe9, 0x5f, + 0xa3, 0x07, 0x39, 0x0e, 0x70, 0x03, 0x95, 0x1c, 0xaf, 0x1f, 0x09, 0x5a, 0x2b, 0xd6, 0x8e, 0x74, + 0x57, 0x7a, 0xd2, 0x3e, 0x21, 0x44, 0x20, 0x49, 0xbf, 0xd3, 0xfd, 0x14, 0x1c, 0xfd, 0x6b, 0xbf, + 0xd3, 0x12, 0xfd, 0x67, 0x05, 0xe1, 0x6c, 0xfc, 0x67, 0x1e, 0x65, 0xf8, 0x93, 0x5b, 0x93, 0x65, + 0xac, 0x37, 0x59, 0xdc, 0x5a, 0xcc, 0xd5, 0xbe, 0x4c, 0xe2, 0x7e, 0x22, 0x49, 0x4d, 0xd5, 0x73, + 0x54, 0xf6, 0x18, 0x8c, 0xa8, 0x5a, 0x14, 0x6d, 0x3e, 0xba, 0x43, 0x9b, 0xad, 0x5d, 0xe9, 0xbf, + 0xdc, 0xe6, 0x9e, 0x48, 0xec, 0x50, 0xff, 0x4d, 0x41, 0x0f, 0x4e, 0xdd, 0x08, 0x28, 0x95, 0x7a, + 0xdd, 0x60, 0xe8, 0x39, 0xd3, 0x0d, 0x6c, 0xca, 0x67, 0xa8, 0x44, 0x43, 0x70, 0x04, 0x05, 0xd5, + 0xc3, 0x77, 0xd7, 0x2a, 0x29, 0x27, 0xd3, 0x5e, 0x08, 0xce, 0x92, 0x6e, 0x7e, 0x22, 0xc2, 0xaf, + 0xfe, 0xab, 0x82, 0x1e, 0xe6, 0xe8, 0x6f, 0x80, 0xad, 0x4f, 0xb3, 0x6c, 0x1d, 0xdf, 0xb5, 0xb4, + 0x15, 0x94, 0x7d, 0x93, 0x5b, 0x57, 0x17, 0x20, 0xc2, 0xc7, 0x68, 0x87, 0x8f, 0x7a, 0x0f, 0x86, + 0xe0, 0xb0, 0x20, 0x59, 0x86, 0x57, 0xa4, 0x9b, 0x1d, 0xbe, 0x0c, 0x09, 0x46, 0x32, 0x9a, 0xfc, + 0xde, 0xea, 0xfb, 0x54, 0xdc, 0x01, 0x37, 0xee, 0xad, 0x93, 0x4e, 0x4f, 0x5c, 0x00, 0x09, 0xae, + 0xff, 0x90, 0xdf, 0x58, 0x32, 0x1e, 0x02, 0x7e, 0x1f, 0x95, 0xd8, 0x34, 0x04, 0x19, 0xf8, 0x71, + 0x42, 0xcb, 0xd9, 0x34, 0x84, 0xbf, 0x66, 0xf5, 0xd7, 0x56, 0x98, 0x71, 0x98, 0x08, 0x43, 0xfc, + 0x1c, 0x15, 0x59, 0xf0, 0x5f, 0x67, 0x82, 0xf7, 0xc2, 0x42, 0x32, 0x78, 0xf1, 0x2c, 0x20, 0x45, + 0x16, 0xe8, 0xdf, 0xe6, 0x66, 0xcd, 0x07, 0x06, 0xf7, 0xd1, 0x36, 0x08, 0x48, 0x55, 0x04, 0x63, + 0x77, 0x0e, 0xcc, 0x8b, 0xb1, 0x6a, 0x32, 0xf0, 0x76, 0xac, 0x40, 0xa4, 0x6f, 0xfd, 0xc7, 0x22, + 0x42, 0xcb, 0x0b, 0x66, 0x03, 0x1b, 0xd6, 0x40, 0x25, 0x7e, 0x7d, 0x49, 0x42, 0x17, 0x3b, 0xc2, + 0x73, 0x20, 0x02, 0xc1, 0xaf, 0xa3, 0x6d, 0xfe, 0xdb, 0xee, 0x8a, 0x87, 0xa7, 0xb2, 0x4c, 0xfd, + 0xa9, 0x90, 0x12, 0x89, 0x72, 0xbd, 0xf8, 0xd1, 0x91, 0x8f, 0xcb, 0x42, 0x2f, 0xae, 0x85, 0x48, + 0x14, 0x3f, 0x46, 0x95, 0xb8, 0xd8, 0x76, 0x97, 0xaa, 0xe5, 0xc6, 0x56, 0xb3, 0x62, 0xed, 0xce, + 0x67, 0xf5, 0xca, 0x69, 0x22, 0x24, 0x4b, 0x1c, 0xb7, 0x50, 0x35, 0x3e, 0xf0, 0xb1, 0x8c, 0x5f, + 0x90, 0x8a, 0xb5, 0x37, 0x9f, 0xd5, 0xab, 0xa7, 0x4b, 0x31, 0x49, 0xeb, 0xe8, 0x3f, 0x29, 0xa8, + 0x96, 0xba, 0xa3, 0xff, 0xff, 0x55, 0x3e, 0xcb, 0xae, 0xb2, 0xb9, 0xd6, 0x60, 0x2c, 0x33, 0x5c, + 0xb1, 0xc1, 0x7f, 0x2a, 0x68, 0xa7, 0x03, 0x8c, 0x6f, 0x13, 0x0d, 0x6d, 0x07, 0x36, 0xf6, 0x5d, + 0xe2, 0xe7, 0xec, 0xb7, 0x4c, 0x84, 0x24, 0x38, 0x7e, 0x84, 0xca, 0x3e, 0x30, 0xaf, 0x2f, 0x3f, + 0x46, 0x16, 0x25, 0x74, 0x80, 0xb5, 0x4f, 0x48, 0x8c, 0x65, 0x99, 0x2e, 0xfd, 0x33, 0xd3, 0xfa, + 0xa5, 0x82, 0xf6, 0xd3, 0xf5, 0x6e, 0x80, 0xb8, 0x8f, 0xb2, 0xc4, 0xb5, 0xd6, 0x22, 0x2e, 0x9d, + 0x63, 0x3e, 0x75, 0x56, 0xf3, 0xf2, 0x5a, 0x2b, 0xbc, 0xbc, 0xd6, 0x0a, 0x57, 0xd7, 0x5a, 0xe1, + 0xbb, 0xb9, 0xa6, 0x5c, 0xce, 0x35, 0xe5, 0xe5, 0x5c, 0x53, 0xae, 0xe6, 0x9a, 0xf2, 0xfb, 0x5c, + 0x53, 0xbe, 0xff, 0x43, 0x2b, 0x7c, 0x5c, 0x9c, 0xb4, 0xfe, 0x0e, 0x00, 0x00, 0xff, 0xff, 0xf6, + 0xe6, 0x53, 0x02, 0xab, 0x0b, 0x00, 0x00, } diff --git a/vendor/github.com/openshift/api/network/v1/generated.proto b/vendor/github.com/openshift/api/network/v1/generated.proto index e6f2ff513740..6bbc3ffacf78 100644 --- a/vendor/github.com/openshift/api/network/v1/generated.proto +++ b/vendor/github.com/openshift/api/network/v1/generated.proto @@ -114,9 +114,17 @@ message HostSubnet { // Subnet is the CIDR range of the overlay network assigned to the node for its pods optional string subnet = 4; - // EgressIPs is the list of automatic egress IP addresses currently hosted by this node + // EgressIPs is the list of automatic egress IP addresses currently hosted by this node. + // If EgressCIDRs is empty, this can be set by hand; if EgressCIDRs is set then the + // master will overwrite the value here with its own allocation of egress IPs. // +optional repeated string egressIPs = 5; + + // EgressCIDRs is the list of CIDR ranges available for automatically assigning + // egress IPs to this node from. If this field is set then EgressIPs should be + // treated as read-only. + // +optional + repeated string egressCIDRs = 6; } // HostSubnetList is a collection of HostSubnets diff --git a/vendor/github.com/openshift/api/network/v1/types.go b/vendor/github.com/openshift/api/network/v1/types.go index 9735d5068f55..bf436e453100 100644 --- a/vendor/github.com/openshift/api/network/v1/types.go +++ b/vendor/github.com/openshift/api/network/v1/types.go @@ -69,9 +69,16 @@ type HostSubnet struct { // Subnet is the CIDR range of the overlay network assigned to the node for its pods Subnet string `json:"subnet" protobuf:"bytes,4,opt,name=subnet"` - // EgressIPs is the list of automatic egress IP addresses currently hosted by this node + // EgressIPs is the list of automatic egress IP addresses currently hosted by this node. + // If EgressCIDRs is empty, this can be set by hand; if EgressCIDRs is set then the + // master will overwrite the value here with its own allocation of egress IPs. // +optional EgressIPs []string `json:"egressIPs,omitempty" protobuf:"bytes,5,rep,name=egressIPs"` + // EgressCIDRs is the list of CIDR ranges available for automatically assigning + // egress IPs to this node from. If this field is set then EgressIPs should be + // treated as read-only. + // +optional + EgressCIDRs []string `json:"egressCIDRs,omitempty" protobuf:"bytes,6,rep,name=egressCIDRs"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/vendor/github.com/openshift/api/network/v1/types_swagger_doc_generated.go b/vendor/github.com/openshift/api/network/v1/types_swagger_doc_generated.go index 86c4c6df7610..fc2de92b0ece 100644 --- a/vendor/github.com/openshift/api/network/v1/types_swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/network/v1/types_swagger_doc_generated.go @@ -95,12 +95,13 @@ func (EgressNetworkPolicySpec) SwaggerDoc() map[string]string { } var map_HostSubnet = map[string]string{ - "": "HostSubnet describes the container subnet network on a node. The HostSubnet object must have the same name as the Node object it corresponds to.", - "metadata": "Standard object's metadata.", - "host": "Host is the name of the node. (This is the same as the object's name, but both fields must be set.)", - "hostIP": "HostIP is the IP address to be used as a VTEP by other nodes in the overlay network", - "subnet": "Subnet is the CIDR range of the overlay network assigned to the node for its pods", - "egressIPs": "EgressIPs is the list of automatic egress IP addresses currently hosted by this node", + "": "HostSubnet describes the container subnet network on a node. The HostSubnet object must have the same name as the Node object it corresponds to.", + "metadata": "Standard object's metadata.", + "host": "Host is the name of the node. (This is the same as the object's name, but both fields must be set.)", + "hostIP": "HostIP is the IP address to be used as a VTEP by other nodes in the overlay network", + "subnet": "Subnet is the CIDR range of the overlay network assigned to the node for its pods", + "egressIPs": "EgressIPs is the list of automatic egress IP addresses currently hosted by this node. If EgressCIDRs is empty, this can be set by hand; if EgressCIDRs is set then the master will overwrite the value here with its own allocation of egress IPs.", + "egressCIDRs": "EgressCIDRs is the list of CIDR ranges available for automatically assigning egress IPs to this node from. If this field is set then EgressIPs should be treated as read-only.", } func (HostSubnet) SwaggerDoc() map[string]string { diff --git a/vendor/github.com/openshift/api/network/v1/zz_generated.deepcopy.go b/vendor/github.com/openshift/api/network/v1/zz_generated.deepcopy.go index c39237bd54f0..8b7cc15a5b20 100644 --- a/vendor/github.com/openshift/api/network/v1/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/api/network/v1/zz_generated.deepcopy.go @@ -212,6 +212,11 @@ func (in *HostSubnet) DeepCopyInto(out *HostSubnet) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.EgressCIDRs != nil { + in, out := &in.EgressCIDRs, &out.EgressCIDRs + *out = make([]string, len(*in)) + copy(*out, *in) + } return } diff --git a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/rbac.go b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/rbac.go new file mode 100644 index 000000000000..de0d54ead7bd --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/rbac.go @@ -0,0 +1,115 @@ +package resourceapply + +import ( + "fmt" + + "github.com/openshift/library-go/pkg/operator/resource/resourcemerge" + rbacv1 "k8s.io/api/rbac/v1" + "k8s.io/apimachinery/pkg/api/equality" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + rbacclientv1 "k8s.io/client-go/kubernetes/typed/rbac/v1" +) + +// ApplyClusterRole merges objectmeta, requires rules, aggregation rules are not allowed for now. +func ApplyClusterRole(client rbacclientv1.ClusterRolesGetter, required *rbacv1.ClusterRole) (*rbacv1.ClusterRole, bool, error) { + if required.AggregationRule != nil && len(required.AggregationRule.ClusterRoleSelectors) != 0 { + return nil, false, fmt.Errorf("cannot create an aggregated cluster role") + } + + existing, err := client.ClusterRoles().Get(required.Name, metav1.GetOptions{}) + if apierrors.IsNotFound(err) { + actual, err := client.ClusterRoles().Create(required) + return actual, true, err + } + if err != nil { + return nil, false, err + } + + modified := resourcemerge.BoolPtr(false) + resourcemerge.EnsureObjectMeta(modified, &existing.ObjectMeta, required.ObjectMeta) + contentSame := equality.Semantic.DeepEqual(existing.Rules, required.Rules) + if contentSame && !*modified { + return existing, false, nil + } + existing.Rules = required.Rules + existing.AggregationRule = nil + + actual, err := client.ClusterRoles().Update(existing) + return actual, true, err +} + +// ApplyClusterRoleBinding merges objectmeta, requires subjects and role refs +// TODO on non-matching roleref, delete and recreate +func ApplyClusterRoleBinding(client rbacclientv1.ClusterRoleBindingsGetter, required *rbacv1.ClusterRoleBinding) (*rbacv1.ClusterRoleBinding, bool, error) { + existing, err := client.ClusterRoleBindings().Get(required.Name, metav1.GetOptions{}) + if apierrors.IsNotFound(err) { + actual, err := client.ClusterRoleBindings().Create(required) + return actual, true, err + } + if err != nil { + return nil, false, err + } + + modified := resourcemerge.BoolPtr(false) + resourcemerge.EnsureObjectMeta(modified, &existing.ObjectMeta, required.ObjectMeta) + contentSame := equality.Semantic.DeepEqual(existing.Subjects, required.Subjects) && + equality.Semantic.DeepEqual(existing.RoleRef, required.RoleRef) + if contentSame && !*modified { + return existing, false, nil + } + existing.Subjects = required.Subjects + existing.RoleRef = required.RoleRef + + actual, err := client.ClusterRoleBindings().Update(existing) + return actual, true, err +} + +// ApplyRole merges objectmeta, requires rules +func ApplyRole(client rbacclientv1.RolesGetter, required *rbacv1.Role) (*rbacv1.Role, bool, error) { + existing, err := client.Roles(required.Namespace).Get(required.Name, metav1.GetOptions{}) + if apierrors.IsNotFound(err) { + actual, err := client.Roles(required.Namespace).Create(required) + return actual, true, err + } + if err != nil { + return nil, false, err + } + + modified := resourcemerge.BoolPtr(false) + resourcemerge.EnsureObjectMeta(modified, &existing.ObjectMeta, required.ObjectMeta) + contentSame := equality.Semantic.DeepEqual(existing.Rules, required.Rules) + if contentSame && !*modified { + return existing, false, nil + } + existing.Rules = required.Rules + + actual, err := client.Roles(required.Namespace).Update(existing) + return actual, true, err +} + +// ApplyRoleBinding merges objectmeta, requires subjects and role refs +// TODO on non-matching roleref, delete and recreate +func ApplyRoleBinding(client rbacclientv1.RoleBindingsGetter, required *rbacv1.RoleBinding) (*rbacv1.RoleBinding, bool, error) { + existing, err := client.RoleBindings(required.Namespace).Get(required.Name, metav1.GetOptions{}) + if apierrors.IsNotFound(err) { + actual, err := client.RoleBindings(required.Namespace).Create(required) + return actual, true, err + } + if err != nil { + return nil, false, err + } + + modified := resourcemerge.BoolPtr(false) + resourcemerge.EnsureObjectMeta(modified, &existing.ObjectMeta, required.ObjectMeta) + contentSame := equality.Semantic.DeepEqual(existing.Subjects, required.Subjects) && + equality.Semantic.DeepEqual(existing.RoleRef, required.RoleRef) + if contentSame && !*modified { + return existing, false, nil + } + existing.Subjects = required.Subjects + existing.RoleRef = required.RoleRef + + actual, err := client.RoleBindings(required.Namespace).Update(existing) + return actual, true, err +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourcecread/rbac.go b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourcecread/rbac.go index d6ae68c343c7..d9c1524ae7f6 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourcecread/rbac.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourcecread/rbac.go @@ -24,3 +24,27 @@ func ReadClusterRoleBindingV1OrDie(objBytes []byte) *rbacv1.ClusterRoleBinding { } return requiredObj.(*rbacv1.ClusterRoleBinding) } + +func ReadClusterRoleV1OrDie(objBytes []byte) *rbacv1.ClusterRole{ + requiredObj, err := runtime.Decode(rbacCodecs.UniversalDecoder(rbacv1.SchemeGroupVersion), objBytes) + if err != nil { + panic(err) + } + return requiredObj.(*rbacv1.ClusterRole) +} + +func ReadRoleBindingV1OrDie(objBytes []byte) *rbacv1.RoleBinding { + requiredObj, err := runtime.Decode(rbacCodecs.UniversalDecoder(rbacv1.SchemeGroupVersion), objBytes) + if err != nil { + panic(err) + } + return requiredObj.(*rbacv1.RoleBinding) +} + +func ReadRoleV1OrDie(objBytes []byte) *rbacv1.Role{ + requiredObj, err := runtime.Decode(rbacCodecs.UniversalDecoder(rbacv1.SchemeGroupVersion), objBytes) + if err != nil { + panic(err) + } + return requiredObj.(*rbacv1.Role) +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourcemerge/apps.go b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourcemerge/apps.go new file mode 100644 index 000000000000..4a01ae788158 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourcemerge/apps.go @@ -0,0 +1,43 @@ +package resourcemerge + +import ( + appsv1 "k8s.io/api/apps/v1" + + operatorsv1alpha1 "github.com/openshift/api/operator/v1alpha1" + "github.com/openshift/library-go/pkg/operator/v1alpha1helpers" +) + +func ExpectedDeploymentGeneration(required *appsv1.Deployment, previousAvailability *operatorsv1alpha1.VersionAvailablity) int64 { + generation := int64(-1) + if previousAvailability != nil { + for _, curr := range previousAvailability.Generations { + if curr.Namespace == required.Namespace && + curr.Name == required.Name && + curr.Group == "apps" && + curr.Resource == "deployments" { + + generation = curr.LastGeneration + } + } + } + + return generation +} + +func ApplyGenerationAvailability(versionAvailability operatorsv1alpha1.VersionAvailablity, actual *appsv1.Deployment, errors ...error) operatorsv1alpha1.VersionAvailablity { + newAvailability := versionAvailability.DeepCopy() + if actual != nil { + newAvailability.UpdatedReplicas = actual.Status.UpdatedReplicas + newAvailability.ReadyReplicas = actual.Status.ReadyReplicas + newAvailability.Generations = []operatorsv1alpha1.GenerationHistory{ + { + Group: "apps", Resource: "Deployment", + Namespace: actual.Namespace, Name: actual.Name, + LastGeneration: actual.ObjectMeta.Generation, + }, + } + } + v1alpha1helpers.SetErrors(newAvailability, errors...) + + return *newAvailability +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourcemerge/generic_config_merger.go b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourcemerge/generic_config_merger.go new file mode 100644 index 000000000000..ee676a8a0d23 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourcemerge/generic_config_merger.go @@ -0,0 +1,121 @@ +package resourcemerge + +import ( + "github.com/golang/glog" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + kyaml "k8s.io/apimachinery/pkg/util/yaml" + + "reflect" +) + +// MergeConfigMap takes a configmap, the target key, special overlay funcs a list of config configs to overlay on top of each other +// It returns the resultant configmap and a bool indicating if any changes were made to the configmap +func MergeConfigMap(configMap *corev1.ConfigMap, configKey string, specialCases map[string]MergeFunc, configYAMLs ...[]byte) (*corev1.ConfigMap, bool, error) { + configBytes, err := MergeProcessConfig(specialCases, configYAMLs...) + if err != nil { + return nil, false, err + } + + if reflect.DeepEqual(configMap.Data[configKey], configBytes) { + return configMap, false, nil + } + + ret := configMap.DeepCopy() + ret.Data[configKey] = string(configBytes) + + return ret, true, nil +} + +// MergeProcessConfig merges a series of config yaml files together with each later one overlaying all previous +func MergeProcessConfig(specialCases map[string]MergeFunc, configYAMLs ...[]byte) ([]byte, error) { + currentConfigYAML := configYAMLs[0] + + for _, currConfigYAML := range configYAMLs[1:] { + prevConfigJSON, err := kyaml.ToJSON(currentConfigYAML) + if err != nil { + glog.Warning(err) + // maybe it's just json + prevConfigJSON = currentConfigYAML + } + prevConfigObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, prevConfigJSON) + if err != nil { + return nil, err + } + prevConfig := prevConfigObj.(*unstructured.Unstructured) + + if len(currConfigYAML) > 0 { + currConfigJSON, err := kyaml.ToJSON(currConfigYAML) + if err != nil { + glog.Warning(err) + // maybe it's just json + currConfigJSON = currConfigYAML + } + currConfigObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, currConfigJSON) + if err != nil { + return nil, err + } + currConfig := currConfigObj.(*unstructured.Unstructured) + if err := mergeConfig(prevConfig.Object, currConfig.Object, "", specialCases); err != nil { + return nil, err + } + } + + currentConfigYAML, err = runtime.Encode(unstructured.UnstructuredJSONScheme, prevConfig) + if err != nil { + return nil, err + } + } + + return currentConfigYAML, nil +} + +type MergeFunc func(dst, src interface{}, currentPath string) (interface{}, error) + +// mergeConfig overwrites entries in curr by additional. It modifies curr. +func mergeConfig(curr, additional map[string]interface{}, currentPath string, specialCases map[string]MergeFunc) error { + for additionalKey, additionalVal := range additional { + fullKey := currentPath + "." + additionalKey + specialCase, ok := specialCases[fullKey] + if ok { + var err error + curr[additionalKey], err = specialCase(curr[additionalKey], additionalVal, currentPath) + if err != nil { + return err + } + continue + } + + currVal, ok := curr[additionalKey] + if !ok { + curr[additionalKey] = additionalVal + continue + } + + // only some scalars are accepted + switch castVal := additionalVal.(type) { + case map[string]interface{}: + currValAsMap, ok := currVal.(map[string]interface{}) + if !ok { + currValAsMap = map[string]interface{}{} + curr[additionalKey] = currValAsMap + } + + err := mergeConfig(currValAsMap, castVal, fullKey, specialCases) + if err != nil { + return err + } + continue + + default: + if err := unstructured.SetNestedField(curr, castVal, additionalKey); err != nil { + return err + } + } + + } + + return nil +} diff --git a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge_test.go b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourcemerge/generic_config_merger_test.go similarity index 97% rename from vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge_test.go rename to vendor/github.com/openshift/library-go/pkg/operator/resource/resourcemerge/generic_config_merger_test.go index c2a200c66ae5..fe020bfcfda6 100644 --- a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge_test.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourcemerge/generic_config_merger_test.go @@ -1,4 +1,4 @@ -package operator +package resourcemerge import ( "reflect" @@ -13,7 +13,7 @@ func TestMergeConfig(t *testing.T) { name string curr map[string]interface{} additional map[string]interface{} - specialCases map[string]mergeFunc + specialCases map[string]MergeFunc expected map[string]interface{} expectedErr string diff --git a/vendor/github.com/openshift/service-serving-cert-signer/glide.lock b/vendor/github.com/openshift/service-serving-cert-signer/glide.lock index 0f69c722289a..f4b2714a60d4 100644 --- a/vendor/github.com/openshift/service-serving-cert-signer/glide.lock +++ b/vendor/github.com/openshift/service-serving-cert-signer/glide.lock @@ -1,5 +1,5 @@ hash: 7a825a3fb9315325701b51170aad4bedabbaaa546168698d201dea4edb448483 -updated: 2018-07-05T10:07:25.138991608-04:00 +updated: 2018-07-17T08:42:40.351628601-04:00 imports: - name: github.com/beorn7/perks version: 3ac7bf7a47d159a033b107610db8a1b6575507a4 @@ -74,13 +74,13 @@ imports: - name: github.com/modern-go/reflect2 version: 05fbef0ca5da472bbf96c9322b84a53edc03c9fd - name: github.com/openshift/api - version: aaea23fe8f58729c8196c8e7f4f40d12bd0e2135 + version: 12a230f9f9225237f1a35b86171848da610900bb subpackages: - config/v1 - operator/v1alpha1 - servicecertsigner/v1alpha1 - name: github.com/openshift/client-go - version: 4688ad28de2e88110c0ea30179c51b9b205f99be + version: b22949ca0eae046da7611d0d20c8089dcec212d6 subpackages: - servicecertsigner/clientset/versioned - servicecertsigner/clientset/versioned/scheme @@ -91,7 +91,7 @@ imports: - servicecertsigner/informers/externalversions/servicecertsigner/v1alpha1 - servicecertsigner/listers/servicecertsigner/v1alpha1 - name: github.com/openshift/library-go - version: 4bdffb3d6ca083fad9ee9f51d3273d328d349dbc + version: d366b6f2e76695de0e702cb9d06767bd517753b0 subpackages: - pkg/config/client - pkg/config/leaderelection @@ -131,7 +131,7 @@ imports: subpackages: - xfs - name: github.com/sirupsen/logrus - version: e54a77765aca7bbdd8e56c1c54f60579968b2dc9 + version: 92052687f8ec598ff0da626d2909478cfd1e3a3c - name: github.com/spf13/cobra version: c439c4fa093711d42e1b01acb1235b52004753c1 - name: github.com/spf13/pflag diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/build-images.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/build-images.sh index d3eb62c3c3e3..5c81ea9c6632 100755 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/build-images.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/build-images.sh @@ -16,17 +16,5 @@ function cleanup() { trap "cleanup" EXIT os::util::ensure::gopath_binary_exists imagebuilder -# image builds require RPMs to have been built -os::build::release::check_for_rpms - -# we need to mount RPMs into the container builds for installation -cat < "${OS_OUTPUT_RPMPATH}/_local.repo" -[origin-local-release] -name = OpenShift Origin Release from Local Source -baseurl = file:///srv/origin-local-release/ -gpgcheck = 0 -enabled = 0 -END -OS_BUILD_IMAGE_ARGS="${OS_BUILD_IMAGE_ARGS:-} -mount ${OS_OUTPUT_RPMPATH}/:/srv/origin-local-release/ -mount ${OS_OUTPUT_RPMPATH}/_local.repo:/etc/yum.repos.d/origin-local-release.repo" os::build::images \ No newline at end of file diff --git a/vendor/github.com/openshift/service-serving-cert-signer/manifests/v3.10.0/apiservice-cabundle-controller/clusterrole.yaml b/vendor/github.com/openshift/service-serving-cert-signer/manifests/v3.10.0/apiservice-cabundle-controller/clusterrole.yaml index 1a87caa4dc7d..0a3a8d6d4f6e 100644 --- a/vendor/github.com/openshift/service-serving-cert-signer/manifests/v3.10.0/apiservice-cabundle-controller/clusterrole.yaml +++ b/vendor/github.com/openshift/service-serving-cert-signer/manifests/v3.10.0/apiservice-cabundle-controller/clusterrole.yaml @@ -1,4 +1,4 @@ -apiVersion: rbac.authorization.k8s.io/v1beta1 +apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: system:openshift:controller:apiservice-cabundle-injector diff --git a/vendor/github.com/openshift/service-serving-cert-signer/manifests/v3.10.0/service-serving-cert-signer-controller/clusterrole.yaml b/vendor/github.com/openshift/service-serving-cert-signer/manifests/v3.10.0/service-serving-cert-signer-controller/clusterrole.yaml index b5e252172684..095c4611f227 100644 --- a/vendor/github.com/openshift/service-serving-cert-signer/manifests/v3.10.0/service-serving-cert-signer-controller/clusterrole.yaml +++ b/vendor/github.com/openshift/service-serving-cert-signer/manifests/v3.10.0/service-serving-cert-signer-controller/clusterrole.yaml @@ -1,4 +1,4 @@ -apiVersion: rbac.authorization.k8s.io/v1beta1 +apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: system:openshift:controller:service-serving-cert-signer diff --git a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge.go b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge.go deleted file mode 100644 index 952373d25acb..000000000000 --- a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge.go +++ /dev/null @@ -1,91 +0,0 @@ -package operator - -import ( - "github.com/golang/glog" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - kyaml "k8s.io/apimachinery/pkg/util/yaml" -) - -func mergeProcessConfig(defaultConfigYAML, userConfigYAML []byte, specialCases map[string]mergeFunc) ([]byte, error) { - defaultConfigJSON, err := kyaml.ToJSON(defaultConfigYAML) - if err != nil { - return nil, err - } - defaultConfigObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, defaultConfigJSON) - if err != nil { - return nil, err - } - defaultConfig := defaultConfigObj.(*unstructured.Unstructured) - - if len(userConfigYAML) > 0 { - userConfigJSON, err := kyaml.ToJSON(userConfigYAML) - if err != nil { - glog.Warning(err) - // maybe it's just yaml - userConfigJSON = userConfigYAML - } - userConfigObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, userConfigJSON) - if err != nil { - return nil, err - } - userConfig := userConfigObj.(*unstructured.Unstructured) - if err := mergeConfig(defaultConfig.Object, userConfig.Object, "", specialCases); err != nil { - return nil, err - } - } - - configBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, defaultConfig) - if err != nil { - return nil, err - } - return configBytes, nil -} - -type mergeFunc func(dst, src interface{}, currentPath string) (interface{}, error) - -// mergeConfig overwrites entries in curr by additional. It modifies curr. -func mergeConfig(curr, additional map[string]interface{}, currentPath string, specialCases map[string]mergeFunc) error { - for additionalKey, additionalVal := range additional { - fullKey := currentPath + "." + additionalKey - specialCase, ok := specialCases[fullKey] - if ok { - var err error - curr[additionalKey], err = specialCase(curr[additionalKey], additionalVal, currentPath) - if err != nil { - return err - } - continue - } - - currVal, ok := curr[additionalKey] - if !ok { - curr[additionalKey] = additionalVal - continue - } - - // only some scalars are accepted - switch castVal := additionalVal.(type) { - case map[string]interface{}: - currValAsMap, ok := currVal.(map[string]interface{}) - if !ok { - currValAsMap = map[string]interface{}{} - curr[additionalKey] = currValAsMap - } - - err := mergeConfig(currValAsMap, castVal, fullKey, specialCases) - if err != nil { - return err - } - continue - - default: - if err := unstructured.SetNestedField(curr, castVal, additionalKey); err != nil { - return err - } - } - - } - - return nil -} diff --git a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/operator.go b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/operator.go index 93c34f9dabeb..3b30ac12640c 100644 --- a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/operator.go +++ b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/operator.go @@ -18,6 +18,7 @@ import ( "k8s.io/client-go/informers" appsclientv1 "k8s.io/client-go/kubernetes/typed/apps/v1" coreclientv1 "k8s.io/client-go/kubernetes/typed/core/v1" + rbacclientv1 "k8s.io/client-go/kubernetes/typed/rbac/v1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" @@ -38,6 +39,7 @@ type ServiceCertSignerOperator struct { appsv1Client appsclientv1.AppsV1Interface corev1Client coreclientv1.CoreV1Interface + rbacv1Client rbacclientv1.RbacV1Interface // queue only ever has one item, but it has nice error handling backoff/retry semantics queue workqueue.RateLimitingInterface @@ -49,11 +51,13 @@ func NewServiceCertSignerOperator( operatorConfigClient scsclientv1alpha1.ServiceCertSignerOperatorConfigsGetter, appsv1Client appsclientv1.AppsV1Interface, corev1Client coreclientv1.CoreV1Interface, + rbacv1Client rbacclientv1.RbacV1Interface, ) *ServiceCertSignerOperator { c := &ServiceCertSignerOperator{ operatorConfigClient: operatorConfigClient, appsv1Client: appsv1Client, corev1Client: corev1Client, + rbacv1Client: rbacv1Client, queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "ServiceCertSignerOperator"), } @@ -123,7 +127,7 @@ func (c ServiceCertSignerOperator) sync() error { var versionAvailability operatorsv1alpha1.VersionAvailablity operatorConfig.Status.TaskSummary = "sync-[3.10.0,3.10.1)" operatorConfig.Status.TargetAvailability = nil - versionAvailability, errors = sync_v310_00_to_latest(c, operatorConfig, operatorConfig.Status.CurrentAvailability) + versionAvailability, errors = sync_v311_00_to_latest(c, operatorConfig, operatorConfig.Status.CurrentAvailability) operatorConfig.Status.CurrentAvailability = &versionAvailability default: diff --git a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/read.go b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/read.go deleted file mode 100644 index 12e60deb2ebd..000000000000 --- a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/read.go +++ /dev/null @@ -1,38 +0,0 @@ -package operator - -import ( - "fmt" - - "k8s.io/apimachinery/pkg/runtime/serializer" - "k8s.io/apimachinery/pkg/runtime" - kyaml "k8s.io/apimachinery/pkg/util/yaml" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - - scsv1alpha1 "github.com/openshift/api/servicecertsigner/v1alpha1" -) - -var ( - configScheme = runtime.NewScheme() - configCodecs = serializer.NewCodecFactory(configScheme) -) - -func init() { - scsv1alpha1.AddToScheme(configScheme) -} - -func readServiceServingCertSignerConfig(objBytes []byte) (*unstructured.Unstructured, error) { - data, err := kyaml.ToJSON(objBytes) - if err != nil { - panic(err) - } - defaultConfigObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, data) - if err != nil { - return nil, err - } - ret, ok := defaultConfigObj.(*unstructured.Unstructured) - if !ok { - return nil, fmt.Errorf("expected *unstructured.Unstructured, got %T", defaultConfigObj) - } - - return ret, nil -} \ No newline at end of file diff --git a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/starter.go b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/starter.go index 8f2e93f3ea13..87c04a0b0256 100644 --- a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/starter.go +++ b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/starter.go @@ -31,6 +31,7 @@ func RunOperator(clientConfig *rest.Config, stopCh <-chan struct{}) error { scsClient.ServicecertsignerV1alpha1(), kubeClient.AppsV1(), kubeClient.CoreV1(), + kubeClient.RbacV1(), ) operatorInformers.Start(stopCh) diff --git a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_all_v311_00.go b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_all_v311_00.go new file mode 100644 index 000000000000..7c7eb858886b --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_all_v311_00.go @@ -0,0 +1,34 @@ +package operator + +import ( + operatorsv1alpha1 "github.com/openshift/api/operator/v1alpha1" + scsv1alpha1 "github.com/openshift/api/servicecertsigner/v1alpha1" +) + +// sync_v311_00_to_latest takes care of synchronizing (not upgrading) the thing we're managing. +// most of the time the sync method will be good for a large span of minor versions +func sync_v311_00_to_latest(c ServiceCertSignerOperator, operatorConfig *scsv1alpha1.ServiceCertSignerOperatorConfig, previousAvailability *operatorsv1alpha1.VersionAvailablity) (operatorsv1alpha1.VersionAvailablity, []error) { + signingVersionAvailability, signingErrors := syncSigningController_v311_00_to_latest(c, operatorConfig, previousAvailability) + apiServiceInjectorVersionAvailability, apiServiceInjectorErrors := syncAPIServiceController_v311_00_to_latest(c, operatorConfig, previousAvailability) + + allErrors := []error{} + allErrors = append(allErrors, signingErrors...) + allErrors = append(allErrors, apiServiceInjectorErrors...) + + mergedVersionAvailability := operatorsv1alpha1.VersionAvailablity{ + Version: operatorConfig.Spec.Version, + } + mergedVersionAvailability.Generations = append(mergedVersionAvailability.Generations, signingVersionAvailability.Generations...) + mergedVersionAvailability.Generations = append(mergedVersionAvailability.Generations, apiServiceInjectorVersionAvailability.Generations...) + if signingVersionAvailability.UpdatedReplicas > 0 && apiServiceInjectorVersionAvailability.UpdatedReplicas > 0 { + mergedVersionAvailability.UpdatedReplicas = 1 + } + if signingVersionAvailability.ReadyReplicas > 0 && apiServiceInjectorVersionAvailability.ReadyReplicas > 0 { + mergedVersionAvailability.ReadyReplicas = 1 + } + for _, err := range allErrors { + mergedVersionAvailability.Errors = append(mergedVersionAvailability.Errors, err.Error()) + } + + return mergedVersionAvailability, allErrors +} diff --git a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_apiservice_v311_00.go b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_apiservice_v311_00.go new file mode 100644 index 000000000000..2e5caae5db56 --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_apiservice_v311_00.go @@ -0,0 +1,134 @@ +package operator + +import ( + "fmt" + + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + appsclientv1 "k8s.io/client-go/kubernetes/typed/apps/v1" + coreclientv1 "k8s.io/client-go/kubernetes/typed/core/v1" + + operatorsv1alpha1 "github.com/openshift/api/operator/v1alpha1" + scsv1alpha1 "github.com/openshift/api/servicecertsigner/v1alpha1" + "github.com/openshift/library-go/pkg/operator/resource/resourceapply" + "github.com/openshift/library-go/pkg/operator/resource/resourcecread" + "github.com/openshift/library-go/pkg/operator/resource/resourcemerge" + "github.com/openshift/service-serving-cert-signer/pkg/operator/v310_00_assets" +) + +// syncAPIServiceController_v311_00_to_latest takes care of synchronizing (not upgrading) the thing we're managing. +// most of the time the sync method will be good for a large span of minor versions +func syncAPIServiceController_v311_00_to_latest(c ServiceCertSignerOperator, operatorConfig *scsv1alpha1.ServiceCertSignerOperatorConfig, previousAvailability *operatorsv1alpha1.VersionAvailablity) (operatorsv1alpha1.VersionAvailablity, []error) { + versionAvailability := operatorsv1alpha1.VersionAvailablity{ + Version: operatorConfig.Spec.Version, + } + + errors := []error{} + var err error + + requiredNamespace := resourceread.ReadNamespaceV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/ns.yaml")) + _, _, err = resourceapply.ApplyNamespace(c.corev1Client, requiredNamespace) + if err != nil { + errors = append(errors, fmt.Errorf("%q: %v", "ns", err)) + } + + requiredClusterRole := resourceread.ReadClusterRoleV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/clusterrole.yaml")) + _, _, err = resourceapply.ApplyClusterRole(c.rbacv1Client, requiredClusterRole) + if err != nil { + errors = append(errors, fmt.Errorf("%q: %v", "svc", err)) + } + + requiredClusterRoleBinding := resourceread.ReadClusterRoleBindingV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/clusterrolebinding.yaml")) + _, _, err = resourceapply.ApplyClusterRoleBinding(c.rbacv1Client, requiredClusterRoleBinding) + if err != nil { + errors = append(errors, fmt.Errorf("%q: %v", "svc", err)) + } + + requiredService := resourceread.ReadServiceV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/svc.yaml")) + _, _, err = resourceapply.ApplyService(c.corev1Client, requiredService) + if err != nil { + errors = append(errors, fmt.Errorf("%q: %v", "svc", err)) + } + + requiredSA := resourceread.ReadServiceAccountV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/sa.yaml")) + _, saModified, err := resourceapply.ApplyServiceAccount(c.corev1Client, requiredSA) + if err != nil { + errors = append(errors, fmt.Errorf("%q: %v", "sa", err)) + } + + // TODO create a new configmap whenever the data value changes + _, configMapModified, err := manageAPIServiceConfigMap_v311_00_to_latest(c.corev1Client, operatorConfig) + if err != nil { + errors = append(errors, fmt.Errorf("%q: %v", "configmap", err)) + } + + _, signingCABundleModified, err := manageSigningCABundle(c.corev1Client) + if err != nil { + errors = append(errors, fmt.Errorf("%q: %v", "signing-key", err)) + } + + forceDeployment := operatorConfig.ObjectMeta.Generation != operatorConfig.Status.ObservedGeneration + if saModified { // SA modification can cause new tokens + forceDeployment = true + } + if signingCABundleModified { + forceDeployment = true + } + if configMapModified { + forceDeployment = true + } + + // we have attempted to update our configmaps and secrets, now it is time to create the DS + // TODO check basic preconditions here + actualDeployment, _, err := manageAPIServiceDeployment_v311_00_to_latest(c.appsv1Client, operatorConfig, previousAvailability, forceDeployment) + if err != nil { + errors = append(errors, fmt.Errorf("%q: %v", "deployment", err)) + } + + return resourcemerge.ApplyGenerationAvailability(versionAvailability, actualDeployment, errors...), errors +} + +func manageAPIServiceConfigMap_v311_00_to_latest(client coreclientv1.ConfigMapsGetter, operatorConfig *scsv1alpha1.ServiceCertSignerOperatorConfig) (*corev1.ConfigMap, bool, error) { + configMap := resourceread.ReadConfigMapV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/cm.yaml")) + defaultConfig := v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/defaultconfig.yaml") + requiredConfigMap, _, err := resourcemerge.MergeConfigMap(configMap, "controller-config.yaml", nil, defaultConfig, operatorConfig.Spec.APIServiceCABundleInjectorConfig.Raw) + if err != nil { + return nil, false, err + } + return resourceapply.ApplyConfigMap(client, requiredConfigMap) +} + +func manageAPIServiceDeployment_v311_00_to_latest(client appsclientv1.DeploymentsGetter, options *scsv1alpha1.ServiceCertSignerOperatorConfig, previousAvailability *operatorsv1alpha1.VersionAvailablity, forceDeployment bool) (*appsv1.Deployment, bool, error) { + required := resourceread.ReadDeploymentV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/deployment.yaml")) + required.Spec.Template.Spec.Containers[0].Image = options.Spec.ImagePullSpec + required.Spec.Template.Spec.Containers[0].Args = append(required.Spec.Template.Spec.Containers[0].Args, fmt.Sprintf("-v=%d", options.Spec.Logging.Level)) + + return resourceapply.ApplyDeployment(client, required, resourcemerge.ExpectedDeploymentGeneration(required, previousAvailability), forceDeployment) +} + +// TODO manage rotation in addition to initial creation +func manageSigningCABundle(client coreclientv1.CoreV1Interface) (*corev1.ConfigMap, bool, error) { + configMap := resourceread.ReadConfigMapV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/signing-cabundle.yaml")) + existing, err := client.ConfigMaps(configMap.Namespace).Get(configMap.Name, metav1.GetOptions{}) + if !apierrors.IsNotFound(err) { + return existing, false, err + } + + secret := resourceread.ReadSecretV1OrDie(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/signing-secret.yaml")) + currentSigningKeySecret, err := client.Secrets(secret.Namespace).Get(secret.Name, metav1.GetOptions{}) + if apierrors.IsNotFound(err) { + return existing, false, err + } + if err != nil { + return existing, false, err + } + if len(currentSigningKeySecret.Data["tls.crt"]) == 0 { + return existing, false, err + } + + configMap.Data["cabundle.crt"] = string(currentSigningKeySecret.Data["tls.crt"]) + + return resourceapply.ApplyConfigMap(client, configMap) +} diff --git a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_signer_v311_00.go b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_signer_v311_00.go new file mode 100644 index 000000000000..a1cd26181c35 --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_signer_v311_00.go @@ -0,0 +1,141 @@ +package operator + +import ( + "bytes" + "fmt" + "time" + + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + appsclientv1 "k8s.io/client-go/kubernetes/typed/apps/v1" + coreclientv1 "k8s.io/client-go/kubernetes/typed/core/v1" + + operatorsv1alpha1 "github.com/openshift/api/operator/v1alpha1" + scsv1alpha1 "github.com/openshift/api/servicecertsigner/v1alpha1" + "github.com/openshift/library-go/pkg/crypto" + "github.com/openshift/library-go/pkg/operator/resource/resourceapply" + "github.com/openshift/library-go/pkg/operator/resource/resourcecread" + "github.com/openshift/library-go/pkg/operator/resource/resourcemerge" + "github.com/openshift/service-serving-cert-signer/pkg/operator/v310_00_assets" +) + +// syncSigningController_v311_00_to_latest takes care of synchronizing (not upgrading) the thing we're managing. +// most of the time the sync method will be good for a large span of minor versions +func syncSigningController_v311_00_to_latest(c ServiceCertSignerOperator, operatorConfig *scsv1alpha1.ServiceCertSignerOperatorConfig, previousAvailability *operatorsv1alpha1.VersionAvailablity) (operatorsv1alpha1.VersionAvailablity, []error) { + versionAvailability := operatorsv1alpha1.VersionAvailablity{ + Version: operatorConfig.Spec.Version, + } + + errors := []error{} + var err error + + requiredNamespace := resourceread.ReadNamespaceV1OrDie(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/ns.yaml")) + _, _, err = resourceapply.ApplyNamespace(c.corev1Client, requiredNamespace) + if err != nil { + errors = append(errors, fmt.Errorf("%q: %v", "ns", err)) + } + + requiredClusterRole := resourceread.ReadClusterRoleV1OrDie(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/clusterrole.yaml")) + _, _, err = resourceapply.ApplyClusterRole(c.rbacv1Client, requiredClusterRole) + if err != nil { + errors = append(errors, fmt.Errorf("%q: %v", "svc", err)) + } + + requiredClusterRoleBinding := resourceread.ReadClusterRoleBindingV1OrDie(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/clusterrolebinding.yaml")) + _, _, err = resourceapply.ApplyClusterRoleBinding(c.rbacv1Client, requiredClusterRoleBinding) + if err != nil { + errors = append(errors, fmt.Errorf("%q: %v", "svc", err)) + } + + requiredService := resourceread.ReadServiceV1OrDie(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/svc.yaml")) + _, _, err = resourceapply.ApplyService(c.corev1Client, requiredService) + if err != nil { + errors = append(errors, fmt.Errorf("%q: %v", "svc", err)) + } + + requiredSA := resourceread.ReadServiceAccountV1OrDie(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/sa.yaml")) + _, saModified, err := resourceapply.ApplyServiceAccount(c.corev1Client, requiredSA) + if err != nil { + errors = append(errors, fmt.Errorf("%q: %v", "sa", err)) + } + + // TODO create a new configmap whenever the data value changes + _, configMapModified, err := manageSigningConfigMap_v311_00_to_latest(c.corev1Client, operatorConfig) + if err != nil { + errors = append(errors, fmt.Errorf("%q: %v", "configmap", err)) + } + + _, signingSecretModified, err := manageSigningSecret_v311_00_to_latest(c.corev1Client) + if err != nil { + errors = append(errors, fmt.Errorf("%q: %v", "signing-key", err)) + } + + forceDeployment := operatorConfig.ObjectMeta.Generation != operatorConfig.Status.ObservedGeneration + if saModified { // SA modification can cause new tokens + forceDeployment = true + } + if signingSecretModified { + forceDeployment = true + } + if configMapModified { + forceDeployment = true + } + + // our configmaps and secrets are in order, now it is time to create the DS + // TODO check basic preconditions here + actualDeployment, _, err := manageSignerDeployment_v311_00_to_latest(c.appsv1Client, operatorConfig, previousAvailability, forceDeployment) + if err != nil { + errors = append(errors, fmt.Errorf("%q: %v", "deployment", err)) + } + + return resourcemerge.ApplyGenerationAvailability(versionAvailability, actualDeployment, errors...), errors +} + +func manageSigningConfigMap_v311_00_to_latest(client coreclientv1.ConfigMapsGetter, operatorConfig *scsv1alpha1.ServiceCertSignerOperatorConfig) (*corev1.ConfigMap, bool, error) { + configMap := resourceread.ReadConfigMapV1OrDie(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/cm.yaml")) + defaultConfig := v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/defaultconfig.yaml") + requiredConfigMap, _, err := resourcemerge.MergeConfigMap(configMap, "controller-config.yaml", nil, defaultConfig, operatorConfig.Spec.ServiceServingCertSignerConfig.Raw) + if err != nil { + return nil, false, err + } + return resourceapply.ApplyConfigMap(client, requiredConfigMap) +} + +// TODO manage rotation in addition to initial creation +func manageSigningSecret_v311_00_to_latest(client coreclientv1.SecretsGetter) (*corev1.Secret, bool, error) { + secret := resourceread.ReadSecretV1OrDie(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/signing-secret.yaml")) + existing, err := client.Secrets(secret.Namespace).Get(secret.Name, metav1.GetOptions{}) + if !apierrors.IsNotFound(err) { + return existing, false, err + } + + ca, err := crypto.MakeCAConfig(serviceServingCertSignerName(), 10) + if err != nil { + return existing, false, err + } + + certBytes := &bytes.Buffer{} + keyBytes := &bytes.Buffer{} + if err := ca.WriteCertConfig(certBytes, keyBytes); err != nil { + return existing, false, err + } + + secret.Data["tls.crt"] = certBytes.Bytes() + secret.Data["tls.key"] = keyBytes.Bytes() + + return resourceapply.ApplySecret(client, secret) +} + +func manageSignerDeployment_v311_00_to_latest(client appsclientv1.DeploymentsGetter, options *scsv1alpha1.ServiceCertSignerOperatorConfig, previousAvailability *operatorsv1alpha1.VersionAvailablity, forceDeployment bool) (*appsv1.Deployment, bool, error) { + required := resourceread.ReadDeploymentV1OrDie(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/deployment.yaml")) + required.Spec.Template.Spec.Containers[0].Image = options.Spec.ImagePullSpec + required.Spec.Template.Spec.Containers[0].Args = append(required.Spec.Template.Spec.Containers[0].Args, fmt.Sprintf("-v=%d", options.Spec.Logging.Level)) + + return resourceapply.ApplyDeployment(client, required, resourcemerge.ExpectedDeploymentGeneration(required, previousAvailability), forceDeployment) +} + +func serviceServingCertSignerName() string { + return fmt.Sprintf("%s@%d", "openshift-service-serving-signer", time.Now().Unix()) +} diff --git a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_v310_00.go b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_v310_00.go deleted file mode 100644 index eb2477821a2d..000000000000 --- a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_v310_00.go +++ /dev/null @@ -1,301 +0,0 @@ -package operator - -import ( - "bytes" - "fmt" - "time" - - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - operatorsv1alpha1 "github.com/openshift/api/operator/v1alpha1" - scsv1alpha1 "github.com/openshift/api/servicecertsigner/v1alpha1" - "github.com/openshift/library-go/pkg/crypto" - "github.com/openshift/library-go/pkg/operator/resource/resourceapply" - "github.com/openshift/library-go/pkg/operator/resource/resourcecread" - "github.com/openshift/library-go/pkg/operator/v1alpha1helpers" - "github.com/openshift/service-serving-cert-signer/pkg/operator/v310_00_assets" -) - -// most of the time the sync method will be good for a large span of minor versions -func sync_v310_00_to_latest(c ServiceCertSignerOperator, operatorConfig *scsv1alpha1.ServiceCertSignerOperatorConfig, previousAvailability *operatorsv1alpha1.VersionAvailablity) (operatorsv1alpha1.VersionAvailablity, []error) { - signingVersionAvailability, signingErrors := sync_v310_00_to_latest_SigningController(c, operatorConfig, previousAvailability) - apiServiceInjectorVersionAvailability, apiServiceInjectorErrors := sync_v310_00_to_latest_APIServiceController(c, operatorConfig, previousAvailability) - - allErrors := []error{} - allErrors = append(allErrors, signingErrors...) - allErrors = append(allErrors, apiServiceInjectorErrors...) - - mergedVersionAvailability := operatorsv1alpha1.VersionAvailablity{ - Version: operatorConfig.Spec.Version, - } - mergedVersionAvailability.Generations = append(mergedVersionAvailability.Generations, signingVersionAvailability.Generations...) - mergedVersionAvailability.Generations = append(mergedVersionAvailability.Generations, apiServiceInjectorVersionAvailability.Generations...) - if signingVersionAvailability.UpdatedReplicas > 0 && apiServiceInjectorVersionAvailability.UpdatedReplicas > 0 { - mergedVersionAvailability.UpdatedReplicas = 1 - } - if signingVersionAvailability.ReadyReplicas > 0 && apiServiceInjectorVersionAvailability.ReadyReplicas > 0 { - mergedVersionAvailability.ReadyReplicas = 1 - } - for _, err := range allErrors { - mergedVersionAvailability.Errors = append(mergedVersionAvailability.Errors, err.Error()) - } - - return mergedVersionAvailability, allErrors -} - -func sync_v310_00_to_latest_APIServiceController(c ServiceCertSignerOperator, operatorConfig *scsv1alpha1.ServiceCertSignerOperatorConfig, previousAvailability *operatorsv1alpha1.VersionAvailablity) (operatorsv1alpha1.VersionAvailablity, []error) { - versionAvailability := operatorsv1alpha1.VersionAvailablity{ - Version: operatorConfig.Spec.Version, - } - - errors := []error{} - var err error - - requiredNamespace := resourceread.ReadNamespaceV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/ns.yaml")) - _, _, err = resourceapply.ApplyNamespace(c.corev1Client, requiredNamespace) - if err != nil { - errors = append(errors, fmt.Errorf("%q: %v", "ns", err)) - } - - requiredService := resourceread.ReadServiceV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/svc.yaml")) - _, _, err = resourceapply.ApplyService(c.corev1Client, requiredService) - if err != nil { - errors = append(errors, fmt.Errorf("%q: %v", "svc", err)) - } - - requiredSA := resourceread.ReadServiceAccountV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/sa.yaml")) - _, saModified, err := resourceapply.ApplyServiceAccount(c.corev1Client, requiredSA) - if err != nil { - errors = append(errors, fmt.Errorf("%q: %v", "sa", err)) - } - - // TODO create a new configmap whenever the data value changes - _, configMapModified, err := ensureAPIServiceInjectorConfigMap_v310_00_to_latest(c, operatorConfig.Spec) - if err != nil { - errors = append(errors, fmt.Errorf("%q: %v", "cm", err)) - } - - _, signingCABundleModified, err := manageSigningCABundle(c) - if err != nil { - errors = append(errors, fmt.Errorf("%q: %v", "signing-key", err)) - } - - forceDeployment := operatorConfig.ObjectMeta.Generation != operatorConfig.Status.ObservedGeneration - if saModified { // SA modification can cause new tokens - forceDeployment = true - } - if signingCABundleModified { - forceDeployment = true - } - if configMapModified { - forceDeployment = true - } - - // we have attempted to update our configmaps and secrets, now it is time to create the DS - // TODO check basic preconditions here - actualDeployment, _, err := ensureAPIServiceInjectorDeployment_v310_00_to_latest(c, operatorConfig, previousAvailability, forceDeployment) - if err != nil { - errors = append(errors, fmt.Errorf("%q: %v", "deployment", err)) - } - if actualDeployment != nil { - versionAvailability.UpdatedReplicas = actualDeployment.Status.UpdatedReplicas - versionAvailability.ReadyReplicas = actualDeployment.Status.ReadyReplicas - versionAvailability.Generations = []operatorsv1alpha1.GenerationHistory{ - { - Group: "apps", Resource: "Deployment", - Namespace: targetNamespaceName, Name: "apiservice-cabundle-injector", - LastGeneration: actualDeployment.ObjectMeta.Generation, - }, - } - } - - v1alpha1helpers.SetErrors(&versionAvailability, errors...) - - return versionAvailability, errors -} - -func sync_v310_00_to_latest_SigningController(c ServiceCertSignerOperator, operatorConfig *scsv1alpha1.ServiceCertSignerOperatorConfig, previousAvailability *operatorsv1alpha1.VersionAvailablity) (operatorsv1alpha1.VersionAvailablity, []error) { - versionAvailability := operatorsv1alpha1.VersionAvailablity{ - Version: operatorConfig.Spec.Version, - } - - errors := []error{} - var err error - - requiredNamespace := resourceread.ReadNamespaceV1OrDie(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/ns.yaml")) - _, _, err = resourceapply.ApplyNamespace(c.corev1Client, requiredNamespace) - if err != nil { - errors = append(errors, fmt.Errorf("%q: %v", "ns", err)) - } - - requiredService := resourceread.ReadServiceV1OrDie(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/svc.yaml")) - _, _, err = resourceapply.ApplyService(c.corev1Client, requiredService) - if err != nil { - errors = append(errors, fmt.Errorf("%q: %v", "svc", err)) - } - - requiredSA := resourceread.ReadServiceAccountV1OrDie(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/sa.yaml")) - _, saModified, err := resourceapply.ApplyServiceAccount(c.corev1Client, requiredSA) - if err != nil { - errors = append(errors, fmt.Errorf("%q: %v", "sa", err)) - } - - // TODO create a new configmap whenever the data value changes - _, configMapModified, err := ensureServingSignerConfigMap_v310_00_to_latest(c, operatorConfig.Spec) - if err != nil { - errors = append(errors, fmt.Errorf("%q: %v", "cm", err)) - } - - _, signingSecretModified, err := manageSigningSecret(c) - if err != nil { - errors = append(errors, fmt.Errorf("%q: %v", "signing-key", err)) - } - - forceDeployment := operatorConfig.ObjectMeta.Generation != operatorConfig.Status.ObservedGeneration - if saModified { // SA modification can cause new tokens - forceDeployment = true - } - if signingSecretModified { - forceDeployment = true - } - if configMapModified { - forceDeployment = true - } - - // our configmaps and secrets are in order, now it is time to create the DS - // TODO check basic preconditions here - actualDeployment, _, err := ensureServingSignerDeployment_v310_00_to_latest(c, operatorConfig, previousAvailability, forceDeployment) - if err != nil { - errors = append(errors, fmt.Errorf("%q: %v", "deployment", err)) - } - if actualDeployment != nil { - versionAvailability.UpdatedReplicas = actualDeployment.Status.UpdatedReplicas - versionAvailability.ReadyReplicas = actualDeployment.Status.ReadyReplicas - versionAvailability.Generations = []operatorsv1alpha1.GenerationHistory{ - { - Group: "apps", Resource: "Deployment", - Namespace: targetNamespaceName, Name: "service-serving-cert-signer", - LastGeneration: actualDeployment.ObjectMeta.Generation, - }, - } - } - - v1alpha1helpers.SetErrors(&versionAvailability, errors...) - - return versionAvailability, errors -} - -// TODO manage rotation in addition to initial creation -func manageSigningSecret(c ServiceCertSignerOperator) (*corev1.Secret, bool, error) { - secret := resourceread.ReadSecretV1OrDie(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/signing-secret.yaml")) - existing, err := c.corev1Client.Secrets(secret.Namespace).Get(secret.Name, metav1.GetOptions{}) - if !apierrors.IsNotFound(err) { - return existing, false, err - } - - ca, err := crypto.MakeCAConfig(serviceServingCertSignerName(), 10) - if err != nil { - return existing, false, err - } - - certBytes := &bytes.Buffer{} - keyBytes := &bytes.Buffer{} - if err := ca.WriteCertConfig(certBytes, keyBytes); err != nil { - return existing, false, err - } - - secret.Data["tls.crt"] = certBytes.Bytes() - secret.Data["tls.key"] = keyBytes.Bytes() - - return resourceapply.ApplySecret(c.corev1Client, secret) -} - -func ensureServingSignerConfigMap_v310_00_to_latest(c ServiceCertSignerOperator, options scsv1alpha1.ServiceCertSignerOperatorConfigSpec) (*corev1.ConfigMap, bool, error) { - configBytes, err := mergeProcessConfig(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/defaultconfig.yaml"), options.ServiceServingCertSignerConfig.Raw, nil) - if err != nil { - return nil, false, err - } - - requiredConfigMap := resourceread.ReadConfigMapV1OrDie(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/cm.yaml")) - const configKey = "controller-config.yaml" - requiredConfigMap.Data[configKey] = string(configBytes) - - return resourceapply.ApplyConfigMap(c.corev1Client, requiredConfigMap) -} - -func ensureServingSignerDeployment_v310_00_to_latest(c ServiceCertSignerOperator, options *scsv1alpha1.ServiceCertSignerOperatorConfig, previousAvailability *operatorsv1alpha1.VersionAvailablity, forceDeployment bool) (*appsv1.Deployment, bool, error) { - required := resourceread.ReadDeploymentV1OrDie(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/deployment.yaml")) - required.Spec.Template.Spec.Containers[0].Image = options.Spec.ImagePullSpec - required.Spec.Template.Spec.Containers[0].Args = append(required.Spec.Template.Spec.Containers[0].Args, fmt.Sprintf("-v=%d", options.Spec.Logging.Level)) - - generation := int64(-1) - if previousAvailability != nil { - for _, curr := range previousAvailability.Generations { - if curr.Name == "service-serving-cert-signer" { - generation = curr.LastGeneration - } - } - } - return resourceapply.ApplyDeployment(c.appsv1Client, required, generation, forceDeployment) -} - -func serviceServingCertSignerName() string { - return fmt.Sprintf("%s@%d", "openshift-service-serving-signer", time.Now().Unix()) -} - -func ensureAPIServiceInjectorConfigMap_v310_00_to_latest(c ServiceCertSignerOperator, options scsv1alpha1.ServiceCertSignerOperatorConfigSpec) (*corev1.ConfigMap, bool, error) { - configBytes, err := mergeProcessConfig(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/defaultconfig.yaml"), options.APIServiceCABundleInjectorConfig.Raw, nil) - if err != nil { - return nil, false, err - } - - requiredConfigMap := resourceread.ReadConfigMapV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/cm.yaml")) - const configKey = "controller-config.yaml" - requiredConfigMap.Data[configKey] = string(configBytes) - - return resourceapply.ApplyConfigMap(c.corev1Client, requiredConfigMap) -} - -func ensureAPIServiceInjectorDeployment_v310_00_to_latest(c ServiceCertSignerOperator, options *scsv1alpha1.ServiceCertSignerOperatorConfig, previousAvailability *operatorsv1alpha1.VersionAvailablity, forceDeployment bool) (*appsv1.Deployment, bool, error) { - required := resourceread.ReadDeploymentV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/deployment.yaml")) - required.Spec.Template.Spec.Containers[0].Image = options.Spec.ImagePullSpec - required.Spec.Template.Spec.Containers[0].Args = append(required.Spec.Template.Spec.Containers[0].Args, fmt.Sprintf("-v=%d", options.Spec.Logging.Level)) - - generation := int64(-1) - if previousAvailability != nil { - for _, curr := range previousAvailability.Generations { - if curr.Name == "apiservice-cabundle-injector" { - generation = curr.LastGeneration - } - } - } - return resourceapply.ApplyDeployment(c.appsv1Client, required, generation, forceDeployment) -} - -// TODO manage rotation in addition to initial creation -func manageSigningCABundle(c ServiceCertSignerOperator) (*corev1.ConfigMap, bool, error) { - configMap := resourceread.ReadConfigMapV1OrDie(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/signing-cabundle.yaml")) - existing, err := c.corev1Client.ConfigMaps(configMap.Namespace).Get(configMap.Name, metav1.GetOptions{}) - if !apierrors.IsNotFound(err) { - return existing, false, err - } - - secret := resourceread.ReadSecretV1OrDie(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/signing-secret.yaml")) - currentSigningKeySecret, err := c.corev1Client.Secrets(secret.Namespace).Get(secret.Name, metav1.GetOptions{}) - if apierrors.IsNotFound(err) { - return existing, false, err - } - if err != nil { - return existing, false, err - } - if len(currentSigningKeySecret.Data["tls.crt"]) == 0 { - return existing, false, err - } - - configMap.Data["cabundle.crt"] = string(currentSigningKeySecret.Data["tls.crt"]) - - return resourceapply.ApplyConfigMap(c.corev1Client, configMap) -} diff --git a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/v310_00_assets/bindata.go b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/v310_00_assets/bindata.go index 9d2a5f64a9af..f3ee5162ca1f 100644 --- a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/v310_00_assets/bindata.go +++ b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/v310_00_assets/bindata.go @@ -61,7 +61,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _v3100ApiserviceCabundleControllerClusterroleYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1beta1 +var _v3100ApiserviceCabundleControllerClusterroleYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: system:openshift:controller:apiservice-cabundle-injector @@ -336,7 +336,7 @@ func v3100ApiserviceCabundleControllerSvcYaml() (*asset, error) { return a, nil } -var _v3100ServiceServingCertSignerControllerClusterroleYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1beta1 +var _v3100ServiceServingCertSignerControllerClusterroleYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: system:openshift:controller:service-serving-cert-signer