)]}'
{"metropolis/node/labels.go":[{"author":{"_account_id":1000038,"name":"Jan Schär","display_name":"Jan","email":"jan@monogon.tech","username":"jan","avatars":[{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"e086b3e4be1a566ce7441b84184fa1181ab57035","unresolved":true,"context_lines":[{"line_number":71,"context_line":"// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT"},{"line_number":72,"context_line":"// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE"},{"line_number":73,"context_line":"// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."},{"line_number":74,"context_line":"func isDomainName(s string) bool {"},{"line_number":75,"context_line":"\t// The root domain name is valid. See golang.org/issue/45715."},{"line_number":76,"context_line":"\tif s \u003d\u003d \".\" {"},{"line_number":77,"context_line":"\t\treturn true"}],"source_content_type":"text/x-go","patch_set":1,"id":"d823ccb7_1407f000","line":74,"range":{"start_line":74,"start_character":5,"end_line":74,"end_character":17},"updated":"2024-10-01 17:23:42.000000000","message":"This check does not match how Kubernetes validates labels. It is stricter in some ways and looser in others. Because we want to sync labels to Kubernetes, it would make sense to make the validation exactly the same, or at least stricter, such that any valid metropolis label is also a valid Kubernetes label.\n\nHere is how Kubernetes validates labels: https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1/validation#ValidateLabels\nLabel prefixes are validated with this function: https://pkg.go.dev/k8s.io/apimachinery/pkg/util/validation#IsDNS1123Subdomain\n\nSpecifically, the differences are:\n\n- This allows names to end with `.`, Kubernetes does not.\n- This allows names to contain underscores and uppercase letters, Kubernetes does not.\n- Kubernetes does not check that parts are at most 63 bytes (I would say this is a bug in Kubernetes though).\n- Kubernetes does not forbid names consisting only of dots and digits.","commit_id":"136852f1e424b232553a943633cdbccf6d670fc1"},{"author":{"_account_id":1000038,"name":"Jan Schär","display_name":"Jan","email":"jan@monogon.tech","username":"jan","avatars":[{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"6cfc4ec2ae89b423071580cae9a85f38094b0e78","unresolved":false,"context_lines":[{"line_number":71,"context_line":"// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT"},{"line_number":72,"context_line":"// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE"},{"line_number":73,"context_line":"// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."},{"line_number":74,"context_line":"func isDomainName(s string) bool {"},{"line_number":75,"context_line":"\t// The root domain name is valid. See golang.org/issue/45715."},{"line_number":76,"context_line":"\tif s \u003d\u003d \".\" {"},{"line_number":77,"context_line":"\t\treturn true"}],"source_content_type":"text/x-go","patch_set":1,"id":"49de0b0f_3c4a7b92","line":74,"range":{"start_line":74,"start_character":5,"end_line":74,"end_character":17},"in_reply_to":"3747b544_539d291f","updated":"2024-10-08 09:45:43.000000000","message":"I implemented a domain validation function in https://review.monogon.dev/c/monogon/+/3508 which accepts a subset of the domains accepted by Kubernetes. We could later use that for labels as well.","commit_id":"136852f1e424b232553a943633cdbccf6d670fc1"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"add2f4297f938c11f8f67fb68051c6ee2ada5817","unresolved":true,"context_lines":[{"line_number":71,"context_line":"// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT"},{"line_number":72,"context_line":"// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE"},{"line_number":73,"context_line":"// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."},{"line_number":74,"context_line":"func isDomainName(s string) bool {"},{"line_number":75,"context_line":"\t// The root domain name is valid. See golang.org/issue/45715."},{"line_number":76,"context_line":"\tif s \u003d\u003d \".\" {"},{"line_number":77,"context_line":"\t\treturn true"}],"source_content_type":"text/x-go","patch_set":1,"id":"3747b544_539d291f","line":74,"range":{"start_line":74,"start_character":5,"end_line":74,"end_character":17},"in_reply_to":"d823ccb7_1407f000","updated":"2024-10-07 17:25:44.000000000","message":"Right, at this point might as well just use their code. I don\u0027t like doing that, but the alternative (surgically implementing a subset of their validation logic) sounds even worse...","commit_id":"136852f1e424b232553a943633cdbccf6d670fc1"},{"author":{"_account_id":1000038,"name":"Jan Schär","display_name":"Jan","email":"jan@monogon.tech","username":"jan","avatars":[{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"e086b3e4be1a566ce7441b84184fa1181ab57035","unresolved":true,"context_lines":[{"line_number":151,"context_line":"// If it\u0027s valid, nil is returned. Otherwise, one of ErrLabelEmpty,"},{"line_number":152,"context_line":"// ErrLabelTooLong, ErrLabelInvalidFirstCharacter or ErrLabelInvalidCharacter is"},{"line_number":153,"context_line":"// returned."},{"line_number":154,"context_line":"func ValidateLabel(v string) error {"},{"line_number":155,"context_line":"\tif len(v) \u003d\u003d 0 {"},{"line_number":156,"context_line":"\t\treturn ErrLabelEmpty"},{"line_number":157,"context_line":"\t}"}],"source_content_type":"text/x-go","patch_set":1,"id":"2819831a_5240f423","line":154,"range":{"start_line":154,"start_character":5,"end_line":154,"end_character":18},"updated":"2024-10-01 17:23:42.000000000","message":"ValidateLabel is currently used for both keys and values, but prefixes should only be allowed for keys.","commit_id":"136852f1e424b232553a943633cdbccf6d670fc1"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"add2f4297f938c11f8f67fb68051c6ee2ada5817","unresolved":false,"context_lines":[{"line_number":151,"context_line":"// If it\u0027s valid, nil is returned. Otherwise, one of ErrLabelEmpty,"},{"line_number":152,"context_line":"// ErrLabelTooLong, ErrLabelInvalidFirstCharacter or ErrLabelInvalidCharacter is"},{"line_number":153,"context_line":"// returned."},{"line_number":154,"context_line":"func ValidateLabel(v string) error {"},{"line_number":155,"context_line":"\tif len(v) \u003d\u003d 0 {"},{"line_number":156,"context_line":"\t\treturn ErrLabelEmpty"},{"line_number":157,"context_line":"\t}"}],"source_content_type":"text/x-go","patch_set":1,"id":"d3dd90e4_1a38b881","line":154,"range":{"start_line":154,"start_character":5,"end_line":154,"end_character":18},"in_reply_to":"2819831a_5240f423","updated":"2024-10-07 17:25:44.000000000","message":"Done","commit_id":"136852f1e424b232553a943633cdbccf6d670fc1"},{"author":{"_account_id":1000038,"name":"Jan Schär","display_name":"Jan","email":"jan@monogon.tech","username":"jan","avatars":[{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"6cfc4ec2ae89b423071580cae9a85f38094b0e78","unresolved":true,"context_lines":[{"line_number":106,"context_line":"// ErrLabelInvalidFirstCharacter, ErrLabelInvalidCharacter, or"},{"line_number":107,"context_line":"// ErrLabelInvalidCharacter is returned."},{"line_number":108,"context_line":"func ValidateLabelValue(v string) error {"},{"line_number":109,"context_line":"\tif !reLabelFirstLast.MatchString(string(v[0])) {"},{"line_number":110,"context_line":"\t\treturn ErrLabelInvalidFirstCharacter"},{"line_number":111,"context_line":"\t}"},{"line_number":112,"context_line":"\tif !reLabelFirstLast.MatchString(string(v[len(v)-1])) {"}],"source_content_type":"text/x-go","patch_set":2,"id":"ae506195_b3200d95","line":109,"range":{"start_line":109,"start_character":41,"end_line":109,"end_character":45},"updated":"2024-10-08 09:45:43.000000000","message":"This will panic if the label is empty. We can allow empty values, but should still restrict the maximum length to 63 for compatibility with Kubernetes.","commit_id":"c03cc2f663a6fe200aead54a47c3489db417ffd8"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"58e42cc0c60703056c319661478391bc47f87f93","unresolved":false,"context_lines":[{"line_number":106,"context_line":"// ErrLabelInvalidFirstCharacter, ErrLabelInvalidCharacter, or"},{"line_number":107,"context_line":"// ErrLabelInvalidCharacter is returned."},{"line_number":108,"context_line":"func ValidateLabelValue(v string) error {"},{"line_number":109,"context_line":"\tif !reLabelFirstLast.MatchString(string(v[0])) {"},{"line_number":110,"context_line":"\t\treturn ErrLabelInvalidFirstCharacter"},{"line_number":111,"context_line":"\t}"},{"line_number":112,"context_line":"\tif !reLabelFirstLast.MatchString(string(v[len(v)-1])) {"}],"source_content_type":"text/x-go","patch_set":2,"id":"b69db6f5_ae04ab3a","line":109,"range":{"start_line":109,"start_character":41,"end_line":109,"end_character":45},"in_reply_to":"ae506195_b3200d95","updated":"2024-10-08 10:35:17.000000000","message":"Done","commit_id":"c03cc2f663a6fe200aead54a47c3489db417ffd8"},{"author":{"_account_id":1000038,"name":"Jan Schär","display_name":"Jan","email":"jan@monogon.tech","username":"jan","avatars":[{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"fc84fceee9e07bdafce34af3e35fee90bb12d0a3","unresolved":true,"context_lines":[{"line_number":109,"context_line":"\tif !reLabelFirstLast.MatchString(string(v[0])) {"},{"line_number":110,"context_line":"\t\treturn ErrLabelInvalidFirstCharacter"},{"line_number":111,"context_line":"\t}"},{"line_number":112,"context_line":"\tif !reLabelFirstLast.MatchString(string(v[len(v)-1])) {"},{"line_number":113,"context_line":"\t\treturn ErrLabelInvalidLastCharacter"},{"line_number":114,"context_line":"\t}"},{"line_number":115,"context_line":"\t// Body characters are a superset of the first/last characters, and we\u0027ve already"}],"source_content_type":"text/x-go","patch_set":2,"id":"59719153_0ce21020","line":112,"range":{"start_line":112,"start_character":1,"end_line":112,"end_character":56},"updated":"2024-10-08 12:03:33.000000000","message":"Why did you remove this? Kubernetes has this restriction for the last character also for label values. See https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#syntax-and-character-set","commit_id":"c03cc2f663a6fe200aead54a47c3489db417ffd8"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"128cbf287361f89b48f80110cba29c014676339d","unresolved":false,"context_lines":[{"line_number":109,"context_line":"\tif !reLabelFirstLast.MatchString(string(v[0])) {"},{"line_number":110,"context_line":"\t\treturn ErrLabelInvalidFirstCharacter"},{"line_number":111,"context_line":"\t}"},{"line_number":112,"context_line":"\tif !reLabelFirstLast.MatchString(string(v[len(v)-1])) {"},{"line_number":113,"context_line":"\t\treturn ErrLabelInvalidLastCharacter"},{"line_number":114,"context_line":"\t}"},{"line_number":115,"context_line":"\t// Body characters are a superset of the first/last characters, and we\u0027ve already"}],"source_content_type":"text/x-go","patch_set":2,"id":"8fb3fa40_16de51ec","line":112,"range":{"start_line":112,"start_character":1,"end_line":112,"end_character":56},"in_reply_to":"59719153_0ce21020","updated":"2024-10-14 13:25:06.000000000","message":"Grr, missed it, right.","commit_id":"c03cc2f663a6fe200aead54a47c3489db417ffd8"},{"author":{"_account_id":1000038,"name":"Jan Schär","display_name":"Jan","email":"jan@monogon.tech","username":"jan","avatars":[{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"940c3c6628296507dbe857c43fb064721d745e93","unresolved":true,"context_lines":[{"line_number":100,"context_line":"//"},{"line_number":101,"context_line":"//  1. 0 to 63 characters long (inclusive);"},{"line_number":102,"context_line":"//  2. Characters are all ASCII a-z A-Z 0-9 \u0027_\u0027, \u0027-\u0027 or \u0027.\u0027;"},{"line_number":103,"context_line":"//  3. The first character is ASCII a-z A-Z or 0-9."},{"line_number":104,"context_line":"//"},{"line_number":105,"context_line":"// If it\u0027s valid, nil is returned. Otherwise, one of ErrLabelTooLong,"},{"line_number":106,"context_line":"// ErrLabelInvalidFirstCharacter, or ErrLabelInvalidLastCharacter,"}],"source_content_type":"text/x-go","patch_set":5,"id":"0ad55fd5_86ff3834","line":103,"updated":"2024-10-15 09:07:41.000000000","message":"```suggestion\n//  3. The first character is ASCII a-z A-Z or 0-9.\n//  4. The last character is ASCII a-z A-Z or 0-9.\n```","commit_id":"3cde4e85ad88a42db0e84bbd3b4c2ee745a5488a"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"1f9227f3c3b35e6f927d2303ae3074f205b4d3fd","unresolved":false,"context_lines":[{"line_number":100,"context_line":"//"},{"line_number":101,"context_line":"//  1. 0 to 63 characters long (inclusive);"},{"line_number":102,"context_line":"//  2. Characters are all ASCII a-z A-Z 0-9 \u0027_\u0027, \u0027-\u0027 or \u0027.\u0027;"},{"line_number":103,"context_line":"//  3. The first character is ASCII a-z A-Z or 0-9."},{"line_number":104,"context_line":"//"},{"line_number":105,"context_line":"// If it\u0027s valid, nil is returned. Otherwise, one of ErrLabelTooLong,"},{"line_number":106,"context_line":"// ErrLabelInvalidFirstCharacter, or ErrLabelInvalidLastCharacter,"}],"source_content_type":"text/x-go","patch_set":5,"id":"d058c967_9c6531ab","line":103,"in_reply_to":"0ad55fd5_86ff3834","updated":"2024-10-15 11:49:30.000000000","message":"Done","commit_id":"3cde4e85ad88a42db0e84bbd3b4c2ee745a5488a"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"79530c4c520bdeef3494a2f968f621b13f09c942","unresolved":false,"context_lines":[{"line_number":100,"context_line":"//"},{"line_number":101,"context_line":"//  1. 0 to 63 characters long (inclusive);"},{"line_number":102,"context_line":"//  2. Characters are all ASCII a-z A-Z 0-9 \u0027_\u0027, \u0027-\u0027 or \u0027.\u0027;"},{"line_number":103,"context_line":"//  3. The first character is ASCII a-z A-Z or 0-9."},{"line_number":104,"context_line":"//"},{"line_number":105,"context_line":"// If it\u0027s valid, nil is returned. Otherwise, one of ErrLabelTooLong,"},{"line_number":106,"context_line":"// ErrLabelInvalidFirstCharacter, or ErrLabelInvalidLastCharacter,"}],"source_content_type":"text/x-go","patch_set":5,"id":"680ad0da_cbd93fd7","line":103,"in_reply_to":"9e84b05e_56154775","updated":"2024-10-22 12:07:57.000000000","message":"Actually, no, misread Gerrit. Go ahead!","commit_id":"3cde4e85ad88a42db0e84bbd3b4c2ee745a5488a"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"9ad7ff58b336d8b12798751f8e69b7e16d406bbb","unresolved":false,"context_lines":[{"line_number":100,"context_line":"//"},{"line_number":101,"context_line":"//  1. 0 to 63 characters long (inclusive);"},{"line_number":102,"context_line":"//  2. Characters are all ASCII a-z A-Z 0-9 \u0027_\u0027, \u0027-\u0027 or \u0027.\u0027;"},{"line_number":103,"context_line":"//  3. The first character is ASCII a-z A-Z or 0-9."},{"line_number":104,"context_line":"//"},{"line_number":105,"context_line":"// If it\u0027s valid, nil is returned. Otherwise, one of ErrLabelTooLong,"},{"line_number":106,"context_line":"// ErrLabelInvalidFirstCharacter, or ErrLabelInvalidLastCharacter,"}],"source_content_type":"text/x-go","patch_set":5,"id":"9e84b05e_56154775","line":103,"in_reply_to":"d058c967_9c6531ab","updated":"2024-10-22 12:06:49.000000000","message":"Actually not, whoops, wait.","commit_id":"3cde4e85ad88a42db0e84bbd3b4c2ee745a5488a"},{"author":{"_account_id":1000038,"name":"Jan Schär","display_name":"Jan","email":"jan@monogon.tech","username":"jan","avatars":[{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"3fad5ecafda895f6d2c9f78f4c2aaf17f6fef240","unresolved":true,"context_lines":[{"line_number":61,"context_line":"// ErrLabelTooLong, ErrLabelInvalidFirstCharacter or ErrLabelInvalidCharacter is"},{"line_number":62,"context_line":"// returned."},{"line_number":63,"context_line":"func ValidateLabelKey(v string) error {"},{"line_number":64,"context_line":"\tif len(v) \u003d\u003d 0 {"},{"line_number":65,"context_line":"\t\treturn ErrLabelEmpty"},{"line_number":66,"context_line":"\t}"},{"line_number":67,"context_line":""}],"source_content_type":"text/x-go","patch_set":6,"id":"25097083_bc1c0c6d","line":64,"range":{"start_line":64,"start_character":1,"end_line":64,"end_character":17},"updated":"2024-10-28 12:53:28.000000000","message":"This check should be moved after splitting away the prefix. Otherwise, a label key like `example.com/` will cause a panic at `v[0]`.","commit_id":"8a8342aa7c6f2a9b1d2ec01ddbd21279a92cf2e5"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"0ddcd3fe093e4bd98826750c52a321d9aec8f2f2","unresolved":false,"context_lines":[{"line_number":61,"context_line":"// ErrLabelTooLong, ErrLabelInvalidFirstCharacter or ErrLabelInvalidCharacter is"},{"line_number":62,"context_line":"// returned."},{"line_number":63,"context_line":"func ValidateLabelKey(v string) error {"},{"line_number":64,"context_line":"\tif len(v) \u003d\u003d 0 {"},{"line_number":65,"context_line":"\t\treturn ErrLabelEmpty"},{"line_number":66,"context_line":"\t}"},{"line_number":67,"context_line":""}],"source_content_type":"text/x-go","patch_set":6,"id":"6707d059_0d869d31","line":64,"range":{"start_line":64,"start_character":1,"end_line":64,"end_character":17},"in_reply_to":"25097083_bc1c0c6d","updated":"2024-10-28 13:01:18.000000000","message":"Copied it below to avoid the panic, but also left it in this spot, so that an empty label throws an ErrLabelEmpty instead of ErrLabelInvalidPrefix (as Split(\"\", \"/\") returns an empty list).","commit_id":"8a8342aa7c6f2a9b1d2ec01ddbd21279a92cf2e5"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"75d2577f985d443fafdfa24ab9df3962c2c01255","unresolved":true,"context_lines":[{"line_number":61,"context_line":"// ErrLabelTooLong, ErrLabelInvalidFirstCharacter or ErrLabelInvalidCharacter is"},{"line_number":62,"context_line":"// returned."},{"line_number":63,"context_line":"func ValidateLabelKey(v string) error {"},{"line_number":64,"context_line":"\tif len(v) \u003d\u003d 0 {"},{"line_number":65,"context_line":"\t\treturn ErrLabelEmpty"},{"line_number":66,"context_line":"\t}"},{"line_number":67,"context_line":""}],"source_content_type":"text/x-go","patch_set":6,"id":"cd5fc7c8_07dff574","line":64,"range":{"start_line":64,"start_character":1,"end_line":64,"end_character":17},"in_reply_to":"38ab91e6_bf419a49","updated":"2024-10-28 13:38:14.000000000","message":"(I also added a testcase for `example.com/` if that\u0027s what you meant)","commit_id":"8a8342aa7c6f2a9b1d2ec01ddbd21279a92cf2e5"},{"author":{"_account_id":1000038,"name":"Jan Schär","display_name":"Jan","email":"jan@monogon.tech","username":"jan","avatars":[{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"07d25f9bfe6be22f7852abd233e87e1dac5a5d47","unresolved":true,"context_lines":[{"line_number":61,"context_line":"// ErrLabelTooLong, ErrLabelInvalidFirstCharacter or ErrLabelInvalidCharacter is"},{"line_number":62,"context_line":"// returned."},{"line_number":63,"context_line":"func ValidateLabelKey(v string) error {"},{"line_number":64,"context_line":"\tif len(v) \u003d\u003d 0 {"},{"line_number":65,"context_line":"\t\treturn ErrLabelEmpty"},{"line_number":66,"context_line":"\t}"},{"line_number":67,"context_line":""}],"source_content_type":"text/x-go","patch_set":6,"id":"bc858d62_c8bf309d","line":64,"range":{"start_line":64,"start_character":1,"end_line":64,"end_character":17},"in_reply_to":"6707d059_0d869d31","updated":"2024-10-28 13:10:15.000000000","message":"But `Split(\"\", \"/\")` does not return the empty list, it returns a list of length 1 containing the empty string. So the first check is not needed.\n\nPlease also add a test case for this.","commit_id":"8a8342aa7c6f2a9b1d2ec01ddbd21279a92cf2e5"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"709717d01ac270c34ca616667715f228ff6e5a80","unresolved":true,"context_lines":[{"line_number":61,"context_line":"// ErrLabelTooLong, ErrLabelInvalidFirstCharacter or ErrLabelInvalidCharacter is"},{"line_number":62,"context_line":"// returned."},{"line_number":63,"context_line":"func ValidateLabelKey(v string) error {"},{"line_number":64,"context_line":"\tif len(v) \u003d\u003d 0 {"},{"line_number":65,"context_line":"\t\treturn ErrLabelEmpty"},{"line_number":66,"context_line":"\t}"},{"line_number":67,"context_line":""}],"source_content_type":"text/x-go","patch_set":6,"id":"38ab91e6_bf419a49","line":64,"range":{"start_line":64,"start_character":1,"end_line":64,"end_character":17},"in_reply_to":"bc858d62_c8bf309d","updated":"2024-10-28 13:31:19.000000000","message":"Oh yeah, you\u0027re right (I just looked at a +%v which showed [], forgot that this can be a [\"\"]...). There\u0027s already a test case for this.","commit_id":"8a8342aa7c6f2a9b1d2ec01ddbd21279a92cf2e5"},{"author":{"_account_id":1000038,"name":"Jan Schär","display_name":"Jan","email":"jan@monogon.tech","username":"jan","avatars":[{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"55e566050b442bf615262b3bcb853e2f72b37c4a","unresolved":false,"context_lines":[{"line_number":61,"context_line":"// ErrLabelTooLong, ErrLabelInvalidFirstCharacter or ErrLabelInvalidCharacter is"},{"line_number":62,"context_line":"// returned."},{"line_number":63,"context_line":"func ValidateLabelKey(v string) error {"},{"line_number":64,"context_line":"\tif len(v) \u003d\u003d 0 {"},{"line_number":65,"context_line":"\t\treturn ErrLabelEmpty"},{"line_number":66,"context_line":"\t}"},{"line_number":67,"context_line":""}],"source_content_type":"text/x-go","patch_set":6,"id":"3cd1a86d_071bc586","line":64,"range":{"start_line":64,"start_character":1,"end_line":64,"end_character":17},"in_reply_to":"cd5fc7c8_07dff574","updated":"2024-10-28 13:56:01.000000000","message":"Done","commit_id":"8a8342aa7c6f2a9b1d2ec01ddbd21279a92cf2e5"}],"metropolis/node/labels_test.go":[{"author":{"_account_id":1000038,"name":"Jan Schär","display_name":"Jan","email":"jan@monogon.tech","username":"jan","avatars":[{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/fd0e7f48847aa0e46c8f361df2d6c26b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"fc84fceee9e07bdafce34af3e35fee90bb12d0a3","unresolved":true,"context_lines":[{"line_number":31,"context_line":"\t}"},{"line_number":32,"context_line":"}"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"func TestValidateLabelValue(t *testing.T) {"},{"line_number":35,"context_line":"\tfor i, te :\u003d range []struct {"},{"line_number":36,"context_line":"\t\tin   string"},{"line_number":37,"context_line":"\t\twant error"}],"source_content_type":"text/x-go","patch_set":3,"id":"157449f4_85c95eaa","line":34,"range":{"start_line":34,"start_character":5,"end_line":34,"end_character":27},"updated":"2024-10-08 12:03:33.000000000","message":"Because we want labels to be compatible with Kubernetes, you could actually test here that a valid label value according to ValidateLabelValue is also valid according to https://pkg.go.dev/k8s.io/apimachinery/pkg/util/validation#IsValidLabelValue\n\nSomething like this:\n\n```\n\t\tif ValidateLabelValue(te.in) \u003d\u003d nil {\n\t\t\tif errs :\u003d validation.IsValidLabelValue(te.in); len(errs) \u003e 0 {\n\t\t\t\tt.Errorf(\"%q: is not a valid Kubernetes label value: %v\", te.in, errs)\n\t\t\t}\n\t\t}\n```","commit_id":"2825e4c29d36769bdf39f70727ce149e2131ad67"},{"author":{"_account_id":1000002,"name":"Serge Bazanski","display_name":"Serge","email":"serge@monogon.tech","username":"serge","avatars":[{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/52c41428b6369f2c02b9717425216f7d.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"128cbf287361f89b48f80110cba29c014676339d","unresolved":false,"context_lines":[{"line_number":31,"context_line":"\t}"},{"line_number":32,"context_line":"}"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"func TestValidateLabelValue(t *testing.T) {"},{"line_number":35,"context_line":"\tfor i, te :\u003d range []struct {"},{"line_number":36,"context_line":"\t\tin   string"},{"line_number":37,"context_line":"\t\twant error"}],"source_content_type":"text/x-go","patch_set":3,"id":"5b9aeed2_9d8879e0","line":34,"range":{"start_line":34,"start_character":5,"end_line":34,"end_character":27},"in_reply_to":"157449f4_85c95eaa","updated":"2024-10-14 13:25:06.000000000","message":"Done","commit_id":"2825e4c29d36769bdf39f70727ce149e2131ad67"}]}
