mirror of
https://github.com/psviderski/uncloud.git
synced 2026-10-06 13:18:58 +00:00
feat(dns): allow setting an externally managed cluster domain
This commit is contained in:
1 parent
b28c458029
commit
9ee3ca15eb
21 files changed
+233
-136
No files matched your search
+78
-62
@@ -392,6 +392,9 @@ type Domain struct {
|
|||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||||
|
// Whether the domain is reserved in Uncloud DNS. Older daemons (<0.21) omit this field
|
||||||
|
// and only support reserved domains, so clients should treat absence as true.
|
||||||
|
Reserved *bool `protobuf:"varint,2,opt,name=reserved,proto3,oneof" json:"reserved,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Domain) Reset() {
|
func (x *Domain) Reset() {
|
||||||
@@ -433,6 +436,13 @@ func (x *Domain) GetName() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *Domain) GetReserved() bool {
|
||||||
|
if x != nil && x.Reserved != nil {
|
||||||
|
return *x.Reserved
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
type ReserveDomainRequest struct {
|
type ReserveDomainRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -485,6 +495,7 @@ type SetDomainRequest struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
// An externally managed domain name. Empty clears a manually set domain.
|
||||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -723,68 +734,72 @@ var file_api_pb_cluster_proto_rawDesc = []byte{
|
|||||||
0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x08, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
|
0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x08, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
|
||||||
0x73, 0x22, 0x26, 0x0a, 0x14, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69,
|
0x73, 0x22, 0x26, 0x0a, 0x14, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69,
|
||||||
0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
|
0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
|
||||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x1c, 0x0a, 0x06, 0x44, 0x6f, 0x6d,
|
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x4a, 0x0a, 0x06, 0x44, 0x6f, 0x6d,
|
||||||
0x61, 0x69, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
|
0x61, 0x69, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x32, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x65, 0x72,
|
0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x65, 0x72,
|
||||||
0x76, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
|
0x76, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x08, 0x72, 0x65, 0x73,
|
||||||
0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
|
0x65, 0x72, 0x76, 0x65, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x72, 0x65, 0x73,
|
||||||
0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x22, 0x26, 0x0a, 0x10, 0x53,
|
0x65, 0x72, 0x76, 0x65, 0x64, 0x22, 0x32, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65,
|
||||||
0x65, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
|
0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a,
|
||||||
0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
|
0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x61, 0x6d, 0x65, 0x22, 0x46, 0x0a, 0x1a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x6f, 0x6d,
|
0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x22, 0x26, 0x0a, 0x10, 0x53, 0x65, 0x74,
|
||||||
0x61, 0x69, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a,
|
||||||
0x74, 0x12, 0x28, 0x0a, 0x07, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03,
|
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
|
||||||
0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x4e, 0x53, 0x52, 0x65, 0x63, 0x6f,
|
0x65, 0x22, 0x46, 0x0a, 0x1a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
||||||
0x72, 0x64, 0x52, 0x07, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x22, 0x47, 0x0a, 0x1b, 0x43,
|
0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
|
||||||
0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72,
|
0x28, 0x0a, 0x07, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
|
||||||
0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x07, 0x72, 0x65,
|
0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x4e, 0x53, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64,
|
||||||
0x63, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70,
|
0x52, 0x07, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x22, 0x47, 0x0a, 0x1b, 0x43, 0x72, 0x65,
|
||||||
0x69, 0x2e, 0x44, 0x4e, 0x53, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x07, 0x72, 0x65, 0x63,
|
0x61, 0x74, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73,
|
||||||
0x6f, 0x72, 0x64, 0x73, 0x22, 0x96, 0x01, 0x0a, 0x09, 0x44, 0x4e, 0x53, 0x52, 0x65, 0x63, 0x6f,
|
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x07, 0x72, 0x65, 0x63, 0x6f,
|
||||||
0x72, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x2e,
|
||||||
0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2d, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02,
|
0x44, 0x4e, 0x53, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x07, 0x72, 0x65, 0x63, 0x6f, 0x72,
|
||||||
0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x4e, 0x53, 0x52, 0x65,
|
0x64, 0x73, 0x22, 0x96, 0x01, 0x0a, 0x09, 0x44, 0x4e, 0x53, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64,
|
||||||
0x63, 0x6f, 0x72, 0x64, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x79, 0x70, 0x65, 0x52,
|
0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
|
||||||
0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18,
|
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2d, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01,
|
||||||
0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x2e, 0x0a,
|
0x28, 0x0e, 0x32, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x4e, 0x53, 0x52, 0x65, 0x63, 0x6f,
|
||||||
0x0a, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55,
|
0x72, 0x64, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74,
|
||||||
0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x05, 0x0a, 0x01,
|
0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x03, 0x20,
|
||||||
0x41, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x41, 0x41, 0x41, 0x10, 0x02, 0x32, 0xfb, 0x03,
|
0x03, 0x28, 0x09, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x2e, 0x0a, 0x0a, 0x52,
|
||||||
0x0a, 0x07, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x0a, 0x41, 0x64, 0x64,
|
0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53,
|
||||||
0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x64,
|
0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x05, 0x0a, 0x01, 0x41, 0x10,
|
||||||
0x64, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
0x01, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x41, 0x41, 0x41, 0x10, 0x02, 0x32, 0x86, 0x04, 0x0a, 0x07,
|
||||||
0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x64, 0x64, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
|
0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x4d, 0x61,
|
||||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74,
|
0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x64, 0x64, 0x4d,
|
||||||
0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
|
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e,
|
||||||
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
|
0x61, 0x70, 0x69, 0x2e, 0x41, 0x64, 0x64, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65,
|
||||||
0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69,
|
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61,
|
||||||
0x6e, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x0d, 0x52,
|
0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
|
||||||
0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x19, 0x2e, 0x61,
|
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19,
|
||||||
0x70, 0x69, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
|
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
|
||||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x0d, 0x52, 0x65, 0x6d,
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12,
|
0x6f, 0x76, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69,
|
||||||
0x37, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65,
|
||||||
0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x44, 0x6f,
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
|
||||||
0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x61, 0x70,
|
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x37, 0x0a,
|
||||||
0x69, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x2f, 0x0a, 0x09, 0x53, 0x65, 0x74, 0x44,
|
0x0d, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x19,
|
||||||
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x74, 0x44,
|
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x44, 0x6f, 0x6d, 0x61,
|
||||||
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x61,
|
0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x2e,
|
||||||
0x70, 0x69, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x30, 0x0a, 0x09, 0x47, 0x65, 0x74,
|
0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3a, 0x0a, 0x09, 0x53, 0x65, 0x74, 0x44, 0x6f, 0x6d,
|
||||||
0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
|
0x61, 0x69, 0x6e, 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x74, 0x44, 0x6f, 0x6d,
|
||||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0b,
|
0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f,
|
||||||
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x34, 0x0a, 0x0d, 0x52,
|
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70,
|
||||||
0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x16, 0x2e, 0x67,
|
0x74, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12,
|
||||||
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45,
|
0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
|
||||||
0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x6f,
|
||||||
0x6e, 0x12, 0x58, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
0x6d, 0x61, 0x69, 0x6e, 0x12, 0x34, 0x0a, 0x0d, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x44,
|
||||||
0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43,
|
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
|
||||||
0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72,
|
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0b, 0x2e,
|
||||||
0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e,
|
0x61, 0x70, 0x69, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x58, 0x0a, 0x13, 0x43, 0x72,
|
||||||
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x63, 0x6f,
|
0x65, 0x61, 0x74, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64,
|
||||||
0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x26, 0x5a, 0x24, 0x67,
|
0x73, 0x12, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x6f,
|
||||||
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x73, 0x76, 0x69, 0x64, 0x65,
|
0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||||
0x72, 0x73, 0x6b, 0x69, 0x2f, 0x75, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x61, 0x70, 0x69,
|
0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44,
|
||||||
0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70,
|
||||||
|
0x6f, 0x6e, 0x73, 0x65, 0x42, 0x26, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
|
||||||
|
0x6f, 0x6d, 0x2f, 0x70, 0x73, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x6b, 0x69, 0x2f, 0x75, 0x6e,
|
||||||
|
0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72,
|
||||||
|
0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -842,7 +857,7 @@ var file_api_pb_cluster_proto_depIdxs = []int32{
|
|||||||
5, // 18: api.Cluster.ListMachines:output_type -> api.ListMachinesResponse
|
5, // 18: api.Cluster.ListMachines:output_type -> api.ListMachinesResponse
|
||||||
16, // 19: api.Cluster.RemoveMachine:output_type -> google.protobuf.Empty
|
16, // 19: api.Cluster.RemoveMachine:output_type -> google.protobuf.Empty
|
||||||
7, // 20: api.Cluster.ReserveDomain:output_type -> api.Domain
|
7, // 20: api.Cluster.ReserveDomain:output_type -> api.Domain
|
||||||
7, // 21: api.Cluster.SetDomain:output_type -> api.Domain
|
16, // 21: api.Cluster.SetDomain:output_type -> google.protobuf.Empty
|
||||||
7, // 22: api.Cluster.GetDomain:output_type -> api.Domain
|
7, // 22: api.Cluster.GetDomain:output_type -> api.Domain
|
||||||
7, // 23: api.Cluster.ReleaseDomain:output_type -> api.Domain
|
7, // 23: api.Cluster.ReleaseDomain:output_type -> api.Domain
|
||||||
11, // 24: api.Cluster.CreateDomainRecords:output_type -> api.CreateDomainRecordsResponse
|
11, // 24: api.Cluster.CreateDomainRecords:output_type -> api.CreateDomainRecordsResponse
|
||||||
@@ -994,6 +1009,7 @@ func file_api_pb_cluster_proto_init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
file_api_pb_cluster_proto_msgTypes[5].OneofWrappers = []any{}
|
||||||
type x struct{}
|
type x struct{}
|
||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ service Cluster {
|
|||||||
rpc RemoveMachine(RemoveMachineRequest) returns (google.protobuf.Empty);
|
rpc RemoveMachine(RemoveMachineRequest) returns (google.protobuf.Empty);
|
||||||
|
|
||||||
rpc ReserveDomain(ReserveDomainRequest) returns (Domain);
|
rpc ReserveDomain(ReserveDomainRequest) returns (Domain);
|
||||||
rpc SetDomain(SetDomainRequest) returns (Domain);
|
rpc SetDomain(SetDomainRequest) returns (google.protobuf.Empty);
|
||||||
rpc GetDomain(google.protobuf.Empty) returns (Domain);
|
rpc GetDomain(google.protobuf.Empty) returns (Domain);
|
||||||
rpc ReleaseDomain(google.protobuf.Empty) returns (Domain);
|
rpc ReleaseDomain(google.protobuf.Empty) returns (Domain);
|
||||||
rpc CreateDomainRecords(CreateDomainRecordsRequest) returns (CreateDomainRecordsResponse);
|
rpc CreateDomainRecords(CreateDomainRecordsRequest) returns (CreateDomainRecordsResponse);
|
||||||
@@ -57,6 +57,9 @@ message RemoveMachineRequest {
|
|||||||
|
|
||||||
message Domain {
|
message Domain {
|
||||||
string name = 1;
|
string name = 1;
|
||||||
|
// Whether the domain is reserved in Uncloud DNS. Older daemons (<0.21) omit this field
|
||||||
|
// and only support reserved domains, so clients should treat absence as true.
|
||||||
|
optional bool reserved = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ReserveDomainRequest {
|
message ReserveDomainRequest {
|
||||||
@@ -64,6 +67,7 @@ message ReserveDomainRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message SetDomainRequest {
|
message SetDomainRequest {
|
||||||
|
// An externally managed domain name. Empty clears a manually set domain.
|
||||||
string name = 1;
|
string name = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ type ClusterClient interface {
|
|||||||
ListMachines(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ListMachinesResponse, error)
|
ListMachines(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ListMachinesResponse, error)
|
||||||
RemoveMachine(ctx context.Context, in *RemoveMachineRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
RemoveMachine(ctx context.Context, in *RemoveMachineRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||||
ReserveDomain(ctx context.Context, in *ReserveDomainRequest, opts ...grpc.CallOption) (*Domain, error)
|
ReserveDomain(ctx context.Context, in *ReserveDomainRequest, opts ...grpc.CallOption) (*Domain, error)
|
||||||
SetDomain(ctx context.Context, in *SetDomainRequest, opts ...grpc.CallOption) (*Domain, error)
|
SetDomain(ctx context.Context, in *SetDomainRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||||
GetDomain(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*Domain, error)
|
GetDomain(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*Domain, error)
|
||||||
ReleaseDomain(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*Domain, error)
|
ReleaseDomain(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*Domain, error)
|
||||||
CreateDomainRecords(ctx context.Context, in *CreateDomainRecordsRequest, opts ...grpc.CallOption) (*CreateDomainRecordsResponse, error)
|
CreateDomainRecords(ctx context.Context, in *CreateDomainRecordsRequest, opts ...grpc.CallOption) (*CreateDomainRecordsResponse, error)
|
||||||
@@ -92,9 +92,9 @@ func (c *clusterClient) ReserveDomain(ctx context.Context, in *ReserveDomainRequ
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *clusterClient) SetDomain(ctx context.Context, in *SetDomainRequest, opts ...grpc.CallOption) (*Domain, error) {
|
func (c *clusterClient) SetDomain(ctx context.Context, in *SetDomainRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(Domain)
|
out := new(emptypb.Empty)
|
||||||
err := c.cc.Invoke(ctx, Cluster_SetDomain_FullMethodName, in, out, cOpts...)
|
err := c.cc.Invoke(ctx, Cluster_SetDomain_FullMethodName, in, out, cOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -140,7 +140,7 @@ type ClusterServer interface {
|
|||||||
ListMachines(context.Context, *emptypb.Empty) (*ListMachinesResponse, error)
|
ListMachines(context.Context, *emptypb.Empty) (*ListMachinesResponse, error)
|
||||||
RemoveMachine(context.Context, *RemoveMachineRequest) (*emptypb.Empty, error)
|
RemoveMachine(context.Context, *RemoveMachineRequest) (*emptypb.Empty, error)
|
||||||
ReserveDomain(context.Context, *ReserveDomainRequest) (*Domain, error)
|
ReserveDomain(context.Context, *ReserveDomainRequest) (*Domain, error)
|
||||||
SetDomain(context.Context, *SetDomainRequest) (*Domain, error)
|
SetDomain(context.Context, *SetDomainRequest) (*emptypb.Empty, error)
|
||||||
GetDomain(context.Context, *emptypb.Empty) (*Domain, error)
|
GetDomain(context.Context, *emptypb.Empty) (*Domain, error)
|
||||||
ReleaseDomain(context.Context, *emptypb.Empty) (*Domain, error)
|
ReleaseDomain(context.Context, *emptypb.Empty) (*Domain, error)
|
||||||
CreateDomainRecords(context.Context, *CreateDomainRecordsRequest) (*CreateDomainRecordsResponse, error)
|
CreateDomainRecords(context.Context, *CreateDomainRecordsRequest) (*CreateDomainRecordsResponse, error)
|
||||||
@@ -166,7 +166,7 @@ func (UnimplementedClusterServer) RemoveMachine(context.Context, *RemoveMachineR
|
|||||||
func (UnimplementedClusterServer) ReserveDomain(context.Context, *ReserveDomainRequest) (*Domain, error) {
|
func (UnimplementedClusterServer) ReserveDomain(context.Context, *ReserveDomainRequest) (*Domain, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method ReserveDomain not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method ReserveDomain not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedClusterServer) SetDomain(context.Context, *SetDomainRequest) (*Domain, error) {
|
func (UnimplementedClusterServer) SetDomain(context.Context, *SetDomainRequest) (*emptypb.Empty, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method SetDomain not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method SetDomain not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedClusterServer) GetDomain(context.Context, *emptypb.Empty) (*Domain, error) {
|
func (UnimplementedClusterServer) GetDomain(context.Context, *emptypb.Empty) (*Domain, error) {
|
||||||
|
|||||||
@@ -202,6 +202,10 @@ func UpdateDomainRecords(ctx context.Context, clusterClient *client.Client, prog
|
|||||||
}
|
}
|
||||||
return fmt.Errorf("get cluster domain: %w", err)
|
return fmt.Errorf("get cluster domain: %w", err)
|
||||||
}
|
}
|
||||||
|
if !domain.Reserved {
|
||||||
|
fmt.Printf("Skipping DNS records update as cluster domain '%s' is managed externally.\n", domain.Name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println("Updating cluster domain records in Uncloud DNS to point to machines running caddy service...")
|
fmt.Println("Updating cluster domain records in Uncloud DNS to point to machines running caddy service...")
|
||||||
// TODO: split the method into two: one to get the records and one to update them to ask for update confirmation.
|
// TODO: split the method into two: one to get the records and one to update them to ask for update confirmation.
|
||||||
@@ -216,7 +220,7 @@ func UpdateDomainRecords(ctx context.Context, clusterClient *client.Client, prog
|
|||||||
if errors.Is(err, client.ErrNoReachableMachines) {
|
if errors.Is(err, client.ErrNoReachableMachines) {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Printf("DNS records for domain '%s' could not be updated as there are no internet-reachable "+
|
fmt.Printf("DNS records for domain '%s' could not be updated as there are no internet-reachable "+
|
||||||
"machines running caddy containers.\n", domain)
|
"machines running caddy containers.\n", domain.Name)
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println("Possible solutions:")
|
fmt.Println("Possible solutions:")
|
||||||
fmt.Println("- Ensure your machines have public IP addresses")
|
fmt.Println("- Ensure your machines have public IP addresses")
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ func release(ctx context.Context, uncli *cli.CLI) error {
|
|||||||
if status.Convert(err).Code() == codes.NotFound {
|
if status.Convert(err).Code() == codes.NotFound {
|
||||||
return errors.New("no domain reserved")
|
return errors.New("no domain reserved")
|
||||||
}
|
}
|
||||||
|
return fmt.Errorf("release cluster domain: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Released cluster domain: %s\n", domain.Name)
|
fmt.Printf("Released cluster domain: %s\n", domain.Name)
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ func reserve(ctx context.Context, uncli *cli.CLI, opts reserveOptions) error {
|
|||||||
domain, err := clusterClient.ReserveDomain(ctx, &pb.ReserveDomainRequest{Endpoint: opts.endpoint})
|
domain, err := clusterClient.ReserveDomain(ctx, &pb.ReserveDomainRequest{Endpoint: opts.endpoint})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if status.Convert(err).Code() == codes.AlreadyExists {
|
if status.Convert(err).Code() == codes.AlreadyExists {
|
||||||
return errors.New("domain already reserved")
|
return errors.New("cluster domain already configured, unset it with 'uc dns set \"\"' " +
|
||||||
|
"or release a reservation with 'uc dns release' first")
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-3
@@ -7,11 +7,13 @@ import (
|
|||||||
func NewRootCommand() *cobra.Command {
|
func NewRootCommand() *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "dns",
|
Use: "dns",
|
||||||
Short: "Manage cluster domain in Uncloud DNS.",
|
Short: "Manage the cluster domain.",
|
||||||
Long: "Manage cluster domain in Uncloud DNS.\n" +
|
Long: "Manage the cluster domain.\n" +
|
||||||
"DNS commands allow you to reserve or release a unique 'xxxxxx.uncld.dev' domain for your " +
|
"DNS commands allow you to reserve or release a unique 'xxxxxx.uncld.dev' domain for your " +
|
||||||
"cluster. When reserved, Caddy service deployments will automatically update DNS records to route " +
|
"cluster. When reserved, Caddy service deployments will automatically update DNS records to route " +
|
||||||
"traffic to the services in the cluster.",
|
"traffic to the services in the cluster.\n\n" +
|
||||||
|
"EXPERIMENTAL: Use 'uc dns set' to configure an externally managed domain instead. " +
|
||||||
|
"Uncloud does not manage DNS records for manually set domains.",
|
||||||
}
|
}
|
||||||
cmd.AddCommand(
|
cmd.AddCommand(
|
||||||
NewReleaseCommand(),
|
NewReleaseCommand(),
|
||||||
|
|||||||
+25
-13
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
"github.com/psviderski/uncloud/api/pb"
|
"github.com/psviderski/uncloud/api/pb"
|
||||||
"github.com/psviderski/uncloud/internal/cli"
|
"github.com/psviderski/uncloud/internal/cli"
|
||||||
|
"github.com/psviderski/uncloud/internal/cli/tui"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
@@ -17,9 +18,14 @@ func NewSetCommand() *cobra.Command {
|
|||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "set DOMAIN_NAME",
|
Use: "set DOMAIN_NAME",
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
Short: "Set a cluster domain directly in the cluster.",
|
Short: "Set or unset an externally managed cluster domain (EXPERIMENTAL).",
|
||||||
Long: "Set a cluster domain directly in the cluster, bypassing Uncloud DNS. " +
|
Long: "EXPERIMENTAL: Set the cluster domain used to generate ingress hostnames for services.\n" +
|
||||||
"This assumes the DNS is externally set up.",
|
"Configure wildcard DNS records for this domain with your DNS provider. " +
|
||||||
|
"Uncloud will not create, verify, update, or delete external DNS records.\n" +
|
||||||
|
"Pass an empty string to unset a manually set domain. " +
|
||||||
|
"Use 'uc dns release' to release a domain reserved in Uncloud DNS. " +
|
||||||
|
"Setting or unsetting the domain does not change existing service hostnames.",
|
||||||
|
Example: " uc dns set apps.example.com\n uc dns set \"\"",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
uncli := cmd.Context().Value("cli").(*cli.CLI)
|
uncli := cmd.Context().Value("cli").(*cli.CLI)
|
||||||
return set(cmd.Context(), uncli, args[0])
|
return set(cmd.Context(), uncli, args[0])
|
||||||
@@ -30,10 +36,12 @@ func NewSetCommand() *cobra.Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func set(ctx context.Context, uncli *cli.CLI, name string) error {
|
func set(ctx context.Context, uncli *cli.CLI, name string) error {
|
||||||
labels, ok := dns.IsDomainName(name)
|
if name != "" {
|
||||||
if !ok || labels < 3 {
|
if labels, ok := dns.IsDomainName(name); !ok || labels < 2 {
|
||||||
return fmt.Errorf("domain '%s' is not a valid name", name)
|
return fmt.Errorf("invalid cluster domain %q: must be a valid domain name with at least two labels", name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
tui.PrintWarning("Setting an externally managed cluster domain is experimental.")
|
||||||
|
|
||||||
clusterClient, err := uncli.ConnectCluster(ctx)
|
clusterClient, err := uncli.ConnectCluster(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -41,17 +49,21 @@ func set(ctx context.Context, uncli *cli.CLI, name string) error {
|
|||||||
}
|
}
|
||||||
defer clusterClient.Close()
|
defer clusterClient.Close()
|
||||||
|
|
||||||
domain, err := clusterClient.SetDomain(ctx, &pb.SetDomainRequest{Name: name})
|
_, err = clusterClient.SetDomain(ctx, &pb.SetDomainRequest{Name: name})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if status.Convert(err).Code() == codes.AlreadyExists {
|
if status.Convert(err).Code() == codes.AlreadyExists {
|
||||||
return errors.New("domain already reserved")
|
return errors.New("cluster domain already configured, unset it with 'uc dns set \"\"' or " +
|
||||||
|
"release a reservation with 'uc dns release' first")
|
||||||
}
|
}
|
||||||
return err
|
return fmt.Errorf("set cluster domain: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Set cluster domain: %s\n", domain.Name)
|
if name == "" {
|
||||||
|
fmt.Println("Unset cluster domain. External DNS records have not been changed.")
|
||||||
// No need to update anything as the domain records pointing to this cluster should be wildcard, so all
|
return nil
|
||||||
// names already exist.
|
}
|
||||||
|
fmt.Printf("Set cluster domain: %s\n", name)
|
||||||
|
fmt.Println("DNS is managed externally. " +
|
||||||
|
"Configure wildcard DNS records pointing to machines running the Caddy service.")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
+2
-2
@@ -33,11 +33,11 @@ func show(ctx context.Context, uncli *cli.CLI) error {
|
|||||||
domain, err := clusterClient.GetDomain(ctx)
|
domain, err := clusterClient.GetDomain(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, api.ErrNotFound) {
|
if errors.Is(err, api.ErrNotFound) {
|
||||||
return errors.New("no domain reserved")
|
return errors.New("no cluster domain configured")
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(domain)
|
fmt.Println(domain.Name)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -4,20 +4,24 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/miekg/dns"
|
||||||
"github.com/psviderski/uncloud/api/pb"
|
"github.com/psviderski/uncloud/api/pb"
|
||||||
"github.com/psviderski/uncloud/internal/dns"
|
undns "github.com/psviderski/uncloud/internal/dns"
|
||||||
"github.com/psviderski/uncloud/internal/machine/store"
|
"github.com/psviderski/uncloud/internal/machine/store"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
"google.golang.org/protobuf/types/known/emptypb"
|
"google.golang.org/protobuf/types/known/emptypb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// uncloudDNSKey is the key used to store the details of the reserved domain in the store.
|
// uncloudDNSKey stores the cluster domain and, when reserved, its Uncloud DNS credentials.
|
||||||
const uncloudDNSKey = "uncloud_dns"
|
const uncloudDNSKey = "uncloud_dns"
|
||||||
|
|
||||||
type uncloudDNSDomain struct {
|
type uncloudDNSDomain struct {
|
||||||
// Endpoint is the API endpoint of the Uncloud DNS service where the domain is reserved.
|
// Endpoint is the API endpoint of the Uncloud DNS service where the domain is reserved.
|
||||||
|
// An empty endpoint means the domain is managed externally.
|
||||||
Endpoint string
|
Endpoint string
|
||||||
Name string
|
Name string
|
||||||
// TODO: encrypt the token in the store.
|
// TODO: encrypt the token in the store.
|
||||||
@@ -34,14 +38,14 @@ func (c *Cluster) ReserveDomain(ctx context.Context, req *pb.ReserveDomainReques
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, err := c.storedDomain(ctx); err == nil {
|
if _, err := c.storedDomain(ctx); err == nil {
|
||||||
return nil, status.Errorf(codes.AlreadyExists, "domain already reserved")
|
return nil, status.Error(codes.AlreadyExists, "cluster domain already configured")
|
||||||
} else {
|
} else {
|
||||||
if s := status.Convert(err); s.Code() != codes.NotFound {
|
if s := status.Convert(err); s.Code() != codes.NotFound {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dnsClient := dns.NewClient()
|
dnsClient := undns.NewClient()
|
||||||
name, token, err := dnsClient.ReserveDomain(req.Endpoint)
|
name, token, err := dnsClient.ReserveDomain(req.Endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
@@ -60,7 +64,7 @@ func (c *Cluster) ReserveDomain(ctx context.Context, req *pb.ReserveDomainReques
|
|||||||
return nil, status.Errorf(codes.Internal, "store reserved domain: %v", err)
|
return nil, status.Errorf(codes.Internal, "store reserved domain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &pb.Domain{Name: name}, nil
|
return &pb.Domain{Name: name, Reserved: proto.Bool(true)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cluster) GetDomain(ctx context.Context, _ *emptypb.Empty) (*pb.Domain, error) {
|
func (c *Cluster) GetDomain(ctx context.Context, _ *emptypb.Empty) (*pb.Domain, error) {
|
||||||
@@ -73,7 +77,7 @@ func (c *Cluster) GetDomain(ctx context.Context, _ *emptypb.Empty) (*pb.Domain,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &pb.Domain{Name: domain.Name}, nil
|
return &pb.Domain{Name: domain.Name, Reserved: proto.Bool(domain.Endpoint != "")}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cluster) storedDomain(ctx context.Context) (uncloudDNSDomain, error) {
|
func (c *Cluster) storedDomain(ctx context.Context) (uncloudDNSDomain, error) {
|
||||||
@@ -103,33 +107,54 @@ func (c *Cluster) ReleaseDomain(ctx context.Context, _ *emptypb.Empty) (*pb.Doma
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if domain.Endpoint == "" {
|
||||||
|
return nil, status.Error(codes.FailedPrecondition,
|
||||||
|
"cluster domain is set manually, use 'uc dns set \"\"' to unset it")
|
||||||
|
}
|
||||||
|
|
||||||
if err = c.store.Delete(ctx, uncloudDNSKey); err != nil {
|
if err = c.store.Delete(ctx, uncloudDNSKey); err != nil {
|
||||||
return nil, status.Errorf(codes.Internal, "delete domain from store: %v", err)
|
return nil, status.Errorf(codes.Internal, "delete domain from store: %v", err)
|
||||||
}
|
}
|
||||||
// TODO: implement and call Uncloud DNS endpoint to release/delete the domain.
|
// TODO: implement and call Uncloud DNS endpoint to release/delete the domain.
|
||||||
|
|
||||||
return &pb.Domain{Name: domain.Name}, nil
|
return &pb.Domain{Name: domain.Name, Reserved: proto.Bool(true)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cluster) SetDomain(ctx context.Context, req *pb.SetDomainRequest) (*pb.Domain, error) {
|
func (c *Cluster) SetDomain(ctx context.Context, req *pb.SetDomainRequest) (*emptypb.Empty, error) {
|
||||||
if err := c.checkReady(); err != nil {
|
if err := c.checkReady(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := c.storedDomain(ctx); err == nil {
|
name := req.GetName()
|
||||||
return nil, status.Errorf(codes.AlreadyExists, "domain already reserved")
|
if name != "" {
|
||||||
} else {
|
if labels, ok := dns.IsDomainName(name); !ok || labels < 2 {
|
||||||
if s := status.Convert(err); s.Code() != codes.NotFound {
|
return nil, status.Errorf(codes.InvalidArgument,
|
||||||
return nil, err
|
"invalid cluster domain '%s': must be a valid domain name with at least two labels", name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
name = strings.ToLower(strings.TrimSuffix(name, "."))
|
||||||
|
|
||||||
domain := uncloudDNSDomain{
|
existing, err := c.storedDomain(ctx)
|
||||||
Endpoint: "",
|
if err != nil && status.Code(err) != codes.NotFound {
|
||||||
Name: req.Name,
|
return nil, err
|
||||||
Token: "",
|
|
||||||
}
|
}
|
||||||
|
if name == "" {
|
||||||
|
if err == nil {
|
||||||
|
if existing.Endpoint != "" {
|
||||||
|
return nil, status.Error(codes.FailedPrecondition,
|
||||||
|
"cluster domain is reserved in Uncloud DNS, use 'uc dns release' to release it")
|
||||||
|
}
|
||||||
|
if err := c.store.Delete(ctx, uncloudDNSKey); err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "unset cluster domain: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &emptypb.Empty{}, nil
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
return nil, status.Error(codes.AlreadyExists, "cluster domain already configured")
|
||||||
|
}
|
||||||
|
|
||||||
|
domain := uncloudDNSDomain{Name: name}
|
||||||
domainJSON, err := json.Marshal(domain)
|
domainJSON, err := json.Marshal(domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.Errorf(codes.Internal, "marshal set domain for store: %v", err)
|
return nil, status.Errorf(codes.Internal, "marshal set domain for store: %v", err)
|
||||||
@@ -138,7 +163,7 @@ func (c *Cluster) SetDomain(ctx context.Context, req *pb.SetDomainRequest) (*pb.
|
|||||||
return nil, status.Errorf(codes.Internal, "store set domain: %v", err)
|
return nil, status.Errorf(codes.Internal, "store set domain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &pb.Domain{Name: req.Name}, nil
|
return &emptypb.Empty{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cluster) CreateDomainRecords(
|
func (c *Cluster) CreateDomainRecords(
|
||||||
@@ -153,16 +178,16 @@ func (c *Cluster) CreateDomainRecords(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if domain.Endpoint == "" { // uc dns set has set a name
|
if domain.Endpoint == "" {
|
||||||
return &pb.CreateDomainRecordsResponse{}, nil
|
return nil, status.Error(codes.FailedPrecondition, "cluster domain is not reserved in Uncloud DNS")
|
||||||
}
|
}
|
||||||
|
|
||||||
dnsClient := dns.NewClient()
|
dnsClient := undns.NewClient()
|
||||||
recordsReq := make([]dns.RecordRequest, len(req.Records))
|
recordsReq := make([]undns.RecordRequest, len(req.Records))
|
||||||
for i, r := range req.Records {
|
for i, r := range req.Records {
|
||||||
recordsReq[i] = dns.RecordRequest{
|
recordsReq[i] = undns.RecordRequest{
|
||||||
Name: r.Name,
|
Name: r.Name,
|
||||||
Type: dns.RecordType(r.Type.String()),
|
Type: undns.RecordType(r.Type.String()),
|
||||||
Values: r.Values,
|
Values: r.Values,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -182,9 +207,9 @@ func (c *Cluster) CreateDomainRecords(
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
case dns.RecordTypeA:
|
case undns.RecordTypeA:
|
||||||
resp.Records[i].Type = pb.DNSRecord_A
|
resp.Records[i].Type = pb.DNSRecord_A
|
||||||
case dns.RecordTypeAAAA:
|
case undns.RecordTypeAAAA:
|
||||||
resp.Records[i].Type = pb.DNSRecord_AAAA
|
resp.Records[i].Type = pb.DNSRecord_AAAA
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@ type ContainerClient interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DNSClient interface {
|
type DNSClient interface {
|
||||||
GetDomain(ctx context.Context) (string, error)
|
GetDomain(ctx context.Context) (ClusterDomain, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ImageClient interface {
|
type ImageClient interface {
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
// ClusterDomain is the domain name assigned to the cluster.
|
||||||
|
type ClusterDomain struct {
|
||||||
|
Name string
|
||||||
|
// Reserved reports whether the domain is reserved in Uncloud DNS or set and managed externally.
|
||||||
|
Reserved bool
|
||||||
|
}
|
||||||
@@ -46,8 +46,8 @@ func NewDeploymentWithStrategy(ctx context.Context, cli Client, project *types.P
|
|||||||
return nil, fmt.Errorf("get cluster domain: %w", err)
|
return nil, fmt.Errorf("get cluster domain: %w", err)
|
||||||
}
|
}
|
||||||
resolver := &deploy.ServiceSpecResolver{
|
resolver := &deploy.ServiceSpecResolver{
|
||||||
// If the domain is not found (not reserved), an empty domain is used for the resolver.
|
// If no domain is configured, an empty domain is used for the resolver.
|
||||||
ClusterDomain: domain,
|
ClusterDomain: domain.Name,
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Deployment{
|
return &Deployment{
|
||||||
|
|||||||
@@ -306,8 +306,8 @@ func (d *Deployment) Plan(ctx context.Context) (ServicePlan, error) {
|
|||||||
return ServicePlan{}, fmt.Errorf("get cluster domain: %w", err)
|
return ServicePlan{}, fmt.Errorf("get cluster domain: %w", err)
|
||||||
}
|
}
|
||||||
specResolver := &ServiceSpecResolver{
|
specResolver := &ServiceSpecResolver{
|
||||||
// If the domain is not found (not reserved), an empty domain is used for the resolver.
|
// If no domain is configured, an empty domain is used for the resolver.
|
||||||
ClusterDomain: clusterDomain,
|
ClusterDomain: clusterDomain.Name,
|
||||||
}
|
}
|
||||||
|
|
||||||
resolvedSpec, err := specResolver.Resolve(d.Spec)
|
resolvedSpec, err := specResolver.Resolve(d.Spec)
|
||||||
|
|||||||
+20
-7
@@ -21,17 +21,21 @@ import (
|
|||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetDomain returns the cluster domain name or ErrNotFound if it hasn't been reserved yet.
|
// GetDomain returns the cluster domain or api.ErrNotFound if none is configured.
|
||||||
func (cli *Client) GetDomain(ctx context.Context) (string, error) {
|
func (cli *Client) GetDomain(ctx context.Context) (api.ClusterDomain, error) {
|
||||||
domain, err := cli.ClusterClient.GetDomain(ctx, nil)
|
domain, err := cli.ClusterClient.GetDomain(ctx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if status.Convert(err).Code() == codes.NotFound {
|
if status.Code(err) == codes.NotFound {
|
||||||
return "", api.ErrNotFound
|
return api.ClusterDomain{}, api.ErrNotFound
|
||||||
}
|
}
|
||||||
return "", err
|
return api.ClusterDomain{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return domain.Name, nil
|
return api.ClusterDomain{
|
||||||
|
Name: domain.Name,
|
||||||
|
// Older daemons (<0.21) omit Reserved and only support reserved domains.
|
||||||
|
Reserved: domain.Reserved == nil || domain.GetReserved(),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var ErrNoReachableMachines = errors.New("no internet-reachable machines running service containers")
|
var ErrNoReachableMachines = errors.New("no internet-reachable machines running service containers")
|
||||||
@@ -39,8 +43,17 @@ var ErrNoReachableMachines = errors.New("no internet-reachable machines running
|
|||||||
// CreateIngressRecords verifies which machines running the specified service (typically Caddy) are reachable from
|
// CreateIngressRecords verifies which machines running the specified service (typically Caddy) are reachable from
|
||||||
// the internet, then creates DNS records for the cluster domain pointing to those machines. It tests each machine
|
// the internet, then creates DNS records for the cluster domain pointing to those machines. It tests each machine
|
||||||
// by sending HTTP requests to their public IPs. Only machines that respond correctly with their machine ID are included
|
// by sending HTTP requests to their public IPs. Only machines that respond correctly with their machine ID are included
|
||||||
// in the resulting DNS configuration. Returns the created DNS records or an error.
|
// in the resulting DNS configuration. The domain must be reserved in Uncloud DNS.
|
||||||
|
// Returns the created DNS records or an error.
|
||||||
func (cli *Client) CreateIngressRecords(ctx context.Context, serviceID string) ([]*pb.DNSRecord, error) {
|
func (cli *Client) CreateIngressRecords(ctx context.Context, serviceID string) ([]*pb.DNSRecord, error) {
|
||||||
|
domain, err := cli.GetDomain(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("get cluster domain: %w", err)
|
||||||
|
}
|
||||||
|
if !domain.Reserved {
|
||||||
|
return nil, status.Error(codes.FailedPrecondition, "cluster domain is not reserved in Uncloud DNS")
|
||||||
|
}
|
||||||
|
|
||||||
svc, err := cli.InspectService(ctx, serviceID)
|
svc, err := cli.InspectService(ctx, serviceID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("inspect service '%s': %w", serviceID, err)
|
return nil, fmt.Errorf("inspect service '%s': %w", serviceID, err)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ A CLI tool for managing Uncloud resources such as machines, services, and volume
|
|||||||
* [uc caddy](uc_caddy.md) - Manage Caddy reverse proxy service.
|
* [uc caddy](uc_caddy.md) - Manage Caddy reverse proxy service.
|
||||||
* [uc ctx](uc_ctx.md) - Switch between different cluster contexts. Contains subcommands to manage contexts.
|
* [uc ctx](uc_ctx.md) - Switch between different cluster contexts. Contains subcommands to manage contexts.
|
||||||
* [uc deploy](uc_deploy.md) - Deploy services from a Compose file.
|
* [uc deploy](uc_deploy.md) - Deploy services from a Compose file.
|
||||||
* [uc dns](uc_dns.md) - Manage cluster domain in Uncloud DNS.
|
* [uc dns](uc_dns.md) - Manage the cluster domain.
|
||||||
* [uc exec](uc_exec.md) - Execute a command in a running service container.
|
* [uc exec](uc_exec.md) - Execute a command in a running service container.
|
||||||
* [uc image](uc_image.md) - Manage images on machines in the cluster.
|
* [uc image](uc_image.md) - Manage images on machines in the cluster.
|
||||||
* [uc images](uc_images.md) - List images on machines in the cluster.
|
* [uc images](uc_images.md) - List images on machines in the cluster.
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
# uc dns
|
# uc dns
|
||||||
|
|
||||||
Manage cluster domain in Uncloud DNS.
|
Manage the cluster domain.
|
||||||
|
|
||||||
## Synopsis
|
## Synopsis
|
||||||
|
|
||||||
Manage cluster domain in Uncloud DNS.
|
Manage the cluster domain.
|
||||||
DNS commands allow you to reserve or release a unique 'xxxxxx.uncld.dev' domain for your cluster. When reserved, Caddy service deployments will automatically update DNS records to route traffic to the services in the cluster.
|
DNS commands allow you to reserve or release a unique 'xxxxxx.uncld.dev' domain for your cluster. When reserved, Caddy service deployments will automatically update DNS records to route traffic to the services in the cluster.
|
||||||
|
|
||||||
|
EXPERIMENTAL: Use 'uc dns set' to configure an externally managed domain instead. Uncloud does not manage DNS records for manually set domains.
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -27,6 +29,6 @@ DNS commands allow you to reserve or release a unique 'xxxxxx.uncld.dev' domain
|
|||||||
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
|
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
|
||||||
* [uc dns release](uc_dns_release.md) - Release the reserved cluster domain.
|
* [uc dns release](uc_dns_release.md) - Release the reserved cluster domain.
|
||||||
* [uc dns reserve](uc_dns_reserve.md) - Reserve a cluster domain in Uncloud DNS.
|
* [uc dns reserve](uc_dns_reserve.md) - Reserve a cluster domain in Uncloud DNS.
|
||||||
* [uc dns set](uc_dns_set.md) - Set a cluster domain directly in the cluster.
|
* [uc dns set](uc_dns_set.md) - Set or unset an externally managed cluster domain (EXPERIMENTAL).
|
||||||
* [uc dns show](uc_dns_show.md) - Print the cluster domain name.
|
* [uc dns show](uc_dns_show.md) - Print the cluster domain name.
|
||||||
|
|
||||||
@@ -23,5 +23,5 @@ uc dns release [flags]
|
|||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
|
||||||
* [uc dns](uc_dns.md) - Manage cluster domain in Uncloud DNS.
|
* [uc dns](uc_dns.md) - Manage the cluster domain.
|
||||||
|
|
||||||
@@ -24,5 +24,5 @@ uc dns reserve [flags]
|
|||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
|
||||||
* [uc dns](uc_dns.md) - Manage cluster domain in Uncloud DNS.
|
* [uc dns](uc_dns.md) - Manage the cluster domain.
|
||||||
|
|
||||||
@@ -1,15 +1,24 @@
|
|||||||
# uc dns set
|
# uc dns set
|
||||||
|
|
||||||
Set a cluster domain directly in the cluster.
|
Set or unset an externally managed cluster domain (EXPERIMENTAL).
|
||||||
|
|
||||||
## Synopsis
|
## Synopsis
|
||||||
|
|
||||||
Set a cluster domain directly in the cluster, bypassing Uncloud DNS. This assumes the DNS is externally set up.
|
EXPERIMENTAL: Set the cluster domain used to generate ingress hostnames for services.
|
||||||
|
Configure wildcard DNS records for this domain with your DNS provider. Uncloud will not create, verify, update, or delete external DNS records.
|
||||||
|
Pass an empty string to unset a manually set domain. Use 'uc dns release' to release a domain reserved in Uncloud DNS. Setting or unsetting the domain does not change existing service hostnames.
|
||||||
|
|
||||||
```
|
```
|
||||||
uc dns set DOMAIN_NAME [flags]
|
uc dns set DOMAIN_NAME [flags]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
uc dns set apps.example.com
|
||||||
|
uc dns set ""
|
||||||
|
```
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -27,5 +36,5 @@ uc dns set DOMAIN_NAME [flags]
|
|||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
|
||||||
* [uc dns](uc_dns.md) - Manage cluster domain in Uncloud DNS.
|
* [uc dns](uc_dns.md) - Manage the cluster domain.
|
||||||
|
|
||||||
@@ -23,5 +23,5 @@ uc dns show [flags]
|
|||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
|
||||||
* [uc dns](uc_dns.md) - Manage cluster domain in Uncloud DNS.
|
* [uc dns](uc_dns.md) - Manage the cluster domain.
|
||||||
|
|
||||||
Reference in new issue
Block a user