)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"3501e91806507de808d0fc0253d312789e5d29b1","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"f6f16415_1ec5ecfc","updated":"2021-06-24 12:51:33.000000000","message":"A few nits and some code organization which I think is suboptimal. Otherwise looks good.","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"da54141df76781c5bb47d18a5b5d4bb29f3237d5","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"c3ab1b6f_d0ae5f39","updated":"2021-07-06 10:53:20.000000000","message":"LGTM","commit_id":"77ffd52aa27139d51e75d86384e38265f206357f"}],"metropolis/node/core/curator/impl_leader.go":[{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"3501e91806507de808d0fc0253d312789e5d29b1","unresolved":true,"context_lines":[{"line_number":25,"context_line":"\tlockKey string"},{"line_number":26,"context_line":"\t// lockRev is the revision at which lockKey was created. The leader will use it"},{"line_number":27,"context_line":"\t// in combination with lockKey to ensure all mutations/reads performed to etcd"},{"line_number":28,"context_line":"\t// success only if this leader election is still valid."},{"line_number":29,"context_line":"\tlockRev int64"},{"line_number":30,"context_line":"\t// etcd is the etcd client in which curator data and leader election state is"},{"line_number":31,"context_line":"\t// stored."}],"source_content_type":"text/x-go","patch_set":5,"id":"b76d9c2a_6802ed52","line":28,"range":{"start_line":28,"start_character":50,"end_line":28,"end_character":55},"updated":"2021-06-24 12:51:33.000000000","message":"\u0027current\u0027?","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"3501e91806507de808d0fc0253d312789e5d29b1","unresolved":true,"context_lines":[{"line_number":25,"context_line":"\tlockKey string"},{"line_number":26,"context_line":"\t// lockRev is the revision at which lockKey was created. The leader will use it"},{"line_number":27,"context_line":"\t// in combination with lockKey to ensure all mutations/reads performed to etcd"},{"line_number":28,"context_line":"\t// success only if this leader election is still valid."},{"line_number":29,"context_line":"\tlockRev int64"},{"line_number":30,"context_line":"\t// etcd is the etcd client in which curator data and leader election state is"},{"line_number":31,"context_line":"\t// stored."}],"source_content_type":"text/x-go","patch_set":5,"id":"c73d883f_a4dec9cb","line":28,"range":{"start_line":28,"start_character":4,"end_line":28,"end_character":11},"updated":"2021-06-24 12:51:33.000000000","message":"\u0027succeed\u0027","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"},{"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":"ec323c5a5b73bc5d9f1198521eb9c29a6eae2984","unresolved":false,"context_lines":[{"line_number":25,"context_line":"\tlockKey string"},{"line_number":26,"context_line":"\t// lockRev is the revision at which lockKey was created. The leader will use it"},{"line_number":27,"context_line":"\t// in combination with lockKey to ensure all mutations/reads performed to etcd"},{"line_number":28,"context_line":"\t// success only if this leader election is still valid."},{"line_number":29,"context_line":"\tlockRev int64"},{"line_number":30,"context_line":"\t// etcd is the etcd client in which curator data and leader election state is"},{"line_number":31,"context_line":"\t// stored."}],"source_content_type":"text/x-go","patch_set":5,"id":"1e7965f9_bf280186","line":28,"range":{"start_line":28,"start_character":50,"end_line":28,"end_character":55},"in_reply_to":"b76d9c2a_6802ed52","updated":"2021-07-01 11:04:53.000000000","message":"Done","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"},{"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":"ec323c5a5b73bc5d9f1198521eb9c29a6eae2984","unresolved":false,"context_lines":[{"line_number":25,"context_line":"\tlockKey string"},{"line_number":26,"context_line":"\t// lockRev is the revision at which lockKey was created. The leader will use it"},{"line_number":27,"context_line":"\t// in combination with lockKey to ensure all mutations/reads performed to etcd"},{"line_number":28,"context_line":"\t// success only if this leader election is still valid."},{"line_number":29,"context_line":"\tlockRev int64"},{"line_number":30,"context_line":"\t// etcd is the etcd client in which curator data and leader election state is"},{"line_number":31,"context_line":"\t// stored."}],"source_content_type":"text/x-go","patch_set":5,"id":"302f9037_15c820f3","line":28,"range":{"start_line":28,"start_character":4,"end_line":28,"end_character":11},"in_reply_to":"c73d883f_a4dec9cb","updated":"2021-07-01 11:04:53.000000000","message":"Done","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"3501e91806507de808d0fc0253d312789e5d29b1","unresolved":true,"context_lines":[{"line_number":61,"context_line":"\t\treturn status.Error(codes.Unavailable, \"lost leadership\"), true"},{"line_number":62,"context_line":"\t}"},{"line_number":63,"context_line":"\tif errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {"},{"line_number":64,"context_line":"\t\treturn status.Errorf(codes.Unavailable, \"%v\", err), true"},{"line_number":65,"context_line":"\t}"},{"line_number":66,"context_line":"\treturn err, false"},{"line_number":67,"context_line":"}"}],"source_content_type":"text/x-go","patch_set":5,"id":"96e0d7b8_04c21ec1","line":64,"range":{"start_line":64,"start_character":23,"end_line":64,"end_character":40},"updated":"2021-06-24 12:51:33.000000000","message":"gRPC knows about DeadlineExceeded and Canceled, is there a good reason why we\u0027re converting them to Unavailable here?","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"},{"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":"ec323c5a5b73bc5d9f1198521eb9c29a6eae2984","unresolved":false,"context_lines":[{"line_number":61,"context_line":"\t\treturn status.Error(codes.Unavailable, \"lost leadership\"), true"},{"line_number":62,"context_line":"\t}"},{"line_number":63,"context_line":"\tif errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {"},{"line_number":64,"context_line":"\t\treturn status.Errorf(codes.Unavailable, \"%v\", err), true"},{"line_number":65,"context_line":"\t}"},{"line_number":66,"context_line":"\treturn err, false"},{"line_number":67,"context_line":"}"}],"source_content_type":"text/x-go","patch_set":5,"id":"d1123592_89d05419","line":64,"range":{"start_line":64,"start_character":23,"end_line":64,"end_character":40},"in_reply_to":"96e0d7b8_04c21ec1","updated":"2021-07-01 11:04:53.000000000","message":"You\u0027re right, I don\u0027t know why I was attempting to catch this.","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"3501e91806507de808d0fc0253d312789e5d29b1","unresolved":true,"context_lines":[{"line_number":67,"context_line":"}"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"func (l *curatorLeader) Watch(req *apb.WatchRequest, srv apb.Curator_WatchServer) error {"},{"line_number":70,"context_line":"\tnic, ok :\u003d req.Kind.(*apb.WatchRequest_NodeInCluster_)"},{"line_number":71,"context_line":"\tif !ok {"},{"line_number":72,"context_line":"\t\treturn status.Error(codes.Unimplemented, \"unsupported watch kind\")"},{"line_number":73,"context_line":"\t}"}],"source_content_type":"text/x-go","patch_set":5,"id":"11fc47a7_3178e758","line":70,"range":{"start_line":70,"start_character":53,"end_line":70,"end_character":54},"updated":"2021-06-24 12:51:33.000000000","message":"The underscore at the end looks like a typo, but the CI passes. Am I overlooking something or is this not being built?","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"},{"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":"ec323c5a5b73bc5d9f1198521eb9c29a6eae2984","unresolved":false,"context_lines":[{"line_number":67,"context_line":"}"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"func (l *curatorLeader) Watch(req *apb.WatchRequest, srv apb.Curator_WatchServer) error {"},{"line_number":70,"context_line":"\tnic, ok :\u003d req.Kind.(*apb.WatchRequest_NodeInCluster_)"},{"line_number":71,"context_line":"\tif !ok {"},{"line_number":72,"context_line":"\t\treturn status.Error(codes.Unimplemented, \"unsupported watch kind\")"},{"line_number":73,"context_line":"\t}"}],"source_content_type":"text/x-go","patch_set":5,"id":"e79fc884_84b32481","line":70,"range":{"start_line":70,"start_character":53,"end_line":70,"end_character":54},"in_reply_to":"11fc47a7_3178e758","updated":"2021-07-01 11:04:53.000000000","message":"It\u0027s not a typo, it\u0027s the name of the generated proto oneof type when a oneof member has the same name as a type contained in the parent proto message.\n\nUsually:\n\nmessage Foo {\n}\n\nmessage Bar {\n   oneof kind {\n      Foo foo \u003d 1;\n   }\n}\n\nwould yield Bar_Foo as the oneoff inner type name. However, if you move Foo inside Bar:\n\n\nmessage Bar {\n   message Foo {\n   }\n   oneof kind {\n      Foo foo \u003d 1;\n   }\n}\n\nthen the message type Foo is now Bar_Foo, and the oneof inner type is now Bar_Foo_.","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"3501e91806507de808d0fc0253d312789e5d29b1","unresolved":true,"context_lines":[{"line_number":76,"context_line":"\t// underneath the NodeEtcdPrefix. Worst case an attacker can do is request a node"},{"line_number":77,"context_line":"\t// that doesn\u0027t exist, and that will just hang . All access is privileged, so"},{"line_number":78,"context_line":"\t// there\u0027s also no need to filter anything."},{"line_number":79,"context_line":"\t// TODO(q3k): formalize and strongly etcd paths for cluster state? Probably"},{"line_number":80,"context_line":"\t// worth waiting for type parameters before attempting to do that."},{"line_number":81,"context_line":"\tnodePath :\u003d nodeEtcdPath(nodeID)"},{"line_number":82,"context_line":""}],"source_content_type":"text/x-go","patch_set":5,"id":"22b996c6_48052afe","line":79,"range":{"start_line":79,"start_character":29,"end_line":79,"end_character":38},"updated":"2021-06-24 12:51:33.000000000","message":"strongly ...","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"},{"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":"ec323c5a5b73bc5d9f1198521eb9c29a6eae2984","unresolved":false,"context_lines":[{"line_number":76,"context_line":"\t// underneath the NodeEtcdPrefix. Worst case an attacker can do is request a node"},{"line_number":77,"context_line":"\t// that doesn\u0027t exist, and that will just hang . All access is privileged, so"},{"line_number":78,"context_line":"\t// there\u0027s also no need to filter anything."},{"line_number":79,"context_line":"\t// TODO(q3k): formalize and strongly etcd paths for cluster state? Probably"},{"line_number":80,"context_line":"\t// worth waiting for type parameters before attempting to do that."},{"line_number":81,"context_line":"\tnodePath :\u003d nodeEtcdPath(nodeID)"},{"line_number":82,"context_line":""}],"source_content_type":"text/x-go","patch_set":5,"id":"3561745b_6bf61020","line":79,"range":{"start_line":79,"start_character":29,"end_line":79,"end_character":38},"in_reply_to":"22b996c6_48052afe","updated":"2021-07-01 11:04:53.000000000","message":"Done","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"}],"metropolis/node/core/curator/state_node.go":[{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"3501e91806507de808d0fc0253d312789e5d29b1","unresolved":true,"context_lines":[{"line_number":175,"context_line":"// current hostname, and local files like hosts and machine-id accordingly."},{"line_number":176,"context_line":"//"},{"line_number":177,"context_line":"// TODO(q3k): move this to roleserver?"},{"line_number":178,"context_line":"func (n *Node) ConfigureLocalHostname(ctx context.Context, ephemeral *localstorage.EphemeralDirectory, address net.IP) error {"},{"line_number":179,"context_line":"\tif err :\u003d unix.Sethostname([]byte(n.ID())); err !\u003d nil {"},{"line_number":180,"context_line":"\t\treturn fmt.Errorf(\"failed to set runtime hostname: %w\", err)"},{"line_number":181,"context_line":"\t}"}],"source_content_type":"text/x-go","patch_set":5,"id":"069fd213_6fb61fc4","line":178,"updated":"2021-06-24 12:51:33.000000000","message":"This function seems out-of-place here. The only parameter from node this uses is the ID, which needs to be available pretty globally anyways. Can\u0027t we move this out of the curator?","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"},{"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":"ec323c5a5b73bc5d9f1198521eb9c29a6eae2984","unresolved":true,"context_lines":[{"line_number":175,"context_line":"// current hostname, and local files like hosts and machine-id accordingly."},{"line_number":176,"context_line":"//"},{"line_number":177,"context_line":"// TODO(q3k): move this to roleserver?"},{"line_number":178,"context_line":"func (n *Node) ConfigureLocalHostname(ctx context.Context, ephemeral *localstorage.EphemeralDirectory, address net.IP) error {"},{"line_number":179,"context_line":"\tif err :\u003d unix.Sethostname([]byte(n.ID())); err !\u003d nil {"},{"line_number":180,"context_line":"\t\treturn fmt.Errorf(\"failed to set runtime hostname: %w\", err)"},{"line_number":181,"context_line":"\t}"}],"source_content_type":"text/x-go","patch_set":5,"id":"f386bb7a_98fb4eff","line":178,"in_reply_to":"069fd213_6fb61fc4","updated":"2021-07-01 11:04:53.000000000","message":"It is out of place, and that\u0027s why the TODO is there. It\u0027s lifted directly from the cluster bootstrap code, and I want to move it out to somewhere else once we land this stack.","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"da54141df76781c5bb47d18a5b5d4bb29f3237d5","unresolved":false,"context_lines":[{"line_number":175,"context_line":"// current hostname, and local files like hosts and machine-id accordingly."},{"line_number":176,"context_line":"//"},{"line_number":177,"context_line":"// TODO(q3k): move this to roleserver?"},{"line_number":178,"context_line":"func (n *Node) ConfigureLocalHostname(ctx context.Context, ephemeral *localstorage.EphemeralDirectory, address net.IP) error {"},{"line_number":179,"context_line":"\tif err :\u003d unix.Sethostname([]byte(n.ID())); err !\u003d nil {"},{"line_number":180,"context_line":"\t\treturn fmt.Errorf(\"failed to set runtime hostname: %w\", err)"},{"line_number":181,"context_line":"\t}"}],"source_content_type":"text/x-go","patch_set":5,"id":"945ad24b_d186a369","line":178,"in_reply_to":"f386bb7a_98fb4eff","updated":"2021-07-06 10:53:20.000000000","message":"Ack","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"}],"metropolis/node/core/curator/state_pki.go":[{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"3501e91806507de808d0fc0253d312789e5d29b1","unresolved":true,"context_lines":[{"line_number":16,"context_line":"\tpkiCA \u003d pkiNamespace.New(pki.SelfSigned, \"cluster-ca\", pki.CA(\"Metropolis Cluster CA\"))"},{"line_number":17,"context_line":")"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"// NodeCredentials are the public and private part of the credentials of a node."},{"line_number":20,"context_line":"//"},{"line_number":21,"context_line":"// It represents all the data necessary for a node to authenticate over mTLS to"},{"line_number":22,"context_line":"// other nodes and the rest of the cluster."}],"source_content_type":"text/x-go","patch_set":5,"id":"0e749d60_3d5b5c04","line":19,"updated":"2021-06-24 12:51:33.000000000","message":"I would move all code from this file into the bootstrapping code. The functions and types here are pretty specific to that usecase and don\u0027t make much sense in more general applications. The abstractions are also very leaky (which is fine for bootstrapping, but then this should live there). As far as I understand things like NodeCredentials.Save will not be used for anything other than bootstrapping as the curator is not involved in writing out node credentials in these cases.","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"},{"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":"ec323c5a5b73bc5d9f1198521eb9c29a6eae2984","unresolved":true,"context_lines":[{"line_number":16,"context_line":"\tpkiCA \u003d pkiNamespace.New(pki.SelfSigned, \"cluster-ca\", pki.CA(\"Metropolis Cluster CA\"))"},{"line_number":17,"context_line":")"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"// NodeCredentials are the public and private part of the credentials of a node."},{"line_number":20,"context_line":"//"},{"line_number":21,"context_line":"// It represents all the data necessary for a node to authenticate over mTLS to"},{"line_number":22,"context_line":"// other nodes and the rest of the cluster."}],"source_content_type":"text/x-go","patch_set":5,"id":"ceadc22d_e116d5cc","line":19,"in_reply_to":"0e749d60_3d5b5c04","updated":"2021-07-01 11:04:53.000000000","message":"NodeCredentials.Save will be also used in the Register flow.\n\nBut agreed, this is quite hairy. I spent a lot of time right now re-engineering this and in the end realized why it ended up here:\n\n  a) I wanted these types to live near the curator, but kinda in the \u0027client\u0027 part of the curator - ie., make them owned and defiend by the curator (as it has the main NodeID logic), but to be used by Curator clients. The idea was that the Curator might have more clients than the Cluster library/manager, so they\u0027d better live here than there.\n\n  b) I wanted to avoid a dependency loop curator-\u003ecluster-\u003ecurator. If these types live in the curator, NewNodeForBootstrap can immediately return NodeCredentials. However, if these types lived in clustr, it would have to return cluster.NodeCredentials. This doesn\u0027t work when the cluster code also needs to accesss the curator code to call the curator.NewNodeForBootstrap function in the first place...\n\n  c) Sequencing this to be in the cluster manager is just pure pain with this change stack, as we\u0027re in the middle of a larger refactor.\n\nIn view of these, I\u0027ve ended up fixing this in another CR (197). That solves c). b) is solved by making NewNodeForBootstrap return []byte instead of NodeCredentials. a) is not solved, we\u0027ll do that when we need it. Further discussion about this can happen in 197, but point is that as it is right now it should at least satisfy the base concern of this comment being that this code is hairy and weirdly duplicated with the Node type.","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"da54141df76781c5bb47d18a5b5d4bb29f3237d5","unresolved":false,"context_lines":[{"line_number":16,"context_line":"\tpkiCA \u003d pkiNamespace.New(pki.SelfSigned, \"cluster-ca\", pki.CA(\"Metropolis Cluster CA\"))"},{"line_number":17,"context_line":")"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"// NodeCredentials are the public and private part of the credentials of a node."},{"line_number":20,"context_line":"//"},{"line_number":21,"context_line":"// It represents all the data necessary for a node to authenticate over mTLS to"},{"line_number":22,"context_line":"// other nodes and the rest of the cluster."}],"source_content_type":"text/x-go","patch_set":5,"id":"08532c06_c3396675","line":19,"in_reply_to":"ceadc22d_e116d5cc","updated":"2021-07-06 10:53:20.000000000","message":"Ack","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"da54141df76781c5bb47d18a5b5d4bb29f3237d5","unresolved":false,"context_lines":[{"line_number":16,"context_line":"\tpkiCA \u003d pkiNamespace.New(pki.SelfSigned, \"cluster-ca\", pki.CA(\"Metropolis Cluster CA\"))"},{"line_number":17,"context_line":")"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"// NodeCredentials are the public and private part of the credentials of a node."},{"line_number":20,"context_line":"//"},{"line_number":21,"context_line":"// It represents all the data necessary for a node to authenticate over mTLS to"},{"line_number":22,"context_line":"// other nodes and the rest of the cluster."}],"source_content_type":"text/x-go","patch_set":5,"id":"b2436922_e41f4c70","line":19,"in_reply_to":"ceadc22d_e116d5cc","updated":"2021-07-06 10:53:20.000000000","message":"Ack","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"},{"author":{"_account_id":1000001,"name":"Lorenz Brun","display_name":"Lorenz","email":"lorenz@monogon.tech","username":"lorenz","avatars":[{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/75c04f6e9881c24ee621fba80667eed8.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"3501e91806507de808d0fc0253d312789e5d29b1","unresolved":true,"context_lines":[{"line_number":33,"context_line":"// NodeCertificate is the public part of the credential of a node."},{"line_number":34,"context_line":"type NodeCertificate struct {"},{"line_number":35,"context_line":"\t// PublicKey is the ED25519 public key of the node."},{"line_number":36,"context_line":"\tPublicKey []byte"},{"line_number":37,"context_line":"\t// Certificate is the DER-encoded TLS certificate emitted for the node (ie."},{"line_number":38,"context_line":"\t// PublicKey) by the cluster CA."},{"line_number":39,"context_line":"\tCertificate []byte"}],"source_content_type":"text/x-go","patch_set":5,"id":"f8d4a0e8_1992c5b6","line":36,"range":{"start_line":36,"start_character":1,"end_line":36,"end_character":10},"updated":"2021-06-24 12:51:33.000000000","message":"This is accessible from (x509.Certificate).SubjectPublicKey. There should probably be a comment why this is there and that it is the public key from the certificate below.","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"},{"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":"ec323c5a5b73bc5d9f1198521eb9c29a6eae2984","unresolved":false,"context_lines":[{"line_number":33,"context_line":"// NodeCertificate is the public part of the credential of a node."},{"line_number":34,"context_line":"type NodeCertificate struct {"},{"line_number":35,"context_line":"\t// PublicKey is the ED25519 public key of the node."},{"line_number":36,"context_line":"\tPublicKey []byte"},{"line_number":37,"context_line":"\t// Certificate is the DER-encoded TLS certificate emitted for the node (ie."},{"line_number":38,"context_line":"\t// PublicKey) by the cluster CA."},{"line_number":39,"context_line":"\tCertificate []byte"}],"source_content_type":"text/x-go","patch_set":5,"id":"89aaa6ed_1bb4daf7","line":36,"range":{"start_line":36,"start_character":1,"end_line":36,"end_character":10},"in_reply_to":"f8d4a0e8_1992c5b6","updated":"2021-07-01 11:04:53.000000000","message":"Oh yeah, this was unnecessarily denormalized. Refactored this slightly to use a x509.Certificate as a source of truth internally.","commit_id":"421508442e22f2551471bb7e9cc7f05adc76083b"}]}
