@@ -46,21 +46,22 @@ public struct NetworkConfiguration: Codable, Sendable, Identifiable {
4646 public let ipv6Subnet : CIDRv6 ?
4747
4848 /// Key-value labels for the network.
49- public var labels : [ String : String ] = [ : ]
49+ /// Resource labels should not be mutated, except while building a network configurations.
50+ public let labels : ResourceLabels
5051
5152 /// Details about the network plugin that manages this network.
5253 /// FIXME: This field only needs to be optional while we wait for the field
5354 /// to be proliferated to most users when they update container.
54- public var pluginInfo : NetworkPluginInfo ?
55+ public let pluginInfo : NetworkPluginInfo ?
5556
5657 /// Creates a network configuration
5758 public init (
5859 id: String ,
5960 mode: NetworkMode ,
6061 ipv4Subnet: CIDRv4 ? = nil ,
6162 ipv6Subnet: CIDRv6 ? = nil ,
62- labels: [ String : String ] = [ : ] ,
63- pluginInfo: NetworkPluginInfo
63+ labels: ResourceLabels = . init ( ) ,
64+ pluginInfo: NetworkPluginInfo ?
6465 ) throws {
6566 self . id = id
6667 self . creationDate = Date ( )
@@ -98,7 +99,8 @@ public struct NetworkConfiguration: Codable, Sendable, Identifiable {
9899 ipv4Subnet = try subnetText. map { try CIDRv4 ( $0) }
99100 ipv6Subnet = try container. decodeIfPresent ( String . self, forKey: . ipv6Subnet)
100101 . map { try CIDRv6 ( $0) }
101- labels = try container. decodeIfPresent ( [ String : String ] . self, forKey: . labels) ?? [ : ]
102+ let decodedLabels = try container. decodeIfPresent ( [ String : String ] . self, forKey: . labels) ?? [ : ]
103+ labels = try . init( decodedLabels)
102104 pluginInfo = try container. decodeIfPresent ( NetworkPluginInfo . self, forKey: . pluginInfo)
103105 try validate ( )
104106 }
@@ -120,28 +122,6 @@ public struct NetworkConfiguration: Codable, Sendable, Identifiable {
120122 guard id. isValidNetworkID ( ) else {
121123 throw ContainerizationError ( . invalidArgument, message: " invalid network ID: \( id) " )
122124 }
123-
124- for (key, value) in labels {
125- try validateLabel ( key: key, value: value)
126- }
127- }
128-
129- /// TODO: Extract when we clean up client dependencies.
130- private func validateLabel( key: String , value: String ) throws {
131- let keyLengthMax = 128
132- let labelLengthMax = 4096
133- guard key. count <= keyLengthMax else {
134- throw ContainerizationError ( . invalidArgument, message: " invalid label, key length is greater than \( keyLengthMax) : \( key) " )
135- }
136-
137- guard key. isValidLabelKey ( ) else {
138- throw ContainerizationError ( . invalidArgument, message: " invalid label key: \( key) " )
139- }
140-
141- let fullLabel = " \( key) = \( value) "
142- guard fullLabel. count <= labelLengthMax else {
143- throw ContainerizationError ( . invalidArgument, message: " invalid label, key length is greater than \( labelLengthMax) : \( fullLabel) " )
144- }
145125 }
146126}
147127
@@ -151,14 +131,4 @@ extension String {
151131 let pattern = #"^[a-z0-9](?:[a-z0-9._-]{0,61}[a-z0-9])?$"#
152132 return self . range ( of: pattern, options: . regularExpression) != nil
153133 }
154-
155- /// Ensure label key conforms to OCI or Docker label guidelines.
156- /// TODO: Extract when we clean up client dependencies.
157- fileprivate func isValidLabelKey( ) -> Bool {
158- let dockerPattern = #/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)*$/#
159- let ociPattern = #/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)*(?:/(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)*))*$/#
160- let dockerMatch = !self . ranges ( of: dockerPattern) . isEmpty
161- let ociMatch = !self . ranges ( of: ociPattern) . isEmpty
162- return dockerMatch || ociMatch
163- }
164134}
0 commit comments