From 9eb8db1e4e3ce905301e2adfe483082fa9c47fbe Mon Sep 17 00:00:00 2001 From: Tanmay Satam Date: Thu, 8 Feb 2024 12:35:17 -0500 Subject: [PATCH] Update cluster lifecycle API fields to readOnly (#3380) * Exclude Python AAZ client from license hack script * Update clusterProfile url, apiserverProfile url and ip, ingressProfile ip, systemdata to be readonly in v20231122 API * Update swagger json (generated) * Update API static validation tests and converter to respect readOnly fields * Update generated client SDKs --- .sha256sum | 2 +- hack/licenses/main.go | 2 +- pkg/api/v20231122/openshiftcluster.go | 10 ++-- pkg/api/v20231122/openshiftcluster_convert.go | 32 +++++++----- .../openshiftcluster_validatestatic_test.go | 49 +++++++++++++------ .../mgmt/2023-11-22/redhatopenshift/models.go | 35 +++++++++++-- .../v2023_11_22/models/_models.py | 35 ++++++++----- .../v2023_11_22/models/_models_py3.py | 40 ++++++++------- .../stable/2023-11-22/redhatopenshift.json | 12 +++-- 9 files changed, 146 insertions(+), 71 deletions(-) diff --git a/.sha256sum b/.sha256sum index 29d20d7987d..ad15e322152 100644 --- a/.sha256sum +++ b/.sha256sum @@ -5,4 +5,4 @@ b1f1de0fe40d05de90742b17928968923b936adc294000f58974f50a297581dd swagger/redhat 01ba9562a8dac2824998ff0ad0d2465f79e6a66597bdb321e9409b9f2d12d222 swagger/redhatopenshift/resource-manager/Microsoft.RedHatOpenShift/stable/2023-04-01/redhatopenshift.json c023515341196746454c0ae7af077d40d3ec13f6b88b33cb558f0a7ab17a5a24 swagger/redhatopenshift/resource-manager/Microsoft.RedHatOpenShift/preview/2023-07-01-preview/redhatopenshift.json 440748951dd1c3b34b5ccbdcb7cd966e3b89490887a1f1d64429561fad789515 swagger/redhatopenshift/resource-manager/Microsoft.RedHatOpenShift/stable/2023-09-04/redhatopenshift.json -98b241e3225ff4bbe96f4046aea98dae06c2bac2cc0e25ab8d85583bfc7f1861 swagger/redhatopenshift/resource-manager/Microsoft.RedHatOpenShift/stable/2023-11-22/redhatopenshift.json +a1052ac8642527343815b212823c7c22f1edf9690b1004041b9ef6bab5b10393 swagger/redhatopenshift/resource-manager/Microsoft.RedHatOpenShift/stable/2023-11-22/redhatopenshift.json diff --git a/hack/licenses/main.go b/hack/licenses/main.go index 674504a69df..a90533d6bfa 100644 --- a/hack/licenses/main.go +++ b/hack/licenses/main.go @@ -106,7 +106,7 @@ func applyPythonLicense() error { } switch path { - case "python/client", "vendor": + case "python/client", "vendor", "python/az/aro/azext_aro/aaz": return filepath.SkipDir } diff --git a/pkg/api/v20231122/openshiftcluster.go b/pkg/api/v20231122/openshiftcluster.go index b2667b62b34..f405a94acd9 100644 --- a/pkg/api/v20231122/openshiftcluster.go +++ b/pkg/api/v20231122/openshiftcluster.go @@ -29,7 +29,7 @@ type OpenShiftCluster struct { Location string `json:"location,omitempty"` // SystemData - The system metadata relating to this resource - SystemData *SystemData `json:"systemData,omitempty"` + SystemData *SystemData `json:"systemData,omitempty" swagger:"readOnly"` // The resource tags. Tags Tags `json:"tags,omitempty" mutable:"true"` @@ -119,7 +119,7 @@ type ClusterProfile struct { // ConsoleProfile represents a console profile. type ConsoleProfile struct { // The URL to access the cluster console. - URL string `json:"url,omitempty"` + URL string `json:"url,omitempty" swagger:"readOnly"` } // ServicePrincipalProfile represents a service principal profile. @@ -249,10 +249,10 @@ type APIServerProfile struct { Visibility Visibility `json:"visibility,omitempty"` // The URL to access the cluster API server. - URL string `json:"url,omitempty"` + URL string `json:"url,omitempty" swagger:"readOnly"` // The IP of the cluster API server. - IP string `json:"ip,omitempty"` + IP string `json:"ip,omitempty" swagger:"readOnly"` } // Visibility represents visibility. @@ -273,7 +273,7 @@ type IngressProfile struct { Visibility Visibility `json:"visibility,omitempty"` // The IP of the ingress. - IP string `json:"ip,omitempty"` + IP string `json:"ip,omitempty" swagger:"readOnly"` } // CreatedByType by defines user type, which executed the request diff --git a/pkg/api/v20231122/openshiftcluster_convert.go b/pkg/api/v20231122/openshiftcluster_convert.go index 5fd8e44d96c..ab633f4d5e0 100644 --- a/pkg/api/v20231122/openshiftcluster_convert.go +++ b/pkg/api/v20231122/openshiftcluster_convert.go @@ -174,7 +174,9 @@ func (c openShiftClusterConverter) ToInternal(_oc interface{}, out *api.OpenShif out.Properties.ClusterProfile.Domain = oc.Properties.ClusterProfile.Domain out.Properties.ClusterProfile.Version = oc.Properties.ClusterProfile.Version out.Properties.ClusterProfile.ResourceGroupID = oc.Properties.ClusterProfile.ResourceGroupID - out.Properties.ConsoleProfile.URL = oc.Properties.ConsoleProfile.URL + if oc.Properties.ConsoleProfile.URL != "" { + out.Properties.ConsoleProfile.URL = oc.Properties.ConsoleProfile.URL + } out.Properties.ClusterProfile.FipsValidatedModules = api.FipsValidatedModules(oc.Properties.ClusterProfile.FipsValidatedModules) out.Properties.ServicePrincipalProfile.ClientID = oc.Properties.ServicePrincipalProfile.ClientID out.Properties.ServicePrincipalProfile.ClientSecret = api.SecureString(oc.Properties.ServicePrincipalProfile.ClientSecret) @@ -238,25 +240,33 @@ func (c openShiftClusterConverter) ToInternal(_oc interface{}, out *api.OpenShif } } out.Properties.APIServerProfile.Visibility = api.Visibility(oc.Properties.APIServerProfile.Visibility) - out.Properties.APIServerProfile.URL = oc.Properties.APIServerProfile.URL - out.Properties.APIServerProfile.IP = oc.Properties.APIServerProfile.IP + if oc.Properties.APIServerProfile.URL != "" { + out.Properties.APIServerProfile.URL = oc.Properties.APIServerProfile.URL + } + if oc.Properties.APIServerProfile.IP != "" { + out.Properties.APIServerProfile.IP = oc.Properties.APIServerProfile.IP + } out.Properties.IngressProfiles = nil if oc.Properties.IngressProfiles != nil { out.Properties.IngressProfiles = make([]api.IngressProfile, len(oc.Properties.IngressProfiles)) for i := range oc.Properties.IngressProfiles { out.Properties.IngressProfiles[i].Name = oc.Properties.IngressProfiles[i].Name out.Properties.IngressProfiles[i].Visibility = api.Visibility(oc.Properties.IngressProfiles[i].Visibility) - out.Properties.IngressProfiles[i].IP = oc.Properties.IngressProfiles[i].IP + if oc.Properties.IngressProfiles[i].IP != "" { + out.Properties.IngressProfiles[i].IP = oc.Properties.IngressProfiles[i].IP + } } } - out.SystemData = api.SystemData{ - CreatedBy: oc.SystemData.CreatedBy, - CreatedAt: oc.SystemData.CreatedAt, - CreatedByType: api.CreatedByType(oc.SystemData.CreatedByType), - LastModifiedBy: oc.SystemData.LastModifiedBy, - LastModifiedAt: oc.SystemData.LastModifiedAt, - LastModifiedByType: api.CreatedByType(oc.SystemData.CreatedByType), + if oc.SystemData != nil { + out.SystemData = api.SystemData{ + CreatedBy: oc.SystemData.CreatedBy, + CreatedAt: oc.SystemData.CreatedAt, + CreatedByType: api.CreatedByType(oc.SystemData.CreatedByType), + LastModifiedBy: oc.SystemData.LastModifiedBy, + LastModifiedAt: oc.SystemData.LastModifiedAt, + LastModifiedByType: api.CreatedByType(oc.SystemData.CreatedByType), + } } } diff --git a/pkg/api/v20231122/openshiftcluster_validatestatic_test.go b/pkg/api/v20231122/openshiftcluster_validatestatic_test.go index 03de661d722..0e875c60033 100644 --- a/pkg/api/v20231122/openshiftcluster_validatestatic_test.go +++ b/pkg/api/v20231122/openshiftcluster_validatestatic_test.go @@ -34,6 +34,11 @@ type testMode string const ( testModeCreate testMode = "Create" testModeUpdate testMode = "Update" + + consoleProfileUrl = "https://console-openshift-console.apps.cluster.location.aroapp.io/" + apiserverProfileUrl = "https://api.cluster.location.aroapp.io:6443/" + apiserverProfileIp = "1.2.3.4" + ingressProfileIp = "1.2.3.4" ) var ( @@ -44,12 +49,23 @@ func getResourceID(clusterName string) string { return fmt.Sprintf("/subscriptions/%s/resourcegroups/resourceGroup/providers/microsoft.redhatopenshift/openshiftclusters/%s", subscriptionID, clusterName) } -func validOpenShiftCluster(name, location string) *OpenShiftCluster { +func validSystemData() *SystemData { timestamp, err := time.Parse(time.RFC3339, "2021-01-23T12:34:54.0000000Z") if err != nil { panic(err) } + return &SystemData{ + CreatedBy: "00000000-0000-0000-0000-000000000000", + CreatedByType: CreatedByTypeApplication, + CreatedAt: ×tamp, + LastModifiedBy: "00000000-0000-0000-0000-000000000000", + LastModifiedByType: CreatedByTypeApplication, + LastModifiedAt: ×tamp, + } +} + +func validOpenShiftCluster(name, location string) *OpenShiftCluster { oc := &OpenShiftCluster{ ID: getResourceID(name), Name: name, @@ -58,14 +74,6 @@ func validOpenShiftCluster(name, location string) *OpenShiftCluster { Tags: Tags{ "key": "value", }, - SystemData: &SystemData{ - CreatedBy: "00000000-0000-0000-0000-000000000000", - CreatedByType: CreatedByTypeApplication, - CreatedAt: ×tamp, - LastModifiedBy: "00000000-0000-0000-0000-000000000000", - LastModifiedByType: CreatedByTypeApplication, - LastModifiedAt: ×tamp, - }, Properties: OpenShiftClusterProperties{ ProvisioningState: ProvisioningStateSucceeded, ClusterProfile: ClusterProfile{ @@ -76,7 +84,7 @@ func validOpenShiftCluster(name, location string) *OpenShiftCluster { FipsValidatedModules: FipsValidatedModulesDisabled, }, ConsoleProfile: ConsoleProfile{ - URL: "https://console-openshift-console.apps.cluster.location.aroapp.io/", + URL: "", }, ServicePrincipalProfile: ServicePrincipalProfile{ ClientSecret: "clientSecret", @@ -109,14 +117,14 @@ func validOpenShiftCluster(name, location string) *OpenShiftCluster { }, APIServerProfile: APIServerProfile{ Visibility: VisibilityPublic, - URL: "https://api.cluster.location.aroapp.io:6443/", - IP: "1.2.3.4", + URL: "", + IP: "", }, IngressProfiles: []IngressProfile{ { Name: "default", Visibility: VisibilityPublic, - IP: "1.2.3.4", + IP: "", }, }, }, @@ -168,7 +176,15 @@ func runTests(t *testing.T, mode testMode, tests []*validateTest) { var current *api.OpenShiftCluster if mode == testModeUpdate { current = &api.OpenShiftCluster{} - (&openShiftClusterConverter{}).ToInternal(validOCForTest(), current) + + ext := validOCForTest() + ext.SystemData = validSystemData() + ext.Properties.ConsoleProfile.URL = consoleProfileUrl + ext.Properties.APIServerProfile.URL = apiserverProfileUrl + ext.Properties.APIServerProfile.IP = apiserverProfileIp + ext.Properties.IngressProfiles[0].IP = ingressProfileIp + + (&openShiftClusterConverter{}).ToInternal(ext, current) } err := v.Static(oc, current, v.location, v.domain, tt.requireD2sV3Workers, v.resourceID) @@ -1075,14 +1091,15 @@ func TestOpenShiftClusterStaticValidateDelta(t *testing.T) { modify: func(oc *OpenShiftCluster) { oc.SystemData = &SystemData{} }, - wantErr: "400: PropertyChangeNotAllowed: systemData.createdBy: Changing property 'systemData.createdBy' is not allowed.", + wantErr: "400: PropertyChangeNotAllowed: systemData: Changing property 'systemData' is not allowed.", }, { name: "systemData LastUpdated changed", modify: func(oc *OpenShiftCluster) { + oc.SystemData = &SystemData{} oc.SystemData.LastModifiedBy = "Bob" }, - wantErr: "400: PropertyChangeNotAllowed: systemData.lastModifiedBy: Changing property 'systemData.lastModifiedBy' is not allowed.", + wantErr: "400: PropertyChangeNotAllowed: systemData: Changing property 'systemData' is not allowed.", }, { name: "update LoadBalancerProfile.ManagedOutboundIPs.Count", diff --git a/pkg/client/services/redhatopenshift/mgmt/2023-11-22/redhatopenshift/models.go b/pkg/client/services/redhatopenshift/mgmt/2023-11-22/redhatopenshift/models.go index 0b52821a121..57302d8e1ea 100644 --- a/pkg/client/services/redhatopenshift/mgmt/2023-11-22/redhatopenshift/models.go +++ b/pkg/client/services/redhatopenshift/mgmt/2023-11-22/redhatopenshift/models.go @@ -36,12 +36,21 @@ const fqdn = "github.com/Azure/ARO-RP/pkg/client/services/redhatopenshift/mgmt/2 type APIServerProfile struct { // Visibility - API server visibility. Possible values include: 'Private', 'Public' Visibility Visibility `json:"visibility,omitempty"` - // URL - The URL to access the cluster API server. + // URL - READ-ONLY; The URL to access the cluster API server. URL *string `json:"url,omitempty"` - // IP - The IP of the cluster API server. + // IP - READ-ONLY; The IP of the cluster API server. IP *string `json:"ip,omitempty"` } +// MarshalJSON is the custom marshaler for APIServerProfile. +func (asp APIServerProfile) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if asp.Visibility != "" { + objectMap["visibility"] = asp.Visibility + } + return json.Marshal(objectMap) +} + // AzureEntityResource the resource model definition for an Azure Resource Manager resource with an etag. type AzureEntityResource struct { // Etag - READ-ONLY; Resource Etag. @@ -96,10 +105,16 @@ type ClusterProfile struct { // ConsoleProfile consoleProfile represents a console profile. type ConsoleProfile struct { - // URL - The URL to access the cluster console. + // URL - READ-ONLY; The URL to access the cluster console. URL *string `json:"url,omitempty"` } +// MarshalJSON is the custom marshaler for ConsoleProfile. +func (cp ConsoleProfile) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + return json.Marshal(objectMap) +} + // Display display represents the display details of an operation. type Display struct { // Provider - Friendly name of the resource provider. @@ -125,10 +140,22 @@ type IngressProfile struct { Name *string `json:"name,omitempty"` // Visibility - Ingress visibility. Possible values include: 'Private', 'Public' Visibility Visibility `json:"visibility,omitempty"` - // IP - The IP of the ingress. + // IP - READ-ONLY; The IP of the ingress. IP *string `json:"ip,omitempty"` } +// MarshalJSON is the custom marshaler for IngressProfile. +func (IP IngressProfile) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if IP.Name != nil { + objectMap["name"] = IP.Name + } + if IP.Visibility != "" { + objectMap["visibility"] = IP.Visibility + } + return json.Marshal(objectMap) +} + // LoadBalancerProfile loadBalancerProfile represents the profile of the cluster public load balancer. type LoadBalancerProfile struct { // ManagedOutboundIps - The desired managed outbound IPs for the cluster public load balancer. diff --git a/python/client/azure/mgmt/redhatopenshift/v2023_11_22/models/_models.py b/python/client/azure/mgmt/redhatopenshift/v2023_11_22/models/_models.py index b182f547a86..c6691d24c64 100644 --- a/python/client/azure/mgmt/redhatopenshift/v2023_11_22/models/_models.py +++ b/python/client/azure/mgmt/redhatopenshift/v2023_11_22/models/_models.py @@ -20,6 +20,8 @@ class APIServerProfile(msrest.serialization.Model): """APIServerProfile represents an API server profile. + Variables are only populated by the server, and will be ignored when sending a request. + :ivar visibility: API server visibility. Possible values include: "Private", "Public". :vartype visibility: str or ~azure.mgmt.redhatopenshift.v2023_11_22.models.Visibility :ivar url: The URL to access the cluster API server. @@ -28,6 +30,11 @@ class APIServerProfile(msrest.serialization.Model): :vartype ip: str """ + _validation = { + 'url': {'readonly': True}, + 'ip': {'readonly': True}, + } + _attribute_map = { 'visibility': {'key': 'visibility', 'type': 'str'}, 'url': {'key': 'url', 'type': 'str'}, @@ -41,15 +48,11 @@ def __init__( """ :keyword visibility: API server visibility. Possible values include: "Private", "Public". :paramtype visibility: str or ~azure.mgmt.redhatopenshift.v2023_11_22.models.Visibility - :keyword url: The URL to access the cluster API server. - :paramtype url: str - :keyword ip: The IP of the cluster API server. - :paramtype ip: str """ super(APIServerProfile, self).__init__(**kwargs) self.visibility = kwargs.get('visibility', None) - self.url = kwargs.get('url', None) - self.ip = kwargs.get('ip', None) + self.url = None + self.ip = None class CloudErrorBody(msrest.serialization.Model): @@ -153,10 +156,16 @@ def __init__( class ConsoleProfile(msrest.serialization.Model): """ConsoleProfile represents a console profile. + Variables are only populated by the server, and will be ignored when sending a request. + :ivar url: The URL to access the cluster console. :vartype url: str """ + _validation = { + 'url': {'readonly': True}, + } + _attribute_map = { 'url': {'key': 'url', 'type': 'str'}, } @@ -166,11 +175,9 @@ def __init__( **kwargs ): """ - :keyword url: The URL to access the cluster console. - :paramtype url: str """ super(ConsoleProfile, self).__init__(**kwargs) - self.url = kwargs.get('url', None) + self.url = None class Display(msrest.serialization.Model): @@ -240,6 +247,8 @@ def __init__( class IngressProfile(msrest.serialization.Model): """IngressProfile represents an ingress profile. + Variables are only populated by the server, and will be ignored when sending a request. + :ivar name: The ingress profile name. :vartype name: str :ivar visibility: Ingress visibility. Possible values include: "Private", "Public". @@ -248,6 +257,10 @@ class IngressProfile(msrest.serialization.Model): :vartype ip: str """ + _validation = { + 'ip': {'readonly': True}, + } + _attribute_map = { 'name': {'key': 'name', 'type': 'str'}, 'visibility': {'key': 'visibility', 'type': 'str'}, @@ -263,13 +276,11 @@ def __init__( :paramtype name: str :keyword visibility: Ingress visibility. Possible values include: "Private", "Public". :paramtype visibility: str or ~azure.mgmt.redhatopenshift.v2023_11_22.models.Visibility - :keyword ip: The IP of the ingress. - :paramtype ip: str """ super(IngressProfile, self).__init__(**kwargs) self.name = kwargs.get('name', None) self.visibility = kwargs.get('visibility', None) - self.ip = kwargs.get('ip', None) + self.ip = None class LoadBalancerProfile(msrest.serialization.Model): diff --git a/python/client/azure/mgmt/redhatopenshift/v2023_11_22/models/_models_py3.py b/python/client/azure/mgmt/redhatopenshift/v2023_11_22/models/_models_py3.py index 97c198d0319..e881c9c36b3 100644 --- a/python/client/azure/mgmt/redhatopenshift/v2023_11_22/models/_models_py3.py +++ b/python/client/azure/mgmt/redhatopenshift/v2023_11_22/models/_models_py3.py @@ -25,6 +25,8 @@ class APIServerProfile(msrest.serialization.Model): """APIServerProfile represents an API server profile. + Variables are only populated by the server, and will be ignored when sending a request. + :ivar visibility: API server visibility. Possible values include: "Private", "Public". :vartype visibility: str or ~azure.mgmt.redhatopenshift.v2023_11_22.models.Visibility :ivar url: The URL to access the cluster API server. @@ -33,6 +35,11 @@ class APIServerProfile(msrest.serialization.Model): :vartype ip: str """ + _validation = { + 'url': {'readonly': True}, + 'ip': {'readonly': True}, + } + _attribute_map = { 'visibility': {'key': 'visibility', 'type': 'str'}, 'url': {'key': 'url', 'type': 'str'}, @@ -43,22 +50,16 @@ def __init__( self, *, visibility: Optional[Union[str, "Visibility"]] = None, - url: Optional[str] = None, - ip: Optional[str] = None, **kwargs ): """ :keyword visibility: API server visibility. Possible values include: "Private", "Public". :paramtype visibility: str or ~azure.mgmt.redhatopenshift.v2023_11_22.models.Visibility - :keyword url: The URL to access the cluster API server. - :paramtype url: str - :keyword ip: The IP of the cluster API server. - :paramtype ip: str """ super(APIServerProfile, self).__init__(**kwargs) self.visibility = visibility - self.url = url - self.ip = ip + self.url = None + self.ip = None class CloudErrorBody(msrest.serialization.Model): @@ -173,26 +174,28 @@ def __init__( class ConsoleProfile(msrest.serialization.Model): """ConsoleProfile represents a console profile. + Variables are only populated by the server, and will be ignored when sending a request. + :ivar url: The URL to access the cluster console. :vartype url: str """ + _validation = { + 'url': {'readonly': True}, + } + _attribute_map = { 'url': {'key': 'url', 'type': 'str'}, } def __init__( self, - *, - url: Optional[str] = None, **kwargs ): """ - :keyword url: The URL to access the cluster console. - :paramtype url: str """ super(ConsoleProfile, self).__init__(**kwargs) - self.url = url + self.url = None class Display(msrest.serialization.Model): @@ -269,6 +272,8 @@ def __init__( class IngressProfile(msrest.serialization.Model): """IngressProfile represents an ingress profile. + Variables are only populated by the server, and will be ignored when sending a request. + :ivar name: The ingress profile name. :vartype name: str :ivar visibility: Ingress visibility. Possible values include: "Private", "Public". @@ -277,6 +282,10 @@ class IngressProfile(msrest.serialization.Model): :vartype ip: str """ + _validation = { + 'ip': {'readonly': True}, + } + _attribute_map = { 'name': {'key': 'name', 'type': 'str'}, 'visibility': {'key': 'visibility', 'type': 'str'}, @@ -288,7 +297,6 @@ def __init__( *, name: Optional[str] = None, visibility: Optional[Union[str, "Visibility"]] = None, - ip: Optional[str] = None, **kwargs ): """ @@ -296,13 +304,11 @@ def __init__( :paramtype name: str :keyword visibility: Ingress visibility. Possible values include: "Private", "Public". :paramtype visibility: str or ~azure.mgmt.redhatopenshift.v2023_11_22.models.Visibility - :keyword ip: The IP of the ingress. - :paramtype ip: str """ super(IngressProfile, self).__init__(**kwargs) self.name = name self.visibility = visibility - self.ip = ip + self.ip = None class LoadBalancerProfile(msrest.serialization.Model): diff --git a/swagger/redhatopenshift/resource-manager/Microsoft.RedHatOpenShift/stable/2023-11-22/redhatopenshift.json b/swagger/redhatopenshift/resource-manager/Microsoft.RedHatOpenShift/stable/2023-11-22/redhatopenshift.json index ef92b1dd5a7..31bca4cdb9f 100644 --- a/swagger/redhatopenshift/resource-manager/Microsoft.RedHatOpenShift/stable/2023-11-22/redhatopenshift.json +++ b/swagger/redhatopenshift/resource-manager/Microsoft.RedHatOpenShift/stable/2023-11-22/redhatopenshift.json @@ -1744,11 +1744,13 @@ }, "url": { "description": "The URL to access the cluster API server.", - "type": "string" + "type": "string", + "readOnly": true }, "ip": { "description": "The IP of the cluster API server.", - "type": "string" + "type": "string", + "readOnly": true } } }, @@ -1820,7 +1822,8 @@ "properties": { "url": { "description": "The URL to access the cluster console.", - "type": "string" + "type": "string", + "readOnly": true } } }, @@ -1894,7 +1897,8 @@ }, "ip": { "description": "The IP of the ingress.", - "type": "string" + "type": "string", + "readOnly": true } } },